vboot/ui: Split disabled_item_mask into two masks for log screen

Add three macros in 2api.h for bitmask operations:
- VB2_SET_BIT(mask, index)
- VB2_CLR_BIT(mask, index)
- VB2_GET_BIT(mask, index)
These macros will be used in corresponding depthcharge CLs.

Split disabled_item_mask into:
- disabled_item_mask: Disabled style, but still visible and selectable.
- hidden_item_mask: Not visible.

Ignore selecting on disabled menu items.

Set appropriate disabled_item_mask for page up/down buttons in log
screen.

Revise tests of hidden_item_mask and add unit tests of disabled_item_mask.

BUG=b:163301076, b:146399181
BRANCH=none
TEST=CC=x86_64-pc-linux-gnu-clang;
     make clean && make runtests
TEST=CC=x86_64-pc-linux-gnu-clang; DETACHABLE=1;
     make clean && make runtests
TEST=CC=x86_64-pc-linux-gnu-clang; PHYSICAL_PRESENCE_KEYBOARD=1;
     make clean && make runtests
TEST=CC=x86_64-pc-linux-gnu-clang; DIAGNOSTIC_UI=1;
     make clean && make runtests
TEST=Build locally, navigate to debug info screen with <TAB>,
     select page up or page down, and observe that nothing happens.

Cq-Depend: chromium:2432168
Signed-off-by: Hsuan Ting Chen <roccochen@chromium.org>
Change-Id: I1607af53f6e2b5c1cde568cb24606314051d2380
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/vboot_reference/+/2426154
Reviewed-by: Yu-Ping Wu <yupingso@chromium.org>
Commit-Queue: Yu-Ping Wu <yupingso@chromium.org>
diff --git a/firmware/2lib/2ui.c b/firmware/2lib/2ui.c
index 44edc4a..5b1e339 100644
--- a/firmware/2lib/2ui.c
+++ b/firmware/2lib/2ui.c
@@ -144,8 +144,7 @@
 		return VB2_REQUEST_UI_CONTINUE;
 
 	item = ui->state->selected_item - 1;
-	while (item >= 0 &&
-	       ((1 << item) & ui->state->disabled_item_mask))
+	while (item >= 0 && VB2_GET_BIT(ui->state->hidden_item_mask, item))
 		item--;
 	/* Only update if item is valid */
 	if (item >= 0)
@@ -165,7 +164,7 @@
 	menu = get_menu(ui);
 	item = ui->state->selected_item + 1;
 	while (item < menu->num_items &&
-	       ((1 << item) & ui->state->disabled_item_mask))
+	       VB2_GET_BIT(ui->state->hidden_item_mask, item))
 		item++;
 	/* Only update if item is valid */
 	if (item < menu->num_items)
@@ -188,6 +187,14 @@
 
 	menu_item = &menu->items[ui->state->selected_item];
 
+	/* Cannot select a disabled menu item */
+	if (VB2_GET_BIT(ui->state->disabled_item_mask,
+			ui->state->selected_item)) {
+		VB2_DEBUG("Menu item <%s> disabled; ignoring\n",
+			  menu_item->text);
+		return VB2_REQUEST_UI_CONTINUE;
+	}
+
 	if (menu_item->action) {
 		VB2_DEBUG("Menu item <%s> run action\n", menu_item->text);
 		return menu_item->action(ui);
@@ -331,6 +338,7 @@
 			vb2ex_display_ui(ui.state->screen->id, ui.locale_id,
 					 ui.state->selected_item,
 					 ui.state->disabled_item_mask,
+					 ui.state->hidden_item_mask,
 					 ui.disable_timer,
 					 ui.state->current_page,
 					 ui.error_code);
diff --git a/firmware/2lib/2ui_screens.c b/firmware/2lib/2ui_screens.c
index aaf7daf..29a1062 100644
--- a/firmware/2lib/2ui_screens.c
+++ b/firmware/2lib/2ui_screens.c
@@ -52,50 +52,92 @@
 })
 
 /******************************************************************************/
-/* Functions used for log screens */
 /*
- * TODO(b/163301076): Reconsider the functionalities of page up/down buttons
- * when reaching the start/end of the log.
+ * Functions used for log screens
+ *
+ * Expects that the page_count is valid and page_up_item and page_down_item are
+ * assigned to correct menu item indices in all three functions, the
+ * current_page is valid in prev and next actions, and the back_item is assigned
+ * to a correct menu item index.
  */
 
-static vb2_error_t log_page_init(struct vb2_ui_context *ui,
-				 uint32_t page_down_item,
-				 uint32_t alternate_item)
+static vb2_error_t log_page_init(struct vb2_ui_context *ui)
 {
+	const struct vb2_screen_info *screen = ui->state->screen;
+
 	ui->state->current_page = 0;
 
-	if (ui->state->page_count == 1)
-		ui->state->selected_item = alternate_item;
-	else
-		ui->state->selected_item = page_down_item;
+	if (ui->state->page_count == 1) {
+		VB2_SET_BIT(ui->state->disabled_item_mask,
+			    screen->page_up_item);
+		VB2_SET_BIT(ui->state->disabled_item_mask,
+			    screen->page_down_item);
+		ui->state->selected_item = screen->back_item;
+	} else {
+		VB2_SET_BIT(ui->state->disabled_item_mask,
+			    screen->page_up_item);
+		ui->state->selected_item = screen->page_down_item;
+	}
 
 	return VB2_REQUEST_UI_CONTINUE;
 }
 
 static vb2_error_t log_page_prev_action(struct vb2_ui_context *ui)
 {
-	if (ui->state->current_page == 0) {
-		VB2_DEBUG("WARNING: Ignore page up on the first page\n");
-		ui->error_beep = 1;
+	const struct vb2_screen_info *screen = ui->state->screen;
+
+	/* Validity check. */
+	if (ui->state->current_page == 0)
 		return VB2_REQUEST_UI_CONTINUE;
-	}
+
 	ui->state->current_page--;
 
+	/* Clear bits of page down. */
+	if (ui->state->current_page != ui->state->page_count - 1)
+		VB2_CLR_BIT(ui->state->disabled_item_mask,
+			    screen->page_down_item);
+
+	/* Disable page up at the first page. */
+	if (ui->state->current_page == 0)
+		VB2_SET_BIT(ui->state->disabled_item_mask,
+			    screen->page_up_item);
+
 	return VB2_REQUEST_UI_CONTINUE;
 }
 
 static vb2_error_t log_page_next_action(struct vb2_ui_context *ui)
 {
-	if (ui->state->current_page == ui->state->page_count - 1) {
-		VB2_DEBUG("WARNING: Ignore page down on the last page\n");
-		ui->error_beep = 1;
+	const struct vb2_screen_info *screen = ui->state->screen;
+
+	/* Validity check. */
+	if (ui->state->current_page == ui->state->page_count - 1)
 		return VB2_REQUEST_UI_CONTINUE;
-	}
+
 	ui->state->current_page++;
 
+	/* Clear bits of page up. */
+	if (ui->state->current_page != 0)
+		VB2_CLR_BIT(ui->state->disabled_item_mask,
+			    screen->page_up_item);
+
+	/* Disable page down at the last page. */
+	if (ui->state->current_page == ui->state->page_count - 1)
+		VB2_SET_BIT(ui->state->disabled_item_mask,
+			    screen->page_down_item);
+
 	return VB2_REQUEST_UI_CONTINUE;
 }
 
+#define PAGE_UP_ITEM ((struct vb2_menu_item){ \
+	.text = "Page up", \
+	.action = log_page_prev_action, \
+})
+
+#define PAGE_DOWN_ITEM ((struct vb2_menu_item){ \
+	.text = "Page down", \
+	.action = log_page_next_action, \
+})
+
 /******************************************************************************/
 /* VB2_SCREEN_BLANK */
 
@@ -207,8 +249,8 @@
 	ui->state->selected_item = ADVANCED_OPTIONS_ITEM_DEVELOPER_MODE;
 	if (vb2_get_sd(ui->ctx)->flags & VB2_SD_FLAG_DEV_MODE_ENABLED ||
 	    !vb2_allow_recovery(ui->ctx)) {
-		ui->state->disabled_item_mask |=
-			1 << ADVANCED_OPTIONS_ITEM_DEVELOPER_MODE;
+		VB2_SET_BIT(ui->state->hidden_item_mask,
+			    ADVANCED_OPTIONS_ITEM_DEVELOPER_MODE);
 		ui->state->selected_item = ADVANCED_OPTIONS_ITEM_DEBUG_INFO;
 	}
 
@@ -243,6 +285,7 @@
 /******************************************************************************/
 /* VB2_SCREEN_DEBUG_INFO */
 
+#define DEBUG_INFO_ITEM_PAGE_UP 1
 #define DEBUG_INFO_ITEM_PAGE_DOWN 2
 #define DEBUG_INFO_ITEM_BACK 3
 
@@ -261,9 +304,7 @@
 		return vb2_ui_screen_back(ui);
 	}
 
-	return log_page_init(ui,
-			     DEBUG_INFO_ITEM_PAGE_DOWN,
-			     DEBUG_INFO_ITEM_BACK);
+	return log_page_init(ui);
 }
 
 static vb2_error_t debug_info_reinit(struct vb2_ui_context *ui)
@@ -286,14 +327,8 @@
 
 static const struct vb2_menu_item debug_info_items[] = {
 	LANGUAGE_SELECT_ITEM,
-	{
-		.text = "Page up",
-		.action = log_page_prev_action,
-	},
-	[DEBUG_INFO_ITEM_PAGE_DOWN] = {
-		.text = "Page down",
-		.action = log_page_next_action,
-	},
+	[DEBUG_INFO_ITEM_PAGE_UP] = PAGE_UP_ITEM,
+	[DEBUG_INFO_ITEM_PAGE_DOWN] = PAGE_DOWN_ITEM,
 	[DEBUG_INFO_ITEM_BACK] = BACK_ITEM,
 	POWER_OFF_ITEM,
 };
