mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2025-11-25 10:45:02 +00:00
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
This commit is contained in:
@@ -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* 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
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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_ */
|
||||
|
||||
@@ -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_ */
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user