diff options
Diffstat (limited to 'firmware/lib')
-rw-r--r-- | firmware/lib/include/load_kernel_fw.h | 2 | ||||
-rw-r--r-- | firmware/lib/include/vboot_display.h | 5 | ||||
-rw-r--r-- | firmware/lib/include/vboot_kernel.h | 6 | ||||
-rw-r--r-- | firmware/lib/region-fw.c | 54 | ||||
-rw-r--r-- | firmware/lib/region-init.c | 49 | ||||
-rw-r--r-- | firmware/lib/region-kernel.c | 199 | ||||
-rw-r--r-- | firmware/lib/vboot_api_firmware.c | 14 | ||||
-rw-r--r-- | firmware/lib/vboot_api_init.c | 21 | ||||
-rw-r--r-- | firmware/lib/vboot_api_kernel.c | 33 | ||||
-rw-r--r-- | firmware/lib/vboot_audio.c | 3 | ||||
-rw-r--r-- | firmware/lib/vboot_display.c | 233 | ||||
-rw-r--r-- | firmware/lib/vboot_firmware.c | 13 | ||||
-rw-r--r-- | firmware/lib/vboot_kernel.c | 18 |
13 files changed, 455 insertions, 195 deletions
diff --git a/firmware/lib/include/load_kernel_fw.h b/firmware/lib/include/load_kernel_fw.h index dd6e1a84..a710ee5d 100644 --- a/firmware/lib/include/load_kernel_fw.h +++ b/firmware/lib/include/load_kernel_fw.h @@ -74,7 +74,7 @@ typedef struct LoadKernelParams { * Returns VBERROR_SUCCESS if successful. If unsuccessful, sets a recovery * reason via VbNvStorage and returns an error code. */ -VbError_t LoadKernel(LoadKernelParams *params); +VbError_t LoadKernel(LoadKernelParams *params, VbCommonParams *cparams); /* * The bootloader is loaded using the EFI LoadImage() and StartImage() calls. diff --git a/firmware/lib/include/vboot_display.h b/firmware/lib/include/vboot_display.h index 17ce48b8..c35f6697 100644 --- a/firmware/lib/include/vboot_display.h +++ b/firmware/lib/include/vboot_display.h @@ -43,11 +43,6 @@ void VbRenderTextAtPos(const char *text, int right_to_left, const char *RecoveryReasonString(uint8_t code); /** - * Return a fixed string representing the HWID. - */ -const char *VbHWID(VbCommonParams *cparams); - -/** * Get the number of localizations in the GBB bitmap data. */ VbError_t VbGetLocalizationCount(VbCommonParams *cparams, uint32_t *count); diff --git a/firmware/lib/include/vboot_kernel.h b/firmware/lib/include/vboot_kernel.h index 1243cb84..48e12536 100644 --- a/firmware/lib/include/vboot_kernel.h +++ b/firmware/lib/include/vboot_kernel.h @@ -11,6 +11,7 @@ #include "cgptlib.h" #include "load_firmware_fw.h" +#include "load_kernel_fw.h" #include "vboot_api.h" /** @@ -33,6 +34,11 @@ int WriteAndFreeGptData(VbExDiskHandle_t disk_handle, GptData *gptdata); VbNvContext *VbApiKernelGetVnc(void); /** + * Exported for unit tests only - frees memory used by VbSelectAndLoadKernel() + */ +void VbApiKernelFree(VbCommonParams *cparams); + +/** * Try to load a kernel. */ uint32_t VbTryLoadKernel(VbCommonParams *cparams, LoadKernelParams *p, diff --git a/firmware/lib/region-fw.c b/firmware/lib/region-fw.c new file mode 100644 index 00000000..13b1c92b --- /dev/null +++ b/firmware/lib/region-fw.c @@ -0,0 +1,54 @@ +/* Copyright (c) 2013 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. + * + * High-level firmware API for loading and verifying rewritable firmware. + * (Firmware portion) + */ + +#include "sysincludes.h" + +#include "bmpblk_header.h" +#include "region.h" +#include "gbb_header.h" +#include "load_kernel_fw.h" +#include "utility.h" +#include "vboot_api.h" +#include "vboot_struct.h" + +static VbError_t VbGbbReadKey(VbCommonParams *cparams, uint32_t offset, + VbPublicKey **keyp) +{ + VbPublicKey hdr, *key; + VbError_t ret; + uint32_t size; + + ret = VbRegionReadData(cparams, VB_REGION_GBB, offset, + sizeof(VbPublicKey), &hdr); + if (ret) + return ret; + + /* Deal with a zero-size key (used in testing) */ + size = hdr.key_offset + hdr.key_size; + if (size < sizeof(hdr)) + size = sizeof(hdr); + key = VbExMalloc(size); + ret = VbRegionReadData(cparams, VB_REGION_GBB, offset, size, key); + if (ret) { + VbExFree(key); + return ret; + } + + *keyp = key; + return VBERROR_SUCCESS; +} + +VbError_t VbGbbReadRootKey(VbCommonParams *cparams, VbPublicKey **keyp) +{ + return VbGbbReadKey(cparams, cparams->gbb->rootkey_offset, keyp); +} + +VbError_t VbGbbReadRecoveryKey(VbCommonParams *cparams, VbPublicKey **keyp) +{ + return VbGbbReadKey(cparams, cparams->gbb->recovery_key_offset, keyp); +} diff --git a/firmware/lib/region-init.c b/firmware/lib/region-init.c new file mode 100644 index 00000000..2c2b7263 --- /dev/null +++ b/firmware/lib/region-init.c @@ -0,0 +1,49 @@ +/* Copyright (c) 2013 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. + * + * High-level firmware API for loading and verifying rewritable firmware. + * (Firmware portion) + */ + +#include "sysincludes.h" + +#include "bmpblk_header.h" +#include "region.h" +#include "gbb_header.h" +#include "load_kernel_fw.h" +#include "utility.h" +#include "vboot_api.h" +#include "vboot_struct.h" + +VbError_t VbRegionReadData(VbCommonParams *cparams, + enum vb_firmware_region region, uint32_t offset, + uint32_t size, void *buf) +{ + /* This is the old API, for backwards compatibility */ + if (region == VB_REGION_GBB && cparams->gbb_data) { + if (offset + size > cparams->gbb_size) + return VBERROR_INVALID_GBB; + Memcpy(buf, cparams->gbb_data + offset, size); + } else +#ifdef REGION_READ + { + VbError_t ret; + + ret = VbExRegionRead(cparams, region, offset, size, buf); + if (ret) + return ret; + } +#else + return VBERROR_INVALID_GBB; +#endif + + return VBERROR_SUCCESS; +} + +VbError_t VbGbbReadHeader_static(VbCommonParams *cparams, + GoogleBinaryBlockHeader *gbb) +{ + return VbRegionReadData(cparams, VB_REGION_GBB, 0, + sizeof(GoogleBinaryBlockHeader), gbb); +} diff --git a/firmware/lib/region-kernel.c b/firmware/lib/region-kernel.c new file mode 100644 index 00000000..3d7cb84a --- /dev/null +++ b/firmware/lib/region-kernel.c @@ -0,0 +1,199 @@ +/* Copyright (c) 2013 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. + * + * High-level firmware API for loading and verifying rewritable firmware. + * (Firmware portion) + */ + +#include "sysincludes.h" + +#include "bmpblk_header.h" +#include "region.h" +#include "gbb_header.h" +#include "load_kernel_fw.h" +#include "utility.h" +#include "vboot_api.h" +#include "vboot_struct.h" + +static VbError_t VbRegionReadGbb(VbCommonParams *cparams, uint32_t offset, + uint32_t size, void *buf) +{ + return VbRegionReadData(cparams, VB_REGION_GBB, offset, size, buf); +} + +VbError_t VbGbbReadBmpHeader(VbCommonParams *cparams, BmpBlockHeader *hdr_ret) +{ + BmpBlockHeader *hdr; + VbError_t ret; + + if (!cparams) + return VBERROR_INVALID_GBB; + if (!cparams->bmp) { + GoogleBinaryBlockHeader *gbb = cparams->gbb; + + if (0 == gbb->bmpfv_size) + return VBERROR_INVALID_GBB; + + hdr = VbExMalloc(sizeof(*hdr)); + ret = VbRegionReadGbb(cparams, gbb->bmpfv_offset, + sizeof(BmpBlockHeader), hdr); + if (ret) { + VbExFree(hdr); + return ret; + } + + /* Sanity-check the bitmap block header */ + if ((0 != Memcmp(hdr->signature, BMPBLOCK_SIGNATURE, + BMPBLOCK_SIGNATURE_SIZE)) || + (hdr->major_version > BMPBLOCK_MAJOR_VERSION) || + ((hdr->major_version == BMPBLOCK_MAJOR_VERSION) && + (hdr->minor_version > BMPBLOCK_MINOR_VERSION))) { + VBDEBUG(("VbDisplayScreenFromGBB(): " + "invalid/too new bitmap header\n")); + VbExFree(hdr); + return VBERROR_INVALID_BMPFV; + } + cparams->bmp = hdr; + } + + *hdr_ret = *cparams->bmp; + return VBERROR_SUCCESS; +} + +VbError_t VbRegionReadHWID(VbCommonParams *cparams, char *hwid, + uint32_t max_size) +{ + GoogleBinaryBlockHeader *gbb; + VbError_t ret; + + if (!max_size) + return VBERROR_INVALID_PARAMETER; + *hwid = '\0'; + StrnAppend(hwid, "{INVALID}", max_size); + if (!cparams) + return VBERROR_INVALID_GBB; + + gbb = cparams->gbb; + + if (0 == gbb->hwid_size) { + VBDEBUG(("VbHWID(): invalid hwid size\n")); + return VBERROR_SUCCESS; /* oddly enough! */ + } + + if (gbb->hwid_size > max_size) { + VBDEBUG(("VbDisplayDebugInfo(): invalid hwid offset/size\n")); + return VBERROR_INVALID_PARAMETER; + } + ret = VbRegionReadGbb(cparams, gbb->hwid_offset, gbb->hwid_size, hwid); + if (ret) + return ret; + + return VBERROR_SUCCESS; +} + +VbError_t VbGbbReadImage(VbCommonParams *cparams, + uint32_t localization, uint32_t screen_index, + uint32_t image_num, ScreenLayout *layout, + ImageInfo *image_info, char **image_datap, + uint32_t *image_data_sizep) +{ + uint32_t layout_offset, image_offset, data_offset, data_size; + GoogleBinaryBlockHeader *gbb; + BmpBlockHeader hdr; + void *data = NULL; + VbError_t ret; + + if (!cparams) + return VBERROR_INVALID_GBB; + + ret = VbGbbReadBmpHeader(cparams, &hdr); + if (ret) + return ret; + + gbb = cparams->gbb; + layout_offset = gbb->bmpfv_offset + sizeof(BmpBlockHeader) + + localization * hdr.number_of_screenlayouts * + sizeof(ScreenLayout) + + screen_index * sizeof(ScreenLayout); + ret = VbRegionReadGbb(cparams, layout_offset, sizeof(*layout), layout); + if (ret) + return ret; + + if (!layout->images[image_num].image_info_offset) + return VBERROR_NO_IMAGE_PRESENT; + + image_offset = gbb->bmpfv_offset + + layout->images[image_num].image_info_offset; + ret = VbRegionReadGbb(cparams, image_offset, sizeof(*image_info), + image_info); + if (ret) + return ret; + + data_offset = image_offset + sizeof(*image_info); + data_size = image_info->compressed_size; + if (data_size) { + void *orig_data; + + data = VbExMalloc(image_info->compressed_size); + ret = VbRegionReadGbb(cparams, data_offset, + image_info->compressed_size, data); + if (ret) { + VbExFree(data); + return ret; + } + if (image_info->compression != COMPRESS_NONE) { + uint32_t inoutsize = image_info->original_size; + + orig_data = VbExMalloc(image_info->original_size); + ret = VbExDecompress(data, + image_info->compressed_size, + image_info->compression, + orig_data, &inoutsize); + data_size = inoutsize; + VbExFree(data); + data = orig_data; + if (ret) { + VbExFree(data); + return ret; + } + } + } + + *image_datap = data; + *image_data_sizep = data_size; + + return VBERROR_SUCCESS; +} + +#define OUTBUF_LEN 128 + +void VbRegionCheckVersion(VbCommonParams *cparams) +{ + GoogleBinaryBlockHeader *gbb; + + if (!cparams) + return; + + gbb = cparams->gbb; + + /* + * If GBB flags is nonzero, complain because that's something that the + * factory MUST fix before shipping. We only have to do this here, + * because it's obvious that something is wrong if we're not displaying + * screens from the GBB. + */ + if (gbb->major_version == GBB_MAJOR_VER && gbb->minor_version >= 1 && + (gbb->flags != 0)) { + uint32_t used = 0; + char outbuf[OUTBUF_LEN]; + + *outbuf = '\0'; + used += StrnAppend(outbuf + used, "gbb.flags is nonzero: 0x", + OUTBUF_LEN - used); + used += Uint64ToString(outbuf + used, OUTBUF_LEN - used, + gbb->flags, 16, 8); + used += StrnAppend(outbuf + used, "\n", OUTBUF_LEN - used); + (void)VbExDisplayDebugInfo(outbuf); + } +} diff --git a/firmware/lib/vboot_api_firmware.c b/firmware/lib/vboot_api_firmware.c index e0c93a37..cfe4251c 100644 --- a/firmware/lib/vboot_api_firmware.c +++ b/firmware/lib/vboot_api_firmware.c @@ -7,6 +7,7 @@ #include "sysincludes.h" +#include "gbb_access.h" #include "gbb_header.h" #include "load_firmware_fw.h" #include "rollback_index.h" @@ -27,6 +28,9 @@ VbError_t VbSelectFirmware(VbCommonParams *cparams, int is_dev = (shared->flags & VBSD_BOOT_DEV_SWITCH_ON ? 1 : 0); uint32_t tpm_status = 0; + cparams->gbb = NULL; + cparams->bmp = NULL; + /* Start timer */ shared->timer_vb_select_firmware_enter = VbExGetTimer(); @@ -44,6 +48,11 @@ VbError_t VbSelectFirmware(VbCommonParams *cparams, /* Go directly to recovery mode */ fparams->selected_firmware = VB_SELECT_FIRMWARE_RECOVERY; } else { + cparams->gbb = VbExMalloc(sizeof(*cparams->gbb)); + retval = VbGbbReadHeader_static(cparams, cparams->gbb); + if (VBERROR_SUCCESS != retval) + goto VbSelectFirmware_exit; + /* Chain to LoadFirmware() */ retval = LoadFirmware(cparams, fparams, &vnc); @@ -107,6 +116,11 @@ VbError_t VbSelectFirmware(VbCommonParams *cparams, VbSelectFirmware_exit: + if (cparams->gbb) { + VbExFree(cparams->gbb); + cparams->gbb = NULL; + } + /* Save NV storage */ VbNvTeardown(&vnc); if (vnc.raw_changed) diff --git a/firmware/lib/vboot_api_init.c b/firmware/lib/vboot_api_init.c index c55e708c..ebafe2a7 100644 --- a/firmware/lib/vboot_api_init.c +++ b/firmware/lib/vboot_api_init.c @@ -7,6 +7,8 @@ #include "sysincludes.h" +#include "region.h" +#include "gbb_access.h" #include "gbb_header.h" #include "load_firmware_fw.h" #include "rollback_index.h" @@ -19,8 +21,7 @@ VbError_t VbInit(VbCommonParams *cparams, VbInitParams *iparams) { VbSharedDataHeader *shared = (VbSharedDataHeader *)cparams->shared_data_blob; - GoogleBinaryBlockHeader *gbb = - (GoogleBinaryBlockHeader *)cparams->gbb_data; + GoogleBinaryBlockHeader gbb; VbNvContext vnc; VbError_t retval = VBERROR_SUCCESS; uint32_t recovery = VBNV_RECOVERY_NOT_REQUESTED; @@ -36,12 +37,16 @@ VbError_t VbInit(VbCommonParams *cparams, VbInitParams *iparams) uint32_t clear_tpm_owner_request = 0; int is_dev = 0; - VBDEBUG(("VbInit() input flags 0x%x gbb flags 0x%x\n", iparams->flags, - gbb->flags)); - /* Initialize output flags */ iparams->out_flags = 0; + retval = VbGbbReadHeader_static(cparams, &gbb); + if (retval) + return retval; + + VBDEBUG(("VbInit() input flags 0x%x gbb flags 0x%x\n", iparams->flags, + gbb.flags)); + /* Set up NV storage */ VbExNvStorageRead(vnc.raw); VbNvSetup(&vnc); @@ -163,7 +168,7 @@ VbError_t VbInit(VbCommonParams *cparams, VbInitParams *iparams) VbNvGet(&vnc, VBNV_DISABLE_DEV_REQUEST, &disable_dev_request); /* Allow GBB flag to override dev switch */ - if (gbb->flags & GBB_FLAG_FORCE_DEV_SWITCH_ON) + if (gbb.flags & GBB_FLAG_FORCE_DEV_SWITCH_ON) is_hw_dev = 1; /* Have we been explicitly asked to clear the TPM owner? */ @@ -242,11 +247,11 @@ VbError_t VbInit(VbCommonParams *cparams, VbInitParams *iparams) } /* Allow BIOS to load arbitrary option ROMs? */ - if (gbb->flags & GBB_FLAG_LOAD_OPTION_ROMS) + if (gbb.flags & GBB_FLAG_LOAD_OPTION_ROMS) iparams->out_flags |= VB_INIT_OUT_ENABLE_OPROM; /* Factory may need to boot custom OSes when the dev-switch is on */ - if (is_dev && (gbb->flags & GBB_FLAG_ENABLE_ALTERNATE_OS)) + if (is_dev && (gbb.flags & GBB_FLAG_ENABLE_ALTERNATE_OS)) iparams->out_flags |= VB_INIT_OUT_ENABLE_ALTERNATE_OS; /* Set output flags */ diff --git a/firmware/lib/vboot_api_kernel.c b/firmware/lib/vboot_api_kernel.c index 7ad45929..4f0b3f20 100644 --- a/firmware/lib/vboot_api_kernel.c +++ b/firmware/lib/vboot_api_kernel.c @@ -7,8 +7,10 @@ #include "sysincludes.h" +#include "gbb_access.h" #include "gbb_header.h" #include "load_kernel_fw.h" +#include "region.h" #include "rollback_index.h" #include "utility.h" #include "vboot_api.h" @@ -97,7 +99,7 @@ uint32_t VbTryLoadKernel(VbCommonParams *cparams, LoadKernelParams *p, p->disk_handle = disk_info[i].handle; p->bytes_per_lba = disk_info[i].bytes_per_lba; p->ending_lba = disk_info[i].lba_count - 1; - retval = LoadKernel(p); + retval = LoadKernel(p, cparams); VBDEBUG(("VbTryLoadKernel() LoadKernel() = %d\n", retval)); /* @@ -173,8 +175,7 @@ VbError_t VbBootNormal(VbCommonParams *cparams, LoadKernelParams *p) VbError_t VbBootDeveloper(VbCommonParams *cparams, LoadKernelParams *p) { - GoogleBinaryBlockHeader *gbb = - (GoogleBinaryBlockHeader *)cparams->gbb_data; + GoogleBinaryBlockHeader *gbb = cparams->gbb; VbSharedDataHeader *shared = (VbSharedDataHeader *)cparams->shared_data_blob; uint32_t allow_usb = 0, allow_legacy = 0, ctrl_d_pressed = 0; @@ -807,13 +808,25 @@ VbError_t VbEcSoftwareSync(VbCommonParams *cparams) return VBERROR_SUCCESS; } +/* This function is also used by tests */ +void VbApiKernelFree(VbCommonParams *cparams) +{ + /* VbSelectAndLoadKernel() always allocates this, tests don't */ + if (cparams->gbb) { + VbExFree(cparams->gbb); + cparams->gbb = NULL; + } + if (cparams->bmp) { + VbExFree(cparams->bmp); + cparams->bmp = NULL; + } +} + VbError_t VbSelectAndLoadKernel(VbCommonParams *cparams, VbSelectAndLoadKernelParams *kparams) { VbSharedDataHeader *shared = (VbSharedDataHeader *)cparams->shared_data_blob; - GoogleBinaryBlockHeader *gbb = - (GoogleBinaryBlockHeader *)cparams->gbb_data; VbError_t retval = VBERROR_SUCCESS; LoadKernelParams p; uint32_t tpm_status = 0; @@ -831,9 +844,15 @@ VbError_t VbSelectAndLoadKernel(VbCommonParams *cparams, kparams->bootloader_size = 0; Memset(kparams->partition_guid, 0, sizeof(kparams->partition_guid)); + cparams->bmp = NULL; + cparams->gbb = VbExMalloc(sizeof(*cparams->gbb)); + retval = VbGbbReadHeader_static(cparams, cparams->gbb); + if (VBERROR_SUCCESS != retval) + goto VbSelectAndLoadKernel_exit; + /* Do EC software sync if necessary */ if ((shared->flags & VBSD_EC_SOFTWARE_SYNC) && - !(gbb->flags & GBB_FLAG_DISABLE_EC_SOFTWARE_SYNC)) { + !(cparams->gbb->flags & GBB_FLAG_DISABLE_EC_SOFTWARE_SYNC)) { retval = VbEcSoftwareSync(cparams); if (retval != VBERROR_SUCCESS) goto VbSelectAndLoadKernel_exit; @@ -982,6 +1001,8 @@ VbError_t VbSelectAndLoadKernel(VbCommonParams *cparams, VbSelectAndLoadKernel_exit: + VbApiKernelFree(cparams); + VbNvTeardown(&vnc); if (vnc.raw_changed) VbExNvStorageWrite(vnc.raw); diff --git a/firmware/lib/vboot_audio.c b/firmware/lib/vboot_audio.c index 5414f325..e24a039b 100644 --- a/firmware/lib/vboot_audio.c +++ b/firmware/lib/vboot_audio.c @@ -208,8 +208,7 @@ static void VbGetDevMusicNotes(VbAudioContext *audio, int use_short) */ VbAudioContext *VbAudioOpen(VbCommonParams *cparams) { - GoogleBinaryBlockHeader* gbb = - (GoogleBinaryBlockHeader *)cparams->gbb_data; + GoogleBinaryBlockHeader *gbb = cparams->gbb; VbAudioContext *audio = &au; int use_short = 0; uint64_t a, b; diff --git a/firmware/lib/vboot_display.c b/firmware/lib/vboot_display.c index f79dfe13..910c60a0 100644 --- a/firmware/lib/vboot_display.c +++ b/firmware/lib/vboot_display.c @@ -8,7 +8,9 @@ #include "sysincludes.h" #include "bmpblk_font.h" +#include "gbb_access.h" #include "gbb_header.h" +#include "region.h" #include "utility.h" #include "vboot_api.h" #include "vboot_common.h" @@ -20,49 +22,20 @@ static uint32_t disp_width = 0, disp_height = 0; VbError_t VbGetLocalizationCount(VbCommonParams *cparams, uint32_t *count) { - GoogleBinaryBlockHeader *gbb = - (GoogleBinaryBlockHeader *)cparams->gbb_data; - BmpBlockHeader *hdr; + BmpBlockHeader hdr; + VbError_t ret; /* Default to 0 on error */ *count = 0; - /* Make sure bitmap data is inside the GBB and is non-zero in size */ - if (0 == gbb->bmpfv_size || - gbb->bmpfv_offset > cparams->gbb_size || - gbb->bmpfv_offset + gbb->bmpfv_size > cparams->gbb_size) { - return VBERROR_INVALID_GBB; - } - - /* Sanity-check the bitmap block header */ - hdr = (BmpBlockHeader *)(((uint8_t *)gbb) + gbb->bmpfv_offset); - if ((0 != Memcmp(hdr->signature, BMPBLOCK_SIGNATURE, - BMPBLOCK_SIGNATURE_SIZE)) || - (hdr->major_version > BMPBLOCK_MAJOR_VERSION) || - ((hdr->major_version == BMPBLOCK_MAJOR_VERSION) && - (hdr->minor_version > BMPBLOCK_MINOR_VERSION))) { - return VBERROR_INVALID_BMPFV; - } + ret = VbGbbReadBmpHeader(cparams, &hdr); + if (ret) + return ret; - *count = hdr->number_of_localizations; + *count = hdr.number_of_localizations; return VBERROR_SUCCESS; } -const char *VbHWID(VbCommonParams *cparams) -{ - GoogleBinaryBlockHeader *gbb = - (GoogleBinaryBlockHeader *)cparams->gbb_data; - - if (0 == gbb->hwid_size || - gbb->hwid_offset > cparams->gbb_size || - gbb->hwid_offset + gbb->hwid_size > cparams->gbb_size) { - VBDEBUG(("VbHWID(): invalid hwid offset/size\n")); - return "{INVALID}"; - } - - return (char *)((uint8_t *)gbb + gbb->hwid_offset); -} - /* * TODO: We could cache the font info to speed things up, by making the * in-memory font structure distinct from the in-flash version. We'll do that @@ -164,62 +137,24 @@ void VbRenderTextAtPos(const char *text, int right_to_left, } } -#define OUTBUF_LEN 128 - VbError_t VbDisplayScreenFromGBB(VbCommonParams *cparams, uint32_t screen, VbNvContext *vncptr) { - GoogleBinaryBlockHeader *gbb = - (GoogleBinaryBlockHeader *)cparams->gbb_data; - static uint8_t *bmpfv; - void *fullimage = NULL; - BmpBlockHeader *hdr; - ScreenLayout *layout; - ImageInfo *image_info; + char *fullimage = NULL; + BmpBlockHeader hdr; uint32_t screen_index; uint32_t localization = 0; VbError_t retval = VBERROR_UNKNOWN; /* Assume error until proven ok */ uint32_t inoutsize; - uint32_t offset; uint32_t i; VbFont_t *font; const char *text_to_show; int rtol = 0; - char outbuf[OUTBUF_LEN] = ""; - uint32_t used = 0; + VbError_t ret; - /* Make sure bitmap data is inside the GBB and is non-zero in size */ - if (0 == gbb->bmpfv_size || - gbb->bmpfv_offset > cparams->gbb_size || - gbb->bmpfv_offset + gbb->bmpfv_size > cparams->gbb_size) { - VBDEBUG(("VbDisplayScreenFromGBB(): " - "invalid bmpfv offset/size\n")); - return VBERROR_INVALID_GBB; - } - - /* Copy bitmap data from GBB into RAM for speed */ - if (!bmpfv) { -#ifdef COPY_BMP_DATA - bmpfv = (uint8_t *)VbExMalloc(gbb->bmpfv_size); - Memcpy(bmpfv, ((uint8_t *)gbb) + gbb->bmpfv_offset, - gbb->bmpfv_size); -#else - bmpfv = ((uint8_t *)gbb) + gbb->bmpfv_offset; -#endif - } - - /* Sanity-check the bitmap block header */ - hdr = (BmpBlockHeader *)bmpfv; - if ((0 != Memcmp(hdr->signature, BMPBLOCK_SIGNATURE, - BMPBLOCK_SIGNATURE_SIZE)) || - (hdr->major_version > BMPBLOCK_MAJOR_VERSION) || - ((hdr->major_version == BMPBLOCK_MAJOR_VERSION) && - (hdr->minor_version > BMPBLOCK_MINOR_VERSION))) { - VBDEBUG(("VbDisplayScreenFromGBB(): " - "invalid/too new bitmap header\n")); - retval = VBERROR_INVALID_BMPFV; - goto VbDisplayScreenFromGBB_exit; - } + ret = VbGbbReadBmpHeader(cparams, &hdr); + if (ret) + return ret; /* * Translate screen ID into index. Note that not all screens are in @@ -263,7 +198,7 @@ VbError_t VbDisplayScreenFromGBB(VbCommonParams *cparams, uint32_t screen, goto VbDisplayScreenFromGBB_exit; } - if (screen_index >= hdr->number_of_screenlayouts) { + if (screen_index >= hdr.number_of_screenlayouts) { VBDEBUG(("VbDisplayScreenFromGBB(): " "screen %d index %d not in the GBB\n", (int)screen, (int)screen_index)); @@ -273,48 +208,31 @@ VbError_t VbDisplayScreenFromGBB(VbCommonParams *cparams, uint32_t screen, /* Clip localization to number of localizations present in the GBB */ VbNvGet(vncptr, VBNV_LOCALIZATION_INDEX, &localization); - if (localization >= hdr->number_of_localizations) { + if (localization >= hdr.number_of_localizations) { localization = 0; VbNvSet(vncptr, VBNV_LOCALIZATION_INDEX, localization); } - /* - * Calculate offset of screen layout = start of screen stuff + correct - * locale + correct screen. - */ - offset = sizeof(BmpBlockHeader) + - localization * hdr->number_of_screenlayouts * - sizeof(ScreenLayout) + - screen_index * sizeof(ScreenLayout); - layout = (ScreenLayout *)(bmpfv + offset); - /* Display all bitmaps for the image */ for (i = 0; i < MAX_IMAGE_IN_LAYOUT; i++) { - if (!layout->images[i].image_info_offset) + ScreenLayout layout; + ImageInfo image_info; + char hwid[256]; + + ret = VbGbbReadImage(cparams, localization, screen_index, + i, &layout, &image_info, + &fullimage, &inoutsize); + if (ret == VBERROR_NO_IMAGE_PRESENT) { continue; - - offset = layout->images[i].image_info_offset; - image_info = (ImageInfo *)(bmpfv + offset); - fullimage = bmpfv + offset + sizeof(ImageInfo); - inoutsize = image_info->original_size; - if (inoutsize && - image_info->compression != COMPRESS_NONE) { - fullimage = VbExMalloc(inoutsize); - retval = VbExDecompress( - bmpfv + offset + sizeof(ImageInfo), - image_info->compressed_size, - image_info->compression, - fullimage, &inoutsize); - if (VBERROR_SUCCESS != retval) { - VbExFree(fullimage); - goto VbDisplayScreenFromGBB_exit; - } + } else if (ret) { + retval = ret; + goto VbDisplayScreenFromGBB_exit; } - switch(image_info->format) { + switch(image_info.format) { case FORMAT_BMP: - retval = VbExDisplayImage(layout->images[i].x, - layout->images[i].y, + retval = VbExDisplayImage(layout.images[i].x, + layout.images[i].y, fullimage, inoutsize); break; @@ -323,21 +241,23 @@ VbError_t VbDisplayScreenFromGBB(VbCommonParams *cparams, uint32_t screen, * The uncompressed blob is our font structure. Cache * it as needed. */ - font = VbInternalizeFontData(fullimage); + font = VbInternalizeFontData( + (FontArrayHeader *)fullimage); /* TODO: handle text in general here */ - if (TAG_HWID == image_info->tag || - TAG_HWID_RTOL == image_info->tag) { - text_to_show = VbHWID(cparams); - rtol = (TAG_HWID_RTOL == image_info->tag); + if (TAG_HWID == image_info.tag || + TAG_HWID_RTOL == image_info.tag) { + VbRegionReadHWID(cparams, hwid, sizeof(hwid)); + text_to_show = hwid; + rtol = (TAG_HWID_RTOL == image_info.tag); } else { text_to_show = ""; rtol = 0; } VbRenderTextAtPos(text_to_show, rtol, - layout->images[i].x, - layout->images[i].y, font); + layout.images[i].x, + layout.images[i].y, font); VbDoneWithFontForNow(font); break; @@ -345,12 +265,11 @@ VbError_t VbDisplayScreenFromGBB(VbCommonParams *cparams, uint32_t screen, default: VBDEBUG(("VbDisplayScreenFromGBB(): " "unsupported ImageFormat %d\n", - image_info->format)); + image_info.format)); retval = VBERROR_INVALID_GBB; } - if (COMPRESS_NONE != image_info->compression) - VbExFree(fullimage); + VbExFree(fullimage); if (VBERROR_SUCCESS != retval) goto VbDisplayScreenFromGBB_exit; @@ -359,29 +278,15 @@ VbError_t VbDisplayScreenFromGBB(VbCommonParams *cparams, uint32_t screen, /* Successful if all bitmaps displayed */ retval = VBERROR_SUCCESS; - /* - * If GBB flags is nonzero, complain because that's something that the - * factory MUST fix before shipping. We only have to do this here, - * because it's obvious that something is wrong if we're not displaying - * screens from the GBB. - */ - if (gbb->major_version == GBB_MAJOR_VER && gbb->minor_version >= 1 && - (gbb->flags != 0)) { - used += StrnAppend(outbuf + used, "gbb.flags is nonzero: 0x", - OUTBUF_LEN - used); - used += Uint64ToString(outbuf + used, OUTBUF_LEN - used, - gbb->flags, 16, 8); - used += StrnAppend(outbuf + used, "\n", OUTBUF_LEN - used); - (void)VbExDisplayDebugInfo(outbuf); - } + VbRegionCheckVersion(cparams); VbDisplayScreenFromGBB_exit: VBDEBUG(("leaving VbDisplayScreenFromGBB() with %d\n",retval)); return retval; } -VbError_t VbDisplayScreen(VbCommonParams *cparams, uint32_t screen, int force, - VbNvContext *vncptr) +VbError_t VbDisplayScreen(VbCommonParams *cparams, uint32_t screen, + int force, VbNvContext *vncptr) { VbError_t retval; @@ -403,7 +308,8 @@ VbError_t VbDisplayScreen(VbCommonParams *cparams, uint32_t screen, int force, disp_current_screen = screen; /* Look in the GBB first */ - if (VBERROR_SUCCESS == VbDisplayScreenFromGBB(cparams, screen, vncptr)) + if (VBERROR_SUCCESS == VbDisplayScreenFromGBB(cparams, screen, + vncptr)) return VBERROR_SUCCESS; /* If screen wasn't in the GBB bitmaps, fall back to a default */ @@ -571,29 +477,22 @@ VbError_t VbDisplayDebugInfo(VbCommonParams *cparams, VbNvContext *vncptr) { VbSharedDataHeader *shared = (VbSharedDataHeader *)cparams->shared_data_blob; - GoogleBinaryBlockHeader *gbb = - (GoogleBinaryBlockHeader *)cparams->gbb_data; + GoogleBinaryBlockHeader *gbb = cparams->gbb; char buf[DEBUG_INFO_SIZE] = ""; char sha1sum[SHA1_DIGEST_SIZE * 2 + 1]; + char hwid[256]; uint32_t used = 0; + VbPublicKey *key; + VbError_t ret; uint32_t i; /* Redisplay current screen to overwrite any previous debug output */ VbDisplayScreen(cparams, disp_current_screen, 1, vncptr); /* Add hardware ID */ + VbRegionReadHWID(cparams, hwid, sizeof(hwid)); used += StrnAppend(buf + used, "HWID: ", DEBUG_INFO_SIZE - used); - if (0 == gbb->hwid_size || - gbb->hwid_offset > cparams->gbb_size || - gbb->hwid_offset + gbb->hwid_size > cparams->gbb_size) { - VBDEBUG(("VbDisplayDebugInfo(): invalid hwid offset/size\n")); - used += StrnAppend(buf + used, - "(INVALID)", DEBUG_INFO_SIZE - used); - } else { - used += StrnAppend(buf + used, - (char *)((uint8_t *)gbb + gbb->hwid_offset), - DEBUG_INFO_SIZE - used); - } + used += StrnAppend(buf + used, hwid, DEBUG_INFO_SIZE - used); /* Add recovery reason */ used += StrnAppend(buf + used, @@ -654,15 +553,25 @@ VbError_t VbDisplayDebugInfo(VbCommonParams *cparams, VbNvContext *vncptr) } /* Add sha1sum for Root & Recovery keys */ - FillInSha1Sum(sha1sum, - (VbPublicKey *)((uint8_t *)gbb + gbb->rootkey_offset)); - used += StrnAppend(buf + used, "\ngbb.rootkey: ", DEBUG_INFO_SIZE - used); - used += StrnAppend(buf + used, sha1sum, DEBUG_INFO_SIZE - used); - FillInSha1Sum(sha1sum, - (VbPublicKey *)((uint8_t *)gbb + gbb->recovery_key_offset)); - used += StrnAppend(buf + used, - "\ngbb.recovery_key: ", DEBUG_INFO_SIZE - used); - used += StrnAppend(buf + used, sha1sum, DEBUG_INFO_SIZE - used); + ret = VbGbbReadRootKey(cparams, &key); + if (!ret) { + FillInSha1Sum(sha1sum, key); + VbExFree(key); + used += StrnAppend(buf + used, "\ngbb.rootkey: ", + DEBUG_INFO_SIZE - used); + used += StrnAppend(buf + used, sha1sum, + DEBUG_INFO_SIZE - used); + } + + ret = VbGbbReadRecoveryKey(cparams, &key); + if (!ret) { + FillInSha1Sum(sha1sum, key); + VbExFree(key); + used += StrnAppend(buf + used, "\ngbb.recovery_key: ", + DEBUG_INFO_SIZE - used); + used += StrnAppend(buf + used, sha1sum, + DEBUG_INFO_SIZE - used); + } /* If we're in dev-mode, show the kernel subkey that we expect, too. */ if (0 == shared->recovery_reason) { diff --git a/firmware/lib/vboot_firmware.c b/firmware/lib/vboot_firmware.c index c5000cb7..e6a31fa9 100644 --- a/firmware/lib/vboot_firmware.c +++ b/firmware/lib/vboot_firmware.c @@ -8,6 +8,8 @@ #include "sysincludes.h" +#include "region.h" +#include "gbb_access.h" #include "gbb_header.h" #include "load_firmware_fw.h" #include "utility.h" @@ -41,9 +43,8 @@ int LoadFirmware(VbCommonParams *cparams, VbSelectFirmwareParams *fparams, { VbSharedDataHeader *shared = (VbSharedDataHeader *)cparams->shared_data_blob; - GoogleBinaryBlockHeader *gbb = - (GoogleBinaryBlockHeader *)cparams->gbb_data; - VbPublicKey *root_key; + GoogleBinaryBlockHeader *gbb = cparams->gbb; + VbPublicKey *root_key = NULL; VbLoadFirmwareInternal *lfi; uint32_t try_b_count; @@ -62,12 +63,12 @@ int LoadFirmware(VbCommonParams *cparams, VbSelectFirmwareParams *fparams, VBDEBUG(("LoadFirmware started...\n")); /* Must have a root key from the GBB */ - if (!gbb) { + retval = VbGbbReadRootKey(cparams, &root_key); + if (retval) { VBDEBUG(("No GBB\n")); retval = VBERROR_INVALID_GBB; goto LoadFirmwareExit; } - root_key = (VbPublicKey *)((uint8_t *)gbb + gbb->rootkey_offset); /* Parse flags */ is_dev = (shared->flags & VBSD_BOOT_DEV_SWITCH_ON ? 1 : 0); @@ -345,6 +346,8 @@ int LoadFirmware(VbCommonParams *cparams, VbSelectFirmwareParams *fparams, } LoadFirmwareExit: + VbExFree(root_key); + /* Store recovery request, if any */ VbNvSet(vnc, VBNV_RECOVERY_REQUEST, VBERROR_SUCCESS != retval ? recovery : VBNV_RECOVERY_NOT_REQUESTED); diff --git a/firmware/lib/vboot_kernel.c b/firmware/lib/vboot_kernel.c index aa1e41e3..72cd2cc1 100644 --- a/firmware/lib/vboot_kernel.c +++ b/firmware/lib/vboot_kernel.c @@ -10,6 +10,8 @@ #include "cgptlib.h" #include "cgptlib_internal.h" +#include "region.h" +#include "gbb_access.h" #include "gbb_header.h" #include "load_kernel_fw.h" #include "utility.h" @@ -159,15 +161,14 @@ fail: return ret; } -VbError_t LoadKernel(LoadKernelParams *params) +VbError_t LoadKernel(LoadKernelParams *params, VbCommonParams *cparams) { VbSharedDataHeader *shared = (VbSharedDataHeader *)params->shared_data_blob; VbSharedDataKernelCall *shcall = NULL; VbNvContext* vnc = params->nv_context; - GoogleBinaryBlockHeader* gbb = - (GoogleBinaryBlockHeader *)params->gbb_data; - VbPublicKey* kernel_subkey; + VbPublicKey* kernel_subkey = NULL; + int free_kernel_subkey = 0; GptData gpt; uint64_t part_start, part_size; uint64_t blba; @@ -233,8 +234,10 @@ VbError_t LoadKernel(LoadKernelParams *params) if (kBootRecovery == boot_mode) { /* Use the recovery key to verify the kernel */ - kernel_subkey = (VbPublicKey*) - ((uint8_t*)gbb + gbb->recovery_key_offset); + retval = VbGbbReadRecoveryKey(cparams, &kernel_subkey); + if (VBERROR_SUCCESS != retval) + goto LoadKernelExit; + free_kernel_subkey = 1; } else { /* Use the kernel subkey passed from LoadFirmware(). */ kernel_subkey = &shared->kernel_subkey; @@ -632,5 +635,8 @@ VbError_t LoadKernel(LoadKernelParams *params) /* Store how much shared data we used, if any */ params->shared_data_size = shared->data_used; + if (free_kernel_subkey) + VbExFree(kernel_subkey); + return retval; } |