@@ -304,11 +339,15 @@
 	.init = debug_info_init,
 	.reinit = debug_info_reinit,
 	.menu = MENU_ITEMS(debug_info_items),
+	.page_up_item = DEBUG_INFO_ITEM_PAGE_UP,
+	.page_down_item = DEBUG_INFO_ITEM_PAGE_DOWN,
+	.back_item = DEBUG_INFO_ITEM_BACK,
 };
 
 /******************************************************************************/
 /* VB2_SCREEN_FIRMWARE_LOG */
 
+#define FIRMWARE_LOG_ITEM_PAGE_UP 1
 #define FIRMWARE_LOG_ITEM_PAGE_DOWN 2
 #define FIRMWARE_LOG_ITEM_BACK 3
 
@@ -327,9 +366,7 @@
 		return vb2_ui_screen_back(ui);
 	}
 
-	return log_page_init(ui,
-			     FIRMWARE_LOG_ITEM_PAGE_DOWN,
-			     FIRMWARE_LOG_ITEM_BACK);
+	return log_page_init(ui);
 }
 
 static vb2_error_t firmware_log_reinit(struct vb2_ui_context *ui)
@@ -352,14 +389,8 @@
 
 static const struct vb2_menu_item firmware_log_items[] = {
 	LANGUAGE_SELECT_ITEM,
-	{
-		.text = "Page up",
-		.action = log_page_prev_action,
-	},
-	[FIRMWARE_LOG_ITEM_PAGE_DOWN] = {
-		.text = "Page down",
-		.action = log_page_next_action,
-	},
+	[FIRMWARE_LOG_ITEM_PAGE_UP] = PAGE_UP_ITEM,
+	[FIRMWARE_LOG_ITEM_PAGE_DOWN] = PAGE_DOWN_ITEM,
 	[FIRMWARE_LOG_ITEM_BACK] = BACK_ITEM,
 	POWER_OFF_ITEM,
 };
@@ -370,6 +401,9 @@
 	.init = firmware_log_init,
 	.reinit = firmware_log_reinit,
 	.menu = MENU_ITEMS(firmware_log_items),
+	.page_up_item = FIRMWARE_LOG_ITEM_PAGE_UP,
+	.page_down_item = FIRMWARE_LOG_ITEM_PAGE_DOWN,
+	.back_item = FIRMWARE_LOG_ITEM_BACK,
 };
 
 /******************************************************************************/
@@ -392,14 +426,14 @@
 	ui->state->selected_item = RECOVERY_SELECT_ITEM_PHONE;
 	if (!vb2api_phone_recovery_ui_enabled(ui->ctx)) {
 		VB2_DEBUG("WARNING: Phone recovery not available\n");
-		ui->state->disabled_item_mask |=
-			1 << RECOVERY_SELECT_ITEM_PHONE;
+		VB2_SET_BIT(ui->state->hidden_item_mask,
+			    RECOVERY_SELECT_ITEM_PHONE);
 		ui->state->selected_item = RECOVERY_SELECT_ITEM_EXTERNAL_DISK;
 	}
 
-	if (!DIAGNOSTIC_UI || !vb2api_diagnostic_ui_enabled(ui->ctx))
-		ui->state->disabled_item_mask |=
-			1 << RECOVERY_SELECT_ITEM_DIAGNOSTICS;
+        if (!DIAGNOSTIC_UI || !vb2api_diagnostic_ui_enabled(ui->ctx))
+		VB2_SET_BIT(ui->state->hidden_item_mask,
+			    RECOVERY_SELECT_ITEM_DIAGNOSTICS);
 
 	return VB2_REQUEST_UI_CONTINUE;
 }
@@ -466,8 +500,8 @@
 
 	/* Disable "Confirm" button for other physical presence types. */
 	if (!PHYSICAL_PRESENCE_KEYBOARD) {
-		ui->state->disabled_item_mask |=
-			1 << RECOVERY_TO_DEV_ITEM_CONFIRM;
+		VB2_SET_BIT(ui->state->hidden_item_mask,
+			    RECOVERY_TO_DEV_ITEM_CONFIRM);
 		ui->state->selected_item = RECOVERY_TO_DEV_ITEM_CANCEL;
 	}
 
@@ -655,18 +689,18 @@
 
 	/* Don't show "Return to secure mode" button if GBB forces dev mode. */
 	if (vb2_get_gbb(ui->ctx)->flags & VB2_GBB_FLAG_FORCE_DEV_SWITCH_ON)
-		ui->state->disabled_item_mask |=
-			1 << DEVELOPER_MODE_ITEM_RETURN_TO_SECURE;
+		VB2_SET_BIT(ui->state->hidden_item_mask,
+			    DEVELOPER_MODE_ITEM_RETURN_TO_SECURE);
 
 	/* Don't show "Boot from external disk" button if not allowed. */
 	if (!vb2_dev_boot_external_allowed(ui->ctx))
-		ui->state->disabled_item_mask |=
-			1 << DEVELOPER_MODE_ITEM_BOOT_EXTERNAL;
+		VB2_SET_BIT(ui->state->hidden_item_mask,
+			    DEVELOPER_MODE_ITEM_BOOT_EXTERNAL);
 
 	/* Don't show "Select alternate bootloader" button if not allowed. */
 	if (!vb2_dev_boot_legacy_allowed(ui->ctx))
-		ui->state->disabled_item_mask |=
-			1 << DEVELOPER_MODE_ITEM_SELECT_BOOTLOADER;
+		VB2_SET_BIT(ui->state->hidden_item_mask,
+			    DEVELOPER_MODE_ITEM_SELECT_BOOTLOADER);
 
 	/* Choose the default selection. */
 	switch (default_boot) {
@@ -1035,6 +1069,7 @@
 /******************************************************************************/
 /* VB2_SCREEN_DIAGNOSTICS_STORAGE */
 
+#define DIAGNOSTICS_STORAGE_ITEM_PAGE_UP 0
 #define DIAGNOSTICS_STORAGE_ITEM_PAGE_DOWN 1
 #define DIAGNOSTICS_STORAGE_ITEM_BACK 2
 
@@ -1053,19 +1088,12 @@
 		ui->error_code = VB2_UI_ERROR_DIAGNOSTICS;
 		return vb2_ui_screen_back(ui);
 	}
-	return log_page_init(ui, DIAGNOSTICS_STORAGE_ITEM_PAGE_DOWN,
-			     DIAGNOSTICS_STORAGE_ITEM_BACK);
+	return log_page_init(ui);
 }
 
 static const struct vb2_menu_item diagnostics_storage_items[] = {
-	{
-		.text = "Page up",
-		.action = log_page_prev_action,
-	},
-	[DIAGNOSTICS_STORAGE_ITEM_PAGE_DOWN] = {
-		.text = "Page down",
-		.action = log_page_next_action,
-	},
+	[DIAGNOSTICS_STORAGE_ITEM_PAGE_UP] = PAGE_UP_ITEM,
+	[DIAGNOSTICS_STORAGE_ITEM_PAGE_DOWN] = PAGE_DOWN_ITEM,
 	[DIAGNOSTICS_STORAGE_ITEM_BACK] = BACK_ITEM,
 	POWER_OFF_ITEM,
 };
@@ -1075,12 +1103,16 @@
 	.name = "Storage",
 	.init = diagnostics_storage_init,
 	.menu = MENU_ITEMS(diagnostics_storage_items),
+	.page_up_item = DIAGNOSTICS_STORAGE_ITEM_PAGE_UP,
+	.page_down_item = DIAGNOSTICS_STORAGE_ITEM_PAGE_DOWN,
+	.back_item = DIAGNOSTICS_STORAGE_ITEM_BACK,
 };
 
 /******************************************************************************/
 /* VB2_SCREEN_DIAGNOSTICS_MEMORY_QUICK
    VB2_SCREEN_DIAGNOSTICS_MEMORY_FULL */
 
+#define DIAGNOSTICS_MEMORY_ITEM_PAGE_UP 0
 #define DIAGNOSTICS_MEMORY_ITEM_PAGE_DOWN 1
 #define DIAGNOSTICS_MEMORY_ITEM_CANCEL 2
 #define DIAGNOSTICS_MEMORY_ITEM_BACK 3
@@ -1112,17 +1144,18 @@
 
 	/* Show cancel button when the test is running, otherwise show the back
 	 * button. VB2_SUCCESS indicates the test is finished. */
-	ui->state->disabled_item_mask &= ~(1 << DIAGNOSTICS_MEMORY_ITEM_CANCEL);
-	ui->state->disabled_item_mask &= ~(1 << DIAGNOSTICS_MEMORY_ITEM_BACK);
+	VB2_CLR_BIT(ui->state->hidden_item_mask,
+		    DIAGNOSTICS_MEMORY_ITEM_CANCEL);
+	VB2_CLR_BIT(ui->state->hidden_item_mask, DIAGNOSTICS_MEMORY_ITEM_BACK);
 	if (rv == VB2_ERROR_EX_DIAG_TEST_RUNNING) {
-		ui->state->disabled_item_mask |=
-			1 << DIAGNOSTICS_MEMORY_ITEM_BACK;
+		VB2_SET_BIT(ui->state->hidden_item_mask,
+			    DIAGNOSTICS_MEMORY_ITEM_BACK);
 		if (ui->state->selected_item == DIAGNOSTICS_MEMORY_ITEM_BACK)
 			ui->state->selected_item =
 				DIAGNOSTICS_MEMORY_ITEM_CANCEL;
 	} else {
-		ui->state->disabled_item_mask |=
-			1 << DIAGNOSTICS_MEMORY_ITEM_CANCEL;
+		VB2_SET_BIT(ui->state->hidden_item_mask,
+			    DIAGNOSTICS_MEMORY_ITEM_CANCEL);
 		if (ui->state->selected_item == DIAGNOSTICS_MEMORY_ITEM_CANCEL)
 			ui->state->selected_item = DIAGNOSTICS_MEMORY_ITEM_BACK;
 	}
