diff options
Diffstat (limited to 'firmware')
-rw-r--r-- | firmware/2lib/2ui.c | 67 | ||||
-rw-r--r-- | firmware/2lib/2ui_screens.c | 100 | ||||
-rw-r--r-- | firmware/2lib/include/2api.h | 2 | ||||
-rw-r--r-- | firmware/2lib/include/2ui.h | 13 | ||||
-rw-r--r-- | firmware/2lib/include/2ui_private.h | 5 |
5 files changed, 167 insertions, 20 deletions
diff --git a/firmware/2lib/2ui.c b/firmware/2lib/2ui.c index 3c54ecca..6f90135b 100644 --- a/firmware/2lib/2ui.c +++ b/firmware/2lib/2ui.c @@ -132,29 +132,42 @@ vb2_error_t menu_select_action(struct vb2_ui_context *ui) menu_item = &ui->state.screen->items[ui->state.selected_item]; - VB2_DEBUG("Select <%s> menu item <%s>\n", - ui->state.screen->name, menu_item->text); - - if (menu_item->target) { - VB2_DEBUG("Changing to target screen %#x for menu item <%s>\n", - menu_item->target, menu_item->text); + if (menu_item->action) { + VB2_DEBUG("Menu item <%s> run action\n", menu_item->text); + return menu_item->action(ui); + } else if (menu_item->target) { + VB2_DEBUG("Menu item <%s> to target screen %#x\n", + menu_item->text, menu_item->target); return change_screen(ui, menu_item->target); } - VB2_DEBUG("No target screen for menu item <%s>\n", menu_item->text); - + VB2_DEBUG("Menu item <%s> no action or target screen\n", + menu_item->text); return VB2_REQUEST_UI_CONTINUE; } /** * Return back to the previous screen. */ -vb2_error_t menu_back_action(struct vb2_ui_context *ui) +vb2_error_t vb2_ui_back_action(struct vb2_ui_context *ui) { /* TODO(kitching): Return to previous screen instead of root screen. */ return change_screen(ui, ui->root_screen->id); } +/** + * Context-dependent keyboard shortcut Ctrl+D. + * + * - Manual recovery mode: Change to dev mode transition screen. + * - Developer mode: Boot from internal disk (TODO). + */ +vb2_error_t ctrl_d_action(struct vb2_ui_context *ui) +{ + if (vb2_allow_recovery(ui->ctx)) + return change_screen(ui, VB2_SCREEN_RECOVERY_TO_DEV); + return VB2_REQUEST_UI_CONTINUE; +} + /*****************************************************************************/ /* Action lookup tables */ @@ -165,7 +178,9 @@ static struct input_action action_table[] = { { VB_BUTTON_VOL_UP_SHORT_PRESS, menu_up_action }, { VB_BUTTON_VOL_DOWN_SHORT_PRESS, menu_down_action }, { VB_BUTTON_POWER_SHORT_PRESS, menu_select_action }, - { VB_KEY_ESC, menu_back_action }, + { VB_KEY_ESC, vb2_ui_back_action }, + { VB_KEY_CTRL('D'), ctrl_d_action }, + { ' ', vb2_ui_recovery_to_dev_action }, }; vb2_error_t (*input_action_lookup(int key))(struct vb2_ui_context *ui) @@ -192,6 +207,9 @@ vb2_error_t change_screen(struct vb2_ui_context *ui, enum vb2_screen id) memset(&ui->state, 0, sizeof(ui->state)); ui->state.screen = new_screen_info; + if (ui->state.screen->init) + return ui->state.screen->init(ui); + return VB2_REQUEST_UI_CONTINUE; } @@ -200,7 +218,6 @@ vb2_error_t ui_loop(struct vb2_context *ctx, enum vb2_screen root_screen_id, { struct vb2_ui_context ui; struct vb2_screen_state prev_state; - uint32_t key; uint32_t key_flags; vb2_error_t (*action)(struct vb2_ui_context *ui); vb2_error_t rv; @@ -231,26 +248,38 @@ vb2_error_t ui_loop(struct vb2_context *ctx, enum vb2_screen root_screen_id, ui.state.disabled_item_mask); } + /* Run screen action. */ + if (ui.state.screen->action) { + rv = ui.state.screen->action(&ui); + if (rv != VB2_REQUEST_UI_CONTINUE) + return rv; + } + + /* Grab new keyboard input. */ + ui.key = VbExKeyboardReadWithFlags(&key_flags); + ui.key_trusted = !!(key_flags & VB_KEY_FLAG_TRUSTED_KEYBOARD); + /* Check for shutdown request. */ - key = VbExKeyboardReadWithFlags(&key_flags); - if (shutdown_required(ctx, key)) { + if (shutdown_required(ctx, ui.key)) { VB2_DEBUG("Shutdown required!\n"); return VB2_REQUEST_SHUTDOWN; } /* Run input action function if found. */ - action = input_action_lookup(key); + action = input_action_lookup(ui.key); if (action) { - ui.key = key; rv = action(&ui); - ui.key = 0; if (rv != VB2_REQUEST_UI_CONTINUE) return rv; - } else if (key) { - VB2_DEBUG("Pressed key %#x, trusted? %d\n", key, - !!(key_flags & VB_KEY_FLAG_TRUSTED_KEYBOARD)); + } else if (ui.key) { + VB2_DEBUG("Pressed key %#x, trusted? %d\n", + ui.key, ui.key_trusted); } + /* Reset keyboard input. */ + ui.key = 0; + ui.key_trusted = 0; + /* Run global action function if available. */ if (global_action) { rv = global_action(&ui); diff --git a/firmware/2lib/2ui_screens.c b/firmware/2lib/2ui_screens.c index 5b235c24..a6fffb5e 100644 --- a/firmware/2lib/2ui_screens.c +++ b/firmware/2lib/2ui_screens.c @@ -6,7 +6,11 @@ */ #include "2common.h" +#include "2misc.h" +#include "2nvstorage.h" #include "2ui.h" +#include "2ui_private.h" +#include "vboot_api.h" /* for VB_KEY_ */ #define MENU_ITEMS(a) \ .num_items = ARRAY_SIZE(a), \ @@ -62,6 +66,101 @@ static const struct vb2_screen_info recovery_invalid_screen = { }; /******************************************************************************/ +/* VB2_SCREEN_RECOVERY_TO_DEV */ + +#define RECOVERY_TO_DEV_ITEM_CONFIRM 0 + +vb2_error_t recovery_to_dev_init(struct vb2_ui_context *ui) +{ + if (vb2_get_sd(ui->ctx)->flags & VB2_SD_FLAG_DEV_MODE_ENABLED) { + VB2_DEBUG("Dev mode already enabled?\n"); + return vb2_ui_back_action(ui); + } + + if (!PHYSICAL_PRESENCE_KEYBOARD && vb2ex_physical_presence_pressed()) { + VB2_DEBUG("Presence button stuck?\n"); + return vb2_ui_back_action(ui); + } + + /* Disable "Confirm" button for other physical presence types. */ + if (!PHYSICAL_PRESENCE_KEYBOARD) + ui->state.disabled_item_mask = + 1 << RECOVERY_TO_DEV_ITEM_CONFIRM; + + return VB2_REQUEST_UI_CONTINUE; +} + +vb2_error_t vb2_ui_recovery_to_dev_action(struct vb2_ui_context *ui) +{ + static int pressed_last; + int pressed; + + if (ui->state.screen->id != VB2_SCREEN_RECOVERY_TO_DEV) { + VB2_DEBUG("Action needs RECOVERY_TO_DEV screen\n"); + return VB2_REQUEST_UI_CONTINUE; + } + + if (ui->key == ' ') { + VB2_DEBUG("SPACE means cancel dev mode transition\n"); + return vb2_ui_back_action(ui); + } + + if (PHYSICAL_PRESENCE_KEYBOARD) { + if (ui->key != VB_KEY_ENTER && + ui->key != VB_BUTTON_POWER_SHORT_PRESS) + return VB2_REQUEST_UI_CONTINUE; + if (!ui->key_trusted) { + VB2_DEBUG("Reject untrusted %s confirmation\n", + ui->key == VB_KEY_ENTER ? + "ENTER" : "POWER"); + return VB2_REQUEST_UI_CONTINUE; + } + } else { + pressed = vb2ex_physical_presence_pressed(); + if (pressed) { + VB2_DEBUG("Physical presence button pressed, " + "awaiting release\n"); + pressed_last = 1; + return VB2_REQUEST_UI_CONTINUE; + } + if (!pressed_last) + return VB2_REQUEST_UI_CONTINUE; + VB2_DEBUG("Physical presence button released\n"); + } + VB2_DEBUG("Physical presence confirmed!\n"); + + /* Sanity check, should never happen. */ + if ((vb2_get_sd(ui->ctx)->flags & VB2_SD_FLAG_DEV_MODE_ENABLED) || + !vb2_allow_recovery(ui->ctx)) { + VB2_DEBUG("ERROR: dev transition sanity check failed\n"); + return VB2_REQUEST_UI_CONTINUE; + } + + VB2_DEBUG("Enabling dev mode and rebooting...\n"); + vb2_enable_developer_mode(ui->ctx); + return VB2_REQUEST_REBOOT_EC_TO_RO; +} + +static const struct vb2_menu_item recovery_to_dev_items[] = { + [RECOVERY_TO_DEV_ITEM_CONFIRM] = { + .text = "Confirm", + .action = vb2_ui_recovery_to_dev_action, + }, + { + .text = "Cancel", + .action = vb2_ui_back_action, + }, +}; + +static const struct vb2_screen_info recovery_to_dev_screen = { + .id = VB2_SCREEN_RECOVERY_TO_DEV, + .name = "Transition to developer mode", + .init = recovery_to_dev_init, + .action = vb2_ui_recovery_to_dev_action, + MENU_ITEMS(recovery_to_dev_items), +}; + +/******************************************************************************/ /* VB2_SCREEN_RECOVERY_PHONE_STEP1 */ static const struct vb2_screen_info recovery_phone_step1_screen = { @@ -92,6 +191,7 @@ static const struct vb2_screen_info *screens[] = { &recovery_broken_screen, &recovery_select_screen, &recovery_invalid_screen, + &recovery_to_dev_screen, &recovery_phone_step1_screen, &recovery_disk_step1_screen, }; diff --git a/firmware/2lib/include/2api.h b/firmware/2lib/include/2api.h index 416e2aa5..6b51c54c 100644 --- a/firmware/2lib/include/2api.h +++ b/firmware/2lib/include/2api.h @@ -1181,6 +1181,8 @@ enum vb2_screen { VB2_SCREEN_RECOVERY_SELECT = 0x200, /* Invalid recovery media inserted */ VB2_SCREEN_RECOVERY_INVALID = 0x201, + /* Confirm transition to developer mode */ + VB2_SCREEN_RECOVERY_TO_DEV = 0x202, /* Recovery using disk */ VB2_SCREEN_RECOVERY_DISK_STEP1 = 0x210, VB2_SCREEN_RECOVERY_DISK_STEP2 = 0x211, diff --git a/firmware/2lib/include/2ui.h b/firmware/2lib/include/2ui.h index c0e2b634..b5754020 100644 --- a/firmware/2lib/include/2ui.h +++ b/firmware/2lib/include/2ui.h @@ -14,11 +14,17 @@ /*****************************************************************************/ /* Data structures */ +struct vb2_ui_context; /* Forward declaration */ + struct vb2_screen_info { /* Screen id */ enum vb2_screen id; /* Screen name for printing to console only */ const char *name; + /* Init function runs once when changing to the screen. */ + vb2_error_t (*init)(struct vb2_ui_context *ui); + /* Action function runs repeatedly while on the screen. */ + vb2_error_t (*action)(struct vb2_ui_context *ui); /* Number of menu items */ uint16_t num_items; /* List of menu items */ @@ -30,6 +36,8 @@ struct vb2_menu_item { const char *text; /* Target screen */ enum vb2_screen target; + /* Action function takes precedence over target screen if non-NULL. */ + vb2_error_t (*action)(struct vb2_ui_context *ui); }; struct vb2_screen_state { @@ -44,8 +52,13 @@ struct vb2_ui_context { struct vb2_screen_state state; uint32_t locale_id; uint32_t key; + int key_trusted; }; +vb2_error_t vb2_ui_change_screen(struct vb2_ui_context *ui, enum vb2_screen id); +vb2_error_t vb2_ui_back_action(struct vb2_ui_context *ui); +vb2_error_t vb2_ui_recovery_to_dev_action(struct vb2_ui_context *ui); + /** * Get info struct of a screen. * diff --git a/firmware/2lib/include/2ui_private.h b/firmware/2lib/include/2ui_private.h index 00534492..f7c4e247 100644 --- a/firmware/2lib/include/2ui_private.h +++ b/firmware/2lib/include/2ui_private.h @@ -28,7 +28,7 @@ struct input_action { vb2_error_t menu_up_action(struct vb2_ui_context *ui); vb2_error_t menu_down_action(struct vb2_ui_context *ui); vb2_error_t menu_select_action(struct vb2_ui_context *ui); -vb2_error_t menu_back_action(struct vb2_ui_context *ui); +vb2_error_t ctrl_d_action(struct vb2_ui_context *ui); vb2_error_t (*input_action_lookup(int key))(struct vb2_ui_context *ui); vb2_error_t change_screen(struct vb2_ui_context *ui, enum vb2_screen id); @@ -37,4 +37,7 @@ vb2_error_t ui_loop(struct vb2_context *ctx, enum vb2_screen root_screen_id, vb2_error_t try_recovery_action(struct vb2_ui_context *ui); +/* From 2ui_screens.c */ +vb2_error_t recovery_to_dev_init(struct vb2_ui_context *ui); + #endif /* VBOOT_REFERENCE_2UI_PRIVATE_H_ */ |