summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRandall Spangler <rspangler@chromium.org>2011-03-09 15:54:16 -0800
committerRandall Spangler <rspangler@chromium.org>2011-03-09 15:54:16 -0800
commit95c4031ce903258036beeed0705d25c7e9d25da0 (patch)
tree953d53685e331c4f36dcfb0115137a0fec0abc7b
parentc324fbfb6d37aa62b0e6e2f22dae7c949896ddef (diff)
downloadvboot-95c4031ce903258036beeed0705d25c7e9d25da0.tar.gz
This is necessary to pass additional information about whether firmware A or B is being run. This change also passes the GBB directly into LoadFirmware() and LoadKernel().
Change-Id: I976c11c82c3d665a4feb88226e919f16c2440f60 BUG=chrome-os-partner:1657 TEST=manual - see below make && make runtests Then test verifying a test image in both dev mode (-b1, no key specified) and recovery mode (key specified) build/utility/load_kernel_test -b1 ~/b/USB_images/0.11.224.0-alex/chromiumos_test_image.bin build/utility/load_kernel_test ~/b/USB_images/0.11.224.0-alex/chromiumos_test_image.bin tests/devkeys/recovery_key.vbpubk And make sure the firmware with this change actually boots to USB and SSD. NOTE: u-boot-next needs to change to work with this change. will attempt a follow-up CL with that change Review URL: http://codereview.chromium.org/6626045
-rw-r--r--firmware/include/load_firmware_fw.h30
-rw-r--r--firmware/include/load_kernel_fw.h12
-rw-r--r--firmware/include/vboot_nvstorage.h4
-rw-r--r--firmware/include/vboot_struct.h45
-rw-r--r--firmware/lib/include/vboot_common.h17
-rw-r--r--firmware/lib/vboot_common.c67
-rw-r--r--firmware/lib/vboot_firmware.c39
-rw-r--r--firmware/lib/vboot_kernel.c28
-rw-r--r--firmware/linktest/main.c3
-rw-r--r--firmware/stub/load_firmware_stub.c16
-rw-r--r--utility/load_firmware_test.c34
-rw-r--r--utility/load_kernel_test.c54
12 files changed, 278 insertions, 71 deletions
diff --git a/firmware/include/load_firmware_fw.h b/firmware/include/load_firmware_fw.h
index 271063d7..1e42f1c9 100644
--- a/firmware/include/load_firmware_fw.h
+++ b/firmware/include/load_firmware_fw.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011 The Chromium OS Authors. All rights reserved.
+/* Copyright (c) 2011 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.
*
@@ -12,10 +12,8 @@
#include "sysincludes.h"
#include "vboot_nvstorage.h"
-/* Recommended size of kernel_sign_key_blob in bytes, for
- * implementations which must preallocate a transfer buffer between
- * boot phases */
-#define LOAD_FIRMWARE_KEY_BLOB_REC_SIZE 2104
+/* Recommended size of shared_data_blob in bytes. */
+#define LOAD_FIRMWARE_SHARED_DATA_REC_SIZE 16384
/* Return codes for LoadFirmware() and S3Resume(). */
#define LOAD_FIRMWARE_SUCCESS 0 /* Success */
@@ -29,19 +27,21 @@
typedef struct LoadFirmwareParams {
/* Inputs to LoadFirmware() */
- void *firmware_root_key_blob; /* Key used to sign firmware header */
- void *verification_block_0; /* Key block + preamble for firmware 0 */
- void *verification_block_1; /* Key block + preamble for firmware 1 */
+ void* gbb_data; /* Pointer to GBB data */
+ uint64_t gbb_size; /* Size of GBB data in bytes */
+ void* verification_block_0; /* Key block + preamble for firmware 0 */
+ void* verification_block_1; /* Key block + preamble for firmware 1 */
uint64_t verification_size_0; /* Verification block 0 size in bytes */
uint64_t verification_size_1; /* Verification block 1 size in bytes */
- void *kernel_sign_key_blob; /* Destination buffer for key to use
- * when loading kernel. Pass this
+ void* shared_data_blob; /* Destination buffer for data shared between
+ * LoadFirmware() and LoadKernel(). Pass this
* data to LoadKernel() in
- * LoadKernelParams.header_sign_key_blob. */
- uint64_t kernel_sign_key_size; /* Size of kernel signing key blob
- * buffer, in bytes. On output, this
- * will contain the actual key blob
- * size placed into the buffer. */
+ * LoadKernelParams.shared_data_blob. */
+ uint64_t shared_data_size; /* 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 this 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
diff --git a/firmware/include/load_kernel_fw.h b/firmware/include/load_kernel_fw.h
index 45d18e2c..5815abfc 100644
--- a/firmware/include/load_kernel_fw.h
+++ b/firmware/include/load_kernel_fw.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011 The Chromium OS Authors. All rights reserved.
+/* Copyright (c) 2011 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.
*
@@ -34,7 +34,15 @@
typedef struct LoadKernelParams {
/* Inputs to LoadKernel() */
- void* header_sign_key_blob; /* Key blob used to sign the kernel header */
+ void* shared_data_blob; /* Buffer for data shared between
+ * LoadFirmware() and LoadKernel(). Pass the
+ * same buffer which was passed to
+ * LoadFirmware(). */
+ uint64_t shared_data_size; /* Size of shared data blob buffer, in bytes.
+ * On output, this will contain the actual
+ * data size placed into the buffer. */
+ void* gbb_data; /* Pointer to GBB data */
+ uint64_t gbb_size; /* Size of GBB data in bytes */
uint64_t bytes_per_lba; /* Bytes per lba sector on current device */
uint64_t ending_lba; /* Last addressable lba sector on current
* device */
diff --git a/firmware/include/vboot_nvstorage.h b/firmware/include/vboot_nvstorage.h
index 5ae40b4b..824dfac5 100644
--- a/firmware/include/vboot_nvstorage.h
+++ b/firmware/include/vboot_nvstorage.h
@@ -74,6 +74,8 @@ typedef enum VbNvParam {
#define VBNV_RECOVERY_RO_S3_RESUME 0x04
/* TPM error in read-only firmware */
#define VBNV_RECOVERY_RO_TPM_ERROR 0x05
+/* Shared data error in read-only firmware */
+#define VBNV_RECOVERY_RO_SHARED_DATA 0x06
/* Unspecified/unknown error in read-only firmware */
#define VBNV_RECOVERY_RO_UNSPECIFIED 0x3F
/* User manually requested recovery by pressing a key at developer
@@ -87,6 +89,8 @@ typedef enum VbNvParam {
#define VBNV_RECOVERY_RW_TPM_ERROR 0x44
/* RW firmware in dev mode, but dev switch is off */
#define VBNV_RECOVERY_RW_DEV_MISMATCH 0x45
+/* Shared data error in rewritable firmware */
+#define VBNV_RECOVERY_RW_SHARED_DATA 0x46
/* Unspecified/unknown error in rewritable firmware */
#define VBNV_RECOVERY_RW_UNSPECIFIED 0x7F
/* DM-verity error */
diff --git a/firmware/include/vboot_struct.h b/firmware/include/vboot_struct.h
index ed83f3e7..1e988ee1 100644
--- a/firmware/include/vboot_struct.h
+++ b/firmware/include/vboot_struct.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011 The Chromium OS Authors. All rights reserved.
+/* Copyright (c) 2011 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.
*
@@ -131,6 +131,49 @@ typedef struct VbKernelPreambleHeader {
#define EXPECTED_VBKERNELPREAMBLEHEADER_SIZE 96
+/* Minimum and recommended size of shared_data_blob in bytes. */
+#define VB_SHARED_DATA_MIN_SIZE 3072
+#define VB_SHARED_DATA_REC_SIZE 16384
+
+/* Data shared between LoadFirmware(), LoadKernel(), and OS.
+ *
+ * The boot process is:
+ * 1) Caller allocates buffer, at least VB_SHARED_DATA_MIN bytes, ideally
+ * VB_SHARED_DATA_REC_SIZE bytes.
+ * 2) If non-recovery boot, this is passed to LoadFirmware(), which
+ * initializes the buffer, adding this header and some data.
+ * 3) Buffer is passed to LoadKernel(). If this is a recovery boot,
+ * LoadKernel() initializes the buffer, adding this header. Regardless
+ * of boot type, LoadKernel() adds some data to the buffer.
+ * 4) Caller makes data available to the OS in a platform-dependent manner.
+ * For example, via ACPI or ATAGs. */
+typedef struct VbSharedDataHeader {
+ /* Fields present in version 1 */
+ uint32_t struct_version; /* Version of this structure */
+ uint64_t struct_size; /* Size of this structure in bytes */
+ uint64_t data_size; /* Size of shared data buffer in bytes */
+ uint64_t data_used; /* Amount of shared data used so far */
+
+ VbPublicKey kernel_subkey; /* Kernel subkey, from firmware */
+ uint64_t kernel_subkey_data_offset; /* Offset of kernel subkey data from
+ * start of this struct */
+ uint64_t kernel_subkey_data_size; /* Offset of kernel subkey data */
+
+ uint64_t flags; /* Flags */
+
+ /* After read-only firmware which uses version 1 is released, any additional
+ * fields must be added below, and the struct version must be increased.
+ * Before reading/writing those fields, make sure that the struct being
+ * accessed is at least version 2.
+ *
+ * It's always ok for an older firmware to access a newer struct, since all
+ * the fields it knows about are present. Newer firmware needs to use
+ * reasonable defaults when accessing older structs. */
+
+} __attribute__((packed)) VbSharedDataHeader;
+
+#define VB_SHARED_DATA_VERSION 1 /* Version for struct_version */
+
__pragma(pack(pop)) /* Support packing for MSVC. */
#endif /* VBOOT_REFERENCE_VBOOT_STRUCT_H_ */
diff --git a/firmware/lib/include/vboot_common.h b/firmware/lib/include/vboot_common.h
index 5951286c..ea172af3 100644
--- a/firmware/lib/include/vboot_common.h
+++ b/firmware/lib/include/vboot_common.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
+/* Copyright (c) 2011 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.
*
@@ -23,6 +23,7 @@ enum {
VBOOT_PREAMBLE_INVALID, /* Preamble internal structure is
* invalid */
VBOOT_PREAMBLE_SIGNATURE, /* Preamble signature check failed */
+ VBOOT_SHARED_DATA_INVALID, /* Shared data is invalid. */
VBOOT_ERROR_MAX,
};
extern char* kVbootErrors[VBOOT_ERROR_MAX];
@@ -107,6 +108,20 @@ int VerifyKernelPreamble(const VbKernelPreambleHeader* preamble,
uint64_t size, const RSAPublicKey* key);
+/* Initialize a verified boot shared data structure.
+ *
+ * Returns 0 if success, non-zero if error. */
+int VbSharedDataInit(VbSharedDataHeader* header, uint64_t size);
+
+/* Reserve [size] bytes of the shared data area. Returns the offset of the
+ * reserved data from the start of the shared data buffer, or 0 if error. */
+uint64_t VbSharedDataReserve(VbSharedDataHeader* header, uint64_t size);
+
+/* Copy the kernel subkey into the shared data.
+ *
+ * Returns 0 if success, non-zero if error. */
+int VbSharedDataSetKernelKey(VbSharedDataHeader* header,
+ const VbPublicKey* src);
#endif /* VBOOT_REFERENCE_VBOOT_COMMON_H_ */
diff --git a/firmware/lib/vboot_common.c b/firmware/lib/vboot_common.c
index be76b054..abba130b 100644
--- a/firmware/lib/vboot_common.c
+++ b/firmware/lib/vboot_common.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
+/* Copyright (c) 2011 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.
*
@@ -19,6 +19,7 @@ char* kVbootErrors[VBOOT_ERROR_MAX] = {
"Public key invalid.",
"Preamble invalid.",
"Preamble signature check failed.",
+ "Shared data invalid."
};
@@ -377,3 +378,67 @@ int VerifyKernelPreamble(const VbKernelPreambleHeader* preamble,
/* Success */
return VBOOT_SUCCESS;
}
+
+
+int VbSharedDataInit(VbSharedDataHeader* header, uint64_t size) {
+ if (size < sizeof(VbSharedDataHeader)) {
+ VBDEBUG(("Not enough data for header.\n"));
+ return VBOOT_SHARED_DATA_INVALID;
+ }
+ if (size < VB_SHARED_DATA_MIN_SIZE) {
+ VBDEBUG(("Shared data buffer too small.\n"));
+ return VBOOT_SHARED_DATA_INVALID;
+ }
+
+ if (!header)
+ return VBOOT_SHARED_DATA_INVALID;
+
+ /* Zero the header */
+ Memset(header, 0, sizeof(VbSharedDataHeader));
+
+ /* Initialize fields */
+ header->struct_version = VB_SHARED_DATA_VERSION;
+ header->struct_size = sizeof(VbSharedDataHeader);
+ header->data_size = size;
+ header->data_used = sizeof(VbSharedDataHeader);
+
+ /* Success */
+ return VBOOT_SUCCESS;
+}
+
+
+uint64_t VbSharedDataReserve(VbSharedDataHeader* header, uint64_t size) {
+ uint64_t offs = header->data_used;
+
+ if (!header || size > header->data_size - header->data_used) {
+ VBDEBUG(("VbSharedData buffer out of space.\n"));
+ return 0; /* Not initialized, or not enough space left. */
+ }
+ header->data_used += size;
+ return offs;
+}
+
+
+int VbSharedDataSetKernelKey(VbSharedDataHeader* header,
+ const VbPublicKey* src) {
+
+ VbPublicKey *kdest = &header->kernel_subkey;
+
+ if (!header)
+ return VBOOT_SHARED_DATA_INVALID;
+
+ /* Attempt to allocate space for the key, if it hasn't been allocated yet */
+ if (!header->kernel_subkey_data_offset) {
+ header->kernel_subkey_data_offset = VbSharedDataReserve(header,
+ src->key_size);
+ if (!header->kernel_subkey_data_offset)
+ return VBOOT_SHARED_DATA_INVALID;
+ header->kernel_subkey_data_size = src->key_size;
+ }
+
+ /* Copy the kernel sign key blob into the destination buffer */
+ PublicKeyInit(kdest, (uint8_t*)header + header->kernel_subkey_data_offset,
+ header->kernel_subkey_data_size);
+
+ return PublicKeyCopy(kdest, src);
+}
diff --git a/firmware/lib/vboot_firmware.c b/firmware/lib/vboot_firmware.c
index bbae0952..2f358522 100644
--- a/firmware/lib/vboot_firmware.c
+++ b/firmware/lib/vboot_firmware.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011 The Chromium OS Authors. All rights reserved.
+/* Copyright (c) 2011 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.
*
@@ -6,6 +6,7 @@
* (Firmware portion)
*/
+#include "gbb_header.h"
#include "load_firmware_fw.h"
#include "rollback_index.h"
#include "utility.h"
@@ -39,8 +40,9 @@ int LoadFirmwareSetup(void) {
int LoadFirmware(LoadFirmwareParams* params) {
-
- VbPublicKey* root_key = (VbPublicKey*)params->firmware_root_key_blob;
+ VbSharedDataHeader* shared = (VbSharedDataHeader*)params->shared_data_blob;
+ GoogleBinaryBlockHeader* gbb = (GoogleBinaryBlockHeader*)params->gbb_data;
+ VbPublicKey* root_key;
VbLoadFirmwareInternal* lfi;
VbNvContext* vnc = params->nv_context;
@@ -64,16 +66,19 @@ int LoadFirmware(LoadFirmwareParams* params) {
/* Setup NV storage */
VbNvSetup(vnc);
- if (params->kernel_sign_key_size < sizeof(VbPublicKey)) {
- VBDEBUG(("Kernel sign key buffer too small\n"));
+ /* Initialize shared data structure. */
+ if (0 != VbSharedDataInit(shared, params->shared_data_size)) {
+ VBDEBUG(("Shared data init error\n"));
+ recovery = VBNV_RECOVERY_RO_SHARED_DATA;
goto LoadFirmwareExit;
}
- /* Must have a root key */
- if (!root_key) {
- VBDEBUG(("No root key\n"));
+ /* Must have a root key from the GBB */
+ if (!gbb) {
+ VBDEBUG(("No GBB\n"));
goto LoadFirmwareExit;
}
+ root_key = (VbPublicKey*)((uint8_t*)gbb + gbb->rootkey_offset);
/* Parse flags */
is_dev = (params->boot_flags & BOOT_FLAG_DEVELOPER ? 1 : 0);
@@ -235,21 +240,13 @@ int LoadFirmware(LoadFirmwareParams* params) {
/* If we're still here, the firmware is valid. */
VBDEBUG(("Firmware %d is valid.\n", index));
if (-1 == good_index) {
- VbPublicKey *kdest = (VbPublicKey*)params->kernel_sign_key_blob;
-
- /* Copy the kernel sign key blob into the destination buffer */
- PublicKeyInit(kdest, (uint8_t*)(kdest + 1),
- (params->kernel_sign_key_size - sizeof(VbPublicKey)));
-
- if (0 != PublicKeyCopy(kdest, &preamble->kernel_subkey)) {
- VBDEBUG(("Kernel subkey too big for buffer.\n"));
+ /* Save the key we actually used */
+ if (0 != VbSharedDataSetKernelKey(shared, &preamble->kernel_subkey)) {
+ VBDEBUG(("Unable to save kernel subkey to shared data.\n"));
continue; /* The firmware signature was good, but the public
* key was bigger that the caller can handle. */
}
- /* Save the key size we actually used */
- params->kernel_sign_key_size = kdest->key_offset + kdest->key_size;
-
/* 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;
@@ -314,6 +311,10 @@ LoadFirmwareExit:
recovery : VBNV_RECOVERY_NOT_REQUESTED);
VbNvTeardown(vnc);
+ /* Note that we don't reduce params->shared_data_size to shared->data_used,
+ * since we want to leave space for LoadKernel() to add to the shared data
+ * buffer. */
+
return retval;
}
diff --git a/firmware/lib/vboot_kernel.c b/firmware/lib/vboot_kernel.c
index ea39f7b1..ee2890cf 100644
--- a/firmware/lib/vboot_kernel.c
+++ b/firmware/lib/vboot_kernel.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011 The Chromium OS Authors. All rights reserved.
+/* Copyright (c) 2011 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.
*
@@ -11,6 +11,7 @@
#include "boot_device.h"
#include "cgptlib.h"
#include "cgptlib_internal.h"
+#include "gbb_header.h"
#include "load_kernel_fw.h"
#include "rollback_index.h"
#include "utility.h"
@@ -118,7 +119,9 @@ int WriteAndFreeGptData(GptData* gptdata) {
__pragma(warning(disable: 4127))
int LoadKernel(LoadKernelParams* params) {
+ VbSharedDataHeader* shared = (VbSharedDataHeader*)params->shared_data_blob;
VbNvContext* vnc = params->nv_context;
+ GoogleBinaryBlockHeader* gbb = (GoogleBinaryBlockHeader*)params->gbb_data;
VbPublicKey* kernel_subkey;
GptData gpt;
uint64_t part_start, part_size;
@@ -154,7 +157,6 @@ int LoadKernel(LoadKernelParams* params) {
}
/* Initialization */
- kernel_subkey = (VbPublicKey*)params->header_sign_key_blob;
blba = params->bytes_per_lba;
kbuf_sectors = KBUF_SIZE / blba;
if (0 == kbuf_sectors) {
@@ -187,14 +189,30 @@ int LoadKernel(LoadKernelParams* params) {
params->bootloader_address = 0;
params->bootloader_size = 0;
- /* Let the TPM know if we're in recovery mode */
if (kBootRecovery == boot_mode) {
+ /* Initialize the shared data structure, since LoadFirmware() didn't do it
+ * for us. */
+ if (0 != VbSharedDataInit(shared, params->shared_data_size)) {
+ /* Error initializing the shared data, but we can keep going. We just
+ * can't use the shared data. */
+ VBDEBUG(("Shared data init error\n"));
+ params->shared_data_size = 0;
+ shared = NULL;
+ }
+
+ /* Use the recovery key to verify the kernel */
+ kernel_subkey = (VbPublicKey*)((uint8_t*)gbb + gbb->recovery_key_offset);
+
+ /* Let the TPM know if we're in recovery mode */
if (0 != RollbackKernelRecovery(dev_switch)) {
VBDEBUG(("Error setting up TPM for recovery kernel\n"));
/* Ignore return code, since we need to boot recovery mode to
* fix the TPM. */
}
} else {
+ /* Use the kernel subkey passed from LoadFirmware(). */
+ kernel_subkey = &shared->kernel_subkey;
+
/* Read current kernel key index from TPM. Assumes TPM is already
* initialized. */
status = RollbackKernelRead(&tpm_version);
@@ -505,5 +523,9 @@ LoadKernelExit:
recovery : VBNV_RECOVERY_NOT_REQUESTED);
VbNvTeardown(vnc);
+ /* Store how much shared data we used, if any */
+ if (shared)
+ params->shared_data_size = shared->data_used;
+
return retval;
}
diff --git a/firmware/linktest/main.c b/firmware/linktest/main.c
index b171f195..6f5b83e4 100644
--- a/firmware/linktest/main.c
+++ b/firmware/linktest/main.c
@@ -79,6 +79,9 @@ int main(void)
KeyBlockVerify(0, 0, 0, 0);
VerifyFirmwarePreamble(0, 0, 0);
VerifyKernelPreamble(0, 0, 0);
+ VbSharedDataInit(0, 0);
+ VbSharedDataReserve(0, 0);
+ VbSharedDataSetKernelKey(0, 0);
VbNvSetup(0);
VbNvGet(0, 0, 0);
diff --git a/firmware/stub/load_firmware_stub.c b/firmware/stub/load_firmware_stub.c
index 94d0bfa8..0b0671aa 100644
--- a/firmware/stub/load_firmware_stub.c
+++ b/firmware/stub/load_firmware_stub.c
@@ -63,7 +63,8 @@ int GetFirmwareBody(LoadFirmwareParams* params, uint64_t index) {
* volumes, this call will still be slow. Once we reach feature
* complete, you should modify your code to call LoadImage()
* directly. */
-int VerifyFirmwareDriver_stub(uint8_t* root_key_blob,
+int VerifyFirmwareDriver_stub(uint8_t* gbb_data,
+ uint64_t gbb_size,
uint8_t* verification_headerA,
uint8_t* firmwareA,
uint8_t* verification_headerB,
@@ -91,14 +92,15 @@ int VerifyFirmwareDriver_stub(uint8_t* root_key_blob,
/* Set up the params for LoadFirmware() */
p.caller_internal = &ci;
- p.firmware_root_key_blob = root_key_blob;
+ p.gbb_data = gbb_data;
+ p.gbb_size = gbb_size;
p.verification_block_0 = verification_headerA;
p.verification_block_1 = verification_headerB;
p.nv_context = &vnc;
- /* Allocate a key blob buffer */
- p.kernel_sign_key_blob = Malloc(LOAD_FIRMWARE_KEY_BLOB_REC_SIZE);
- p.kernel_sign_key_size = LOAD_FIRMWARE_KEY_BLOB_REC_SIZE;
+ /* Allocate a shared data buffer */
+ p.shared_data_blob = Malloc(LOAD_FIRMWARE_SHARED_DATA_REC_SIZE);
+ p.shared_data_size = LOAD_FIRMWARE_SHARED_DATA_REC_SIZE;
/* TODO: YOU NEED TO SET THE BOOT FLAGS SOMEHOW */
p.boot_flags = 0;
@@ -111,8 +113,8 @@ int VerifyFirmwareDriver_stub(uint8_t* root_key_blob,
}
if (LOAD_FIRMWARE_SUCCESS == rv) {
- /* TODO: YOU NEED TO KEEP TRACK OF p.kernel_sign_key_blob AND
- * p.kernel_sign_key_size SO YOU CAN PASS THEM TO LoadKernel(). */
+ /* TODO: YOU NEED TO KEEP TRACK OF p.shared_data_blob AND
+ * p.shared_data_size SO YOU CAN PASS THEM TO LoadKernel(). */
return (0 == p.firmware_index ? BOOT_FIRMWARE_A_CONTINUE :
BOOT_FIRMWARE_B_CONTINUE);
diff --git a/utility/load_firmware_test.c b/utility/load_firmware_test.c
index dde0d428..6a4eb8af 100644
--- a/utility/load_firmware_test.c
+++ b/utility/load_firmware_test.c
@@ -44,27 +44,26 @@ int GetFirmwareBody(LoadFirmwareParams* params, uint64_t firmware_index) {
return 0;
}
-/* Get firmware root key
+/* Get GBB
*
- * Return pointer to firmware root key of firmware image, or NULL if not found
+ * Return pointer to GBB from firmware image, or NULL if not found.
*
* [base_of_rom] pointer to firmware image
* [fmap] pointer to Flash Map of firmware image
+ * [gbb_size] GBB size will be stored here if GBB is found
*/
-void* GetFirmwareRootKey(const void* base_of_rom, const void* fmap) {
+void* GetFirmwareGBB(const void* base_of_rom, const void* fmap,
+ uint64_t* gbb_size) {
const FmapHeader* fh = (const FmapHeader*) fmap;
const FmapAreaHeader* ah = (const FmapAreaHeader*)
(fmap + sizeof(FmapHeader));
int i = FmapAreaIndexOrError(fh, ah, "GBB Area");
- const void* gbb;
- const GoogleBinaryBlockHeader* gbbh;
if (i < 0)
return NULL;
- gbb = base_of_rom + ah[i].area_offset;
- gbbh = (const GoogleBinaryBlockHeader*) gbb;
- return (void*) gbb + gbbh->rootkey_offset;
+ *gbb_size = ah[i].area_size;
+ return (void*)(base_of_rom + ah[i].area_offset);
}
/* Get verification block
@@ -151,15 +150,14 @@ int DriveLoadFirmware(const void* base_of_rom, const void* fmap) {
/* Initialize LoadFirmwareParams lfp */
lfp.caller_internal = &ci;
-
- lfp.firmware_root_key_blob = GetFirmwareRootKey(base_of_rom, fmap);
- if (!lfp.firmware_root_key_blob) {
- printf("ERROR: cannot get firmware root key blob\n");
+ lfp.gbb_data = GetFirmwareGBB(base_of_rom, fmap, &lfp.gbb_size);
+ if (!lfp.gbb_data) {
+ printf("ERROR: cannot get firmware GBB\n");
return 1;
}
- printf("firmware root key blob at 0x%08" PRIx64 "\n",
- (uint64_t) (lfp.firmware_root_key_blob - base_of_rom));
+ printf("firmware GBB at 0x%08" PRIx64 "\n",
+ (uint64_t) (lfp.gbb_data - base_of_rom));
/* Loop to initialize firmware key and data A / B */
for (index = 0; index < 2; ++index) {
@@ -186,9 +184,9 @@ int DriveLoadFirmware(const void* base_of_rom, const void* fmap) {
ci.firmware[index].size);
}
- lfp.kernel_sign_key_blob = Malloc(LOAD_FIRMWARE_KEY_BLOB_REC_SIZE);
- lfp.kernel_sign_key_size = LOAD_FIRMWARE_KEY_BLOB_REC_SIZE;
- printf("kernel sign key size is 0x%08" PRIx64 "\n", lfp.kernel_sign_key_size);
+ 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 = 0;
printf("boot flags is 0x%08" PRIx64 "\n", lfp.boot_flags);
@@ -202,7 +200,7 @@ int DriveLoadFirmware(const void* base_of_rom, const void* fmap) {
if (status == LOAD_FIRMWARE_SUCCESS)
printf("firmwiare index is %" PRIu64 "\n", lfp.firmware_index);
- Free(lfp.kernel_sign_key_blob);
+ Free(lfp.shared_data_blob);
return 0;
}
diff --git a/utility/load_kernel_test.c b/utility/load_kernel_test.c
index 8d95ef0c..d26c7cd4 100644
--- a/utility/load_kernel_test.c
+++ b/utility/load_kernel_test.c
@@ -14,11 +14,14 @@
#include <sys/types.h>
#include <unistd.h>
+#include "load_firmware_fw.h"
#include "load_kernel_fw.h"
#include "boot_device.h"
+#include "gbb_header.h"
#include "host_common.h"
#include "rollback_index.h"
#include "utility.h"
+#include "vboot_common.h"
#include "vboot_kernel.h"
#define LBA_BYTES 512
@@ -77,6 +80,10 @@ int BootDeviceWriteLBA(uint64_t lba_start, uint64_t lba_count,
int main(int argc, char* argv[]) {
const char* image_name;
+ uint64_t key_size;
+ uint8_t* key_blob = NULL;
+ VbSharedDataHeader* shared;
+ GoogleBinaryBlockHeader* gbb;
int rv, c, argsleft;
int errorcnt = 0;
char *e = 0;
@@ -136,14 +143,53 @@ int main(int argc, char* argv[]) {
/* Read header signing key blob */
if (argsleft > 1) {
- uint64_t key_size;
- lkp.header_sign_key_blob = ReadFile(argv[optind+1], &key_size);
- if (!lkp.header_sign_key_blob) {
+ key_blob = ReadFile(argv[optind+1], &key_size);
+ if (!key_blob) {
fprintf(stderr, "Unable to read key file %s\n", argv[optind+1]);
return 1;
}
+ printf("Read %" PRIu64 " bytes of key from %s\n", key_size, argv[optind+1]);
}
- /* Need to skip the address check, since we're putting it somewhere on the
+
+ /* Initialize the GBB */
+ lkp.gbb_size = sizeof(GoogleBinaryBlockHeader) + key_size;
+ lkp.gbb_data = (void*)Malloc(lkp.gbb_size);
+ gbb = (GoogleBinaryBlockHeader*)lkp.gbb_data;
+ Memset(gbb, 0, lkp.gbb_size);
+ Memcpy(gbb->signature, GBB_SIGNATURE, GBB_SIGNATURE_SIZE);
+ gbb->major_version = GBB_MAJOR_VER;
+ gbb->minor_version = GBB_MINOR_VER;
+ gbb->header_size = sizeof(GoogleBinaryBlockHeader);
+ /* Fill in the given key, if any, for both root and recovery */
+ if (key_blob) {
+ gbb->rootkey_offset = gbb->header_size;
+ gbb->rootkey_size = key_size;
+ Memcpy((uint8_t*)gbb + gbb->rootkey_offset, key_blob, key_size);
+
+ gbb->recovery_key_offset = gbb->rootkey_offset;
+ gbb->recovery_key_size = key_size;
+ }
+
+ /* Initialize the shared data area */
+ lkp.shared_data_blob = Malloc(LOAD_FIRMWARE_SHARED_DATA_REC_SIZE);
+ lkp.shared_data_size = LOAD_FIRMWARE_SHARED_DATA_REC_SIZE;
+ shared = (VbSharedDataHeader*)lkp.shared_data_blob;
+ if (0 != VbSharedDataInit(shared, lkp.shared_data_size)) {
+ fprintf(stderr, "Unable to init shared data\n");
+ return 1;
+ }
+ /* Copy in the key blob, if any */
+ if (key_blob) {
+ if (0 != VbSharedDataSetKernelKey(shared, (VbPublicKey*)key_blob)) {
+ fprintf(stderr, "Unable to set key in shared data\n");
+ return 1;
+ }
+ }
+
+ /* Free the key blob, now that we're done with it */
+ Free(key_blob);
+
+ /* Needs to skip the address check, since we're putting it somewhere on the
* heap instead of its actual target address in the firmware. */
lkp.boot_flags |= BOOT_FLAG_SKIP_ADDR_CHECK;