@@ -1155,14 +1188,8 @@
 }
 
 static const struct vb2_menu_item diagnostics_memory_items[] = {
-	{
-		.text = "Page up",
-		.action = log_page_prev_action,
-	},
-	[DIAGNOSTICS_MEMORY_ITEM_PAGE_DOWN] = {
-		.text = "Page down",
-		.action = log_page_next_action,
-	},
+	[DIAGNOSTICS_MEMORY_ITEM_PAGE_UP] = PAGE_UP_ITEM,
+	[DIAGNOSTICS_MEMORY_ITEM_PAGE_DOWN] = PAGE_DOWN_ITEM,
 	[DIAGNOSTICS_MEMORY_ITEM_CANCEL] = {
 		.text = "Cancel and go back",
 		.action = vb2_ui_screen_back,
diff --git a/firmware/2lib/include/2api.h b/firmware/2lib/include/2api.h
index 67b5074..b4dfadf 100644
--- a/firmware/2lib/include/2api.h
+++ b/firmware/2lib/include/2api.h
@@ -1293,6 +1293,11 @@
 /*****************************************************************************/
 /* Functions for UI display. */
 
+/* Helpers for bitmask operations */
+#define VB2_SET_BIT(mask, index) ((mask) |= ((uint32_t)1 << (index)))
+#define VB2_CLR_BIT(mask, index) ((mask) &= ~((uint32_t)1 << (index)))
+#define VB2_GET_BIT(mask, index) ((mask) & ((uint32_t)1 << (index)))
+
 /* Screens. */
 enum vb2_screen {
 	/* Blank screen */
@@ -1375,6 +1380,12 @@
  *				doesn't have a menu, this value will be ignored.
  * @param disabled_item_mask	Mask for disabled menu items. Bit (1 << idx)
  *				indicates whether item 'idx' is disabled.
+ *				A disabled menu item is visible and selectable,
+ *				with a different button style.
+ * @param hidden_item_mask	Mask for hidden menu items. Bit (1 << idx)
+ *				indicates whether item 'idx' is hidden.
+ *				A hidden menu item is neither visible nor
+ *				selectable.
  * @param timer_disabled	Whether timer is disabled or not. Some screen
  *				descriptions will depend on this value.
  * @param current_page		Current page number for a log screen. If the
@@ -1387,6 +1398,7 @@
 			     uint32_t locale_id,
 			     uint32_t selected_item,
 			     uint32_t disabled_item_mask,
+			     uint32_t hidden_item_mask,
 			     int timer_disabled,
 			     uint32_t current_page,
 			     enum vb2_ui_error error_code);
diff --git a/firmware/2lib/include/2ui.h b/firmware/2lib/include/2ui.h
index 2fefaf3..d8c3847 100644
--- a/firmware/2lib/include/2ui.h
+++ b/firmware/2lib/include/2ui.h
@@ -59,12 +59,20 @@
 	 * will be ignored.
 	 */
 	const struct vb2_menu *(*get_menu)(struct vb2_ui_context *ui);
+	/*
+	 * Indices of menu items;
+	 * used by log_page_* functions in 2ui_screens.c.
+	 */
+	uint32_t page_up_item;
+	uint32_t page_down_item;
+	uint32_t back_item;
 };
 
 struct vb2_screen_state {
 	const struct vb2_screen_info *screen;
 	uint32_t selected_item;
 	uint32_t disabled_item_mask;
+	uint32_t hidden_item_mask;
 
 	/* For log screen. */
 	uint32_t page_count;
@@ -139,8 +147,8 @@
 /**
  * Move selection to the previous menu item.
  *
- * Update selected_item, taking into account disabled indices (from
- * disabled_item_mask).  The selection does not wrap, meaning that we block
+ * Update selected_item, taking into account hidden indices (from
+ * hidden_item_mask).  The selection does not wrap, meaning that we block
  * on 0 when we hit the start of the menu.
  *
  * @param ui		UI context pointer
@@ -151,8 +159,8 @@
 /**
  * Move selection to the next menu item.
  *
- * Update selected_item, taking into account disabled indices (from
- * disabled_item_mask).  The selection does not wrap, meaning that we block
+ * Update selected_item, taking into account hidden indices (from
+ * hidden_item_mask).  The selection does not wrap, meaning that we block
  * on the max index when we hit the end of the menu.
  *
  * @param ui		UI context pointer
diff --git a/tests/vb2_ui_action_tests.c b/tests/vb2_ui_action_tests.c
index 57b9700..84bb9e0 100644
--- a/tests/vb2_ui_action_tests.c
+++ b/tests/vb2_ui_action_tests.c
@@ -34,6 +34,7 @@
 	uint32_t locale_id;
 	uint32_t selected_item;
 	uint32_t disabled_item_mask;
+	uint32_t hidden_item_mask;
 	int timer_disabled;
 	uint32_t current_page;
 	enum vb2_ui_error error_code;
@@ -188,7 +189,7 @@
 static void screen_state_eq(const struct vb2_screen_state *state,
 			    enum vb2_screen screen,
 			    uint32_t selected_item,
-			    uint32_t disabled_item_mask)
+			    uint32_t hidden_item_mask)
 {
 	if (screen != MOCK_IGNORE) {
 		if (state->screen == NULL)
@@ -199,9 +200,9 @@
 	if (selected_item != MOCK_IGNORE)
 		TEST_EQ(state->selected_item,
 			selected_item, "  state.selected_item");
-	if (disabled_item_mask != MOCK_IGNORE)
-		TEST_EQ(state->disabled_item_mask,
-			disabled_item_mask, "  state.disabled_item_mask");
+	if (hidden_item_mask != MOCK_IGNORE)
+		TEST_EQ(state->hidden_item_mask,
+			hidden_item_mask, "  state.hidden_item_mask");
 }
 
 static void add_mock_key(uint32_t press, int trusted)
@@ -233,7 +234,7 @@
 			 enum vb2_screen screen,
 			 uint32_t locale_id,
 			 uint32_t selected_item,
-			 uint32_t disabled_item_mask,
+			 uint32_t hidden_item_mask,
 			 int line)
 {
 	char text_info[32], text_buf[128];
@@ -263,11 +264,11 @@
 		TEST_EQ(mock_displayed[mock_displayed_i].selected_item,
 			selected_item, text_buf);
 	}
-	if (disabled_item_mask != MOCK_IGNORE) {
-		sprintf(text_buf, "  %s disabled_item_mask of %s",
+	if (hidden_item_mask != MOCK_IGNORE) {
+		sprintf(text_buf, "  %s hidden_item_mask of %s",
 			text_info, text);
-		TEST_EQ(mock_displayed[mock_displayed_i].disabled_item_mask,
-			disabled_item_mask, text_buf);
+		TEST_EQ(mock_displayed[mock_displayed_i].hidden_item_mask,
+			hidden_item_mask, text_buf);
 	}
 	mock_displayed_i++;
 }
@@ -406,6 +407,7 @@
 			     uint32_t locale_id,
 			     uint32_t selected_item,
 			     uint32_t disabled_item_mask,
+			     uint32_t hidden_item_mask,
 			     int timer_disabled,
 			     uint32_t current_page,
 			     enum vb2_ui_error error_code)
@@ -415,6 +417,7 @@
 		.locale_id = locale_id,
 		.selected_item = selected_item,
 		.disabled_item_mask = disabled_item_mask,
+		.hidden_item_mask = hidden_item_mask,
 		.timer_disabled = timer_disabled,
 		.current_page = current_page,
 		.error_code = error_code,
@@ -427,10 +430,11 @@
 		return VB2_SUCCESS;
 
 	VB2_DEBUG("displayed %d: screen=%#x, locale_id=%u, selected_item=%u, "
-		  "disabled_item_mask=%#x, timer_disabled=%d, current_page=%u, "
-		  "error=%#x\n",
+		  "disabled_item_mask=%#x, hidden_item_mask=%#x, "
+		  "timer_disabled=%d, current_page=%u, error=%#x\n",
 		  mock_displayed_count, screen, locale_id, selected_item,
-		  disabled_item_mask, timer_disabled, current_page, error_code);
+		  disabled_item_mask, hidden_item_mask,
+		  timer_disabled, current_page, error_code);
 
 	if (mock_displayed_count >= ARRAY_SIZE(mock_displayed)) {
 		TEST_TRUE(0, "  mock vb2ex_display_ui ran out of entries!");
@@ -510,15 +514,26 @@
 	screen_state_eq(mock_ui_context.state, MOCK_SCREEN_MENU, 1,
 			MOCK_IGNORE);
 
-	/* Valid action with mask */
+	/* Valid action with hidden mask */
+	reset_common_data();
+	mock_ui_context.state->screen = &mock_screen_menu;
+	mock_ui_context.state->selected_item = 2;
+	mock_ui_context.state->hidden_item_mask = 0x0a;  /* 0b01010 */
+	mock_ui_context.key = VB_KEY_UP;
+	TEST_EQ(vb2_ui_menu_prev(&mock_ui_context), VB2_REQUEST_UI_CONTINUE,
+		"valid action with hidden mask");
+	screen_state_eq(mock_ui_context.state, MOCK_SCREEN_MENU, 0,
+			MOCK_IGNORE);
+
+	/* Disabled mask does not affect menu_prev */
 	reset_common_data();
 	mock_ui_context.state->screen = &mock_screen_menu;
 	mock_ui_context.state->selected_item = 2;
 	mock_ui_context.state->disabled_item_mask = 0x0a;  /* 0b01010 */
 	mock_ui_context.key = VB_KEY_UP;
 	TEST_EQ(vb2_ui_menu_prev(&mock_ui_context), VB2_REQUEST_UI_CONTINUE,
-		"valid action with mask");
-	screen_state_eq(mock_ui_context.state, MOCK_SCREEN_MENU, 0,
+		"valid action with disabled mask");
+	screen_state_eq(mock_ui_context.state, MOCK_SCREEN_MENU, 1,
 			MOCK_IGNORE);
 
 	/* Invalid action (blocked) */
@@ -535,7 +550,7 @@
 	reset_common_data();
 	mock_ui_context.state->screen = &mock_screen_menu;
 	mock_ui_context.state->selected_item = 2;
-	mock_ui_context.state->disabled_item_mask = 0x0b;  /* 0b01011 */
+	mock_ui_context.state->hidden_item_mask = 0x0b;  /* 0b01011 */
 	mock_ui_context.key = VB_KEY_UP;
 	TEST_EQ(vb2_ui_menu_prev(&mock_ui_context), VB2_REQUEST_UI_CONTINUE,
 		"invalid action (blocked by mask)");
@@ -572,15 +587,26 @@
 	screen_state_eq(mock_ui_context.state, MOCK_SCREEN_MENU, 3,
 			MOCK_IGNORE);
 
-	/* Valid action with mask */
+	/* Valid action with hidden mask */
+	reset_common_data();
+	mock_ui_context.state->screen = &mock_screen_menu;
+	mock_ui_context.state->selected_item = 2;
+	mock_ui_context.state->hidden_item_mask = 0x0a;  /* 0b01010 */
+	mock_ui_context.key = VB_KEY_DOWN;
+	TEST_EQ(vb2_ui_menu_next(&mock_ui_context), VB2_REQUEST_UI_CONTINUE,
+		"valid action with hidden mask");
+	screen_state_eq(mock_ui_context.state, MOCK_SCREEN_MENU, 4,
+			MOCK_IGNORE);
+
+	/* Disabled mask does not affect menu_next */
 	reset_common_data();
 	mock_ui_context.state->screen = &mock_screen_menu;
 	mock_ui_context.state->selected_item = 2;
 	mock_ui_context.state->disabled_item_mask = 0x0a;  /* 0b01010 */
 	mock_ui_context.key = VB_KEY_DOWN;
 	TEST_EQ(vb2_ui_menu_next(&mock_ui_context), VB2_REQUEST_UI_CONTINUE,
-		"valid action with mask");
-	screen_state_eq(mock_ui_context.state, MOCK_SCREEN_MENU, 4,
+		"valid action with disabled mask");
+	screen_state_eq(mock_ui_context.state, MOCK_SCREEN_MENU, 3,
 			MOCK_IGNORE);
 
 	/* Invalid action (blocked) */
@@ -597,7 +623,7 @@
 	reset_common_data();
 	mock_ui_context.state->screen = &mock_screen_menu;
 	mock_ui_context.state->selected_item = 2;
-	mock_ui_context.state->disabled_item_mask = 0x1a;  /* 0b11010 */
+	mock_ui_context.state->hidden_item_mask = 0x1a;  /* 0b11010 */
 	mock_ui_context.key = VB_KEY_DOWN;
 	TEST_EQ(vb2_ui_menu_next(&mock_ui_context), VB2_REQUEST_UI_CONTINUE,
 		"invalid action (blocked by mask)");
@@ -664,6 +690,16 @@
 	screen_state_eq(mock_ui_context.state, MOCK_SCREEN_MENU, 4,
 			MOCK_IGNORE);
 
+	/* Cannot select a disabled item (item 3) */
+	reset_common_data();
+	mock_ui_context.state->screen = &mock_screen_menu;
+	mock_ui_context.state->selected_item = 3;
+	mock_ui_context.state->disabled_item_mask = 0x08;  /* 0b01000 */
+	mock_ui_context.key = VB_KEY_ENTER;
+	TEST_EQ(vb2_ui_menu_select(&mock_ui_context),
+		VB2_REQUEST_UI_CONTINUE, "cannot select a disabled item");
+	TEST_EQ(mock_action_called, 0, "  no action called");
+
 	/* Ignore power button short press when not DETACHABLE */
 	if (!DETACHABLE) {
 		reset_common_data();
diff --git a/tests/vb2_ui_tests.c b/tests/vb2_ui_tests.c
index ec9bb65..8feb5e5 100644
--- a/tests/vb2_ui_tests.c
+++ b/tests/vb2_ui_tests.c
@@ -28,6 +28,7 @@
 	uint32_t locale_id;
 	uint32_t selected_item;
 	uint32_t disabled_item_mask;
+	uint32_t hidden_item_mask;
 	int timer_disabled;
 	uint32_t current_page;
 	enum vb2_ui_error error_code;
@@ -157,6 +158,7 @@
 			 uint32_t locale_id,
 			 uint32_t selected_item,
 			 uint32_t disabled_item_mask,
+			 uint32_t hidden_item_mask,
 			 uint32_t current_page,
 			 int line)
 {
@@ -193,6 +195,12 @@
 		TEST_EQ(mock_displayed[mock_displayed_i].disabled_item_mask,
 			disabled_item_mask, text_buf);
 	}
+	if (hidden_item_mask != MOCK_IGNORE) {
+		sprintf(text_buf, "  %s hidden_item_mask of %s",
+			text_info, text);
+		TEST_EQ(mock_displayed[mock_displayed_i].hidden_item_mask,
+			hidden_item_mask, text_buf);
+	}
 	if (current_page != MOCK_IGNORE) {
 		sprintf(text_buf, "  %s current_page of %s",
 			text_info, text);
@@ -219,7 +227,7 @@
 
 #define DISPLAYED_PASS() \
 	displayed_eq("", MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, \
-		     MOCK_IGNORE, __LINE__)
+		     MOCK_IGNORE, MOCK_IGNORE, __LINE__)
 
 #define DISPLAYED_NO_EXTRA() displayed_no_extra(__LINE__)
 
@@ -352,6 +360,7 @@
 			     uint32_t locale_id,
 			     uint32_t selected_item,
 			     uint32_t disabled_item_mask,
+			     uint32_t hidden_item_mask,
 			     int timer_disabled,
 			     uint32_t current_page,
 			     enum vb2_ui_error error_code)
@@ -361,6 +370,7 @@
 		.locale_id = locale_id,
 		.selected_item = selected_item,
 		.disabled_item_mask = disabled_item_mask,
+		.hidden_item_mask = hidden_item_mask,
 		.timer_disabled = timer_disabled,
 		.current_page = current_page,
 		.error_code = error_code,
@@ -373,10 +383,11 @@
 		return VB2_SUCCESS;
 
 	VB2_DEBUG("displayed %d: screen=%#x, locale_id=%u, selected_item=%u, "
-		  "disabled_item_mask=%#x, timer_disabled=%d, current_page=%u, "
-		  "error=%#x\n",
+		  "disabled_item_mask=%#x, hidden_item_mask=%#x, "
+		  "timer_disabled=%d, current_page=%u, error=%#x\n",
 		  mock_displayed_count, screen, locale_id, selected_item,
-		  disabled_item_mask, timer_disabled, current_page, error_code);
+		  disabled_item_mask, hidden_item_mask,
+		  timer_disabled, current_page, error_code);
 
 	if (mock_displayed_count >= ARRAY_SIZE(mock_displayed)) {
 		TEST_TRUE(0, "  mock vb2ex_display_ui ran out of entries!");
@@ -732,10 +743,10 @@
 	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,
+	DISPLAYED_EQ("to_norm", VB2_SCREEN_DEVELOPER_TO_NORM, MOCK_IGNORE,
 		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
 	DISPLAYED_PASS();
-	DISPLAYED_EQ("to_norm", VB2_SCREEN_DEVELOPER_TO_NORM,
+	DISPLAYED_EQ("to_norm", VB2_SCREEN_DEVELOPER_TO_NORM, MOCK_IGNORE,
 		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
 	DISPLAYED_NO_EXTRA();
 
@@ -868,11 +879,14 @@
 	TEST_EQ(vb2_manual_recovery_menu(ctx), VB2_SUCCESS,
 		"boots after valid image appears");
 	DISPLAYED_EQ("recovery select", VB2_SCREEN_RECOVERY_SELECT,
-		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
+		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE,
+		     MOCK_IGNORE);
 	DISPLAYED_EQ("recovery invalid", VB2_SCREEN_RECOVERY_INVALID,
-		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
+		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE,
+		     MOCK_IGNORE);
 	DISPLAYED_EQ("recovery select", VB2_SCREEN_RECOVERY_SELECT,
-		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
+		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE,
+		     MOCK_IGNORE);
 	DISPLAYED_NO_EXTRA();
 
 	/* Ctrl+D = to_dev; space = cancel */
@@ -883,11 +897,14 @@
 		"ctrl+d = to_dev; space = cancel");
 	TEST_EQ(mock_enable_dev_mode, 0, "  dev mode not enabled");
 	DISPLAYED_EQ("recovery select", VB2_SCREEN_RECOVERY_SELECT,
-		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
+		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE,
+		     MOCK_IGNORE);
 	DISPLAYED_EQ("to_dev", VB2_SCREEN_RECOVERY_TO_DEV,
-		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
+		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE,
+		     MOCK_IGNORE);
 	DISPLAYED_EQ("recovery select", VB2_SCREEN_RECOVERY_SELECT,
-		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
+		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE,
+		     MOCK_IGNORE);
 	DISPLAYED_NO_EXTRA();
 
 	/* Cancel to_dev transition */
@@ -956,7 +973,7 @@
 		TEST_EQ(mock_enable_dev_mode, 0, "  dev mode not enabled");
 		DISPLAYED_EQ("recovery select", VB2_SCREEN_RECOVERY_SELECT,
 			     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE,
-			     MOCK_IGNORE);
+			     MOCK_IGNORE, MOCK_IGNORE);
 		DISPLAYED_NO_EXTRA();
 
 		/* Button stuck, enter to_dev again */
@@ -975,10 +992,10 @@
 		TEST_EQ(mock_enable_dev_mode, 1, "  dev mode enabled");
 		DISPLAYED_EQ("recovery select", VB2_SCREEN_RECOVERY_SELECT,
 			     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE,
-			     MOCK_IGNORE);
+			     MOCK_IGNORE, MOCK_IGNORE);
 		DISPLAYED_EQ("to_dev", VB2_SCREEN_RECOVERY_TO_DEV,
 			     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE,
-			     MOCK_IGNORE);
+			     MOCK_IGNORE, MOCK_IGNORE);
 		DISPLAYED_NO_EXTRA();
 
 		/* Cancel with holding pp button, enter again */
