dm: usb: Deal with USB keyboard persisting across tests
Clear any USB-keyboard devices before running a unit test, to avoid
using a stale udevice pointer in stdio. Add a long comment to explain
this situation and why this solution seems best, at least for now.
Signed-off-by: Simon Glass <sjg@chromium.org>
diff --git a/test/test-main.c b/test/test-main.c
index 63e8be0..b3d3e24 100644
--- a/test/test-main.c
+++ b/test/test-main.c
@@ -12,6 +12,7 @@
#include <net.h>
#include <of_live.h>
#include <os.h>
+#include <usb.h>
#include <dm/ofnode.h>
#include <dm/root.h>
#include <dm/test.h>
@@ -289,6 +290,43 @@
{
ut_assertok(event_init());
+ /*
+ * Remove any USB keyboard, so that we can add and remove USB devices
+ * in tests.
+ *
+ * For UT_TESTF_DM tests, the old driver model state is saved and
+ * restored across each test. Within in each test there is therefore a
+ * new driver model state, which means that any USB keyboard device in
+ * stdio points to the old state.
+ *
+ * This is fine in most cases. But if a non-UT_TESTF_DM test starts up
+ * USB (thus creating a stdio record pointing to the USB keyboard
+ * device) then when the test finishes, the new driver model state is
+ * freed, meaning that there is now a stale pointer in stdio.
+ *
+ * This means that any future UT_TESTF_DM test which uses stdin will
+ * cause the console system to call tstc() on the stale device pointer,
+ * causing a crash.
+ *
+ * We don't want to fix this by enabling UT_TESTF_DM for all tests as
+ * this causes other problems. For example, bootflow_efi relies on
+ * U-Boot going through a proper init - without that we don't have the
+ * TCG measurement working and get an error
+ * 'tcg2 measurement fails(0x8000000000000007)'. Once we tidy up how EFI
+ * runs tests (e.g. get rid of all the restarting of U-Boot) we could
+ * potentially make the bootstd tests set UT_TESTF_DM, but other tests
+ * might do the same thing.
+ *
+ * We could add a test flag to declare that USB is being used, but that
+ * seems unnecessary, at least for now. We could detect USB being used
+ * in a test, but there is no obvious drawback to clearing out stale
+ * pointers always.
+ *
+ * So just remove any USB keyboards from the console tables. This allows
+ * UT_TESTF_DM and non-UT_TESTF_DM tests to coexist happily.
+ */
+ usb_kbd_remove_for_test();
+
if (test->flags & UTF_DM)
ut_assertok(dm_test_pre_run(uts));