Add vboot support for RO-normal code path.

BUG=chromium-os:17304
TEST=make && make runtests

Change-Id: I4d0f8afd516649fba67119845ec1c4479ba54c43
Reviewed-on: http://gerrit.chromium.org/gerrit/4065
Reviewed-by: Stefan Reinauer <reinauer@chromium.org>
Tested-by: Randall Spangler <rspangler@chromium.org>
This commit is contained in:
Randall Spangler
2011-07-13 16:31:08 -07:00
parent 3a6e2f10b2
commit 8bf0d5ff0f
7 changed files with 78 additions and 62 deletions

View File

@@ -20,9 +20,6 @@
* VbNvContext (VBNV_RECOVERY_REQUEST). */
#define LOAD_FIRMWARE_REBOOT 2 /* Reboot to same mode as current boot */
/* Boot flags for LoadFirmware().boot_flags */
#define BOOT_FLAG_DEVELOPER UINT64_C(0x01) /* Developer switch is on */
typedef struct LoadFirmwareParams {
/* Inputs to LoadFirmware() */
void* gbb_data; /* Pointer to GBB data */
@@ -38,13 +35,12 @@ typedef struct LoadFirmwareParams {
void* shared_data_blob; /* Shared data blob buffer. Pass this
* data to LoadKernel() in
* LoadKernelParams.shared_data_blob. */
uint64_t shared_data_size; /* On input, set to size of shared data blob
uint32_t shared_data_size; /* On input, set to size of shared data blob
* buffer, in bytes. On output, this will
* contain the actual data size placed into
* the buffer. Caller need only pass that
* much data to LoadKernel().*/
uint64_t boot_flags; /* Boot flags */
VbNvContext* nv_context; /* Context for NV storage. nv_context->raw
* must be filled before calling
* LoadFirmware(). On output, check
@@ -52,10 +48,6 @@ typedef struct LoadFirmwareParams {
* nv_context->raw has been modified and
* needs saving. */
/* Outputs from LoadFirmware(); valid only if LoadFirmware() returns
* LOAD_FIRMWARE_SUCCESS. */
uint64_t firmware_index; /* Firmware index to run. */
/* Internal data for LoadFirmware() / UpdateFirmwareBodyHash(). */
void* load_firmware_internal;

View File

@@ -100,6 +100,9 @@ typedef struct VbCommonParams {
/* TODO: add a field to VbInitParams which holds a reason code, and report
* that via VbSharedData. */
#define VB_INIT_FLAG_PREVIOUS_BOOT_FAIL 0x00000010
/* Calling firmware supports read only firmware for normal/developer
* boot path. */
#define VB_INIT_FLAG_RO_NORMAL_SUPPORT 0x00000020
/* Output flags for VbInitParams.out_flags. Used to indicate
* potential boot paths and configuration to the calling firmware
@@ -143,7 +146,7 @@ enum VbSelectFirmware_t {
/* Rewritable firmware A/B for normal or developer path */
VB_SELECT_FIRMWARE_A = 1,
VB_SELECT_FIRMWARE_B = 2,
/* Read only firmware for normal or developer path */
/* Read only firmware for normal or developer path. */
VB_SELECT_FIRMWARE_READONLY = 3
};
@@ -157,7 +160,8 @@ typedef struct VbSelectFirmwareParams {
uint32_t verification_size_B; /* Verification block B size in bytes */
/* Outputs from VbSelectFirmware(); valid only if it returns success. */
uint32_t selected_firmware; /* Main firmware to run; see VB_SELECT_*. */
uint32_t selected_firmware; /* Main firmware to run; see
* VB_SELECT_FIRMWARE_*. */
} VbSelectFirmwareParams;

View File

@@ -180,6 +180,8 @@ typedef struct VbKernelPreambleHeader {
#define VBSD_KERNEL_KEY_VERIFIED 0x00000002
/* LoadFirmware() was told the developer switch was on */
#define VBSD_LF_DEV_SWITCH_ON 0x00000004
/* LoadFirmware() is requesting the read only normal/dev code path */
#define VBSD_LF_USE_RO_NORMAL 0x00000008
/* Developer switch was enabled at boot time */
#define VBSD_BOOT_DEV_SWITCH_ON 0x00000010
/* Recovery switch was enabled at boot time */
@@ -188,7 +190,8 @@ typedef struct VbKernelPreambleHeader {
#define VBSD_BOOT_FIRMWARE_WP_ENABLED 0x00000040
/* Boot is a S3->S0 resume, not a S5->S0 normal boot */
#define VBSD_BOOT_S3_RESUME 0x00000100
/* Read-only firmware supports the normal/developer code path */
#define VBSD_BOOT_RO_NORMAL_SUPPORT 0x00000200
/* Result codes for VbSharedDataHeader.check_fw_a_result (and b_result) */
#define VBSD_LF_CHECK_NOT_DONE 0
@@ -204,6 +207,9 @@ typedef struct VbKernelPreambleHeader {
#define VBSD_LF_CHECK_HASH_WRONG_SIZE 10
#define VBSD_LF_CHECK_VERIFY_BODY 11
#define VBSD_LF_CHECK_VALID 12
/* Read-only normal path requested by firmware preamble, but
* unsupported by firmware. */
#define VBSD_LF_CHECK_NO_RO_NORMAL 13
/* Boot mode for VbSharedDataHeader.lk_boot_mode */
#define VBSD_LK_BOOT_MODE_RECOVERY 0

View File

@@ -40,11 +40,6 @@ VbError_t VbSelectFirmware(VbCommonParams* cparams,
p.shared_data_size = cparams->shared_data_size;
p.nv_context = &vnc;
/* TODO: LoadFirmware() should use VbSharedDataHeader.flags directly. */
p.boot_flags = 0;
if (shared->flags & VBSD_BOOT_DEV_SWITCH_ON)
p.boot_flags |= BOOT_FLAG_DEVELOPER;
p.verification_block_0 = fparams->verification_block_A;
p.verification_block_1 = fparams->verification_block_B;
p.verification_size_0 = fparams->verification_size_A;
@@ -75,8 +70,10 @@ VbError_t VbSelectFirmware(VbCommonParams* cparams,
/* Translate return codes */
if (LOAD_FIRMWARE_SUCCESS == rv) {
/* Found good firmware in either A or B */
if (0 == p.firmware_index)
if (shared->flags & VBSD_LF_USE_RO_NORMAL) {
/* Request the read-only normal/dev code path */
fparams->selected_firmware = VB_SELECT_FIRMWARE_READONLY;
} else if (0 == shared->firmware_index)
fparams->selected_firmware = VB_SELECT_FIRMWARE_A;
else
fparams->selected_firmware = VB_SELECT_FIRMWARE_B;

View File

@@ -49,6 +49,8 @@ VbError_t VbInit(VbCommonParams* cparams, VbInitParams* iparams) {
shared->flags |= VBSD_BOOT_FIRMWARE_WP_ENABLED;
if (iparams->flags & VB_INIT_FLAG_S3_RESUME)
shared->flags |= VBSD_BOOT_S3_RESUME;
if (iparams->flags & VB_INIT_FLAG_RO_NORMAL_SUPPORT)
shared->flags |= VBSD_BOOT_RO_NORMAL_SUPPORT;
is_s3_resume = (iparams->flags & VB_INIT_FLAG_S3_RESUME ? 1 : 0);

View File

@@ -57,7 +57,7 @@ int LoadFirmware(LoadFirmwareParams* params) {
int recovery = VBNV_RECOVERY_RO_UNSPECIFIED;
/* Clear output params in case we fail */
params->firmware_index = 0;
shared->firmware_index = 0xFF;
VBDEBUG(("LoadFirmware started...\n"));
@@ -93,7 +93,7 @@ int LoadFirmware(LoadFirmwareParams* params) {
root_key = (VbPublicKey*)((uint8_t*)gbb + gbb->rootkey_offset);
/* Parse flags */
is_dev = (params->boot_flags & BOOT_FLAG_DEVELOPER ? 1 : 0);
is_dev = (shared->flags & VBSD_BOOT_DEV_SWITCH_ON ? 1 : 0);
if (is_dev)
shared->flags |= VBSD_LF_DEV_SWITCH_ON;
@@ -231,6 +231,21 @@ int LoadFirmware(LoadFirmwareParams* params) {
if (-1 != good_index)
continue;
/* Handle preamble flag for using the RO normal/dev code path */
if (VbGetFirmwarePreambleFlags(preamble) &
VB_FIRMWARE_PREAMBLE_USE_RO_NORMAL) {
/* Fail if calling firmware doesn't support RO normal */
if (!(shared->flags & VBSD_BOOT_RO_NORMAL_SUPPORT)) {
*check_result = VBSD_LF_CHECK_NO_RO_NORMAL;
RSAPublicKeyFree(data_key);
continue;
}
/* Indicate that we should use the RO normal code path */
shared->flags |= VBSD_LF_USE_RO_NORMAL;
} else {
/* Read the firmware data */
VBPERFSTART("VB_RFD");
DigestInit(&lfi->body_digest_context, data_key->algorithm);
@@ -264,11 +279,12 @@ int LoadFirmware(LoadFirmwareParams* params) {
VBPERFEND("VB_VFD");
continue;
}
VBPERFEND("VB_VFD");
/* Done with the digest and data key, so can free them now */
RSAPublicKeyFree(data_key);
VbExFree(body_digest);
VBPERFEND("VB_VFD");
}
/* Done with the data key, so can free it now */
RSAPublicKeyFree(data_key);
/* If we're still here, the firmware is valid. */
VBDEBUG(("Firmware %d is valid.\n", index));
@@ -284,7 +300,7 @@ int LoadFirmware(LoadFirmwareParams* params) {
/* Save the good index, now that we're sure we can actually use
* this firmware. That's the one we'll boot. */
good_index = index;
params->firmware_index = index;
shared->firmware_index = index;
/* Since we now know which firmware to boot, we can update the
* bootable firmware key block mode. */
boot_fw_keyblock_flags = key_block->key_block_flags;
@@ -349,8 +365,7 @@ int LoadFirmware(LoadFirmwareParams* params) {
}
/* Success */
VBDEBUG(("Will boot firmware index %d\n", (int)params->firmware_index));
shared->firmware_index = (uint8_t)params->firmware_index;
VBDEBUG(("Will boot firmware index %d\n", (int)shared->firmware->index));
retval = LOAD_FIRMWARE_SUCCESS;
} else {
uint8_t a = shared->check_fw_a_result;

View File

@@ -189,10 +189,12 @@ int DriveLoadFirmware(const void* base_of_rom, const void* fmap,
lfp.shared_data_blob = malloc(VB_SHARED_DATA_MIN_SIZE);
lfp.shared_data_size = VB_SHARED_DATA_MIN_SIZE;
printf("shared data size 0x%08" PRIx64 "\n", lfp.shared_data_size);
lfp.boot_flags = boot_flags;
printf("boot flags is 0x%08" PRIx64 "\n", lfp.boot_flags);
printf("shared data size 0x%08" PRIx32 "\n", lfp.shared_data_size);
/* TODO: load_firmware_test was broken in the wrapper API rewrite.
* Nothing uses it, so we haven't noticed yet. Need to fix it. See
* crosbug.com/17564. LoadFirmware() now assumes that VbInit() has
* been called to set up the shared data structure, but that isn't
* happening here. */
status = LoadFirmware(&lfp);
status_str = status_string(status);
@@ -200,8 +202,6 @@ int DriveLoadFirmware(const void* base_of_rom, const void* fmap,
printf("LoadFirmware returns %s\n", status_str);
else
printf("LoadFirmware returns unknown status code: %d\n", status);
if (status == LOAD_FIRMWARE_SUCCESS)
printf("firmwiare index is %" PRIu64 "\n", lfp.firmware_index);
free(lfp.shared_data_blob);