@@ -1010,16 +1027,16 @@
 		TEST_EQ(mock_enable_dev_mode, 1, "  dev mode enabled");
 		DISPLAYED_EQ("recovery select", VB2_SCREEN_RECOVERY_SELECT,
 			     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE,
-			     MOCK_IGNORE);
+			     MOCK_IGNORE, MOCK_IGNORE);
 		DISPLAYED_EQ("to_dev", VB2_SCREEN_RECOVERY_TO_DEV,
 			     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE,
-			     MOCK_IGNORE);
+			     MOCK_IGNORE, MOCK_IGNORE);
 		DISPLAYED_EQ("recovery select", VB2_SCREEN_RECOVERY_SELECT,
 			     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE,
-			     MOCK_IGNORE);
+			     MOCK_IGNORE, MOCK_IGNORE);
 		DISPLAYED_EQ("to_dev", VB2_SCREEN_RECOVERY_TO_DEV,
 			     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE,
-			     MOCK_IGNORE);
+			     MOCK_IGNORE, MOCK_IGNORE);
 		DISPLAYED_NO_EXTRA();
 	}
 
@@ -1056,15 +1073,15 @@
 	TEST_EQ(vb2_manual_recovery_menu(ctx), VB2_REQUEST_SHUTDOWN,
 		"change language");
 	DISPLAYED_EQ("RECOVERY_SELECT default", VB2_SCREEN_RECOVERY_SELECT,
-		     23, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
+		     23, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
 	DISPLAYED_EQ("RECOVERY_SELECT lang", VB2_SCREEN_RECOVERY_SELECT,
-		     23, 0, MOCK_IGNORE, MOCK_IGNORE);
+		     23, 0, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
 	DISPLAYED_EQ("LANGUAGE_SELECT 23", VB2_SCREEN_LANGUAGE_SELECT,
-		     23, 23, MOCK_IGNORE, MOCK_IGNORE);
+		     23, 23, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
 	DISPLAYED_EQ("LANGUAGE_SELECT 24", VB2_SCREEN_LANGUAGE_SELECT,
-		     23, 24, MOCK_IGNORE, MOCK_IGNORE);
+		     23, 24, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
 	DISPLAYED_EQ("RECOVERY_SELECT new locale", VB2_SCREEN_RECOVERY_SELECT,
-		     24, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
+		     24, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
 	DISPLAYED_NO_EXTRA();
 	TEST_EQ(vb2_nv_get(ctx, VB2_NV_LOCALIZATION_INDEX), 24,
 		"  locale 24 saved to nvdata");
@@ -1080,13 +1097,13 @@
 	TEST_EQ(vb2_manual_recovery_menu(ctx), VB2_REQUEST_SHUTDOWN,
 		"enter language menu");
 	DISPLAYED_EQ("RECOVERY_SELECT default", VB2_SCREEN_RECOVERY_SELECT,
-		     23, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
+		     23, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
 	DISPLAYED_EQ("RECOVERY_SELECT lang", VB2_SCREEN_RECOVERY_SELECT,
-		     23, 0, MOCK_IGNORE, MOCK_IGNORE);
+		     23, 0, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
 	DISPLAYED_EQ("LANGUAGE_SELECT index 0", VB2_SCREEN_LANGUAGE_SELECT,
-		     23, 0, MOCK_IGNORE, MOCK_IGNORE);
+		     23, 0, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
 	DISPLAYED_EQ("RECOVERY_SELECT locale 0", VB2_SCREEN_RECOVERY_SELECT,
-		     0, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
+		     0, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
 	DISPLAYED_NO_EXTRA();
 
 	VB2_DEBUG("...done.\n");
@@ -1102,7 +1119,7 @@
 	TEST_EQ(vb2_developer_menu(ctx), VB2_REQUEST_SHUTDOWN,
 		"tab = debug info in dev mode");
 	DISPLAYED_PASS();
-	DISPLAYED_EQ("debug info", VB2_SCREEN_DEBUG_INFO,
+	DISPLAYED_EQ("debug info", VB2_SCREEN_DEBUG_INFO, MOCK_IGNORE,
 		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
 	DISPLAYED_NO_EXTRA();
 
@@ -1111,7 +1128,7 @@
 	TEST_EQ(vb2_broken_recovery_menu(ctx), VB2_REQUEST_SHUTDOWN,
 		"tab = debug info in broken recovery mode");
 	DISPLAYED_PASS();
-	DISPLAYED_EQ("debug info", VB2_SCREEN_DEBUG_INFO,
+	DISPLAYED_EQ("debug info", VB2_SCREEN_DEBUG_INFO, MOCK_IGNORE,
 		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
 	DISPLAYED_NO_EXTRA();
 
@@ -1120,7 +1137,7 @@
 	TEST_EQ(vb2_manual_recovery_menu(ctx), VB2_REQUEST_SHUTDOWN,
 		"tab = debug info in manual recovery mode");
 	DISPLAYED_PASS();
-	DISPLAYED_EQ("debug info", VB2_SCREEN_DEBUG_INFO,
+	DISPLAYED_EQ("debug info", VB2_SCREEN_DEBUG_INFO, MOCK_IGNORE,
 		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
 	DISPLAYED_NO_EXTRA();
 
@@ -1142,9 +1159,10 @@
 		"get a one-page debug info");
 	DISPLAYED_PASS();
 	DISPLAYED_EQ("debug info", VB2_SCREEN_DEBUG_INFO,
-		     MOCK_IGNORE, 3, 0x0, 0);
+		     MOCK_IGNORE, 3, 0x6, 0x0, 0);
 	DISPLAYED_EQ("back to root screen", VB2_SCREEN_RECOVERY_SELECT,
-		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
+		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE,
+		     MOCK_IGNORE);
 	DISPLAYED_NO_EXTRA();
 
 	/* Get a three-page debug info and navigate */
@@ -1165,25 +1183,26 @@
 		"get a three-page debug info and navigate");
 	DISPLAYED_PASS();
 	DISPLAYED_EQ("debug info page #0", VB2_SCREEN_DEBUG_INFO,
-		     MOCK_IGNORE, 2, 0x0, 0);
+		     MOCK_IGNORE, 2, 0x2, 0x0, 0);
 	DISPLAYED_EQ("debug info page #1", VB2_SCREEN_DEBUG_INFO,
-		     MOCK_IGNORE, 2, 0x0, 1);
+		     MOCK_IGNORE, 2, 0x0, 0x0, 1);
 	DISPLAYED_EQ("debug info page #2", VB2_SCREEN_DEBUG_INFO,
-		     MOCK_IGNORE, 2, 0x0, 2);
+		     MOCK_IGNORE, 2, 0x4, 0x0, 2);
 	DISPLAYED_EQ("debug info page #2", VB2_SCREEN_DEBUG_INFO,
-		     MOCK_IGNORE, 1, 0x0, 2);
+		     MOCK_IGNORE, 1, 0x4, 0x0, 2);
 	DISPLAYED_EQ("debug info page #1", VB2_SCREEN_DEBUG_INFO,
-		     MOCK_IGNORE, 1, 0x0, 1);
+		     MOCK_IGNORE, 1, 0x0, 0x0, 1);
 	DISPLAYED_EQ("debug info page #0", VB2_SCREEN_DEBUG_INFO,
-		     MOCK_IGNORE, 1, 0x0, 0);
+		     MOCK_IGNORE, 1, 0x2, 0x0, 0);
 	DISPLAYED_EQ("debug info page #0", VB2_SCREEN_DEBUG_INFO,
-		     MOCK_IGNORE, 2, 0x0, 0);
+		     MOCK_IGNORE, 2, 0x2, 0x0, 0);
 	DISPLAYED_EQ("debug info page #1", VB2_SCREEN_DEBUG_INFO,
-		     MOCK_IGNORE, 2, 0x0, 1);
+		     MOCK_IGNORE, 2, 0x0, 0x0, 1);
 	DISPLAYED_EQ("debug info page #1", VB2_SCREEN_DEBUG_INFO,
-		     MOCK_IGNORE, 3, 0x0, 1);
+		     MOCK_IGNORE, 3, 0x0, 0x0, 1);
 	DISPLAYED_EQ("back to root screen", VB2_SCREEN_RECOVERY_SELECT,
-		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
+		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE,
+		     MOCK_IGNORE);
 	DISPLAYED_NO_EXTRA();
 
 	VB2_DEBUG("...done.\n");
