mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2025-11-23 17:55:01 +00:00
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:
@@ -20,9 +20,6 @@
|
|||||||
* VbNvContext (VBNV_RECOVERY_REQUEST). */
|
* VbNvContext (VBNV_RECOVERY_REQUEST). */
|
||||||
#define LOAD_FIRMWARE_REBOOT 2 /* Reboot to same mode as current boot */
|
#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 {
|
typedef struct LoadFirmwareParams {
|
||||||
/* Inputs to LoadFirmware() */
|
/* Inputs to LoadFirmware() */
|
||||||
void* gbb_data; /* Pointer to GBB data */
|
void* gbb_data; /* Pointer to GBB data */
|
||||||
@@ -38,13 +35,12 @@ typedef struct LoadFirmwareParams {
|
|||||||
void* shared_data_blob; /* Shared data blob buffer. Pass this
|
void* shared_data_blob; /* Shared data blob buffer. Pass this
|
||||||
* data to LoadKernel() in
|
* data to LoadKernel() in
|
||||||
* LoadKernelParams.shared_data_blob. */
|
* 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
|
* buffer, in bytes. On output, this will
|
||||||
* contain the actual data size placed into
|
* contain the actual data size placed into
|
||||||
* the buffer. Caller need only pass that
|
* the buffer. Caller need only pass that
|
||||||
* much data to LoadKernel().*/
|
* much data to LoadKernel().*/
|
||||||
|
|
||||||
uint64_t boot_flags; /* Boot flags */
|
|
||||||
VbNvContext* nv_context; /* Context for NV storage. nv_context->raw
|
VbNvContext* nv_context; /* Context for NV storage. nv_context->raw
|
||||||
* must be filled before calling
|
* must be filled before calling
|
||||||
* LoadFirmware(). On output, check
|
* LoadFirmware(). On output, check
|
||||||
@@ -52,10 +48,6 @@ typedef struct LoadFirmwareParams {
|
|||||||
* nv_context->raw has been modified and
|
* nv_context->raw has been modified and
|
||||||
* needs saving. */
|
* 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(). */
|
/* Internal data for LoadFirmware() / UpdateFirmwareBodyHash(). */
|
||||||
void* load_firmware_internal;
|
void* load_firmware_internal;
|
||||||
|
|
||||||
|
|||||||
@@ -100,6 +100,9 @@ typedef struct VbCommonParams {
|
|||||||
/* TODO: add a field to VbInitParams which holds a reason code, and report
|
/* TODO: add a field to VbInitParams which holds a reason code, and report
|
||||||
* that via VbSharedData. */
|
* that via VbSharedData. */
|
||||||
#define VB_INIT_FLAG_PREVIOUS_BOOT_FAIL 0x00000010
|
#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
|
/* Output flags for VbInitParams.out_flags. Used to indicate
|
||||||
* potential boot paths and configuration to the calling firmware
|
* 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 */
|
/* Rewritable firmware A/B for normal or developer path */
|
||||||
VB_SELECT_FIRMWARE_A = 1,
|
VB_SELECT_FIRMWARE_A = 1,
|
||||||
VB_SELECT_FIRMWARE_B = 2,
|
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
|
VB_SELECT_FIRMWARE_READONLY = 3
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -157,7 +160,8 @@ typedef struct VbSelectFirmwareParams {
|
|||||||
uint32_t verification_size_B; /* Verification block B size in bytes */
|
uint32_t verification_size_B; /* Verification block B size in bytes */
|
||||||
|
|
||||||
/* Outputs from VbSelectFirmware(); valid only if it returns success. */
|
/* 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;
|
} VbSelectFirmwareParams;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -180,6 +180,8 @@ typedef struct VbKernelPreambleHeader {
|
|||||||
#define VBSD_KERNEL_KEY_VERIFIED 0x00000002
|
#define VBSD_KERNEL_KEY_VERIFIED 0x00000002
|
||||||
/* LoadFirmware() was told the developer switch was on */
|
/* LoadFirmware() was told the developer switch was on */
|
||||||
#define VBSD_LF_DEV_SWITCH_ON 0x00000004
|
#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 */
|
/* Developer switch was enabled at boot time */
|
||||||
#define VBSD_BOOT_DEV_SWITCH_ON 0x00000010
|
#define VBSD_BOOT_DEV_SWITCH_ON 0x00000010
|
||||||
/* Recovery switch was enabled at boot time */
|
/* Recovery switch was enabled at boot time */
|
||||||
@@ -188,7 +190,8 @@ typedef struct VbKernelPreambleHeader {
|
|||||||
#define VBSD_BOOT_FIRMWARE_WP_ENABLED 0x00000040
|
#define VBSD_BOOT_FIRMWARE_WP_ENABLED 0x00000040
|
||||||
/* Boot is a S3->S0 resume, not a S5->S0 normal boot */
|
/* Boot is a S3->S0 resume, not a S5->S0 normal boot */
|
||||||
#define VBSD_BOOT_S3_RESUME 0x00000100
|
#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) */
|
/* Result codes for VbSharedDataHeader.check_fw_a_result (and b_result) */
|
||||||
#define VBSD_LF_CHECK_NOT_DONE 0
|
#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_HASH_WRONG_SIZE 10
|
||||||
#define VBSD_LF_CHECK_VERIFY_BODY 11
|
#define VBSD_LF_CHECK_VERIFY_BODY 11
|
||||||
#define VBSD_LF_CHECK_VALID 12
|
#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 */
|
/* Boot mode for VbSharedDataHeader.lk_boot_mode */
|
||||||
#define VBSD_LK_BOOT_MODE_RECOVERY 0
|
#define VBSD_LK_BOOT_MODE_RECOVERY 0
|
||||||
|
|||||||
@@ -40,11 +40,6 @@ VbError_t VbSelectFirmware(VbCommonParams* cparams,
|
|||||||
p.shared_data_size = cparams->shared_data_size;
|
p.shared_data_size = cparams->shared_data_size;
|
||||||
p.nv_context = &vnc;
|
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_0 = fparams->verification_block_A;
|
||||||
p.verification_block_1 = fparams->verification_block_B;
|
p.verification_block_1 = fparams->verification_block_B;
|
||||||
p.verification_size_0 = fparams->verification_size_A;
|
p.verification_size_0 = fparams->verification_size_A;
|
||||||
@@ -75,8 +70,10 @@ VbError_t VbSelectFirmware(VbCommonParams* cparams,
|
|||||||
|
|
||||||
/* Translate return codes */
|
/* Translate return codes */
|
||||||
if (LOAD_FIRMWARE_SUCCESS == rv) {
|
if (LOAD_FIRMWARE_SUCCESS == rv) {
|
||||||
/* Found good firmware in either A or B */
|
if (shared->flags & VBSD_LF_USE_RO_NORMAL) {
|
||||||
if (0 == p.firmware_index)
|
/* 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;
|
fparams->selected_firmware = VB_SELECT_FIRMWARE_A;
|
||||||
else
|
else
|
||||||
fparams->selected_firmware = VB_SELECT_FIRMWARE_B;
|
fparams->selected_firmware = VB_SELECT_FIRMWARE_B;
|
||||||
|
|||||||
@@ -49,6 +49,8 @@ VbError_t VbInit(VbCommonParams* cparams, VbInitParams* iparams) {
|
|||||||
shared->flags |= VBSD_BOOT_FIRMWARE_WP_ENABLED;
|
shared->flags |= VBSD_BOOT_FIRMWARE_WP_ENABLED;
|
||||||
if (iparams->flags & VB_INIT_FLAG_S3_RESUME)
|
if (iparams->flags & VB_INIT_FLAG_S3_RESUME)
|
||||||
shared->flags |= VBSD_BOOT_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);
|
is_s3_resume = (iparams->flags & VB_INIT_FLAG_S3_RESUME ? 1 : 0);
|
||||||
|
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ int LoadFirmware(LoadFirmwareParams* params) {
|
|||||||
int recovery = VBNV_RECOVERY_RO_UNSPECIFIED;
|
int recovery = VBNV_RECOVERY_RO_UNSPECIFIED;
|
||||||
|
|
||||||
/* Clear output params in case we fail */
|
/* Clear output params in case we fail */
|
||||||
params->firmware_index = 0;
|
shared->firmware_index = 0xFF;
|
||||||
|
|
||||||
VBDEBUG(("LoadFirmware started...\n"));
|
VBDEBUG(("LoadFirmware started...\n"));
|
||||||
|
|
||||||
@@ -93,7 +93,7 @@ int LoadFirmware(LoadFirmwareParams* params) {
|
|||||||
root_key = (VbPublicKey*)((uint8_t*)gbb + gbb->rootkey_offset);
|
root_key = (VbPublicKey*)((uint8_t*)gbb + gbb->rootkey_offset);
|
||||||
|
|
||||||
/* Parse flags */
|
/* 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)
|
if (is_dev)
|
||||||
shared->flags |= VBSD_LF_DEV_SWITCH_ON;
|
shared->flags |= VBSD_LF_DEV_SWITCH_ON;
|
||||||
|
|
||||||
@@ -231,44 +231,60 @@ int LoadFirmware(LoadFirmwareParams* params) {
|
|||||||
if (-1 != good_index)
|
if (-1 != good_index)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* Read the firmware data */
|
/* Handle preamble flag for using the RO normal/dev code path */
|
||||||
VBPERFSTART("VB_RFD");
|
if (VbGetFirmwarePreambleFlags(preamble) &
|
||||||
DigestInit(&lfi->body_digest_context, data_key->algorithm);
|
VB_FIRMWARE_PREAMBLE_USE_RO_NORMAL) {
|
||||||
lfi->body_size_accum = 0;
|
|
||||||
if (0 != GetFirmwareBody(params, index)) {
|
|
||||||
VBDEBUG(("GetFirmwareBody() failed for index %d\n", index));
|
|
||||||
*check_result = VBSD_LF_CHECK_GET_FW_BODY;
|
|
||||||
RSAPublicKeyFree(data_key);
|
|
||||||
VBPERFEND("VB_RFD");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (lfi->body_size_accum != preamble->body_signature.data_size) {
|
|
||||||
VBDEBUG(("Hash updated %d bytes but expected %d\n",
|
|
||||||
(int)lfi->body_size_accum,
|
|
||||||
(int)preamble->body_signature.data_size));
|
|
||||||
*check_result = VBSD_LF_CHECK_HASH_WRONG_SIZE;
|
|
||||||
RSAPublicKeyFree(data_key);
|
|
||||||
VBPERFEND("VB_RFD");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
VBPERFEND("VB_RFD");
|
|
||||||
|
|
||||||
/* Verify firmware data */
|
/* Fail if calling firmware doesn't support RO normal */
|
||||||
VBPERFSTART("VB_VFD");
|
if (!(shared->flags & VBSD_BOOT_RO_NORMAL_SUPPORT)) {
|
||||||
body_digest = DigestFinal(&lfi->body_digest_context);
|
*check_result = VBSD_LF_CHECK_NO_RO_NORMAL;
|
||||||
if (0 != VerifyDigest(body_digest, &preamble->body_signature, data_key)) {
|
RSAPublicKeyFree(data_key);
|
||||||
VBDEBUG(("Firmware body verification failed.\n"));
|
continue;
|
||||||
*check_result = VBSD_LF_CHECK_VERIFY_BODY;
|
}
|
||||||
RSAPublicKeyFree(data_key);
|
|
||||||
|
/* 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);
|
||||||
|
lfi->body_size_accum = 0;
|
||||||
|
if (0 != GetFirmwareBody(params, index)) {
|
||||||
|
VBDEBUG(("GetFirmwareBody() failed for index %d\n", index));
|
||||||
|
*check_result = VBSD_LF_CHECK_GET_FW_BODY;
|
||||||
|
RSAPublicKeyFree(data_key);
|
||||||
|
VBPERFEND("VB_RFD");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (lfi->body_size_accum != preamble->body_signature.data_size) {
|
||||||
|
VBDEBUG(("Hash updated %d bytes but expected %d\n",
|
||||||
|
(int)lfi->body_size_accum,
|
||||||
|
(int)preamble->body_signature.data_size));
|
||||||
|
*check_result = VBSD_LF_CHECK_HASH_WRONG_SIZE;
|
||||||
|
RSAPublicKeyFree(data_key);
|
||||||
|
VBPERFEND("VB_RFD");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
VBPERFEND("VB_RFD");
|
||||||
|
|
||||||
|
/* Verify firmware data */
|
||||||
|
VBPERFSTART("VB_VFD");
|
||||||
|
body_digest = DigestFinal(&lfi->body_digest_context);
|
||||||
|
if (0 != VerifyDigest(body_digest, &preamble->body_signature, data_key)) {
|
||||||
|
VBDEBUG(("Firmware body verification failed.\n"));
|
||||||
|
*check_result = VBSD_LF_CHECK_VERIFY_BODY;
|
||||||
|
RSAPublicKeyFree(data_key);
|
||||||
|
VbExFree(body_digest);
|
||||||
|
VBPERFEND("VB_VFD");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
VbExFree(body_digest);
|
VbExFree(body_digest);
|
||||||
VBPERFEND("VB_VFD");
|
VBPERFEND("VB_VFD");
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
VBPERFEND("VB_VFD");
|
|
||||||
|
|
||||||
/* Done with the digest and data key, so can free them now */
|
/* Done with the data key, so can free it now */
|
||||||
RSAPublicKeyFree(data_key);
|
RSAPublicKeyFree(data_key);
|
||||||
VbExFree(body_digest);
|
|
||||||
|
|
||||||
/* If we're still here, the firmware is valid. */
|
/* If we're still here, the firmware is valid. */
|
||||||
VBDEBUG(("Firmware %d is valid.\n", index));
|
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
|
/* Save the good index, now that we're sure we can actually use
|
||||||
* this firmware. That's the one we'll boot. */
|
* this firmware. That's the one we'll boot. */
|
||||||
good_index = index;
|
good_index = index;
|
||||||
params->firmware_index = index;
|
shared->firmware_index = index;
|
||||||
/* Since we now know which firmware to boot, we can update the
|
/* Since we now know which firmware to boot, we can update the
|
||||||
* bootable firmware key block mode. */
|
* bootable firmware key block mode. */
|
||||||
boot_fw_keyblock_flags = key_block->key_block_flags;
|
boot_fw_keyblock_flags = key_block->key_block_flags;
|
||||||
@@ -349,8 +365,7 @@ int LoadFirmware(LoadFirmwareParams* params) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Success */
|
/* Success */
|
||||||
VBDEBUG(("Will boot firmware index %d\n", (int)params->firmware_index));
|
VBDEBUG(("Will boot firmware index %d\n", (int)shared->firmware->index));
|
||||||
shared->firmware_index = (uint8_t)params->firmware_index;
|
|
||||||
retval = LOAD_FIRMWARE_SUCCESS;
|
retval = LOAD_FIRMWARE_SUCCESS;
|
||||||
} else {
|
} else {
|
||||||
uint8_t a = shared->check_fw_a_result;
|
uint8_t a = shared->check_fw_a_result;
|
||||||
|
|||||||
@@ -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_blob = malloc(VB_SHARED_DATA_MIN_SIZE);
|
||||||
lfp.shared_data_size = 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);
|
printf("shared data size 0x%08" PRIx32 "\n", lfp.shared_data_size);
|
||||||
|
/* TODO: load_firmware_test was broken in the wrapper API rewrite.
|
||||||
lfp.boot_flags = boot_flags;
|
* Nothing uses it, so we haven't noticed yet. Need to fix it. See
|
||||||
printf("boot flags is 0x%08" PRIx64 "\n", lfp.boot_flags);
|
* 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 = LoadFirmware(&lfp);
|
||||||
status_str = status_string(status);
|
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);
|
printf("LoadFirmware returns %s\n", status_str);
|
||||||
else
|
else
|
||||||
printf("LoadFirmware returns unknown status code: %d\n", status);
|
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);
|
free(lfp.shared_data_blob);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user