diff options
Diffstat (limited to 'firmware/2lib')
-rw-r--r-- | firmware/2lib/2misc.c | 133 | ||||
-rw-r--r-- | firmware/2lib/2stub.c | 12 | ||||
-rw-r--r-- | firmware/2lib/2ui.c | 13 | ||||
-rw-r--r-- | firmware/2lib/2ui_screens.c | 118 | ||||
-rw-r--r-- | firmware/2lib/include/2api.h | 46 | ||||
-rw-r--r-- | firmware/2lib/include/2return_codes.h | 3 | ||||
-rw-r--r-- | firmware/2lib/include/2ui.h | 5 |
7 files changed, 322 insertions, 8 deletions
diff --git a/firmware/2lib/2misc.c b/firmware/2lib/2misc.c index 86b866de..8e5444a6 100644 --- a/firmware/2lib/2misc.c +++ b/firmware/2lib/2misc.c @@ -574,3 +574,136 @@ int vb2api_use_short_dev_screen_delay(struct vb2_context *ctx) struct vb2_gbb_header *gbb = vb2_get_gbb(ctx); return gbb->flags & VB2_GBB_FLAG_DEV_SCREEN_SHORT_DELAY; } + +static void snprint_sha1_sum(struct vb2_packed_key *key, + char *dest, size_t dest_size) +{ + uint8_t *buf = ((uint8_t *)key) + key->key_offset; + uint64_t buflen = key->key_size; + uint8_t digest[VB2_SHA1_DIGEST_SIZE]; + int32_t used = 0; + int i; + + vb2_digest_buffer(buf, buflen, VB2_HASH_SHA1, digest, sizeof(digest)); + for (i = 0; i < sizeof(digest); i++) + if (used < dest_size) + used += snprintf(dest + used, dest_size - used, + "%02x", digest[i]); + dest[dest_size - 1] = '\0'; +} + +#define DEBUG_INFO_MAX_LENGTH 1024 + +#define DEBUG_INFO_APPEND(format, args...) do { \ + if (used < DEBUG_INFO_MAX_LENGTH) \ + used += snprintf(buf + used, DEBUG_INFO_MAX_LENGTH - used, \ + format, ## args); \ +} while (0) + +char *vb2api_get_debug_info(struct vb2_context *ctx) +{ + char *buf; + uint32_t used = 0; + + struct vb2_shared_data *sd = vb2_get_sd(ctx); + struct vb2_gbb_header *gbb = vb2_get_gbb(ctx); + struct vb2_workbuf wb; + char sha1sum[VB2_SHA1_DIGEST_SIZE * 2 + 1]; + + vb2_error_t rv; + uint32_t i; + + buf = malloc(DEBUG_INFO_MAX_LENGTH + 1); + if (buf == NULL) + return NULL; + + vb2_workbuf_from_ctx(ctx, &wb); + + /* Add hardware ID */ + { + char hwid[VB2_GBB_HWID_MAX_SIZE]; + uint32_t size = sizeof(hwid); + rv = vb2api_gbb_read_hwid(ctx, hwid, &size); + if (rv) + strcpy(hwid, "{INVALID}"); + DEBUG_INFO_APPEND("HWID: %s", hwid); + } + + /* Add recovery reason and subcode */ + i = vb2_nv_get(ctx, VB2_NV_RECOVERY_SUBCODE); + DEBUG_INFO_APPEND("\nrecovery_reason: %#.2x / %#.2x %s", + sd->recovery_reason, i, + vb2_get_recovery_reason_string(sd->recovery_reason)); + + /* Add vb2_context and vb2_shared_data flags */ + DEBUG_INFO_APPEND("\ncontext.flags: %#.16" PRIx64, ctx->flags); + DEBUG_INFO_APPEND("\nshared_data.flags: %#.8x", sd->flags); + DEBUG_INFO_APPEND("\nshared_data.status: %#.8x", sd->status); + + /* Add raw contents of nvdata */ + DEBUG_INFO_APPEND("\nnvdata:"); + if (vb2_nv_get_size(ctx) > 16) /* Multi-line starts on next line */ + DEBUG_INFO_APPEND("\n "); + for (i = 0; i < vb2_nv_get_size(ctx); i++) { + /* Split into 16-byte blocks */ + if (i > 0 && i % 16 == 0) + DEBUG_INFO_APPEND("\n "); + DEBUG_INFO_APPEND(" %02x", ctx->nvdata[i]); + } + + /* Add dev_boot_usb flag */ + i = vb2_nv_get(ctx, VB2_NV_DEV_BOOT_EXTERNAL); + DEBUG_INFO_APPEND("\ndev_boot_usb: %d", i); + + /* Add dev_boot_legacy flag */ + i = vb2_nv_get(ctx, VB2_NV_DEV_BOOT_LEGACY); + DEBUG_INFO_APPEND("\ndev_boot_legacy: %d", i); + + /* Add dev_default_boot flag */ + i = vb2_nv_get(ctx, VB2_NV_DEV_DEFAULT_BOOT); + DEBUG_INFO_APPEND("\ndev_default_boot: %d", i); + + /* Add dev_boot_signed_only flag */ + i = vb2_nv_get(ctx, VB2_NV_DEV_BOOT_SIGNED_ONLY); + DEBUG_INFO_APPEND("\ndev_boot_signed_only: %d", i); + + /* Add TPM versions */ + DEBUG_INFO_APPEND("\nTPM: fwver=%#.8x kernver=%#.8x", + sd->fw_version_secdata, sd->kernel_version_secdata); + + /* Add GBB flags */ + DEBUG_INFO_APPEND("\ngbb.flags: %#.8x", gbb->flags); + + /* Add sha1sum for Root & Recovery keys */ + { + struct vb2_packed_key *key; + struct vb2_workbuf wblocal = wb; + rv = vb2_gbb_read_root_key(ctx, &key, NULL, &wblocal); + if (rv == VB2_SUCCESS) { + snprint_sha1_sum(key, sha1sum, sizeof(sha1sum)); + DEBUG_INFO_APPEND("\ngbb.rootkey: %s", sha1sum); + } + } + + { + struct vb2_packed_key *key; + struct vb2_workbuf wblocal = wb; + rv = vb2_gbb_read_recovery_key(ctx, &key, NULL, &wblocal); + if (rv == VB2_SUCCESS) { + snprint_sha1_sum(key, sha1sum, sizeof(sha1sum)); + DEBUG_INFO_APPEND("\ngbb.recovery_key: %s", sha1sum); + } + } + + /* If we're in dev-mode, show the kernel subkey that we expect, too. */ + if (!(ctx->flags & VB2_CONTEXT_RECOVERY_MODE) && + sd->kernel_key_offset) { + struct vb2_packed_key *key = + vb2_member_of(sd, sd->kernel_key_offset); + snprint_sha1_sum(key, sha1sum, sizeof(sha1sum)); + DEBUG_INFO_APPEND("\nkernel_subkey: %s", sha1sum); + } + + buf[DEBUG_INFO_MAX_LENGTH] = '\0'; + return buf; +} diff --git a/firmware/2lib/2stub.c b/firmware/2lib/2stub.c index 70cbeffc..c4b9bdf3 100644 --- a/firmware/2lib/2stub.c +++ b/firmware/2lib/2stub.c @@ -92,3 +92,15 @@ void vb2ex_abort(void) /* Stub simply exits. */ exit(1); } + +__attribute__((weak)) +const char *vb2ex_get_debug_info(struct vb2_context *ctx) +{ + return NULL; +} + +__attribute__((weak)) +uint32_t vb2ex_prepare_log_screen(const char *str) +{ + return 1; +} diff --git a/firmware/2lib/2ui.c b/firmware/2lib/2ui.c index fea3b4ad..8adfab80 100644 --- a/firmware/2lib/2ui.c +++ b/firmware/2lib/2ui.c @@ -15,7 +15,6 @@ #include "2ui_private.h" #include "vboot_api.h" /* For VB_SHUTDOWN_REQUEST_POWER_BUTTON */ #include "vboot_kernel.h" -#include "vboot_ui_legacy.h" /* TODO(b/144969088): VbDisplayDebugInfo */ #define KEY_DELAY_MS 20 /* Delay between key scans in UI loops */ @@ -326,6 +325,7 @@ vb2_error_t ui_loop(struct vb2_context *ctx, enum vb2_screen root_screen_id, ui.state->selected_item, ui.state->disabled_item_mask, ui.disable_timer, + ui.state->current_page, ui.error_code); if (ui.error_beep) { vb2ex_beep(250, 400); @@ -399,10 +399,8 @@ vb2_error_t developer_action(struct vb2_ui_context *ui) if (ui->key == VB_KEY_CTRL('D') || (DETACHABLE && ui->key == VB_BUTTON_VOL_DOWN_LONG_PRESS)) return vb2_ui_developer_mode_boot_internal_action(ui); - - /* TODO(b/144969088): Re-implement as debug info screen. */ if (ui->key == '\t') - VbDisplayDebugInfo(ui->ctx); + return vb2_ui_screen_change(ui, VB2_SCREEN_DEBUG_INFO); return VB2_REQUEST_UI_CONTINUE; } @@ -417,9 +415,9 @@ vb2_error_t vb2_broken_recovery_menu(struct vb2_context *ctx) vb2_error_t broken_recovery_action(struct vb2_ui_context *ui) { - /* TODO(b/144969088): Re-implement as debug info screen. */ + /* Broken recovery keyboard shortcuts */ if (ui->key == '\t') - VbDisplayDebugInfo(ui->ctx); + return vb2_ui_screen_change(ui, VB2_SCREEN_DEBUG_INFO); return VB2_REQUEST_UI_CONTINUE; } @@ -455,9 +453,8 @@ vb2_error_t manual_recovery_action(struct vb2_ui_context *ui) (DETACHABLE && ui->key == VB_BUTTON_VOL_UP_DOWN_COMBO_PRESS)) return vb2_ui_screen_change(ui, VB2_SCREEN_RECOVERY_TO_DEV); - /* TODO(b/144969088): Re-implement as debug info screen. */ if (ui->key == '\t') - VbDisplayDebugInfo(ui->ctx); + return vb2_ui_screen_change(ui, VB2_SCREEN_DEBUG_INFO); return VB2_REQUEST_UI_CONTINUE; } diff --git a/firmware/2lib/2ui_screens.c b/firmware/2lib/2ui_screens.c index ab15a2b3..741f4b91 100644 --- a/firmware/2lib/2ui_screens.c +++ b/firmware/2lib/2ui_screens.c @@ -52,6 +52,66 @@ static vb2_error_t power_off_action(struct vb2_ui_context *ui) } /******************************************************************************/ +/* Functions used for log screens */ + +static vb2_error_t log_page_init(struct vb2_ui_context *ui, + uint32_t page_up_item, + uint32_t page_down_item, + uint32_t alternate_item) +{ + ui->state->current_page = 0; + + if (ui->state->page_count == 1) { + ui->state->disabled_item_mask |= 1 << page_up_item; + ui->state->disabled_item_mask |= 1 << page_down_item; + ui->state->selected_item = alternate_item; + } else { + ui->state->disabled_item_mask |= 1 << page_up_item; + ui->state->selected_item = page_down_item; + } + + return VB2_REQUEST_UI_CONTINUE; +} + +static vb2_error_t log_page_prev(struct vb2_ui_context *ui, + uint32_t page_up_item, + uint32_t page_down_item) +{ + if (ui->state->current_page == 0) + return VB2_REQUEST_UI_CONTINUE; + ui->state->current_page--; + + /* Clear bits of page down. */ + ui->state->disabled_item_mask &= ~(1 << page_down_item); + + if (ui->state->current_page == 0) { + ui->state->disabled_item_mask |= 1 << page_up_item; + ui->state->selected_item = page_down_item; + } + + return VB2_REQUEST_UI_CONTINUE; +} + +static vb2_error_t log_page_next(struct vb2_ui_context *ui, + uint32_t page_up_item, + uint32_t page_down_item) +{ + if (ui->state->current_page == ui->state->page_count - 1) + return VB2_REQUEST_UI_CONTINUE; + ui->state->current_page++; + + /* Clear bits of page up. */ + ui->state->disabled_item_mask &= ~(1 << page_up_item); + + if (ui->state->current_page == ui->state->page_count - 1) { + ui->state->disabled_item_mask |= 1 << page_down_item; + ui->state->selected_item = page_up_item; + } + + return VB2_REQUEST_UI_CONTINUE; +} + +/******************************************************************************/ /* VB2_SCREEN_BLANK */ static const struct vb2_screen_info blank_screen = { @@ -176,6 +236,7 @@ static const struct vb2_menu_item advanced_options_items[] = { .text = "Enable developer mode", .target = VB2_SCREEN_RECOVERY_TO_DEV, }, + /* TODO(b:144969088): Add debug info item */ [ADVANCED_OPTIONS_ITEM_BACK] = BACK_ITEM, POWER_OFF_ITEM, }; @@ -188,6 +249,62 @@ static const struct vb2_screen_info advanced_options_screen = { }; /******************************************************************************/ +/* VB2_SCREEN_DEBUG_INFO */ + +#define DEBUG_INFO_ITEM_PAGE_UP 1 +#define DEBUG_INFO_ITEM_PAGE_DOWN 2 +#define DEBUG_INFO_ITEM_BACK 3 + +static vb2_error_t debug_info_init(struct vb2_ui_context *ui) +{ + const char *log_string = vb2ex_get_debug_info(ui->ctx); + ui->state->page_count = vb2ex_prepare_log_screen(log_string); + if (ui->state->page_count == 0) { + ui->error_code = VB2_UI_ERROR_DEBUG_LOG; + return vb2_ui_screen_back(ui); + } + return log_page_init(ui, + DEBUG_INFO_ITEM_PAGE_UP, + DEBUG_INFO_ITEM_PAGE_DOWN, + DEBUG_INFO_ITEM_BACK); +} + +static vb2_error_t debug_info_page_prev_action(struct vb2_ui_context *ui) +{ + return log_page_prev(ui, + DEBUG_INFO_ITEM_PAGE_UP, + DEBUG_INFO_ITEM_PAGE_DOWN); +} + +static vb2_error_t debug_info_page_next_action(struct vb2_ui_context *ui) +{ + return log_page_next(ui, + DEBUG_INFO_ITEM_PAGE_UP, + DEBUG_INFO_ITEM_PAGE_DOWN); +} + +static const struct vb2_menu_item debug_info_items[] = { + LANGUAGE_SELECT_ITEM, + [DEBUG_INFO_ITEM_PAGE_UP] = { + .text = "Page up", + .action = debug_info_page_prev_action, + }, + [DEBUG_INFO_ITEM_PAGE_DOWN] = { + .text = "Page down", + .action = debug_info_page_next_action, + }, + [DEBUG_INFO_ITEM_BACK] = BACK_ITEM, + POWER_OFF_ITEM, +}; + +static const struct vb2_screen_info debug_info_screen = { + .id = VB2_SCREEN_DEBUG_INFO, + .name = "Debug info", + .init = debug_info_init, + .menu = MENU_ITEMS(debug_info_items), +}; + +/******************************************************************************/ /* VB2_SCREEN_RECOVERY_SELECT */ #define RECOVERY_SELECT_ITEM_PHONE 1 @@ -662,6 +779,7 @@ static const struct vb2_screen_info *screens[] = { &language_select_screen, &recovery_broken_screen, &advanced_options_screen, + &debug_info_screen, &recovery_select_screen, &recovery_invalid_screen, &recovery_to_dev_screen, diff --git a/firmware/2lib/include/2api.h b/firmware/2lib/include/2api.h index b6c9bea4..649ee096 100644 --- a/firmware/2lib/include/2api.h +++ b/firmware/2lib/include/2api.h @@ -1269,6 +1269,8 @@ enum vb2_screen { VB2_SCREEN_ADVANCED_OPTIONS = 0x120, /* Language selection screen */ VB2_SCREEN_LANGUAGE_SELECT = 0x130, + /* Debug info */ + VB2_SCREEN_DEBUG_INFO = 0x140, /* First recovery screen to select recovering from disk or phone */ VB2_SCREEN_RECOVERY_SELECT = 0x200, /* Invalid recovery media inserted */ @@ -1297,6 +1299,8 @@ enum vb2_ui_error { VB2_UI_ERROR_NONE = 0, /* Dev mode already enabled */ VB2_UI_ERROR_DEV_MODE_ALREADY_ENABLED, + /* Debug info screen initialization failed */ + VB2_UI_ERROR_DEBUG_LOG, }; /** @@ -1310,6 +1314,9 @@ enum vb2_ui_error { * indicates whether item 'idx' is disabled. * @param timer_disabled Whether timer is disabled or not. Some screen * descriptions will depend on this value. + * @param current_page Current page number for a log screen. If the + * screen doesn't show logs, this value will be + * ignored. * @param error_code Error code if an error occurred. * @return VB2_SUCCESS, or error code on error. */ @@ -1318,6 +1325,7 @@ vb2_error_t vb2ex_display_ui(enum vb2_screen screen, uint32_t selected_item, uint32_t disabled_item_mask, int timer_disabled, + uint32_t current_page, enum vb2_ui_error error_code); /** @@ -1354,6 +1362,44 @@ void vb2ex_msleep(uint32_t msec); */ void vb2ex_beep(uint32_t msec, uint32_t frequency); +/** + * Get the full debug info string. + * + * Return a pointer to the full debug info string which is guaranteed to be + * null-terminated. The function implementation should manage string memory + * internally. Subsequent calls may update the string and return the same + * pointer, or return a new pointer if necessary. + * + * @param ctx Vboot context + * @return The pointer to the full debug info string. NULL on error. + */ +const char *vb2ex_get_debug_info(struct vb2_context *ctx); + +/** + * Get the vboot debug info. + * + * Return a pointer to the vboot debug info string which is guaranteed to be + * null-terminated. The caller owns the string and should call free() when + * finished with it. + * + * @param ctx Vboot context + * @return The pointer to the vboot debug info string. NULL on error. + */ +char *vb2api_get_debug_info(struct vb2_context *ctx); + +/** + * Specify the string to be used for an upcoming log screen display. + * + * Before a vb2ex_display_ui() call is made for a screen which displays logs, + * the log string should be provided via this function. The total number of + * pages in the log string is returned. If the log string ever changes, this + * function should be called again before the next vb2ex_display_ui() call. + * + * @param str The log string to display. + * @return The number of pages after pagination. 0 if none or error. + */ +uint32_t vb2ex_prepare_log_screen(const char *str); + /*****************************************************************************/ /* Timer. */ diff --git a/firmware/2lib/include/2return_codes.h b/firmware/2lib/include/2return_codes.h index 8d69847c..336c11e0 100644 --- a/firmware/2lib/include/2return_codes.h +++ b/firmware/2lib/include/2return_codes.h @@ -774,6 +774,9 @@ enum vb2_return_code { /* Memory allocation failure */ VB2_ERROR_UI_MEMORY_ALLOC = 0x100c0007, + /* Log screen initialization failed */ + VB2_ERROR_UI_LOG_INIT = 0x100c0008, + /********************************************************************** * Errors generated by host library (non-firmware) start here. */ diff --git a/firmware/2lib/include/2ui.h b/firmware/2lib/include/2ui.h index fa8c66a3..5f2434c2 100644 --- a/firmware/2lib/include/2ui.h +++ b/firmware/2lib/include/2ui.h @@ -56,6 +56,11 @@ struct vb2_screen_state { const struct vb2_screen_info *screen; uint32_t selected_item; uint32_t disabled_item_mask; + + /* For log screen. */ + uint32_t page_count; + uint32_t current_page; + struct vb2_screen_state *prev; }; |