Add 'exit' hftest command

A device may need to exit out of the hftest environment, e.g. an Android
device would otherwise always reboot back to hftest and would not be
able to flash a new image.

Add a hftest_device_exit_test_environment() to the hftest_device driver,
where this can be implemented in a board-specific way.

The default PSCI implementation will not support this command and will
print an error message.

Change-Id: I60a92aac21dfbc8b6476f6efe694f05b0967a27d
diff --git a/test/hftest/BUILD.gn b/test/hftest/BUILD.gn
index 80936f7..b11a50b 100644
--- a/test/hftest/BUILD.gn
+++ b/test/hftest/BUILD.gn
@@ -107,6 +107,7 @@
     "//src/arch/${plat_arch}/hftest:interrupts",
     "//src/arch/${plat_arch}/hftest:power_mgmt",
     hftest_ctrl,
+    hftest_device,
   ]
 }
 
diff --git a/test/hftest/device_psci.c b/test/hftest/device_psci.c
index fd9a8c5..f853d18 100644
--- a/test/hftest/device_psci.c
+++ b/test/hftest/device_psci.c
@@ -22,3 +22,8 @@
 {
 	arch_reboot();
 }
+
+void hftest_device_exit_test_environment(void)
+{
+	HFTEST_LOG("%s not supported", __func__);
+}
diff --git a/test/hftest/standalone_main.c b/test/hftest/standalone_main.c
index 91b53b5..8f0cec9 100644
--- a/test/hftest/standalone_main.c
+++ b/test/hftest/standalone_main.c
@@ -60,6 +60,11 @@
 		goto out;
 	}
 
+	if (memiter_iseq(&command, "exit")) {
+		hftest_device_exit_test_environment();
+		goto out;
+	}
+
 	if (memiter_iseq(&command, "json")) {
 		hftest_json();
 		goto out;
diff --git a/test/inc/test/hftest.h b/test/inc/test/hftest.h
index 6f141b9..d4779d0 100644
--- a/test/inc/test/hftest.h
+++ b/test/inc/test/hftest.h
@@ -128,6 +128,17 @@
 noreturn void hftest_device_reboot(void);
 
 /**
+ * Device-specific operation to escape from the test environment.
+ * For example, an Android device with UART test controller will reboot after
+ * every test run back into hftest. So as to flash the device with a different
+ * system image, the device must escape this loop and boot into the Android
+ * bootloader.
+ * If successful, this function will not return.
+ * It may not be supported on all devices.
+ */
+void hftest_device_exit_test_environment(void);
+
+/**
  * Starts the CPU with the given ID. It will start at the provided entry point
  * with the provided argument. It is a wrapper around the generic cpu_start()
  * and takes care of MMU initialization.