vboot/ui: Change root screen if DEV_DISABLE_BOOT is set

Change UI root screen to DEVELOPER_TO_NORM if DEV_DISABLE_BOOT is set in
FWMP, and disable all dev-mode shortcuts except '\t'. This ensures
DEVELOPER_TO_NORM and VB2_SCREEN_DEBUG_INFO are the only two screens
accessible from the UI.

Also hide the "Cancel" menu item in DEVELOPER_TO_NORM.

BUG=b:159579189, chromium:1181484
TEST=make runtests
TEST=emerge-asurada depthcharge
BRANCH=none

Change-Id: Ifedb53ae2eb968b1118340aef30cda00b7925f03
Signed-off-by: Yu-Ping Wu <yupingso@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/vboot_reference/+/2716747
Reviewed-by: Joel Kitching <kitching@chromium.org>
diff --git a/firmware/2lib/2ui.c b/firmware/2lib/2ui.c
index 80d0568..800f06a 100644
--- a/firmware/2lib/2ui.c
+++ b/firmware/2lib/2ui.c
@@ -408,12 +408,24 @@
 
 vb2_error_t vb2_developer_menu(struct vb2_context *ctx)
 {
-	return ui_loop(ctx, VB2_SCREEN_DEVELOPER_MODE, developer_action);
+	enum vb2_screen root_screen_id = VB2_SCREEN_DEVELOPER_MODE;
+	if (!vb2_dev_boot_allowed(ctx)) {
+		VB2_DEBUG("WARNING: Dev boot not allowed; forcing to-norm\n");
+		root_screen_id = VB2_SCREEN_DEVELOPER_TO_NORM;
+	}
+	return ui_loop(ctx, root_screen_id, developer_action);
 }
 
 vb2_error_t developer_action(struct vb2_ui_context *ui)
 {
 	/* Developer mode keyboard shortcuts */
+	if (ui->key == '\t')
+		return vb2_ui_screen_change(ui, VB2_SCREEN_DEBUG_INFO);
+
+	/* Ignore other shortcuts */
+	if (!vb2_dev_boot_allowed(ui->ctx))
+		return VB2_REQUEST_UI_CONTINUE;
+
 	if (ui->key == VB_KEY_CTRL('S'))
 		return vb2_ui_screen_change(ui, VB2_SCREEN_DEVELOPER_TO_NORM);
 	if (ui->key == VB_KEY_CTRL('U') ||
@@ -424,8 +436,6 @@
 		return vb2_ui_developer_mode_boot_internal_action(ui);
 	if (ui->key == VB_KEY_CTRL('L'))  /* L for aLtfw (formerly Legacy) */
 		return vb2_ui_developer_mode_boot_altfw_action(ui);
-	if (ui->key == '\t')
-		return vb2_ui_screen_change(ui, VB2_SCREEN_DEBUG_INFO);
 
 	return VB2_REQUEST_UI_CONTINUE;
 }
diff --git a/firmware/2lib/2ui_screens.c b/firmware/2lib/2ui_screens.c
index a3ee41a..3026f76 100644
--- a/firmware/2lib/2ui_screens.c
+++ b/firmware/2lib/2ui_screens.c
@@ -851,6 +851,7 @@
 /* VB2_SCREEN_DEVELOPER_TO_NORM */
 
 #define DEVELOPER_TO_NORM_ITEM_CONFIRM 1
+#define DEVELOPER_TO_NORM_ITEM_CANCEL 2
 
 static vb2_error_t developer_to_norm_init(struct vb2_ui_context *ui)
 {
@@ -861,6 +862,10 @@
 		return vb2_ui_screen_back(ui);
 	}
 	ui->state->selected_item = DEVELOPER_TO_NORM_ITEM_CONFIRM;
+	/* Hide "Cancel" button if dev boot is not allowed */
+	if (!vb2_dev_boot_allowed(ui->ctx))
+		VB2_SET_BIT(ui->state->hidden_item_mask,
+			    DEVELOPER_TO_NORM_ITEM_CANCEL);
 	return VB2_REQUEST_UI_CONTINUE;
 }
 
@@ -878,11 +883,11 @@
 
 static const struct vb2_menu_item developer_to_norm_items[] = {
 	LANGUAGE_SELECT_ITEM,
-	{
+	[DEVELOPER_TO_NORM_ITEM_CONFIRM] = {
 		.text = "Confirm",
 		.action = developer_to_norm_action,
 	},
-	{
+	[DEVELOPER_TO_NORM_ITEM_CANCEL] = {
 		.text = "Cancel",
 		.action = vb2_ui_screen_back,
 	},
diff --git a/tests/vb2_ui_tests.c b/tests/vb2_ui_tests.c
index baac919..812fe5e 100644
--- a/tests/vb2_ui_tests.c
+++ b/tests/vb2_ui_tests.c
@@ -727,15 +727,11 @@
 			"VB_BUTTON_VOL_UP_LONG_PRESS = boot external");
 	}
 
-	/* If dev mode is disabled, goes to to_norm screen repeatedly */
+	/* If dev mode is disabled, directly goes to to_norm screen */
 	reset_common_data(FOR_DEVELOPER);
-	add_mock_keypress(VB_KEY_ESC);
 	mock_dev_boot_allowed = 0;
 	TEST_EQ(vb2_developer_menu(ctx), VB2_REQUEST_SHUTDOWN,
-		"if dev mode is disabled, goes to to_norm screen repeatedly");
-	DISPLAYED_EQ("to_norm", VB2_SCREEN_DEVELOPER_TO_NORM, MOCK_IGNORE,
-		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
-	DISPLAYED_PASS();
+		"if dev mode is disabled, directly goes to to_norm screen");
 	DISPLAYED_EQ("to_norm", VB2_SCREEN_DEVELOPER_TO_NORM, MOCK_IGNORE,
 		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
 	DISPLAYED_NO_EXTRA();