@@ -1266,7 +1285,7 @@
 	TEST_EQ(vb2_developer_menu(ctx), VB2_SUCCESS,
 		"dev mode screen: set default selection to boot internal");
 	DISPLAYED_EQ("dev mode screen", VB2_SCREEN_DEVELOPER_MODE,
-		     MOCK_IGNORE, 2, MOCK_IGNORE, MOCK_IGNORE);
+		     MOCK_IGNORE, 2, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
 
 	reset_common_data(FOR_DEVELOPER);
 	add_mock_vbtlk(VB2_SUCCESS, VB_DISK_FLAG_REMOVABLE);
@@ -1274,34 +1293,34 @@
 	TEST_EQ(vb2_developer_menu(ctx), VB2_SUCCESS,
 		"dev mode screen: set default selection to boot external");
 	DISPLAYED_EQ("dev mode screen", VB2_SCREEN_DEVELOPER_MODE,
-		     MOCK_IGNORE, 3, MOCK_IGNORE, MOCK_IGNORE);
+		     MOCK_IGNORE, 3, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
 
-	/* Dev mode: disabled item mask */
+	/* Dev mode: disabled and hidden item mask */
 	reset_common_data(FOR_DEVELOPER);
 	mock_dev_boot_legacy_allowed = 1;
 	add_mock_vbtlk(VB2_SUCCESS, VB_DISK_FLAG_FIXED);
 	TEST_EQ(vb2_developer_menu(ctx), VB2_SUCCESS,
-		"dev mode screen: no disabled item mask");
+		"dev mode screen: no disabled or hidden item");
 	DISPLAYED_EQ("dev mode screen", VB2_SCREEN_DEVELOPER_MODE,
-		     MOCK_IGNORE, MOCK_IGNORE, 0x0, MOCK_IGNORE);
+		     MOCK_IGNORE, MOCK_IGNORE, 0x0, 0x0, MOCK_IGNORE);
 
 	reset_common_data(FOR_DEVELOPER);
 	mock_dev_boot_legacy_allowed = 1;
 	gbb.flags |= VB2_GBB_FLAG_FORCE_DEV_SWITCH_ON;
 	add_mock_vbtlk(VB2_SUCCESS, VB_DISK_FLAG_FIXED);
 	TEST_EQ(vb2_developer_menu(ctx), VB2_SUCCESS,
-		"dev mode screen: disable to_norm item");
+		"dev mode screen: hide to_norm item");
 	DISPLAYED_EQ("dev mode screen", VB2_SCREEN_DEVELOPER_MODE,
-		     MOCK_IGNORE, MOCK_IGNORE, 0x2, MOCK_IGNORE);
+		     MOCK_IGNORE, MOCK_IGNORE, 0x0, 0x2, MOCK_IGNORE);
 
 	reset_common_data(FOR_DEVELOPER);
 	add_mock_vbtlk(VB2_SUCCESS, VB_DISK_FLAG_FIXED);
 	mock_dev_boot_external_allowed = 0;
 	mock_dev_boot_legacy_allowed = 1;
 	TEST_EQ(vb2_developer_menu(ctx), VB2_SUCCESS,
-		"dev mode screen: disable boot external");
+		"dev mode screen: hide boot external");
 	DISPLAYED_EQ("dev mode screen", VB2_SCREEN_DEVELOPER_MODE,
-		     MOCK_IGNORE, MOCK_IGNORE, 0x8, MOCK_IGNORE);
+		     MOCK_IGNORE, MOCK_IGNORE, 0x0, 0x8, MOCK_IGNORE);
 
 	/* Dev mode screen */
 	reset_common_data(FOR_DEVELOPER);  /* Select #2 by default */
