diff options
author | Randall Spangler <rspangler@chromium.org> | 2011-03-09 15:54:16 -0800 |
---|---|---|
committer | Randall Spangler <rspangler@chromium.org> | 2011-03-09 15:54:16 -0800 |
commit | 95c4031ce903258036beeed0705d25c7e9d25da0 (patch) | |
tree | 953d53685e331c4f36dcfb0115137a0fec0abc7b | |
parent | c324fbfb6d37aa62b0e6e2f22dae7c949896ddef (diff) | |
download | vboot-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.h | 30 | ||||
-rw-r--r-- | firmware/include/load_kernel_fw.h | 12 | ||||
-rw-r--r-- | firmware/include/vboot_nvstorage.h | 4 | ||||
-rw-r--r-- | firmware/include/vboot_struct.h | 45 | ||||
-rw-r--r-- | firmware/lib/include/vboot_common.h | 17 | ||||
-rw-r--r-- | firmware/lib/vboot_common.c | 67 | ||||
-rw-r--r-- | firmware/lib/vboot_firmware.c | 39 | ||||
-rw-r--r-- | firmware/lib/vboot_kernel.c | 28 | ||||
-rw-r--r-- | firmware/linktest/main.c | 3 | ||||
-rw-r--r-- | firmware/stub/load_firmware_stub.c | 16 | ||||
-rw-r--r-- | utility/load_firmware_test.c | 34 | ||||
-rw-r--r-- | utility/load_kernel_test.c | 54 |
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; |