From 8c4b828502d8c6c7112286720dddfd30c92a968e Mon Sep 17 00:00:00 2001 From: Shelley Chen Date: Mon, 31 Jul 2017 14:28:42 -0700 Subject: detachables: Skip "Enable Developer Mode" in DEV mode When DUT is already in dev mode, don't let user select the "Enable Developer Mode" selection in the menu. Add disabled_idx_mask to VbExDisplayMenu API to allow for disabling of menu items in the future if needed. BUG=b:63078243, b:35585623 BRANCH=None TEST=reboot into recovery with DUT already in dev mode. Make sure can't scroll to "Enable Developer Mode: entry. reboot into recovery with DUT in normal mode. Make sure "Enable Developer Mode" entry is selectable. CQ-DEPEND=CL:565335 Change-Id: Ic71fe6aa2e41337787a0c2278f729356edb155fd Signed-off-by: Shelley Chen Reviewed-on: https://chromium-review.googlesource.com/598430 Reviewed-by: Julius Werner --- firmware/include/vboot_api.h | 15 ++- firmware/lib/include/vboot_display.h | 3 +- firmware/lib/vboot_display.c | 10 +- firmware/lib/vboot_ui_menu.c | 176 +++++++++++++++++++++-------------- firmware/stub/vboot_api_stub.c | 3 +- 5 files changed, 128 insertions(+), 79 deletions(-) diff --git a/firmware/include/vboot_api.h b/firmware/include/vboot_api.h index 049ec90f..ccd65961 100644 --- a/firmware/include/vboot_api.h +++ b/firmware/include/vboot_api.h @@ -808,13 +808,18 @@ VbError_t VbExDisplayScreen(uint32_t screen_type, uint32_t locale); /** * Display a predefined menu screen; see VB_SCREEN_* for valid screens. * - * This is a backup method of screen display, intended for use if the GBB does - * not contain a full set of bitmaps. It is acceptable for the backup screen - * to be simple ASCII text such as "NO GOOD" or "INSERT"; these screens should - * only be seen during development. + * @param screen_type ID of screen to draw + * @param locale language to display + * @param selected_index Index of menu item that is currently selected. + * @param disabled_idx_mask Bitmap for enabling/disabling certain menu items. + * each bit corresponds to the menu item's index. + * @param redraw_base Setting 1 will force a full redraw of the screen + * + * @return VBERROR_SUCCESS or error code on error. */ VbError_t VbExDisplayMenu(uint32_t screen_type, uint32_t locale, - uint32_t selected_index, uint32_t redraw_base); + uint32_t selected_index, uint32_t disabled_idx_mask, + uint32_t redraw_base); /** * Write an image to the display, with the upper left corner at the specified diff --git a/firmware/lib/include/vboot_display.h b/firmware/lib/include/vboot_display.h index 664bc195..2f237533 100644 --- a/firmware/lib/include/vboot_display.h +++ b/firmware/lib/include/vboot_display.h @@ -20,7 +20,8 @@ VbError_t VbDisplayScreenFromGBB(struct vb2_context *ctx, VbError_t VbDisplayScreen(struct vb2_context *ctx, VbCommonParams *cparams, uint32_t screen, int force); VbError_t VbDisplayMenu(struct vb2_context *ctx, VbCommonParams *cparams, - uint32_t screen, int force, uint32_t selected_index); + uint32_t screen, int force, uint32_t selected_index, + uint32_t disabled_idx_mask); VbError_t VbDisplayDebugInfo(struct vb2_context *ctx, VbCommonParams *cparams); VbError_t VbCheckDisplayKey(struct vb2_context *ctx, VbCommonParams *cparams, uint32_t key); diff --git a/firmware/lib/vboot_display.c b/firmware/lib/vboot_display.c index f3cb4d6e..24ac0725 100644 --- a/firmware/lib/vboot_display.c +++ b/firmware/lib/vboot_display.c @@ -23,6 +23,7 @@ static uint32_t disp_current_screen = VB_SCREEN_BLANK; static uint32_t disp_current_index = 0; +static uint32_t disp_disabled_idx_mask = 0; static uint32_t disp_width = 0, disp_height = 0; __attribute__((weak)) @@ -375,7 +376,7 @@ VbError_t VbDisplayScreen(struct vb2_context *ctx, VbError_t VbDisplayMenu(struct vb2_context *ctx, VbCommonParams *cparams, uint32_t screen, int force, - uint32_t selected_index) + uint32_t selected_index, uint32_t disabled_idx_mask) { uint32_t locale; VbError_t rv; @@ -400,7 +401,8 @@ VbError_t VbDisplayMenu(struct vb2_context *ctx, /* Read the locale last saved */ locale = vb2_nv_get(ctx, VB2_NV_LOCALIZATION_INDEX); - rv = VbExDisplayMenu(screen, locale, selected_index, redraw_base_screen); + rv = VbExDisplayMenu(screen, locale, selected_index, + disabled_idx_mask, redraw_base_screen); if (rv == VBERROR_SUCCESS) { /* @@ -409,6 +411,7 @@ VbError_t VbDisplayMenu(struct vb2_context *ctx, */ disp_current_screen = screen; disp_current_index = selected_index; + disp_disabled_idx_mask = disabled_idx_mask; } return rv; @@ -613,7 +616,8 @@ VbError_t VbDisplayDebugInfo(struct vb2_context *ctx, VbCommonParams *cparams) * highlighted. On a non-detachable screen, this will be a * no-op. */ - VbDisplayMenu(ctx, cparams, disp_current_screen, 1, disp_current_index); + VbDisplayMenu(ctx, cparams, disp_current_screen, 1, + disp_current_index, disp_disabled_idx_mask); /* Add hardware ID */ VbRegionReadHWID(cparams, hwid, sizeof(hwid)); diff --git a/firmware/lib/vboot_ui_menu.c b/firmware/lib/vboot_ui_menu.c index 29c561b5..d7c647ca 100644 --- a/firmware/lib/vboot_ui_menu.c +++ b/firmware/lib/vboot_ui_menu.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The Chromium OS Authors. All rights reserved. * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -226,6 +226,7 @@ static VB_MENU current_menu = VB_MENU_DEV_WARNING; static VB_MENU prev_menu = VB_MENU_DEV_WARNING; static int current_menu_idx = VB_WARN_POWER_OFF; static int selected = 0; +static int disabled_idx_mask = 0; static uint32_t default_boot = VB2_DEV_DEFAULT_BOOT_DISK; // TODO: add in consts @@ -376,7 +377,8 @@ VbError_t vb2_draw_current_screen(struct vb2_context *ctx, screen = VB_MENU_TO_SCREEN_MAP[current_menu]; else return VBERROR_UNKNOWN; - return VbDisplayMenu(ctx, cparams, screen, 0, current_menu_idx); + return VbDisplayMenu(ctx, cparams, screen, 0, + current_menu_idx, disabled_idx_mask); } /** @@ -564,41 +566,38 @@ VbError_t vb2_update_menu(struct vb2_context *ctx) } break; case VB_MENU_LANGUAGES: - switch(current_menu_idx) { + /* + * Assume that we selected a language. Go to previous + * menu. Purposely bypassing vb2_set_menu_items() here + * because need to do in different order. + */ + current_menu = prev_menu; + prev_menu = VB_MENU_LANGUAGES; + /* default to power off index */ + switch (current_menu) { + case VB_MENU_DEV_WARNING: + current_menu_idx = VB_WARN_POWER_OFF; + break; + case VB_MENU_DEV: + current_menu_idx = VB_DEV_POWER_OFF; + break; + case VB_MENU_TO_NORM: + current_menu_idx = VB_TO_NORM_POWER_OFF; + break; + case VB_MENU_RECOVERY: + current_menu_idx = VB_RECOVERY_POWER_OFF; + break; + case VB_MENU_TO_DEV: + current_menu_idx = VB_TO_DEV_POWER_OFF; + break; default: - /* - * Assume that we selected a language. Go to previous - * menu. Purposely bypassing vb2_set_menu_items() here - * because need to do in different order. - */ - current_menu = prev_menu; - prev_menu = VB_MENU_LANGUAGES; - /* default to power off index */ - switch (current_menu) { - case VB_MENU_DEV_WARNING: - current_menu_idx = VB_WARN_POWER_OFF; - break; - case VB_MENU_DEV: - current_menu_idx = VB_DEV_POWER_OFF; - break; - case VB_MENU_TO_NORM: - current_menu_idx = VB_TO_NORM_POWER_OFF; - break; - case VB_MENU_RECOVERY: - current_menu_idx = VB_RECOVERY_POWER_OFF; - break; - case VB_MENU_TO_DEV: - current_menu_idx = VB_TO_DEV_POWER_OFF; - break; - default: - current_menu_idx = 0; - break; - } - selected = current_menu_idx; + current_menu_idx = 0; break; } + selected = current_menu_idx; + break; default: - VB2_DEBUG("Current Menu Invalid!"); + VB2_DEBUG("Current Menu Invalid! 0x%x\n", current_menu_idx); } return ret; } @@ -624,6 +623,69 @@ VbError_t vb2_update_locale(struct vb2_context *ctx) { return VBERROR_SUCCESS; } +/** + * Adjust the disabled_idx_mask based on current menu and settings. + * + * @param flags flag to check for dev/normal mode. + * @return VBERROR_SUCCESS + */ +VbError_t vb2_set_disabled_idx_mask(uint32_t flags) { + /* Disable "Enable Developer Mode" menu item */ + disabled_idx_mask = 0; + if (current_menu == VB_MENU_RECOVERY && + (flags & VBSD_BOOT_DEV_SWITCH_ON)) { + disabled_idx_mask |= 1 << VB_RECOVERY_TO_DEV; + } + return VBERROR_SUCCESS; +} + +/** + * Updates current_menu_idx upon an up/down key press, taking into + * account disabled indices (from disabled_idx_mask). The cursor + * will not wrap, meaning that we block on the 0 or max index when + * we hit the ends of the menu. + * + * @param cparams common params + * @param key VOL_KEY_UP = increase index selection + * VOL_KEY_DOWN = decrease index selection. + * Every other key has no effect now. + */ +void vb2_update_selection(VbCommonParams *cparams, uint32_t key) { + int idx; + uint32_t menu_size; + + if (current_menu == VB_MENU_LANGUAGES) { + VbGetLocalizationCount(cparams, &menu_size); + } else { + vb2_get_current_menu_size(current_menu, + NULL, &menu_size); + } + + switch (key) { + case VB_KEY_UP: + idx = current_menu_idx - 1; + while (idx >= 0 && + ((1 << idx) & disabled_idx_mask)) + idx--; + /* Only update if idx is valid */ + if (idx >= 0) + current_menu_idx = idx; + break; + case VB_KEY_DOWN: + idx = current_menu_idx + 1; + while (idx < menu_size && + ((1 << idx) & disabled_idx_mask)) + idx++; + /* Only update if idx is valid */ + if (idx < menu_size) + current_menu_idx = idx; + break; + default: + /* Do not update anything */ + break; + } +} + /** * Main function that handles developer warning menu functionality * @@ -634,10 +696,8 @@ VbError_t vb2_update_locale(struct vb2_context *ctx) { VbError_t vb2_developer_menu(struct vb2_context *ctx, VbCommonParams *cparams) { GoogleBinaryBlockHeader *gbb = cparams->gbb; -#if defined(VBOOT_DEBUG) VbSharedDataHeader *shared = (VbSharedDataHeader *)cparams->shared_data_blob; -#endif uint32_t disable_dev_boot = 0; uint32_t use_usb = 0; @@ -646,7 +706,6 @@ VbError_t vb2_developer_menu(struct vb2_context *ctx, VbCommonParams *cparams) VbAudioContext *audio = 0; VbError_t ret; - VB2_DEBUG("Entering\n"); /* Check if USB booting is allowed */ @@ -712,6 +771,8 @@ VbError_t vb2_developer_menu(struct vb2_context *ctx, VbCommonParams *cparams) } } + + vb2_set_disabled_idx_mask(shared->flags); /* Show the dev mode warning screen */ vb2_draw_current_screen(ctx, cparams); @@ -721,7 +782,6 @@ VbError_t vb2_developer_menu(struct vb2_context *ctx, VbCommonParams *cparams) /* We'll loop until we finish the delay or are interrupted */ do { uint32_t key; - uint32_t menu_size; if (VbWantShutdownMenu(gbb->flags)) { VB2_DEBUG("shutdown requested!\n"); @@ -776,27 +836,14 @@ VbError_t vb2_developer_menu(struct vb2_context *ctx, VbCommonParams *cparams) break; case VB_BUTTON_VOL_UP: case VB_KEY_UP: - vb2_get_current_menu_size(current_menu, - NULL, &menu_size); - /* Do not wrap selection index */ - if (current_menu_idx > 0) - current_menu_idx--; + vb2_update_selection(cparams, key); vb2_draw_current_screen(ctx, cparams); /* reset 30 second timer */ audio = VbAudioOpen(cparams); break; case VB_BUTTON_VOL_DOWN: case VB_KEY_DOWN: - /* Do not wrap selection index */ - if (current_menu == VB_MENU_LANGUAGES) { - VbGetLocalizationCount(cparams, &menu_size); - } - else { - vb2_get_current_menu_size(current_menu, - NULL, &menu_size); - } - if (current_menu_idx < menu_size-1) - current_menu_idx++; + vb2_update_selection(cparams, key); vb2_draw_current_screen(ctx, cparams); /* reset 30 second timer */ audio = VbAudioOpen(cparams); @@ -812,6 +859,7 @@ VbError_t vb2_developer_menu(struct vb2_context *ctx, VbCommonParams *cparams) vb2_update_locale(ctx); ret = vb2_update_menu(ctx); + vb2_set_disabled_idx_mask(shared->flags); /* * Unfortunately, we need the blanking to get rid of * artifacts from previous menu printing. @@ -965,7 +1013,6 @@ VbError_t vb2_recovery_menu(struct vb2_context *ctx, VbCommonParams *cparams) uint32_t key; int i; VbError_t ret; - uint32_t menu_size; VB2_DEBUG("start\n"); @@ -1029,6 +1076,8 @@ VbError_t vb2_recovery_menu(struct vb2_context *ctx, VbCommonParams *cparams) if (VBERROR_SUCCESS == retval) break; /* Found a recovery kernel */ + vb2_set_disabled_idx_mask(shared->flags); + if (current_menu != VB_MENU_RECOVERY || current_menu_idx != VB_RECOVERY_DBG_INFO) { if (retval == VBERROR_NO_DISK_FOUND) @@ -1051,24 +1100,12 @@ VbError_t vb2_recovery_menu(struct vb2_context *ctx, VbCommonParams *cparams) break; case VB_BUTTON_VOL_UP: case VB_KEY_UP: - vb2_get_current_menu_size(current_menu, NULL, - &menu_size); - if (current_menu_idx > 0) - current_menu_idx--; + vb2_update_selection(cparams, key); vb2_draw_current_screen(ctx, cparams); break; case VB_BUTTON_VOL_DOWN: case VB_KEY_DOWN: - /* Do not wrap selection index */ - if (current_menu == VB_MENU_LANGUAGES) { - VbGetLocalizationCount(cparams, &menu_size); - } - else { - vb2_get_current_menu_size(current_menu, - NULL, &menu_size); - } - if (current_menu_idx < menu_size-1) - current_menu_idx++; + vb2_update_selection(cparams, key); vb2_draw_current_screen(ctx, cparams); break; case VB_BUTTON_POWER: @@ -1082,6 +1119,9 @@ VbError_t vb2_recovery_menu(struct vb2_context *ctx, VbCommonParams *cparams) vb2_update_locale(ctx); ret = vb2_update_menu(ctx); + + vb2_set_disabled_idx_mask(shared->flags); + if (current_menu != VB_MENU_RECOVERY || current_menu_idx != VB_RECOVERY_DBG_INFO) { /* @@ -1124,8 +1164,6 @@ VbError_t vb2_recovery_menu(struct vb2_context *ctx, VbCommonParams *cparams) * - user forced recovery mode * - EC isn't pwned */ - // TODO: let's put an error here if we're - // already in dev mode. if (current_menu == VB_MENU_TO_DEV && current_menu_idx == 0 && shared->flags & VBSD_HONOR_VIRT_DEV_SWITCH && diff --git a/firmware/stub/vboot_api_stub.c b/firmware/stub/vboot_api_stub.c index 834bff1c..c51cef4b 100644 --- a/firmware/stub/vboot_api_stub.c +++ b/firmware/stub/vboot_api_stub.c @@ -52,7 +52,8 @@ VbError_t VbExDisplayScreen(uint32_t screen_type, uint32_t locale) } VbError_t VbExDisplayMenu(uint32_t screen_type, uint32_t locale, - uint32_t selected_index, uint32_t redraw_base) + uint32_t selected_index, uint32_t disabled_idx_mask, + uint32_t redraw_base) { return VBERROR_SUCCESS; } -- cgit v1.2.1