@@ -1324,19 +1343,21 @@
 	DISPLAYED_PASS();
 	DISPLAYED_PASS();
 	DISPLAYED_EQ("dev mode", VB2_SCREEN_DEVELOPER_MODE,
-		     MOCK_IGNORE, 0, MOCK_IGNORE, MOCK_IGNORE);
+		     MOCK_IGNORE, 0, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
 	DISPLAYED_EQ("#0: language menu", VB2_SCREEN_LANGUAGE_SELECT,
-		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
+		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE,
+		     MOCK_IGNORE);
 	/* #1: Return to secure mode */
 	DISPLAYED_PASS();
 	DISPLAYED_EQ("dev mode", VB2_SCREEN_DEVELOPER_MODE,
-		     MOCK_IGNORE, 1, MOCK_IGNORE, MOCK_IGNORE);
+		     MOCK_IGNORE, 1, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
 	DISPLAYED_EQ("#1: return to secure mode", VB2_SCREEN_DEVELOPER_TO_NORM,
-		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
+		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE,
+		     MOCK_IGNORE);
 	/* #2: Boot internal */
 	DISPLAYED_PASS();
 	DISPLAYED_EQ("dev mode", VB2_SCREEN_DEVELOPER_MODE,
-		     MOCK_IGNORE, 2, MOCK_IGNORE, MOCK_IGNORE);
+		     MOCK_IGNORE, 2, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
 	VB2_DEBUG("#2: boot internal (no extra screen)\n");
 	DISPLAYED_NO_EXTRA();
 
@@ -1349,7 +1370,7 @@
 		"dev mode screen");
 	/* #3: Boot external */
 	DISPLAYED_EQ("dev mode", VB2_SCREEN_DEVELOPER_MODE,
-		     MOCK_IGNORE, 3, MOCK_IGNORE, MOCK_IGNORE);
+		     MOCK_IGNORE, 3, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
 	VB2_DEBUG("#3: boot external (no extra screen)\n");
 	DISPLAYED_NO_EXTRA();
 
@@ -1380,15 +1401,29 @@
 	DISPLAYED_PASS();
 	DISPLAYED_PASS();
 	DISPLAYED_EQ("dev mode", VB2_SCREEN_DEVELOPER_MODE,
-		     MOCK_IGNORE, 5, MOCK_IGNORE, MOCK_IGNORE);
+		     MOCK_IGNORE, 5, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
 	DISPLAYED_EQ("#4: advanced options", VB2_SCREEN_ADVANCED_OPTIONS,
-		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
+		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE,
+		     MOCK_IGNORE);
 	/* End of menu */
 	DISPLAYED_PASS();
 	DISPLAYED_EQ("end of menu", VB2_SCREEN_DEVELOPER_MODE,
-		     MOCK_IGNORE, 6, MOCK_IGNORE, MOCK_IGNORE);
+		     MOCK_IGNORE, 6, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
 	DISPLAYED_NO_EXTRA();
 
+	/* Advanced options screen: disabled and hidden item mask */
+	reset_common_data(FOR_DEVELOPER);
+	add_mock_keypress(VB_KEY_DOWN);
+	add_mock_keypress(VB_KEY_DOWN);
+	add_mock_keypress(VB_KEY_ENTER);
+	TEST_EQ(vb2_developer_menu(ctx), VB2_REQUEST_SHUTDOWN,
+		"advanced options screen: hide to_dev");
+	DISPLAYED_PASS();
+	DISPLAYED_PASS();
+	DISPLAYED_PASS();
+	DISPLAYED_EQ("advanced options", VB2_SCREEN_ADVANCED_OPTIONS,
+		     MOCK_IGNORE, MOCK_IGNORE, 0x0, 0x2, MOCK_IGNORE);
+
 	/* Advanced options screen */
 	reset_common_data(FOR_DEVELOPER);
 	add_mock_keypress(VB_KEY_DOWN);
@@ -1397,7 +1432,7 @@
 	/* #0: Language menu */
 	add_mock_keypress(VB_KEY_UP);
 	add_mock_keypress(VB_KEY_ENTER);
-	/* #1: (Disabled) */
+	/* #1: (Hidden) */
 	/* #2: Debug info */
 	add_mock_keypress(VB_KEY_ESC);
 	add_mock_keypress(VB_KEY_DOWN);
@@ -1421,31 +1456,35 @@
 	DISPLAYED_PASS();
 	/* #0: Language menu */
 	DISPLAYED_EQ("advanced options", VB2_SCREEN_ADVANCED_OPTIONS,
-		     MOCK_IGNORE, 0, 0x2, MOCK_IGNORE);
+		     MOCK_IGNORE, 0, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
 	DISPLAYED_EQ("#0: language menu", VB2_SCREEN_LANGUAGE_SELECT,
-		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
-	/* #1: (Disabled) */
+		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE,
+		     MOCK_IGNORE);
+	/* #1: (Hidden) */
 	/* #2: Debug info */
 	DISPLAYED_PASS();
 	DISPLAYED_EQ("advanced options", VB2_SCREEN_ADVANCED_OPTIONS,
-		     MOCK_IGNORE, 2, 0x2, MOCK_IGNORE);
+		     MOCK_IGNORE, 2, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
 	DISPLAYED_EQ("#2: debug info", VB2_SCREEN_DEBUG_INFO,
-		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
+		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE,
+		     MOCK_IGNORE);
 	/* #3: Firmware log */
 	DISPLAYED_PASS();
 	DISPLAYED_EQ("advanced options", VB2_SCREEN_ADVANCED_OPTIONS,
-		     MOCK_IGNORE, 3, 0x2, MOCK_IGNORE);
+		     MOCK_IGNORE, 3, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
 	DISPLAYED_EQ("#3: firmware log", VB2_SCREEN_FIRMWARE_LOG,
-		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
+		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE,
+		     MOCK_IGNORE);
 	/* #4: Back */
 	DISPLAYED_PASS();
 	DISPLAYED_EQ("advanced options", VB2_SCREEN_ADVANCED_OPTIONS,
-		     MOCK_IGNORE, 4, 0x2, MOCK_IGNORE);
+		     MOCK_IGNORE, 4, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
 	DISPLAYED_EQ("#4: back", VB2_SCREEN_DEVELOPER_MODE,
-		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
+		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE,
+		     MOCK_IGNORE);
 	/* End of menu */
 	DISPLAYED_EQ("end of menu", VB2_SCREEN_ADVANCED_OPTIONS,
-		     MOCK_IGNORE, 2, MOCK_IGNORE, MOCK_IGNORE);
+		     MOCK_IGNORE, 2, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
 	DISPLAYED_NO_EXTRA();
 
 	VB2_DEBUG("...done.\n");
