summaryrefslogtreecommitdiff
path: root/firmware/2lib
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/2lib')
-rw-r--r--firmware/2lib/2misc.c133
-rw-r--r--firmware/2lib/2stub.c12
-rw-r--r--firmware/2lib/2ui.c13
-rw-r--r--firmware/2lib/2ui_screens.c118
-rw-r--r--firmware/2lib/include/2api.h46
-rw-r--r--firmware/2lib/include/2return_codes.h3
-rw-r--r--firmware/2lib/include/2ui.h5
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;
};