| Index: utility/load_firmware_test.c
|
| diff --git a/utility/load_firmware_test.c b/utility/load_firmware_test.c
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..c5f3cd593d0f65fe7d7969e1b13f2a58327e9d3d
|
| --- /dev/null
|
| +++ b/utility/load_firmware_test.c
|
| @@ -0,0 +1,265 @@
|
| +/* 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.
|
| + *
|
| + * Routines for verifying a firmware image's signature.
|
| + */
|
| +
|
| +#include <stdio.h>
|
| +
|
| +#include "fmap.h"
|
| +#include "gbb_header.h"
|
| +#include "host_misc.h"
|
| +#include "load_firmware_fw.h"
|
| +#include "vboot_struct.h"
|
| +
|
| +
|
| +typedef struct _CallerInternal {
|
| + struct {
|
| + uint8_t* fw;
|
| + uint64_t size;
|
| + } firmware[2];
|
| +} CallerInternal;
|
| +
|
| +static char* progname = NULL;
|
| +static char* image_path = NULL;
|
| +
|
| +
|
| +/* wrapper of FmapAreaIndex; print error when not found */
|
| +int FmapAreaIndexOrError(const FmapHeader* fh, const FmapAreaHeader* ah,
|
| + const char* name);
|
| +/* return NULL on error */
|
| +const char* status_string(int status);
|
| +
|
| +int GetFirmwareBody(LoadFirmwareParams* params, uint64_t firmware_index) {
|
| + CallerInternal* ci = (CallerInternal*) params->caller_internal;
|
| +
|
| + if (firmware_index != 0 && firmware_index != 1)
|
| + return 1;
|
| +
|
| + UpdateFirmwareBodyHash(params,
|
| + ci->firmware[firmware_index].fw,
|
| + ci->firmware[firmware_index].size);
|
| +
|
| + return 0;
|
| +}
|
| +
|
| +/* Get firmware root key
|
| + *
|
| + * Return pointer to firmware root key of firmware image, or NULL if not found
|
| + *
|
| + * [base_of_rom] pointer to firmware image
|
| + * [fmap] pointer to Flash Map of firmware image
|
| + */
|
| +void* GetFirmwareRootKey(const void* base_of_rom, const void* fmap) {
|
| + 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;
|
| +}
|
| +
|
| +/* Get verification block
|
| + *
|
| + * Return zero if succeed, or non-zero if failed
|
| + *
|
| + * [base_of_rom] pointer to firmware image
|
| + * [fmap] pointer to Flash Map of firmware image
|
| + * [index] index of verification block
|
| + * [verification_block_ptr] pointer to storing the found verification block
|
| + * [verification_size_ptr] pointer to store the found verification block size
|
| + */
|
| +int GetVerificationBlock(const void* base_of_rom, const void* fmap, int index,
|
| + void** verification_block_ptr, uint64_t* verification_size_ptr) {
|
| + const char* key_area_name[2] = {
|
| + "Firmware A Key",
|
| + "Firmware B Key"
|
| + };
|
| + const FmapHeader* fh = (const FmapHeader*) fmap;
|
| + const FmapAreaHeader* ah = (const FmapAreaHeader*)
|
| + (fmap + sizeof(FmapHeader));
|
| + int i = FmapAreaIndexOrError(fh, ah, key_area_name[index]);
|
| + const void* kb;
|
| + const VbKeyBlockHeader* kbh;
|
| + const VbFirmwarePreambleHeader* fph;
|
| +
|
| + if (i < 0)
|
| + return 1;
|
| +
|
| + kb = base_of_rom + ah[i].area_offset;
|
| + *verification_block_ptr = (void*) kb;
|
| +
|
| + kbh = (const VbKeyBlockHeader*) kb;
|
| + fph = (const VbFirmwarePreambleHeader*) (kb + kbh->key_block_size);
|
| +
|
| + *verification_size_ptr = kbh->key_block_size + fph->preamble_size;
|
| +
|
| + return 0;
|
| +}
|
| +
|
| +/* Return non-zero if not found */
|
| +int GetFirmwareData(const void* base_of_rom, const void* fmap, int index,
|
| + void *verification_block, uint8_t** body_ptr, uint64_t *size_ptr) {
|
| + const char* data_area_name[2] = {
|
| + "Firmware A Data",
|
| + "Firmware B Data"
|
| + };
|
| + const FmapHeader* fh = (const FmapHeader*) fmap;
|
| + const FmapAreaHeader* ah = (const FmapAreaHeader*)
|
| + (fmap + sizeof(FmapHeader));
|
| + const VbKeyBlockHeader* kbh = (const VbKeyBlockHeader*) verification_block;
|
| + const VbFirmwarePreambleHeader* fph = (const VbFirmwarePreambleHeader*)
|
| + (verification_block + kbh->key_block_size);
|
| + int i = FmapAreaIndexOrError(fh, ah, data_area_name[index]);
|
| +
|
| + if (i < 0)
|
| + return 1;
|
| +
|
| + *body_ptr = (uint8_t*) (base_of_rom + ah[i].area_offset);
|
| + *size_ptr = (uint64_t) fph->body_signature.data_size;
|
| + return 0;
|
| +}
|
| +
|
| +/* Verify firmware image [base_of_rom] using [fmap] for looking up areas.
|
| + * Return zero on success, non-zero on error
|
| + *
|
| + * [base_of_rom] pointer to start of firmware image
|
| + * [fmap] pointer to start of Flash Map of firmware image
|
| + */
|
| +int DriveLoadFirmware(const void* base_of_rom, const void* fmap) {
|
| + LoadFirmwareParams lfp;
|
| + CallerInternal ci;
|
| +
|
| + const char* status_str;
|
| + int index, status;
|
| +
|
| + void** vblock_ptr[2] = {
|
| + &lfp.verification_block_0, &lfp.verification_block_1
|
| + };
|
| + uint64_t* vsize_ptr[2] = {
|
| + &lfp.verification_size_0, &lfp.verification_size_1
|
| + };
|
| +
|
| + /* 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");
|
| + return 1;
|
| + }
|
| +
|
| + printf("firmware root key blob at 0x%08" PRIx64 "\n",
|
| + lfp.firmware_root_key_blob - base_of_rom);
|
| +
|
| + /* Loop to initialize firmware key and data A / B */
|
| + for (index = 0; index < 2; ++index) {
|
| + if (GetVerificationBlock(base_of_rom, fmap, index,
|
| + vblock_ptr[index], vsize_ptr[index])) {
|
| + printf("ERROR: cannot get key block %d\n", index);
|
| + return 1;
|
| + }
|
| +
|
| + printf("verification block %d at 0x%08" PRIx64 "\n", index,
|
| + *vblock_ptr[index] - base_of_rom);
|
| + printf("verification block %d size is 0x%08" PRIx64 "\n", index,
|
| + *vsize_ptr[index]);
|
| +
|
| + if (GetFirmwareData(base_of_rom, fmap, index, *vblock_ptr[index],
|
| + &(ci.firmware[index].fw), &(ci.firmware[index].size))) {
|
| + printf("ERROR: cannot get firmware body %d\n", index);
|
| + return 1;
|
| + }
|
| +
|
| + printf("firmware %c at 0x%08" PRIx64 "\n", "AB"[index],
|
| + (void*) ci.firmware[index].fw - base_of_rom);
|
| + printf("firmware %c size is 0x%08" PRIx64 "\n", "AB"[index],
|
| + 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.boot_flags = 0;
|
| + printf("boot flags is 0x%08" PRIx64 "\n", lfp.boot_flags);
|
| +
|
| + status = LoadFirmware(&lfp);
|
| + status_str = status_string(status);
|
| + if (status_str)
|
| + 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.kernel_sign_key_blob);
|
| +
|
| + return 0;
|
| +}
|
| +
|
| +/* wrap FmapAreaIndex; print error when not found */
|
| +int FmapAreaIndexOrError(const FmapHeader* fh, const FmapAreaHeader* ah,
|
| + const char* name) {
|
| + int i = FmapAreaIndex(fh, ah, name);
|
| + if (i < 0)
|
| + fprintf(stderr, "%s: can't find %s in firmware image\n", progname, name);
|
| + return i;
|
| +}
|
| +
|
| +/* Convert status returned by LoadFirmware to string. Return NULL on error. */
|
| +const char* status_string(int status) {
|
| + switch (status) {
|
| + case LOAD_FIRMWARE_SUCCESS:
|
| + return "LOAD_FIRMWARE_SUCCESS";
|
| + case LOAD_FIRMWARE_RECOVERY:
|
| + return "LOAD_FIRMWARE_RECOVERY";
|
| + case LOAD_FIRMWARE_REBOOT:
|
| + return "LOAD_FIRMWARE_REBOOT";
|
| + case LOAD_FIRMWARE_RECOVERY_TPM:
|
| + return "LOAD_FIRMWARE_RECOVERY_TPM";
|
| + default:
|
| + return NULL;
|
| + }
|
| +}
|
| +
|
| +int main(int argc, char* argv[]) {
|
| + int retval = 0;
|
| + const void* base_of_rom;
|
| + const void* fmap;
|
| + uint64_t rom_size;
|
| +
|
| + progname = argv[0];
|
| +
|
| + if (argc < 2) {
|
| + fprintf(stderr, "usage: %s <firmware_image>\n", progname);
|
| + exit(1);
|
| + }
|
| +
|
| + image_path = argv[1];
|
| +
|
| + base_of_rom = ReadFile(image_path, &rom_size);
|
| + if (base_of_rom == NULL) {
|
| + fprintf(stderr, "%s: can not open %s\n", progname, image_path);
|
| + exit(1);
|
| + }
|
| +
|
| + printf("opened %s\n", image_path);
|
| +
|
| + fmap = FmapFind((char*) base_of_rom, rom_size);
|
| +
|
| + retval = DriveLoadFirmware(base_of_rom, fmap);
|
| +
|
| + Free((void*) base_of_rom);
|
| +
|
| + return retval;
|
| +}
|
|
|