@@ -1453,6 +1492,13 @@
 
 static void broken_recovery_screen_tests(void)
 {
+	/* Broken screen: disabled and hidden item mask */
+	reset_common_data(FOR_BROKEN_RECOVERY);
+	TEST_EQ(vb2_broken_recovery_menu(ctx), VB2_REQUEST_SHUTDOWN,
+		"broken screen: no disabled and hidden item mask");
+	DISPLAYED_EQ("broken screen", VB2_SCREEN_RECOVERY_BROKEN,
+		     MOCK_IGNORE, MOCK_IGNORE, 0x0, 0x0, MOCK_IGNORE);
+
 	/* Broken screen */
 	reset_common_data(FOR_BROKEN_RECOVERY);
 	/* #0: Language menu */
@@ -1470,27 +1516,38 @@
 	/* #0: Language menu */
 	DISPLAYED_PASS();
 	DISPLAYED_EQ("broken screen", VB2_SCREEN_RECOVERY_BROKEN,
-		     MOCK_IGNORE, 0, 0x0, MOCK_IGNORE);
+		     MOCK_IGNORE, 0, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
 	DISPLAYED_EQ("#0: language menu", VB2_SCREEN_LANGUAGE_SELECT,
-		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
+		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE,
+		     MOCK_IGNORE);
 	/* #1: Advanced options */
 	DISPLAYED_PASS();
 	DISPLAYED_EQ("broken screen", VB2_SCREEN_RECOVERY_BROKEN,
-		     MOCK_IGNORE, 1, 0x0, MOCK_IGNORE);
+		     MOCK_IGNORE, 1, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
 	DISPLAYED_EQ("#1: advanced options", VB2_SCREEN_ADVANCED_OPTIONS,
-		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
+		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE,
+		     MOCK_IGNORE);
 	/* End of menu */
 	DISPLAYED_EQ("end of menu", VB2_SCREEN_RECOVERY_BROKEN,
-		     MOCK_IGNORE, 1, MOCK_IGNORE, MOCK_IGNORE);
+		     MOCK_IGNORE, 1, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
 	DISPLAYED_NO_EXTRA();
 
+	/* Advanced options screen: disabled and hidden item mask */
+	reset_common_data(FOR_BROKEN_RECOVERY);
+	add_mock_keypress(VB_KEY_ENTER);
+	TEST_EQ(vb2_broken_recovery_menu(ctx), VB2_REQUEST_SHUTDOWN,
+		"advanced options screen: hide to_dev item");
+	DISPLAYED_PASS();
+	DISPLAYED_EQ("advanced options", VB2_SCREEN_ADVANCED_OPTIONS,
+		     MOCK_IGNORE, MOCK_IGNORE, 0x0, 0x2, MOCK_IGNORE);
+
 	/* Advanced options screen */
 	reset_common_data(FOR_BROKEN_RECOVERY);
 	add_mock_keypress(VB_KEY_ENTER);
 	/* #0: Language menu */
 	add_mock_keypress(VB_KEY_UP);
 	add_mock_keypress(VB_KEY_ENTER);
-	/* #1: (Disabled) */
+	/* #1: (Hidden) */
 	/* #2: Debug info */
 	add_mock_keypress(VB_KEY_ESC);
 	add_mock_keypress(VB_KEY_DOWN);
@@ -1512,31 +1569,35 @@
 	DISPLAYED_PASS();
 	/* #0: Language menu */
 	DISPLAYED_EQ("advanced options", VB2_SCREEN_ADVANCED_OPTIONS,
-		     MOCK_IGNORE, 0, 0x2, MOCK_IGNORE);
+		     MOCK_IGNORE, 0, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
 	DISPLAYED_EQ("#0: language menu", VB2_SCREEN_LANGUAGE_SELECT,
-		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
-	/* #1: (Disabled) */
+		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE,
+		     MOCK_IGNORE);
+	/* #1: (Hidden) */
 	/* #2: Debug info */
 	DISPLAYED_PASS();
 	DISPLAYED_EQ("advanced options", VB2_SCREEN_ADVANCED_OPTIONS,
-		     MOCK_IGNORE, 2, 0x2, MOCK_IGNORE);
+		     MOCK_IGNORE, 2, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
 	DISPLAYED_EQ("#2: debug info", VB2_SCREEN_DEBUG_INFO,
-		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
+		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE,
+		     MOCK_IGNORE);
 	/* #3: Firmware log */
 	DISPLAYED_PASS();
 	DISPLAYED_EQ("advanced options", VB2_SCREEN_ADVANCED_OPTIONS,
-		     MOCK_IGNORE, 3, 0x2, MOCK_IGNORE);
+		     MOCK_IGNORE, 3, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
 	DISPLAYED_EQ("#3: firmware log", VB2_SCREEN_FIRMWARE_LOG,
-		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
+		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE,
+		     MOCK_IGNORE);
 	/* #4: Back */
 	DISPLAYED_PASS();
 	DISPLAYED_EQ("advanced options", VB2_SCREEN_ADVANCED_OPTIONS,
-		     MOCK_IGNORE, 4, 0x2, MOCK_IGNORE);
+		     MOCK_IGNORE, 4, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
 	DISPLAYED_EQ("#4: back", VB2_SCREEN_RECOVERY_BROKEN,
-		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
+		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE,
+		     MOCK_IGNORE);
 	/* End of menu */
 	DISPLAYED_EQ("end of menu", VB2_SCREEN_ADVANCED_OPTIONS,
-		     MOCK_IGNORE, 2, MOCK_IGNORE, MOCK_IGNORE);
+		     MOCK_IGNORE, 2, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
 	DISPLAYED_NO_EXTRA();
 
 	VB2_DEBUG("...done.\n");
@@ -1544,6 +1605,16 @@
 
 static void manual_recovery_screen_tests(void)
 {
+	/* Recovery select screen: disabled and hidden item mask */
+	reset_common_data(FOR_MANUAL_RECOVERY);
+	TEST_EQ(vb2_manual_recovery_menu(ctx), VB2_REQUEST_SHUTDOWN,
+		DIAGNOSTIC_UI ?
+			"recovery select screen: no disabled or hidden item" :
+			"recovery select screen: hide `launch diag`");
+	DISPLAYED_EQ("recovery select", VB2_SCREEN_RECOVERY_SELECT,
+		     MOCK_IGNORE, MOCK_IGNORE, 0x0, DIAGNOSTIC_UI ? 0x0 : 0x8,
+		     MOCK_IGNORE);
+
 	/* Recovery select screen */
 	reset_common_data(FOR_MANUAL_RECOVERY);
 	/* #0: Language menu */
@@ -1574,40 +1645,60 @@
 	/* #0: Language menu */
 	DISPLAYED_PASS();
 	DISPLAYED_EQ("recovery select", VB2_SCREEN_RECOVERY_SELECT,
-		     MOCK_IGNORE, 0, DIAGNOSTIC_UI ? 0x0 : (1 << 3),
-		     MOCK_IGNORE);
+		     MOCK_IGNORE, 0, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
 	DISPLAYED_EQ("#0: language menu", VB2_SCREEN_LANGUAGE_SELECT,
-		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
+		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE,
+		     MOCK_IGNORE);
 	/* #1: Phone recovery */
 	DISPLAYED_PASS();
 	DISPLAYED_EQ("recovery select", VB2_SCREEN_RECOVERY_SELECT,
-		     MOCK_IGNORE, 1, MOCK_IGNORE, MOCK_IGNORE);
+		     MOCK_IGNORE, 1, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
 	DISPLAYED_EQ("#1: phone recovery", VB2_SCREEN_RECOVERY_PHONE_STEP1,
-		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
+		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE,
+		     MOCK_IGNORE);
 	/* #2: External disk recovery */
 	DISPLAYED_PASS();
 	DISPLAYED_EQ("recovery select", VB2_SCREEN_RECOVERY_SELECT,
-		     MOCK_IGNORE, 2, MOCK_IGNORE, MOCK_IGNORE);
+		     MOCK_IGNORE, 2, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
 	DISPLAYED_EQ("#2: disk recovery", VB2_SCREEN_RECOVERY_DISK_STEP1,
-		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
+		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE,
+		     MOCK_IGNORE);
 	DISPLAYED_EQ("recovery select", VB2_SCREEN_RECOVERY_SELECT,
-		MOCK_IGNORE, 2, MOCK_IGNORE, MOCK_IGNORE);
+		MOCK_IGNORE, 2, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
 	/* #3: Launch diagnostics */
 	if (DIAGNOSTIC_UI)
 		DISPLAYED_EQ("recovery select", VB2_SCREEN_RECOVERY_SELECT,
-			MOCK_IGNORE, 3, MOCK_IGNORE, MOCK_IGNORE);
+			MOCK_IGNORE, 3, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
 	/* #4: Advanced options */
 	DISPLAYED_EQ("recovery select", VB2_SCREEN_RECOVERY_SELECT,
-		     MOCK_IGNORE, 4, MOCK_IGNORE, MOCK_IGNORE);
+		     MOCK_IGNORE, 4, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
 
 	DISPLAYED_EQ("#3: advanced options", VB2_SCREEN_ADVANCED_OPTIONS,
-		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
+		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE,
+		     MOCK_IGNORE);
 	/* End of menu */
 	DISPLAYED_PASS();
 	DISPLAYED_EQ("end of menu", VB2_SCREEN_RECOVERY_SELECT,
-		     MOCK_IGNORE, 5, MOCK_IGNORE, MOCK_IGNORE);
+		     MOCK_IGNORE, 5, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
 	DISPLAYED_NO_EXTRA();
 
+	/* Advanced options screen: disabled and hidden item mask */
+	reset_common_data(FOR_MANUAL_RECOVERY);
+	add_mock_keypress(VB_KEY_DOWN);
+	add_mock_keypress(VB_KEY_DOWN);
+	if (DIAGNOSTIC_UI)
+		add_mock_keypress(VB_KEY_DOWN);
+	add_mock_keypress(VB_KEY_ENTER);
+	TEST_EQ(vb2_manual_recovery_menu(ctx), VB2_REQUEST_SHUTDOWN,
+		"advanced options screen: no disabled or hidden item");
+	DISPLAYED_PASS();
+	DISPLAYED_PASS();
+	if (DIAGNOSTIC_UI)
+		DISPLAYED_PASS();
+	DISPLAYED_PASS();
+	DISPLAYED_EQ("advanced options", VB2_SCREEN_ADVANCED_OPTIONS,
+		     MOCK_IGNORE, MOCK_IGNORE, 0x0, 0x0, MOCK_IGNORE);
+
 	/* Advanced options screen */
 	reset_common_data(FOR_MANUAL_RECOVERY);
 	/* #0: Language menu */
@@ -1648,37 +1739,42 @@
 	/* #0: Language menu */
 	DISPLAYED_PASS();
 	DISPLAYED_EQ("advanced options", VB2_SCREEN_ADVANCED_OPTIONS,
-		     MOCK_IGNORE, 0, 0x0, MOCK_IGNORE);
+		     MOCK_IGNORE, 0, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
 	DISPLAYED_EQ("#0: language menu", VB2_SCREEN_LANGUAGE_SELECT,
-		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
+		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE,
+		     MOCK_IGNORE);
 	/* #1: Enable dev mode */
 	DISPLAYED_PASS();
 	DISPLAYED_EQ("advanced options", VB2_SCREEN_ADVANCED_OPTIONS,
-		     MOCK_IGNORE, 1, 0x0, MOCK_IGNORE);
+		     MOCK_IGNORE, 1, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
 	DISPLAYED_EQ("#1: enable dev mode", VB2_SCREEN_RECOVERY_TO_DEV,
-		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
+		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE,
+		     MOCK_IGNORE);
 	/* #2: Debug info */
 	DISPLAYED_PASS();
 	DISPLAYED_EQ("advanced options", VB2_SCREEN_ADVANCED_OPTIONS,
-		     MOCK_IGNORE, 2, 0x0, MOCK_IGNORE);
+		     MOCK_IGNORE, 2, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
 	DISPLAYED_EQ("#2: debug info", VB2_SCREEN_DEBUG_INFO,
-		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
+		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE,
+		     MOCK_IGNORE);
 	/* #3: Firmware log */
 	DISPLAYED_PASS();
 	DISPLAYED_EQ("advanced options", VB2_SCREEN_ADVANCED_OPTIONS,
-		     MOCK_IGNORE, 3, 0x0, MOCK_IGNORE);
+		     MOCK_IGNORE, 3, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
 	DISPLAYED_EQ("#3: firmware log", VB2_SCREEN_FIRMWARE_LOG,
-		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
+		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE,
+		     MOCK_IGNORE);
 	/* #4: Back */
 	DISPLAYED_PASS();
 	DISPLAYED_EQ("advanced options", VB2_SCREEN_ADVANCED_OPTIONS,
-		     MOCK_IGNORE, 4, 0x0, MOCK_IGNORE);
+		     MOCK_IGNORE, 4, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
 	DISPLAYED_EQ("#4: back", VB2_SCREEN_RECOVERY_SELECT,
-		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
+		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE,
+		     MOCK_IGNORE);
 	/* End of menu */
 	DISPLAYED_PASS();
 	DISPLAYED_EQ("end of menu", VB2_SCREEN_ADVANCED_OPTIONS,
-		     MOCK_IGNORE, 2, 0x0, MOCK_IGNORE);
+		     MOCK_IGNORE, 2, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
 	DISPLAYED_NO_EXTRA();
 
 	VB2_DEBUG("...done.\n");
@@ -1688,6 +1784,13 @@
 {
 	VB2_DEBUG("Testing diagnostic screens...\n");
 
+	/* Diagnostics screen: disabled and hidden item mask */
+	reset_common_data(FOR_DIAGNOSTICS);
+	TEST_EQ(vb2_diagnostic_menu(ctx), VB2_REQUEST_SHUTDOWN,
+		"diagnostic screen: no disabled or hidden item");
+	DISPLAYED_EQ("diagnostic menu", VB2_SCREEN_DIAGNOSTICS,
+		     MOCK_IGNORE, MOCK_IGNORE, 0x0, 0x0, MOCK_IGNORE);
+
 	/* Diagnostics screen */
 	reset_common_data(FOR_DIAGNOSTICS);
 
@@ -1715,36 +1818,44 @@
 		"diagnostic screen");
 
 	DISPLAYED_EQ("default on first button of menu",
-		     VB2_SCREEN_DIAGNOSTICS, MOCK_IGNORE, 1, 0x0, MOCK_IGNORE);
+		     VB2_SCREEN_DIAGNOSTICS, MOCK_IGNORE, 1, MOCK_IGNORE,
+		     MOCK_IGNORE, MOCK_IGNORE);
 	/* #0: Language menu */
 	DISPLAYED_EQ("language selection",
-		     VB2_SCREEN_DIAGNOSTICS, MOCK_IGNORE, 0, 0x0, MOCK_IGNORE);
+		     VB2_SCREEN_DIAGNOSTICS, MOCK_IGNORE, 0, MOCK_IGNORE,
+		     MOCK_IGNORE, MOCK_IGNORE);
 	DISPLAYED_EQ("#0: language menu", VB2_SCREEN_LANGUAGE_SELECT,
-		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
+		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE,
+		     MOCK_IGNORE);
 	/* #1: Storage screen */
 	DISPLAYED_PASS();
 	DISPLAYED_EQ("storage button",
-		     VB2_SCREEN_DIAGNOSTICS, MOCK_IGNORE, 1, 0x0, MOCK_IGNORE);
+		     VB2_SCREEN_DIAGNOSTICS, MOCK_IGNORE, 1, MOCK_IGNORE,
+		     MOCK_IGNORE, MOCK_IGNORE);
 	DISPLAYED_EQ("#1: storage screen", VB2_SCREEN_DIAGNOSTICS_STORAGE,
-		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
+		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE,
+		     MOCK_IGNORE);
 	/* #2: Quick memory test screen */
 	DISPLAYED_PASS();
 	DISPLAYED_EQ("quick memory test button",
-		     VB2_SCREEN_DIAGNOSTICS, MOCK_IGNORE, 2, 0x0, MOCK_IGNORE);
+		     VB2_SCREEN_DIAGNOSTICS, MOCK_IGNORE, 2, MOCK_IGNORE,
+		     MOCK_IGNORE, MOCK_IGNORE);
 	DISPLAYED_EQ("#1: quick memory test screen",
 		     VB2_SCREEN_DIAGNOSTICS_MEMORY_QUICK, MOCK_IGNORE,
-		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
+		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
 	/* #3: Full memory test screen */
 	DISPLAYED_PASS();
 	DISPLAYED_EQ("full memory test button",
-		     VB2_SCREEN_DIAGNOSTICS, MOCK_IGNORE, 3, 0x0, MOCK_IGNORE);
+		     VB2_SCREEN_DIAGNOSTICS, MOCK_IGNORE, 3, MOCK_IGNORE,
+		     MOCK_IGNORE, MOCK_IGNORE);
 	DISPLAYED_EQ("#3: full memory test screen",
 		     VB2_SCREEN_DIAGNOSTICS_MEMORY_FULL, MOCK_IGNORE,
-		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
+		     MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
 	/* #4: Power of (End of menu) */
 	DISPLAYED_PASS();
 	DISPLAYED_EQ("power off",
-		     VB2_SCREEN_DIAGNOSTICS, MOCK_IGNORE, 4, 0x0, MOCK_IGNORE);
+		     VB2_SCREEN_DIAGNOSTICS, MOCK_IGNORE, 4, MOCK_IGNORE,
+		     MOCK_IGNORE, MOCK_IGNORE);
 	DISPLAYED_NO_EXTRA();
 
 	VB2_DEBUG("...done.\n");
