diff options
-rw-r--r-- | firmware/2lib/2api.c | 30 | ||||
-rw-r--r-- | firmware/2lib/include/2api.h | 94 | ||||
-rw-r--r-- | firmware/2lib/include/2info.h | 146 |
3 files changed, 203 insertions, 67 deletions
diff --git a/firmware/2lib/2api.c b/firmware/2lib/2api.c index 9184b23d..13b3a697 100644 --- a/firmware/2lib/2api.c +++ b/firmware/2lib/2api.c @@ -365,3 +365,33 @@ int vb2api_check_hash(struct vb2_context *ctx) { return vb2api_check_hash_get_digest(ctx, NULL, 0); } + +union vb2_fw_boot_info vb2api_get_fw_boot_info(struct vb2_context *ctx) +{ + union vb2_fw_boot_info info; + + struct vb2_shared_data *sd = vb2_get_sd(ctx); + + info.tries = vb2_nv_get(ctx, VB2_NV_TRY_COUNT); + info.slot = sd->fw_slot; + info.prev_slot = sd->last_fw_slot; + info.prev_result = sd->last_fw_result; + info.boot_mode = ctx->boot_mode; + + VB2_DEBUG("boot_mode=`%s`\n", vb2_boot_mode_string(info.boot_mode)); + + if (ctx->flags & VB2_CONTEXT_RECOVERY_MODE) { + info.recovery_reason = sd->recovery_reason; + info.recovery_subcode = vb2_nv_get(ctx, VB2_NV_RECOVERY_SUBCODE); + VB2_DEBUG("recovery_reason: %#x / %#x\n", + info.recovery_reason, info.recovery_subcode); + } + + VB2_DEBUG("fw_tried=`%s` fw_try_count=%d " + "fw_prev_tried=`%s` fw_prev_result=`%s`.\n", + vb2_slot_string(info.slot), info.tries, + vb2_slot_string(info.prev_slot), + vb2_result_string(info.prev_result)); + + return info; +} diff --git a/firmware/2lib/include/2api.h b/firmware/2lib/include/2api.h index a833da7c..904b7105 100644 --- a/firmware/2lib/include/2api.h +++ b/firmware/2lib/include/2api.h @@ -24,6 +24,7 @@ #include "2fw_hash_tags.h" #include "2gbb_flags.h" #include "2id.h" +#include "2info.h" #include "2recovery_reasons.h" #include "2return_codes.h" #include "2rsa.h" @@ -266,73 +267,6 @@ enum vb2_context_flags { VB2_CONTEXT_DISABLE_TPM = (1 << 28), }; -/* Boot mode decided in vb2api_fw_phase1. - * - * Boot mode is a constant set by verified boot and may be read (but should not - * be set or cleared) by the caller. - * The boot modes are mutually exclusive. If a boot fulfill more than one - * constraints of the listing boot modes, it will be set to the most important - * one. The priority is the same as the listing order. - */ -enum vb2_boot_mode { - /* Undefined, The boot mode is not set. */ - VB2_BOOT_MODE_UNDEFINED = 0, - - /* - * Manual recovery boot, regardless of dev mode state. - * - * VB2_CONTEXT_RECOVERY_MODE is set and the recovery is physically - * requested (a.k.a. Manual recovery). All other recovery requests - * including manual recovery requested by a (compromised) host will end - * up with a broken screen. - */ - VB2_BOOT_MODE_MANUAL_RECOVERY = 1, - - /* - * Broken screen. - * - * If a recovery boot is not a manual recovery (a.k.a. not requested - * physically), the recovery is not allowed and will end up with - * broken screen. - */ - VB2_BOOT_MODE_BROKEN_SCREEN = 2, - - /* - * Diagnostic boot. - * - * If diagnostic boot is enabled (a.k.a. vb2api_diagnostic_ui_enabled) - * and the nvdata contains VB2_NV_DIAG_REQUEST from previous boot, it - * will boot to diagnostic mode. - */ - VB2_BOOT_MODE_DIAGNOSTICS = 3, - - /* - * Developer boot: self-signed kernel okay. - * - * The developer mode switch is set (a.k.a. VB2_CONTEXT_DEVELOPER_MODE) - * and we are in the developer boot mode. - */ - VB2_BOOT_MODE_DEVELOPER = 4, - - /* Normal boot: kernel must be verified. */ - VB2_BOOT_MODE_NORMAL = 5, -}; - -/* Firmware result codes for VB2_NV_FW_RESULT and VB2_NV_FW_PREV_RESULT */ -enum vb2_fw_result { - /* Unknown */ - VB2_FW_RESULT_UNKNOWN = 0, - - /* Trying a new slot, but haven't reached success/failure */ - VB2_FW_RESULT_TRYING = 1, - - /* Successfully booted to the OS */ - VB2_FW_RESULT_SUCCESS = 2, - - /* Known failure */ - VB2_FW_RESULT_FAILURE = 3, -}; - /* Helper for aligning fields in vb2_context. */ #define VB2_PAD_STRUCT3(size, align, count) \ uint8_t _pad##count[align - (((size - 1) % align) + 1)] @@ -1520,4 +1454,30 @@ uint32_t vb2ex_mtime(void); */ void vb2ex_msleep(uint32_t msec); +union vb2_fw_boot_info { + uint8_t raw[4]; + struct { + uint8_t tries : 4; + uint8_t slot : 1; + uint8_t prev_slot : 1; + uint8_t prev_result : 2; + uint8_t boot_mode; + /* The following 2 bytes only exist for recovery mode */ + uint8_t recovery_reason; + uint8_t recovery_subcode; + }; +}; + +/** + * Return `vb2_fw_boot_info` and can be used + * to log information about the current boot in a compact format. + * + * Note: Only call this API at minimum after `vb2api_fw_phase2` function + * returns. + * + * @param ctx Vboot context + * @return filled out vb2 info as per `union vb2_fw_boot_info`. + */ +union vb2_fw_boot_info vb2api_get_fw_boot_info(struct vb2_context *ctx); + #endif /* VBOOT_REFERENCE_2API_H_ */ diff --git a/firmware/2lib/include/2info.h b/firmware/2lib/include/2info.h new file mode 100644 index 00000000..be2ea604 --- /dev/null +++ b/firmware/2lib/include/2info.h @@ -0,0 +1,146 @@ +/* Copyright 2022 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. + * + * Helper functions to retrieve vboot firmware information. + */ + +#ifndef VBOOT_REFERENCE_2INFO_H_ +#define VBOOT_REFERENCE_2INFO_H_ + +/* Boot mode decided in vb2api_fw_phase1. + * + * Boot mode is a constant set by verified boot and may be read (but should not + * be set or cleared) by the caller. + * The boot modes are mutually exclusive. If a boot fulfill more than one + * constraints of the listing boot modes, it will be set to the most important + * one. The priority is the same as the listing order. + */ +enum vb2_boot_mode { + /* Undefined, The boot mode is not set. */ + VB2_BOOT_MODE_UNDEFINED = 0, + + /* + * Manual recovery boot, regardless of dev mode state. + * + * VB2_CONTEXT_RECOVERY_MODE is set and the recovery is physically + * requested (a.k.a. Manual recovery). All other recovery requests + * including manual recovery requested by a (compromised) host will end + * up with a broken screen. + */ + VB2_BOOT_MODE_MANUAL_RECOVERY = 1, + + /* + * Broken screen. + * + * If a recovery boot is not a manual recovery (a.k.a. not requested + * physically), the recovery is not allowed and will end up with + * broken screen. + */ + VB2_BOOT_MODE_BROKEN_SCREEN = 2, + + /* + * Diagnostic boot. + * + * If diagnostic boot is enabled (a.k.a. vb2api_diagnostic_ui_enabled) + * and the nvdata contains VB2_NV_DIAG_REQUEST from previous boot, it + * will boot to diagnostic mode. + */ + VB2_BOOT_MODE_DIAGNOSTICS = 3, + + /* + * Developer boot: self-signed kernel okay. + * + * The developer mode switch is set (a.k.a. VB2_CONTEXT_DEVELOPER_MODE) + * and we are in the developer boot mode. + */ + VB2_BOOT_MODE_DEVELOPER = 4, + + /* Normal boot: kernel must be verified. */ + VB2_BOOT_MODE_NORMAL = 5, +}; + +/* Firmware slot codes */ +enum vb2_fw_slot { + /* Slot A */ + VB2_FW_SLOT_A = 0, + + /* Slot B */ + VB2_FW_SLOT_B = 1, +}; + +/* Firmware result codes for VB2_NV_FW_RESULT and VB2_NV_FW_PREV_RESULT */ +enum vb2_fw_result { + /* Unknown */ + VB2_FW_RESULT_UNKNOWN = 0, + + /* Trying a new slot, but haven't reached success/failure */ + VB2_FW_RESULT_TRYING = 1, + + /* Successfully booted to the OS */ + VB2_FW_RESULT_SUCCESS = 2, + + /* Known failure */ + VB2_FW_RESULT_FAILURE = 3, +}; + +/** + * Convert Firmware Boot Mode into supported string + * + * @return char* firmware boot mode string + */ +static inline const char *vb2_boot_mode_string(uint8_t boot_mode) +{ + switch ((enum vb2_boot_mode)boot_mode) { + /* 0x00 */ case VB2_BOOT_MODE_UNDEFINED: + return "Undefined"; + /* 0x01 */ case VB2_BOOT_MODE_MANUAL_RECOVERY: + return "Manual recovery"; + /* 0x02 */ case VB2_BOOT_MODE_BROKEN_SCREEN: + return "Broken screen"; + /* 0x03 */ case VB2_BOOT_MODE_DIAGNOSTICS: + return "Diagnostic"; + /* 0x04 */ case VB2_BOOT_MODE_DEVELOPER: + return "Developer"; + /* 0x05 */ case VB2_BOOT_MODE_NORMAL: + return "Secure"; + } + + return "Unknown"; +} + +/** + * Convert Firmware Slot result into supported string + * + * @return char* firmware slot result string + */ +static inline const char *vb2_result_string(uint8_t result) +{ + switch ((enum vb2_fw_result)result) { + /* 0x00 */ case VB2_FW_RESULT_UNKNOWN: + return "Unknown"; + /* 0x01 */ case VB2_FW_RESULT_TRYING: + return "Trying"; + /* 0x02 */ case VB2_FW_RESULT_SUCCESS: + return "Success"; + /* 0x03 */ case VB2_FW_RESULT_FAILURE: + return "Failure"; + } + + return "Unknown"; +} + +/** + * Convert Firmware Slot into supported string + * + * @return char* firmware slot name string + */ +static inline const char *vb2_slot_string(uint8_t slot) +{ + if ((enum vb2_fw_slot)slot == VB2_FW_SLOT_A) + /* 0x00 */ return "A"; + else + /* 0x01 */ return "B"; +} + +#endif /* VBOOT_REFERENCE_2INFO_H_ */ |