diff options
author | Mathew King <mathewk@chromium.org> | 2019-02-11 10:27:59 -0700 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2019-02-22 18:23:43 -0800 |
commit | 9d6dc0d222418f90f5080f6c25cd06ca14abf48b (patch) | |
tree | 77c8aa1f55543be4ac6da3b96f38d111e276d3e0 | |
parent | af26dc17173d82c75821cf5385054a3b3b17165d (diff) | |
download | vboot-9d6dc0d222418f90f5080f6c25cd06ca14abf48b.tar.gz |
vboot: Add ui for setting vendor data in VPDfirmware-atlas-11827.12.B
BUG=b:124297157
TEST=make runtest
test on device
BRANCH=none
CQ-DEPEND=CL:1466822
Change-Id: Ic3b1b502b1aff14a795397da3024f8a12eb04775
Reviewed-on: https://chromium-review.googlesource.com/1466290
Commit-Ready: Mathew King <mathewk@chromium.org>
Tested-by: Mathew King <mathewk@chromium.org>
Reviewed-by: Julius Werner <jwerner@chromium.org>
Reviewed-by: Mathew King <mathewk@chromium.org>
-rw-r--r-- | Makefile | 9 | ||||
-rw-r--r-- | firmware/2lib/include/2api.h | 3 | ||||
-rw-r--r-- | firmware/include/vboot_api.h | 47 | ||||
-rw-r--r-- | firmware/lib/ec_sync_all.c | 2 | ||||
-rw-r--r-- | firmware/lib/include/sysincludes.h | 1 | ||||
-rw-r--r-- | firmware/lib/include/vboot_display.h | 3 | ||||
-rw-r--r-- | firmware/lib/vboot_api_kernel.c | 3 | ||||
-rw-r--r-- | firmware/lib/vboot_display.c | 10 | ||||
-rw-r--r-- | firmware/lib/vboot_ui.c | 207 | ||||
-rw-r--r-- | firmware/lib/vboot_ui_menu.c | 6 | ||||
-rw-r--r-- | firmware/stub/vboot_api_stub.c | 8 | ||||
-rw-r--r-- | tests/ec_sync_tests.c | 3 | ||||
-rw-r--r-- | tests/vboot_api_devmode_tests.c | 3 | ||||
-rw-r--r-- | tests/vboot_api_kernel2_tests.c | 185 | ||||
-rw-r--r-- | tests/vboot_detach_menu_tests.c | 3 |
15 files changed, 461 insertions, 32 deletions
@@ -163,6 +163,7 @@ else # FIRMWARE_ARCH not defined; assuming local compile. CC ?= gcc CFLAGS += -DCHROMEOS_ENVIRONMENT -Wall ${WERROR} ${DEBUG_FLAGS} +CHROMEOS_ENVIRONMENT = 1 endif ifneq (${DEBUG},) @@ -411,6 +412,14 @@ VBINIT_SRCS += \ firmware/lib/tpm_lite/mocked_tlcl.c endif +ifneq (${VENDOR_DATA_LENGTH},) +CFLAGS += -DVENDOR_DATA_LENGTH=${VENDOR_DATA_LENGTH} +else ifeq (${CHROMEOS_ENVIRONMENT},1) +CFLAGS += -DVENDOR_DATA_LENGTH=4 +else +CFLAGS += -DVENDOR_DATA_LENGTH=0 +endif + ifeq (${FIRMWARE_ARCH},) # Include BIOS stubs in the firmware library when compiling for host # TODO: split out other stub funcs too diff --git a/firmware/2lib/include/2api.h b/firmware/2lib/include/2api.h index 90647d5e..34eb779d 100644 --- a/firmware/2lib/include/2api.h +++ b/firmware/2lib/include/2api.h @@ -177,6 +177,9 @@ enum vb2_context_flags { * data provided by the caller could be uninitialized.) */ VB2_CONTEXT_NVDATA_V2 = (1 << 18), + + /* Allow vendor data to be set via the vendor data ui. */ + VB2_CONTEXT_VENDOR_DATA_SETTABLE = (1 << 19), }; /* diff --git a/firmware/include/vboot_api.h b/firmware/include/vboot_api.h index 0d3addff..860a5fc9 100644 --- a/firmware/include/vboot_api.h +++ b/firmware/include/vboot_api.h @@ -138,6 +138,8 @@ enum VbErrorPredefined_t { VBERROR_PERIPHERAL_BUSY = 0x10030, /* Error reading or writing Alt OS flags to TPM */ VBERROR_TPM_ALT_OS = 0x10031, + /* Error writing VPD */ + VBERROR_VPD_WRITE = 0x10032, /* VbExEcGetExpectedRWHash() may return the following codes */ /* Compute expected RW hash from the EC image; BIOS doesn't have it */ @@ -274,7 +276,7 @@ typedef struct VbSelectAndLoadKernelParams { void *kernel_buffer; /* Size of kernel buffer in bytes */ uint32_t kernel_buffer_size; - /* input flags. Currently used for detachables */ + /* input flags. */ uint32_t inflags; /* @@ -306,6 +308,11 @@ typedef struct VbSelectAndLoadKernelParams { */ #define VB_SALK_INFLAGS_ENABLE_DETACHABLE_UI (1 << 0) +/* Flag to indicate that the vendor data is not set and the vendor data + * UI should be enabled. + */ +#define VB_SALK_INFLAGS_VENDOR_DATA_SETTABLE (1 << 1) + /** * Select and loads the kernel. * @@ -671,9 +678,32 @@ enum VbScreenType_t { VB_SCREEN_ALT_FW_PICK = 0x212, /* Alt firmware menu screen (for detachable UI ) */ VB_SCREEN_ALT_FW_MENU = 0x213, + /* Set vendor data menu screen */ + VB_SCREEN_SET_VENDOR_DATA = 0x214, + /* Confirm vendor data menu screen */ + VB_SCREEN_CONFIRM_VENDOR_DATA = 0x215, }; /** + * Extra data needed when displaying vendor data screens + */ +typedef struct VbVendorData +{ + /* Current state of the the vendor data input */ + const char *input_text; +} VbVendorData; + +/** + * Extra data that may be used when displaying a screen + */ +typedef struct VbScreenData +{ + union { + VbVendorData vendor_data; + }; +} VbScreenData; + +/** * Display a predefined screen; see VB_SCREEN_* for valid screens. * * This is a backup method of screen display, intended for use if the GBB does @@ -681,7 +711,8 @@ enum VbScreenType_t { * to be simple ASCII text such as "NO GOOD" or "INSERT"; these screens should * only be seen during development. */ -VbError_t VbExDisplayScreen(uint32_t screen_type, uint32_t locale); +VbError_t VbExDisplayScreen(uint32_t screen_type, uint32_t locale, + const VbScreenData *data); /** * Display a predefined menu screen; see VB_SCREEN_* for valid screens. @@ -714,6 +745,17 @@ VbError_t VbExDisplayMenu(uint32_t screen_type, uint32_t locale, */ VbError_t VbExDisplayDebugInfo(const char *info_str); +/** + * Write vendor data to read-only VPD + * + * @param vendor_data_value The value of vendor data to write to VPD. The + * string length will be exactly VENDOR_DATA_LENGTH + * characters and null-terminated. + * + * @return VBERROR_SUCCESS or error code on error. + */ +VbError_t VbExSetVendorData(const char *vendor_data_value); + /*****************************************************************************/ /* Keyboard and switches */ @@ -724,6 +766,7 @@ VbError_t VbExDisplayDebugInfo(const char *info_str); enum VbKeyCode_t { VB_KEY_ENTER = '\r', VB_KEY_ESC = 0x1b, + VB_KEY_BACKSPACE = 0x8, VB_KEY_UP = 0x100, VB_KEY_DOWN = 0x101, VB_KEY_LEFT = 0x102, diff --git a/firmware/lib/ec_sync_all.c b/firmware/lib/ec_sync_all.c index 36d9e727..6c3fe74f 100644 --- a/firmware/lib/ec_sync_all.c +++ b/firmware/lib/ec_sync_all.c @@ -79,7 +79,7 @@ VbError_t ec_sync_all(struct vb2_context *ctx) /* Display the wait screen if we need it */ if (need_wait_screen) { VB2_DEBUG("EC is slow. Show WAIT screen.\n"); - VbDisplayScreen(ctx, VB_SCREEN_WAIT, 0); + VbDisplayScreen(ctx, VB_SCREEN_WAIT, 0, NULL); } /* Phase 2; Applies update and/or jumps to the correct EC image */ diff --git a/firmware/lib/include/sysincludes.h b/firmware/lib/include/sysincludes.h index 7a9139c0..28aa96c5 100644 --- a/firmware/lib/include/sysincludes.h +++ b/firmware/lib/include/sysincludes.h @@ -15,6 +15,7 @@ #ifndef VBOOT_REFERENCE_SYSINCLUDES_H_ #define VBOOT_REFERENCE_SYSINCLUDES_H_ +#include <ctype.h> #include <inttypes.h> /* For PRIu64 */ #include <stddef.h> #include <stdint.h> diff --git a/firmware/lib/include/vboot_display.h b/firmware/lib/include/vboot_display.h index 20066dfa..4c8df0e6 100644 --- a/firmware/lib/include/vboot_display.h +++ b/firmware/lib/include/vboot_display.h @@ -10,7 +10,8 @@ struct vb2_context; -VbError_t VbDisplayScreen(struct vb2_context *ctx, uint32_t screen, int force); +VbError_t VbDisplayScreen(struct vb2_context *ctx, uint32_t screen, int force, + const VbScreenData *data); VbError_t VbDisplayMenu(struct vb2_context *ctx, uint32_t screen, int force, uint32_t selected_index, uint32_t disabled_idx_mask); diff --git a/firmware/lib/vboot_api_kernel.c b/firmware/lib/vboot_api_kernel.c index 516b1e44..17b3b7b2 100644 --- a/firmware/lib/vboot_api_kernel.c +++ b/firmware/lib/vboot_api_kernel.c @@ -432,6 +432,9 @@ VbError_t VbSelectAndLoadKernel(VbCommonParams *cparams, retval = VbBootRecovery(&ctx); VbExEcEnteringMode(0, VB_EC_RECOVERY); } else if (ctx.flags & VB2_CONTEXT_DEVELOPER_MODE) { + if (kparams->inflags & VB_SALK_INFLAGS_VENDOR_DATA_SETTABLE) + ctx.flags |= VB2_CONTEXT_VENDOR_DATA_SETTABLE; + /* Developer boot. This has UI. */ if (kparams->inflags & VB_SALK_INFLAGS_ENABLE_DETACHABLE_UI) retval = VbBootDeveloperMenu(&ctx); diff --git a/firmware/lib/vboot_display.c b/firmware/lib/vboot_display.c index c7607726..a17d6dd1 100644 --- a/firmware/lib/vboot_display.c +++ b/firmware/lib/vboot_display.c @@ -35,7 +35,8 @@ VbError_t VbExGetAltFwIdxMask(void) { return 0; } -VbError_t VbDisplayScreen(struct vb2_context *ctx, uint32_t screen, int force) +VbError_t VbDisplayScreen(struct vb2_context *ctx, uint32_t screen, int force, + const VbScreenData *data) { uint32_t locale; VbError_t rv; @@ -47,7 +48,7 @@ VbError_t VbDisplayScreen(struct vb2_context *ctx, uint32_t screen, int force) /* Read the locale last saved */ locale = vb2_nv_get(ctx, VB2_NV_LOCALIZATION_INDEX); - rv = VbExDisplayScreen(screen, locale); + rv = VbExDisplayScreen(screen, locale, data); if (rv == VBERROR_SUCCESS) /* Keep track of the currently displayed screen */ @@ -464,12 +465,13 @@ VbError_t VbCheckDisplayKey(struct vb2_context *ctx, uint32_t key) #endif /* Force redraw of current screen */ - return VbDisplayScreen(ctx, disp_current_screen, 1); + return VbDisplayScreen(ctx, disp_current_screen, 1, NULL); } if (0 == memcmp(MagicBuffer, MAGIC_WORD, MAGIC_WORD_LEN)) { if (VBEASTEREGG) - (void)VbDisplayScreen(ctx, disp_current_screen, 1); + (void)VbDisplayScreen(ctx, disp_current_screen, 1, + NULL); } return VBERROR_SUCCESS; diff --git a/firmware/lib/vboot_ui.c b/firmware/lib/vboot_ui.c index 57e546a2..dea6e039 100644 --- a/firmware/lib/vboot_ui.c +++ b/firmware/lib/vboot_ui.c @@ -176,7 +176,7 @@ VbError_t vb2_altfw_ui(struct vb2_context *ctx) { int active = 1; - VbDisplayScreen(ctx, VB_SCREEN_ALT_FW_PICK, 0); + VbDisplayScreen(ctx, VB_SCREEN_ALT_FW_PICK, 0, NULL); /* We'll loop until the user decides what to do */ do { @@ -217,11 +217,152 @@ VbError_t vb2_altfw_ui(struct vb2_context *ctx) } while (active); /* Back to developer screen */ - VbDisplayScreen(ctx, VB_SCREEN_DEVELOPER_WARNING, 0); + VbDisplayScreen(ctx, VB_SCREEN_DEVELOPER_WARNING, 0, NULL); return 0; } +/* + * Prompt the user to enter the vendor data + */ +VbError_t vb2_enter_vendor_data_ui(struct vb2_context *ctx, char *data_value) +{ + int len = 0; + VbScreenData data = { + .vendor_data = { data_value } + }; + + data_value[0] = '\0'; + VbDisplayScreen(ctx, VB_SCREEN_SET_VENDOR_DATA, 1, &data); + + /* We'll loop until the user decides what to do */ + do { + uint32_t key = VbExKeyboardRead(); + + if (VbWantShutdown(ctx, key)) { + VB2_DEBUG("Vendor Data UI - shutdown requested!\n"); + return VBERROR_SHUTDOWN_REQUESTED; + } + switch (key) { + case 0: + /* nothing pressed */ + break; + case VB_KEY_ESC: + /* Escape pressed - return to developer screen */ + VB2_DEBUG("Vendor Data UI - user pressed Esc: " + "exit to Developer screen\n"); + data_value[0] = '\0'; + return VBERROR_SUCCESS; + case 'a'...'z': + key = toupper(key); + case '0'...'9': + case 'A'...'Z': + if (len < VENDOR_DATA_LENGTH) { + data_value[len++] = key; + data_value[len] = '\0'; + VbDisplayScreen(ctx, VB_SCREEN_SET_VENDOR_DATA, + 1, &data); + } else { + vb2_error_beep(VB_BEEP_NOT_ALLOWED); + } + + VB2_DEBUG("Vendor Data UI - vendor_data: %s\n", + data_value); + break; + case VB_KEY_BACKSPACE: + if (len > 0) { + data_value[--len] = '\0'; + VbDisplayScreen(ctx, VB_SCREEN_SET_VENDOR_DATA, + 1, &data); + } + + VB2_DEBUG("Vendor Data UI - vendor_data: %s\n", + data_value); + break; + case VB_KEY_ENTER: + if (len == VENDOR_DATA_LENGTH) { + /* Enter pressed - confirm input */ + VB2_DEBUG("Vendor Data UI - user pressed " + "Enter: confirm vendor data\n"); + return VBERROR_SUCCESS; + } else { + vb2_error_beep(VB_BEEP_NOT_ALLOWED); + } + break; + default: + VB2_DEBUG("Vendor Data UI - pressed key %d\n", key); + break; + } + VbExSleepMs(DEV_KEY_DELAY); + } while (1); + + return VBERROR_SUCCESS; +} + +/* + * User interface for setting the vendor data in VPD + */ +VbError_t vb2_vendor_data_ui(struct vb2_context *ctx) +{ + char data_value[VENDOR_DATA_LENGTH + 1]; + VbScreenData data = { + .vendor_data = { data_value } + }; + + VbError_t ret = vb2_enter_vendor_data_ui(ctx, data_value); + + if (ret) + return ret; + + /* Vendor data was not entered just return */ + if (data_value[0] == '\0') + return VBERROR_SUCCESS; + + VbDisplayScreen(ctx, VB_SCREEN_CONFIRM_VENDOR_DATA, 1, &data); + /* We'll loop until the user decides what to do */ + do { + uint32_t key = VbExKeyboardRead(); + + if (VbWantShutdown(ctx, key)) { + VB2_DEBUG("Vendor Data UI - shutdown requested!\n"); + return VBERROR_SHUTDOWN_REQUESTED; + } + switch (key) { + case 0: + /* nothing pressed */ + break; + case VB_KEY_ESC: + /* Escape pressed - return to developer screen */ + VB2_DEBUG("Vendor Data UI - user pressed Esc: " + "exit to Developer screen\n"); + return VBERROR_SUCCESS; + case VB_KEY_ENTER: + /* Enter pressed - write vendor data */ + VB2_DEBUG("Vendor Data UI - user pressed Enter: " + "write vendor data (%s) to VPD\n", + data_value); + ret = VbExSetVendorData(data_value); + + if (ret == VBERROR_SUCCESS) { + vb2_nv_set(ctx, VB2_NV_DISABLE_DEV_REQUEST, 1); + return VBERROR_REBOOT_REQUIRED; + } else { + /* + * TODO(mathewk): If setting vendor data fails + * we should give helpful feedback to the user + */ + return ret; + } + default: + VB2_DEBUG("Vendor Data UI - pressed key %d\n", key); + break; + } + VbExSleepMs(DEV_KEY_DELAY); + } while (1); + + return VBERROR_SUCCESS; +} + static const char dev_disable_msg[] = "Developer mode is disabled on this device by system policy.\n" "For more information, see http://dev.chromium.org/chromium-os/fwmp\n" @@ -279,7 +420,8 @@ VbError_t vb2_developer_ui(struct vb2_context *ctx) /* If dev mode is disabled, only allow TONORM */ while (disable_dev_boot) { VB2_DEBUG("dev_disable_boot is set\n"); - VbDisplayScreen(ctx, VB_SCREEN_DEVELOPER_TO_NORM, 0); + VbDisplayScreen(ctx, + VB_SCREEN_DEVELOPER_TO_NORM, 0, NULL); VbExDisplayDebugInfo(dev_disable_msg); /* Ignore space in VbUserConfirms()... */ @@ -287,7 +429,8 @@ VbError_t vb2_developer_ui(struct vb2_context *ctx) case 1: VB2_DEBUG("leaving dev-mode\n"); vb2_nv_set(ctx, VB2_NV_DISABLE_DEV_REQUEST, 1); - VbDisplayScreen(ctx, VB_SCREEN_TO_NORM_CONFIRMED, 0); + VbDisplayScreen(ctx, + VB_SCREEN_TO_NORM_CONFIRMED, 0, NULL); VbExSleepMs(5000); return VBERROR_REBOOT_REQUIRED; case -1: @@ -300,7 +443,7 @@ VbError_t vb2_developer_ui(struct vb2_context *ctx) } /* Show the dev mode warning screen */ - VbDisplayScreen(ctx, VB_SCREEN_DEVELOPER_WARNING, 0); + VbDisplayScreen(ctx, VB_SCREEN_DEVELOPER_WARNING, 0, NULL); /* Initialize audio/delay context */ vb2_audio_start(ctx); @@ -342,7 +485,8 @@ VbError_t vb2_developer_ui(struct vb2_context *ctx) break; } VbDisplayScreen(ctx, - VB_SCREEN_DEVELOPER_TO_NORM, 0); + VB_SCREEN_DEVELOPER_TO_NORM, + 0, NULL); /* Ignore space in VbUserConfirms()... */ switch (VbUserConfirms(ctx, 0)) { case 1: @@ -350,7 +494,8 @@ VbError_t vb2_developer_ui(struct vb2_context *ctx) vb2_nv_set(ctx, VB2_NV_DISABLE_DEV_REQUEST, 1); VbDisplayScreen(ctx, - VB_SCREEN_TO_NORM_CONFIRMED, 0); + VB_SCREEN_TO_NORM_CONFIRMED, + 0, NULL); VbExSleepMs(5000); return VBERROR_REBOOT_REQUIRED; case -1: @@ -360,7 +505,8 @@ VbError_t vb2_developer_ui(struct vb2_context *ctx) /* Stay in dev-mode */ VB2_DEBUG("stay in dev-mode\n"); VbDisplayScreen(ctx, - VB_SCREEN_DEVELOPER_WARNING, 0); + VB_SCREEN_DEVELOPER_WARNING, + 0, NULL); /* Start new countdown */ vb2_audio_start(ctx); } @@ -395,6 +541,35 @@ VbError_t vb2_developer_ui(struct vb2_context *ctx) vb2_error_no_altfw(); } break; + case VB_KEY_CTRL('S'): + if (VENDOR_DATA_LENGTH == 0) + break; + /* + * Only show the vendor data ui if it is tag is settable + */ + if (ctx->flags & VB2_CONTEXT_VENDOR_DATA_SETTABLE) { + int ret; + + VB2_DEBUG("VbBootDeveloper() - user pressed " + "Ctrl+S; Try set vendor data\n"); + + ret = vb2_vendor_data_ui(ctx); + if (ret) { + return ret; + } else { + /* Show dev mode warning screen again */ + VbDisplayScreen(ctx, + VB_SCREEN_DEVELOPER_WARNING, + 0, NULL); + } + } else { + vb2_error_notify( + "WARNING: Vendor data cannot be " + "changed because it is already set.\n", + NULL, + VB_BEEP_NOT_ALLOWED); + } + break; case VB_KEY_CTRL_ENTER: /* * The Ctrl-Enter is special for Lumpy test purpose; @@ -418,13 +593,14 @@ VbError_t vb2_developer_ui(struct vb2_context *ctx) * Clear the screen to show we get the Ctrl+U * key press. */ - VbDisplayScreen(ctx, VB_SCREEN_BLANK, 0); + VbDisplayScreen(ctx, VB_SCREEN_BLANK, 0, NULL); if (VBERROR_SUCCESS == VbTryUsb(ctx)) { return VBERROR_SUCCESS; } else { /* Show dev mode warning screen again */ VbDisplayScreen(ctx, - VB_SCREEN_DEVELOPER_WARNING, 0); + VB_SCREEN_DEVELOPER_WARNING, + 0, NULL); } } break; @@ -467,7 +643,7 @@ VbError_t VbBootDeveloper(struct vb2_context *ctx) { vb2_init_ui(); VbError_t retval = vb2_developer_ui(ctx); - VbDisplayScreen(ctx, VB_SCREEN_BLANK, 0); + VbDisplayScreen(ctx, VB_SCREEN_BLANK, 0, NULL); return retval; } @@ -509,7 +685,7 @@ static VbError_t recovery_ui(struct vb2_context *ctx) */ vb2_nv_commit(ctx); - VbDisplayScreen(ctx, VB_SCREEN_OS_BROKEN, 0); + VbDisplayScreen(ctx, VB_SCREEN_OS_BROKEN, 0, NULL); VB2_DEBUG("VbBootRecovery() waiting for manual recovery\n"); while (1) { key = VbExKeyboardRead(); @@ -541,7 +717,7 @@ static VbError_t recovery_ui(struct vb2_context *ctx) VbDisplayScreen(ctx, VBERROR_NO_DISK_FOUND == retval ? VB_SCREEN_RECOVERY_INSERT : VB_SCREEN_RECOVERY_NO_GOOD, - 0); + 0, NULL); /* * Scan keyboard more frequently than media, since x86 @@ -578,7 +754,8 @@ static VbError_t recovery_ui(struct vb2_context *ctx) /* Ask the user to confirm entering dev-mode */ VbDisplayScreen(ctx, - VB_SCREEN_RECOVERY_TO_DEV, 0); + VB_SCREEN_RECOVERY_TO_DEV, + 0, NULL); /* SPACE means no... */ uint32_t vbc_flags = VB_CONFIRM_SPACE_MEANS_NO | @@ -622,6 +799,6 @@ VbError_t VbBootRecovery(struct vb2_context *ctx) { vb2_init_ui(); VbError_t retval = recovery_ui(ctx); - VbDisplayScreen(ctx, VB_SCREEN_BLANK, 0); + VbDisplayScreen(ctx, VB_SCREEN_BLANK, 0, NULL); return retval; } diff --git a/firmware/lib/vboot_ui_menu.c b/firmware/lib/vboot_ui_menu.c index e269d237..380dd3ed 100644 --- a/firmware/lib/vboot_ui_menu.c +++ b/firmware/lib/vboot_ui_menu.c @@ -71,7 +71,7 @@ static VbError_t vb2_draw_current_screen(struct vb2_context *ctx) { /* Flash the screen to black to catch user awareness, then redraw menu. */ static void vb2_flash_screen(struct vb2_context *ctx) { - VbDisplayScreen(ctx, VB_SCREEN_BLANK, 0); + VbDisplayScreen(ctx, VB_SCREEN_BLANK, 0, NULL); VbExSleepMs(50); vb2_draw_current_screen(ctx); } @@ -808,7 +808,7 @@ VbError_t VbBootDeveloperMenu(struct vb2_context *ctx) if (VBERROR_SUCCESS != retval) return retval; retval = vb2_developer_menu(ctx); - VbDisplayScreen(ctx, VB_SCREEN_BLANK, 0); + VbDisplayScreen(ctx, VB_SCREEN_BLANK, 0, NULL); return retval; } @@ -913,6 +913,6 @@ VbError_t VbBootRecoveryMenu(struct vb2_context *ctx) retval = recovery_ui(ctx); else retval = broken_ui(ctx); - VbDisplayScreen(ctx, VB_SCREEN_BLANK, 0); + VbDisplayScreen(ctx, VB_SCREEN_BLANK, 0, NULL); return retval; } diff --git a/firmware/stub/vboot_api_stub.c b/firmware/stub/vboot_api_stub.c index effa237d..599b80c7 100644 --- a/firmware/stub/vboot_api_stub.c +++ b/firmware/stub/vboot_api_stub.c @@ -26,7 +26,8 @@ VbError_t VbExBeep(uint32_t msec, uint32_t frequency) return VBERROR_SUCCESS; } -VbError_t VbExDisplayScreen(uint32_t screen_type, uint32_t locale) +VbError_t VbExDisplayScreen(uint32_t screen_type, uint32_t locale, + const VbScreenData *data) { return VBERROR_SUCCESS; } @@ -173,3 +174,8 @@ uint8_t VbExOverrideGptEntryPriority(const GptEntry *e) { return 0; } + +VbError_t VbExSetVendorData(const char *vendor_data_value) +{ + return 0; +} diff --git a/tests/ec_sync_tests.c b/tests/ec_sync_tests.c index 4b01b64a..a971b961 100644 --- a/tests/ec_sync_tests.c +++ b/tests/ec_sync_tests.c @@ -202,7 +202,8 @@ VbError_t VbExEcUpdateImage(int devidx, enum VbSelectFirmware_t select, return update_retval; } -VbError_t VbDisplayScreen(struct vb2_context *ctx, uint32_t screen, int force) +VbError_t VbDisplayScreen(struct vb2_context *ctx, uint32_t screen, int force, + const VbScreenData *data) { if (screens_count < ARRAY_SIZE(screens_displayed)) screens_displayed[screens_count++] = screen; diff --git a/tests/vboot_api_devmode_tests.c b/tests/vboot_api_devmode_tests.c index 31428a4b..8aaa4b10 100644 --- a/tests/vboot_api_devmode_tests.c +++ b/tests/vboot_api_devmode_tests.c @@ -235,7 +235,8 @@ VbError_t VbExBeep(uint32_t msec, uint32_t frequency) return beep_return; } -VbError_t VbExDisplayScreen(uint32_t screen_type, uint32_t locale) +VbError_t VbExDisplayScreen(uint32_t screen_type, uint32_t locale, + const VbScreenData *data) { switch(screen_type) { case VB_SCREEN_BLANK: diff --git a/tests/vboot_api_kernel2_tests.c b/tests/vboot_api_kernel2_tests.c index 9b887597..9224725f 100644 --- a/tests/vboot_api_kernel2_tests.c +++ b/tests/vboot_api_kernel2_tests.c @@ -41,7 +41,7 @@ static int altfw_num; static int trust_ec; static int virtdev_set; static uint32_t virtdev_retval; -static uint32_t mock_keypress[8]; +static uint32_t mock_keypress[16]; static uint32_t mock_keyflags[8]; static uint32_t mock_keypress_count; static uint32_t mock_switches[8]; @@ -52,6 +52,9 @@ static uint32_t screens_count = 0; static uint32_t mock_num_disks[8]; static uint32_t mock_num_disks_count; +static char set_vendor_data[32]; +static int set_vendor_data_called; + extern enum VbEcBootMode_t VbGetMode(void); extern struct RollbackSpaceFwmp *VbApiKernelGetFwmp(void); @@ -83,6 +86,7 @@ static void ResetMocks(void) trust_ec = 0; virtdev_set = 0; virtdev_retval = 0; + set_vendor_data_called = 0; memset(screens_displayed, 0, sizeof(screens_displayed)); screens_count = 0; @@ -193,7 +197,8 @@ uint32_t VbTryLoadKernel(struct vb2_context *ctx, uint32_t get_info_flags) return vbtlk_retval + get_info_flags; } -VbError_t VbDisplayScreen(struct vb2_context *ctx, uint32_t screen, int force) +VbError_t VbDisplayScreen(struct vb2_context *ctx, uint32_t screen, int force, + const VbScreenData *data) { if (screens_count < ARRAY_SIZE(screens_displayed)) screens_displayed[screens_count++] = screen; @@ -207,6 +212,14 @@ uint32_t SetVirtualDevMode(int val) return virtdev_retval; } +VbError_t VbExSetVendorData(const char *vendor_data_value) +{ + set_vendor_data_called = 1; + strncpy(set_vendor_data, vendor_data_value, sizeof(set_vendor_data)); + + return VBERROR_SUCCESS; +} + /* Tests */ static void VbUserConfirmsTest(void) @@ -590,6 +603,174 @@ static void VbBootDevTest(void) vbtlk_retval = VBERROR_SUCCESS - VB_DISK_FLAG_REMOVABLE; TEST_EQ(VbBootDeveloper(&ctx), 0, "Ctrl+U force USB"); + /* Ctrl+S set vendor data and reboot */ + ResetMocks(); + ctx.flags |= VB2_CONTEXT_VENDOR_DATA_SETTABLE; + mock_keypress[0] = VB_KEY_CTRL('S'); + mock_keypress[1] = '4'; + mock_keypress[2] = '3'; + mock_keypress[3] = '2'; + mock_keypress[4] = '1'; + mock_keypress[5] = VB_KEY_ENTER; // Set vendor data + mock_keypress[6] = VB_KEY_ENTER; // Confirm vendor data + TEST_EQ(VbBootDeveloper(&ctx), VBERROR_REBOOT_REQUIRED, + "Ctrl+S set vendor data and reboot"); + TEST_EQ(set_vendor_data_called, 1, " VbExSetVendorData() called"); + TEST_STR_EQ(set_vendor_data, "4321", " Vendor data correct"); + + /* Ctrl+S extra keys ignored */ + ResetMocks(); + ctx.flags |= VB2_CONTEXT_VENDOR_DATA_SETTABLE; + mock_keypress[0] = VB_KEY_CTRL('S'); + mock_keypress[1] = '4'; + mock_keypress[2] = '3'; + mock_keypress[3] = '2'; + mock_keypress[4] = '1'; + mock_keypress[5] = '5'; + mock_keypress[6] = VB_KEY_ENTER; // Set vendor data + mock_keypress[7] = VB_KEY_ENTER; // Confirm vendor data + TEST_EQ(VbBootDeveloper(&ctx), VBERROR_REBOOT_REQUIRED, + "Ctrl+S extra keys ignored"); + TEST_EQ(set_vendor_data_called, 1, " VbExSetVendorData() called"); + TEST_STR_EQ(set_vendor_data, "4321", " Vendor data correct"); + + /* Ctrl+S converts case */ + ResetMocks(); + ctx.flags |= VB2_CONTEXT_VENDOR_DATA_SETTABLE; + mock_keypress[0] = VB_KEY_CTRL('S'); + mock_keypress[1] = 'a'; + mock_keypress[2] = 'B'; + mock_keypress[3] = 'Y'; + mock_keypress[4] = 'z'; + mock_keypress[5] = VB_KEY_ENTER; // Set vendor data + mock_keypress[6] = VB_KEY_ENTER; // Confirm vendor data + TEST_EQ(VbBootDeveloper(&ctx), VBERROR_REBOOT_REQUIRED, + "Ctrl+S converts case"); + TEST_EQ(set_vendor_data_called, 1, " VbExSetVendorData() called"); + TEST_STR_EQ(set_vendor_data, "ABYZ", " Vendor data correct"); + + /* Ctrl+S backspace works */ + ResetMocks(); + ctx.flags |= VB2_CONTEXT_VENDOR_DATA_SETTABLE; + mock_keypress[0] = VB_KEY_CTRL('S'); + mock_keypress[1] = 'A'; + mock_keypress[2] = 'B'; + mock_keypress[3] = 'C'; + mock_keypress[4] = VB_KEY_BACKSPACE; + mock_keypress[5] = VB_KEY_BACKSPACE; + mock_keypress[6] = '3'; + mock_keypress[7] = '2'; + mock_keypress[8] = '1'; + mock_keypress[9] = VB_KEY_ENTER; // Set vendor data + mock_keypress[10] = VB_KEY_ENTER; // Confirm vendor data + TEST_EQ(VbBootDeveloper(&ctx), VBERROR_REBOOT_REQUIRED, + "Ctrl+S backspace works"); + TEST_EQ(set_vendor_data_called, 1, " VbExSetVendorData() called"); + TEST_STR_EQ(set_vendor_data, "A321", " Vendor data correct"); + + /* Ctrl+S invalid chars don't print */ + ResetMocks(); + ctx.flags |= VB2_CONTEXT_VENDOR_DATA_SETTABLE; + mock_keypress[0] = VB_KEY_CTRL('S'); + mock_keypress[1] = '4'; + mock_keypress[2] = '-'; + mock_keypress[3] = '^'; + mock_keypress[4] = '&'; + mock_keypress[5] = '$'; + mock_keypress[6] = '.'; + mock_keypress[7] = '3'; + mock_keypress[8] = '2'; + mock_keypress[9] = '1'; + mock_keypress[10] = VB_KEY_ENTER; // Set vendor data + mock_keypress[11] = VB_KEY_ENTER; // Confirm vendor data + TEST_EQ(VbBootDeveloper(&ctx), VBERROR_REBOOT_REQUIRED, + "Ctrl+S invalid chars don't print"); + TEST_EQ(set_vendor_data_called, 1, " VbExSetVendorData() called"); + TEST_STR_EQ(set_vendor_data, "4321", " Vendor data correct"); + + /* Ctrl+S invalid chars don't print with backspace */ + ResetMocks(); + ctx.flags |= VB2_CONTEXT_VENDOR_DATA_SETTABLE; + mock_keypress[0] = VB_KEY_CTRL('S'); + mock_keypress[1] = '4'; + mock_keypress[2] = '-'; + mock_keypress[3] = VB_KEY_BACKSPACE; // Should delete 4 + mock_keypress[4] = '3'; + mock_keypress[5] = '2'; + mock_keypress[6] = '1'; + mock_keypress[7] = '0'; + mock_keypress[8] = VB_KEY_ENTER; // Set vendor data + mock_keypress[9] = VB_KEY_ENTER; // Confirm vendor data + TEST_EQ(VbBootDeveloper(&ctx), VBERROR_REBOOT_REQUIRED, + "Ctrl+S invalid chars don't print with backspace"); + TEST_EQ(set_vendor_data_called, 1, " VbExSetVendorData() called"); + TEST_STR_EQ(set_vendor_data, "3210", " Vendor data correct"); + + /* Ctrl+S backspace only doesn't underrun */ + ResetMocks(); + ctx.flags |= VB2_CONTEXT_VENDOR_DATA_SETTABLE; + mock_keypress[0] = VB_KEY_CTRL('S'); + mock_keypress[1] = 'A'; + mock_keypress[2] = VB_KEY_BACKSPACE; + mock_keypress[3] = VB_KEY_BACKSPACE; + mock_keypress[4] = '4'; + mock_keypress[5] = '3'; + mock_keypress[6] = '2'; + mock_keypress[7] = '1'; + mock_keypress[8] = VB_KEY_ENTER; // Set vendor data + mock_keypress[9] = VB_KEY_ENTER; // Confirm vendor data + TEST_EQ(VbBootDeveloper(&ctx), VBERROR_REBOOT_REQUIRED, + "Ctrl+S backspace only doesn't underrun"); + TEST_EQ(set_vendor_data_called, 1, " VbExSetVendorData() called"); + TEST_STR_EQ(set_vendor_data, "4321", " Vendor data correct"); + + /* Ctrl+S too short */ + ResetMocks(); + ctx.flags |= VB2_CONTEXT_VENDOR_DATA_SETTABLE; + mock_keypress[0] = VB_KEY_CTRL('S'); + mock_keypress[1] = '1'; + mock_keypress[2] = '2'; + mock_keypress[3] = '3'; + mock_keypress[4] = VB_KEY_ENTER; // Set vendor data (Nothing happens) + mock_keypress[5] = VB_KEY_ENTER; // Confirm vendor data (Nothing happens) + mock_keypress[6] = VB_KEY_ESC; + TEST_EQ(VbBootDeveloper(&ctx), 1002, "Ctrl+S too short"); + TEST_EQ(set_vendor_data_called, 0, " VbExSetVendorData() not called"); + + /* Ctrl+S esc from set screen */ + ResetMocks(); + ctx.flags |= VB2_CONTEXT_VENDOR_DATA_SETTABLE; + mock_keypress[0] = VB_KEY_CTRL('S'); + mock_keypress[1] = VB_KEY_ESC; + TEST_EQ(VbBootDeveloper(&ctx), 1002, "Ctrl+S esc from set screen"); + TEST_EQ(set_vendor_data_called, 0, " VbExSetVendorData() not called"); + + /* Ctrl+S esc from set screen with tag */ + ResetMocks(); + ctx.flags |= VB2_CONTEXT_VENDOR_DATA_SETTABLE; + mock_keypress[0] = VB_KEY_CTRL('S'); + mock_keypress[1] = '4'; + mock_keypress[2] = '3'; + mock_keypress[3] = '2'; + mock_keypress[4] = '1'; + mock_keypress[5] = VB_KEY_ESC; + TEST_EQ(VbBootDeveloper(&ctx), 1002, + "Ctrl+S esc from set screen with tag"); + TEST_EQ(set_vendor_data_called, 0, " VbExSetVendorData() not called"); + + /* Ctrl+S esc from confirm screen */ + ResetMocks(); + ctx.flags |= VB2_CONTEXT_VENDOR_DATA_SETTABLE; + mock_keypress[0] = VB_KEY_CTRL('S'); + mock_keypress[1] = '4'; + mock_keypress[2] = '3'; + mock_keypress[3] = '2'; + mock_keypress[4] = '1'; + mock_keypress[5] = VB_KEY_ENTER; // Set vendor data + mock_keypress[6] = VB_KEY_ESC; + TEST_EQ(VbBootDeveloper(&ctx), 1002, "Ctrl+S esc from set screen"); + TEST_EQ(set_vendor_data_called, 0, " VbExSetVendorData() not called"); + /* If no USB, eventually times out and tries fixed disk */ ResetMocks(); vb2_nv_set(&ctx, VB2_NV_DEV_BOOT_USB, 1); diff --git a/tests/vboot_detach_menu_tests.c b/tests/vboot_detach_menu_tests.c index 68a8a2c2..4db4f3a4 100644 --- a/tests/vboot_detach_menu_tests.c +++ b/tests/vboot_detach_menu_tests.c @@ -205,7 +205,8 @@ VbError_t VbTryLoadKernel(struct vb2_context *ctx, uint32_t get_info_flags) return vbtlk_last_retval + get_info_flags; } -VbError_t VbDisplayScreen(struct vb2_context *ctx, uint32_t screen, int force) +VbError_t VbDisplayScreen(struct vb2_context *ctx, uint32_t screen, int force, + const VbScreenData *data) { if (screens_count < ARRAY_SIZE(screens_displayed)) screens_displayed[screens_count++] = screen; |