summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile18
-rw-r--r--firmware/include/gbb_access.h83
-rw-r--r--firmware/include/region.h55
-rw-r--r--firmware/include/vboot_api.h41
-rw-r--r--firmware/lib/include/load_kernel_fw.h2
-rw-r--r--firmware/lib/include/vboot_display.h5
-rw-r--r--firmware/lib/include/vboot_kernel.h6
-rw-r--r--firmware/lib/region-fw.c55
-rw-r--r--firmware/lib/region-init.c50
-rw-r--r--firmware/lib/region-kernel.c200
-rw-r--r--firmware/lib/vboot_api_firmware.c14
-rw-r--r--firmware/lib/vboot_api_init.c21
-rw-r--r--firmware/lib/vboot_api_kernel.c33
-rw-r--r--firmware/lib/vboot_audio.c3
-rw-r--r--firmware/lib/vboot_display.c233
-rw-r--r--firmware/lib/vboot_firmware.c13
-rw-r--r--firmware/lib/vboot_kernel.c18
-rw-r--r--firmware/linktest/main.c2
-rw-r--r--firmware/stub/vboot_api_stub_region.c21
-rw-r--r--tests/vboot_api_devmode_tests.c1
-rw-r--r--tests/vboot_api_firmware_tests.c7
-rw-r--r--tests/vboot_api_init_tests.c1
-rw-r--r--tests/vboot_api_kernel2_tests.c1
-rw-r--r--tests/vboot_api_kernel4_tests.c1
-rw-r--r--tests/vboot_api_kernel_tests.c2
-rw-r--r--tests/vboot_audio_tests.c1
-rw-r--r--tests/vboot_display_tests.c55
-rw-r--r--tests/vboot_firmware_tests.c24
-rw-r--r--tests/vboot_kernel_tests.c114
-rw-r--r--tests/vboot_region_tests.c213
-rw-r--r--utility/load_kernel_test.c5
31 files changed, 1044 insertions, 254 deletions
diff --git a/Makefile b/Makefile
index 403b4d62..b810a5f5 100644
--- a/Makefile
+++ b/Makefile
@@ -239,6 +239,7 @@ VBINIT_SRCS = \
firmware/lib/vboot_api_init.c \
firmware/lib/vboot_common_init.c \
firmware/lib/vboot_nvstorage.c \
+ firmware/lib/region-init.c \
# Additional firmware library sources needed by VbSelectFirmware() call
VBSF_SRCS = \
@@ -252,7 +253,8 @@ VBSF_SRCS = \
firmware/lib/stateful_util.c \
firmware/lib/vboot_api_firmware.c \
firmware/lib/vboot_common.c \
- firmware/lib/vboot_firmware.c
+ firmware/lib/vboot_firmware.c \
+ firmware/lib/region-fw.c \
# Additional firmware library sources needed by VbSelectAndLoadKernel() call
VBSLK_SRCS = \
@@ -264,7 +266,8 @@ VBSLK_SRCS = \
firmware/lib/vboot_api_kernel.c \
firmware/lib/vboot_audio.c \
firmware/lib/vboot_display.c \
- firmware/lib/vboot_kernel.c
+ firmware/lib/vboot_kernel.c \
+ firmware/lib/region-kernel.c \
# Support real TPM unless BIOS sets MOCK_TPM
ifeq (${MOCK_TPM},)
@@ -289,7 +292,8 @@ ifeq (${FIRMWARE_ARCH},)
VBINIT_SRCS += \
firmware/stub/tpm_lite_stub.c \
firmware/stub/utility_stub.c \
- firmware/stub/vboot_api_stub_init.c
+ firmware/stub/vboot_api_stub_init.c \
+ firmware/stub/vboot_api_stub_region.c
VBSF_SRCS += \
firmware/stub/vboot_api_stub_sf.c
@@ -533,6 +537,10 @@ TEST_NAMES = \
tests/vboot_nvstorage_test \
tests/futility/test_not_really
+ifdef REGION_READ
+TEST_NAMES += tests/vboot_region_tests
+endif
+
# TODO: port these tests to new API, if not already eqivalent
# functionality in other tests. These don't even compile at present.
#
@@ -642,6 +650,10 @@ ${FWLIB_OBJS}: CFLAGS += -DSAVE_LOCALE_IMMEDIATELY
${FWLIB_OBJS}: CFLAGS += -DCOPY_BMP_DATA
endif
+ifdef REGION_READ
+${FWLIB_OBJS}: CFLAGS += -DREGION_READ
+endif
+
ifeq (${FIRMWARE_ARCH},)
# Disable rollback TPM when compiling locally, since otherwise
# load_kernel_test attempts to talk to the TPM.
diff --git a/firmware/include/gbb_access.h b/firmware/include/gbb_access.h
new file mode 100644
index 00000000..b94d0cdb
--- /dev/null
+++ b/firmware/include/gbb_access.h
@@ -0,0 +1,83 @@
+/* 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.
+ *
+ * Access to portions of the GBB using the region API.
+ */
+
+#ifndef VBOOT_REFERENCE_GBB_ACCESS_H_
+#define VBOOT_REFERENCE_GBB_ACCESS_H_
+
+#include "vboot_api.h"
+
+struct BmpBlockHeader;
+struct ImageInfo;
+struct GoogleBinaryBlockHeader;
+struct ScreenLayout;
+struct VbPublicKey;
+
+/**
+ * Read the GBB header
+ *
+ * This accesses the GBB and reads its header.
+ *
+ * @param cparams Vboot common parameters
+ * @param gbb Place to put GBB header
+ */
+VbError_t VbGbbReadHeader_static(VbCommonParams *cparams,
+ struct GoogleBinaryBlockHeader *gbb);
+
+/**
+ * Read the root key from the GBB
+ *
+ * @param cparams Vboot common parameters
+ * @param keyp Returns a pointer to the key. The caller must call
+ * VbExFree() on the key when finished with it.
+ * @return VBERROR_... error, VBERROR_SUCCESS on success,
+ */
+VbError_t VbGbbReadRootKey(VbCommonParams *cparams,
+ struct VbPublicKey **keyp);
+
+/**
+ * Read the recovery key from the GBB
+ *
+ * @param cparams Vboot common parameters
+ * @param keyp Returns a pointer to the key. The caller must call
+ * VbExFree() on the key when finished with it.
+ * @return VBERROR_... error, VBERROR_SUCCESS on success,
+ */
+VbError_t VbGbbReadRecoveryKey(VbCommonParams *cparams,
+ struct VbPublicKey **keyp);
+
+/**
+ * Read the bitmap block header from the GBB
+ *
+ * @param cparams Vboot common parameters
+ * @param hdr The header is placed in this block
+ * @return VBERROR_... error, VBERROR_SUCCESS on success,
+ */
+VbError_t VbGbbReadBmpHeader(VbCommonParams *cparams,
+ struct BmpBlockHeader *hdr);
+
+/**
+ * Read a image from the GBB
+ *
+ * The caller must call VbExFree() on *image_datap when finished with it.
+ *
+ * @param cparams Vboot common parameters
+ * @param localization Localization/language number
+ * @param screen_index Index of screen to display (VB_SCREEN_...)
+ * @param image_num Image number within the screen
+ * @param layout Returns layout information (x, y position)
+ * @param image_info Returns information about the image (format)
+ * @param image_datap Returns a pointer to the image data
+ * @param iamge_data_sizep Return size of image data
+ * @return VBERROR_... error, VBERROR_SUCCESS on success,
+ */
+VbError_t VbGbbReadImage(VbCommonParams *cparams,
+ uint32_t localization, uint32_t screen_index,
+ uint32_t image_num, struct ScreenLayout *layout,
+ struct ImageInfo *image_info, char **image_datap,
+ uint32_t *image_data_sizep);
+
+#endif
diff --git a/firmware/include/region.h b/firmware/include/region.h
new file mode 100644
index 00000000..78e1dba0
--- /dev/null
+++ b/firmware/include/region.h
@@ -0,0 +1,55 @@
+/* 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.
+ *
+ * Access to portions of the firmware image, perhaps later to be expanded
+ * to other devices.
+ */
+
+#ifndef VBOOT_REFERENCE_REGION_H_
+#define VBOOT_REFERENCE_REGION_H_
+
+#include "bmpblk_header.h"
+#include "gbb_header.h"
+#include "vboot_api.h"
+#include "vboot_struct.h"
+
+/* The maximum length of a hardware ID */
+#define VB_REGION_HWID_LEN 256
+
+/**
+ * Read data from a region
+ *
+ * @param cparams Vboot common parameters
+ * @param region Region number to read
+ * @param offset Offset within region to start reading
+ * @param size Size of data to read
+ * @param buf Buffer to put the data into
+ * @return VBERROR_... error, VBERROR_SUCCESS on success,
+ */
+VbError_t VbRegionReadData(VbCommonParams *cparams,
+ enum vb_firmware_region region, uint32_t offset,
+ uint32_t size, void *buf);
+
+/**
+ * Check the version of the GBB and print debug information if valid
+ *
+ * @param cparams Vboot common parameters
+ */
+void VbRegionCheckVersion(VbCommonParams *cparams);
+
+/**
+ * Read the hardware ID from the GBB
+ *
+ * @param cparams Vboot common parameters
+ * @param hwid Place to put HWID, which will be null-terminated
+ * @param max_size Maximum size of HWID including terminated null
+ * character (suggest VB_REGION_HWID_LEN). If this size
+ * it too small then VBERROR_INVALID_PARAMETER is
+ * returned.
+ * @return VBERROR_... error, VBERROR_SUCCESS on success,
+ */
+VbError_t VbRegionReadHWID(VbCommonParams *cparams, char *hwid,
+ uint32_t max_size);
+
+#endif /* VBOOT_REFERENCE_REGION_H_ */
diff --git a/firmware/include/vboot_api.h b/firmware/include/vboot_api.h
index 10adc377..214da753 100644
--- a/firmware/include/vboot_api.h
+++ b/firmware/include/vboot_api.h
@@ -104,6 +104,14 @@ enum VbErrorPredefined_t {
VBERROR_VGA_OPROM_MISMATCH = 0x10021,
/* Need EC to reboot to read-only code */
VBERROR_EC_REBOOT_TO_RO_REQUIRED = 0x10022,
+ /* Invalid region read parameters */
+ VBERROR_REGION_READ_INVALID = 0x10023,
+ /* Cannot read from region */
+ VBERROR_REGION_READ_FAILED = 0x10024,
+ /* Unsupported region type */
+ VBERROR_UNSUPPORTED_REGION = 0x10025,
+ /* No image present (returned from VbGbbReadImage() for missing image) */
+ VBERROR_NO_IMAGE_PRESENT = 0x10026,
/* VbExEcGetExpectedRWHash() may return the following codes */
/* Compute expected RW hash from the EC image; BIOS doesn't have it */
@@ -167,6 +175,10 @@ typedef struct VbCommonParams {
* the stack.
*/
void *caller_context;
+
+ /* For internal use of Vboot - do not examine or modify! */
+ struct GoogleBinaryBlockHeader *gbb;
+ struct BmpBlockHeader *bmp;
} VbCommonParams;
/* Flags for VbInitParams.flags */
@@ -827,4 +839,33 @@ enum {
*/
int VbExLegacy(void);
+/* Regions for VbExRegionRead() */
+enum vb_firmware_region {
+ VB_REGION_GBB, /* Google Binary Block - see gbbheader.h */
+
+ VB_REGION_COUNT,
+};
+
+/**
+ * Read data from a region of the firmware image
+ *
+ * Vboot wants access to a region, to read data from it. This function
+ * reads it (typically from the firmware image such as SPI flash) and
+ * returns the data.
+ *
+ * cparams is passed so that the boot loader has some context for the
+ * operation.
+ *
+ * @param cparams Common parameters, e.g. use member caller_context
+ * to point to useful context data
+ * @param region Firmware region to read
+ * @param offset Start offset within region
+ * @param size Number of bytes to read
+ * @param buf Place to put data
+ * @return VBERROR_... error, VBERROR_SUCCESS on success,
+ */
+VbError_t VbExRegionRead(VbCommonParams *cparams,
+ enum vb_firmware_region region, uint32_t offset,
+ uint32_t size, void *buf);
+
#endif /* VBOOT_REFERENCE_VBOOT_API_H_ */
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..e2c6488a
--- /dev/null
+++ b/firmware/lib/region-fw.c
@@ -0,0 +1,55 @@
+/* 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_access.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..bec0450d
--- /dev/null
+++ b/firmware/lib/region-init.c
@@ -0,0 +1,50 @@
+/* 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_access.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..84d474da
--- /dev/null
+++ b/firmware/lib/region-kernel.c
@@ -0,0 +1,200 @@
+/* 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_access.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;
}
diff --git a/firmware/linktest/main.c b/firmware/linktest/main.c
index bdf1483a..2ff8e9d7 100644
--- a/firmware/linktest/main.c
+++ b/firmware/linktest/main.c
@@ -27,7 +27,7 @@ int main(void)
LoadFirmware(0, 0, 0);
/* load_kernel_fw.h */
- LoadKernel(0);
+ LoadKernel(0, 0);
/* rollback_index.h */
RollbackS3Resume();
diff --git a/firmware/stub/vboot_api_stub_region.c b/firmware/stub/vboot_api_stub_region.c
new file mode 100644
index 00000000..07142035
--- /dev/null
+++ b/firmware/stub/vboot_api_stub_region.c
@@ -0,0 +1,21 @@
+/* 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.
+ *
+ * Stub implementations of region API function.
+ */
+
+#include <stdint.h>
+
+#define _STUB_IMPLEMENTATION_
+
+#include <stdlib.h>
+
+#include "vboot_api.h"
+
+VbError_t VbExRegionRead(VbCommonParams *cparams,
+ enum vb_firmware_region region, uint32_t offset,
+ uint32_t size, void *buf)
+{
+ return VBERROR_SUCCESS;
+}
diff --git a/tests/vboot_api_devmode_tests.c b/tests/vboot_api_devmode_tests.c
index b10bba67..61f0de14 100644
--- a/tests/vboot_api_devmode_tests.c
+++ b/tests/vboot_api_devmode_tests.c
@@ -153,6 +153,7 @@ static void ResetMocks(void) {
cparams.shared_data_size = sizeof(shared_data);
cparams.shared_data_blob = shared_data;
cparams.gbb_data = &gbb;
+ cparams.gbb = &gbb;
Memset(&lkparams, 0, sizeof(lkparams));
diff --git a/tests/vboot_api_firmware_tests.c b/tests/vboot_api_firmware_tests.c
index 9e7c441d..4a97b930 100644
--- a/tests/vboot_api_firmware_tests.c
+++ b/tests/vboot_api_firmware_tests.c
@@ -9,6 +9,7 @@
#include <stdio.h>
#include <stdlib.h>
+#include "gbb_header.h"
#include "host_common.h"
#include "rollback_index.h"
#include "test_common.h"
@@ -23,6 +24,7 @@
/* Mock data */
static VbCommonParams cparams;
static VbSelectFirmwareParams fparams;
+static GoogleBinaryBlockHeader gbb;
static VbNvContext vnc;
static uint8_t shared_data[VB_SHARED_DATA_MIN_SIZE];
static VbSharedDataHeader* shared = (VbSharedDataHeader*)shared_data;
@@ -49,6 +51,11 @@ static void ResetMocks(void) {
Memset(&fparams, 0, sizeof(fparams));
+ Memset(&gbb, 0, sizeof(gbb));
+ cparams.gbb_data = &gbb;
+ cparams.gbb_size = sizeof(gbb);
+ cparams.gbb = &gbb;
+
Memset(&vnc, 0, sizeof(vnc));
VbNvSetup(&vnc);
VbNvTeardown(&vnc); /* So CRC gets generated */
diff --git a/tests/vboot_api_init_tests.c b/tests/vboot_api_init_tests.c
index 6451bd81..9aa34b41 100644
--- a/tests/vboot_api_init_tests.c
+++ b/tests/vboot_api_init_tests.c
@@ -40,6 +40,7 @@ static void ResetMocks(void)
cparams.shared_data_size = sizeof(shared_data);
cparams.shared_data_blob = shared_data;
cparams.gbb_data = &gbb;
+ cparams.gbb_size = sizeof(gbb);
Memset(&gbb, 0, sizeof(gbb));
gbb.major_version = GBB_MAJOR_VER;
diff --git a/tests/vboot_api_kernel2_tests.c b/tests/vboot_api_kernel2_tests.c
index c1572c2f..323f5f66 100644
--- a/tests/vboot_api_kernel2_tests.c
+++ b/tests/vboot_api_kernel2_tests.c
@@ -49,6 +49,7 @@ static void ResetMocks(void)
cparams.shared_data_size = sizeof(shared_data);
cparams.shared_data_blob = shared_data;
cparams.gbb_data = &gbb;
+ cparams.gbb = &gbb;
Memset(&gbb, 0, sizeof(gbb));
gbb.major_version = GBB_MAJOR_VER;
diff --git a/tests/vboot_api_kernel4_tests.c b/tests/vboot_api_kernel4_tests.c
index e2155f56..82b15016 100644
--- a/tests/vboot_api_kernel4_tests.c
+++ b/tests/vboot_api_kernel4_tests.c
@@ -41,6 +41,7 @@ static void ResetMocks(void)
cparams.shared_data_size = sizeof(shared_data);
cparams.shared_data_blob = shared_data;
cparams.gbb_data = &gbb;
+ cparams.gbb_size = sizeof(gbb);
Memset(&kparams, 0, sizeof(kparams));
diff --git a/tests/vboot_api_kernel_tests.c b/tests/vboot_api_kernel_tests.c
index 87dc6cfa..8cfc1cb4 100644
--- a/tests/vboot_api_kernel_tests.c
+++ b/tests/vboot_api_kernel_tests.c
@@ -269,7 +269,7 @@ VbError_t VbExDiskFreeInfo(VbDiskInfo *infos,
return VBERROR_SUCCESS;
}
-VbError_t LoadKernel(LoadKernelParams *params)
+VbError_t LoadKernel(LoadKernelParams *params, VbCommonParams *cparams)
{
got_find_disk = (const char *)params->disk_handle;
VBDEBUG(("%s(%d): got_find_disk = %s\n", __FUNCTION__,
diff --git a/tests/vboot_audio_tests.c b/tests/vboot_audio_tests.c
index 23667b1e..d674931d 100644
--- a/tests/vboot_audio_tests.c
+++ b/tests/vboot_audio_tests.c
@@ -62,6 +62,7 @@ static void ResetMocks(void) {
VBDEBUG(("ResetMocks()\n"));
Memset(&cparams, 0, sizeof(cparams));
cparams.gbb_data = &gbb;
+ cparams.gbb = &gbb;
Memset(&gbb, 0, sizeof(gbb));
gbb.major_version = GBB_MAJOR_VER;
gbb.minor_version = GBB_MINOR_VER;
diff --git a/tests/vboot_display_tests.c b/tests/vboot_display_tests.c
index 8e4a3a27..8086d319 100644
--- a/tests/vboot_display_tests.c
+++ b/tests/vboot_display_tests.c
@@ -13,9 +13,11 @@
#include "bmpblk_font.h"
#include "gbb_header.h"
#include "host_common.h"
+#include "region.h"
#include "test_common.h"
#include "vboot_common.h"
#include "vboot_display.h"
+#include "vboot_kernel.h"
#include "vboot_nvstorage.h"
/* Mock data */
@@ -59,6 +61,20 @@ static void ResetMocks(void)
cparams.gbb_data = gbb;
cparams.gbb_size = sizeof(gbb_data);
+ /*
+ * Note, VbApiKernelFree() expects this to be allocated by
+ * VbExMalloc(), so we cannot just assign it staticly.
+ */
+ cparams.gbb = VbExMalloc(sizeof(*gbb));
+ gbb->header_size = sizeof(*gbb);
+ gbb->rootkey_offset = gbb_used;
+ gbb->rootkey_size = 64;
+ gbb_used += 64;
+ gbb->recovery_key_offset = gbb_used;
+ gbb->recovery_key_size = 64;
+ gbb_used += 64;
+ memcpy(cparams.gbb, gbb, sizeof(*gbb));
+
Memset(&vnc, 0, sizeof(vnc));
VbNvSetup(&vnc);
VbNvTeardown(&vnc); /* So CRC gets generated */
@@ -81,6 +97,7 @@ VbError_t VbExDisplayDebugInfo(const char *info_str)
/* Test displaying debug info */
static void DebugInfoTest(void)
{
+ char hwid[VB_REGION_HWID_LEN];
int i;
/* Recovery string should be non-null for any code */
@@ -89,28 +106,39 @@ static void DebugInfoTest(void)
/* HWID should come from the gbb */
ResetMocks();
- TEST_EQ(strcmp(VbHWID(&cparams), "Test HWID"), 0, "HWID");
+ VbRegionReadHWID(&cparams, hwid, sizeof(hwid));
+ TEST_EQ(strcmp(hwid, "Test HWID"), 0, "HWID");
+ VbApiKernelFree(&cparams);
ResetMocks();
cparams.gbb_size = 0;
- TEST_EQ(strcmp(VbHWID(&cparams), "{INVALID}"), 0, "HWID bad gbb");
+ VbRegionReadHWID(&cparams, hwid, sizeof(hwid));
+ TEST_EQ(strcmp(hwid, "{INVALID}"), 0, "HWID bad gbb");
+ VbApiKernelFree(&cparams);
ResetMocks();
- gbb->hwid_size = 0;
- TEST_EQ(strcmp(VbHWID(&cparams), "{INVALID}"), 0, "HWID missing");
+ cparams.gbb->hwid_size = 0;
+ VbRegionReadHWID(&cparams, hwid, sizeof(hwid));
+ TEST_EQ(strcmp(hwid, "{INVALID}"), 0, "HWID missing");
+ VbApiKernelFree(&cparams);
ResetMocks();
- gbb->hwid_offset = cparams.gbb_size + 1;
- TEST_EQ(strcmp(VbHWID(&cparams), "{INVALID}"), 0, "HWID past end");
+ cparams.gbb->hwid_offset = cparams.gbb_size + 1;
+ VbRegionReadHWID(&cparams, hwid, sizeof(hwid));
+ TEST_EQ(strcmp(hwid, "{INVALID}"), 0, "HWID past end");
+ VbApiKernelFree(&cparams);
ResetMocks();
- gbb->hwid_size = cparams.gbb_size;
- TEST_EQ(strcmp(VbHWID(&cparams), "{INVALID}"), 0, "HWID overflow");
+ cparams.gbb->hwid_size = cparams.gbb_size;
+ VbRegionReadHWID(&cparams, hwid, sizeof(hwid));
+ TEST_EQ(strcmp(hwid, "{INVALID}"), 0, "HWID overflow");
+ VbApiKernelFree(&cparams);
/* Display debug info */
ResetMocks();
VbDisplayDebugInfo(&cparams, &vnc);
TEST_NEQ(*debug_info, '\0', "Some debug info was displayed");
+ VbApiKernelFree(&cparams);
}
/* Test localization */
@@ -119,21 +147,23 @@ static void LocalizationTest(void)
uint32_t count = 6;
ResetMocks();
- gbb->bmpfv_size = 0;
+ cparams.gbb->bmpfv_size = 0;
TEST_EQ(VbGetLocalizationCount(&cparams, &count),
VBERROR_INVALID_GBB, "VbGetLocalizationCount bad gbb");
TEST_EQ(count, 0, " count");
+ VbApiKernelFree(&cparams);
ResetMocks();
bhdr->signature[0] ^= 0x5a;
TEST_EQ(VbGetLocalizationCount(&cparams, &count),
VBERROR_INVALID_BMPFV, "VbGetLocalizationCount bad bmpfv");
+ VbApiKernelFree(&cparams);
ResetMocks();
TEST_EQ(VbGetLocalizationCount(&cparams, &count), 0,
"VbGetLocalizationCount()");
TEST_EQ(count, 3, " count");
-
+ VbApiKernelFree(&cparams);
}
/* Test display key checking */
@@ -144,10 +174,12 @@ static void DisplayKeyTest(void)
ResetMocks();
VbCheckDisplayKey(&cparams, 'q', &vnc);
TEST_EQ(*debug_info, '\0', "DisplayKey q = does nothing");
+ VbApiKernelFree(&cparams);
ResetMocks();
VbCheckDisplayKey(&cparams, '\t', &vnc);
TEST_NEQ(*debug_info, '\0', "DisplayKey tab = display");
+ VbApiKernelFree(&cparams);
/* Toggle localization */
ResetMocks();
@@ -165,6 +197,7 @@ static void DisplayKeyTest(void)
VbCheckDisplayKey(&cparams, VB_KEY_UP, &vnc);
VbNvGet(&vnc, VBNV_LOCALIZATION_INDEX, &u);
TEST_EQ(u, 0, "DisplayKey up");
+ VbApiKernelFree(&cparams);
/* Reset localization if localization count is invalid */
ResetMocks();
@@ -174,7 +207,7 @@ static void DisplayKeyTest(void)
VbCheckDisplayKey(&cparams, VB_KEY_UP, &vnc);
VbNvGet(&vnc, VBNV_LOCALIZATION_INDEX, &u);
TEST_EQ(u, 0, "DisplayKey invalid");
-
+ VbApiKernelFree(&cparams);
}
static void FontTest(void)
diff --git a/tests/vboot_firmware_tests.c b/tests/vboot_firmware_tests.c
index f6b96fec..724e7f8b 100644
--- a/tests/vboot_firmware_tests.c
+++ b/tests/vboot_firmware_tests.c
@@ -8,6 +8,7 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include "gbb_header.h"
#include "host_common.h"
@@ -33,13 +34,20 @@ static uint8_t* digest_returned;
static uint8_t* digest_expect_ptr;
static int hash_fw_index;
+#define TEST_KEY_DATA \
+ "Test contents for the root key this should be 64 chars long."
+
/* Reset mock data (for use before each test) */
static void ResetMocks(void) {
+ VbPublicKey *root_key;
+ uint8_t *root_key_data;
int i;
Memset(&cparams, 0, sizeof(cparams));
cparams.shared_data_blob = shared_data;
cparams.gbb_data = gbb_data;
+ cparams.gbb_size = sizeof(gbb_data);
+ cparams.gbb = gbb;
Memset(&fparams, 0, sizeof(fparams));
fparams.verification_block_A = vblock;
@@ -75,6 +83,14 @@ static void ResetMocks(void) {
Memset(&gbb_data, 0, sizeof(gbb_data));
gbb->rootkey_offset = sizeof(GoogleBinaryBlockHeader);
+ root_key = (VbPublicKey *)(gbb_data + gbb->rootkey_offset);
+ root_key_data = (uint8_t *)(root_key + 1);
+ strcpy((char *)root_key_data, TEST_KEY_DATA);
+ PublicKeyInit(root_key, (uint8_t *)root_key_data, sizeof(TEST_KEY_DATA));
+
+ gbb->major_version = GBB_MAJOR_VER;
+ gbb->minor_version = GBB_MINOR_VER;
+ gbb->flags = 0;
Memset(&data_key, 0, sizeof(data_key));
@@ -91,7 +107,13 @@ int KeyBlockVerify(const VbKeyBlockHeader* block, uint64_t size,
const VbPublicKey *key, int hash_only) {
TEST_EQ(hash_only, 0, " Don't verify firmware with hash");
- TEST_PTR_EQ(key, gbb_data + gbb->rootkey_offset, " Verify with root key");
+
+ /*
+ * We cannot check the address of key, since it will be allocated. We
+ * check the contents instead.
+ */
+ TEST_STR_EQ((char *)GetPublicKeyDataC(key), TEST_KEY_DATA,
+ " Verify with root key");
TEST_NEQ(block==vblock || block==vblock+1, 0, " Verify a valid key block");
/* Mock uses header_version_major to hold return value */
diff --git a/tests/vboot_kernel_tests.c b/tests/vboot_kernel_tests.c
index 6992e94a..8dde9cb6 100644
--- a/tests/vboot_kernel_tests.c
+++ b/tests/vboot_kernel_tests.c
@@ -47,7 +47,8 @@ static int verify_data_fail;
static RSAPublicKey *mock_data_key;
static int mock_data_key_allocated;
-static GoogleBinaryBlockHeader gbb;
+static uint8_t gbb_data[sizeof(GoogleBinaryBlockHeader) + 2048];
+static GoogleBinaryBlockHeader *gbb = (GoogleBinaryBlockHeader*)gbb_data;
static VbExDiskHandle_t handle;
static VbNvContext vnc;
static uint8_t shared_data[VB_SHARED_DATA_MIN_SIZE];
@@ -55,6 +56,7 @@ static VbSharedDataHeader *shared = (VbSharedDataHeader *)shared_data;
static LoadKernelParams lkp;
static VbKeyBlockHeader kbh;
static VbKernelPreambleHeader kph;
+static VbCommonParams cparams;
static void ResetCallLog(void)
{
@@ -79,10 +81,15 @@ static void ResetMocks(void)
mock_data_key = (RSAPublicKey *)"TestDataKey";
mock_data_key_allocated = 0;
- memset(&gbb, 0, sizeof(gbb));
- gbb.major_version = GBB_MAJOR_VER;
- gbb.minor_version = GBB_MINOR_VER;
- gbb.flags = 0;
+ memset(gbb, 0, sizeof(gbb));
+ gbb->major_version = GBB_MAJOR_VER;
+ gbb->minor_version = GBB_MINOR_VER;
+ gbb->flags = 0;
+
+ memset(&cparams, '\0', sizeof(cparams));
+ cparams.gbb = gbb;
+ cparams.gbb_data = gbb;
+ cparams.gbb_size = sizeof(gbb_data);
memset(&vnc, 0, sizeof(vnc));
VbNvSetup(&vnc);
@@ -95,7 +102,8 @@ static void ResetMocks(void)
memset(&lkp, 0, sizeof(lkp));
lkp.nv_context = &vnc;
lkp.shared_data_blob = shared;
- lkp.gbb_data = &gbb;
+ lkp.gbb_data = gbb;
+ lkp.gbb_size = sizeof(gbb_data);
lkp.bytes_per_lba = 512;
lkp.ending_lba = 1023;
lkp.kernel_buffer = kernel_buffer;
@@ -129,6 +137,8 @@ VbError_t VbExDiskRead(VbExDiskHandle_t handle, uint64_t lba_start,
if ((int)lba_start == disk_read_to_fail)
return VBERROR_SIMULATED;
+ /* Keep valgrind happy */
+ Memset(buffer, '\0', lba_count);
return VBERROR_SUCCESS;
}
@@ -238,6 +248,11 @@ static void ReadWriteGptTest(void)
"VbExDiskRead(h, 991, 32)\n"
"VbExDiskRead(h, 1023, 1)\n");
ResetCallLog();
+ /*
+ * Valgrind complains about access to uninitialized memory here, so
+ * zero the primary header before each test.
+ */
+ Memset(g.primary_header, '\0', g.sector_bytes);
TEST_EQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree");
TEST_CALLS("");
@@ -246,6 +261,7 @@ static void ReadWriteGptTest(void)
AllocAndReadGptData(handle, &g);
g.modified |= GPT_MODIFIED_HEADER1 | GPT_MODIFIED_ENTRIES1;
ResetCallLog();
+ Memset(g.primary_header, '\0', g.sector_bytes);
TEST_EQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree mod 1");
TEST_CALLS("VbExDiskWrite(h, 1, 1)\n"
"VbExDiskWrite(h, 2, 32)\n");
@@ -255,6 +271,7 @@ static void ReadWriteGptTest(void)
AllocAndReadGptData(handle, &g);
g.modified = -1;
ResetCallLog();
+ Memset(g.primary_header, '\0', g.sector_bytes);
TEST_EQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree mod all");
TEST_CALLS("VbExDiskWrite(h, 1, 1)\n"
"VbExDiskWrite(h, 2, 32)\n"
@@ -276,21 +293,25 @@ static void ReadWriteGptTest(void)
ResetMocks();
disk_read_to_fail = 1;
TEST_NEQ(AllocAndReadGptData(handle, &g), 0, "AllocAndRead disk fail");
+ Memset(g.primary_header, '\0', g.sector_bytes);
WriteAndFreeGptData(handle, &g);
ResetMocks();
disk_read_to_fail = 2;
TEST_NEQ(AllocAndReadGptData(handle, &g), 0, "AllocAndRead disk fail");
+ Memset(g.primary_header, '\0', g.sector_bytes);
WriteAndFreeGptData(handle, &g);
ResetMocks();
disk_read_to_fail = 991;
TEST_NEQ(AllocAndReadGptData(handle, &g), 0, "AllocAndRead disk fail");
+ Memset(g.primary_header, '\0', g.sector_bytes);
WriteAndFreeGptData(handle, &g);
ResetMocks();
disk_read_to_fail = 1023;
TEST_NEQ(AllocAndReadGptData(handle, &g), 0, "AllocAndRead disk fail");
+ Memset(g.primary_header, '\0', g.sector_bytes);
WriteAndFreeGptData(handle, &g);
/* Error writing */
@@ -298,24 +319,28 @@ static void ReadWriteGptTest(void)
disk_write_to_fail = 1;
AllocAndReadGptData(handle, &g);
g.modified = -1;
+ Memset(g.primary_header, '\0', g.sector_bytes);
TEST_NEQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree disk fail");
ResetMocks();
disk_write_to_fail = 2;
AllocAndReadGptData(handle, &g);
g.modified = -1;
+ Memset(g.primary_header, '\0', g.sector_bytes);
TEST_NEQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree disk fail");
ResetMocks();
disk_write_to_fail = 991;
AllocAndReadGptData(handle, &g);
g.modified = -1;
+ Memset(g.primary_header, '\0', g.sector_bytes);
TEST_NEQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree disk fail");
ResetMocks();
disk_write_to_fail = 1023;
AllocAndReadGptData(handle, &g);
g.modified = -1;
+ Memset(g.primary_header, '\0', g.sector_bytes);
TEST_NEQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree disk fail");
}
@@ -327,23 +352,28 @@ static void InvalidParamsTest(void)
{
ResetMocks();
lkp.bytes_per_lba = 0;
- TEST_EQ(LoadKernel(&lkp), VBERROR_INVALID_PARAMETER, "Bad lba size");
+ TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_PARAMETER,
+ "Bad lba size");
ResetMocks();
lkp.ending_lba = 0;
- TEST_EQ(LoadKernel(&lkp), VBERROR_INVALID_PARAMETER, "Bad lba count");
+ TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_PARAMETER,
+ "Bad lba count");
ResetMocks();
lkp.bytes_per_lba = 128*1024;
- TEST_EQ(LoadKernel(&lkp), VBERROR_INVALID_PARAMETER, "Huge lba size");
+ TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_PARAMETER,
+ "Huge lba size");
ResetMocks();
disk_read_to_fail = 1;
- TEST_EQ(LoadKernel(&lkp), VBERROR_NO_KERNEL_FOUND, "Can't read disk");
+ TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_NO_KERNEL_FOUND,
+ "Can't read disk");
ResetMocks();
gpt_init_fail = 1;
- TEST_EQ(LoadKernel(&lkp), VBERROR_NO_KERNEL_FOUND, "Bad GPT");
+ TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_NO_KERNEL_FOUND,
+ "Bad GPT");
}
static void LoadKernelTest(void)
@@ -351,7 +381,7 @@ static void LoadKernelTest(void)
uint32_t u;
ResetMocks();
- TEST_EQ(LoadKernel(&lkp), 0, "First kernel good");
+ TEST_EQ(LoadKernel(&lkp, &cparams), 0, "First kernel good");
TEST_EQ(lkp.partition_number, 1, " part num");
TEST_EQ(lkp.bootloader_address, 0xbeadd008, " bootloader addr");
TEST_EQ(lkp.bootloader_size, 0x1234, " bootloader size");
@@ -362,46 +392,46 @@ static void LoadKernelTest(void)
ResetMocks();
mock_parts[1].start = 300;
mock_parts[1].size = 150;
- TEST_EQ(LoadKernel(&lkp), 0, "Two good kernels");
+ TEST_EQ(LoadKernel(&lkp, &cparams), 0, "Two good kernels");
TEST_EQ(lkp.partition_number, 1, " part num");
TEST_EQ(mock_part_next, 1, " didn't read second one");
/* Fail if no kernels found */
ResetMocks();
mock_parts[0].size = 0;
- TEST_EQ(LoadKernel(&lkp), VBERROR_NO_KERNEL_FOUND, "No kernels");
+ TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_NO_KERNEL_FOUND, "No kernels");
VbNvGet(&vnc, VBNV_RECOVERY_REQUEST, &u);
TEST_EQ(u, VBNV_RECOVERY_RW_NO_OS, " recovery request");
/* Skip kernels which are too small */
ResetMocks();
mock_parts[0].size = 10;
- TEST_EQ(LoadKernel(&lkp), VBERROR_INVALID_KERNEL_FOUND, "Too small");
+ TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND, "Too small");
VbNvGet(&vnc, VBNV_RECOVERY_REQUEST, &u);
TEST_EQ(u, VBNV_RECOVERY_RW_INVALID_OS, " recovery request");
ResetMocks();
disk_read_to_fail = 100;
- TEST_EQ(LoadKernel(&lkp), VBERROR_INVALID_KERNEL_FOUND,
+ TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
"Fail reading kernel start");
ResetMocks();
key_block_verify_fail = 1;
- TEST_EQ(LoadKernel(&lkp), VBERROR_INVALID_KERNEL_FOUND,
+ TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
"Fail key block sig");
/* In dev mode, fail if hash is bad too */
ResetMocks();
lkp.boot_flags |= BOOT_FLAG_DEVELOPER;
key_block_verify_fail = 2;
- TEST_EQ(LoadKernel(&lkp), VBERROR_INVALID_KERNEL_FOUND,
+ TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
"Fail key block dev hash");
/* But just bad sig is ok */
ResetMocks();
lkp.boot_flags |= BOOT_FLAG_DEVELOPER;
key_block_verify_fail = 1;
- TEST_EQ(LoadKernel(&lkp), 0, "Succeed key block dev sig");
+ TEST_EQ(LoadKernel(&lkp, &cparams), 0, "Succeed key block dev sig");
/* In dev mode and requiring signed kernel, fail if sig is bad */
ResetMocks();
@@ -409,124 +439,126 @@ static void LoadKernelTest(void)
VbNvSet(&vnc, VBNV_DEV_BOOT_SIGNED_ONLY, 1);
VbNvTeardown(&vnc);
key_block_verify_fail = 1;
- TEST_EQ(LoadKernel(&lkp), VBERROR_INVALID_KERNEL_FOUND,
+ TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
"Fail key block dev sig");
/* Check key block flag mismatches */
ResetMocks();
kbh.key_block_flags =
KEY_BLOCK_FLAG_RECOVERY_0 | KEY_BLOCK_FLAG_DEVELOPER_1;
- TEST_EQ(LoadKernel(&lkp), VBERROR_INVALID_KERNEL_FOUND,
+ TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
"Key block dev flag mismatch");
ResetMocks();
kbh.key_block_flags =
KEY_BLOCK_FLAG_RECOVERY_1 | KEY_BLOCK_FLAG_DEVELOPER_0;
- TEST_EQ(LoadKernel(&lkp), VBERROR_INVALID_KERNEL_FOUND,
+ TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
"Key block rec flag mismatch");
ResetMocks();
lkp.boot_flags |= BOOT_FLAG_RECOVERY;
kbh.key_block_flags =
KEY_BLOCK_FLAG_RECOVERY_1 | KEY_BLOCK_FLAG_DEVELOPER_1;
- TEST_EQ(LoadKernel(&lkp), VBERROR_INVALID_KERNEL_FOUND,
+ TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
"Key block recdev flag mismatch");
ResetMocks();
lkp.boot_flags |= BOOT_FLAG_RECOVERY | BOOT_FLAG_DEVELOPER;
kbh.key_block_flags =
KEY_BLOCK_FLAG_RECOVERY_1 | KEY_BLOCK_FLAG_DEVELOPER_0;
- TEST_EQ(LoadKernel(&lkp), VBERROR_INVALID_KERNEL_FOUND,
+ TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
"Key block rec!dev flag mismatch");
ResetMocks();
kbh.data_key.key_version = 1;
- TEST_EQ(LoadKernel(&lkp), VBERROR_INVALID_KERNEL_FOUND,
+ TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
"Key block kernel key rollback");
ResetMocks();
kbh.data_key.key_version = 0x10000;
- TEST_EQ(LoadKernel(&lkp), VBERROR_INVALID_KERNEL_FOUND,
+ TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
"Key block kernel key version too big");
ResetMocks();
kbh.data_key.key_version = 3;
- TEST_EQ(LoadKernel(&lkp), 0, "Key block version roll forward");
+ TEST_EQ(LoadKernel(&lkp, &cparams), 0, "Key block version roll forward");
TEST_EQ(shared->kernel_version_tpm, 0x30001, " shared version");
ResetMocks();
kbh.data_key.key_version = 3;
mock_parts[1].start = 300;
mock_parts[1].size = 150;
- TEST_EQ(LoadKernel(&lkp), 0, "Two kernels roll forward");
+ TEST_EQ(LoadKernel(&lkp, &cparams), 0, "Two kernels roll forward");
TEST_EQ(mock_part_next, 2, " read both");
TEST_EQ(shared->kernel_version_tpm, 0x30001, " shared version");
ResetMocks();
kbh.data_key.key_version = 1;
lkp.boot_flags |= BOOT_FLAG_DEVELOPER;
- TEST_EQ(LoadKernel(&lkp), 0, "Key version ignored in dev mode");
+ TEST_EQ(LoadKernel(&lkp, &cparams), 0, "Key version ignored in dev mode");
ResetMocks();
kbh.data_key.key_version = 1;
lkp.boot_flags |= BOOT_FLAG_RECOVERY;
- TEST_EQ(LoadKernel(&lkp), 0, "Key version ignored in rec mode");
+ TEST_EQ(LoadKernel(&lkp, &cparams), 0, "Key version ignored in rec mode");
ResetMocks();
mock_data_key = NULL;
- TEST_EQ(LoadKernel(&lkp), VBERROR_INVALID_KERNEL_FOUND, "Bad data key");
+ TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
+ "Bad data key");
ResetMocks();
preamble_verify_fail = 1;
- TEST_EQ(LoadKernel(&lkp), VBERROR_INVALID_KERNEL_FOUND, "Bad preamble");
+ TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
+ "Bad preamble");
ResetMocks();
kph.kernel_version = 0;
- TEST_EQ(LoadKernel(&lkp), VBERROR_INVALID_KERNEL_FOUND,
+ TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
"Kernel version rollback");
ResetMocks();
kph.kernel_version = 0;
lkp.boot_flags |= BOOT_FLAG_DEVELOPER;
- TEST_EQ(LoadKernel(&lkp), 0, "Kernel version ignored in dev mode");
+ TEST_EQ(LoadKernel(&lkp, &cparams), 0, "Kernel version ignored in dev mode");
ResetMocks();
kph.kernel_version = 0;
lkp.boot_flags |= BOOT_FLAG_RECOVERY;
- TEST_EQ(LoadKernel(&lkp), 0, "Kernel version ignored in rec mode");
+ TEST_EQ(LoadKernel(&lkp, &cparams), 0, "Kernel version ignored in rec mode");
ResetMocks();
kph.preamble_size |= 0x07;
- TEST_EQ(LoadKernel(&lkp), VBERROR_INVALID_KERNEL_FOUND,
+ TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
"Kernel body offset");
/* Check getting kernel load address from header */
ResetMocks();
kph.body_load_address = (size_t)kernel_buffer;
lkp.kernel_buffer = NULL;
- TEST_EQ(LoadKernel(&lkp), 0, "Get load address from preamble");
+ TEST_EQ(LoadKernel(&lkp, &cparams), 0, "Get load address from preamble");
TEST_PTR_EQ(lkp.kernel_buffer, kernel_buffer, " address");
/* Size is rounded up to nearest sector */
TEST_EQ(lkp.kernel_buffer_size, 70144, " size");
ResetMocks();
lkp.kernel_buffer_size = 8192;
- TEST_EQ(LoadKernel(&lkp), VBERROR_INVALID_KERNEL_FOUND,
+ TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
"Kernel too big for buffer");
ResetMocks();
mock_parts[0].size = 130;
- TEST_EQ(LoadKernel(&lkp), VBERROR_INVALID_KERNEL_FOUND,
+ TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
"Kernel too big for partition");
ResetMocks();
disk_read_to_fail = 108;
- TEST_EQ(LoadKernel(&lkp), VBERROR_INVALID_KERNEL_FOUND,
+ TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
"Fail reading kernel data");
ResetMocks();
verify_data_fail = 1;
- TEST_EQ(LoadKernel(&lkp), VBERROR_INVALID_KERNEL_FOUND, "Bad data");
+ TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND, "Bad data");
}
int main(void)
diff --git a/tests/vboot_region_tests.c b/tests/vboot_region_tests.c
new file mode 100644
index 00000000..1293136e
--- /dev/null
+++ b/tests/vboot_region_tests.c
@@ -0,0 +1,213 @@
+/* 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.
+ *
+ * Tests for vboot region API
+ */
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "bmpblk_font.h"
+#include "gbb_header.h"
+#include "host_common.h"
+#include "rollback_index.h"
+#include "test_common.h"
+#include "vboot_common.h"
+#include "vboot_nvstorage.h"
+#include "vboot_struct.h"
+
+/* Mock data */
+static VbCommonParams cparams;
+static VbNvContext vnc;
+static VbSelectFirmwareParams fparams;
+VbSelectAndLoadKernelParams kparams;
+static char gbb_data[4096 + sizeof(GoogleBinaryBlockHeader)];
+static uint8_t shared_data[VB_SHARED_DATA_MIN_SIZE];
+static VbSharedDataHeader* shared = (VbSharedDataHeader*)shared_data;
+/* Mock TPM versions */
+static uint32_t mock_tpm_version;
+static uint32_t mock_lf_tpm_version; /* TPM version set by LoadFirmware() */
+static uint32_t mock_seen_region;
+/* Mock return values, so we can simulate errors */
+static VbError_t mock_lf_retval;
+
+#define COMPRESSED_SIZE 200
+#define ORIGINAL_SIZE 400
+
+/* Reset mock data (for use before each test) */
+static void ResetMocks(void) {
+ GoogleBinaryBlockHeader *gbb;
+ BmpBlockHeader *bhdr;
+ ImageInfo *image_info;
+ ScreenLayout *layout;
+ int gbb_used;
+
+ Memset(&vnc, 0, sizeof(vnc));
+ VbNvSetup(&vnc);
+ VbNvTeardown(&vnc); /* So CRC gets generated */
+
+ Memset(&cparams, 0, sizeof(cparams));
+ cparams.shared_data_size = sizeof(shared_data);
+ cparams.shared_data_blob = shared_data;
+
+ Memset(&fparams, 0, sizeof(fparams));
+
+ Memset(gbb_data, 0, sizeof(gbb_data));
+ gbb = (GoogleBinaryBlockHeader *)gbb_data;
+ gbb->major_version = GBB_MAJOR_VER;
+ gbb->minor_version = GBB_MINOR_VER;
+ gbb->flags = 0;
+ gbb_used = sizeof(GoogleBinaryBlockHeader);
+
+ gbb->hwid_offset = gbb_used;
+ strcpy(gbb_data + gbb->hwid_offset, "Test HWID");
+ gbb->hwid_size = strlen(gbb_data + gbb->hwid_offset) + 1;
+ gbb_used = (gbb_used + gbb->hwid_size + 7) & ~7;
+
+ gbb->bmpfv_offset = gbb_used;
+ bhdr = (BmpBlockHeader *)(gbb_data + gbb->bmpfv_offset);
+ gbb->bmpfv_size = sizeof(BmpBlockHeader);
+ gbb_used = (gbb_used + gbb->bmpfv_size + 7) & ~7;
+ memcpy(bhdr->signature, BMPBLOCK_SIGNATURE, BMPBLOCK_SIGNATURE_SIZE);
+ bhdr->major_version = BMPBLOCK_MAJOR_VERSION;
+ bhdr->minor_version = BMPBLOCK_MINOR_VERSION;
+ bhdr->number_of_localizations = 3;
+ bhdr->number_of_screenlayouts = 1;
+
+ layout = (ScreenLayout *)(gbb_data + gbb_used);
+ gbb_used += sizeof(*layout);
+ layout->images[0].x = 1;
+ layout->images[0].image_info_offset = gbb_used - gbb->bmpfv_offset;
+
+ /* First image is uncompressed */
+ image_info = (ImageInfo *)(gbb_data + gbb_used);
+ image_info->format = FORMAT_BMP;
+ image_info->compressed_size = ORIGINAL_SIZE;
+ image_info->original_size = ORIGINAL_SIZE;
+ image_info->compression = COMPRESS_NONE;
+ gbb_used += sizeof(*image_info);
+ strcpy(gbb_data + gbb_used, "original");
+ gbb_used += ORIGINAL_SIZE;
+
+ /* Second image is compressed */
+ layout->images[1].image_info_offset = gbb_used - gbb->bmpfv_offset;
+ layout->images[1].x = 2;
+ image_info = (ImageInfo *)(gbb_data + gbb_used);
+ image_info->format = FORMAT_BMP;
+ image_info->compressed_size = COMPRESSED_SIZE;
+ image_info->original_size = ORIGINAL_SIZE;
+ image_info->compression = COMPRESS_LZMA1;
+ gbb_used += sizeof(*image_info) + COMPRESSED_SIZE;
+
+ Memset(&shared_data, 0, sizeof(shared_data));
+ VbSharedDataInit(shared, sizeof(shared_data));
+ shared->fw_keyblock_flags = 0xABCDE0;
+
+ mock_tpm_version = mock_lf_tpm_version = 0x20004;
+ shared->fw_version_tpm_start = mock_tpm_version;
+ mock_lf_retval = 0;
+ mock_seen_region = 0;
+}
+
+/****************************************************************************/
+/* Mocked verification functions */
+
+uint32_t SetTPMBootModeState(int developer_mode, int recovery_mode,
+ uint64_t fw_keyblock_flags) {
+ return VBERROR_SUCCESS;
+}
+
+VbError_t VbExNvStorageRead(uint8_t* buf) {
+ Memcpy(buf, vnc.raw, sizeof(vnc.raw));
+ return VBERROR_SUCCESS;
+}
+
+VbError_t VbExNvStorageWrite(const uint8_t* buf) {
+ Memcpy(vnc.raw, buf, sizeof(vnc.raw));
+ return VBERROR_SUCCESS;
+}
+
+VbError_t VbExRegionRead(VbCommonParams *cparams,
+ enum vb_firmware_region region, uint32_t offset,
+ uint32_t size, void *buf)
+{
+ if (region != VB_REGION_GBB)
+ return VBERROR_UNSUPPORTED_REGION;
+ mock_seen_region |= 1 << region;
+ if (offset + size > sizeof(gbb_data))
+ return VBERROR_REGION_READ_INVALID;
+ memcpy(buf, gbb_data + offset, size);
+ return VBERROR_SUCCESS;
+}
+
+VbError_t VbExDisplayImage(uint32_t x, uint32_t y,
+ void *buffer, uint32_t buffersize)
+{
+ switch (x) {
+ case 1:
+ TEST_STR_EQ(buffer, "original", " uncompressed image");
+ break;
+ case 2:
+ TEST_STR_EQ(buffer, "decompressed", " compressed image");
+ break;
+ default:
+ TEST_STR_EQ(buffer, "invalid", " correct image");
+ break;
+ }
+ return VBERROR_SUCCESS;
+}
+
+VbError_t VbExDecompress(void *inbuf, uint32_t in_size,
+ uint32_t compression_type,
+ void *outbuf, uint32_t *out_size)
+{
+ *out_size = ORIGINAL_SIZE;
+ strcpy(outbuf, "decompressed");
+ return VBERROR_SUCCESS;
+}
+
+int LoadFirmware(VbCommonParams *cparams, VbSelectFirmwareParams *fparams,
+ VbNvContext *vnc) {
+ shared->fw_version_tpm = mock_lf_tpm_version;
+ TEST_PTR_NEQ(cparams->gbb, NULL, " GBB allocated");
+ return mock_lf_retval;
+}
+
+/****************************************************************************/
+
+static void VbRegionReadTest(void) {
+ /* Should read GBB */
+ ResetMocks();
+ TEST_TRUE(1, "Normal call");
+ TEST_EQ(VbSelectFirmware(&cparams, &fparams), VBERROR_SUCCESS,
+ " Success");
+ TEST_EQ(mock_seen_region, 1 << VB_REGION_GBB, " GBB region");
+ TEST_PTR_EQ(cparams.gbb, NULL, " GBB free");
+
+ ResetMocks();
+ TEST_EQ(VbSelectAndLoadKernel(&cparams, &kparams),
+ VBERROR_NO_DISK_FOUND, "Kernel");
+ TEST_PTR_EQ(cparams.gbb, NULL, " GBB free");
+ TEST_PTR_EQ(cparams.bmp, NULL, " BMP free");
+
+ ResetMocks();
+ shared->flags |= VBSD_BOOT_DEV_SWITCH_ON;
+ TEST_EQ(VbSelectAndLoadKernel(&cparams, &kparams),
+ VBERROR_NO_DISK_FOUND, "Kernel");
+}
+
+int main(int argc, char* argv[]) {
+ int error_code = 0;
+
+ VbRegionReadTest();
+
+ if (vboot_api_stub_check_memory())
+ error_code = 255;
+ if (!gTestSuccess)
+ error_code = 255;
+
+ return error_code;
+}
diff --git a/utility/load_kernel_test.c b/utility/load_kernel_test.c
index 307b8ee2..8e6c5191 100644
--- a/utility/load_kernel_test.c
+++ b/utility/load_kernel_test.c
@@ -27,6 +27,7 @@
/* Global variables for stub functions */
static LoadKernelParams lkp;
+static VbCommonParams cparams;
static VbNvContext vnc;
static FILE *image_file = NULL;
@@ -94,6 +95,7 @@ int main(int argc, char* argv[]) {
Memset(&vnc, 0, sizeof(VbNvContext));
VbNvSetup(&vnc);
lkp.nv_context = &vnc;
+ Memset(&cparams, 0, sizeof(VbCommonParams));
/* Parse options */
opterr = 0;
@@ -157,6 +159,7 @@ int main(int argc, char* argv[]) {
lkp.gbb_size = sizeof(GoogleBinaryBlockHeader) + key_size;
lkp.gbb_data = (void*)malloc(lkp.gbb_size);
gbb = (GoogleBinaryBlockHeader*)lkp.gbb_data;
+ cparams.gbb = gbb;
Memset(gbb, 0, lkp.gbb_size);
Memcpy(gbb->signature, GBB_SIGNATURE, GBB_SIGNATURE_SIZE);
gbb->major_version = GBB_MAJOR_VER;
@@ -214,7 +217,7 @@ int main(int argc, char* argv[]) {
lkp.kernel_buffer_size = KERNEL_BUFFER_SIZE;
/* Call LoadKernel() */
- rv = LoadKernel(&lkp);
+ rv = LoadKernel(&lkp, &cparams);
printf("LoadKernel() returned %d\n", rv);
if (VBERROR_SUCCESS == rv) {