diff --git a/tests/vb2_ui_utility_tests.c b/tests/vb2_ui_utility_tests.c
index dbdebd3..821402a 100644
--- a/tests/vb2_ui_utility_tests.c
+++ b/tests/vb2_ui_utility_tests.c
@@ -85,7 +85,7 @@
 static void screen_state_eq(const struct vb2_screen_state *state,
 			    enum vb2_screen screen,
 			    uint32_t selected_item,
-			    uint32_t disabled_item_mask)
+			    uint32_t hidden_item_mask)
 {
 	if (screen != MOCK_IGNORE) {
 		if (state->screen == NULL)
@@ -96,9 +96,9 @@
 	if (selected_item != MOCK_IGNORE)
 		TEST_EQ(state->selected_item,
 			selected_item, "  state.selected_item");
-	if (disabled_item_mask != MOCK_IGNORE)
-		TEST_EQ(state->disabled_item_mask,
-			disabled_item_mask, "  state.disabled_item_mask");
+	if (hidden_item_mask != MOCK_IGNORE)
+		TEST_EQ(state->hidden_item_mask,
+			hidden_item_mask, "  state.hidden_item_mask");
 }
 
 /* Reset mock data (for use before each test) */
@@ -292,7 +292,7 @@
 	vb2_ui_screen_change(&mock_ui_context, MOCK_SCREEN_ROOT);
 	vb2_ui_screen_change(&mock_ui_context, MOCK_SCREEN_BASE);
 	mock_ui_context.state->selected_item = 2;
-	mock_ui_context.state->disabled_item_mask = 0x10;
+	mock_ui_context.state->hidden_item_mask = 0x10;
 	vb2_ui_screen_change(&mock_ui_context, MOCK_SCREEN_MENU);
 	TEST_EQ(vb2_ui_screen_back(&mock_ui_context), VB2_REQUEST_UI_CONTINUE,
 		"back to previous screen");
@@ -305,7 +305,7 @@
 	vb2_ui_screen_change(&mock_ui_context, MOCK_SCREEN_ROOT);
 	vb2_ui_screen_change(&mock_ui_context, MOCK_SCREEN_BASE);
 	mock_ui_context.state->selected_item = 2;
-	mock_ui_context.state->disabled_item_mask = 0x10;
+	mock_ui_context.state->hidden_item_mask = 0x10;
 	vb2_ui_screen_change(&mock_ui_context, MOCK_SCREEN_MENU);
 	TEST_EQ(vb2_ui_screen_change(&mock_ui_context, MOCK_SCREEN_BASE),
 		VB2_REQUEST_UI_CONTINUE, "change to target in stack");