diff options
Diffstat (limited to 'firmware/2lib/2ui.c')
-rw-r--r-- | firmware/2lib/2ui.c | 414 |
1 files changed, 0 insertions, 414 deletions
diff --git a/firmware/2lib/2ui.c b/firmware/2lib/2ui.c deleted file mode 100644 index 64680220..00000000 --- a/firmware/2lib/2ui.c +++ /dev/null @@ -1,414 +0,0 @@ -/* Copyright 2020 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. - * - * User interfaces for developer and recovery mode menus. - */ - -#include "2api.h" -#include "2common.h" -#include "2misc.h" -#include "2nvstorage.h" -#include "2return_codes.h" -#include "2ui.h" -#include "2ui_private.h" -#include "vboot_api.h" /* For VB_SHUTDOWN_REQUEST_POWER_BUTTON */ - -/*****************************************************************************/ -/* Utility functions */ - -/** - * Check GBB flags against VbExIsShutdownRequested() shutdown request, - * and check for VB_BUTTON_POWER_SHORT_PRESS key, to determine if a - * shutdown is required. - * - * @param ui UI context pointer - * @return VB2_REQUEST_SHUTDOWN if shutdown needed, or VB2_SUCCESS - */ -vb2_error_t vb2_check_shutdown_request(struct vb2_ui_context *ui) -{ - uint32_t shutdown_request = VbExIsShutdownRequested(); - - /* - * Ignore power button push until after we have seen it released. - * This avoids shutting down immediately if the power button is still - * being held on startup. After we've recognized a valid power button - * push then don't report the event until after the button is released. - */ - if (shutdown_request & VB_SHUTDOWN_REQUEST_POWER_BUTTON) { - shutdown_request &= ~VB_SHUTDOWN_REQUEST_POWER_BUTTON; - if (ui->power_button == VB2_POWER_BUTTON_RELEASED) - ui->power_button = VB2_POWER_BUTTON_PRESSED; - } else { - if (ui->power_button == VB2_POWER_BUTTON_PRESSED) - shutdown_request |= VB_SHUTDOWN_REQUEST_POWER_BUTTON; - ui->power_button = VB2_POWER_BUTTON_RELEASED; - } - - if (ui->key == VB_BUTTON_POWER_SHORT_PRESS) - shutdown_request |= VB_SHUTDOWN_REQUEST_POWER_BUTTON; - - /* If desired, ignore shutdown request due to lid closure. */ - if (vb2api_gbb_get_flags(ui->ctx) & VB2_GBB_FLAG_DISABLE_LID_SHUTDOWN) - shutdown_request &= ~VB_SHUTDOWN_REQUEST_LID_CLOSED; - - /* - * In detachables, disable shutdown due to power button. - * It is used for menu selection instead. - */ - if (DETACHABLE) - shutdown_request &= ~VB_SHUTDOWN_REQUEST_POWER_BUTTON; - - if (shutdown_request) - return VB2_REQUEST_SHUTDOWN; - - return VB2_SUCCESS; -} - -/*****************************************************************************/ -/* Error action functions */ - -vb2_error_t vb2_error_exit_action(struct vb2_ui_context *ui) -{ - /* - * If an error message is currently shown on the screen, any - * key press clears that error. Unset the key so that it is - * not processed by other action functions. - */ - if (ui->key && ui->error_code) { - ui->error_code = VB2_UI_ERROR_NONE; - ui->key = 0; - } - return VB2_SUCCESS; -} - -/*****************************************************************************/ -/* Menu navigation functions */ - -const struct vb2_menu *vb2_get_menu(struct vb2_ui_context *ui) -{ - const struct vb2_menu *menu; - static const struct vb2_menu empty_menu = { - .num_items = 0, - .items = NULL, - }; - if (ui->state->screen->get_menu) { - menu = ui->state->screen->get_menu(ui); - return menu ? menu : &empty_menu; - } else { - return &ui->state->screen->menu; - } -} - -vb2_error_t vb2_menu_navigation_action(struct vb2_ui_context *ui) -{ - uint32_t key = ui->key; - - /* Map detachable button presses for simplicity. */ - if (DETACHABLE) { - if (key == VB_BUTTON_VOL_UP_SHORT_PRESS) - key = VB_KEY_UP; - else if (key == VB_BUTTON_VOL_DOWN_SHORT_PRESS) - key = VB_KEY_DOWN; - else if (key == VB_BUTTON_POWER_SHORT_PRESS) - key = VB_KEY_ENTER; - } - - switch (key) { - case VB_KEY_UP: - return vb2_ui_menu_prev(ui); - case VB_KEY_DOWN: - return vb2_ui_menu_next(ui); - case VB_KEY_ENTER: - return vb2_ui_menu_select(ui); - case VB_KEY_ESC: - return vb2_ui_screen_back(ui); - default: - if (key != 0) - VB2_DEBUG("Pressed key %#x, trusted? %d\n", - ui->key, ui->key_trusted); - } - - return VB2_SUCCESS; -} - -vb2_error_t vb2_ui_menu_prev(struct vb2_ui_context *ui) -{ - int item; - - if (!DETACHABLE && ui->key == VB_BUTTON_VOL_UP_SHORT_PRESS) - return VB2_SUCCESS; - - item = ui->state->selected_item - 1; - while (item >= 0 && VB2_GET_BIT(ui->state->hidden_item_mask, item)) - item--; - /* Only update if item is valid */ - if (item >= 0) - ui->state->selected_item = item; - - return VB2_SUCCESS; -} - -vb2_error_t vb2_ui_menu_next(struct vb2_ui_context *ui) -{ - int item; - const struct vb2_menu *menu; - - if (!DETACHABLE && ui->key == VB_BUTTON_VOL_DOWN_SHORT_PRESS) - return VB2_SUCCESS; - - menu = vb2_get_menu(ui); - item = ui->state->selected_item + 1; - while (item < menu->num_items && - VB2_GET_BIT(ui->state->hidden_item_mask, item)) - item++; - /* Only update if item is valid */ - if (item < menu->num_items) - ui->state->selected_item = item; - - return VB2_SUCCESS; -} - -vb2_error_t vb2_ui_menu_select(struct vb2_ui_context *ui) -{ - const struct vb2_menu *menu; - const struct vb2_menu_item *menu_item; - - if (!DETACHABLE && ui->key == VB_BUTTON_POWER_SHORT_PRESS) - return VB2_SUCCESS; - - menu = vb2_get_menu(ui); - if (menu->num_items == 0) - return VB2_SUCCESS; - - 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_SUCCESS; - } - - 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 vb2_ui_screen_change(ui, menu_item->target); - } - - VB2_DEBUG("Menu item <%s> no action or target screen\n", - menu_item->text); - return VB2_SUCCESS; -} - -/*****************************************************************************/ -/* Screen navigation functions */ - -vb2_error_t vb2_ui_screen_back(struct vb2_ui_context *ui) -{ - struct vb2_screen_state *tmp; - - if (ui->state && ui->state->prev) { - tmp = ui->state->prev; - free(ui->state); - ui->state = tmp; - if (ui->state->screen->reinit) - VB2_TRY(ui->state->screen->reinit(ui)); - } else { - VB2_DEBUG("ERROR: No previous screen; ignoring\n"); - } - - return VB2_REQUEST_UI_CONTINUE; -} - -static vb2_error_t default_screen_init(struct vb2_ui_context *ui) -{ - const struct vb2_menu *menu = vb2_get_menu(ui); - ui->state->selected_item = 0; - if (menu->num_items > 1 && menu->items[0].is_language_select) - ui->state->selected_item = 1; - return VB2_SUCCESS; -} - -vb2_error_t vb2_ui_screen_change(struct vb2_ui_context *ui, enum vb2_screen id) -{ - const struct vb2_screen_info *new_screen_info; - struct vb2_screen_state *cur_state; - int state_exists = 0; - - new_screen_info = vb2_get_screen_info(id); - if (new_screen_info == NULL) { - VB2_DEBUG("ERROR: Screen entry %#x not found; ignoring\n", id); - return VB2_REQUEST_UI_CONTINUE; - } - - /* Check to see if the screen state already exists in our stack. */ - cur_state = ui->state; - while (cur_state != NULL) { - if (cur_state->screen->id == id) { - state_exists = 1; - break; - } - cur_state = cur_state->prev; - } - - if (state_exists) { - /* Pop until the requested screen is at the top of stack. */ - while (ui->state->screen->id != id) { - cur_state = ui->state; - ui->state = cur_state->prev; - free(cur_state); - } - if (ui->state->screen->reinit) - VB2_TRY(ui->state->screen->reinit(ui)); - } else { - /* Allocate the requested screen on top of the stack. */ - cur_state = malloc(sizeof(*ui->state)); - if (cur_state == NULL) { - VB2_DEBUG("WARNING: malloc failed; ignoring\n"); - return VB2_REQUEST_UI_CONTINUE; - } - memset(cur_state, 0, sizeof(*ui->state)); - cur_state->prev = ui->state; - cur_state->screen = new_screen_info; - ui->state = cur_state; - if (ui->state->screen->init) - VB2_TRY(ui->state->screen->init(ui)); - else - VB2_TRY(default_screen_init(ui)); - } - - return VB2_REQUEST_UI_CONTINUE; -} - -/*****************************************************************************/ -/* Core UI loop */ - -static vb2_error_t ui_loop_impl( - struct vb2_context *ctx, enum vb2_screen root_screen_id, - vb2_error_t (*global_action)(struct vb2_ui_context *ui)) -{ - struct vb2_ui_context ui; - struct vb2_screen_state prev_state; - int prev_disable_timer; - enum vb2_ui_error prev_error_code; - const struct vb2_menu *menu; - const struct vb2_screen_info *root_info; - uint32_t key_flags; - uint32_t start_time_ms, elapsed_ms; - vb2_error_t rv; - - memset(&ui, 0, sizeof(ui)); - ui.ctx = ctx; - root_info = vb2_get_screen_info(root_screen_id); - if (root_info == NULL) - VB2_DIE("Root screen not found.\n"); - ui.locale_id = vb2api_get_locale_id(ctx); - - rv = vb2_ui_screen_change(&ui, root_screen_id); - if (rv && rv != VB2_REQUEST_UI_CONTINUE) - return rv; - - memset(&prev_state, 0, sizeof(prev_state)); - prev_disable_timer = 0; - prev_error_code = VB2_UI_ERROR_NONE; - - while (1) { - start_time_ms = vb2ex_mtime(); - - /* Draw if there are state changes. */ - if (memcmp(&prev_state, ui.state, sizeof(*ui.state)) || - /* Redraw when timer is disabled. */ - prev_disable_timer != ui.disable_timer || - /* Redraw/beep on a transition. */ - prev_error_code != ui.error_code || - /* Beep. */ - ui.error_beep != 0 || - /* Redraw on a screen request to refresh. */ - ui.force_display) { - - menu = vb2_get_menu(&ui); - VB2_DEBUG("<%s> menu item <%s>\n", - ui.state->screen->name, - menu->num_items ? - menu->items[ui.state->selected_item].text : - "null"); - 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); - if (ui.error_beep || - (ui.error_code && - prev_error_code != ui.error_code)) { - vb2ex_beep(250, 400); - ui.error_beep = 0; - } - - /* Reset refresh flag. */ - ui.force_display = 0; - - /* Update prev variables. */ - memcpy(&prev_state, ui.state, sizeof(*ui.state)); - prev_disable_timer = ui.disable_timer; - prev_error_code = ui.error_code; - } - - /* Grab new keyboard input. */ - ui.key = VbExKeyboardReadWithFlags(&key_flags); - ui.key_trusted = !!(key_flags & VB_KEY_FLAG_TRUSTED_KEYBOARD); - - /* Check for shutdown request. */ - rv = vb2_check_shutdown_request(&ui); - if (rv && rv != VB2_REQUEST_UI_CONTINUE) { - VB2_DEBUG("Shutdown requested!\n"); - return rv; - } - - /* Check if we need to exit an error box. */ - rv = vb2_error_exit_action(&ui); - if (rv && rv != VB2_REQUEST_UI_CONTINUE) - return rv; - - /* Run screen action. */ - if (ui.state->screen->action) { - rv = ui.state->screen->action(&ui); - if (rv && rv != VB2_REQUEST_UI_CONTINUE) - return rv; - } - - /* Run menu navigation action. */ - rv = vb2_menu_navigation_action(&ui); - if (rv && rv != VB2_REQUEST_UI_CONTINUE) - return rv; - - /* Run global action function if available. */ - if (global_action) { - rv = global_action(&ui); - if (rv && rv != VB2_REQUEST_UI_CONTINUE) - return rv; - } - - /* Delay. */ - elapsed_ms = vb2ex_mtime() - start_time_ms; - if (elapsed_ms < KEY_DELAY_MS) - vb2ex_msleep(KEY_DELAY_MS - elapsed_ms); - } - - return VB2_SUCCESS; -} - -vb2_error_t vb2_ui_loop(struct vb2_context *ctx, enum vb2_screen root_screen_id, - vb2_error_t (*global_action)(struct vb2_ui_context *ui)) -{ - vb2_error_t rv = ui_loop_impl(ctx, root_screen_id, global_action); - if (rv == VB2_REQUEST_UI_EXIT) - return VB2_SUCCESS; - return rv; -} |