summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMathew King <mathewk@chromium.org>2019-02-11 10:27:59 -0700
committerchrome-bot <chrome-bot@chromium.org>2019-02-22 18:23:43 -0800
commit9d6dc0d222418f90f5080f6c25cd06ca14abf48b (patch)
tree77c8aa1f55543be4ac6da3b96f38d111e276d3e0
parentaf26dc17173d82c75821cf5385054a3b3b17165d (diff)
downloadvboot-firmware-atlas-11827.12.B.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--Makefile9
-rw-r--r--firmware/2lib/include/2api.h3
-rw-r--r--firmware/include/vboot_api.h47
-rw-r--r--firmware/lib/ec_sync_all.c2
-rw-r--r--firmware/lib/include/sysincludes.h1
-rw-r--r--firmware/lib/include/vboot_display.h3
-rw-r--r--firmware/lib/vboot_api_kernel.c3
-rw-r--r--firmware/lib/vboot_display.c10
-rw-r--r--firmware/lib/vboot_ui.c207
-rw-r--r--firmware/lib/vboot_ui_menu.c6
-rw-r--r--firmware/stub/vboot_api_stub.c8
-rw-r--r--tests/ec_sync_tests.c3
-rw-r--r--tests/vboot_api_devmode_tests.c3
-rw-r--r--tests/vboot_api_kernel2_tests.c185
-rw-r--r--tests/vboot_detach_menu_tests.c3
15 files changed, 461 insertions, 32 deletions
diff --git a/Makefile b/Makefile
index 4fa4423f..5b6ea76f 100644
--- a/Makefile
+++ b/Makefile
@@ -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;