summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRandall Spangler <rspangler@chromium.org>2011-07-13 16:31:08 -0700
committerRandall Spangler <rspangler@chromium.org>2011-07-14 17:07:10 -0700
commit8bf0d5ff0ff77aaf496507bbe8d65a5f3027c80c (patch)
tree326c2e1495b7c82946a9faba33d93c012a6c7c96
parent3a6e2f10b279b9b285ae4b832d2df92a05dacd52 (diff)
downloadvboot-8bf0d5ff0ff77aaf496507bbe8d65a5f3027c80c.tar.gz
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>
-rw-r--r--firmware/include/load_firmware_fw.h10
-rw-r--r--firmware/include/vboot_api.h8
-rw-r--r--firmware/include/vboot_struct.h8
-rw-r--r--firmware/lib/vboot_api_firmware.c11
-rw-r--r--firmware/lib/vboot_api_init.c2
-rw-r--r--firmware/lib/vboot_firmware.c89
-rw-r--r--utility/load_firmware_test.c12
7 files changed, 78 insertions, 62 deletions
diff --git a/firmware/include/load_firmware_fw.h b/firmware/include/load_firmware_fw.h
index 98beabd3..8f0f20db 100644
--- a/firmware/include/load_firmware_fw.h
+++ b/firmware/include/load_firmware_fw.h
@@ -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;
diff --git a/firmware/include/vboot_api.h b/firmware/include/vboot_api.h
index a97f0e8f..55a0332c 100644
--- a/firmware/include/vboot_api.h
+++ b/firmware/include/vboot_api.h
@@ -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;
diff --git a/firmware/include/vboot_struct.h b/firmware/include/vboot_struct.h
index dd6a4155..408ca2fe 100644
--- a/firmware/include/vboot_struct.h
+++ b/firmware/include/vboot_struct.h
@@ -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
diff --git a/firmware/lib/vboot_api_firmware.c b/firmware/lib/vboot_api_firmware.c
index e4e4af02..091d6dd1 100644
--- a/firmware/lib/vboot_api_firmware.c
+++ b/firmware/lib/vboot_api_firmware.c
@@ -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;
diff --git a/firmware/lib/vboot_api_init.c b/firmware/lib/vboot_api_init.c
index 890b5768..df831291 100644
--- a/firmware/lib/vboot_api_init.c
+++ b/firmware/lib/vboot_api_init.c
@@ -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);
diff --git a/firmware/lib/vboot_firmware.c b/firmware/lib/vboot_firmware.c
index 1e989a4d..da8ef553 100644
--- a/firmware/lib/vboot_firmware.c
+++ b/firmware/lib/vboot_firmware.c
@@ -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,44 +231,60 @@ int LoadFirmware(LoadFirmwareParams* params) {
if (-1 != good_index)
continue;
- /* 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);
+ /* 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);
+ 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");
- 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);
+
+ /* 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);
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);
- VbExFree(body_digest);
/* 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;
diff --git a/utility/load_firmware_test.c b/utility/load_firmware_test.c
index 872bb4ca..5b5bd9f7 100644
--- a/utility/load_firmware_test.c
+++ b/utility/load_firmware_test.c
@@ -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);