vboot/ui: add screens for dev boot from external disk

Add polling screens for booting from external disk in dev mode.

BRANCH=none
BUG=b:146399181, b:158973903
TEST=make runtests
TEST=emerge-puff depthcharge
TEST=1. Enter developer mode screen
     2. Select "Boot from external disk", then screen changes to
        DEVELOPER_BOOT_EXTERNAL
     3. Plug in invalid usb, then screen changes to
         DEVELOPER_INVALID_DISK
     4. Unplug usb, then screen changes back to
        DEVELOPER_BOOT_EXTERNAL
     5. Plug in valid usb, then device boots successfully

Cq-Depend: chromium:2245066
Change-Id: I633f16ca0d92eaf27eb3b7630ee61b2044942741
Signed-off-by: Yu-Ping Wu <yupingso@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/vboot_reference/+/2246298
Reviewed-by: Joel Kitching <kitching@chromium.org>
diff --git a/firmware/2lib/2ui_screens.c b/firmware/2lib/2ui_screens.c
index 1a1259d..2ac3f5e 100644
--- a/firmware/2lib/2ui_screens.c
+++ b/firmware/2lib/2ui_screens.c
@@ -461,6 +461,8 @@
 vb2_error_t vb2_ui_developer_mode_boot_external_action(
 	struct vb2_ui_context *ui)
 {
+	vb2_error_t rv;
+
 	/* Sanity check, should never happen. */
 	if (!(ui->ctx->flags & VB2_CONTEXT_DEVELOPER_MODE) ||
 	    !vb2_dev_boot_allowed(ui->ctx) ||
@@ -469,12 +471,20 @@
 		return VB2_REQUEST_UI_CONTINUE;
 	}
 
-	if (VbTryLoadKernel(ui->ctx, VB_DISK_FLAG_REMOVABLE)) {
-		VB2_DEBUG("ERROR: Dev mode external boot failed\n");
-		return VB2_REQUEST_UI_CONTINUE;
+	rv = VbTryLoadKernel(ui->ctx, VB_DISK_FLAG_REMOVABLE);
+	if (rv == VB2_SUCCESS) {
+		return VB2_SUCCESS;
+	} else if (rv == VB2_ERROR_LK_NO_DISK_FOUND) {
+		if (ui->state.screen->id != VB2_SCREEN_DEVELOPER_BOOT_EXTERNAL)
+			VB2_DEBUG("No external disk found\n");
+		return vb2_ui_change_screen(
+			ui, VB2_SCREEN_DEVELOPER_BOOT_EXTERNAL);
+	} else {
+		if (ui->state.screen->id != VB2_SCREEN_DEVELOPER_INVALID_DISK)
+			VB2_DEBUG("Invalid external disk: %#x\n", rv);
+		return vb2_ui_change_screen(
+			ui, VB2_SCREEN_DEVELOPER_INVALID_DISK);
 	}
-
-	return VB2_SUCCESS;
 }
 
 vb2_error_t developer_mode_action(struct vb2_ui_context *ui)
@@ -573,6 +583,36 @@
 };
 
 /******************************************************************************/
+/* VB2_SCREEN_DEVELOPER_BOOT_EXTERNAL */
+
+static const struct vb2_menu_item developer_boot_external_items[] = {
+	LANGUAGE_SELECT_ITEM,
+	BACK_ITEM,
+};
+
+static const struct vb2_screen_info developer_boot_external_screen = {
+	.id = VB2_SCREEN_DEVELOPER_BOOT_EXTERNAL,
+	.name = "Developer boot from external disk",
+	.action = vb2_ui_developer_mode_boot_external_action,
+	.menu = MENU_ITEMS(developer_boot_external_items),
+};
+
+/******************************************************************************/
+/* VB2_SCREEN_DEVELOPER_INVALID_DISK */
+
+static const struct vb2_menu_item developer_invalid_disk_items[] = {
+	LANGUAGE_SELECT_ITEM,
+	BACK_ITEM,
+};
+
+static const struct vb2_screen_info developer_invalid_disk_screen = {
+	.id = VB2_SCREEN_DEVELOPER_INVALID_DISK,
+	.name = "Invalid external disk in dev mode",
+	.action = vb2_ui_developer_mode_boot_external_action,
+	.menu = MENU_ITEMS(developer_invalid_disk_items),
+};
+
+/******************************************************************************/
 /*
  * TODO(chromium:1035800): Refactor UI code across vboot and depthcharge.
  * Currently vboot and depthcharge maintain their own copies of menus/screens.
@@ -595,6 +635,8 @@
 	&recovery_disk_step3_screen,
 	&developer_mode_screen,
 	&developer_to_norm_screen,
+	&developer_boot_external_screen,
+	&developer_invalid_disk_screen,
 };
 
 const struct vb2_screen_info *vb2_get_screen_info(enum vb2_screen id)
diff --git a/firmware/2lib/include/2api.h b/firmware/2lib/include/2api.h
index e78c85a..1696289 100644
--- a/firmware/2lib/include/2api.h
+++ b/firmware/2lib/include/2api.h
@@ -1216,10 +1216,14 @@
 	VB2_SCREEN_RECOVERY_DISK_STEP1		= 0x220,
 	VB2_SCREEN_RECOVERY_DISK_STEP2		= 0x221,
 	VB2_SCREEN_RECOVERY_DISK_STEP3		= 0x222,
-	/* Developer screen */
+	/* Developer mode screen */
 	VB2_SCREEN_DEVELOPER_MODE		= 0x300,
 	/* Confirm transition to normal mode */
 	VB2_SCREEN_DEVELOPER_TO_NORM		= 0x310,
+	/* Developer boot from external disk */
+	VB2_SCREEN_DEVELOPER_BOOT_EXTERNAL	= 0x320,
+	/* Invalid external disk inserted */
+	VB2_SCREEN_DEVELOPER_INVALID_DISK	= 0x330,
 };
 
 /**