Merge cos-sdk into ToT
Includes changes for the most recent ChromeOS merge.
BUG=b/257271340
TEST=presubmit
RELEASE_NOTE=None
Change-Id: I9910568160c45bbbf5cc1a7267cf74dcba9d8aa3
diff --git a/.gitignore b/.gitignore
index 9edc243..bb49193 100644
--- a/.gitignore
+++ b/.gitignore
@@ -11,3 +11,4 @@
scripts/newbitmaps/strings/localized_text/*/*.png
target
.idea
+*.swp
diff --git a/Android.mk b/Android.mk
index c54a3b7..e0ba6aa 100644
--- a/Android.mk
+++ b/Android.mk
@@ -67,7 +67,6 @@
firmware/stub/vboot_api_stub_sf.c
VBSLK_SRCS += \
- firmware/stub/vboot_api_stub.c \
firmware/stub/vboot_api_stub_disk.c \
firmware/stub/vboot_api_stub_stream.c
@@ -169,4 +168,3 @@
LOCAL_STATIC_LIBRARIES := libvboot_util-host
LOCAL_SHARED_LIBRARIES := libcrypto-host
include $(BUILD_HOST_EXECUTABLE)
-
diff --git a/Makefile b/Makefile
index 4a07128..7731598 100644
--- a/Makefile
+++ b/Makefile
@@ -237,7 +237,7 @@
# Code coverage
ifneq ($(filter-out 0,${COV}),)
- COV_FLAGS = -O0 --coverage -DCOVERAGE
+ COV_FLAGS = -Og --coverage -DCOVERAGE
CFLAGS += ${COV_FLAGS}
LDFLAGS += ${COV_FLAGS}
COV_INFO = ${BUILD}/coverage.info
@@ -275,6 +275,13 @@
LIBZIP_LIBS := $(shell ${PKG_CONFIG} --libs libzip)
endif
+LIBARCHIVE_VERSION := $(shell ${PKG_CONFIG} --modversion libarchive 2>/dev/null)
+HAVE_LIBARCHIVE := $(if ${LIBARCHIVE_VERSION},1)
+ifneq ($(filter-out 0,${HAVE_LIBARCHIVE}),)
+ CFLAGS += -DHAVE_LIBARCHIVE $(shell ${PKG_CONFIG} --cflags libarchive)
+ LIBARCHIVE_LIBS := $(shell ${PKG_CONFIG} --libs libarchive)
+endif
+
HAVE_CROSID := $(shell ${PKG_CONFIG} --exists crosid && echo 1)
ifeq ($(HAVE_CROSID),1)
CFLAGS += -DHAVE_CROSID $(shell ${PKG_CONFIG} --cflags crosid)
@@ -369,6 +376,7 @@
firmware/2lib/2gbb.c \
firmware/2lib/2hmac.c \
firmware/2lib/2kernel.c \
+ firmware/2lib/2load_kernel.c \
firmware/2lib/2misc.c \
firmware/2lib/2nvstorage.c \
firmware/2lib/2packed_key.c \
@@ -388,8 +396,6 @@
firmware/lib/cgptlib/cgptlib_internal.c \
firmware/lib/cgptlib/crc32.c \
firmware/lib/gpt_misc.c \
- firmware/lib/vboot_api_kernel.c \
- firmware/lib/vboot_kernel.c \
firmware/lib20/api_kernel.c \
firmware/lib20/kernel.c
@@ -423,7 +429,6 @@
# TODO: split out other stub funcs too
FWLIB_SRCS += \
firmware/stub/tpm_lite_stub.c \
- firmware/stub/vboot_api_stub.c \
firmware/stub/vboot_api_stub_disk.c \
firmware/stub/vboot_api_stub_stream.c \
firmware/2lib/2stub.c
@@ -439,12 +444,14 @@
ifneq ($(filter-out 0,${USE_FLASHROM}),)
$(info building with libflashrom support)
FLASHROM_LIBS := $(shell ${PKG_CONFIG} --libs flashrom)
-COMMONLIB_SRCS = \
+COMMONLIB_SRCS += \
host/lib/flashrom.c \
- host/lib/flashrom_drv.c \
- host/lib/subprocess.c
+ host/lib/flashrom_drv.c
CFLAGS += -DUSE_FLASHROM
endif
+COMMONLIB_SRCS += \
+ host/lib/subprocess.c \
+ host/lib/cbfstool.c
# Intermediate library for the vboot_reference utilities to link against.
UTILLIB = ${BUILD}/libvboot_util.a
@@ -515,7 +522,6 @@
firmware/lib/cgptlib/crc32.c \
firmware/lib/gpt_misc.c \
firmware/stub/tpm_lite_stub.c \
- firmware/stub/vboot_api_stub.c \
firmware/stub/vboot_api_stub_disk.c \
futility/dump_kernel_config_lib.c \
$(CROSSYSTEM_ARCH_C) \
@@ -675,6 +681,7 @@
FUTIL_SRCS += host/lib/flashrom_drv.c \
futility/flashrom_wp_drv.c \
futility/updater_archive.c \
+ futility/updater_manifest.c \
futility/updater_quirks.c \
futility/updater_utils.c \
futility/updater.c
@@ -693,10 +700,10 @@
# Library of handy test functions.
TESTLIB = ${BUILD}/tests/test.a
-TESTLIB_SRCS += \
- tests/test_common.c \
- tests/timer_utils.c \
- tests/crc32_test.c
+TEST_COMMON_DIR = tests/common
+
+TESTLIB_SRCS += $(wildcard $(TEST_COMMON_DIR)/*.c)
+TESTLIB_SRCS += tests/crc32_test.c
TESTLIB_OBJS = ${TESTLIB_SRCS:%.c=${BUILD}/%.o}
TEST_OBJS += ${TESTLIB_OBJS}
@@ -709,10 +716,6 @@
tests/gpt_misc_tests \
tests/sha_benchmark \
tests/subprocess_tests \
- tests/vboot_api_kernel4_tests \
- tests/vboot_api_kernel_tests \
- tests/vboot_kernel_tests \
- tests/vboot_kernel2_tests \
tests/verify_kernel
ifeq ($(filter-out 0,${MOCK_TPM})$(filter-out 0,${TPM2_MODE}),)
@@ -743,7 +746,10 @@
tests/vb2_host_key_tests \
tests/vb2_host_nvdata_flashrom_tests \
tests/vb2_kernel_tests \
+ tests/vb2_load_kernel_tests \
+ tests/vb2_load_kernel2_tests \
tests/vb2_misc_tests \
+ tests/vb2_misc2_tests \
tests/vb2_nvstorage_tests \
tests/vb2_rsa_utility_tests \
tests/vb2_recovery_reasons_tests \
@@ -1043,7 +1049,8 @@
futil: ${FUTIL_BIN}
# FUTIL_LIBS is shared by FUTIL_BIN and TEST_FUTIL_BINS.
-FUTIL_LIBS = ${CROSID_LIBS} ${CRYPTO_LIBS} ${LIBZIP_LIBS} ${FLASHROM_LIBS}
+FUTIL_LIBS = ${CROSID_LIBS} ${CRYPTO_LIBS} ${LIBZIP_LIBS} ${LIBARCHIVE_LIBS} \
+ ${FLASHROM_LIBS}
${FUTIL_BIN}: LDLIBS += ${FUTIL_LIBS}
${FUTIL_BIN}: ${FUTIL_OBJS} ${UTILLIB} ${FWLIB}
@@ -1279,10 +1286,6 @@
# tlcl_tests only works when MOCK_TPM is disabled
${RUNTEST} ${BUILD_RUN}/tests/tlcl_tests
endif
- ${RUNTEST} ${BUILD_RUN}/tests/vboot_api_kernel4_tests
- ${RUNTEST} ${BUILD_RUN}/tests/vboot_api_kernel_tests
- ${RUNTEST} ${BUILD_RUN}/tests/vboot_kernel_tests
- ${RUNTEST} ${BUILD_RUN}/tests/vboot_kernel2_tests
.PHONY: run2tests
run2tests: install_for_test
@@ -1296,8 +1299,11 @@
${RUNTEST} ${BUILD_RUN}/tests/vb2_firmware_tests
${RUNTEST} ${BUILD_RUN}/tests/vb2_gbb_tests
${RUNTEST} ${BUILD_RUN}/tests/vb2_host_key_tests
+ ${RUNTEST} ${BUILD_RUN}/tests/vb2_load_kernel_tests
+ ${RUNTEST} ${BUILD_RUN}/tests/vb2_load_kernel2_tests
${RUNTEST} ${BUILD_RUN}/tests/vb2_kernel_tests
${RUNTEST} ${BUILD_RUN}/tests/vb2_misc_tests
+ ${RUNTEST} ${BUILD_RUN}/tests/vb2_misc2_tests
${RUNTEST} ${BUILD_RUN}/tests/vb2_nvstorage_tests
${RUNTEST} ${BUILD_RUN}/tests/vb2_rsa_utility_tests
${RUNTEST} ${BUILD_RUN}/tests/vb2_secdata_firmware_tests
@@ -1340,13 +1346,18 @@
${Q}echo -e "\nruntests: \E[32;1mALL TESTS PASSED SUCCESSFULLY!\E[0;m\n"
# Code coverage
+.PHONY: coverage
+ifeq ($(filter-out 0,${COV}),)
+coverage:
+ $(error Build coverage like this: make clean && COV=1 make coverage)
+else
.PHONY: coverage_init
coverage_init: install_for_test
rm -f ${COV_INFO}*
lcov -c -i -d . -b . -o ${COV_INFO}.initial
.PHONY: coverage_html
-coverage_html:
+coverage_html: coverage_init runtests
lcov -c -d . -b . -o ${COV_INFO}.tests
lcov -a ${COV_INFO}.initial -a ${COV_INFO}.tests -o ${COV_INFO}.total
lcov -r ${COV_INFO}.total '/usr/*' -o ${COV_INFO}.local
@@ -1358,11 +1369,6 @@
lcov -e ${COV_INFO}.nostub '${SRCDIR}/firmware/*' \
-o ${COV_INFO}.firmware
-.PHONY: coverage
-ifeq ($(filter-out 0,${COV}),)
-coverage:
- $(error Build coverage like this: make clean && COV=1 make coverage)
-else
coverage: coverage_init runtests coverage_html
endif
diff --git a/OWNERS b/OWNERS
index 21ecb22..b748e0e 100644
--- a/OWNERS
+++ b/OWNERS
@@ -2,4 +2,4 @@
yupingso@chromium.org
twawrzynczak@chromium.org
hungte@chromium.org
-*
+roccochen@chromium.org
diff --git a/cgpt/cgpt_find.c b/cgpt/cgpt_find.c
index 8046aad..f50908f 100644
--- a/cgpt/cgpt_find.c
+++ b/cgpt/cgpt_find.c
@@ -243,8 +243,14 @@
goto cleanup;
}
}
+ // Create a temp dir to work in.
+ if (mkdtemp(temp_dir) == NULL) {
+ perror("Cannot create a temporary directory.\n");
+ goto cleanup;
+ }
if (ReadNorFlash(temp_dir) != 0) {
perror("ReadNorFlash");
+ RemoveDir(temp_dir);
goto cleanup;
}
char nor_file[64];
diff --git a/cgpt/cgpt_nor.c b/cgpt/cgpt_nor.c
index 1530271..e96ee27 100644
--- a/cgpt/cgpt_nor.c
+++ b/cgpt/cgpt_nor.c
@@ -203,20 +203,11 @@
#define FLASHROM_RW_GPT_SEC "RW_GPT_SECONDARY:rw_gpt_2"
#define FLASHROM_RW_GPT "RW_GPT:rw_gpt"
-// Read RW_GPT from NOR flash to "rw_gpt" in a temp dir |temp_dir_template|.
-// |temp_dir_template| is passed to mkdtemp() so it must satisfy all
-// requirements by mkdtemp.
+// Read RW_GPT from NOR flash to "rw_gpt" in a dir.
// TODO(b:184812319): Replace this function with flashrom_read.
-int ReadNorFlash(char *temp_dir_template) {
+int ReadNorFlash(const char *dir) {
int ret = 0;
- // Create a temp dir to work in.
- ret++;
- if (mkdtemp(temp_dir_template) == NULL) {
- Error("Cannot create a temporary directory.\n");
- return ret;
- }
-
// Read RW_GPT section from NOR flash to "rw_gpt".
ret++;
@@ -225,7 +216,7 @@
Error("Cannot get current directory.\n");
return ret;
}
- if (chdir(temp_dir_template) < 0) {
+ if (chdir(dir) < 0) {
Error("Cannot change directory.\n");
goto out_free;
}
@@ -234,7 +225,6 @@
// output.
if (subprocess_run(argv, &subprocess_null, &subprocess_null, NULL) != 0) {
Error("Cannot exec flashrom to read from RW_GPT section.\n");
- RemoveDir(temp_dir_template);
} else {
ret = 0;
}
@@ -248,6 +238,18 @@
return ret;
}
+static int FlashromWriteRegion(const char *region)
+{
+ const char *const argv[] = {FLASHROM_PATH, "-i", region, "-w", "--noverify-all"};
+ // Redirect stdout to /dev/null so that flashrom does not muck up cgpt's
+ // output.
+ if (subprocess_run(argv, &subprocess_null, &subprocess_null, NULL) != 0) {
+ Warning("Cannot write '%s' back with flashrom.\n", region);
+ return 1;
+ }
+ return 0;
+}
+
// Write "rw_gpt" back to NOR flash. We write the file in two parts for safety.
// TODO(b:184812319): Replace this function with flashrom_write.
int WriteNorFlash(const char *dir) {
@@ -270,22 +272,11 @@
Error("Cannot change directory.\n");
goto out_free;
}
- const char *const argv1[] = {FLASHROM_PATH, "-i", FLASHROM_RW_GPT_PRI,
- "-w", "--noverify-all"};
- // Redirect stdout to /dev/null so that flashrom does not muck up cgpt's
- // output.
- if (subprocess_run(argv1, &subprocess_null, &subprocess_null, NULL) != 0) {
- Warning("Cannot write the 1st half of rw_gpt back with flashrom.\n");
+ if (FlashromWriteRegion(FLASHROM_RW_GPT_PRI))
nr_fails++;
- }
- const char *const argv2[] = {FLASHROM_PATH, "-i", FLASHROM_RW_GPT_SEC,
- "-w", "--noverify-all"};
- // Redirect stdout to /dev/null so that flashrom does not muck up cgpt's
- // output.
- if (subprocess_run(argv2, &subprocess_null, &subprocess_null, NULL) != 0) {
- Warning("Cannot write the 2nd half of rw_gpt back with flashrom.\n");
+ if (FlashromWriteRegion(FLASHROM_RW_GPT_SEC))
nr_fails++;
- }
+
if (chdir(cwd) < 0) {
Error("Cannot change directory back to original.\n");
goto out_free;
diff --git a/cgpt/cgpt_nor.h b/cgpt/cgpt_nor.h
index 4746089..93e9dde 100644
--- a/cgpt/cgpt_nor.h
+++ b/cgpt/cgpt_nor.h
@@ -23,10 +23,8 @@
// Exec "rm" to remove |dir|.
int RemoveDir(const char *dir);
-// Read RW_GPT from NOR flash to "rw_gpt" in a temp dir |temp_dir_template|.
-// |temp_dir_template| is passed to mkdtemp() so it must satisfy all
-// requirements by mkdtemp().
-int ReadNorFlash(char *temp_dir_template);
+// Read RW_GPT from NOR flash to "rw_gpt" in dir.
+int ReadNorFlash(const char *dir);
// Write "rw_gpt" back to NOR flash. We write the file in two parts for safety.
int WriteNorFlash(const char *dir);
diff --git a/cgpt/cgpt_wrapper.c b/cgpt/cgpt_wrapper.c
index d26682d..17336c1 100644
--- a/cgpt/cgpt_wrapper.c
+++ b/cgpt/cgpt_wrapper.c
@@ -82,9 +82,13 @@
// Create a temp dir to work in.
ret++;
char temp_dir[] = "/tmp/cgpt_wrapper.XXXXXX";
- if (ReadNorFlash(temp_dir) != 0) {
+ if (mkdtemp(temp_dir_template) == NULL) {
+ Error("Cannot create a temporary directory.\n");
return ret;
}
+ if (ReadNorFlash(temp_dir) != 0) {
+ goto cleanup;
+ }
char rw_gpt_path[PATH_MAX];
if (snprintf(rw_gpt_path, sizeof(rw_gpt_path), "%s/rw_gpt", temp_dir) < 0) {
goto cleanup;
diff --git a/firmware/2lib/2api.c b/firmware/2lib/2api.c
index c041d8a..13b3a69 100644
--- a/firmware/2lib/2api.c
+++ b/firmware/2lib/2api.c
@@ -72,26 +72,21 @@
*/
vb2_check_recovery(ctx);
+ /* Decide the boot mode */
+ vb2_set_boot_mode(ctx);
+
/*
- * Check for possible reasons to ask the firmware to make display
- * available. VB2_CONTEXT_RECOVERY_MODE may have been set above by
- * vb2_check_recovery. VB2_SD_FLAG_DEV_MODE_ENABLED may have been set
- * above by vb2_check_dev_switch. VB2_NV_DIAG_REQUEST may have been
- * set during the last boot in recovery mode.
+ * Initialize display if VB2_NV_DISPLAY_REQUEST is set or in non-normal
+ * boot mode.
*/
- if (!(ctx->flags & VB2_CONTEXT_DISPLAY_INIT) &&
- (vb2_nv_get(ctx, VB2_NV_DISPLAY_REQUEST) ||
- sd->flags & VB2_SD_FLAG_DEV_MODE_ENABLED ||
- ctx->flags & VB2_CONTEXT_RECOVERY_MODE ||
- vb2_nv_get(ctx, VB2_NV_DIAG_REQUEST)))
+ if (vb2_nv_get(ctx, VB2_NV_DISPLAY_REQUEST) ||
+ ctx->boot_mode != VB2_BOOT_MODE_NORMAL)
ctx->flags |= VB2_CONTEXT_DISPLAY_INIT;
+
/* Mark display as available for downstream vboot and vboot callers. */
if (ctx->flags & VB2_CONTEXT_DISPLAY_INIT)
sd->flags |= VB2_SD_FLAG_DISPLAY_AVAILABLE;
- /* Decide the boot mode */
- vb2_set_boot_mode(ctx);
-
/* Return error if recovery is needed */
if (ctx->flags & VB2_CONTEXT_RECOVERY_MODE) {
/* Always clear RAM when entering recovery mode */
@@ -370,3 +365,33 @@
{
return vb2api_check_hash_get_digest(ctx, NULL, 0);
}
+
+union vb2_fw_boot_info vb2api_get_fw_boot_info(struct vb2_context *ctx)
+{
+ union vb2_fw_boot_info info;
+
+ struct vb2_shared_data *sd = vb2_get_sd(ctx);
+
+ info.tries = vb2_nv_get(ctx, VB2_NV_TRY_COUNT);
+ info.slot = sd->fw_slot;
+ info.prev_slot = sd->last_fw_slot;
+ info.prev_result = sd->last_fw_result;
+ info.boot_mode = ctx->boot_mode;
+
+ VB2_DEBUG("boot_mode=`%s`\n", vb2_boot_mode_string(info.boot_mode));
+
+ if (ctx->flags & VB2_CONTEXT_RECOVERY_MODE) {
+ info.recovery_reason = sd->recovery_reason;
+ info.recovery_subcode = vb2_nv_get(ctx, VB2_NV_RECOVERY_SUBCODE);
+ VB2_DEBUG("recovery_reason: %#x / %#x\n",
+ info.recovery_reason, info.recovery_subcode);
+ }
+
+ VB2_DEBUG("fw_tried=`%s` fw_try_count=%d "
+ "fw_prev_tried=`%s` fw_prev_result=`%s`.\n",
+ vb2_slot_string(info.slot), info.tries,
+ vb2_slot_string(info.prev_slot),
+ vb2_result_string(info.prev_result));
+
+ return info;
+}
diff --git a/firmware/2lib/2auxfw_sync.c b/firmware/2lib/2auxfw_sync.c
index eaea1d4..76ad722 100644
--- a/firmware/2lib/2auxfw_sync.c
+++ b/firmware/2lib/2auxfw_sync.c
@@ -48,12 +48,14 @@
return vb2ex_auxfw_check(severity);
}
+test_mockable
vb2_error_t vb2api_auxfw_sync(struct vb2_context *ctx)
{
enum vb2_auxfw_update_severity fw_update = VB2_AUXFW_NO_UPDATE;
/* Check for update severity */
- VB2_TRY(auxfw_sync_check_update(ctx, &fw_update));
+ VB2_TRY(auxfw_sync_check_update(ctx, &fw_update), ctx,
+ VB2_RECOVERY_AUXFW_UPDATE);
if (fw_update > VB2_AUXFW_NO_UPDATE) {
VB2_DEBUG("Updating auxfw\n");
diff --git a/firmware/2lib/2ec_sync.c b/firmware/2lib/2ec_sync.c
index e75313b..b1bc7eb 100644
--- a/firmware/2lib/2ec_sync.c
+++ b/firmware/2lib/2ec_sync.c
@@ -338,6 +338,7 @@
return sync_ec(ctx);
}
+test_mockable
vb2_error_t vb2api_ec_sync(struct vb2_context *ctx)
{
struct vb2_shared_data *sd = vb2_get_sd(ctx);
diff --git a/firmware/2lib/2kernel.c b/firmware/2lib/2kernel.c
index 5b18cad..ff89e14 100644
--- a/firmware/2lib/2kernel.c
+++ b/firmware/2lib/2kernel.c
@@ -5,94 +5,12 @@
* Kernel selection, loading, verification, and booting.
*/
+#include "2api.h"
#include "2common.h"
-#include "2kernel.h"
#include "2misc.h"
#include "2nvstorage.h"
#include "2rsa.h"
#include "2secdata.h"
-#include "vboot_api.h"
-
-/**
- * Reset any NVRAM requests.
- *
- * @param ctx Vboot context
- * @return 1 if a reboot is required, 0 otherwise.
- */
-static int vb2_reset_nv_requests(struct vb2_context *ctx)
-{
- int need_reboot = 0;
-
- if (vb2_nv_get(ctx, VB2_NV_DISPLAY_REQUEST)) {
- VB2_DEBUG("Unset display request (undo display init)\n");
- vb2_nv_set(ctx, VB2_NV_DISPLAY_REQUEST, 0);
- need_reboot = 1;
- }
-
- if (vb2_nv_get(ctx, VB2_NV_DIAG_REQUEST)) {
- VB2_DEBUG("Unset diagnostic request (undo display init)\n");
- vb2_nv_set(ctx, VB2_NV_DIAG_REQUEST, 0);
- need_reboot = 1;
- }
-
- return need_reboot;
-}
-
-vb2_error_t vb2_normal_boot(struct vb2_context *ctx)
-{
- struct vb2_shared_data *sd = vb2_get_sd(ctx);
- uint32_t max_rollforward = vb2_nv_get(ctx,
- VB2_NV_KERNEL_MAX_ROLLFORWARD);
-
- /* Boot from fixed disk only */
- VB2_DEBUG("Entering\n");
-
- if (vb2_reset_nv_requests(ctx)) {
- VB2_DEBUG("Normal mode: reboot to reset NVRAM requests\n");
- return VB2_REQUEST_REBOOT;
- }
-
- vb2_error_t rv = VbTryLoadKernel(ctx, VB_DISK_FLAG_FIXED);
-
- VB2_DEBUG("Checking if TPM kernel version needs advancing\n");
-
- /*
- * Special case for when we're trying a slot with new firmware.
- * Firmware updates also usually change the kernel key, which means
- * that the new firmware can only boot a new kernel, and the old
- * firmware in the previous slot can only boot the previous kernel.
- *
- * Don't roll-forward the kernel version, because we don't yet know if
- * the new kernel will successfully boot.
- */
- if (vb2_nv_get(ctx, VB2_NV_FW_RESULT) == VB2_FW_RESULT_TRYING) {
- VB2_DEBUG("Trying new FW; skip kernel version roll-forward.\n");
- return rv;
- }
-
- /*
- * Limit kernel version rollforward if needed. Can't limit kernel
- * version to less than the version currently in the TPM. That is,
- * we're limiting rollforward, not allowing rollback.
- */
- if (max_rollforward < sd->kernel_version_secdata)
- max_rollforward = sd->kernel_version_secdata;
-
- if (sd->kernel_version > max_rollforward) {
- VB2_DEBUG("Limiting TPM kernel version roll-forward "
- "to %#x < %#x\n",
- max_rollforward, sd->kernel_version);
-
- sd->kernel_version = max_rollforward;
- }
-
- if (sd->kernel_version > sd->kernel_version_secdata) {
- vb2_secdata_kernel_set(ctx, VB2_SECDATA_KERNEL_VERSIONS,
- sd->kernel_version);
- }
-
- return rv;
-}
int vb2api_is_developer_signed(struct vb2_context *ctx)
{
@@ -197,3 +115,165 @@
return VB2_SUCCESS;
}
+
+static vb2_error_t handle_battery_cutoff(struct vb2_context *ctx)
+{
+ /*
+ * Check if we need to cut-off battery. This should be done after EC
+ * FW and auxfw are updated, and before the kernel is started. This
+ * is to make sure all firmware is up-to-date before shipping (which
+ * is the typical use-case for cutoff).
+ */
+ if (vb2_nv_get(ctx, VB2_NV_BATTERY_CUTOFF_REQUEST)) {
+ VB2_DEBUG("Request to cut-off battery\n");
+ vb2_nv_set(ctx, VB2_NV_BATTERY_CUTOFF_REQUEST, 0);
+
+ /* May lose power immediately, so commit our update now. */
+ VB2_TRY(vb2ex_commit_data(ctx));
+
+ vb2ex_ec_battery_cutoff();
+ return VB2_REQUEST_SHUTDOWN;
+ }
+
+ return VB2_SUCCESS;
+}
+
+vb2_error_t vb2api_kernel_phase2(struct vb2_context *ctx)
+{
+ struct vb2_shared_data *sd = vb2_get_sd(ctx);
+ vb2_gbb_flags_t gbb_flags = vb2api_gbb_get_flags(ctx);
+
+ VB2_DEBUG("GBB flags are %#x\n", gbb_flags);
+
+ /*
+ * Do EC and auxfw software sync unless we're in recovery mode. This
+ * has UI but it's just a single non-interactive WAIT screen.
+ */
+ if (!(ctx->flags & VB2_CONTEXT_RECOVERY_MODE)) {
+ VB2_TRY(vb2api_ec_sync(ctx));
+ VB2_TRY(vb2api_auxfw_sync(ctx));
+ VB2_TRY(handle_battery_cutoff(ctx));
+ }
+
+ /*
+ * If in the broken screen, save the recovery reason as subcode.
+ * Otherwise, clear any leftover recovery requests or subcodes.
+ */
+ vb2_clear_recovery(ctx);
+
+ /*
+ * Clear the diagnostic request flag and commit nvdata to prevent
+ * booting back into diagnostic mode when a forced system reset occurs.
+ */
+ if (vb2_nv_get(ctx, VB2_NV_DIAG_REQUEST)) {
+ vb2_nv_set(ctx, VB2_NV_DIAG_REQUEST, 0);
+ /*
+ * According to current FAFT design (firmware_MiniDiag), we
+ * need an AP reset after MiniDiag test items to preserve the
+ * CBMEM console logs. So we need to commit nvdata immediately
+ * to prevent booting back to VB2_BOOT_MODE_DIAGNOSTICS.
+ */
+ vb2ex_commit_data(ctx);
+ }
+
+ /* Select boot path */
+ switch (ctx->boot_mode) {
+ case VB2_BOOT_MODE_MANUAL_RECOVERY:
+ case VB2_BOOT_MODE_BROKEN_SCREEN:
+ /* If we're in recovery mode just to do memory retraining, all
+ we need to do is reboot. */
+ if (sd->recovery_reason == VB2_RECOVERY_TRAIN_AND_REBOOT) {
+ VB2_DEBUG("Reboot after retraining in recovery\n");
+ return VB2_REQUEST_REBOOT;
+ }
+
+ /*
+ * Need to commit nvdata changes immediately, since we will be
+ * entering either manual recovery UI or BROKEN screen shortly.
+ */
+ vb2ex_commit_data(ctx);
+ break;
+ case VB2_BOOT_MODE_DIAGNOSTICS:
+ case VB2_BOOT_MODE_DEVELOPER:
+ break;
+ case VB2_BOOT_MODE_NORMAL:
+ if (vb2_nv_get(ctx, VB2_NV_DISPLAY_REQUEST)) {
+ vb2_nv_set(ctx, VB2_NV_DISPLAY_REQUEST, 0);
+ VB2_DEBUG("Normal mode: "
+ "reboot to unset display request\n");
+ return VB2_REQUEST_REBOOT;
+ }
+ break;
+ default:
+ return VB2_ERROR_ESCAPE_NO_BOOT;
+ }
+
+ return VB2_SUCCESS;
+}
+
+static void update_kernel_version(struct vb2_context *ctx)
+{
+ struct vb2_shared_data *sd = vb2_get_sd(ctx);
+ uint32_t max_rollforward =
+ vb2_nv_get(ctx, VB2_NV_KERNEL_MAX_ROLLFORWARD);
+
+ VB2_DEBUG("Checking if TPM kernel version needs advancing\n");
+
+ /*
+ * Special case for when we're trying a slot with new firmware.
+ * Firmware updates also usually change the kernel key, which means
+ * that the new firmware can only boot a new kernel, and the old
+ * firmware in the previous slot can only boot the previous kernel.
+ *
+ * Don't roll-forward the kernel version, because we don't yet know if
+ * the new kernel will successfully boot.
+ */
+ if (vb2_nv_get(ctx, VB2_NV_FW_RESULT) == VB2_FW_RESULT_TRYING) {
+ VB2_DEBUG("Trying new FW; "
+ "skip kernel version roll-forward.\n");
+ return;
+ }
+
+ /*
+ * Limit kernel version rollforward if needed. Can't limit kernel
+ * version to less than the version currently in the TPM. That is,
+ * we're limiting rollforward, not allowing rollback.
+ */
+ if (max_rollforward < sd->kernel_version_secdata)
+ max_rollforward = sd->kernel_version_secdata;
+
+ if (sd->kernel_version > max_rollforward) {
+ VB2_DEBUG("Limiting TPM kernel version roll-forward "
+ "to %#x < %#x\n",
+ max_rollforward, sd->kernel_version);
+
+ sd->kernel_version = max_rollforward;
+ }
+
+ if (sd->kernel_version > sd->kernel_version_secdata) {
+ vb2_secdata_kernel_set(ctx, VB2_SECDATA_KERNEL_VERSIONS,
+ sd->kernel_version);
+ }
+}
+
+vb2_error_t vb2api_kernel_finalize(struct vb2_context *ctx)
+{
+ vb2_gbb_flags_t gbb_flags = vb2api_gbb_get_flags(ctx);
+
+ /*
+ * Disallow booting to kernel when NO_BOOT flag is set, except when
+ * GBB flag disables software sync.
+ */
+ if (!(gbb_flags & VB2_GBB_FLAG_DISABLE_EC_SOFTWARE_SYNC)
+ && (ctx->flags & VB2_CONTEXT_EC_SYNC_SUPPORTED)
+ && (ctx->flags & VB2_CONTEXT_NO_BOOT)) {
+ VB2_DEBUG("Blocking escape from NO_BOOT mode.\n");
+ vb2api_fail(ctx, VB2_RECOVERY_ESCAPE_NO_BOOT, 0);
+ return VB2_ERROR_ESCAPE_NO_BOOT;
+ }
+
+ if (ctx->boot_mode == VB2_BOOT_MODE_NORMAL)
+ update_kernel_version(ctx);
+
+ return VB2_SUCCESS;
+}
diff --git a/firmware/lib/vboot_kernel.c b/firmware/2lib/2load_kernel.c
similarity index 95%
rename from firmware/lib/vboot_kernel.c
rename to firmware/2lib/2load_kernel.c
index 1edf4a5..65e4053 100644
--- a/firmware/lib/vboot_kernel.c
+++ b/firmware/2lib/2load_kernel.c
@@ -16,7 +16,6 @@
#include "cgptlib.h"
#include "cgptlib_internal.h"
#include "gpt_misc.h"
-#include "load_kernel_fw.h"
#include "vboot_api.h"
enum vb2_load_partition_flags {
@@ -348,7 +347,7 @@
* @return VB2_SUCCESS, or non-zero error code.
*/
static vb2_error_t vb2_load_partition(
- struct vb2_context *ctx, VbSelectAndLoadKernelParams *params,
+ struct vb2_context *ctx, struct vb2_kernel_params *params,
VbExStream_t stream, uint32_t lpflags)
{
uint32_t read_ms = 0, start_ts;
@@ -462,8 +461,8 @@
}
static vb2_error_t try_minios_kernel(struct vb2_context *ctx,
- VbSelectAndLoadKernelParams *params,
- VbDiskInfo *disk_info,
+ struct vb2_kernel_params *params,
+ struct vb2_disk_info *disk_info,
uint64_t sector) {
VbExStream_t stream;
uint64_t sectors_left = disk_info->lba_count - sector;
@@ -471,7 +470,7 @@
vb2_error_t rv = VB2_ERROR_LK_NO_KERNEL_FOUND;
/* Re-open stream at correct offset to pass to vb2_load_partition. */
- if (VbExStreamOpen(params->disk_handle, sector, sectors_left,
+ if (VbExStreamOpen(disk_info->handle, sector, sectors_left,
&stream)) {
VB2_DEBUG("Unable to open disk handle.\n");
return rv;
@@ -488,8 +487,8 @@
}
static vb2_error_t try_minios_sectors(struct vb2_context *ctx,
- VbSelectAndLoadKernelParams *params,
- VbDiskInfo *disk_info,
+ struct vb2_kernel_params *params,
+ struct vb2_disk_info *disk_info,
uint64_t start, uint64_t count)
{
const uint32_t buf_size = count * disk_info->bytes_per_lba;
@@ -504,7 +503,7 @@
return rv;
}
- if (VbExStreamOpen(params->disk_handle, start, count, &stream)) {
+ if (VbExStreamOpen(disk_info->handle, start, count, &stream)) {
VB2_DEBUG("Unable to open disk handle.\n");
free(buf);
return rv;
@@ -534,8 +533,8 @@
}
static vb2_error_t try_minios_sector_region(struct vb2_context *ctx,
- VbSelectAndLoadKernelParams *params,
- VbDiskInfo *disk_info,
+ struct vb2_kernel_params *params,
+ struct vb2_disk_info *disk_info,
int end_region)
{
const uint64_t disk_count_half = (disk_info->lba_count + 1) / 2;
@@ -577,14 +576,15 @@
* the start and end of disks are considered, and the kernel must start exactly
* at the first byte of the sector.
*/
-vb2_error_t LoadMiniOsKernel(struct vb2_context *ctx,
- VbSelectAndLoadKernelParams *params,
- VbDiskInfo *disk_info, uint32_t minios_flags)
+vb2_error_t vb2api_load_minios_kernel(struct vb2_context *ctx,
+ struct vb2_kernel_params *params,
+ struct vb2_disk_info *disk_info,
+ uint32_t minios_flags)
{
vb2_error_t rv;
int end_region_first = vb2_nv_get(ctx, VB2_NV_MINIOS_PRIORITY);
- if (minios_flags & VB_MINIOS_FLAG_NON_ACTIVE)
+ if (minios_flags & VB2_MINIOS_FLAG_NON_ACTIVE)
rv = VB2_ERROR_UNKNOWN; /* Ignore active partition */
else
rv = try_minios_sector_region(ctx, params, disk_info,
@@ -593,19 +593,16 @@
if (rv)
rv = try_minios_sector_region(ctx, params, disk_info,
!end_region_first);
- if (rv)
- return rv;
- rv = vb2ex_tpm_set_mode(VB2_TPM_MODE_DISABLED);
- if (rv)
- VB2_DEBUG("Failed to disable TPM\n");
+ if (rv == VB2_SUCCESS)
+ params->disk_handle = disk_info->handle;
return rv;
}
-vb2_error_t LoadKernel(struct vb2_context *ctx,
- VbSelectAndLoadKernelParams *params,
- VbDiskInfo *disk_info)
+vb2_error_t vb2api_load_kernel(struct vb2_context *ctx,
+ struct vb2_kernel_params *params,
+ struct vb2_disk_info *disk_info)
{
struct vb2_shared_data *sd = vb2_get_sd(ctx);
int found_partitions = 0;
@@ -621,7 +618,7 @@
gpt.streaming_drive_sectors = disk_info->streaming_lba_count
?: disk_info->lba_count;
gpt.gpt_drive_sectors = disk_info->lba_count;
- gpt.flags = disk_info->flags & VB_DISK_FLAG_EXTERNAL_GPT
+ gpt.flags = disk_info->flags & VB2_DISK_FLAG_EXTERNAL_GPT
? GPT_FLAG_EXTERNAL : 0;
if (AllocAndReadGptData(disk_info->handle, &gpt)) {
VB2_DEBUG("Unable to read GPT data\n");
@@ -754,6 +751,7 @@
/* Success! */
rv = VB2_SUCCESS;
+ params->disk_handle = disk_info->handle;
} else if (found_partitions > 0) {
rv = VB2_ERROR_LK_INVALID_KERNEL_FOUND;
} else {
diff --git a/firmware/2lib/2misc.c b/firmware/2lib/2misc.c
index 6e92690..5735127 100644
--- a/firmware/2lib/2misc.c
+++ b/firmware/2lib/2misc.c
@@ -520,6 +520,7 @@
VB2_SECDATA_KERNEL_FLAG_PHONE_RECOVERY_UI_DISABLED);
}
+test_mockable
int vb2api_diagnostic_ui_enabled(struct vb2_context *ctx)
{
return !(vb2_secdata_kernel_get(ctx, VB2_SECDATA_KERNEL_FLAGS) &
diff --git a/firmware/2lib/2recovery_reasons.c b/firmware/2lib/2recovery_reasons.c
index 8c43dce..73fd812 100644
--- a/firmware/2lib/2recovery_reasons.c
+++ b/firmware/2lib/2recovery_reasons.c
@@ -113,7 +113,7 @@
/* 0x46 */ case VB2_RECOVERY_RW_SHARED_DATA:
return "Shared data error in rewritable firmware";
/* 0x47 */ case VB2_RECOVERY_DEPRECATED_RW_TEST_LK:
- return "Test error from LoadKernel()";
+ return "Test error from vb2api_load_kernel()";
/* 0x48 */ case VB2_RECOVERY_DEPRECATED_RW_NO_DISK:
return "No bootable storage device in system";
/* 0x49 */ case VB2_RECOVERY_TPM_E_FAIL:
diff --git a/firmware/2lib/2rsa.c b/firmware/2lib/2rsa.c
index dcd8bad..eb07b04 100644
--- a/firmware/2lib/2rsa.c
+++ b/firmware/2lib/2rsa.c
@@ -14,7 +14,6 @@
#include "2rsa_private.h"
#include "2sha.h"
#include "2sysincludes.h"
-#include "vboot_test.h"
/**
* a[] -= mod
diff --git a/firmware/2lib/2secdata_kernel.c b/firmware/2lib/2secdata_kernel.c
index 0d4208f..754552c 100644
--- a/firmware/2lib/2secdata_kernel.c
+++ b/firmware/2lib/2secdata_kernel.c
@@ -11,7 +11,6 @@
#include "2secdata.h"
#include "2secdata_struct.h"
#include "2sysincludes.h"
-#include "vboot_test.h"
#define MAJOR_VER(x) (((x) & 0xf0) >> 4)
#define MINOR_VER(x) ((x) & 0x0f)
@@ -181,6 +180,7 @@
return VB2_SUCCESS;
}
+test_mockable
uint32_t vb2_secdata_kernel_get(struct vb2_context *ctx,
enum vb2_secdata_kernel_param param)
{
@@ -213,6 +213,7 @@
return 0;
}
+test_mockable
void vb2_secdata_kernel_set(struct vb2_context *ctx,
enum vb2_secdata_kernel_param param,
uint32_t value)
@@ -273,6 +274,7 @@
VB2_REC_OR_DIE(ctx, "%s\n", msg);
}
+test_mockable
const uint8_t *vb2_secdata_kernel_get_ec_hash(struct vb2_context *ctx)
{
struct vb2_shared_data *sd = vb2_get_sd(ctx);
diff --git a/firmware/2lib/2stub.c b/firmware/2lib/2stub.c
index da754ad..51d2eb2 100644
--- a/firmware/2lib/2stub.c
+++ b/firmware/2lib/2stub.c
@@ -38,11 +38,12 @@
}
__attribute__((weak))
-uint32_t vb2ex_mtime(void)
+vb2_error_t vb2ex_commit_data(struct vb2_context *ctx)
{
- struct timeval tv;
- gettimeofday(&tv, NULL);
- return tv.tv_sec * VB2_MSEC_PER_SEC + tv.tv_usec / VB2_USEC_PER_MSEC;
+ ctx->flags &= ~VB2_CONTEXT_SECDATA_FIRMWARE_CHANGED;
+ ctx->flags &= ~VB2_CONTEXT_SECDATA_KERNEL_CHANGED;
+ ctx->flags &= ~VB2_CONTEXT_NVDATA_CHANGED;
+ return VB2_SUCCESS;
}
__attribute__((weak))
@@ -159,105 +160,17 @@
}
/*****************************************************************************/
-/* UI-related stubs */
+/* Timer-related stubs */
__attribute__((weak))
-const char *vb2ex_get_debug_info(struct vb2_context *ctx)
+uint32_t vb2ex_mtime(void)
{
- return NULL;
-}
-
-__attribute__((weak))
-const char *vb2ex_get_firmware_log(int reset)
-{
- return NULL;
-}
-
-__attribute__((weak))
-vb2_error_t vb2ex_diag_get_storage_health(const char **out)
-{
- *out = "mock";
- return VB2_SUCCESS;
-}
-
-__attribute__((weak))
-vb2_error_t vb2ex_diag_get_storage_test_log(const char **out)
-{
- *out = "mock";
- return VB2_SUCCESS;
-}
-
-__attribute__((weak))
-vb2_error_t vb2ex_diag_memory_quick_test(int reset, const char **out)
-{
- *out = "mock";
- return VB2_SUCCESS;
-}
-
-__attribute__((weak))
-vb2_error_t vb2ex_diag_memory_full_test(int reset, const char **out)
-{
- *out = "mock";
- return VB2_SUCCESS;
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ return tv.tv_sec * VB2_MSEC_PER_SEC + tv.tv_usec / VB2_USEC_PER_MSEC;
}
__attribute__((weak))
void vb2ex_msleep(uint32_t msec)
{
}
-
-__attribute__((weak))
-void vb2ex_beep(uint32_t msec, uint32_t frequency)
-{
-}
-
-__attribute__((weak))
-uint32_t vb2ex_get_locale_count(void)
-{
- return 0;
-}
-
-__attribute__((weak))
-uint32_t vb2ex_get_altfw_count(void)
-{
- return 0;
-}
-
-__attribute__((weak))
-int vb2ex_physical_presence_pressed(void)
-{
- return 0;
-}
-
-__attribute__((weak))
-vb2_error_t vb2ex_commit_data(struct vb2_context *ctx)
-{
- ctx->flags &= ~VB2_CONTEXT_SECDATA_FIRMWARE_CHANGED;
- ctx->flags &= ~VB2_CONTEXT_SECDATA_KERNEL_CHANGED;
- ctx->flags &= ~VB2_CONTEXT_NVDATA_CHANGED;
- return VB2_SUCCESS;
-}
-
-__attribute__((weak))
-vb2_error_t vb2ex_broken_screen_ui(struct vb2_context *ctx)
-{
- return VB2_SUCCESS;
-}
-
-__attribute__((weak))
-vb2_error_t vb2ex_manual_recovery_ui(struct vb2_context *ctx)
-{
- return VB2_SUCCESS;
-}
-
-__attribute__((weak))
-vb2_error_t vb2ex_developer_ui(struct vb2_context *ctx)
-{
- return VB2_SUCCESS;
-}
-
-__attribute__((weak))
-vb2_error_t vb2ex_diagnostic_ui(struct vb2_context *ctx)
-{
- return VB2_SUCCESS;
-}
diff --git a/firmware/2lib/include/2api.h b/firmware/2lib/include/2api.h
index 1430111..79283c2 100644
--- a/firmware/2lib/include/2api.h
+++ b/firmware/2lib/include/2api.h
@@ -24,6 +24,7 @@
#include "2fw_hash_tags.h"
#include "2gbb_flags.h"
#include "2id.h"
+#include "2info.h"
#include "2recovery_reasons.h"
#include "2return_codes.h"
#include "2rsa.h"
@@ -165,14 +166,14 @@
/*
* System supports EC software sync. Caller may set this flag at any
- * time before calling VbSelectAndLoadKernel().
+ * time before calling vb2api_kernel_phase2().
*/
VB2_CONTEXT_EC_SYNC_SUPPORTED = (1 << 15),
/*
* EC software sync is slow to update; warning screen should be
* displayed. Caller may set this flag at any time before calling
- * VbSelectAndLoadKernel(). Deprecated as part of chromium:1038259.
+ * vb2api_kernel_phase2(). Deprecated as part of chromium:1038259.
*/
VB2_CONTEXT_DEPRECATED_EC_SYNC_SLOW = (1 << 16),
@@ -257,58 +258,12 @@
* nvdata, FWMP or GBB flags.
*/
VB2_CONTEXT_DEV_BOOT_ALTFW_ALLOWED = (1 << 27),
-};
-
-/* Boot mode decided in vb2api_fw_phase1.
- *
- * Boot mode is a constant set by verified boot and may be read (but should not
- * be set or cleared) by the caller.
- * The boot modes are mutually exclusive. If a boot fulfill more than one
- * constraints of the listing boot modes, it will be set to the most important
- * one. The priority is the same as the listing order.
- */
-enum vb2_boot_mode {
- /* Undefined, The boot mode is not set. */
- VB2_BOOT_MODE_UNDEFINED = 0,
/*
- * Manual recovery boot, regardless of dev mode state.
- *
- * VB2_CONTEXT_RECOVERY_MODE is set and the recovery is physically
- * requested (a.k.a. Manual recovery). All other recovery requests
- * including manual recovery requested by a (compromised) host will end
- * up with a broken screen.
+ * If this is set after kernel verification, caller should disable the
+ * TPM before jumping to kernel.
*/
- VB2_BOOT_MODE_MANUAL_RECOVERY = 1,
-
- /*
- * Broken screen.
- *
- * If a recovery boot is not a manual recovery (a.k.a. not requested
- * physically), the recovery is not allowed and will end up with
- * broken screen.
- */
- VB2_BOOT_MODE_BROKEN_SCREEN = 2,
-
- /*
- * Diagnostic boot.
- *
- * If diagnostic boot is enabled (a.k.a. vb2api_diagnostic_ui_enabled)
- * and the nvdata contains VB2_NV_DIAG_REQUEST from previous boot, it
- * will boot to diagnostic mode.
- */
- VB2_BOOT_MODE_DIAGNOSTICS = 3,
-
- /*
- * Developer boot: self-signed kernel okay.
- *
- * The developer mode switch is set (a.k.a. VB2_CONTEXT_DEVELOPER_MODE)
- * and we are in the developer boot mode.
- */
- VB2_BOOT_MODE_DEVELOPER = 4,
-
- /* Normal boot: kernel must be verified. */
- VB2_BOOT_MODE_NORMAL = 5,
+ VB2_CONTEXT_DISABLE_TPM = (1 << 28),
};
/* Helper for aligning fields in vb2_context. */
@@ -391,10 +346,10 @@
*/
/*
- * Mutually exclusive boot mode.
+ * Mutually exclusive boot mode (from enum vb2_boot_mode).
* This constant is initialized after calling vb2api_fw_phase1().
*/
- const enum vb2_boot_mode boot_mode;
+ const uint8_t boot_mode;
};
/* Resource index for vb2ex_read_resource() */
@@ -506,7 +461,8 @@
* use to verify kernel data - the recovery key from the GBB, or the
* kernel subkey from the firmware verification stage.
*
- * Kernel phase 2 is finding loading, and verifying the kernel partition.
+ * Call vb2api_kernel_phase2(). Do EC and auxfw software sync, clear
+ * recovery and commit nvdata if needed.
*
* Find a boot device (you're on your own here).
*
@@ -812,6 +768,142 @@
vb2_error_t vb2api_kernel_phase1(struct vb2_context *ctx);
/**
+ * Do kernel verification.
+ *
+ * Must be called after vb2api_kernel_phase1.
+ *
+ * @param ctx Vboot context
+ * @return VB2_SUCCESS, or error code on error.
+ */
+vb2_error_t vb2api_kernel_phase2(struct vb2_context *ctx);
+
+/**
+ * Finalize for kernel verification stage.
+ *
+ * Handle NO_BOOT flag. Also, check and roll forward kernel version.
+ *
+ * @param ctx Vboot context
+ * @return VB2_SUCCESS, or error code on error.
+ */
+vb2_error_t vb2api_kernel_finalize(struct vb2_context *ctx);
+
+struct vb2_kernel_params {
+ /* Inputs to vb2api_load_kernel(). */
+ /* Destination buffer for kernel (normally at 0x100000 on x86). */
+ void *kernel_buffer;
+ /* Size of kernel buffer in bytes. */
+ uint32_t kernel_buffer_size;
+
+ /*
+ * Outputs from vb2api_load_kernel(); valid only if it returns success.
+ */
+ /* Handle of disk containing loaded kernel. */
+ vb2ex_disk_handle_t disk_handle;
+ /* Partition number on disk to boot (1...M). */
+ uint32_t partition_number;
+ /* Address of bootloader image in RAM. */
+ uint64_t bootloader_address;
+ /* Size of bootloader image in bytes. */
+ uint32_t bootloader_size;
+ /* UniquePartitionGuid for boot partition. */
+ uint8_t partition_guid[16];
+ /* Flags set by signer. */
+ uint32_t flags;
+};
+
+/*****************************************************************************/
+/* Disk access */
+
+/* Flags for vb2_disk_info */
+
+/*
+ * Disk selection in the lower 16 bits (where the disk lives), and disk
+ * attributes in the higher 16 bits (extra information about the disk
+ * needed to access it correctly).
+ */
+#define VB2_DISK_FLAG_SELECT_MASK 0xffff
+#define VB2_DISK_FLAG_ATTRIBUTE_MASK (0xffff << 16)
+
+/*
+ * Disks are used in two ways:
+ * - As a random-access device to read and write the GPT
+ * - As a streaming device to read the kernel
+ * These are implemented differently on raw NAND vs eMMC/SATA/USB
+ * - On eMMC/SATA/USB, both of these refer to the same underlying
+ * storage, so they have the same size and LBA size. In this case,
+ * the GPT should not point to the same address as itself.
+ * - On raw NAND, the GPT is held on a portion of the SPI flash.
+ * Random access GPT operations refer to the SPI and streaming
+ * operations refer to NAND. The GPT may therefore point into
+ * the same offsets as itself.
+ * These types are distinguished by the following flag and vb2_disk_info
+ * has separate fields to describe the random-access ("GPT") and
+ * streaming aspects of the disk. If a disk is random-access (i.e.
+ * not raw NAND) then these fields are equal.
+ */
+#define VB2_DISK_FLAG_EXTERNAL_GPT (1 << 16)
+
+/* Information on a single disk. */
+struct vb2_disk_info {
+ /* Disk handle. */
+ vb2ex_disk_handle_t handle;
+ /* Size of a random-access LBA sector in bytes. */
+ uint64_t bytes_per_lba;
+ /* Number of random-access LBA sectors on the device.
+ * If streaming_lba_count is 0, this stands in for the size of the
+ * randomly accessed portion as well as the streaming portion.
+ * Otherwise, this is only the randomly-accessed portion. */
+ uint64_t lba_count;
+ /* Number of streaming sectors on the device. */
+ uint64_t streaming_lba_count;
+ /* Flags (see VB2_DISK_FLAG_* constants). */
+ uint32_t flags;
+ /*
+ * Optional name string, for use in debugging. May be empty or null if
+ * not available.
+ */
+ const char *name;
+};
+
+/**
+ * Attempt to load kernel from the specified device. On success, the output
+ * fields of params will be filled. The caller should set the input fields of
+ * params.
+ *
+ *
+ * @param ctx Vboot context
+ * @param params Params specific to loading the kernel
+ * @param disk_info Disk from which to read kernel
+ *
+ * @return VB2_SUCCESS, or non-zero error code.
+ */
+vb2_error_t vb2api_load_kernel(struct vb2_context *ctx,
+ struct vb2_kernel_params *params,
+ struct vb2_disk_info *disk_info);
+
+/* miniOS flags */
+
+/* Boot from non-active miniOS partition only. */
+#define VB2_MINIOS_FLAG_NON_ACTIVE (1 << 0)
+
+/**
+ * Attempt to load miniOS kernel from the specified device. On success, the
+ * output fields of params will be filled. The caller should set the input
+ * fields of params.
+ *
+ * @param ctx Vboot context
+ * @param params Params specific to loading the kernel
+ * @param disk_info Disk from which to read kernel
+ * @param minios_flags Flags for miniOS
+ *
+ * @return VB2_SUCCESS, or non-zero error code.
+ */
+vb2_error_t vb2api_load_minios_kernel(struct vb2_context *ctx,
+ struct vb2_kernel_params *params,
+ struct vb2_disk_info *disk_info,
+ uint32_t minios_flags);
+
+/**
* Load the verified boot block (vblock) for a kernel.
*
* This function may be called multiple times, to load and verify the
@@ -1027,7 +1119,7 @@
vb2_error_t vb2api_enable_developer_mode(struct vb2_context *ctx);
/**
- * Request to disable developer mode by setting VB2_NV_DIAG_REQUEST.
+ * Request to disable developer mode by setting VB2_NV_DISABLE_DEV_REQUEST.
*
* @param ctx Vboot context
* @return VB2_SUCCESS if success; other errors if the check of
@@ -1433,124 +1525,7 @@
vb2_error_t vb2ex_ec_battery_cutoff(void);
/*****************************************************************************/
-/* Functions for UI display. */
-
-/**
- * UI for a non-manual recovery ("BROKEN").
- *
- * Enter the broken screen UI, which shows that an unrecoverable error was
- * encountered last boot. Wait for the user to physically reset or shut down.
- *
- * @param ctx Vboot context
- * @return VB2_SUCCESS, or non-zero error code.
- */
-vb2_error_t vb2ex_broken_screen_ui(struct vb2_context *ctx);
-
-/**
- * UI for a manual recovery-mode boot.
- *
- * Enter the recovery menu, which prompts the user to insert recovery media,
- * navigate the step-by-step recovery, or enter developer mode if allowed.
- *
- * @param ctx Vboot context
- * @return VB2_SUCCESS, or non-zero error code.
- */
-vb2_error_t vb2ex_manual_recovery_ui(struct vb2_context *ctx);
-
-/**
- * UI for a developer-mode boot.
- *
- * Enter the developer menu, which provides options to switch out of developer
- * mode, boot from external media, use legacy bootloader, or boot Chrome OS from
- * disk.
- *
- * If a timeout occurs, take the default boot action.
- *
- * @param ctx Vboot context
- * @return VB2_SUCCESS, or non-zero error code.
- */
-vb2_error_t vb2ex_developer_ui(struct vb2_context *ctx);
-
-/**
- * UI for a diagnostic tools boot.
- *
- * Enter the diagnostic tools menu, which provides debug information and
- * diagnostic tests of various hardware components.
- *
- * @param ctx Vboot context
- * @return VB2_SUCCESS, or non-zero error code.
- */
-vb2_error_t vb2ex_diagnostic_ui(struct vb2_context *ctx);
-
-/* Helpers for bitmask operations */
-#define VB2_SET_BIT(mask, index) ((mask) |= ((uint32_t)1 << (index)))
-#define VB2_CLR_BIT(mask, index) ((mask) &= ~((uint32_t)1 << (index)))
-#define VB2_GET_BIT(mask, index) ((mask) & ((uint32_t)1 << (index)))
-
-/**
- * Check that physical presence button is currently pressed by the user.
- *
- * @return 1 for pressed, 0 for not.
- */
-int vb2ex_physical_presence_pressed(void);
-
-/**
- * Get the number of supported locales.
- *
- * @return Number of locales. 0 if none or on error.
- */
-uint32_t vb2ex_get_locale_count(void);
-
-/**
- * Return the number of available alternate bootloaders.
- *
- * @return Number of alternate bootloaders. 0 if none or on error.
- */
-uint32_t vb2ex_get_altfw_count(void);
-
-/**
- * Run alternate bootloader.
- *
- * @param altfw_id ID of alternate bootloader to run, where
- * altfw_id <= vb2ex_get_altfw_count(). 0 for default,
- * which corresponds to an alternate bootloader in
- * the range 1 <= altfw_id <= vb2ex_getfw_count().
- * @return VB2_SUCCESS, or error code on error.
- */
-vb2_error_t vb2ex_run_altfw(uint32_t altfw_id);
-
-/**
- * Delay for at least the specified number of milliseconds.
- *
- * @param msec Duration in milliseconds.
- */
-void vb2ex_msleep(uint32_t msec);
-
-/**
- * Play a beep tone of the specified frequency in Hz for the duration msec.
- *
- * This is effectively a sleep call that makes noise. The implementation may
- * beep at a fixed frequency if frequency support is not available. Regardless
- * of whether any errors occur, the callback is expected to delay for the
- * specified duration before returning.
- *
- * @param msec Duration of beep in milliseconds.
- * @param frequency Sound frequency in Hz.
- */
-void vb2ex_beep(uint32_t msec, uint32_t frequency);
-
-/**
- * Get the full debug info string.
- *
- * Return a pointer to the full debug info string which is guaranteed to be
- * null-terminated. The function implementation should manage string memory
- * internally. Subsequent calls may update the string and return the same
- * pointer, or return a new pointer if necessary.
- *
- * @param ctx Vboot context
- * @return The pointer to the full debug info string. NULL on error.
- */
-const char *vb2ex_get_debug_info(struct vb2_context *ctx);
+/* Functions for firmware UI. */
/**
* Get the vboot debug info.
@@ -1564,67 +1539,6 @@
*/
char *vb2api_get_debug_info(struct vb2_context *ctx);
-/**
- * Get the full firmware log string.
- *
- * Return a pointer to the full firmware log string which is guaranteed to be
- * null-terminated. The function implementation should snapshot the full
- * firmware log when it is called. If `reset` is not zero, it will reset the
- * firmware log snapshot.
- *
- * @param reset Discard the current firmware log snapshot and
- * reacquire a new one.
- * @return The pointer to the full firmware log string. NULL on error.
- */
-const char *vb2ex_get_firmware_log(int reset);
-
-/**
- * Get the health info of the storage.
- *
- * @param out For returning a read-only pointer of full log string which is
- * guaranteed to be null-terminated. The function will manage
- * memory internally, so the returned pointer will only be valid
- * until next call.
- * @return VB2_SUCCESS, or error code on error.
- */
-vb2_error_t vb2ex_diag_get_storage_health(const char **out);
-
-/**
- * Get the storage self-test log.
- *
- * @param out For returning a read-only pointer of full log string which is
- * guaranteed to be null-terminated. The function will manage
- * memory internally, so the returned pointer will only be valid
- * until next call.
- * @return The status of storage test. VB2_SUCCESS means the test is finished,
- * regardless of passing or failing. VB2_ERROR_EX_DIAG_TEST_RUNNING means
- * the test is still running. VB2_ERROR_EX_UNIMPLEMENTED means the storage
- * self-test is not supported on this device. Other non-zero codes for internal
- * errors.
- */
-vb2_error_t vb2ex_diag_get_storage_test_log(const char **out);
-
-/**
- * Get the memory diagnostic status. When it is called, it will take over the
- * control for a short period of time running memory test, and then return the
- * result of current status. If `reset` is not zero, it will reset the memory
- * test state.
- *
- * @param reset Discard the current memory test result and re-initialize
- * a new test.
- * @param out For returning a read-only pointer of full log string which is
- * guaranteed to be null-terminated. The function will manage
- * memory internally, so the returned pointer will only be valid
- * until next call.
- * @return The status of memory test. VB2_SUCCESS means the test is finished,
- * regardless of passing or failing. VB2_ERROR_EX_DIAG_TEST_RUNNING means
- * the test is still running but the output buffer was unchanged.
- * VB2_ERROR_EX_DIAG_TEST_UPDATED means the test is still running and the output
- * buffer was updated. Other non-zero codes for internal errors.
- */
-vb2_error_t vb2ex_diag_memory_quick_test(int reset, const char **out);
-vb2_error_t vb2ex_diag_memory_full_test(int reset, const char **out);
-
/*****************************************************************************/
/* Timer. */
@@ -1638,4 +1552,37 @@
*/
uint32_t vb2ex_mtime(void);
+/**
+ * Delay for at least the specified number of milliseconds.
+ *
+ * @param msec Duration in milliseconds.
+ */
+void vb2ex_msleep(uint32_t msec);
+
+union vb2_fw_boot_info {
+ uint8_t raw[4];
+ struct {
+ uint8_t tries : 4;
+ uint8_t slot : 1;
+ uint8_t prev_slot : 1;
+ uint8_t prev_result : 2;
+ uint8_t boot_mode;
+ /* The following 2 bytes only exist for recovery mode */
+ uint8_t recovery_reason;
+ uint8_t recovery_subcode;
+ };
+};
+
+/**
+ * Return `vb2_fw_boot_info` and can be used
+ * to log information about the current boot in a compact format.
+ *
+ * Note: Only call this API at minimum after `vb2api_fw_phase2` function
+ * returns.
+ *
+ * @param ctx Vboot context
+ * @return filled out vb2 info as per `union vb2_fw_boot_info`.
+ */
+union vb2_fw_boot_info vb2api_get_fw_boot_info(struct vb2_context *ctx);
+
#endif /* VBOOT_REFERENCE_2API_H_ */
diff --git a/firmware/2lib/include/2constants.h b/firmware/2lib/include/2constants.h
index 96dc999..c1e6bb9 100644
--- a/firmware/2lib/include/2constants.h
+++ b/firmware/2lib/include/2constants.h
@@ -80,6 +80,14 @@
#ifndef __ASSEMBLER__
#include <stdint.h>
typedef uint32_t vb2_gbb_flags_t;
+/*
+ * We use disk handles rather than indices. Using indices causes problems if
+ * a disk is removed/inserted in the middle of processing.
+ *
+ * TODO(b/181739551): move this to 2api.h when the VbExDisk* functions are
+ * removed from vboot_api.h.
+ */
+typedef void *vb2ex_disk_handle_t;
#endif
/* Size of legacy VbSharedDataHeader struct. Defined here to avoid including
diff --git a/firmware/2lib/include/2info.h b/firmware/2lib/include/2info.h
new file mode 100644
index 0000000..be2ea60
--- /dev/null
+++ b/firmware/2lib/include/2info.h
@@ -0,0 +1,146 @@
+/* Copyright 2022 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.
+ *
+ * Helper functions to retrieve vboot firmware information.
+ */
+
+#ifndef VBOOT_REFERENCE_2INFO_H_
+#define VBOOT_REFERENCE_2INFO_H_
+
+/* Boot mode decided in vb2api_fw_phase1.
+ *
+ * Boot mode is a constant set by verified boot and may be read (but should not
+ * be set or cleared) by the caller.
+ * The boot modes are mutually exclusive. If a boot fulfill more than one
+ * constraints of the listing boot modes, it will be set to the most important
+ * one. The priority is the same as the listing order.
+ */
+enum vb2_boot_mode {
+ /* Undefined, The boot mode is not set. */
+ VB2_BOOT_MODE_UNDEFINED = 0,
+
+ /*
+ * Manual recovery boot, regardless of dev mode state.
+ *
+ * VB2_CONTEXT_RECOVERY_MODE is set and the recovery is physically
+ * requested (a.k.a. Manual recovery). All other recovery requests
+ * including manual recovery requested by a (compromised) host will end
+ * up with a broken screen.
+ */
+ VB2_BOOT_MODE_MANUAL_RECOVERY = 1,
+
+ /*
+ * Broken screen.
+ *
+ * If a recovery boot is not a manual recovery (a.k.a. not requested
+ * physically), the recovery is not allowed and will end up with
+ * broken screen.
+ */
+ VB2_BOOT_MODE_BROKEN_SCREEN = 2,
+
+ /*
+ * Diagnostic boot.
+ *
+ * If diagnostic boot is enabled (a.k.a. vb2api_diagnostic_ui_enabled)
+ * and the nvdata contains VB2_NV_DIAG_REQUEST from previous boot, it
+ * will boot to diagnostic mode.
+ */
+ VB2_BOOT_MODE_DIAGNOSTICS = 3,
+
+ /*
+ * Developer boot: self-signed kernel okay.
+ *
+ * The developer mode switch is set (a.k.a. VB2_CONTEXT_DEVELOPER_MODE)
+ * and we are in the developer boot mode.
+ */
+ VB2_BOOT_MODE_DEVELOPER = 4,
+
+ /* Normal boot: kernel must be verified. */
+ VB2_BOOT_MODE_NORMAL = 5,
+};
+
+/* Firmware slot codes */
+enum vb2_fw_slot {
+ /* Slot A */
+ VB2_FW_SLOT_A = 0,
+
+ /* Slot B */
+ VB2_FW_SLOT_B = 1,
+};
+
+/* Firmware result codes for VB2_NV_FW_RESULT and VB2_NV_FW_PREV_RESULT */
+enum vb2_fw_result {
+ /* Unknown */
+ VB2_FW_RESULT_UNKNOWN = 0,
+
+ /* Trying a new slot, but haven't reached success/failure */
+ VB2_FW_RESULT_TRYING = 1,
+
+ /* Successfully booted to the OS */
+ VB2_FW_RESULT_SUCCESS = 2,
+
+ /* Known failure */
+ VB2_FW_RESULT_FAILURE = 3,
+};
+
+/**
+ * Convert Firmware Boot Mode into supported string
+ *
+ * @return char* firmware boot mode string
+ */
+static inline const char *vb2_boot_mode_string(uint8_t boot_mode)
+{
+ switch ((enum vb2_boot_mode)boot_mode) {
+ /* 0x00 */ case VB2_BOOT_MODE_UNDEFINED:
+ return "Undefined";
+ /* 0x01 */ case VB2_BOOT_MODE_MANUAL_RECOVERY:
+ return "Manual recovery";
+ /* 0x02 */ case VB2_BOOT_MODE_BROKEN_SCREEN:
+ return "Broken screen";
+ /* 0x03 */ case VB2_BOOT_MODE_DIAGNOSTICS:
+ return "Diagnostic";
+ /* 0x04 */ case VB2_BOOT_MODE_DEVELOPER:
+ return "Developer";
+ /* 0x05 */ case VB2_BOOT_MODE_NORMAL:
+ return "Secure";
+ }
+
+ return "Unknown";
+}
+
+/**
+ * Convert Firmware Slot result into supported string
+ *
+ * @return char* firmware slot result string
+ */
+static inline const char *vb2_result_string(uint8_t result)
+{
+ switch ((enum vb2_fw_result)result) {
+ /* 0x00 */ case VB2_FW_RESULT_UNKNOWN:
+ return "Unknown";
+ /* 0x01 */ case VB2_FW_RESULT_TRYING:
+ return "Trying";
+ /* 0x02 */ case VB2_FW_RESULT_SUCCESS:
+ return "Success";
+ /* 0x03 */ case VB2_FW_RESULT_FAILURE:
+ return "Failure";
+ }
+
+ return "Unknown";
+}
+
+/**
+ * Convert Firmware Slot into supported string
+ *
+ * @return char* firmware slot name string
+ */
+static inline const char *vb2_slot_string(uint8_t slot)
+{
+ if ((enum vb2_fw_slot)slot == VB2_FW_SLOT_A)
+ /* 0x00 */ return "A";
+ else
+ /* 0x01 */ return "B";
+}
+
+#endif /* VBOOT_REFERENCE_2INFO_H_ */
diff --git a/firmware/2lib/include/2kernel.h b/firmware/2lib/include/2kernel.h
deleted file mode 100644
index bed1a01..0000000
--- a/firmware/2lib/include/2kernel.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/* Copyright 2020 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.
- *
- * Kernel selection, loading, verification, and booting.
- */
-
-#ifndef VBOOT_REFERENCE_2KERNEL_H_
-#define VBOOT_REFERENCE_2KERNEL_H_
-
-#include "2common.h"
-
-/**
- * Handle a normal boot.
- *
- * @param ctx Vboot context.
- * @return VB2_SUCCESS, or error code on error.
- */
-vb2_error_t vb2_normal_boot(struct vb2_context *ctx);
-
-#endif /* VBOOT_REFERENCE_2KERNEL_H_ */
diff --git a/firmware/2lib/include/2nvstorage.h b/firmware/2lib/include/2nvstorage.h
index fe75823..a457250 100644
--- a/firmware/2lib/include/2nvstorage.h
+++ b/firmware/2lib/include/2nvstorage.h
@@ -129,21 +129,6 @@
VB2_NV_MINIOS_PRIORITY,
};
-/* Firmware result codes for VB2_NV_FW_RESULT and VB2_NV_FW_PREV_RESULT */
-enum vb2_fw_result {
- /* Unknown */
- VB2_FW_RESULT_UNKNOWN = 0,
-
- /* Trying a new slot, but haven't reached success/failure */
- VB2_FW_RESULT_TRYING = 1,
-
- /* Successfully booted to the OS */
- VB2_FW_RESULT_SUCCESS = 2,
-
- /* Known failure */
- VB2_FW_RESULT_FAILURE = 3,
-};
-
/*
* Default value for VB2_NV_FIRMWARE_MAX_ROLLFORWARD on V1. This preserves the
* existing behavior that V1 systems will always roll forward the firmware
diff --git a/firmware/2lib/include/2recovery_reasons.h b/firmware/2lib/include/2recovery_reasons.h
index 30dbd2e..918e332 100644
--- a/firmware/2lib/include/2recovery_reasons.h
+++ b/firmware/2lib/include/2recovery_reasons.h
@@ -205,7 +205,7 @@
/* Shared data error in rewritable firmware */
VB2_RECOVERY_RW_SHARED_DATA = 0x46,
- /* Test error from LoadKernel() (deprecated) */
+ /* Test error from vb2api_load_kernel() (deprecated) */
VB2_RECOVERY_DEPRECATED_RW_TEST_LK = 0x47,
/* No bootable disk found (deprecated, see 0x5a) */
diff --git a/firmware/2lib/include/2return_codes.h b/firmware/2lib/include/2return_codes.h
index 176c2c6..a7b7930 100644
--- a/firmware/2lib/include/2return_codes.h
+++ b/firmware/2lib/include/2return_codes.h
@@ -754,29 +754,32 @@
* Deprecated: functionality removed with legacy UI (b/167643628) */
VB2_ERROR_DEPRECATED_EX_SET_VENDOR_DATA,
- /* The memory test is running but the output buffer was unchanged. */
- VB2_ERROR_EX_DIAG_TEST_RUNNING,
+ /* The memory test is running but the output buffer was unchanged.
+ Deprecated with b/172339016. */
+ VB2_ERROR_DEPRECATED_EX_DIAG_TEST_RUNNING,
- /* The memory test is running and the output buffer was updated. */
- VB2_ERROR_EX_DIAG_TEST_UPDATED,
+ /* The memory test is running and the output buffer was updated.
+ Deprecated with b/172339016. */
+ VB2_ERROR_DEPRECATED_EX_DIAG_TEST_UPDATED,
- /* The memory test initialization failed. */
- VB2_ERROR_EX_DIAG_TEST_INIT_FAILED,
+ /* The memory test initialization failed.
+ Deprecated with b/172339016. */
+ VB2_ERROR_DEPRECATED_EX_DIAG_TEST_INIT_FAILED,
/**********************************************************************
- * LoadKernel errors
+ * Kernel loading errors
*
* Should be ordered by specificity -- lower number means more specific.
*/
VB2_ERROR_LK = 0x100b0000,
- /* Only an invalid kernel was found in LoadKernel() */
+ /* Only an invalid kernel was found in vb2api_load_kernel() */
VB2_ERROR_LK_INVALID_KERNEL_FOUND = 0x100b1000,
- /* No kernel partitions were found in LoadKernel() */
+ /* No kernel partitions were found in vb2api_load_kernel() */
VB2_ERROR_LK_NO_KERNEL_FOUND = 0x100b2000,
- /* No working block devices were found in VbTryLoadKernel() */
+ /* No working block devices were found */
VB2_ERROR_LK_NO_DISK_FOUND = 0x100b3000,
/**********************************************************************
@@ -843,6 +846,9 @@
/* Flashrom exited with failure status */
VB2_ERROR_FLASHROM,
+ /* cbfstool exited with failure status */
+ VB2_ERROR_CBFSTOOL,
+
/**********************************************************************
* Errors generated by host library key functions
*/
diff --git a/firmware/include/gpt_misc.h b/firmware/include/gpt_misc.h
index aa46094..e01e0dc 100644
--- a/firmware/include/gpt_misc.h
+++ b/firmware/include/gpt_misc.h
@@ -76,9 +76,8 @@
* depthcharge does not have logic to properly setup stored_on_device and
* gpt_drive_sectors, but it does do a memset(gpt, 0, sizeof(GptData)). And so,
* GPT_STORED_ON_DEVICE should be 0 to make stored_on_device compatible with
- * present behavior. At the same time, in vboot_kernel:LoadKernel(), and
- * cgpt_common:GptLoad(), we need to have simple shims to set gpt_drive_sectors
- * to drive_sectors.
+ * present behavior. At the same time, in vb2api_load_kernel() and GptLoad(),
+ * we need to have simple shims to set gpt_drive_sectors to drive_sectors.
*
* TODO(namnguyen): Remove those shims when the firmware can set these fields.
*/
@@ -157,12 +156,12 @@
*
* Returns 0 if successful, 1 if error.
*/
-int AllocAndReadGptData(VbExDiskHandle_t disk_handle, GptData *gptdata);
+int AllocAndReadGptData(vb2ex_disk_handle_t disk_handle, GptData *gptdata);
/**
* Write any changes for the GPT data back to the drive, then free the buffers.
*/
-int WriteAndFreeGptData(VbExDiskHandle_t disk_handle, GptData *gptdata);
+int WriteAndFreeGptData(vb2ex_disk_handle_t disk_handle, GptData *gptdata);
/**
* Return 1 if the entry is unused, 0 if it is used.
diff --git a/firmware/include/vboot_api.h b/firmware/include/vboot_api.h
index ce3ac2d..c2fc0ad 100644
--- a/firmware/include/vboot_api.h
+++ b/firmware/include/vboot_api.h
@@ -24,6 +24,7 @@
#include <stdint.h>
#include <stdlib.h>
+#include "../2lib/include/2constants.h"
#include "../2lib/include/2return_codes.h"
#include "gpt.h"
@@ -32,192 +33,12 @@
#endif /* __cplusplus */
struct vb2_context;
+struct vb2_disk_info;
typedef struct VbSharedDataHeader VbSharedDataHeader;
-
-/*****************************************************************************/
-/* Main entry points from firmware into vboot_reference */
-
-/*
- * We use disk handles rather than indices. Using indices causes problems if
- * a disk is removed/inserted in the middle of processing.
- */
-typedef void *VbExDiskHandle_t;
-
-typedef struct VbSelectAndLoadKernelParams {
- /* Inputs to VbSelectAndLoadKernel() */
- /* Destination buffer for kernel (normally at 0x100000 on x86) */
- void *kernel_buffer;
- /* Size of kernel buffer in bytes */
- uint32_t kernel_buffer_size;
-
- /*
- * Outputs from VbSelectAndLoadKernel(); valid only if it returns
- * success.
- */
- /* Handle of disk containing loaded kernel */
- VbExDiskHandle_t disk_handle;
- /* Partition number on disk to boot (1...M) */
- uint32_t partition_number;
- /* Address of bootloader image in RAM */
- uint64_t bootloader_address;
- /* Size of bootloader image in bytes */
- uint32_t bootloader_size;
- /* UniquePartitionGuid for boot partition */
- uint8_t partition_guid[16];
- /* Flags set by signer */
- uint32_t flags;
-} VbSelectAndLoadKernelParams;
-
-/**
- * Select and loads the kernel.
- *
- * Returns VB2_SUCCESS if success, non-zero if error; on error, caller
- * should reboot. */
-vb2_error_t VbSelectAndLoadKernel(struct vb2_context *ctx,
- VbSelectAndLoadKernelParams *kparams);
-
-/**
- * Attempt loading a kernel from the specified type(s) of disks.
- *
- * If successful, sets kparams.disk_handle to the disk for the kernel and
- * returns VB2_SUCCESS.
- *
- * @param ctx Vboot context
- * @param disk_flags Flags to pass to VbExDiskGetInfo()
- * @return VB2_SUCCESS or the most specific VB2_ERROR_LK error.
- */
-vb2_error_t VbTryLoadKernel(struct vb2_context *ctx, uint32_t disk_flags);
-
-/* miniOS flags */
-
-/* Boot from non-active miniOS partition only */
-#define VB_MINIOS_FLAG_NON_ACTIVE (1 << 0)
-
-/**
- * Attempt loading a miniOS kernel from internal disk.
- *
- * Scans sectors at the start and end of the disk, and looks for miniOS kernels
- * starting at the beginning of the sector. Attempts loading any miniOS
- * kernels found.
- *
- * If successful, sets lkp.disk_handle to the disk for the kernel and returns
- * VB2_SUCCESS.
- *
- * @param ctx Vboot context
- * @param minios_flags Flags for miniOS
- * @return VB2_SUCCESS or the most specific VB2_ERROR_LK error.
- */
-vb2_error_t VbTryLoadMiniOsKernel(struct vb2_context *ctx,
- uint32_t minios_flags);
-
/*****************************************************************************/
/* Disk access (previously in boot_device.h) */
-/* Flags for VbDisk APIs */
-
-/*
- * Disk selection in the lower 16 bits (where the disk lives), and disk
- * attributes in the higher 16 bits (extra information about the disk
- * needed to access it correctly).
- */
-#define VB_DISK_FLAG_SELECT_MASK 0xffff
-#define VB_DISK_FLAG_ATTRIBUTE_MASK (0xffff << 16)
-
-/* Disk is removable. Example removable disks: SD cards, USB keys. */
-#define VB_DISK_FLAG_REMOVABLE (1 << 0)
-/*
- * Disk is fixed. If this flag is present, disk is internal to the system and
- * not removable. Example fixed disks: internal SATA SSD, eMMC.
- */
-#define VB_DISK_FLAG_FIXED (1 << 1)
-/*
- * Note that VB_DISK_FLAG_REMOVABLE and VB_DISK_FLAG_FIXED are
- * mutually-exclusive for a single disk. VbExDiskGetInfo() may specify both
- * flags to request disks of both types in a single call.
- *
- * At some point we could specify additional flags, but we don't currently
- * have a way to make use of these:
- *
- * USB Device is known to be attached to USB. Note that the SD
- * card reader inside x86 systems is attached to USB so this
- * isn't super useful.
- * SD Device is known to be a SD card. Note that external card
- * readers might not return this information, so also of
- * questionable use.
- * READ_ONLY Device is known to be read-only. Could be used by recovery
- * when processing read-only recovery image.
- */
-
-/*
- * Disks are used in two ways:
- * - As a random-access device to read and write the GPT
- * - As a streaming device to read the kernel
- * These are implemented differently on raw NAND vs eMMC/SATA/USB
- * - On eMMC/SATA/USB, both of these refer to the same underlying
- * storage, so they have the same size and LBA size. In this case,
- * the GPT should not point to the same address as itself.
- * - On raw NAND, the GPT is held on a portion of the SPI flash.
- * Random access GPT operations refer to the SPI and streaming
- * operations refer to NAND. The GPT may therefore point into
- * the same offsets as itself.
- * These types are distinguished by the following flag and VbDiskInfo
- * has separate fields to describe the random-access ("GPT") and
- * streaming aspects of the disk. If a disk is random-access (i.e.
- * not raw NAND) then these fields are equal.
- */
-#define VB_DISK_FLAG_EXTERNAL_GPT (1 << 16)
-
-/* Information on a single disk */
-typedef struct VbDiskInfo {
- /* Disk handle */
- VbExDiskHandle_t handle;
- /* Size of a random-access LBA sector in bytes */
- uint64_t bytes_per_lba;
- /* Number of random-access LBA sectors on the device.
- * If streaming_lba_count is 0, this stands in for the size of the
- * randomly accessed portion as well as the streaming portion.
- * Otherwise, this is only the randomly-accessed portion. */
- uint64_t lba_count;
- /* Number of streaming sectors on the device */
- uint64_t streaming_lba_count;
- /* Flags (see VB_DISK_FLAG_* constants) */
- uint32_t flags;
- /*
- * Optional name string, for use in debugging. May be empty or null if
- * not available.
- */
- const char *name;
-} VbDiskInfo;
-
-/**
- * Store information into [info] for all disks (storage devices) attached to
- * the system which match all of the disk_flags.
- *
- * On output, count indicates how many disks are present, and [infos_ptr]
- * points to a [count]-sized array of VbDiskInfo structs with the information
- * on those disks; this pointer must be freed by calling VbExDiskFreeInfo().
- * If count=0, infos_ptr may point to NULL. If [infos_ptr] points to NULL
- * because count=0 or error, it is not necessary to call VbExDiskFreeInfo().
- *
- * A multi-function device (such as a 4-in-1 card reader) should provide
- * multiple disk handles.
- *
- * The firmware must not alter or free the list pointed to by [infos_ptr] until
- * VbExDiskFreeInfo() is called.
- */
-vb2_error_t VbExDiskGetInfo(VbDiskInfo **infos_ptr, uint32_t *count,
- uint32_t disk_flags);
-
-/**
- * Free a disk information list [infos] previously returned by
- * VbExDiskGetInfo(). If [preserve_handle] != NULL, the firmware must ensure
- * that handle remains valid after this call; all other handles from the info
- * list need not remain valid after this call.
- */
-vb2_error_t VbExDiskFreeInfo(VbDiskInfo *infos,
- VbExDiskHandle_t preserve_handle);
-
/**
* Read lba_count LBA sectors, starting at sector lba_start, from the disk,
* into the buffer.
@@ -229,7 +50,7 @@
* which as been removed), the function must return error but must not
* crash.
*/
-vb2_error_t VbExDiskRead(VbExDiskHandle_t handle, uint64_t lba_start,
+vb2_error_t VbExDiskRead(vb2ex_disk_handle_t handle, uint64_t lba_start,
uint64_t lba_count, void *buffer);
/**
@@ -243,7 +64,7 @@
* which as been removed), the function must return error but must not
* crash.
*/
-vb2_error_t VbExDiskWrite(VbExDiskHandle_t handle, uint64_t lba_start,
+vb2_error_t VbExDiskWrite(vb2ex_disk_handle_t handle, uint64_t lba_start,
uint64_t lba_count, const void *buffer);
/* Streaming read interface */
@@ -263,7 +84,7 @@
* device. It is not used to access the GPT. The size of the content addressed
* is within streaming_lba_count.
*/
-vb2_error_t VbExStreamOpen(VbExDiskHandle_t handle, uint64_t lba_start,
+vb2_error_t VbExStreamOpen(vb2ex_disk_handle_t handle, uint64_t lba_start,
uint64_t lba_count, VbExStream_t *stream_ptr);
/**
diff --git a/firmware/lib/gpt_misc.c b/firmware/lib/gpt_misc.c
index 641ef37..b42d466 100644
--- a/firmware/lib/gpt_misc.c
+++ b/firmware/lib/gpt_misc.c
@@ -19,7 +19,7 @@
*
* Returns 0 if successful, 1 if error.
*/
-int AllocAndReadGptData(VbExDiskHandle_t disk_handle, GptData *gptdata)
+int AllocAndReadGptData(vb2ex_disk_handle_t disk_handle, GptData *gptdata)
{
int primary_valid = 0, secondary_valid = 0;
@@ -126,7 +126,7 @@
*
* Returns 0 if successful, 1 if error.
*/
-int WriteAndFreeGptData(VbExDiskHandle_t disk_handle, GptData *gptdata)
+int WriteAndFreeGptData(vb2ex_disk_handle_t disk_handle, GptData *gptdata)
{
int skip_primary = 0;
GptHeader *header;
diff --git a/firmware/lib/include/load_kernel_fw.h b/firmware/lib/include/load_kernel_fw.h
deleted file mode 100644
index 76d2556..0000000
--- a/firmware/lib/include/load_kernel_fw.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/* 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 kernel.
- * (Firmware Portion)
- */
-
-#ifndef VBOOT_REFERENCE_LOAD_KERNEL_FW_H_
-#define VBOOT_REFERENCE_LOAD_KERNEL_FW_H_
-
-#include "vboot_api.h"
-
-/**
- * Attempt to load kernel from the specified device.
- *
- * @param ctx Vboot context
- * @param params Params specific to loading the kernel
- * @param disk_info Disk from which to read kernel
- *
- * Returns VB2_SUCCESS if successful. If unsuccessful, returns an error code.
- */
-vb2_error_t LoadKernel(struct vb2_context *ctx,
- VbSelectAndLoadKernelParams *params,
- VbDiskInfo *disk_info);
-
-/**
- * Attempt to load miniOS kernel from the specified device.
- *
- * @param ctx Vboot context
- * @param params Params specific to loading the kernel
- * @param disk_info Disk from which to read kernel
- * @param minios_flags Flags for miniOS
- *
- * Returns VB2_SUCCESS if successful. If unsuccessful, returns an error code.
- */
-vb2_error_t LoadMiniOsKernel(struct vb2_context *ctx,
- VbSelectAndLoadKernelParams *params,
- VbDiskInfo *disk_info, uint32_t minios_flags);
-
-#endif /* VBOOT_REFERENCE_LOAD_KERNEL_FW_H_ */
diff --git a/firmware/lib/include/vboot_struct.h b/firmware/lib/include/vboot_struct.h
index 374dfd4..ea4a9ee 100644
--- a/firmware/lib/include/vboot_struct.h
+++ b/firmware/lib/include/vboot_struct.h
@@ -35,9 +35,9 @@
Deprecated as part of chromium:1010389. */
#define VBSD_FWB_TRIED 0x00000001
/*
- * LoadKernel() verified the good kernel keyblock using the kernel subkey from
- * the firmware. If this flag is not present, it just used the hash of the
- * kernel keyblock.
+ * vb2api_load_kernel() verified the good kernel keyblock using the kernel
+ * subkey from the firmware. If this flag is not present, it just used the
+ * hash of the kernel keyblock.
*/
#define VBSD_KERNEL_KEY_VERIFIED 0x00000002
/* Developer switch was enabled at boot time */
@@ -111,21 +111,8 @@
/* Firmware lowest version found */
uint32_t fw_version_lowest;
- /* Debugging information from LoadKernel() */
- /* Number of times LoadKernel() called */
- uint32_t lk_call_count;
/* Reserved for padding */
- uint8_t reserved3[896];
-
- /*
- * Offset and size of supplemental kernel data. Reserve space for
- * these fields now, so that future LoadKernel() versions can store
- * information there without needing to shift down whatever data the
- * original LoadFirmware() might have put immediately following its
- * VbSharedDataHeader.
- */
- uint64_t kernel_supplemental_offset;
- uint64_t kernel_supplemental_size;
+ uint8_t reserved3[916];
/*
* Fields added in version 2. Before accessing, make sure that
@@ -137,7 +124,7 @@
uint8_t reserved4[7];
/* Flags from firmware keyblock */
uint64_t fw_keyblock_flags;
- /* Kernel TPM version at start of VbSelectAndLoadKernel() */
+ /* Kernel TPM version at start of vb2api_kernel_phase1 */
uint32_t kernel_version_tpm_start;
/* Kernel lowest version found */
uint32_t kernel_version_lowest;
diff --git a/firmware/lib/include/vboot_test.h b/firmware/lib/include/vboot_test.h
deleted file mode 100644
index fb1f52a..0000000
--- a/firmware/lib/include/vboot_test.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/* Copyright 2019 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.
- *
- * This header is for APIs that are only used by test code.
- */
-
-#ifndef VBOOT_REFERENCE_TEST_API_H_
-#define VBOOT_REFERENCE_TEST_API_H_
-
-/****************************************************************************
- * vboot_api_kernel.c */
-
-struct VbSelectAndLoadKernelParams;
-struct VbSelectAndLoadKernelParams **VbApiKernelGetParamsPtr(void);
-
-#endif /* VBOOT_REFERENCE_TEST_API_H_ */
diff --git a/firmware/lib/vboot_api_kernel.c b/firmware/lib/vboot_api_kernel.c
deleted file mode 100644
index 9e89620..0000000
--- a/firmware/lib/vboot_api_kernel.c
+++ /dev/null
@@ -1,264 +0,0 @@
-/* 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 wrapper API - entry points for kernel selection
- */
-
-#include "2api.h"
-#include "2common.h"
-#include "2kernel.h"
-#include "2misc.h"
-#include "2nvstorage.h"
-#include "2rsa.h"
-#include "2secdata.h"
-#include "2sysincludes.h"
-#include "load_kernel_fw.h"
-#include "vboot_api.h"
-#include "vboot_struct.h"
-#include "vboot_test.h"
-
-/* Global variables */
-static VbSelectAndLoadKernelParams *kparams_ptr;
-
-#ifdef CHROMEOS_ENVIRONMENT
-/* Global variable accessor for unit tests */
-struct VbSelectAndLoadKernelParams **VbApiKernelGetParamsPtr(void)
-{
- return &kparams_ptr;
-}
-#endif
-
-static vb2_error_t handle_battery_cutoff(struct vb2_context *ctx)
-{
- /*
- * Check if we need to cut-off battery. This should be done after EC
- * FW and auxfw are updated, and before the kernel is started. This
- * is to make sure all firmware is up-to-date before shipping (which
- * is the typical use-case for cutoff).
- */
- if (vb2_nv_get(ctx, VB2_NV_BATTERY_CUTOFF_REQUEST)) {
- VB2_DEBUG("Request to cut-off battery\n");
- vb2_nv_set(ctx, VB2_NV_BATTERY_CUTOFF_REQUEST, 0);
-
- /* May lose power immediately, so commit our update now. */
- VB2_TRY(vb2ex_commit_data(ctx));
-
- vb2ex_ec_battery_cutoff();
- return VB2_REQUEST_SHUTDOWN;
- }
-
- return VB2_SUCCESS;
-}
-
-static int is_valid_disk(VbDiskInfo *info, uint32_t disk_flags)
-{
- return info->bytes_per_lba >= 512 &&
- (info->bytes_per_lba & (info->bytes_per_lba - 1)) == 0 &&
- info->lba_count >= 16 &&
- (info->flags & disk_flags & VB_DISK_FLAG_SELECT_MASK) &&
- ((info->flags & VB_DISK_FLAG_SELECT_MASK) &
- ((info->flags & VB_DISK_FLAG_SELECT_MASK) - 1)) == 0;
-}
-
-static vb2_error_t VbTryLoadKernelImpl(struct vb2_context *ctx,
- uint32_t disk_flags, int minios,
- uint32_t minios_flags)
-{
- vb2_error_t rv = VB2_ERROR_LK_NO_DISK_FOUND;
- VbDiskInfo* disk_info = NULL;
- uint32_t disk_count = 0;
- uint32_t i;
- vb2_error_t new_rv;
-
- /* TODO: Should have been set by VbSelectAndLoadKernel. Remove when
- this global is no longer needed. */
- VB2_ASSERT(kparams_ptr);
-
- kparams_ptr->disk_handle = NULL;
-
- /* Find disks */
- if (VB2_SUCCESS != VbExDiskGetInfo(&disk_info, &disk_count, disk_flags))
- disk_count = 0;
-
- /* Loop over disks */
- for (i = 0; i < disk_count; i++) {
- VB2_DEBUG("trying disk %d\n", (int)i);
-
- if (!is_valid_disk(&disk_info[i], disk_flags)) {
- VB2_DEBUG(" skipping: bytes_per_lba=%" PRIu64
- " lba_count=%" PRIu64 " flags=%#x\n",
- disk_info[i].bytes_per_lba,
- disk_info[i].lba_count,
- disk_info[i].flags);
- continue;
- }
- kparams_ptr->disk_handle = disk_info[i].handle;
-
- if (minios) {
- new_rv = LoadMiniOsKernel(ctx, kparams_ptr,
- &disk_info[i], minios_flags);
- VB2_DEBUG("LoadMiniOsKernel() = %#x\n", new_rv);
- } else {
- new_rv = LoadKernel(ctx, kparams_ptr, &disk_info[i]);
- VB2_DEBUG("LoadKernel() = %#x\n", new_rv);
- }
-
- /* Stop now if we found a kernel. */
- if (VB2_SUCCESS == new_rv) {
- VbExDiskFreeInfo(disk_info, disk_info[i].handle);
- return VB2_SUCCESS;
- }
-
- /* Don't update error if we already have a more specific one. */
- if (VB2_ERROR_LK_INVALID_KERNEL_FOUND != rv)
- rv = new_rv;
- }
-
- /* If we drop out of the loop, we didn't find any usable kernel. */
- if (!(ctx->flags & VB2_CONTEXT_RECOVERY_MODE) &&
- !(ctx->flags & VB2_CONTEXT_DEVELOPER_MODE)) {
- switch (rv) {
- case VB2_ERROR_LK_INVALID_KERNEL_FOUND:
- vb2api_fail(ctx, VB2_RECOVERY_RW_INVALID_OS, rv);
- break;
- case VB2_ERROR_LK_NO_KERNEL_FOUND:
- vb2api_fail(ctx, VB2_RECOVERY_RW_NO_KERNEL, rv);
- break;
- case VB2_ERROR_LK_NO_DISK_FOUND:
- vb2api_fail(ctx, VB2_RECOVERY_RW_NO_DISK, rv);
- break;
- default:
- vb2api_fail(ctx, VB2_RECOVERY_LK_UNSPECIFIED, rv);
- break;
- }
- }
-
- /* If we didn't find any good kernels, don't return a disk handle. */
- VbExDiskFreeInfo(disk_info, NULL);
-
- return rv;
-}
-
-test_mockable
-vb2_error_t VbTryLoadKernel(struct vb2_context *ctx, uint32_t disk_flags)
-{
- return VbTryLoadKernelImpl(ctx, disk_flags, 0, 0);
-}
-
-test_mockable
-vb2_error_t VbTryLoadMiniOsKernel(struct vb2_context *ctx,
- uint32_t minios_flags)
-{
- return VbTryLoadKernelImpl(ctx, VB_DISK_FLAG_FIXED, 1, minios_flags);
-}
-
-vb2_error_t VbSelectAndLoadKernel(struct vb2_context *ctx,
- VbSelectAndLoadKernelParams *kparams)
-{
- struct vb2_shared_data *sd = vb2_get_sd(ctx);
- vb2_gbb_flags_t gbb_flags = vb2api_gbb_get_flags(ctx);
-
- /* TODO: Send this argument through subsequent function calls, rather
- than relying on a global to pass it to VbTryLoadKernel. */
- kparams_ptr = kparams;
-
- /* Init nvstorage space. TODO(kitching): Remove once we add assertions
- to vb2_nv_get and vb2_nv_set. */
- vb2_nv_init(ctx);
-
- VB2_TRY(vb2api_kernel_phase1(ctx));
-
- VB2_DEBUG("GBB flags are %#x\n", gbb_flags);
-
- /*
- * Do EC and auxfw software sync unless we're in recovery mode. This
- * has UI but it's just a single non-interactive WAIT screen.
- */
- if (!(ctx->flags & VB2_CONTEXT_RECOVERY_MODE)) {
- VB2_TRY(vb2api_ec_sync(ctx));
- VB2_TRY(vb2api_auxfw_sync(ctx));
- VB2_TRY(handle_battery_cutoff(ctx));
- }
-
- /*
- * If in the broken screen, save the recovery reason as subcode.
- * Otherwise, clear any leftover recovery requests or subcodes.
- */
- vb2_clear_recovery(ctx);
-
- /* Select boot path */
- switch (ctx->boot_mode) {
- case VB2_BOOT_MODE_MANUAL_RECOVERY:
- case VB2_BOOT_MODE_BROKEN_SCREEN:
- /* If we're in recovery mode just to do memory retraining, all
- we need to do is reboot. */
- if (sd->recovery_reason == VB2_RECOVERY_TRAIN_AND_REBOOT) {
- VB2_DEBUG("Reboot after retraining in recovery\n");
- return VB2_REQUEST_REBOOT;
- }
-
- /*
- * Need to commit nvdata changes immediately, since we will be
- * entering either manual recovery UI or BROKEN screen shortly.
- */
- vb2ex_commit_data(ctx);
-
- /*
- * In EFS2, recovery mode can be entered even when battery is
- * drained or damaged. EC-RO sets NO_BOOT flag in such case and
- * uses PD power to boot AP.
- *
- * TODO: Inform user why recovery failed to start.
- */
- if (ctx->flags & VB2_CONTEXT_NO_BOOT)
- VB2_DEBUG("NO_BOOT in RECOVERY mode\n");
-
- /* Recovery boot. This has UI. */
- if (ctx->boot_mode == VB2_BOOT_MODE_MANUAL_RECOVERY)
- VB2_TRY(vb2ex_manual_recovery_ui(ctx));
- else
- VB2_TRY(vb2ex_broken_screen_ui(ctx));
- break;
- case VB2_BOOT_MODE_DIAGNOSTICS:
- /*
- * Need to clear the request flag and commit nvdata changes
- * immediately to avoid booting back into diagnostic tool when a
- * forced system reset occurs.
- */
- vb2_nv_set(ctx, VB2_NV_DIAG_REQUEST, 0);
- vb2ex_commit_data(ctx);
-
- /* Diagnostic boot. This has UI. */
- VB2_TRY(vb2ex_diagnostic_ui(ctx));
- /*
- * The diagnostic menu should either boot a rom, or
- * return either of reboot or shutdown.
- */
- return VB2_REQUEST_REBOOT;
- case VB2_BOOT_MODE_DEVELOPER:
- /* Developer boot. This has UI. */
- VB2_TRY(vb2ex_developer_ui(ctx));
- break;
- case VB2_BOOT_MODE_NORMAL:
- /* Normal boot */
- VB2_TRY(vb2_normal_boot(ctx));
- break;
- default:
- return VB2_ERROR_ESCAPE_NO_BOOT;
- }
-
- /*
- * Stop all cases returning SUCCESS against NO_BOOT flag except when
- * GBB flag disables software sync.
- */
- if (!(gbb_flags & VB2_GBB_FLAG_DISABLE_EC_SOFTWARE_SYNC)
- && (ctx->flags & VB2_CONTEXT_EC_SYNC_SUPPORTED)
- && (ctx->flags & VB2_CONTEXT_NO_BOOT)) {
- VB2_DEBUG("Blocking escape from NO_BOOT mode.\n");
- vb2api_fail(ctx, VB2_RECOVERY_ESCAPE_NO_BOOT, 0);
- return VB2_ERROR_ESCAPE_NO_BOOT;
- }
-
- return VB2_SUCCESS;
-}
diff --git a/firmware/stub/vboot_api_stub.c b/firmware/stub/vboot_api_stub.c
deleted file mode 100644
index 9335c8b..0000000
--- a/firmware/stub/vboot_api_stub.c
+++ /dev/null
@@ -1,25 +0,0 @@
-/* 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 firmware-provided API functions.
- */
-
-#include <stdint.h>
-
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/time.h>
-
-#include "2api.h"
-#include "2common.h"
-#include "vboot_api.h"
-#include "vboot_test.h"
-
-__attribute__((weak))
-vb2_error_t vb2ex_run_altfw(uint32_t altfw_id)
-{
- return VB2_SUCCESS;
-}
diff --git a/firmware/stub/vboot_api_stub_disk.c b/firmware/stub/vboot_api_stub_disk.c
index 3244dc6..b09388e 100644
--- a/firmware/stub/vboot_api_stub_disk.c
+++ b/firmware/stub/vboot_api_stub_disk.c
@@ -15,35 +15,15 @@
#include "2common.h"
#include "vboot_api.h"
-
__attribute__((weak))
-vb2_error_t VbExDiskGetInfo(VbDiskInfo** infos_ptr, uint32_t* count,
- uint32_t disk_flags)
-{
- *infos_ptr = NULL;
- *count = 0;
- return VB2_SUCCESS;
-}
-
-
-__attribute__((weak))
-vb2_error_t VbExDiskFreeInfo(VbDiskInfo* infos_ptr,
- VbExDiskHandle_t preserve_handle)
-{
- return VB2_SUCCESS;
-}
-
-
-__attribute__((weak))
-vb2_error_t VbExDiskRead(VbExDiskHandle_t handle, uint64_t lba_start,
+vb2_error_t VbExDiskRead(vb2ex_disk_handle_t handle, uint64_t lba_start,
uint64_t lba_count, void* buffer)
{
return VB2_SUCCESS;
}
-
__attribute__((weak))
-vb2_error_t VbExDiskWrite(VbExDiskHandle_t handle, uint64_t lba_start,
+vb2_error_t VbExDiskWrite(vb2ex_disk_handle_t handle, uint64_t lba_start,
uint64_t lba_count, const void* buffer)
{
return VB2_SUCCESS;
diff --git a/firmware/stub/vboot_api_stub_stream.c b/firmware/stub/vboot_api_stub_stream.c
index 68e7ec7..1a6a65c 100644
--- a/firmware/stub/vboot_api_stub_stream.c
+++ b/firmware/stub/vboot_api_stub_stream.c
@@ -16,7 +16,7 @@
/* Internal struct to simulate a stream for sector-based disks */
struct disk_stream {
/* Disk handle */
- VbExDiskHandle_t handle;
+ vb2ex_disk_handle_t handle;
/* Next sector to read */
uint64_t sector;
@@ -26,7 +26,7 @@
};
__attribute__((weak))
-vb2_error_t VbExStreamOpen(VbExDiskHandle_t handle, uint64_t lba_start,
+vb2_error_t VbExStreamOpen(vb2ex_disk_handle_t handle, uint64_t lba_start,
uint64_t lba_count, VbExStream_t *stream)
{
struct disk_stream *s;
diff --git a/futility/cmd_gscvd.c b/futility/cmd_gscvd.c
index 7fff293..458c754 100644
--- a/futility/cmd_gscvd.c
+++ b/futility/cmd_gscvd.c
@@ -40,9 +40,9 @@
* AP firmware file is ~/tmp/guybrush-signed:
*
./build/futility/futility gscvd --outfile ~/tmp/guybrush-signed \
- -R 818100:10000,f00000:100,f80000:2000,f8c000:1000,0x00804000:0x00000800 \
- -k ~/tmp/packed -p tests/devkeys/arv_platform.vbprivk -b 5a5a4352 \
- -r tests/devkeys/arv_root.vbpubk ~/tmp/image-guybrush.serial.bin
+ -R 818100:10000,f00000:100,f80000:2000,f8c000:1000,0x00804000:0x00000800 \
+ -k ~/tmp/packed -p tests/devkeys/arv_platform.vbprivk -b 5a5a4352 \
+ -r tests/devkeys/arv_root.vbpubk ~/tmp/image-guybrush.serial.bin
*------------
* Command to validate a previously signed AP firmware file. The hash is the
* sha256sum of tests/devkeys/kernel_subkey.vbpubk:
@@ -60,6 +60,7 @@
/* name hasarg *flag val */
{"outfile", 1, NULL, OPT_OUTFILE},
{"ranges", 1, NULL, 'R'},
+ {"add_gbb", 0, NULL, 'G'},
{"board_id", 1, NULL, 'b'},
{"root_pub_key", 1, NULL, 'r'},
{"keyblock", 1, NULL, 'k'},
@@ -68,7 +69,7 @@
{}
};
-static const char *short_opts = "R:b:hk:p:r:";
+static const char *short_opts = "R:Gb:hk:p:r:";
static const char usage[] =
"\n"
@@ -82,8 +83,15 @@
" hex tuples <offset>:<size>, the\n"
" areas of the RO covered by the\n"
" signature\n"
- " -b|--board_id <hex value> The Board ID of the board for which\n"
- " the image is being signed\n"
+ " -G|--add_gbb Add the `GBB` FMAP section to the\n"
+ " ranges covered by the signature.\n"
+ " This option takes special care\n"
+ " to exclude the HWID (and its\n"
+ " digest) from this range.\n"
+ " -b|--board_id <string|hex> The Board ID of the board for\n"
+ " which the image is signed.\n"
+ " Can be passed as a 4-letter\n"
+ " string or a hexadecimal number.\n"
" -r|--root_pub_key <file> The main public key, in .vbpubk\n"
" format, used to verify platform\n"
" key\n"
@@ -140,36 +148,25 @@
*
* @return 0 on success 1 on failure.
*/
-static int load_ap_firmware(const char *file_name, struct file_buf *file)
+static int load_ap_firmware(const char *file_name, struct file_buf *file,
+ int mode)
{
- int fd;
- int rv;
+ if (futil_open_and_map_file(file_name, &file->fd, mode, &file->data,
+ &file->len))
+ return 1;
- fd = open(file_name, O_RDWR);
- if (fd < 0) {
- ERROR("Can't open %s: %s\n", file_name,
- strerror(errno));
+ if (!fmap_find_by_name(file->data, file->len, NULL, "RO_GSCVD",
+ &file->ro_gscvd)) {
+ ERROR("Could not find RO_GSCVD in the FMAP\n");
+ futil_unmap_and_close_file(file->fd, mode, file->data,
+ file->len);
+ file->fd = -1;
+ file->data = NULL;
+ file->len = 0;
return 1;
}
- file->fd = fd;
- do {
- rv = 1;
-
- if (futil_map_file(fd, MAP_RW, &file->data, &file->len)) {
- file->data = NULL;
- break;
- }
-
- if (!fmap_find_by_name(file->data, file->len, NULL, "RO_GSCVD",
- &file->ro_gscvd)) {
- ERROR("Could not find RO_GSCVD in the FMAP\n");
- break;
- }
- rv = 0;
- } while (false);
-
- return rv;
+ return 0;
}
/**
@@ -191,9 +188,6 @@
in_range(range->offset + range->size, ah))
return true;
- ERROR("Range %#x..+%#x does not fit in %s\n", range->offset,
- range->size, ah->area_name);
-
return false;
}
@@ -237,6 +231,7 @@
{
size_t i;
FmapAreaHeader *wp_ro;
+ FmapAreaHeader *si_all;
int errorcount;
if (!fmap_find_by_name(file->data, file->len, NULL, "WP_RO", &wp_ro)) {
@@ -244,13 +239,24 @@
return 1;
}
+ /* Intel boards can have an SI_ALL region that's not in WP_RO but is
+ protected by platform-specific mechanisms, and may still contain
+ components that we want to protect from physical attack. */
+ if (!fmap_find_by_name(file->data, file->len, NULL, "SI_ALL", &si_all))
+ si_all = NULL;
+
errorcount = 0;
for (i = 0; i < ranges->range_count; i++) {
size_t j;
- /* Must fit into WP_RO. */
- if (!range_fits(ranges->ranges + i, wp_ro))
+ /* Must fit into WP_RO or SI_ALL. */
+ if (!range_fits(ranges->ranges + i, wp_ro) &&
+ (!si_all || !range_fits(ranges->ranges + i, si_all))) {
+ ERROR("Range %#x..+%#x does not fit in WP_RO/SI_ALL\n",
+ ranges->ranges[i].offset,
+ ranges->ranges[i].size);
errorcount++;
+ }
/* Must not overlap with RO_GSCVD. */
if (range_overlaps(ranges->ranges + i,
@@ -296,7 +302,6 @@
return -1;
}
- output->range_count = 0;
cursor = str;
do {
char *colon;
@@ -346,6 +351,71 @@
}
/**
+ * Add GBB to ranges.
+ *
+ * Splits the `GBB` FMAP section into separate ranges to exclude the HWID string
+ * and the `hwid_digest` field in the header. Will also exclude the empty area
+ * behind the end of the actual GBB data.
+ *
+ * @param ranges pointer to the ranges container
+ * @param file pointer to the AP firmware file layout descriptor
+ */
+static int add_gbb(struct gscvd_ro_ranges *ranges, const struct file_buf *file)
+{
+ FmapAreaHeader *area;
+
+ if (!fmap_find_by_name(file->data, file->len, NULL, "GBB", &area)) {
+ ERROR("Could not find a GBB area in the FMAP.\n");
+ return 1;
+ }
+
+ struct vb2_gbb_header *gbb = (void *)file->data + area->area_offset;
+ uint32_t maxlen;
+
+ if (!futil_valid_gbb_header(gbb, area->area_size, &maxlen)) {
+ ERROR("GBB is invalid.\n");
+ return 1;
+ }
+
+ /*
+ * This implementation relies on the fact that no meaningful fields come
+ * after the `hwid_digest` field in the header. If we ever make new GBB
+ * versions that add more fields, the code below needs to be adapted.
+ * Older versions than 1.2 or GBBs with a bmpblk are not expected with
+ * GSCVD images.
+ */
+ if (gbb->major_version != 1 || gbb->minor_version != 2 ||
+ gbb->bmpfv_size != 0) {
+ ERROR("Unsupported GBB version.\n");
+ return 1;
+ }
+
+ uint32_t lower_key_offset = VB2_MIN(gbb->rootkey_offset,
+ gbb->recovery_key_offset);
+ if (gbb->hwid_offset > lower_key_offset) {
+ ERROR("Weird GBB layout (HWID should come first)\n");
+ return 1;
+ }
+
+ if (ranges->range_count >= ARRAY_SIZE(ranges->ranges) - 2) {
+ ERROR("Too many ranges, can't fit GBB!\n");
+ return 1;
+ }
+
+ ranges->ranges[ranges->range_count].offset = area->area_offset;
+ ranges->ranges[ranges->range_count].size =
+ offsetof(struct vb2_gbb_header, hwid_digest);
+ ranges->range_count++;
+
+ ranges->ranges[ranges->range_count].offset = area->area_offset +
+ lower_key_offset;
+ ranges->ranges[ranges->range_count].size = maxlen - lower_key_offset;
+ ranges->range_count++;
+
+ return 0;
+}
+
+/**
* Calculate hash of the RO ranges.
*
* @param ap_firmware_file pointer to the AP firmware file layout descriptor
@@ -807,7 +877,7 @@
rv = -1; /* Speculative, will be cleared on success. */
- if (load_ap_firmware(file_name, &ap_firmware_file))
+ if (load_ap_firmware(file_name, &ap_firmware_file, FILE_RO))
break;
/* Copy ranges from gscvd to local structure. */
@@ -842,16 +912,24 @@
break;
}
- if (validate_pubk_signature(&gvd->root_key_header,
- kblock))
+ if (validate_pubk_signature(&gvd->root_key_header, kblock)) {
+ ERROR("Keyblock not signed by root key\n");
break;
+ }
- if (validate_gvd_signature(gvd, &kblock->data_key))
+ if (validate_gvd_signature(gvd, &kblock->data_key)) {
+ ERROR("GVD not signed by platform key\n");
break;
+ }
rv = 0;
} while (false);
+ if (ap_firmware_file.fd != -1)
+ futil_unmap_and_close_file(ap_firmware_file.fd, FILE_RO,
+ ap_firmware_file.data,
+ ap_firmware_file.len);
+
return rv;
}
@@ -890,6 +968,7 @@
{
int i;
int longindex;
+ bool do_gbb = false;
char *infile = NULL;
char *outfile = NULL;
char *work_file = NULL;
@@ -918,13 +997,24 @@
errorcount++;
}
break;
+ case 'G':
+ do_gbb = true;
+ break;
case 'b': {
char *e;
long long bid;
+ if (strlen(optarg) == 4) {
+ board_id = optarg[0] << 24 |
+ optarg[1] << 16 |
+ optarg[2] << 8 |
+ optarg[3];
+ break;
+ }
+
bid = strtoull(optarg, &e, 16);
if (*e || (bid >= UINT32_MAX)) {
- ERROR("Board ID value '%s' is invalid\n",
+ ERROR("Cannot parse Board ID '%s'\n",
optarg);
errorcount++;
} else {
@@ -980,15 +1070,36 @@
return validate_gscvd(argc - 1, argv + 1);
if (optind != (argc - 1)) {
- ERROR("Misformatted command line\n%s\n", usage);
- return 1;
+ ERROR("Misformatted command line\n");
+ goto usage_out;
}
- if (errorcount || !ranges.range_count || !root_pubk || !kblock ||
- !plat_privk || (board_id == UINT32_MAX)) {
- /* Error message(s) should have been printed by now. */
- ERROR("%s\n", usage);
- return 1;
+ if (errorcount) /* Error message(s) should have been printed by now. */
+ goto usage_out;
+
+ if (!root_pubk) {
+ ERROR("Missing --root_pub_key argument\n");
+ goto usage_out;
+ }
+
+ if (!kblock) {
+ ERROR("Missing --keyblock argument\n");
+ goto usage_out;
+ }
+
+ if (!plat_privk) {
+ ERROR("Missing --platform_priv argument\n");
+ goto usage_out;
+ }
+
+ if (board_id == UINT32_MAX) {
+ ERROR("Missing --board_id argument\n");
+ goto usage_out;
+ }
+
+ if (!ranges.range_count && !do_gbb) {
+ ERROR("Missing --ranges argument\n");
+ goto usage_out;
}
infile = argv[optind];
@@ -1009,7 +1120,10 @@
if (validate_privk(kblock, plat_privk))
break;
- if (load_ap_firmware(work_file, &ap_firmware_file))
+ if (load_ap_firmware(work_file, &ap_firmware_file, FILE_RW))
+ break;
+
+ if (do_gbb && add_gbb(&ranges, &ap_firmware_file))
break;
if (verify_ranges(&ranges, &ap_firmware_file))
@@ -1033,17 +1147,16 @@
free(kblock);
vb2_private_key_free(plat_privk);
- /* Now flush the file. */
- if (ap_firmware_file.data) {
- rv |= futil_unmap_file(ap_firmware_file.fd, true,
- ap_firmware_file.data,
- ap_firmware_file.len);
- }
-
if (ap_firmware_file.fd != -1)
- close(ap_firmware_file.fd);
+ futil_unmap_and_close_file(ap_firmware_file.fd, FILE_RW,
+ ap_firmware_file.data,
+ ap_firmware_file.len);
return rv;
+
+usage_out:
+ fputs(usage, stderr);
+ return 1;
}
DECLARE_FUTIL_COMMAND(gscvd, do_gscvd, VBOOT_VERSION_2_1,
diff --git a/futility/cmd_load_fmap.c b/futility/cmd_load_fmap.c
index 818fda8..4ab194e 100644
--- a/futility/cmd_load_fmap.c
+++ b/futility/cmd_load_fmap.c
@@ -149,22 +149,16 @@
else
outfile = infile;
- fd = open(outfile, O_RDWR);
- if (fd < 0) {
- fprintf(stderr, "Can't open %s: %s\n",
- outfile, strerror(errno));
- return 1;
- }
+ errorcnt |= futil_open_and_map_file(outfile, &fd, FILE_RW, &buf, &len);
- errorcnt |= futil_map_file(fd, MAP_RW, &buf, &len);
if (errorcnt)
- goto done_file;
+ goto done;
fmap = fmap_find(buf, len);
if (!fmap) {
fprintf(stderr, "Can't find an FMAP in %s\n", infile);
errorcnt++;
- goto done_map;
+ goto done;
}
for (i = optind; i < argc; i++) {
@@ -190,20 +184,10 @@
}
}
-done_map:
- errorcnt |= futil_unmap_file(fd, 1, buf, len);
-
-done_file:
-
- if (0 != close(fd)) {
- fprintf(stderr, "Error closing %s: %s\n",
- outfile, strerror(errno));
- errorcnt++;
- }
-
+done:
+ errorcnt |= futil_unmap_and_close_file(fd, FILE_RW, buf, len);
return !!errorcnt;
}
DECLARE_FUTIL_COMMAND(load_fmap, do_load_fmap, VBOOT_VERSION_ALL,
"Replace the contents of specified FMAP areas");
-
diff --git a/futility/cmd_show.c b/futility/cmd_show.c
index dbe6edd..9816106 100644
--- a/futility/cmd_show.c
+++ b/futility/cmd_show.c
@@ -86,31 +86,49 @@
packed_key_sha1_string(data_key));
}
-int ft_show_pubkey(const char *name, uint8_t *buf, uint32_t len, void *data)
+int ft_show_pubkey(const char *name, void *data)
{
- struct vb2_packed_key *pubkey = (struct vb2_packed_key *)buf;
+ int fd = -1;
+ struct vb2_packed_key *pubkey;
+ uint32_t len;
+ int rv = 0;
+
+ if (futil_open_and_map_file(name, &fd, FILE_RO, (uint8_t **)&pubkey,
+ &len))
+ return 1;
if (vb2_packed_key_looks_ok(pubkey, len)) {
printf("%s looks bogus\n", name);
- return 1;
+ rv = 1;
+ goto done;
}
printf("Public Key file: %s\n", name);
show_pubkey(pubkey, " ");
- return 0;
+done:
+ futil_unmap_and_close_file(fd, FILE_RO, (uint8_t *)pubkey, len);
+ return rv;
}
-int ft_show_privkey(const char *name, uint8_t *buf, uint32_t len, void *data)
+int ft_show_privkey(const char *name, void *data)
{
- struct vb2_packed_private_key *pkey =
- (struct vb2_packed_private_key *)buf;
+ int fd = -1;
+ int rv = 0;
+ struct vb2_packed_private_key *pkey = NULL;
+ uint32_t len;
struct vb2_private_key key;
- const unsigned char *start = pkey->key_data;
+ const unsigned char *start;
+ if (futil_open_and_map_file(name, &fd, FILE_RO, (uint8_t **)&pkey,
+ &len))
+ return 1;
+
+ start = pkey->key_data;
if (len <= sizeof(*pkey)) {
printf("%s looks bogus\n", name);
- return 1;
+ rv = 1;
+ goto done;
}
len -= sizeof(*pkey);
key.rsa_private_key = d2i_RSAPrivateKey(NULL, &start, len);
@@ -122,20 +140,30 @@
printf(" Key sha1sum: %s\n",
private_key_sha1_string(&key));
- return 0;
+done:
+ futil_unmap_and_close_file(fd, FILE_RO, (uint8_t *)pkey, len);
+ return rv;
}
-int ft_show_keyblock(const char *name, uint8_t *buf, uint32_t len, void *data)
+int ft_show_keyblock(const char *name, void *data)
{
- struct vb2_keyblock *block = (struct vb2_keyblock *)buf;
+ struct vb2_keyblock *block;
struct vb2_public_key *sign_key = show_option.k;
int good_sig = 0;
int retval = 0;
+ int fd = -1;
+ uint32_t len;
+
+ retval = futil_open_and_map_file(name, &fd, FILE_RO, (uint8_t **)&block,
+ &len);
+ if (retval)
+ return 1;
/* Check the hash only first */
if (0 != vb2_verify_keyblock_hash(block, len, &wb)) {
printf("%s is invalid\n", name);
- return 1;
+ retval = 1;
+ goto done;
}
/* Check the signature if we have one */
@@ -148,11 +176,13 @@
show_keyblock(block, name, !!sign_key, good_sig);
+done:
+ futil_unmap_and_close_file(fd, FILE_RO, (uint8_t *)block, len);
return retval;
}
-int ft_show_fw_preamble(const char *name, uint8_t *buf, uint32_t len,
- void *data)
+int show_fw_preamble_buf(const char *name, uint8_t *buf, uint32_t len,
+ void *data)
{
struct vb2_keyblock *keyblock = (struct vb2_keyblock *)buf;
struct bios_state_s *state = (struct bios_state_s *)data;
@@ -282,17 +312,40 @@
return retval;
}
-int ft_show_kernel_preamble(const char *name, uint8_t *buf, uint32_t len,
- void *data)
+int ft_show_fw_preamble(const char *name, void *data)
{
- struct vb2_keyblock *keyblock = (struct vb2_keyblock *)buf;
+ int rv = 0;
+ int fd = -1;
+ uint8_t *buf;
+ uint32_t len;
+
+ if (futil_open_and_map_file(name, &fd, FILE_RO, &buf, &len))
+ return 1;
+
+ rv = show_fw_preamble_buf(name, buf, len, data);
+
+ futil_unmap_and_close_file(fd, FILE_RO, buf, len);
+ return rv;
+}
+
+int ft_show_kernel_preamble(const char *name, void *data)
+{
+ struct vb2_keyblock *keyblock;
struct vb2_public_key *sign_key = show_option.k;
- int retval = 0;
+ int retval = 1;
+ int fd = -1;
+ uint8_t *buf;
+ uint32_t len;
+
+ if (futil_open_and_map_file(name, &fd, FILE_RO, &buf, &len))
+ return 1;
+
+ keyblock = (struct vb2_keyblock *)buf;
/* Check the hash... */
if (VB2_SUCCESS != vb2_verify_keyblock_hash(keyblock, len, &wb)) {
printf("%s keyblock component is invalid\n", name);
- return 1;
+ goto done;
}
/* If we have a key, check the signature too */
@@ -304,13 +357,10 @@
printf("Kernel partition: %s\n", name);
show_keyblock(keyblock, NULL, !!sign_key, good_sig);
- if (show_option.strict && (!sign_key || !good_sig))
- retval = 1;
-
struct vb2_public_key data_key;
if (VB2_SUCCESS != vb2_unpack_key(&data_key, &keyblock->data_key)) {
fprintf(stderr, "Error parsing data key in %s\n", name);
- return 1;
+ goto done;
}
uint32_t more = keyblock->keyblock_size;
@@ -320,7 +370,7 @@
if (VB2_SUCCESS != vb2_verify_kernel_preamble(pre2, len - more,
&data_key, &wb)) {
printf("%s is invalid\n", name);
- return 1;
+ goto done;
}
printf("Kernel Preamble:\n");
@@ -367,20 +417,24 @@
if (!kernel_blob) {
/* TODO: Is this always a failure? The preamble is okay. */
fprintf(stderr, "No kernel blob available to verify.\n");
- return 1;
+ goto done;
}
if (VB2_SUCCESS !=
vb2_verify_data(kernel_blob, kernel_size, &pre2->body_signature,
&data_key, &wb)) {
fprintf(stderr, "Error verifying kernel body.\n");
- return 1;
+ goto done;
}
printf("Body verification succeeded.\n");
printf("Config:\n%s\n", kernel_blob + kernel_cmd_line_offset(pre2));
+ if (!show_option.strict || (sign_key && good_sig))
+ retval = 0;
+done:
+ futil_unmap_and_close_file(fd, FILE_RO, buf, len);
return retval;
}
@@ -476,9 +530,8 @@
uint8_t *pubkbuf = NULL;
struct vb2_public_key pubk2;
char *infile = 0;
- int ifd, i;
+ int i;
int errorcnt = 0;
- uint8_t *buf;
uint32_t len;
char *e = 0;
int type_override = 0;
@@ -585,34 +638,14 @@
for (i = optind; i < argc; i++) {
infile = argv[i];
- ifd = open(infile, O_RDONLY);
- if (ifd < 0) {
- errorcnt++;
- fprintf(stderr, "Can't open %s: %s\n",
- infile, strerror(errno));
- continue;
- }
-
- if (0 != futil_map_file(ifd, MAP_RO, &buf, &len)) {
- errorcnt++;
- goto boo;
- }
/* Allow the user to override the type */
if (type_override)
type = show_option.type;
else
- type = futil_file_type_buf(buf, len);
+ futil_file_type(infile, &type);
- errorcnt += futil_file_type_show(type, infile, buf, len);
-
- errorcnt += futil_unmap_file(ifd, MAP_RO, buf, len);
-boo:
- if (close(ifd)) {
- errorcnt++;
- fprintf(stderr, "Error when closing %s: %s\n",
- infile, strerror(errno));
- }
+ errorcnt += futil_file_type_show(type, infile);
}
done:
@@ -635,4 +668,5 @@
DECLARE_FUTIL_COMMAND(verify, do_verify,
VBOOT_VERSION_ALL,
- "Verify the signatures of various binary components");
+ "Verify the signatures of various binary components. "
+ "This does not verify GSCVD contents.");
diff --git a/futility/cmd_sign.c b/futility/cmd_sign.c
index be8b634..2f9a017 100644
--- a/futility/cmd_sign.c
+++ b/futility/cmd_sign.c
@@ -29,8 +29,11 @@
#include "util_misc.h"
#include "vb1_helper.h"
+#define DEFAULT_KEYSETDIR "/usr/share/vboot/devkeys"
+
/* Options */
struct sign_option_s sign_option = {
+ .keysetdir = DEFAULT_KEYSETDIR,
.version = 1,
.arch = ARCH_UNSPECIFIED,
.kloadaddr = CROS_32BIT_ENTRY_ADDR,
@@ -55,14 +58,21 @@
}
/* This wraps/signs a public key, producing a keyblock. */
-int ft_sign_pubkey(const char *name, uint8_t *buf, uint32_t len, void *data)
+int ft_sign_pubkey(const char *name, void *data)
{
- struct vb2_packed_key *data_key = (struct vb2_packed_key *)buf;
+ struct vb2_packed_key *data_key;
+ uint32_t data_len;
struct vb2_keyblock *block;
+ int rv = 1;
+ int fd = -1;
- if (vb2_packed_key_looks_ok(data_key, len)) {
- fprintf(stderr, "Public key looks bad.\n");
+ if (futil_open_and_map_file(name, &fd, FILE_MODE_SIGN(sign_option),
+ (uint8_t **)&data_key, &data_len))
return 1;
+
+ if (vb2_packed_key_looks_ok(data_key, data_len)) {
+ fprintf(stderr, "Public key looks bad.\n");
+ goto done;
}
if (sign_option.pem_signpriv) {
@@ -82,7 +92,7 @@
fprintf(stderr,
"Unable to read PEM signing key: %s\n",
strerror(errno));
- return 1;
+ goto done;
}
block = vb2_create_keyblock(data_key,
sign_option.signprivate,
@@ -95,20 +105,24 @@
}
/* Write it out */
- return WriteSomeParts(sign_option.outfile,
- block, block->keyblock_size,
- NULL, 0);
+ rv = WriteSomeParts(sign_option.outfile, block, block->keyblock_size,
+ NULL, 0);
+done:
+ futil_unmap_and_close_file(fd, FILE_MODE_SIGN(sign_option),
+ (uint8_t *)data_key, data_len);
+ return rv;
}
-int ft_sign_raw_kernel(const char *name, uint8_t *buf, uint32_t len,
- void *data)
+int ft_sign_raw_kernel(const char *name, void *data)
{
- uint8_t *vmlinuz_data, *kblob_data, *vblock_data;
+ uint8_t *vmlinuz_data = NULL, *kblob_data = NULL, *vblock_data = NULL;
uint32_t vmlinuz_size, kblob_size, vblock_size;
- int rv;
+ int rv = 1;
+ int fd = -1;
- vmlinuz_data = buf;
- vmlinuz_size = len;
+ if (futil_open_and_map_file(name, &fd, FILE_MODE_SIGN(sign_option),
+ &vmlinuz_data, &vmlinuz_size))
+ return 1;
kblob_data = CreateKernelBlob(
vmlinuz_data, vmlinuz_size,
@@ -118,7 +132,7 @@
&kblob_size);
if (!kblob_data) {
fprintf(stderr, "Unable to create kernel blob\n");
- return 1;
+ goto done;
}
VB2_DEBUG("kblob_size = %#x\n", kblob_size);
@@ -131,8 +145,7 @@
sign_option.flags, &vblock_size);
if (!vblock_data) {
fprintf(stderr, "Unable to sign kernel blob\n");
- free(kblob_data);
- return 1;
+ goto done;
}
VB2_DEBUG("vblock_size = %#x\n", vblock_size);
@@ -150,22 +163,26 @@
vblock_data, vblock_size,
kblob_data, kblob_size);
+done:
+ futil_unmap_and_close_file(fd, FILE_MODE_SIGN(sign_option),
+ vmlinuz_data, vmlinuz_size);
free(vblock_data);
free(kblob_data);
return rv;
}
-int ft_sign_kern_preamble(const char *name, uint8_t *buf, uint32_t len,
- void *data)
+int ft_sign_kern_preamble(const char *name, void *data)
{
- uint8_t *kpart_data, *kblob_data, *vblock_data;
+ uint8_t *kpart_data = NULL, *kblob_data = NULL, *vblock_data = NULL;
uint32_t kpart_size, kblob_size, vblock_size;
struct vb2_keyblock *keyblock = NULL;
struct vb2_kernel_preamble *preamble = NULL;
- int rv = 0;
+ int rv = 1;
+ int fd = -1;
- kpart_data = buf;
- kpart_size = len;
+ if (futil_open_and_map_file(name, &fd, FILE_MODE_SIGN(sign_option),
+ &kpart_data, &kpart_size))
+ return 1;
/* Note: This just sets some static pointers. It doesn't malloc. */
kblob_data = unpack_kernel_partition(kpart_data, kpart_size,
@@ -174,7 +191,7 @@
if (!kblob_data) {
fprintf(stderr, "Unable to unpack kernel partition\n");
- return 1;
+ goto done;
}
/*
@@ -192,7 +209,7 @@
sign_option.config_data,
sign_option.config_size)) {
fprintf(stderr, "Unable to update config\n");
- return 1;
+ goto done;
}
/* Preserve the version unless a new one is given */
@@ -219,7 +236,7 @@
&vblock_size);
if (!vblock_data) {
fprintf(stderr, "Unable to sign kernel blob\n");
- return 1;
+ goto done;
}
VB2_DEBUG("vblock_size = %#x\n", vblock_size);
@@ -238,24 +255,33 @@
* all our modifications to the buffer will get flushed to
* disk when we close it. */
memcpy(kpart_data, vblock_data, vblock_size);
+ rv = 0;
}
-
+done:
+ futil_unmap_and_close_file(fd, FILE_MODE_SIGN(sign_option), kpart_data,
+ kpart_size);
free(vblock_data);
return rv;
}
-int ft_sign_raw_firmware(const char *name, uint8_t *buf, uint32_t len,
- void *data)
+int ft_sign_raw_firmware(const char *name, void *data)
{
- struct vb2_signature *body_sig;
- struct vb2_fw_preamble *preamble;
- int rv;
+ struct vb2_signature *body_sig = NULL;
+ struct vb2_fw_preamble *preamble = NULL;
+ uint8_t *buf;
+ uint32_t len;
+ int rv = 1;
+ int fd = -1;
+
+ if (futil_open_and_map_file(name, &fd, FILE_MODE_SIGN(sign_option),
+ &buf, &len))
+ return 1;
body_sig = vb2_calculate_signature(buf, len, sign_option.signprivate);
if (!body_sig) {
fprintf(stderr, "Error calculating body signature\n");
- return 1;
+ goto done;
}
preamble = vb2_create_fw_preamble(
@@ -267,7 +293,7 @@
if (!preamble) {
fprintf(stderr, "Error creating firmware preamble.\n");
free(body_sig);
- return 1;
+ goto done;
}
rv = WriteSomeParts(sign_option.outfile,
@@ -275,12 +301,94 @@
sign_option.keyblock->keyblock_size,
preamble, preamble->preamble_size);
+done:
+ futil_unmap_and_close_file(fd, FILE_MODE_SIGN(sign_option), buf, len);
free(preamble);
free(body_sig);
return rv;
}
+static int load_keyset(void)
+{
+ char *buf = NULL;
+ int errorcnt = 0;
+ const char *s = NULL;
+ const char *b = NULL;
+ const char *k = NULL;
+ const char *format;
+ struct stat sb;
+
+ if (!sign_option.keysetdir)
+ FATAL("Keyset should never be NULL. Aborting\n");
+
+ /* Failure means this is not a directory */
+ if (stat(sign_option.keysetdir, &sb) == -1 ||
+ (sb.st_mode & S_IFMT) != S_IFDIR)
+ format = "%s%s.%s";
+ else
+ format = "%s/%s.%s";
+
+ switch (sign_option.type) {
+ case FILE_TYPE_BIOS_IMAGE:
+ case FILE_TYPE_RAW_FIRMWARE:
+ s = "firmware_data_key";
+ b = "firmware";
+ k = "kernel_subkey";
+ break;
+ case FILE_TYPE_RAW_KERNEL:
+ s = "kernel_data_key";
+ b = "kernel";
+ break;
+ case FILE_TYPE_KERN_PREAMBLE:
+ s = "kernel_data_key";
+ break;
+ default:
+ return 0;
+ }
+
+ if (s && !sign_option.signprivate) {
+ if (asprintf(&buf, format, sign_option.keysetdir, s,
+ "vbprivk") <= 0)
+ FATAL("Failed to allocate string\n");
+ INFO("Loading private data key from default keyset: %s\n", buf);
+ sign_option.signprivate = vb2_read_private_key(buf);
+ if (!sign_option.signprivate) {
+ ERROR("Error reading %s\n", buf);
+ errorcnt++;
+ }
+ free(buf);
+ }
+
+ if (b && !sign_option.keyblock) {
+ if (asprintf(&buf, format, sign_option.keysetdir, b,
+ "keyblock") <= 0)
+ FATAL("Failed to allocate string\n");
+ INFO("Loading keyblock from default keyset: %s\n", buf);
+ sign_option.keyblock = vb2_read_keyblock(buf);
+ if (!sign_option.keyblock) {
+ ERROR("Error reading %s\n", buf);
+ errorcnt++;
+ }
+ free(buf);
+ }
+
+ if (k && !sign_option.kernel_subkey) {
+ if (asprintf(&buf, format, sign_option.keysetdir, k,
+ "vbpubk") <= 0)
+ FATAL("Failed to allocate string\n");
+ INFO("Loading kernel subkey from default keyset: %s\n", buf);
+ sign_option.kernel_subkey = vb2_read_packed_key(buf);
+ if (!sign_option.kernel_subkey) {
+ ERROR("Error reading %s\n", buf);
+ errorcnt++;
+ }
+ free(buf);
+ }
+
+ return errorcnt;
+}
+
static const char usage_pubkey[] = "\n"
"To sign a public key / create a new keyblock:\n"
"\n"
@@ -313,41 +421,46 @@
"To sign a raw firmware blob (FW_MAIN_A/B):\n"
"\n"
"Required PARAMS:\n"
- " -s|--signprivate FILE.vbprivk The private firmware data key\n"
- " -b|--keyblock FILE.keyblock The keyblock containing the\n"
- " public firmware data key\n"
- " -k|--kernelkey FILE.vbpubk The public kernel subkey\n"
" -v|--version NUM The firmware version number\n"
" [--fv] INFILE"
" The raw firmware blob (FW_MAIN_A/B)\n"
" [--outfile] OUTFILE Output VBLOCK_A/B\n"
"\n"
"Optional PARAMS:\n"
+ " -s|--signprivate FILE.vbprivk The private firmware data key\n"
+ " -b|--keyblock FILE.keyblock The keyblock containing the\n"
+ " public firmware data key\n"
+ " -k|--kernelkey FILE.vbpubk The public kernel subkey\n"
" -f|--flags NUM The preamble flags value"
" (default is 0)\n"
+ " -K|--keyset PATH Prefix of private firmware data"
+ " key,\n"
+ " keyblock and public kernel"
+ " subkey.\n"
+ " Prefix must be valid path with\n"
+ " optional file name prefix.\n"
+ " Used as defaults for -s, -b and"
+ " -k,\n"
+ " if not passed expliticly\n"
+ " (default is '%s')\n"
"\n";
static void print_help_raw_firmware(int argc, char *argv[])
{
- puts(usage_fw_main);
+ printf(usage_fw_main, DEFAULT_KEYSETDIR);
}
static const char usage_bios[] = "\n"
"To sign a complete firmware image (bios.bin):\n"
"\n"
"Required PARAMS:\n"
+ " [--infile] INFILE Input firmware image (modified\n"
+ " in place if no OUTFILE given)\n"
+ "\n"
+ "Optional PARAMS:\n"
" -s|--signprivate FILE.vbprivk The private firmware data key\n"
" -b|--keyblock FILE.keyblock The keyblock containing the\n"
" public firmware data key\n"
" -k|--kernelkey FILE.vbpubk The public kernel subkey\n"
- " [--infile] INFILE Input firmware image (modified\n"
- " in place if no OUTFILE given)\n"
- "\n"
- "These are required if the A and B firmware differ:\n"
- " -S|--devsign FILE.vbprivk The DEV private firmware data key\n"
- " -B|--devkeyblock FILE.keyblock The keyblock containing the\n"
- " DEV public firmware data key\n"
- "\n"
- "Optional PARAMS:\n"
" -v|--version NUM The firmware version number"
" (default %d)\n"
" -f|--flags NUM The preamble flags value"
@@ -355,21 +468,27 @@
" unchanged, or 0 if unknown)\n"
" -d|--loemdir DIR Local OEM output vblock directory\n"
" -l|--loemid STRING Local OEM vblock suffix\n"
+ " -K|--keyset PATH Prefix of private firmware data"
+ " key,\n"
+ " keyblock and public kernel"
+ " subkey.\n"
+ " Prefix must be valid path with\n"
+ " optional file name prefix.\n"
+ " Used as defaults for -s, -b and"
+ " -k,\n"
+ " if not passed expliticly\n"
+ " (default is '%s')\n"
" [--outfile] OUTFILE Output firmware image\n"
"\n";
static void print_help_bios_image(int argc, char *argv[])
{
- printf(usage_bios, sign_option.version);
+ printf(usage_bios, sign_option.version, DEFAULT_KEYSETDIR);
}
static const char usage_new_kpart[] = "\n"
"To create a new kernel partition image (/dev/sda2, /dev/mmcblk0p2):\n"
"\n"
"Required PARAMS:\n"
- " -s|--signprivate FILE.vbprivk"
- " The private key to sign the kernel blob\n"
- " -b|--keyblock FILE.keyblock Keyblock containing the public\n"
- " key to verify the kernel blob\n"
" -v|--version NUM The kernel version number\n"
" --bootloader FILE Bootloader stub\n"
" --config FILE The kernel commandline file\n"
@@ -379,6 +498,10 @@
" [--outfile] OUTFILE Output kernel partition or vblock\n"
"\n"
"Optional PARAMS:\n"
+ " -s|--signprivate FILE.vbprivk"
+ " The private key to sign the kernel blob\n"
+ " -b|--keyblock FILE.keyblock Keyblock containing the public\n"
+ " key to verify the kernel blob\n"
" --kloadaddr NUM"
" RAM address to load the kernel body\n"
" (default %#x)\n"
@@ -387,22 +510,33 @@
" --vblockonly Emit just the vblock (requires a\n"
" distinct outfile)\n"
" -f|--flags NUM The preamble flags value\n"
+ " -K|--keyset DIR Path to directory containing"
+ " private\n"
+ " kernel data key, and keyblock\n"
+ " -K|--keyset PATH Prefix of private kernel data key\n"
+ " and keyblock.\n"
+ " Prefix must be valid path with\n"
+ " optional file name prefix.\n"
+ " Used as defaults for -s and -b,\n"
+ " if not passed expliticly\n"
+ " (default is '%s')\n"
"\n";
static void print_help_raw_kernel(int argc, char *argv[])
{
- printf(usage_new_kpart, sign_option.kloadaddr, sign_option.padding);
+ printf(usage_new_kpart, sign_option.kloadaddr, sign_option.padding,
+ DEFAULT_KEYSETDIR);
}
static const char usage_old_kpart[] = "\n"
"To resign an existing kernel partition (/dev/sda2, /dev/mmcblk0p2):\n"
"\n"
"Required PARAMS:\n"
- " -s|--signprivate FILE.vbprivk"
- " The private key to sign the kernel blob\n"
" [--infile] INFILE Input kernel partition (modified\n"
" in place if no OUTFILE given)\n"
"\n"
"Optional PARAMS:\n"
+ " -s|--signprivate FILE.vbprivk"
+ " The private key to sign the kernel blob\n"
" -b|--keyblock FILE.keyblock Keyblock containing the public\n"
" key to verify the kernel blob\n"
" -v|--version NUM The kernel version number\n"
@@ -413,10 +547,17 @@
" --vblockonly Emit just the vblock (requires a\n"
" distinct OUTFILE)\n"
" -f|--flags NUM The preamble flags value\n"
+ " -K|--keyset PATH Prefix of private kernel data"
+ " key.\n"
+ " Prefix must be valid path with\n"
+ " optional file name prefix.\n"
+ " Used as default for -s,\n"
+ " if not passed expliticly\n"
+ " (default is '%s')\n"
"\n";
static void print_help_kern_preamble(int argc, char *argv[])
{
- printf(usage_old_kpart, sign_option.padding);
+ printf(usage_old_kpart, sign_option.padding, DEFAULT_KEYSETDIR);
}
static void print_help_usbpd1(int argc, char *argv[])
@@ -595,12 +736,11 @@
{"signprivate", 1, NULL, 's'},
{"keyblock", 1, NULL, 'b'},
{"kernelkey", 1, NULL, 'k'},
- {"devsign", 1, NULL, 'S'},
- {"devkeyblock", 1, NULL, 'B'},
{"version", 1, NULL, 'v'},
{"flags", 1, NULL, 'f'},
{"loemdir", 1, NULL, 'd'},
{"loemid", 1, NULL, 'l'},
+ {"keyset", 1, NULL, 'K'},
{"fv", 1, NULL, OPT_FV},
{"infile", 1, NULL, OPT_INFILE},
{"datapubkey", 1, NULL, OPT_INFILE}, /* alias */
@@ -629,7 +769,7 @@
{"help", 0, NULL, OPT_HELP},
{NULL, 0, NULL, 0},
};
-static const char *short_opts = ":s:b:k:S:B:v:f:d:l:";
+static const char *short_opts = ":s:b:k:v:f:d:l:K:";
/* Return zero on success */
static int parse_number_opt(const char *arg, const char *name, uint32_t *dest)
@@ -648,12 +788,8 @@
{
char *infile = 0;
int i;
- int ifd = -1;
int errorcnt = 0;
- uint8_t *buf;
- uint32_t buf_len;
char *e = 0;
- int mapping;
int helpind = 0;
int longindex;
@@ -682,21 +818,6 @@
errorcnt++;
}
break;
- case 'S':
- sign_option.devsignprivate =
- vb2_read_private_key(optarg);
- if (!sign_option.devsignprivate) {
- fprintf(stderr, "Error reading %s\n", optarg);
- errorcnt++;
- }
- break;
- case 'B':
- sign_option.devkeyblock = vb2_read_keyblock(optarg);
- if (!sign_option.devkeyblock) {
- fprintf(stderr, "Error reading %s\n", optarg);
- errorcnt++;
- }
- break;
case 'v':
sign_option.version_specified = 1;
sign_option.version = strtoul(optarg, &e, 0);
@@ -718,6 +839,9 @@
case 'l':
sign_option.loemid = optarg;
break;
+ case 'K':
+ sign_option.keysetdir = optarg;
+ break;
case OPT_FV:
sign_option.fv_specified = 1;
VBOOT_FALLTHROUGH;
@@ -909,6 +1033,10 @@
sign_option.type = FILE_TYPE_RAW_FIRMWARE;
}
+ /* Load keys and keyblocks from keyset path, if they were not provided
+ earlier. */
+ errorcnt += load_keyset();
+
VB2_DEBUG("type=%s\n", futil_file_type_name(sign_option.type));
/* Check the arguments for the type of thing we want to sign */
@@ -938,7 +1066,6 @@
* may want to read it instead. */
break;
case FILE_TYPE_BIOS_IMAGE:
- case FILE_TYPE_OLD_BIOS_IMAGE:
errorcnt += no_opt_if(!sign_option.signprivate, "signprivate");
errorcnt += no_opt_if(!sign_option.keyblock, "keyblock");
errorcnt += no_opt_if(!sign_option.kernel_subkey, "kernelkey");
@@ -1010,56 +1137,18 @@
if (errorcnt)
goto done;
- if (sign_option.create_new_outfile) {
- /* The input is read-only, the output is write-only. */
- mapping = MAP_RO;
- VB2_DEBUG("open RO %s\n", infile);
- ifd = open(infile, O_RDONLY);
- if (ifd < 0) {
- errorcnt++;
- fprintf(stderr, "Can't open %s for reading: %s\n",
- infile, strerror(errno));
- goto done;
- }
- } else {
+ if (!sign_option.create_new_outfile) {
/* We'll read-modify-write the output file */
- mapping = MAP_RW;
if (sign_option.inout_file_count > 1)
futil_copy_file_or_die(infile, sign_option.outfile);
- VB2_DEBUG("open RW %s\n", sign_option.outfile);
infile = sign_option.outfile;
- ifd = open(sign_option.outfile, O_RDWR);
- if (ifd < 0) {
- errorcnt++;
- fprintf(stderr, "Can't open %s for writing: %s\n",
- sign_option.outfile, strerror(errno));
- goto done;
- }
}
- if (0 != futil_map_file(ifd, mapping, &buf, &buf_len)) {
- errorcnt++;
- goto done;
- }
-
- errorcnt += futil_file_type_sign(sign_option.type, infile,
- buf, buf_len);
-
- errorcnt += futil_unmap_file(ifd, mapping, buf, buf_len);
-
+ errorcnt += futil_file_type_sign(sign_option.type, infile);
done:
- if (ifd >= 0 && close(ifd)) {
- errorcnt++;
- fprintf(stderr, "Error when closing ifd: %s\n",
- strerror(errno));
- }
-
- if (sign_option.signprivate)
- free(sign_option.signprivate);
- if (sign_option.keyblock)
- free(sign_option.keyblock);
- if (sign_option.kernel_subkey)
- free(sign_option.kernel_subkey);
+ free(sign_option.signprivate);
+ free(sign_option.keyblock);
+ free(sign_option.kernel_subkey);
if (sign_option.prikey)
vb2_private_key_free(sign_option.prikey);
diff --git a/futility/cmd_update.c b/futility/cmd_update.c
index e4b3765..a77b224 100644
--- a/futility/cmd_update.c
+++ b/futility/cmd_update.c
@@ -57,7 +57,6 @@
{"ccd", 0, NULL, OPT_CCD},
{"servo", 0, NULL, OPT_SERVO},
- {"servo_noreset", 0, NULL, OPT_SERVO_NORESET},
{"servo_port", 1, NULL, OPT_SERVO_PORT},
{"emulate", 1, NULL, OPT_EMULATE},
{"factory", 0, NULL, OPT_FACTORY},
@@ -112,14 +111,17 @@
" --pd_image=FILE \tPD firmware image (i.e, pd.bin)\n"
"-t, --try \tTry A/B update on reboot if possible\n"
"-a, --archive=PATH \tRead resources from archive\n"
- " --manifest \tPrint out a JSON manifest and exit\n"
- " --repack=DIR \tUpdates archive from DIR\n"
" --unpack=DIR \tExtracts archive to DIR\n"
"-p, --programmer=PRG\tChange AP (host) flashrom programmer\n"
" --fast \tReduce read cycles and do not verify\n"
" --quirks=LIST \tSpecify the quirks to apply\n"
" --list-quirks \tPrint all available quirks\n"
- "-m, --mode=MODE \tRun updater in specified mode\n"
+ "-m, --mode=MODE \tRun updater in the specified mode\n"
+ " --manifest \tScan the archive to print a manifest in JSON\n"
+ "\n"
+ " * If both --manifest and --fast are specified, the updater\n"
+ " will not scan the archive and simply dump the previously\n"
+ " cached manifest (may be out-dated) from the archive.\n"
"\n"
"Legacy and compatibility options:\n"
" --factory \tAlias for --mode=factory\n"
@@ -134,7 +136,6 @@
" --gbb_flags=FLAG\tOverride new GBB flags\n"
" --ccd \tDo fast,force,wp=0,p=raiden_debug_spi\n"
" --servo \tFlash using Servo (v2, v4, micro, ...)\n"
- " --servo_noreset \tLike servo but with 'custom_rst=true'\n"
" --servo_port=PRT\tOverride servod port, implies --servo\n"
" --signature_id=S\tOverride signature ID for key files\n"
" --sys_props=LIST\tList of system properties to override\n"
@@ -144,21 +145,15 @@
argv[0]);
}
-static char *add_servo_noreset(char *programmer)
+static void prepare_servo_control(const char *control_name, int on)
{
- char *ret;
+ char *cmd;
+ if (!control_name)
+ return;
- if (strstr(programmer, "raiden_debug_spi:target=AP") == NULL) {
- ERROR("servo_noreset only works for AP flashing over CCD.\n");
- free(programmer);
-
- return NULL;
- }
-
- ASPRINTF(&ret, "%s,custom_rst=true", programmer);
- free(programmer);
-
- return ret;
+ ASPRINTF(&cmd, "dut-control %s:%s", control_name, on ? "on" : "off");
+ free(host_shell(cmd));
+ free(cmd);
}
static int do_update(int argc, char *argv[])
@@ -166,7 +161,8 @@
struct updater_config *cfg;
struct updater_config_arguments args = {0};
int i, errorcnt = 0, do_update = 1;
- int detect_servo = 0, do_servo_cpu_fw_spi = 0, servo_noreset = 0;
+ int detect_servo = 0;
+ const char *prepare_ctrl_name = NULL;
char *servo_programmer = NULL;
char *endptr;
@@ -211,6 +207,8 @@
break;
case OPT_REPACK:
args.repack = optarg;
+ ERROR("Sorry, --repack is only for the script.\n");
+ errorcnt ++;
break;
case OPT_UNPACK:
args.unpack = optarg;
@@ -277,14 +275,6 @@
args.host_only = 1;
detect_servo = 1;
break;
- case OPT_SERVO_NORESET:
- args.fast_update = 1;
- args.force_update = 1;
- args.write_protection = "0";
- args.host_only = 1;
- detect_servo = 1;
- servo_noreset = 1;
- break;
case OPT_SERVO_PORT:
setenv(ENV_SERVOD_PORT, optarg, 1);
args.fast_update = 1;
@@ -318,10 +308,7 @@
}
if (!errorcnt && detect_servo) {
- servo_programmer = host_detect_servo(&do_servo_cpu_fw_spi);
-
- if (servo_programmer && servo_noreset)
- servo_programmer = add_servo_noreset(servo_programmer);
+ servo_programmer = host_detect_servo(&prepare_ctrl_name);
if (!servo_programmer)
errorcnt++;
@@ -333,8 +320,7 @@
* update (i.e., in updater_setup_config) so we want to turn on
* cpu_fw_spi mode now.
*/
- if (do_servo_cpu_fw_spi)
- free(host_shell("dut-control cpu_fw_spi:on"));
+ prepare_servo_control(prepare_ctrl_name, 1);
if (!errorcnt)
errorcnt += updater_setup_config(cfg, &args, &do_update);
@@ -353,8 +339,7 @@
errorcnt ? "aborted" : "exits successfully");
}
- if (do_servo_cpu_fw_spi)
- free(host_shell("dut-control cpu_fw_spi:off"));
+ prepare_servo_control(prepare_ctrl_name, 0);
free(servo_programmer);
updater_delete_config(cfg);
diff --git a/futility/cmd_validate_rec_mrc.c b/futility/cmd_validate_rec_mrc.c
index 1d35bed..7ba5931 100644
--- a/futility/cmd_validate_rec_mrc.c
+++ b/futility/cmd_validate_rec_mrc.c
@@ -222,31 +222,21 @@
infile = argv[optind++];
- fd = open(infile, O_RDONLY);
- if (fd < 0) {
- fprintf(stderr, "Cannot open %s:%s\n", infile, strerror(errno));
+ if (futil_open_and_map_file(infile, &fd, FILE_RO, &buff, &file_size) !=
+ FILE_ERR_NONE)
return 1;
- }
-
- if (futil_map_file(fd, MAP_RO, &buff, &file_size) != FILE_ERR_NONE) {
- fprintf(stderr, "Cannot map file %s\n", infile);
- close(fd);
- return 1;
- }
if (offset > file_size) {
fprintf(stderr, "File size(%#x) smaller than offset(%#x)\n",
file_size, offset);
- futil_unmap_file(fd, MAP_RO, buff, file_size);
- close(fd);
+ futil_unmap_and_close_file(fd, FILE_RO, buff, file_size);
return 1;
}
if (get_mrc_data_slot((uint16_t *)(buff + offset), &data_offset,
&data_size)) {
fprintf(stderr, "Metadata block error\n");
- futil_unmap_file(fd, MAP_RO, buff, file_size);
- close(fd);
+ futil_unmap_and_close_file(fd, FILE_RO, buff, file_size);
return 1;
}
offset += data_offset;
@@ -259,12 +249,10 @@
"offset=%#x, file size=%#x, data_size=%#x\n",
offset, file_size, data_size);
- if (futil_unmap_file(fd, MAP_RO, buff, file_size) != FILE_ERR_NONE) {
- fprintf(stderr, "Failed to unmap file %s\n", infile);
- ret = 1;
- }
+ if (futil_unmap_and_close_file(fd, FILE_RO, buff, file_size) !=
+ FILE_ERR_NONE)
+ return 1;
- close(fd);
return ret;
}
diff --git a/futility/file_type.c b/futility/file_type.c
index b55d13f..29c4667 100644
--- a/futility/file_type.c
+++ b/futility/file_type.c
@@ -24,8 +24,8 @@
const char *desc;
/* Functions to identify, display, and sign this type of file. */
enum futil_file_type (*recognize)(uint8_t *buf, uint32_t len);
- int (*show)(const char *name, uint8_t *buf, uint32_t len, void *data);
- int (*sign)(const char *name, uint8_t *buf, uint32_t len, void *data);
+ int (*show)(const char *name, void *data);
+ int (*sign)(const char *name, void *data);
};
/* Populate a list of file types and operator functions. */
@@ -99,42 +99,29 @@
enum futil_file_err futil_file_type(const char *filename,
enum futil_file_type *type)
{
- int ifd;
- uint8_t *buf;
- uint32_t buf_len;
+ int ifd = -1;
+ uint8_t *buf = NULL;
+ uint32_t buf_len = 0;
struct stat sb;
enum futil_file_err err = FILE_ERR_NONE;
*type = FILE_TYPE_UNKNOWN;
- ifd = open(filename, O_RDONLY);
- if (ifd < 0) {
- fprintf(stderr, "Can't open %s: %s\n",
- filename, strerror(errno));
- return FILE_ERR_OPEN;
- }
+ err = futil_open_file(filename, &ifd, FILE_RO);
+ if (err != FILE_ERR_NONE)
+ goto done;
if (0 != fstat(ifd, &sb)) {
- fprintf(stderr, "Can't stat input file: %s\n",
- strerror(errno));
- close(ifd);
- return FILE_ERR_STAT;
+ fprintf(stderr, "Can't stat input file: %s\n", strerror(errno));
+ err = FILE_ERR_STAT;
+ goto done;
}
if (S_ISREG(sb.st_mode) || S_ISBLK(sb.st_mode)) {
- err = futil_map_file(ifd, MAP_RO, &buf, &buf_len);
- if (err) {
- close(ifd);
- return err;
- }
-
+ err = futil_map_file(ifd, FILE_RO, &buf, &buf_len);
+ if (err)
+ goto done;
*type = futil_file_type_buf(buf, buf_len);
-
- err = futil_unmap_file(ifd, MAP_RO, buf, buf_len);
- if (err) {
- close(ifd);
- return err;
- }
} else if (S_ISDIR(sb.st_mode)) {
err = FILE_ERR_DIR;
} else if (S_ISCHR(sb.st_mode)) {
@@ -144,37 +131,27 @@
} else if (S_ISSOCK(sb.st_mode)) {
err = FILE_ERR_SOCK;
}
-
- if (close(ifd)) {
- fprintf(stderr, "Error when closing %s: %s\n",
- filename, strerror(errno));
- return FILE_ERR_CLOSE;
- }
-
+done:
+ futil_unmap_and_close_file(ifd, FILE_RO, buf, buf_len);
return err;
}
-int futil_file_type_show(enum futil_file_type type,
- const char *filename,
- uint8_t *buf, uint32_t len)
+int futil_file_type_show(enum futil_file_type type, const char *filename)
{
if (futil_file_types[type].show)
- return futil_file_types[type].show(filename, buf, len, 0);
+ return futil_file_types[type].show(filename, 0);
fprintf(stderr, "Don't know how to show %s (type %s)\n",
filename, futil_file_type_name(type));
return 1;
}
-int futil_file_type_sign(enum futil_file_type type,
- const char *filename,
- uint8_t *buf, uint32_t len)
+int futil_file_type_sign(enum futil_file_type type, const char *filename)
{
if (futil_file_types[type].sign)
- return futil_file_types[type].sign(filename, buf, len, 0);
+ return futil_file_types[type].sign(filename, 0);
fprintf(stderr, "Don't know how to sign %s (type %s)\n",
filename, futil_file_type_name(type));
return 1;
}
-
diff --git a/futility/file_type.h b/futility/file_type.h
index e1efe76..5a074b3 100644
--- a/futility/file_type.h
+++ b/futility/file_type.h
@@ -40,22 +40,18 @@
enum futil_file_type *type);
/*
- * Call the show() method on a buffer containing a specific file type.
+ * Call the show() method on a file containing a specific file type.
* Returns zero on success. It's up to the caller to ensure that only valid
* file types are invoked.
*/
-int futil_file_type_show(enum futil_file_type type,
- const char *filename,
- uint8_t *buf, uint32_t len);
+int futil_file_type_show(enum futil_file_type type, const char *filename);
/*
- * Call the sign() method on a buffer containing a specific file type.
+ * Call the sign() method on a file with specific file type.
* Returns zero on success. It's up to the caller to ensure that only valid
* file types are invoked.
*/
-int futil_file_type_sign(enum futil_file_type type,
- const char *filename,
- uint8_t *buf, uint32_t len);
+int futil_file_type_sign(enum futil_file_type type, const char *filename);
/*
* Declare the file_type functions. Certain functions are reused for more than
@@ -66,14 +62,21 @@
#define R_(FOO) \
enum futil_file_type FOO(uint8_t *buf, uint32_t len);
#define S_(FOO) \
- int FOO(const char *name, uint8_t *buf, uint32_t len, void *data);
+ int FOO(const char *name, void *data);
#define NONE
#define FILE_TYPE(A, B, C, D, E, F) D E F
#include "file_type.inc"
#undef FILE_TYPE
#undef NONE
+#undef SG_
#undef S_
#undef R_
#pragma GCC diagnostic pop
+/* Declared for use inside other show functions. */
+int show_fw_preamble_buf(const char *name, uint8_t *buf, uint32_t len,
+ void *data);
+int show_vb21_pubkey_buf(const char *name, uint8_t *buf, uint32_t len,
+ void *data);
+
#endif /* VBOOT_REFERENCE_FILE_TYPE_H_ */
diff --git a/futility/file_type.inc b/futility/file_type.inc
index 0d3acc9..7a32f9b 100644
--- a/futility/file_type.inc
+++ b/futility/file_type.inc
@@ -19,10 +19,6 @@
R_(ft_recognize_bios_image),
S_(ft_show_bios),
S_(ft_sign_bios))
-FILE_TYPE(OLD_BIOS_IMAGE, "oldbios", "Cr-48 Chrome OS BIOS image",
- R_(ft_recognize_bios_image),
- S_(ft_show_bios),
- S_(ft_sign_bios))
FILE_TYPE(GBB, "gbb", "GBB",
R_(ft_recognize_gbb),
S_(ft_show_gbb),
diff --git a/futility/file_type_bios.c b/futility/file_type_bios.c
index fe0b223..29ecfd4 100644
--- a/futility/file_type_bios.c
+++ b/futility/file_type_bios.c
@@ -5,10 +5,12 @@
#include <errno.h>
#include <limits.h>
+#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
+#include "cbfstool.h"
#include "file_type_bios.h"
#include "file_type.h"
#include "fmap.h"
@@ -27,21 +29,11 @@
_Static_assert(ARRAY_SIZE(fmap_name) == NUM_BIOS_COMPONENTS,
"Size of fmap_name[] should match NUM_BIOS_COMPONENTS");
-static const char * const fmap_oldname[] = {
- "GBB Area", /* BIOS_FMAP_GBB */
- "Firmware A Data", /* BIOS_FMAP_FW_MAIN_A */
- "Firmware B Data", /* BIOS_FMAP_FW_MAIN_B */
- "Firmware A Key", /* BIOS_FMAP_VBLOCK_A */
- "Firmware B Key", /* BIOS_FMAP_VBLOCK_B */
-};
-_Static_assert(ARRAY_SIZE(fmap_oldname) == NUM_BIOS_COMPONENTS,
- "Size of fmap_oldname[] should match NUM_BIOS_COMPONENTS");
-
static void fmap_limit_area(FmapAreaHeader *ah, uint32_t len)
{
uint32_t sum = ah->area_offset + ah->area_size;
if (sum < ah->area_size || sum > len) {
- VB2_DEBUG("%s %#x + %#x > %#x\n",
+ VB2_DEBUG("%.*s %#x + %#x > %#x\n", FMAP_NAMELEN,
ah->area_name, ah->area_offset, ah->area_size, len);
ah->area_offset = 0;
ah->area_size = 0;
@@ -50,7 +42,8 @@
/** Show functions **/
-int ft_show_gbb(const char *name, uint8_t *buf, uint32_t len, void *data)
+static int show_gbb_buf(const char *name, uint8_t *buf, uint32_t len,
+ void *data)
{
struct vb2_gbb_header *gbb = (struct vb2_gbb_header *)buf;
struct bios_state_s *state = (struct bios_state_s *)data;
@@ -85,7 +78,7 @@
if (retval) {
printf("GBB header is invalid, ignoring content\n");
- return 1;
+ return retval;
}
printf("GBB content:\n");
@@ -135,6 +128,23 @@
return retval;
}
+int ft_show_gbb(const char *name, void *data)
+{
+ int retval = 0;
+ int fd = -1;
+ uint8_t *buf;
+ uint32_t len;
+
+ retval = futil_open_and_map_file(name, &fd, FILE_RO, &buf, &len);
+ if (retval)
+ return 1;
+
+ retval = show_gbb_buf(name, buf, len, data);
+
+ futil_unmap_and_close_file(fd, FILE_RO, buf, len);
+ return retval;
+}
+
/*
* This handles FW_MAIN_A and FW_MAIN_B while processing a BIOS image.
*
@@ -165,16 +175,16 @@
/* Functions to call to show the bios components */
static int (*fmap_show_fn[])(const char *name, uint8_t *buf, uint32_t len,
void *data) = {
- ft_show_gbb,
+ show_gbb_buf,
fmap_show_fw_main,
fmap_show_fw_main,
- ft_show_fw_preamble,
- ft_show_fw_preamble,
+ show_fw_preamble_buf,
+ show_fw_preamble_buf,
};
_Static_assert(ARRAY_SIZE(fmap_show_fn) == NUM_BIOS_COMPONENTS,
"Size of fmap_show_fn[] should match NUM_BIOS_COMPONENTS");
-int ft_show_bios(const char *name, uint8_t *buf, uint32_t len, void *data)
+int ft_show_bios(const char *name, void *data)
{
FmapHeader *fmap;
FmapAreaHeader *ah = 0;
@@ -182,6 +192,13 @@
enum bios_component c;
int retval = 0;
struct bios_state_s state;
+ int fd = -1;
+ uint8_t *buf;
+ uint32_t len;
+
+ retval = futil_open_and_map_file(name, &fd, FILE_RO, &buf, &len);
+ if (retval)
+ return 1;
memset(&state, 0, sizeof(state));
@@ -191,8 +208,7 @@
fmap = fmap_find(buf, len);
for (c = 0; c < NUM_BIOS_COMPONENTS; c++) {
/* We know one of these will work, too */
- if (fmap_find_by_name(buf, len, fmap, fmap_name[c], &ah) ||
- fmap_find_by_name(buf, len, fmap, fmap_oldname[c], &ah)) {
+ if (fmap_find_by_name(buf, len, fmap, fmap_name[c], &ah)) {
/* But the file might be truncated */
fmap_limit_area(ah, len);
/* The name is not necessarily null-terminated */
@@ -217,119 +233,41 @@
}
}
+ futil_unmap_and_close_file(fd, FILE_RO, buf, len);
return retval;
}
/** Sign functions **/
-/*
- * This handles FW_MAIN_A and FW_MAIN_B while signing a BIOS image. The data is
- * just the RW firmware blob so there's nothing useful to do with it, but we'll
- * mark it as valid so that we'll know that this FMAP area exists and can
- * be signed.
- */
-static int fmap_sign_fw_main(const char *name, uint8_t *buf, uint32_t len,
- void *data)
-{
- struct bios_state_s *state = (struct bios_state_s *)data;
- state->area[state->c].is_valid = 1;
- return 0;
-}
-
-/*
- * This handles VBLOCK_A and VBLOCK_B while processing a BIOS image. We don't
- * do any signing here. We just check to see if the existing FMAP area contains
- * a firmware preamble so we can preserve its contents. We do the signing once
- * we've looked over all the components.
- */
-static int fmap_sign_fw_preamble(const char *name, uint8_t *buf, uint32_t len,
- void *data)
-{
- static uint8_t workbuf[VB2_FIRMWARE_WORKBUF_RECOMMENDED_SIZE]
- __attribute__((aligned(VB2_WORKBUF_ALIGN)));
- static struct vb2_workbuf wb;
- vb2_workbuf_init(&wb, workbuf, sizeof(workbuf));
-
- struct vb2_keyblock *keyblock = (struct vb2_keyblock *)buf;
- struct bios_state_s *state = (struct bios_state_s *)data;
-
- /*
- * If we have a valid keyblock and fw_preamble, then we can use them to
- * determine the size of the firmware body. Otherwise, we'll have to
- * just sign the whole region.
- */
- if (VB2_SUCCESS != vb2_verify_keyblock_hash(keyblock, len, &wb)) {
- fprintf(stderr, "Warning: %s keyblock is invalid. "
- "Signing the entire FW FMAP region...\n", name);
- goto whatever;
- }
-
- if (vb2_packed_key_looks_ok(&keyblock->data_key,
- keyblock->data_key.key_offset +
- keyblock->data_key.key_size)) {
- fprintf(stderr, "Warning: %s public key is invalid. "
- "Signing the entire FW FMAP region...\n", name);
- goto whatever;
- }
- uint32_t more = keyblock->keyblock_size;
- struct vb2_fw_preamble *preamble =
- (struct vb2_fw_preamble *)(buf + more);
- uint32_t fw_size = preamble->body_signature.data_size;
- struct bios_area_s *fw_body_area = 0;
-
- switch (state->c) {
- case BIOS_FMAP_VBLOCK_A:
- fw_body_area = &state->area[BIOS_FMAP_FW_MAIN_A];
- /* Preserve the flags if they're not specified */
- if (!sign_option.flags_specified)
- sign_option.flags = preamble->flags;
- break;
- case BIOS_FMAP_VBLOCK_B:
- fw_body_area = &state->area[BIOS_FMAP_FW_MAIN_B];
- break;
- default:
- FATAL("Can only handle VBLOCK_A or VBLOCK_B\n");
- }
-
- if (fw_size > fw_body_area->len) {
- fprintf(stderr,
- "%s says the firmware is larger than we have\n",
- name);
- return 1;
- }
-
- /* Update the firmware size */
- fw_body_area->len = fw_size;
-
-whatever:
- state->area[state->c].is_valid = 1;
-
- return 0;
-}
-
static int write_new_preamble(struct bios_area_s *vblock,
struct bios_area_s *fw_body,
struct vb2_private_key *signkey,
struct vb2_keyblock *keyblock)
{
- struct vb2_signature *body_sig;
- struct vb2_fw_preamble *preamble;
+ struct vb2_signature *body_sig = NULL;
+ struct vb2_fw_preamble *preamble = NULL;
+ int retval = 1;
body_sig = vb2_calculate_signature(fw_body->buf, fw_body->len, signkey);
if (!body_sig) {
- fprintf(stderr, "Error calculating body signature\n");
- return 1;
+ ERROR("Error calculating body signature\n");
+ goto end;
}
- preamble = vb2_create_fw_preamble(sign_option.version,
+ preamble = vb2_create_fw_preamble(vblock->version,
(struct vb2_packed_key *)sign_option.kernel_subkey,
body_sig,
signkey,
- sign_option.flags);
+ vblock->flags);
if (!preamble) {
- fprintf(stderr, "Error creating firmware preamble.\n");
+ ERROR("Error creating firmware preamble.\n");
free(body_sig);
- return 1;
+ goto end;
+ }
+
+ if (keyblock->keyblock_size + preamble->preamble_size > vblock->len) {
+ ERROR("Keyblock and preamble do not fit in VBLOCK.\n");
+ goto end;
}
/* Write the new keyblock */
@@ -337,11 +275,13 @@
memcpy(vblock->buf, keyblock, more);
/* and the new preamble */
memcpy(vblock->buf + more, preamble, preamble->preamble_size);
+ retval = 0;
+end:
free(preamble);
free(body_sig);
- return 0;
+ return retval;
}
static int write_loem(const char *ab, struct bios_area_s *vblock)
@@ -387,123 +327,230 @@
struct bios_area_s *fw_b = &state->area[BIOS_FMAP_FW_MAIN_B];
int retval = 0;
- if (!vblock_a->is_valid || !vblock_b->is_valid ||
- !fw_a->is_valid || !fw_b->is_valid) {
+ if (!vblock_a->is_valid || !fw_a->is_valid) {
fprintf(stderr, "Something's wrong. Not changing anything\n");
return 1;
}
- /* Do A & B differ ? */
- if (fw_a->len != fw_b->len ||
- memcmp(fw_a->buf, fw_b->buf, fw_a->len)) {
- /* Yes, must use DEV keys for A */
- if (!sign_option.devsignprivate || !sign_option.devkeyblock) {
- fprintf(stderr,
- "FW A & B differ. DEV keys are required.\n");
- return 1;
- }
- retval |= write_new_preamble(vblock_a, fw_a,
- sign_option.devsignprivate,
- sign_option.devkeyblock);
- } else {
- retval |= write_new_preamble(vblock_a, fw_a,
- sign_option.signprivate,
- sign_option.keyblock);
- }
-
- /* FW B is always normal keys */
- retval |= write_new_preamble(vblock_b, fw_b,
- sign_option.signprivate,
+ retval |= write_new_preamble(vblock_a, fw_a, sign_option.signprivate,
sign_option.keyblock);
-
-
+ if (vblock_b->is_valid && fw_b->is_valid)
+ retval |= write_new_preamble(vblock_b, fw_b,
+ sign_option.signprivate,
+ sign_option.keyblock);
+ else
+ INFO("BIOS image does not have %s. Signing only %s\n",
+ fmap_name[BIOS_FMAP_FW_MAIN_B],
+ fmap_name[BIOS_FMAP_FW_MAIN_A]);
if (sign_option.loemid) {
retval |= write_loem("A", vblock_a);
- retval |= write_loem("B", vblock_b);
+ if (vblock_b->is_valid)
+ retval |= write_loem("B", vblock_b);
}
return retval;
}
-/* Functions to call while preparing to sign the bios */
-static int (*fmap_sign_fn[])(const char *name, uint8_t *buf, uint32_t len,
- void *data) = {
- 0,
- fmap_sign_fw_main,
- fmap_sign_fw_main,
- fmap_sign_fw_preamble,
- fmap_sign_fw_preamble,
-};
-_Static_assert(ARRAY_SIZE(fmap_sign_fn) == NUM_BIOS_COMPONENTS,
- "Size of fmap_sign_fn[] should match NUM_BIOS_COMPONENTS");
-
-int ft_sign_bios(const char *name, uint8_t *buf, uint32_t len, void *data)
+/* Prepare firmware slot for signing.
+ If fw_size is not zero, then it will be used as new length of signed area,
+ for zero the length will be taken form FlashMap or preamble. */
+static int prepare_slot(uint8_t *buf, uint32_t len, size_t fw_size,
+ enum bios_component fw_c, enum bios_component vblock_c,
+ struct bios_state_s *state)
{
FmapHeader *fmap;
- FmapAreaHeader *ah = 0;
- char ah_name[FMAP_NAMELEN + 1];
- enum bios_component c;
- int retval = 0;
- struct bios_state_s state;
+ FmapAreaHeader *ah;
+ const char *fw_main_name = fmap_name[fw_c];
+ const char *vblock_name = fmap_name[vblock_c];
+ static uint8_t workbuf[VB2_FIRMWARE_WORKBUF_RECOMMENDED_SIZE]
+ __attribute__((aligned(VB2_WORKBUF_ALIGN)));
+ static struct vb2_workbuf wb;
- memset(&state, 0, sizeof(state));
-
- /* We've already checked, so we know this will work. */
fmap = fmap_find(buf, len);
- for (c = 0; c < NUM_BIOS_COMPONENTS; c++) {
- /* We know one of these will work, too */
- if (fmap_find_by_name(buf, len, fmap, fmap_name[c], &ah) ||
- fmap_find_by_name(buf, len, fmap, fmap_oldname[c], &ah)) {
- /* But the file might be truncated */
- fmap_limit_area(ah, len);
- /* The name is not necessarily null-terminated */
- snprintf(ah_name, sizeof(ah_name), "%s", ah->area_name);
+ vb2_workbuf_init(&wb, workbuf, sizeof(workbuf));
- /* Update the state we're passing around */
- state.c = c;
- state.area[c].buf = buf + ah->area_offset;
- state.area[c].len = ah->area_size;
+ VB2_DEBUG("Preparing areas: %s and %s\n", fw_main_name, vblock_name);
- VB2_DEBUG("examining FMAP area %d (%s),"
- " offset=0x%08x len=0x%08x\n",
- c, ah_name, ah->area_offset, ah->area_size);
+ /* FW_MAIN */
+ if (!fmap_find_by_name(buf, len, fmap, fw_main_name, &ah)) {
+ ERROR("%s area not found in FMAP\n", fw_main_name);
+ return 1;
+ }
+ fmap_limit_area(ah, len);
+ state->area[fw_c].buf = buf + ah->area_offset;
+ state->area[fw_c].is_valid = 1;
+ if (fw_size > ah->area_size) {
+ ERROR("%s size is incorrect.\n", fmap_name[fw_c]);
+ return 1;
+ } else if (fw_size) {
+ state->area[fw_c].len = fw_size;
+ } else {
+ WARN("%s does not contain CBFS. Trying to sign entire area.\n",
+ fmap_name[fw_c]);
+ state->area[fw_c].len = ah->area_size;
+ }
- /* Go look at it, but abort on error */
- if (fmap_sign_fn[c])
- retval += fmap_sign_fn[c](ah_name,
- state.area[c].buf,
- state.area[c].len,
- &state);
+ /* Corresponding VBLOCK */
+ if (!fmap_find_by_name(buf, len, fmap, vblock_name, &ah)) {
+ ERROR("%s area not found in FMAP\n", vblock_name);
+ return 1;
+ }
+ fmap_limit_area(ah, len);
+ state->area[vblock_c].buf = buf + ah->area_offset;
+ state->area[vblock_c].len = ah->area_size;
+
+ struct vb2_keyblock *keyblock =
+ (struct vb2_keyblock *)state->area[vblock_c].buf;
+ int keyblock_valid = 0;
+
+ if (vb2_verify_keyblock_hash(keyblock, state->area[vblock_c].len,
+ &wb) != VB2_SUCCESS) {
+ WARN("%s keyblock is invalid.\n", vblock_name);
+ goto end;
+ }
+
+ if (vb2_packed_key_looks_ok(&keyblock->data_key,
+ keyblock->data_key.key_offset +
+ keyblock->data_key.key_size)) {
+ WARN("%s public key is invalid.\n", vblock_name);
+ goto end;
+ }
+
+ struct vb2_public_key data_key;
+ if (vb2_unpack_key(&data_key, &keyblock->data_key) != VB2_SUCCESS) {
+ WARN("%s data key is invalid. Failed to parse.\n", vblock_name);
+ goto end;
+ }
+
+ if (keyblock->keyblock_size + sizeof(struct vb2_fw_preamble) >
+ state->area[vblock_c].len) {
+ ERROR("%s is invalid. Keyblock and preamble do not fit.\n",
+ vblock_name);
+ goto end;
+ }
+
+ struct vb2_fw_preamble *preamble =
+ (struct vb2_fw_preamble *)(state->area[vblock_c].buf +
+ keyblock->keyblock_size);
+ if (vb2_verify_fw_preamble(preamble,
+ state->area[vblock_c].len -
+ keyblock->keyblock_size,
+ &data_key, &wb)) {
+ WARN("%s preamble is invalid.\n", vblock_name);
+ goto end;
+ }
+
+ if (fw_size == 0) {
+ if (preamble->body_signature.data_size >
+ state->area[fw_c].len) {
+ ERROR("%s says the firmware is larger than we have.\n",
+ vblock_name);
+ goto end;
+ } else {
+ state->area[fw_c].len =
+ preamble->body_signature.data_size;
}
}
- retval += sign_bios_at_end(&state);
+ keyblock_valid = 1;
+end:
+ if (sign_option.flags_specified)
+ state->area[vblock_c].flags = sign_option.flags;
+ else if (keyblock_valid)
+ state->area[vblock_c].flags = preamble->flags;
+ else
+ state->area[vblock_c].flags = 0;
+
+ if (sign_option.version_specified)
+ state->area[vblock_c].version = sign_option.version;
+ else if (keyblock_valid)
+ state->area[vblock_c].version = preamble->firmware_version;
+ else
+ state->area[vblock_c].version = 1;
+
+ state->area[vblock_c].is_valid = 1;
+
+ return 0;
+}
+
+int ft_sign_bios(const char *name, void *data)
+{
+ int retval = 0;
+ struct bios_state_s state;
+ int fd = -1;
+ uint8_t *buf = NULL;
+ uint32_t len = 0;
+ size_t fw_main_a_size = 0;
+ size_t fw_main_b_size = 0;
+
+ bool fw_main_a_in_cbfs_mode =
+ cbfstool_truncate(name, fmap_name[BIOS_FMAP_FW_MAIN_A],
+ &fw_main_a_size) == VB2_SUCCESS;
+
+ bool fw_main_b_in_cbfs_mode =
+ cbfstool_truncate(name, fmap_name[BIOS_FMAP_FW_MAIN_B],
+ &fw_main_b_size) == VB2_SUCCESS;
+
+ if (fw_main_a_in_cbfs_mode)
+ VB2_DEBUG("CBFS found in area %s\n",
+ fmap_name[BIOS_FMAP_FW_MAIN_A]);
+ else
+ VB2_DEBUG("CBFS not found in area %s\n",
+ fmap_name[BIOS_FMAP_FW_MAIN_A]);
+
+ if (fw_main_b_in_cbfs_mode)
+ VB2_DEBUG("CBFS found in area %s\n",
+ fmap_name[BIOS_FMAP_FW_MAIN_B]);
+ else
+ VB2_DEBUG("CBFS not found in area %s\n",
+ fmap_name[BIOS_FMAP_FW_MAIN_B]);
+
+ if (futil_open_and_map_file(name, &fd, FILE_MODE_SIGN(sign_option),
+ &buf, &len))
+ return 1;
+
+ memset(&state, 0, sizeof(state));
+
+ retval = prepare_slot(buf, len, fw_main_a_size, BIOS_FMAP_FW_MAIN_A,
+ BIOS_FMAP_VBLOCK_A, &state);
+ if (retval)
+ goto done;
+
+ retval = prepare_slot(buf, len, fw_main_b_size, BIOS_FMAP_FW_MAIN_B,
+ BIOS_FMAP_VBLOCK_B, &state);
+ if (retval && state.area[BIOS_FMAP_FW_MAIN_B].is_valid)
+ goto done;
+
+ retval = sign_bios_at_end(&state);
+done:
+ futil_unmap_and_close_file(fd, FILE_MODE_SIGN(sign_option), buf, len);
return retval;
}
enum futil_file_type ft_recognize_bios_image(uint8_t *buf, uint32_t len)
{
FmapHeader *fmap;
- enum bios_component c;
fmap = fmap_find(buf, len);
if (!fmap)
return FILE_TYPE_UNKNOWN;
- for (c = 0; c < NUM_BIOS_COMPONENTS; c++)
- if (!fmap_find_by_name(buf, len, fmap, fmap_name[c], 0))
- break;
- if (c == NUM_BIOS_COMPONENTS)
- return FILE_TYPE_BIOS_IMAGE;
+ /* Correct BIOS image should contain at least GBB, FW_MAIN_A and
+ VBLOCK_A areas. FW_MAIN_B and VBLOCK_B are optional, but will be
+ signed or shown if present. */
+ const int gbb_and_a_slot_ok =
+ fmap_find_by_name(buf, len, fmap, fmap_name[BIOS_FMAP_GBB],
+ 0) != NULL &&
+ fmap_find_by_name(buf, len, fmap,
+ fmap_name[BIOS_FMAP_FW_MAIN_A], 0) != NULL &&
+ fmap_find_by_name(buf, len, fmap, fmap_name[BIOS_FMAP_VBLOCK_A],
+ 0) != NULL;
- for (c = 0; c < NUM_BIOS_COMPONENTS; c++)
- if (!fmap_find_by_name(buf, len, fmap, fmap_oldname[c], 0))
- break;
- if (c == NUM_BIOS_COMPONENTS)
- return FILE_TYPE_OLD_BIOS_IMAGE;
+ if (gbb_and_a_slot_ok)
+ return FILE_TYPE_BIOS_IMAGE;
return FILE_TYPE_UNKNOWN;
}
diff --git a/futility/file_type_bios.h b/futility/file_type_bios.h
index ef40107..8aa2d63 100644
--- a/futility/file_type_bios.h
+++ b/futility/file_type_bios.h
@@ -28,6 +28,10 @@
uint8_t *buf;
uint32_t len;
uint32_t is_valid;
+
+ /* VBLOCK only */
+ uint32_t flags;
+ uint32_t version;
};
/* State to track as we visit all components */
diff --git a/futility/file_type_rwsig.c b/futility/file_type_rwsig.c
index a09782c..b595e25 100644
--- a/futility/file_type_rwsig.c
+++ b/futility/file_type_rwsig.c
@@ -58,7 +58,7 @@
sig->data_size);
}
-int ft_show_rwsig(const char *name, uint8_t *buf, uint32_t len, void *nuthin)
+int ft_show_rwsig(const char *name, void *nuthin)
{
const struct vb21_signature *sig = 0;
const struct vb21_packed_key *pkey = show_option.pkey;
@@ -71,6 +71,15 @@
uint8_t *data;
FmapHeader *fmap;
int i;
+ int fd = -1;
+ uint8_t *buf;
+ uint32_t len;
+ int rv;
+
+ if (futil_open_and_map_file(name, &fd, FILE_RO, &buf, &len))
+ return 1;
+
+ rv = 1;
VB2_DEBUG("name %s len 0x%08x (%d)\n", name, len, len);
@@ -81,7 +90,8 @@
show_sig(name, sig);
if (!show_option.fv) {
printf("No data available to verify\n");
- return show_option.strict;
+ rv = show_option.strict;
+ goto done;
}
data = show_option.fv;
data_size = show_option.fv_size;
@@ -99,15 +109,15 @@
fmap_find_by_name(buf, len, fmap, "KEY_RO", 0);
if (pkey)
- ft_show_vb21_pubkey(name, (uint8_t *)pkey,
- pkey->c.total_size, NULL);
+ show_vb21_pubkey_buf(name, (uint8_t *)pkey,
+ pkey->c.total_size, NULL);
}
sig = (const struct vb21_signature *)
fmap_find_by_name(buf, len, fmap, "SIG_RW", &fmaparea);
if (!sig) {
VB2_DEBUG("No SIG_RW in FMAP.\n");
- return 1;
+ goto done;
}
sig_size = fmaparea->area_size;
@@ -116,7 +126,7 @@
(uint8_t*)sig - buf, sig_size);
if (VB2_SUCCESS != vb21_verify_signature(sig, sig_size))
- return 1;
+ goto done;
show_sig(name, sig);
data = fmap_find_by_name(buf, len, fmap, "EC_RW", &fmaparea);
@@ -129,7 +139,7 @@
if (!data) {
VB2_DEBUG("No EC_RW in FMAP.\n");
- return 1;
+ goto done;
}
} else {
/* Or maybe this is just the RW portion, that does not
@@ -141,7 +151,7 @@
if (len < sig_size) {
VB2_DEBUG("File is too small\n");
- return 1;
+ goto done;
}
sig = (const struct vb21_signature *)(buf + len - sig_size);
@@ -151,13 +161,14 @@
data_size = sig->data_size;
total_data_size = len - sig_size;
} else {
- return 1;
+ goto done;
}
}
if (!pkey) {
printf("No public key available to verify with\n");
- return show_option.strict;
+ rv = show_option.strict;
+ goto done;
}
/* We already did this once, so it should work again */
@@ -165,12 +176,12 @@
(const uint8_t *)pkey,
pkey->c.total_size)) {
VB2_DEBUG("Can't unpack pubkey\n");
- return 1;
+ goto done;
}
if (data_size > total_data_size) {
VB2_DEBUG("Invalid signature data_size: bigger than total area size.\n");
- return 1;
+ goto done;
}
/* The sig is destroyed by the verify operation, so make a copy */
@@ -185,7 +196,7 @@
(const struct vb2_public_key *)&key,
&wb)) {
fprintf(stderr, "Signature verification failed\n");
- return 1;
+ goto done;
}
}
@@ -193,33 +204,46 @@
for (i = data_size; i < total_data_size; i++) {
if (data[i] != 0xff) {
fprintf(stderr, "Padding verification failed\n");
- return 1;
+ goto done;
}
}
printf("Signature verification succeeded.\n");
- return 0;
+ rv = 0;
+done:
+ futil_unmap_and_close_file(fd, FILE_RO, buf, len);
+ return rv;
}
-int ft_sign_rwsig(const char *name, uint8_t *buf, uint32_t len, void *nuthin)
+int ft_sign_rwsig(const char *name, void *nuthin)
{
struct vb21_signature *tmp_sig = 0;
struct vb2_public_key *pubkey = 0;
struct vb21_packed_key *packedkey = 0;
uint8_t *keyb_data = 0;
uint32_t keyb_size;
- uint8_t* data = buf; /* data to be signed */
- uint32_t r, data_size = len, sig_size = SIGNATURE_RSVD_SIZE;
+ uint8_t *data; /* data to be signed */
+ uint32_t r, data_size, sig_size = SIGNATURE_RSVD_SIZE;
int retval = 1;
FmapHeader *fmap = NULL;
FmapAreaHeader *fmaparea;
struct vb21_signature *old_sig = 0;
+ uint8_t *buf = NULL;
+ uint32_t len;
+ int fd = -1;
+
+ if (futil_open_and_map_file(name, &fd, FILE_MODE_SIGN(sign_option),
+ &buf, &len))
+ return 1;
+
+ data = buf;
+ data_size = len;
VB2_DEBUG("name %s len 0x%08x (%d)\n", name, len, len);
/* If we don't have a distinct OUTFILE, look for an existing sig */
if (sign_option.inout_file_count < 2) {
- fmap = fmap_find(buf, len);
+ fmap = fmap_find(data, len);
if (fmap) {
/* This looks like a full image. */
@@ -395,14 +419,12 @@
/* Finally */
retval = 0;
done:
- if (tmp_sig)
- free(tmp_sig);
+ futil_unmap_and_close_file(fd, FILE_MODE_SIGN(sign_option), buf, len);
+ free(tmp_sig);
if (pubkey)
vb2_public_key_free(pubkey);
- if (packedkey)
- free(packedkey);
- if (keyb_data)
- free(keyb_data);
+ free(packedkey);
+ free(keyb_data);
return retval;
}
diff --git a/futility/file_type_usbpd1.c b/futility/file_type_usbpd1.c
index 9379188..a128a99 100644
--- a/futility/file_type_usbpd1.c
+++ b/futility/file_type_usbpd1.c
@@ -78,7 +78,7 @@
return 1;
}
-int ft_sign_usbpd1(const char *name, uint8_t *buf, uint32_t len, void *data)
+int ft_sign_usbpd1(const char *name, void *data)
{
struct vb2_private_key *key_ptr = 0;
struct vb21_signature *sig_ptr = 0;
@@ -94,6 +94,13 @@
uint32_t ro_offset;
uint32_t rw_offset;
uint32_t r;
+ uint8_t *buf = NULL;
+ uint32_t len;
+ int fd = -1;
+
+ if (futil_open_and_map_file(name, &fd, FILE_MODE_SIGN(sign_option),
+ &buf, &len))
+ return 1;
VB2_DEBUG("name %s len %#.8x (%d)\n", name, len, len);
@@ -237,6 +244,7 @@
/* Finally */
retval = 0;
done:
+ futil_unmap_and_close_file(fd, FILE_MODE_SIGN(sign_option), buf, len);
if (key_ptr)
vb2_private_key_free(key_ptr);
if (keyb_data)
@@ -425,35 +433,47 @@
}
-int ft_show_usbpd1(const char *name, uint8_t *buf, uint32_t len, void *data)
+int ft_show_usbpd1(const char *name, void *data)
{
uint32_t ro_size, rw_size, ro_offset, rw_offset;
int s, h;
+ int fd = -1;
+ uint8_t *buf;
+ uint32_t len;
+ int rv = 1;
+
+ if (futil_open_and_map_file(name, &fd, FILE_RO, &buf, &len))
+ return 1;
VB2_DEBUG("name %s len 0x%08x (%d)\n", name, len, len);
/* Get image locations */
if (!parse_size_opts(len, &ro_size, &rw_size, &ro_offset, &rw_offset))
- return 1;
+ goto done;
/* TODO: If we don't have a RO image, ask for a public key
* TODO: If we're given an external public key, use it (and its alg) */
if (!ro_size) {
printf("Can't find the public key\n");
- return 1;
+ goto done;
}
/* TODO: Only loop through the numbers we haven't been given */
- for (s = 0; s < ARRAY_SIZE(sigs); s++)
- for (h = 0; h < ARRAY_SIZE(hashes); h++)
- if (!check_self_consistency(buf, name,
- ro_size, rw_size,
+ for (s = 0; s < ARRAY_SIZE(sigs); s++) {
+ for (h = 0; h < ARRAY_SIZE(hashes); h++) {
+ if (!check_self_consistency(buf, name, ro_size, rw_size,
ro_offset, rw_offset,
- sigs[s], hashes[h]))
- return 0;
+ sigs[s], hashes[h])) {
+ rv = 0;
+ goto done;
+ }
+ }
+ }
printf("This doesn't appear to be a complete usbpd1 image\n");
- return 1;
+done:
+ futil_unmap_and_close_file(fd, FILE_RO, buf, len);
+ return rv;
}
enum futil_file_type ft_recognize_usbpd1(uint8_t *buf, uint32_t len)
diff --git a/futility/futility.h b/futility/futility.h
index 9d40ba7..fa4d3de 100644
--- a/futility/futility.h
+++ b/futility/futility.h
@@ -132,13 +132,26 @@
FILE_ERR_SOCK,
};
+enum file_mode {
+ FILE_RO,
+ FILE_RW,
+};
+
+enum futil_file_err futil_open_file(const char *infile, int *fd,
+ enum file_mode mode);
+enum futil_file_err futil_close_file(int fd);
+
/* Wrapper for mmap/munmap. Skips stupidly large files. */
-#define MAP_RO 0
-#define MAP_RW 1
-enum futil_file_err futil_map_file(int fd, int writeable,
- uint8_t **buf, uint32_t *len);
-enum futil_file_err futil_unmap_file(int fd, int writeable,
- uint8_t *buf, uint32_t len);
+enum futil_file_err futil_map_file(int fd, enum file_mode mode, uint8_t **buf,
+ uint32_t *len);
+enum futil_file_err futil_unmap_file(int fd, enum file_mode mode, uint8_t *buf,
+ uint32_t len);
+
+enum futil_file_err futil_open_and_map_file(const char *infile, int *fd,
+ enum file_mode mode, uint8_t **buf,
+ uint32_t *len);
+enum futil_file_err futil_unmap_and_close_file(int fd, enum file_mode mode,
+ uint8_t *buf, uint32_t len);
/*
* Parse input string as a hex representation of size len, exit with error if
diff --git a/futility/futility_options.h b/futility/futility_options.h
index a79505c..32f240a 100644
--- a/futility/futility_options.h
+++ b/futility/futility_options.h
@@ -34,8 +34,7 @@
struct vb2_private_key *signprivate;
struct vb2_keyblock *keyblock;
struct vb2_packed_key *kernel_subkey;
- struct vb2_private_key *devsignprivate;
- struct vb2_keyblock *devkeyblock;
+ const char *keysetdir;
uint32_t version;
int version_specified;
uint32_t flags;
@@ -67,4 +66,7 @@
};
extern struct sign_option_s sign_option;
+#define FILE_MODE_SIGN(sign_options) \
+ (sign_options.create_new_outfile ? FILE_RO : FILE_RW)
+
#endif /* VBOOT_REFERENCE_FUTILITY_OPTIONS_H_ */
diff --git a/futility/misc.c b/futility/misc.c
index 76b8ad1..4aec13a 100644
--- a/futility/misc.c
+++ b/futility/misc.c
@@ -5,6 +5,7 @@
#include <assert.h>
#include <errno.h>
+#include <fcntl.h>
#if !defined(HAVE_MACOS) && !defined(__FreeBSD__) && !defined(__OpenBSD__)
#include <linux/fs.h> /* For BLKGETSIZE64 */
#endif
@@ -258,8 +259,40 @@
exit(1);
}
+enum futil_file_err futil_open_file(const char *infile, int *fd,
+ enum file_mode mode)
+{
+ if (mode == FILE_RW) {
+ VB2_DEBUG("open RW %s\n", infile);
+ *fd = open(infile, O_RDWR);
+ if (*fd < 0) {
+ fprintf(stderr, "Can't open %s for writing: %s\n",
+ infile, strerror(errno));
+ return FILE_ERR_OPEN;
+ }
+ } else {
+ VB2_DEBUG("open RO %s\n", infile);
+ *fd = open(infile, O_RDONLY);
+ if (*fd < 0) {
+ fprintf(stderr, "Can't open %s for reading: %s\n",
+ infile, strerror(errno));
+ return FILE_ERR_OPEN;
+ }
+ }
+ return FILE_ERR_NONE;
+}
-enum futil_file_err futil_map_file(int fd, int writeable,
+enum futil_file_err futil_close_file(int fd)
+{
+ if (fd >= 0 && close(fd)) {
+ fprintf(stderr, "Error when closing ifd: %s\n",
+ strerror(errno));
+ return FILE_ERR_CLOSE;
+ }
+ return FILE_ERR_NONE;
+}
+
+enum futil_file_err futil_map_file(int fd, enum file_mode mode,
uint8_t **buf, uint32_t *len)
{
struct stat sb;
@@ -284,7 +317,7 @@
}
reasonable_len = (uint32_t)sb.st_size;
- if (writeable)
+ if (mode == FILE_RW)
mmap_ptr = mmap(0, sb.st_size,
PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
else
@@ -293,7 +326,7 @@
if (mmap_ptr == (void *)-1) {
fprintf(stderr, "Can't mmap %s file: %s\n",
- writeable ? "output" : "input",
+ mode == FILE_RW ? "output" : "input",
strerror(errno));
return FILE_ERR_MMAP;
}
@@ -303,14 +336,14 @@
return FILE_ERR_NONE;
}
-enum futil_file_err futil_unmap_file(int fd, int writeable,
+enum futil_file_err futil_unmap_file(int fd, enum file_mode mode,
uint8_t *buf, uint32_t len)
{
void *mmap_ptr = buf;
enum futil_file_err err = FILE_ERR_NONE;
- if (writeable &&
- (0 != msync(mmap_ptr, len, MS_SYNC|MS_INVALIDATE))) {
+ if (mode == FILE_RW &&
+ (0 != msync(mmap_ptr, len, MS_SYNC | MS_INVALIDATE))) {
fprintf(stderr, "msync failed: %s\n", strerror(errno));
err = FILE_ERR_MSYNC;
}
@@ -325,6 +358,36 @@
return err;
}
+enum futil_file_err futil_open_and_map_file(const char *infile, int *fd,
+ enum file_mode mode, uint8_t **buf,
+ uint32_t *len)
+{
+ enum futil_file_err rv = futil_open_file(infile, fd, mode);
+ if (rv != FILE_ERR_NONE)
+ return rv;
+
+ rv = futil_map_file(*fd, mode, buf, len);
+ if (rv != FILE_ERR_NONE)
+ futil_close_file(*fd);
+
+ return rv;
+}
+
+enum futil_file_err futil_unmap_and_close_file(int fd, enum file_mode mode,
+ uint8_t *buf, uint32_t len)
+{
+ enum futil_file_err rv = FILE_ERR_NONE;
+
+ if (buf)
+ rv = futil_unmap_file(fd, mode, buf, len);
+ if (rv != FILE_ERR_NONE)
+ return rv;
+
+ if (fd != -1)
+ return futil_close_file(fd);
+ else
+ return FILE_ERR_NONE;
+}
#define DISK_SECTOR_SIZE 512
enum futil_file_type ft_recognize_gpt(uint8_t *buf, uint32_t len)
diff --git a/futility/updater.c b/futility/updater.c
index 06a696c..1a5e99d 100644
--- a/futility/updater.c
+++ b/futility/updater.c
@@ -20,6 +20,13 @@
static const char ROOTKEY_HASH_DEV[] =
"b11d74edd286c144e1135b49e7f0bc20cf041f10";
+enum try_update_type {
+ TRY_UPDATE_OFF = 0,
+ TRY_UPDATE_AUTO,
+ TRY_UPDATE_DEFERRED_HOLD,
+ TRY_UPDATE_DEFERRED_APPLY,
+};
+
enum target_type {
TARGET_SELF,
TARGET_UPDATE,
@@ -323,132 +330,6 @@
}
/*
- * Emulates writing to firmware.
- * Returns 0 if success, non-zero if error.
- */
-static int emulate_write_firmware(const char *filename,
- const struct firmware_image *image,
- const char *section_name)
-{
- struct firmware_image to_image = {0};
- struct firmware_section from, to;
- int errorcnt = 0;
-
- INFO("(emulation) Writing %s from %s to %s (emu=%s).\n",
- section_name ? section_name : "the whole image",
- image->file_name, image->programmer, filename);
-
- from.data = image->data;
- from.size = image->size;
-
- if (load_firmware_image(&to_image, filename, NULL)) {
- ERROR("Cannot load image from %s.\n", filename);
- return -1;
- }
-
- if (section_name) {
- find_firmware_section(&from, image, section_name);
- if (!from.data) {
- ERROR("No section %s in source image %s.\n",
- section_name, image->file_name);
- errorcnt++;
- }
- find_firmware_section(&to, &to_image, section_name);
- if (!to.data) {
- ERROR("No section %s in destination image %s.\n",
- section_name, filename);
- errorcnt++;
- }
- } else if (image->size != to_image.size) {
- ERROR("Image size is different (%s:%d != %s:%d)\n",
- image->file_name, image->size, to_image.file_name,
- to_image.size);
- errorcnt++;
- } else {
- to.data = to_image.data;
- to.size = to_image.size;
- }
-
- if (!errorcnt) {
- size_t to_write = VB2_MIN(to.size, from.size);
-
- assert(from.data && to.data);
- VB2_DEBUG("Writing %zu bytes\n", to_write);
- memcpy(to.data, from.data, to_write);
- }
-
- if (!errorcnt && vb2_write_file(
- filename, to_image.data, to_image.size)) {
- ERROR("Failed writing to file: %s\n", filename);
- errorcnt++;
- }
-
- free_firmware_image(&to_image);
- return errorcnt;
-}
-
-/*
- * Returns the number of retries when reading or writing to flash.
- */
-static int get_io_retries(struct updater_config *cfg)
-{
- return 1 + get_config_quirk(QUIRK_EXTRA_RETRIES, cfg);
-}
-
-/*
- * Returns 1 if the programmers in image1 and image2 are the same.
- */
-static int is_the_same_programmer(const struct firmware_image *image1,
- const struct firmware_image *image2)
-{
- assert(image1 && image2);
-
- /* Including if both are NULL. */
- if (image1->programmer == image2->programmer)
- return 1;
-
- /* Not the same if either one is NULL. */
- if (!image1->programmer || !image2->programmer)
- return 0;
-
- return strcmp(image1->programmer, image2->programmer) == 0;
-}
-
-/*
- * Writes multiple sections from the given firmware image to the system.
- * The 'sections' should be NULL (write the whole image) or a list of section
- * names to write, and ended with NULL.
- * Returns 0 if success, non-zero if error.
- */
-static int write_firmware_sections(struct updater_config *cfg,
- const struct firmware_image *image,
- const char * const sections[])
-{
- int r = 0;
- struct firmware_image *diff_image = NULL;
-
- if (cfg->emulation) {
- int i;
- if (!sections)
- return emulate_write_firmware(
- cfg->emulation, image, NULL);
- for (i = 0; sections[i] && !r; i++) {
- r |= emulate_write_firmware(
- cfg->emulation, image, sections[i]);
- }
- return r;
- }
-
- if (cfg->use_diff_image && cfg->image_current.data &&
- is_the_same_programmer(&cfg->image_current, image))
- diff_image = &cfg->image_current;
-
- return write_system_firmware(image, diff_image, sections,
- &cfg->tempfiles, cfg->do_verify,
- get_io_retries(cfg), cfg->verbosity + 1);
-}
-
-/*
* Writes a single section from the given firmware image to the system.
* Writes the whole firmware image if the section_name is NULL.
* Returns 0 if success, non-zero if error.
@@ -460,8 +341,8 @@
const char *sections[2] = {0};
sections[0] = section_name;
- return write_firmware_sections(cfg, image,
- section_name ? sections : NULL);
+ return write_system_firmware(
+ cfg, image, section_name ? sections : NULL);
}
/*
@@ -1077,7 +958,7 @@
struct firmware_image *image_to,
int wp_enabled)
{
- const char *target;
+ const char *target, *self_target;
int has_update = 1;
int is_vboot2 = get_system_property(SYS_PROP_FW_VBOOT2, cfg);
@@ -1093,7 +974,7 @@
return UPDATE_ERR_TPM_ROLLBACK;
VB2_DEBUG("Firmware %s vboot2.\n", is_vboot2 ? "is" : "is NOT");
- target = decide_rw_target(cfg, TARGET_SELF, is_vboot2);
+ self_target = target = decide_rw_target(cfg, TARGET_SELF, is_vboot2);
if (target == NULL) {
ERROR("TRY-RW update needs system to boot in RW firmware.\n");
return UPDATE_ERR_TARGET;
@@ -1105,7 +986,7 @@
target, image_to->file_name);
return UPDATE_ERR_INVALID_IMAGE;
}
- if (!cfg->force_update)
+ if (!(cfg->force_update || cfg->try_update == TRY_UPDATE_DEFERRED_HOLD))
has_update = section_needs_update(image_from, image_to, target);
if (has_update) {
@@ -1115,6 +996,24 @@
if (write_firmware(cfg, image_to, target))
return UPDATE_ERR_WRITE_FIRMWARE;
+
+ /*
+ * If the firmware update requested is part of a deferred update
+ * HOLD action, the autoupdater/postinstall will later call
+ * defer update APPLY action to set the correct cookies. So here
+ * it is valid to keep the self slot as the active firmware even
+ * though the target slot is always updated (whether the current
+ * active firmware is the same version or not).
+ */
+ if (cfg->try_update == TRY_UPDATE_DEFERRED_HOLD) {
+ STATUS(
+ "DEFERRED UPDATE: Defer setting cookies for %s\n",
+ target);
+ target = self_target;
+ has_update = 0;
+ }
+ } else {
+ STATUS("NO RW UPDATE: No update for RW firmware.\n");
}
/* Always set right cookies for next boot. */
@@ -1128,9 +1027,6 @@
write_firmware(cfg, image_to, FMAP_RW_LEGACY);
}
- if (!has_update)
- STATUS("NO UPDATE: No need to update.\n");
-
return UPDATE_ERR_DONE;
}
@@ -1144,14 +1040,17 @@
struct firmware_image *image_from,
struct firmware_image *image_to)
{
- int sections_start = 0;
- static const char * const sections[] = {
- FMAP_RW_LEGACY,
+ int i, num = 0;
+ static const char * const required_sections[] = {
FMAP_RW_SECTION_A,
FMAP_RW_SECTION_B,
- FMAP_RW_SHARED,
- NULL,
};
+ static const char * const optional_sections[] = {
+ FMAP_RW_LEGACY,
+ FMAP_RW_SHARED,
+ };
+ const char *sections[ARRAY_SIZE(required_sections) +
+ ARRAY_SIZE(optional_sections) + 1];
STATUS("RW UPDATE: Updating RW sections (%s, %s, %s, and %s).\n",
FMAP_RW_SECTION_A, FMAP_RW_SECTION_B, FMAP_RW_SHARED,
@@ -1163,17 +1062,29 @@
if (check_compatible_tpm_keys(cfg, image_to))
return UPDATE_ERR_TPM_ROLLBACK;
+ for (i = 0; i < ARRAY_SIZE(required_sections); i++)
+ sections[num++] = required_sections[i];
+
/*
+ * The FMAP_RW_LEGACY is a special optional section.
* We may also consider only updating legacy if legacy_needs_update()
* returns true. However, given this is for 'recovery', it is probably
* better to restore everything to the default states. We may revisit
* this if a new scenario is found.
*/
- if (!firmware_section_exists(image_from, sections[sections_start]) ||
- !firmware_section_exists(image_to, sections[sections_start]))
- sections_start++;
+ for (i = 0; i < ARRAY_SIZE(optional_sections); i++) {
+ const char *name = optional_sections[i];
+ if (!firmware_section_exists(image_from, name) ||
+ !firmware_section_exists(image_to, name)) {
+ VB2_DEBUG("Skipped optional section: %s\n", name);
+ continue;
+ }
+ sections[num++] = name;
+ }
+ assert(num < ARRAY_SIZE(sections));
+ sections[num] = NULL;
- if (write_firmware_sections(cfg, image_to, §ions[sections_start]))
+ if (write_system_firmware(cfg, image_to, sections))
return UPDATE_ERR_WRITE_FIRMWARE;
return UPDATE_ERR_DONE;
@@ -1260,6 +1171,23 @@
int wp_enabled, done = 0;
enum updater_error_codes r = UPDATE_ERR_UNKNOWN;
+ /*
+ * For deferred update APPLY action, the only requirement is to set the
+ * correct cookies to the update target slot.
+ */
+ if (cfg->try_update == TRY_UPDATE_DEFERRED_APPLY) {
+ INFO("Apply deferred updates, only setting cookies for the "
+ "next boot slot.\n");
+ int vboot2 = get_system_property(SYS_PROP_FW_VBOOT2, cfg);
+ if (set_try_cookies(
+ cfg,
+ decide_rw_target(cfg, TARGET_UPDATE, vboot2),
+ /*has_update=*/1,
+ vboot2))
+ return UPDATE_ERR_SET_COOKIES;
+ return UPDATE_ERR_DONE;
+ }
+
struct firmware_image *image_from = &cfg->image_current,
*image_to = &cfg->image;
if (!image_to->data)
@@ -1280,8 +1208,7 @@
int ret;
INFO("Loading current system firmware...\n");
- ret = load_system_firmware(image_from, &cfg->tempfiles,
- get_io_retries(cfg), cfg->verbosity);
+ ret = load_system_firmware(cfg, image_from);
if (ret == IMAGE_PARSE_FAILURE && cfg->force_update) {
WARN("No compatible firmware in system.\n");
cfg->check_platform = 0;
@@ -1344,7 +1271,7 @@
* Allocates and initializes a updater_config object with default values.
* Returns the newly allocated object, or NULL on error.
*/
-struct updater_config *updater_new_config()
+struct updater_config *updater_new_config(void)
{
struct updater_config *cfg = (struct updater_config *)calloc(
1, sizeof(struct updater_config));
@@ -1402,7 +1329,7 @@
const char *pd_image)
{
int errorcnt = 0;
- struct archive *ar = cfg->archive;
+ struct u_archive *ar = cfg->archive;
if (!cfg->image.data && image) {
if (image && strcmp(image, "-") == 0) {
@@ -1450,23 +1377,20 @@
}
/*
- * Applies white label information to an existing model config.
+ * Applies custom label information to an existing model config.
* Returns 0 on success, otherwise failure.
*/
-static int updater_apply_white_label(struct updater_config *cfg,
+static int updater_apply_custom_label(struct updater_config *cfg,
struct model_config *model,
const char *signature_id)
{
const char *tmp_image = NULL;
- assert(model->is_white_label);
+ assert(model->is_custom_label);
if (!signature_id) {
if (!cfg->image_current.data) {
- INFO("Loading system firmware for white label...\n");
- load_system_firmware(&cfg->image_current,
- &cfg->tempfiles,
- get_io_retries(cfg),
- cfg->verbosity);
+ INFO("Loading system firmware for custom label...\n");
+ load_system_firmware(cfg, &cfg->image_current);
}
tmp_image = get_firmware_image_temp_file(
&cfg->image_current, &cfg->tempfiles);
@@ -1479,7 +1403,7 @@
quirk_override_signature_id(
cfg, model, &signature_id);
}
- return !!model_apply_white_label(
+ return !!model_apply_custom_label(
model, cfg->archive, signature_id, tmp_image);
}
@@ -1494,7 +1418,7 @@
int is_factory)
{
int errorcnt = 0;
- struct archive *ar = cfg->archive;
+ struct u_archive *ar = cfg->archive;
const struct model_config *model;
if (arg->do_manifest) {
@@ -1508,33 +1432,34 @@
if (!model)
return ++errorcnt;
- /* Load images now so we can get quirks in WL checks. */
+ /* Load images now so we can get quirks in custom label checks. */
errorcnt += updater_load_images(
cfg, arg, model->image, model->ec_image,
model->pd_image);
- if (model->is_white_label && !manifest->has_keyset) {
+ if (model->is_custom_label && !manifest->has_keyset) {
/*
* Developers running unsigned updaters (usually local build)
- * won't be able match any white label tags.
+ * won't be able match any custom label tags.
*/
WARN("No keysets found - this is probably a local build of \n"
- "unsigned firmware updater. Skip applying white label.");
- } else if (model->is_white_label) {
+ "unsigned firmware updater. Skip applying custom label.");
+ } else if (model->is_custom_label) {
/*
- * It is fine to fail in updater_apply_white_label for factory
+ * It is fine to fail in updater_apply_custom_label for factory
* mode so we are not checking the return value; instead we
* verify if the patches do contain new root key.
*/
- updater_apply_white_label(cfg, (struct model_config *)model,
+ updater_apply_custom_label(cfg, (struct model_config *)model,
arg->signature_id);
if (!model->patches.rootkey) {
if (is_factory ||
is_write_protection_enabled(cfg) ||
- get_config_quirk(QUIRK_ALLOW_EMPTY_WLTAG, cfg)) {
- WARN("No VPD for white label.\n");
+ get_config_quirk(QUIRK_ALLOW_EMPTY_CUSTOM_LABEL_TAG,
+ cfg)) {
+ WARN("No VPD for custom label.\n");
} else {
- ERROR("Need VPD set for white label.\n");
+ ERROR("Need VPD set for custom label.\n");
return ++errorcnt;
}
}
@@ -1587,12 +1512,16 @@
/* Setup update mode. */
if (arg->try_update)
- cfg->try_update = 1;
+ cfg->try_update = TRY_UPDATE_AUTO;
if (arg->mode) {
if (strcmp(arg->mode, "autoupdate") == 0) {
- cfg->try_update = 1;
+ cfg->try_update = TRY_UPDATE_AUTO;
+ } else if (strcmp(arg->mode, "deferupdate_hold") == 0) {
+ cfg->try_update = TRY_UPDATE_DEFERRED_HOLD;
+ } else if (strcmp(arg->mode, "deferupdate_apply") == 0) {
+ cfg->try_update = TRY_UPDATE_DEFERRED_APPLY;
} else if (strcmp(arg->mode, "recovery") == 0) {
- cfg->try_update = 0;
+ cfg->try_update = TRY_UPDATE_OFF;
} else if (strcmp(arg->mode, "legacy") == 0) {
cfg->legacy_update = 1;
} else if (strcmp(arg->mode, "factory") == 0 ||
@@ -1608,7 +1537,7 @@
if (cfg->factory_update) {
/* factory_update must be processed after arg->mode. */
check_wp_disabled = 1;
- cfg->try_update = 0;
+ cfg->try_update = TRY_UPDATE_OFF;
}
cfg->gbb_flags = arg->gbb_flags;
cfg->override_gbb_flags = arg->override_gbb_flags;
@@ -1654,7 +1583,7 @@
/* Process archives which may not have valid contents. */
if (arg->repack || arg->unpack) {
const char *work_name = arg->repack ? arg->repack : arg->unpack;
- struct archive *from, *to, *work;
+ struct u_archive *from, *to, *work;
work = archive_open(work_name);
if (arg->repack) {
@@ -1674,8 +1603,25 @@
return errorcnt;
}
- /* Load images from archive. */
- if (arg->archive) {
+ /* Process the manifest and load images from the archive. */
+ if (arg->archive && arg->do_manifest && arg->fast_update) {
+ /* Quickly load and dump the manifest file from the archive. */
+ const char *manifest_name = "manifest.json";
+ uint8_t *data = NULL;
+ uint32_t size = 0;
+
+ if (archive_has_entry(cfg->archive, manifest_name) &&
+ archive_read_file(cfg->archive, manifest_name, &data, &size,
+ NULL) == 0) {
+ /* data is NUL-terminated. */
+ printf("%s\n", data);
+ free(data);
+ } else {
+ ERROR("Failed to read the cached manifest: %s\n",
+ manifest_name);
+ errorcnt++;
+ }
+ } else if (arg->archive) {
struct manifest *m = new_manifest_from_archive(cfg->archive);
if (m) {
errorcnt += updater_setup_archive(
diff --git a/futility/updater.h b/futility/updater.h
index 6dda928..cf03465 100644
--- a/futility/updater.h
+++ b/futility/updater.h
@@ -42,13 +42,14 @@
QUIRK_UNLOCK_ME_FOR_UPDATE,
QUIRK_UNLOCK_WILCO_ME_FOR_UPDATE,
QUIRK_EVE_SMM_STORE,
- QUIRK_ALLOW_EMPTY_WLTAG,
+ QUIRK_ALLOW_EMPTY_CUSTOM_LABEL_TAG,
QUIRK_EC_PARTIAL_RECOVERY,
QUIRK_OVERRIDE_SIGNATURE_ID,
QUIRK_PRESERVE_ME,
QUIRK_NO_CHECK_PLATFORM,
QUIRK_NO_VERIFY,
QUIRK_EXTRA_RETRIES,
+ QUIRK_EXTERNAL_FLASHROM,
QUIRK_MAX,
};
@@ -64,7 +65,7 @@
struct firmware_image ec_image, pd_image;
struct system_property system_properties[SYS_PROP_MAX];
struct quirk_entry quirks[QUIRK_MAX];
- struct archive *archive;
+ struct u_archive *archive;
struct tempfile tempfiles;
int try_update;
int force_update;
@@ -105,13 +106,13 @@
char *image, *ec_image, *pd_image;
struct patch_config patches;
char *signature_id;
- int is_white_label;
+ int is_custom_label;
};
struct manifest {
int num;
struct model_config *models;
- struct archive *archive;
+ struct u_archive *archive;
int default_model;
int has_keyset;
};
@@ -207,26 +208,26 @@
* Returns a pointer to reference to archive (must be released by archive_close
* when not used), otherwise NULL on error.
*/
-struct archive *archive_open(const char *path);
+struct u_archive *archive_open(const char *path);
/*
* Closes an archive reference.
* Returns 0 on success, otherwise non-zero as failure.
*/
-int archive_close(struct archive *ar);
+int archive_close(struct u_archive *ar);
/*
* Checks if an entry (either file or directory) exists in archive.
* Returns 1 if exists, otherwise 0
*/
-int archive_has_entry(struct archive *ar, const char *name);
+int archive_has_entry(struct u_archive *ar, const char *name);
/*
* Reads a file from archive.
* Returns 0 on success (data and size reflects the file content),
* otherwise non-zero as failure.
*/
-int archive_read_file(struct archive *ar, const char *fname,
+int archive_read_file(struct u_archive *ar, const char *fname,
uint8_t **data, uint32_t *size, int64_t *mtime);
/*
@@ -235,20 +236,30 @@
* file system.
* Returns 0 on success, otherwise non-zero as failure.
*/
-int archive_write_file(struct archive *ar, const char *fname,
+int archive_write_file(struct u_archive *ar, const char *fname,
uint8_t *data, uint32_t size, int64_t mtime);
/*
+ * Traverses all files within archive (directories are ignored).
+ * For every entry, the path (relative the archive root) will be passed to
+ * callback function, until the callback returns non-zero.
+ * The arg argument will also be passed to callback.
+ * Returns 0 on success otherwise non-zero as failure.
+ */
+int archive_walk(struct u_archive *ar, void *arg,
+ int (*callback)(const char *path, void *arg));
+
+/*
* Copies all entries from one archive to another.
* Returns 0 on success, otherwise non-zero as failure.
*/
-int archive_copy(struct archive *from, struct archive *to);
+int archive_copy(struct u_archive *from, struct u_archive *to);
/*
* Creates a new manifest object by scanning files in archive.
* Returns the manifest on success, otherwise NULL for failure.
*/
-struct manifest *new_manifest_from_archive(struct archive *archive);
+struct manifest *new_manifest_from_archive(struct u_archive *archive);
/* Releases all resources allocated by given manifest object. */
void delete_manifest(struct manifest *manifest);
@@ -262,7 +273,7 @@
*/
int patch_image_by_model(
struct firmware_image *image, const struct model_config *model,
- struct archive *archive);
+ struct u_archive *archive);
/*
* Finds the existing model_config from manifest that best matches current
@@ -273,14 +284,14 @@
const char *model_name);
/*
- * Applies white label information to an existing model configuration.
+ * Applies custom label information to an existing model configuration.
* Collects signature ID information from either parameter signature_id or
* image file (via VPD) and updates model.patches for key files.
* Returns 0 on success, otherwise failure.
*/
-int model_apply_white_label(
+int model_apply_custom_label(
struct model_config *model,
- struct archive *archive,
+ struct u_archive *archive,
const char *signature_id,
const char *image);
diff --git a/futility/updater_archive.c b/futility/updater_archive.c
index 9c3a608..c6e8f28 100644
--- a/futility/updater_archive.c
+++ b/futility/updater_archive.c
@@ -6,19 +6,20 @@
*/
#include <assert.h>
-#include <ctype.h>
#include <errno.h>
#if defined(__OpenBSD__)
#include <sys/types.h>
#endif
#include <fts.h>
-#include <string.h>
-#include <stdio.h>
-#include <stdlib.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <unistd.h>
+#ifdef HAVE_LIBARCHIVE
+#include <archive.h>
+#include <archive_entry.h>
+#endif
+
#ifdef HAVE_LIBZIP
#ifndef __clang__
/* If libzip headers were built for Clang but later get included with GCC you
@@ -30,62 +31,16 @@
#include <zip.h>
#endif
-#ifdef HAVE_CROSID
-#include <crosid.h>
-#endif
-
#include "host_misc.h"
#include "updater.h"
-#include "util_misc.h"
/*
* A firmware update package (archive) is a file packed by either shar(1) or
* zip(1). See https://chromium.googlesource.com/chromiumos/platform/firmware/
* for more information.
- *
- * A package for single board (i.e., not Unified Build) will have all the image
- * files in top folder:
- * - host: 'image.bin' (or 'bios.bin' as legacy name before CL:1318712)
- * - ec: 'ec.bin'
- * - pd: 'pd.bin'
- * If white label is supported, a 'keyset/' folder will be available, with key
- * files in it:
- * - rootkey.$WLTAG
- * - vblock_A.$WLTAG
- * - vblock_B.$WLTAG
- * The $WLTAG should come from VPD value 'whitelabel_tag', or the
- * 'customization_id'. Note 'customization_id' is in format LOEM[-VARIANT] and
- * we can only take LOEM as $WLTAG, for example A-B => $WLTAG=A.
- *
- * A package for Unified Build is more complicated. There will be a models/
- * folder, and each model (by $(mosys platform model) ) should appear as a sub
- * folder, with a 'setvars.sh' file inside. The 'setvars.sh' is a shell script
- * describing what files should be used and the signature ID ($SIGID) to use.
- *
- * Similar to write label in non-Unified-Build, the keys and vblock files will
- * be in 'keyset/' folder:
- * - rootkey.$SIGID
- * - vblock_A.$SIGID
- * - vblock_B.$SIGID
- * If $SIGID starts with 'sig-id-in-*' then we have to replace it by VPD value
- * 'whitelabel_tag' as '$MODEL-$WLTAG'.
*/
-static const char * const SETVARS_IMAGE_MAIN = "IMAGE_MAIN",
- * const SETVARS_IMAGE_EC = "IMAGE_EC",
- * const SETVARS_IMAGE_PD = "IMAGE_PD",
- * const SETVARS_SIGNATURE_ID = "SIGNATURE_ID",
- * const SIG_ID_IN_VPD_PREFIX = "sig-id-in",
- * const DIR_KEYSET = "keyset",
- * const DIR_MODELS = "models",
- * const DEFAULT_MODEL_NAME = "default",
- * const VPD_WHITELABEL_TAG = "whitelabel_tag",
- * const VPD_CUSTOMIZATION_ID = "customization_id",
- * const ENV_VAR_MODEL_DIR = "${MODEL_DIR}",
- * const PATH_STARTSWITH_KEYSET = "keyset/",
- * const PATH_ENDSWITH_SERVARS = "/setvars.sh";
-
-struct archive {
+struct u_archive {
void *handle;
void * (*open)(const char *name);
@@ -101,7 +56,7 @@
};
/*
- * -- Begin of archive implementations --
+ * -- The fallback driver (using general file system). --
*/
/* Callback for archive_open on a general file system. */
@@ -189,6 +144,7 @@
VB2_DEBUG("Reading %s\n", path);
*data = NULL;
*size = 0;
+ /* vb2_read_file already has an extra '\0' in the end. */
r = vb2_read_file(path, data, size) != VB2_SUCCESS;
if (mtime) {
if (stat(path, &st) == 0)
@@ -234,6 +190,238 @@
return r;
}
+/*
+ * -- The cache driver (used by other drivers). --
+ */
+
+#ifdef HAVE_LIBARCHIVE
+
+/*
+ * For stream-based archives (e.g., tar+gz) we want to create a cache for
+ * storing the names and contents for later processing.
+ */
+struct archive_cache {
+ char *name;
+ uint8_t *data;
+ int64_t mtime;
+ size_t size;
+ int has_data;
+ struct archive_cache *next;
+};
+
+/* Add a new cache node to an existing cache list and return the new head. */
+static struct archive_cache *archive_cache_new(struct archive_cache *cache,
+ const char *name)
+{
+ struct archive_cache *c;
+
+ c = (struct archive_cache *)calloc(sizeof(*c), 1);
+ if (!c)
+ return NULL;
+
+ c->name = strdup(name);
+ if (!c->name) {
+ free(c);
+ return NULL;
+ }
+
+ c->next = cache;
+ return c;
+}
+
+/* Find and return an entry (by name) from the cache. */
+static struct archive_cache *archive_cache_find(struct archive_cache *c,
+ const char *name)
+{
+ for (; c; c = c->next) {
+ assert(c->name);
+ if (!strcmp(c->name, name))
+ return c;
+ }
+ return NULL;
+}
+
+/* Callback for archive_walk to process all entries in the cache. */
+static int archive_cache_walk(
+ struct archive_cache *c, void *arg,
+ int (*callback)(const char *name, void *arg))
+{
+ for (; c; c = c->next) {
+ assert(c->name);
+ if (callback(c->name, arg))
+ break;
+ }
+ return 0;
+}
+
+/* Delete all entries in the cache. */
+static void *archive_cache_free(struct archive_cache *c)
+{
+ struct archive_cache *next;
+
+ while (c) {
+ next = c->next;
+ free(c->name);
+ free(c->data);
+ free(c);
+ c = next;
+ }
+ return NULL;
+}
+
+/*
+ * -- The libarchive driver (multiple formats but very slow). --
+ */
+
+enum {
+ FILTER_IGNORE,
+ FILTER_ABORT,
+ FILTER_NAME_ONLY,
+ FILTER_READ_ALL,
+};
+
+static struct archive_cache *libarchive_read_file_entries(
+ const char *fpath, int (*filter)(struct archive_entry *entry))
+{
+ struct archive *a = archive_read_new();
+ struct archive_entry *entry;
+ struct archive_cache *c, *cache = NULL;
+ int r;
+
+ assert(a);
+ archive_read_support_filter_all(a);
+ archive_read_support_format_all(a);
+ r = archive_read_open_filename(a, fpath, 10240);
+ if (r != ARCHIVE_OK) {
+ ERROR("Failed parsing archive using libarchive: %s\n", fpath);
+ archive_read_free(a);
+ return NULL;
+ }
+
+ WARN("Loading data from archive: %s ", fpath);
+ while (archive_read_next_header(a, &entry) == ARCHIVE_OK) {
+ fputc('.', stderr);
+ if (archive_entry_filetype(entry) != AE_IFREG)
+ continue;
+ if (filter)
+ r = filter(entry);
+ else
+ r = FILTER_READ_ALL;
+
+ if (r == FILTER_ABORT)
+ break;
+ if (r == FILTER_IGNORE)
+ continue;
+
+ c = archive_cache_new(cache, archive_entry_pathname(entry));
+ if (!c) {
+ ERROR("Internal error: out of memory.\n");
+ archive_cache_free(cache);
+ archive_read_free(a);
+ return NULL;
+ }
+ cache = c;
+
+ if (r == FILTER_NAME_ONLY)
+ continue;
+
+ assert(r == FILTER_READ_ALL);
+ c->size = archive_entry_size(entry);
+ c->mtime = archive_entry_mtime(entry);
+ c->data = (uint8_t *)calloc(1, c->size + 1);
+ if (!c->data) {
+ WARN("Out of memory when loading: %s\n", c->name);
+ continue;
+ }
+ if (archive_read_data(a, c->data, c->size) != c->size) {
+ WARN("Failed reading from archive: %s\n", c->name);
+ continue;
+ }
+ c->has_data = 1;
+ }
+ fputs("\r\n", stderr); /* Flush the '.' */
+ VB2_DEBUG("Finished loading from archive: %s.\n", fpath);
+
+ archive_read_free(a);
+ return cache;
+}
+
+/* Callback for archive_open on an ARCHIVE file. */
+static void *archive_libarchive_open(const char *name)
+{
+ /*
+ * The firmware archives today can usually all load into memory
+ * so we are using a NULL filter. Change that to a specific list in
+ * future if the /build/$BOARD/firmware archive becomes too large.
+ */
+ return libarchive_read_file_entries(name, NULL);
+}
+
+/* Callback for archive_close on an ARCHIVE file. */
+static int archive_libarchive_close(void *handle)
+{
+ archive_cache_free(handle);
+ return 0;
+}
+
+/* Callback for archive_has_entry on an ARCHIVE file. */
+static int archive_libarchive_has_entry(void *handle, const char *fname)
+{
+ return archive_cache_find(handle, fname) != NULL;
+}
+
+/* Callback for archive_walk on an ARCHIVE file. */
+static int archive_libarchive_walk(
+ void *handle, void *arg,
+ int (*callback)(const char *name, void *arg))
+{
+ return archive_cache_walk(handle, arg, callback);
+}
+
+/* Callback for archive_read_file on an ARCHIVE file. */
+static int archive_libarchive_read_file(
+ void *handle, const char *fname, uint8_t **data,
+ uint32_t *size, int64_t *mtime)
+{
+ struct archive_cache *c = archive_cache_find(handle, fname);
+
+ if (!c)
+ return 1;
+
+ if (!c->has_data) {
+ /* TODO(hungte) Re-read. */
+ ERROR("Not in the cache: %s\n", fname);
+ return 1;
+ }
+
+ if (mtime)
+ *mtime = c->mtime;
+ if (size)
+ *size = c->size;
+ *data = (uint8_t *)malloc(c->size + 1);
+ if (!*data) {
+ ERROR("Out of memory when reading: %s\n", c->name);
+ return 1;
+ }
+ memcpy(*data, c->data, c->size);
+ (*data)[c->size] = '\0';
+ return 0;
+}
+
+/* Callback for archive_write_file on an ARCHIVE file. */
+static int archive_libarchive_write_file(
+ void *handle, const char *fname, uint8_t *data, uint32_t size,
+ int64_t mtime)
+{
+ ERROR("Not implemented!\n");
+ return 1;
+}
+#endif
+
+/*
+ * -- The libzip driver (for ZIP, the official format for CrOS fw updater). --
+ */
+
#ifdef HAVE_LIBZIP
/* Callback for archive_open on a ZIP file. */
@@ -303,12 +491,13 @@
ERROR("Failed to open entry in ZIP: %s\n", fname);
return 1;
}
- *data = (uint8_t *)malloc(stat.size);
+ *data = (uint8_t *)malloc(stat.size + 1);
if (*data) {
if (zip_fread(fp, *data, stat.size) == stat.size) {
if (mtime)
*mtime = stat.mtime;
*size = stat.size;
+ (*data)[stat.size] = '\0';
} else {
ERROR("Failed to read entry in zip: %s\n", fname);
free(*data);
@@ -348,22 +537,26 @@
#endif
/*
+ * -- The public functions for using u_archive. --
+ */
+
+/*
* Opens an archive from given path.
* The type of archive will be determined automatically.
* Returns a pointer to reference to archive (must be released by archive_close
* when not used), otherwise NULL on error.
*/
-struct archive *archive_open(const char *path)
+struct u_archive *archive_open(const char *path)
{
struct stat path_stat;
- struct archive *ar;
+ struct u_archive *ar;
if (stat(path, &path_stat) != 0) {
ERROR("Cannot identify type of path: %s\n", path);
return NULL;
}
- ar = (struct archive *)malloc(sizeof(*ar));
+ ar = (struct u_archive *)calloc(sizeof(*ar), 1);
if (!ar) {
ERROR("Internal error: allocation failure.\n");
return NULL;
@@ -379,22 +572,48 @@
ar->has_entry = archive_fallback_has_entry;
ar->read_file = archive_fallback_read_file;
ar->write_file = archive_fallback_write_file;
- } else {
+ }
+
+ /* Format detection must try ZIP (the official format) first. */
#ifdef HAVE_LIBZIP
- VB2_DEBUG("Found file, use ZIP driver: %s\n", path);
- ar->open = archive_zip_open;
- ar->close = archive_zip_close;
- ar->walk = archive_zip_walk;
- ar->has_entry = archive_zip_has_entry;
- ar->read_file = archive_zip_read_file;
- ar->write_file = archive_zip_write_file;
-#else
- ERROR("Found file, but no drivers were enabled: %s\n", path);
+ if (!ar->open) {
+ ar->handle = archive_zip_open(path);
+
+ if (ar->handle) {
+ VB2_DEBUG("Found a ZIP file: %s\n", path);
+ ar->open = archive_zip_open;
+ ar->close = archive_zip_close;
+ ar->walk = archive_zip_walk;
+ ar->has_entry = archive_zip_has_entry;
+ ar->read_file = archive_zip_read_file;
+ ar->write_file = archive_zip_write_file;
+ }
+ }
+#endif
+
+ /* LIBARCHIVE must be the last driver. */
+#ifdef HAVE_LIBARCHIVE
+ if (!ar->open) {
+ VB2_DEBUG("Found a file, use libarchive: %s\n", path);
+ ar->open = archive_libarchive_open;
+ ar->close = archive_libarchive_close;
+ ar->walk = archive_libarchive_walk;
+ ar->has_entry = archive_libarchive_has_entry;
+ ar->read_file = archive_libarchive_read_file;
+ ar->write_file = archive_libarchive_write_file;
+ }
+#endif
+
+ if (!ar->open) {
+ ERROR("Found a file, but no drivers were selected: %s\n", path);
free(ar);
return NULL;
-#endif
}
- ar->handle = ar->open(path);
+
+ /* Some drivers may have already opened the archive. */
+ if (!ar->handle)
+ ar->handle = ar->open(path);
+
if (!ar->handle) {
ERROR("Failed to open archive: %s\n", path);
free(ar);
@@ -407,7 +626,7 @@
* Closes an archive reference.
* Returns 0 on success, otherwise non-zero as failure.
*/
-int archive_close(struct archive *ar)
+int archive_close(struct u_archive *ar)
{
int r = ar->close(ar->handle);
free(ar);
@@ -420,7 +639,7 @@
* with real file system.
* Returns 1 if exists, otherwise 0
*/
-int archive_has_entry(struct archive *ar, const char *name)
+int archive_has_entry(struct u_archive *ar, const char *name)
{
if (!ar || *name == '/')
return archive_fallback_has_entry(NULL, name);
@@ -434,8 +653,8 @@
* The arg argument will also be passed to callback.
* Returns 0 on success otherwise non-zero as failure.
*/
-static int archive_walk(struct archive *ar, void *arg,
- int (*callback)(const char *path, void *arg))
+int archive_walk(struct u_archive *ar, void *arg,
+ int (*callback)(const char *path, void *arg))
{
if (!ar)
return archive_fallback_walk(NULL, arg, callback);
@@ -446,10 +665,12 @@
* Reads a file from archive.
* If entry name (fname) is an absolute path (/file), always read
* from real file system.
+ * The returned data must always have one extra (not included by size) '\0' in
+ * the end of the allocated buffer for C string processing.
* Returns 0 on success (data and size reflects the file content),
* otherwise non-zero as failure.
*/
-int archive_read_file(struct archive *ar, const char *fname,
+int archive_read_file(struct u_archive *ar, const char *fname,
uint8_t **data, uint32_t *size, int64_t *mtime)
{
if (!ar || *fname == '/')
@@ -463,7 +684,7 @@
* file system.
* Returns 0 on success, otherwise non-zero as failure.
*/
-int archive_write_file(struct archive *ar, const char *fname,
+int archive_write_file(struct u_archive *ar, const char *fname,
uint8_t *data, uint32_t size, int64_t mtime)
{
if (!ar || *fname == '/')
@@ -472,7 +693,7 @@
}
struct _copy_arg {
- struct archive *from, *to;
+ struct u_archive *from, *to;
};
/* Callback for archive_copy. */
@@ -499,654 +720,8 @@
* Copies all entries from one archive to another.
* Returns 0 on success, otherwise non-zero as failure.
*/
-int archive_copy(struct archive *from, struct archive *to)
+int archive_copy(struct u_archive *from, struct u_archive *to)
{
struct _copy_arg arg = { .from = from, .to = to };
return archive_walk(from, &arg, archive_copy_callback);
}
-
-/*
- * -- End of archive implementations --
- */
-
-/* Utility function to convert a string. */
-static void str_convert(char *s, int (*convert)(int c))
-{
- int c;
-
- for (; *s; s++) {
- c = *s;
- if (!isascii(c))
- continue;
- *s = convert(c);
- }
-}
-
-/* Returns 1 if name ends by given pattern, otherwise 0. */
-static int str_endswith(const char *name, const char *pattern)
-{
- size_t name_len = strlen(name), pattern_len = strlen(pattern);
- if (name_len < pattern_len)
- return 0;
- return strcmp(name + name_len - pattern_len, pattern) == 0;
-}
-
-/* Returns 1 if name starts by given pattern, otherwise 0. */
-static int str_startswith(const char *name, const char *pattern)
-{
- return strncmp(name, pattern, strlen(pattern)) == 0;
-}
-
-/* Returns the VPD value by given key name, or NULL on error (or no value). */
-static char *vpd_get_value(const char *fpath, const char *key)
-{
- char *command, *result;
-
- assert(fpath);
- ASPRINTF(&command, "vpd -g %s -f %s 2>/dev/null", key, fpath);
- result = host_shell(command);
- free(command);
-
- if (result && !*result) {
- free(result);
- result = NULL;
- }
- return result;
-}
-
-/*
- * Reads and parses a setvars type file from archive, then stores into config.
- * Returns 0 on success (at least one entry found), otherwise failure.
- */
-static int model_config_parse_setvars_file(
- struct model_config *cfg, struct archive *archive,
- const char *fpath)
-{
- uint8_t *data;
- uint32_t len;
-
- char *ptr_line, *ptr_token;
- char *line, *k, *v;
- int valid = 0;
-
- if (archive_read_file(archive, fpath, &data, &len, NULL) != 0) {
- ERROR("Failed reading: %s\n", fpath);
- return -1;
- }
-
- /* Valid content should end with \n, or \"; ensure ASCIIZ for parsing */
- if (len)
- data[len - 1] = '\0';
-
- for (line = strtok_r((char *)data, "\n\r", &ptr_line); line;
- line = strtok_r(NULL, "\n\r", &ptr_line)) {
- char *expand_path = NULL;
- int found_valid = 1;
-
- /* Format: KEY="value" */
- k = strtok_r(line, "=", &ptr_token);
- if (!k)
- continue;
- v = strtok_r(NULL, "\"", &ptr_token);
- if (!v)
- continue;
-
- /* Some legacy updaters may be still using ${MODEL_DIR}. */
- if (str_startswith(v, ENV_VAR_MODEL_DIR)) {
- ASPRINTF(&expand_path, "%s/%s%s", DIR_MODELS, cfg->name,
- v + strlen(ENV_VAR_MODEL_DIR));
- }
-
- if (strcmp(k, SETVARS_IMAGE_MAIN) == 0)
- cfg->image = strdup(v);
- else if (strcmp(k, SETVARS_IMAGE_EC) == 0)
- cfg->ec_image = strdup(v);
- else if (strcmp(k, SETVARS_IMAGE_PD) == 0)
- cfg->pd_image = strdup(v);
- else if (strcmp(k, SETVARS_SIGNATURE_ID) == 0) {
- cfg->signature_id = strdup(v);
- if (str_startswith(v, SIG_ID_IN_VPD_PREFIX))
- cfg->is_white_label = 1;
- } else
- found_valid = 0;
- free(expand_path);
- valid += found_valid;
- }
- free(data);
- return valid == 0;
-}
-
-/*
- * Changes the rootkey in firmware GBB to given new key.
- * Returns 0 on success, otherwise failure.
- */
-static int change_gbb_rootkey(struct firmware_image *image,
- const char *section_name,
- const uint8_t *rootkey, uint32_t rootkey_len)
-{
- const struct vb2_gbb_header *gbb = find_gbb(image);
- uint8_t *gbb_rootkey;
- if (!gbb) {
- ERROR("Cannot find GBB in image %s.\n", image->file_name);
- return -1;
- }
- if (gbb->rootkey_size < rootkey_len) {
- ERROR("New root key (%u bytes) larger than GBB (%u bytes).\n",
- rootkey_len, gbb->rootkey_size);
- return -1;
- }
-
- gbb_rootkey = (uint8_t *)gbb + gbb->rootkey_offset;
- /* See cmd_gbb_utility: root key must be first cleared with zero. */
- memset(gbb_rootkey, 0, gbb->rootkey_size);
- memcpy(gbb_rootkey, rootkey, rootkey_len);
- return 0;
-}
-
-/*
- * Changes the VBlock in firmware section to new data.
- * Returns 0 on success, otherwise failure.
- */
-static int change_vblock(struct firmware_image *image, const char *section_name,
- const uint8_t *vblock, uint32_t vblock_len)
-{
- struct firmware_section section;
-
- find_firmware_section(§ion, image, section_name);
- if (!section.data) {
- ERROR("Need section %s in image %s.\n", section_name,
- image->file_name);
- return -1;
- }
- if (section.size < vblock_len) {
- ERROR("Section %s too small (%zu bytes) for vblock (%u bytes).\n",
- section_name, section.size, vblock_len);
- return -1;
- }
- memcpy(section.data, vblock, vblock_len);
- return 0;
-}
-
-/*
- * Applies a key file to firmware image.
- * Returns 0 on success, otherwise failure.
- */
-static int apply_key_file(
- struct firmware_image *image, const char *path,
- struct archive *archive, const char *section_name,
- int (*apply)(struct firmware_image *image, const char *section,
- const uint8_t *data, uint32_t len))
-{
- int r = 0;
- uint8_t *data = NULL;
- uint32_t len;
-
- r = archive_read_file(archive, path, &data, &len, NULL);
- if (r == 0) {
- VB2_DEBUG("Loaded file: %s\n", path);
- r = apply(image, section_name, data, len);
- if (r)
- ERROR("Failed applying %s to %s\n", path, section_name);
- } else {
- ERROR("Failed reading: %s\n", path);
- }
- free(data);
- return r;
-}
-
-/*
- * Modifies a firmware image from patch information specified in model config.
- * Returns 0 on success, otherwise number of failures.
- */
-int patch_image_by_model(
- struct firmware_image *image, const struct model_config *model,
- struct archive *archive)
-{
- int err = 0;
- if (model->patches.rootkey)
- err += !!apply_key_file(
- image, model->patches.rootkey, archive,
- FMAP_RO_GBB, change_gbb_rootkey);
- if (model->patches.vblock_a)
- err += !!apply_key_file(
- image, model->patches.vblock_a, archive,
- FMAP_RW_VBLOCK_A, change_vblock);
- if (model->patches.vblock_b)
- err += !!apply_key_file(
- image, model->patches.vblock_b, archive,
- FMAP_RW_VBLOCK_B, change_vblock);
- return err;
-}
-
-/*
- * Finds available patch files by given model.
- * Updates `model` argument with path of patch files.
- */
-static void find_patches_for_model(struct model_config *model,
- struct archive *archive,
- const char *signature_id)
-{
- char *path;
- int i;
-
- const char *names[] = {
- "rootkey",
- "vblock_A",
- "vblock_B",
- };
-
- char **targets[] = {
- &model->patches.rootkey,
- &model->patches.vblock_a,
- &model->patches.vblock_b,
- };
-
- assert(ARRAY_SIZE(names) == ARRAY_SIZE(targets));
- for (i = 0; i < ARRAY_SIZE(names); i++) {
- ASPRINTF(&path, "%s/%s.%s", DIR_KEYSET, names[i], signature_id);
- if (archive_has_entry(archive, path))
- *targets[i] = path;
- else
- free(path);
- }
-}
-
-/*
- * Adds and copies one new model config to the existing list of given manifest.
- * Returns a pointer to the newly allocated config, or NULL on failure.
- */
-static struct model_config *manifest_add_model(
- struct manifest *manifest,
- const struct model_config *cfg)
-{
- struct model_config *model;
- manifest->num++;
- manifest->models = (struct model_config *)realloc(
- manifest->models, manifest->num * sizeof(*model));
- if (!manifest->models) {
- ERROR("Internal error: failed to allocate buffer.\n");
- return NULL;
- }
- model = &manifest->models[manifest->num - 1];
- memcpy(model, cfg, sizeof(*model));
- return model;
-}
-
-/*
- * A callback function for manifest to scan files in archive.
- * Returns 0 to keep scanning, or non-zero to stop.
- */
-static int manifest_scan_entries(const char *name, void *arg)
-{
- struct manifest *manifest = (struct manifest *)arg;
- struct archive *archive = manifest->archive;
- struct model_config model = {0};
- char *slash;
-
- if (str_startswith(name, PATH_STARTSWITH_KEYSET))
- manifest->has_keyset = 1;
- if (!str_endswith(name, PATH_ENDSWITH_SERVARS))
- return 0;
-
- /* name: models/$MODEL/setvars.sh */
- model.name = strdup(strchr(name, '/') + 1);
- slash = strchr(model.name, '/');
- if (slash)
- *slash = '\0';
-
- VB2_DEBUG("Found model <%s> setvars: %s\n", model.name, name);
- if (model_config_parse_setvars_file(&model, archive, name)) {
- ERROR("Invalid setvars file: %s\n", name);
- return 0;
- }
-
- /* In legacy setvars.sh, the ec_image and pd_image may not exist. */
- if (model.ec_image && !archive_has_entry(archive, model.ec_image)) {
- VB2_DEBUG("Ignore non-exist EC image: %s\n", model.ec_image);
- free(model.ec_image);
- model.ec_image = NULL;
- }
- if (model.pd_image && !archive_has_entry(archive, model.pd_image)) {
- VB2_DEBUG("Ignore non-exist PD image: %s\n", model.pd_image);
- free(model.pd_image);
- model.pd_image = NULL;
- }
-
- /* Find patch files. */
- if (model.signature_id)
- find_patches_for_model(&model, archive, model.signature_id);
-
- return !manifest_add_model(manifest, &model);
-}
-
-/**
- * get_manifest_key() - Wrapper to get the firmware manifest key from crosid
- *
- * @manifest_key_out - Output parameter of the firmware manifest key.
- *
- * Returns:
- * - <0 if libcrosid is unavailable or there was an error reading
- * device data
- * - >=0 (the matched device index) success
- */
-static int get_manifest_key(char **manifest_key_out)
-{
-#ifdef HAVE_CROSID
- return crosid_get_firmware_manifest_key(manifest_key_out);
-#else
- ERROR("This version of futility was compiled without libcrosid "
- "(perhaps compiled outside of the Chrome OS build system?) and "
- "the update command is not fully supported. Either compile "
- "from the Chrome OS build, or pass --model to manually specify "
- "the machine model.\n");
- return -1;
-#endif
-}
-
-/*
- * Finds the existing model_config from manifest that best matches current
- * system (as defined by model_name).
- * Returns a model_config from manifest, or NULL if not found.
- */
-const struct model_config *manifest_find_model(const struct manifest *manifest,
- const char *model_name)
-{
- char *manifest_key = NULL;
- const struct model_config *model = NULL;
- int i;
- int matched_index;
-
- /*
- * For manifest with single model defined, we should just return because
- * there are other mechanisms like platform name check to double confirm
- * if the firmware is valid.
- */
- if (manifest->num == 1)
- return &manifest->models[0];
-
- if (!model_name) {
- matched_index = get_manifest_key(&manifest_key);
- if (matched_index < 0) {
- ERROR("Failed to get device identity. "
- "Run \"crosid -v\" for explanation.\n");
- return NULL;
- }
-
- INFO("Identified the device using libcrosid, "
- "matched chromeos-config index: %d, "
- "manifest key (model): %s\n",
- matched_index, manifest_key);
- model_name = manifest_key;
- }
-
- for (i = 0; !model && i < manifest->num; i++) {
- if (strcmp(model_name, manifest->models[i].name) == 0)
- model = &manifest->models[i];
- }
- if (!model) {
- ERROR("Unsupported model: '%s'.\n", model_name);
-
- fprintf(stderr,
- "The firmware manifest key '%s' is not present in this "
- "updater archive. The known keys to this updater "
- "archive are:\n", model_name);
-
- for (i = 0; i < manifest->num; i++)
- fprintf(stderr, " %s", manifest->models[i].name);
- fprintf(stderr, "\n\n");
- fprintf(stderr,
- "Perhaps you are trying to use an updater archive for "
- "the wrong board, or designed for an older OS version "
- "before this model was supported.\n");
- fprintf(stderr,
- "Hint: Read the FIRMWARE_MANIFEST_KEY from the output "
- "of the crosid command.\n");
- }
-
-
- free(manifest_key);
- return model;
-}
-
-/*
- * Determines the signature ID to use for white label.
- * Returns the signature ID for looking up rootkey and vblock files.
- * Caller must free the returned string.
- */
-static char *resolve_signature_id(struct model_config *model, const char *image)
-{
- int is_unibuild = model->signature_id ? 1 : 0;
- char *wl_tag = vpd_get_value(image, VPD_WHITELABEL_TAG);
- char *sig_id = NULL;
-
- /* Unified build: $model.$wl_tag, or $model (b/126800200). */
- if (is_unibuild) {
- if (!wl_tag) {
- WARN("No VPD '%s' set for white label - use model name "
- "'%s' as default.\n", VPD_WHITELABEL_TAG,
- model->name);
- return strdup(model->name);
- }
-
- ASPRINTF(&sig_id, "%s-%s", model->name, wl_tag);
- free(wl_tag);
- return sig_id;
- }
-
- /* Non-Unibuild: Upper($wl_tag), or Upper(${cid%%-*}). */
- if (!wl_tag) {
- char *cid = vpd_get_value(image, VPD_CUSTOMIZATION_ID);
- if (cid) {
- /* customization_id in format LOEM[-VARIANT]. */
- char *dash = strchr(cid, '-');
- if (dash)
- *dash = '\0';
- wl_tag = cid;
- }
- }
- if (wl_tag)
- str_convert(wl_tag, toupper);
- return wl_tag;
-}
-
-/*
- * Applies white label information to an existing model configuration.
- * Collects signature ID information from either parameter signature_id or
- * image file (via VPD) and updates model.patches for key files.
- * Returns 0 on success, otherwise failure.
- */
-int model_apply_white_label(
- struct model_config *model,
- struct archive *archive,
- const char *signature_id,
- const char *image)
-{
- char *sig_id = NULL;
- int r = 0;
-
- if (!signature_id) {
- sig_id = resolve_signature_id(model, image);
- signature_id = sig_id;
- }
-
- if (signature_id) {
- VB2_DEBUG("Find white label patches by signature ID: '%s'.\n",
- signature_id);
- find_patches_for_model(model, archive, signature_id);
- } else {
- signature_id = "";
- WARN("No VPD '%s' set for white label - use default keys.\n",
- VPD_WHITELABEL_TAG);
- }
- if (!model->patches.rootkey) {
- ERROR("No keys found for signature_id: '%s'\n", signature_id);
- r = 1;
- } else {
- INFO("Applied for white label: %s\n", signature_id);
- }
- free(sig_id);
- return r;
-}
-
-/*
- * Creates a new manifest object by scanning files in archive.
- * Returns the manifest on success, otherwise NULL for failure.
- */
-struct manifest *new_manifest_from_archive(struct archive *archive)
-{
- struct manifest manifest = {0}, *new_manifest;
- struct model_config model = {0};
- const char * const host_image_name = "image.bin",
- * const old_host_image_name = "bios.bin",
- * const ec_name = "ec.bin",
- * const pd_name = "pd.bin";
-
- manifest.archive = archive;
- manifest.default_model = -1;
- archive_walk(archive, &manifest, manifest_scan_entries);
- if (manifest.num == 0) {
- const char *image_name = NULL;
- struct firmware_image image = {0};
-
- /* Try to load from current folder. */
- if (archive_has_entry(archive, old_host_image_name))
- image_name = old_host_image_name;
- else if (archive_has_entry(archive, host_image_name))
- image_name = host_image_name;
- else
- return 0;
-
- model.image = strdup(image_name);
- if (archive_has_entry(archive, ec_name))
- model.ec_image = strdup(ec_name);
- if (archive_has_entry(archive, pd_name))
- model.pd_image = strdup(pd_name);
- /* Extract model name from FWID: $Vendor_$Platform.$Version */
- if (!load_firmware_image(&image, image_name, archive)) {
- char *token = NULL;
- if (strtok(image.ro_version, "_"))
- token = strtok(NULL, ".");
- if (token && *token) {
- str_convert(token, tolower);
- model.name = strdup(token);
- }
- free_firmware_image(&image);
- }
- if (!model.name)
- model.name = strdup(DEFAULT_MODEL_NAME);
- if (manifest.has_keyset)
- model.is_white_label = 1;
- manifest_add_model(&manifest, &model);
- manifest.default_model = manifest.num - 1;
- }
- VB2_DEBUG("%d model(s) loaded.\n", manifest.num);
- if (!manifest.num) {
- ERROR("No valid configurations found from archive.\n");
- return NULL;
- }
-
- new_manifest = (struct manifest *)malloc(sizeof(manifest));
- if (!new_manifest) {
- ERROR("Internal error: memory allocation error.\n");
- return NULL;
- }
- memcpy(new_manifest, &manifest, sizeof(manifest));
- return new_manifest;
-}
-
-/* Releases all resources allocated by given manifest object. */
-void delete_manifest(struct manifest *manifest)
-{
- int i;
- assert(manifest);
- for (i = 0; i < manifest->num; i++) {
- struct model_config *model = &manifest->models[i];
- free(model->name);
- free(model->signature_id);
- free(model->image);
- free(model->ec_image);
- free(model->pd_image);
- free(model->patches.rootkey);
- free(model->patches.vblock_a);
- free(model->patches.vblock_b);
- }
- free(manifest->models);
- free(manifest);
-}
-
-static const char *get_gbb_key_hash(const struct vb2_gbb_header *gbb,
- int32_t offset, int32_t size)
-{
- struct vb2_packed_key *key;
-
- if (!gbb)
- return "<No GBB>";
- key = (struct vb2_packed_key *)((uint8_t *)gbb + offset);
- if (vb2_packed_key_looks_ok(key, size))
- return "<Invalid key>";
- return packed_key_sha1_string(key);
-}
-
-/* Prints the information of given image file in JSON format. */
-static void print_json_image(
- const char *name, const char *fpath, struct model_config *m,
- struct archive *archive, int indent, int is_host)
-{
- struct firmware_image image = {0};
- const struct vb2_gbb_header *gbb = NULL;
- if (!fpath)
- return;
- if (load_firmware_image(&image, fpath, archive))
- return;
- if (!is_host)
- printf(",\n");
- printf("%*s\"%s\": { \"versions\": { \"ro\": \"%s\", \"rw\": \"%s\" },",
- indent, "", name, image.ro_version, image.rw_version_a);
- indent += 2;
- if (!is_host) {
- /* No extra information to be printed */
- } else if (patch_image_by_model(&image, m, archive) != 0) {
- ERROR("Failed to patch images by model: %s\n", m->name);
- } else if (NULL != (gbb = find_gbb(&image))) {
- printf("\n%*s\"keys\": { \"root\": \"%s\", ",
- indent, "",
- get_gbb_key_hash(gbb, gbb->rootkey_offset,
- gbb->rootkey_size));
- printf("\"recovery\": \"%s\" },",
- get_gbb_key_hash(gbb, gbb->recovery_key_offset,
- gbb->recovery_key_size));
- }
- printf("\n%*s\"image\": \"%s\" }", indent, "", fpath);
- free_firmware_image(&image);
-}
-
-/* Prints the information of objects in manifest (models and images) in JSON. */
-void print_json_manifest(const struct manifest *manifest)
-{
- int i, indent;
- struct archive *ar = manifest->archive;
-
- printf("{\n");
- for (i = 0, indent = 2; i < manifest->num; i++) {
- struct model_config *m = &manifest->models[i];
- printf("%s%*s\"%s\": {\n", i ? ",\n" : "", indent, "", m->name);
- indent += 2;
- print_json_image("host", m->image, m, ar, indent, 1);
- print_json_image("ec", m->ec_image, m, ar, indent, 0);
- print_json_image("pd", m->pd_image, m, ar, indent, 0);
- if (m->patches.rootkey) {
- struct patch_config *p = &m->patches;
- printf(",\n%*s\"patches\": { \"rootkey\": \"%s\", "
- "\"vblock_a\": \"%s\", \"vblock_b\": \"%s\" }",
- indent, "", p->rootkey, p->vblock_a,
- p->vblock_b);
- }
- if (m->signature_id)
- printf(",\n%*s\"signature_id\": \"%s\"", indent, "",
- m->signature_id);
- printf("\n }");
- indent -= 2;
- assert(indent == 2);
- }
- printf("\n}\n");
-}
diff --git a/futility/updater_manifest.c b/futility/updater_manifest.c
new file mode 100644
index 0000000..0760cb9
--- /dev/null
+++ b/futility/updater_manifest.c
@@ -0,0 +1,890 @@
+/* Copyright 2022 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.
+ *
+ * Build up the list of updater resources from an archive.
+ */
+
+#include <assert.h>
+#if defined(__OpenBSD__)
+#include <sys/types.h>
+#endif
+
+#ifdef HAVE_CROSID
+#include <crosid.h>
+#endif
+
+#include "updater.h"
+#include "util_misc.h"
+
+/*
+ * The updater reads image files from a package. The package is usually an
+ * archive (see updater_archive.c) with image files and configuration files, and
+ * the meta data is maintained by a "manifest" that described below.
+ *
+ * A package for single board (i.e., not Unified Build) will have all the image
+ * files in top folder:
+ * - host: 'image.bin' (or 'bios.bin' as legacy name before CL:1318712)
+ * - ec: 'ec.bin'
+ * - pd: 'pd.bin'
+ * If custom label is supported, a 'keyset/' folder will be available, with key
+ * files in it:
+ * - rootkey.$CLTAG
+ * - vblock_A.$CLTAG
+ * - vblock_B.$CLTAG
+ * The $CLTAG should come from VPD value 'custom_label_tag'. For legacy devices,
+ * the VPD name may be 'whitelabel_tag', or 'customization_id'.
+ * The 'customization_id' has a different format: LOEM[-VARIANT] and we can only
+ * take LOEM as $CLTAG, for example A-B => $CLTAG=A.
+ *
+ * A package for Unified Build is more complicated. There will be a models/
+ * folder, and each model (by $(mosys platform model) ) should appear as a sub
+ * folder, with a 'setvars.sh' file inside. The 'setvars.sh' is a shell script
+ * describing what files should be used and the signature ID ($SIGID) to use.
+ *
+ * Similar to custom label in non-Unified-Build, the keys and vblock files will
+ * be in 'keyset/' folder:
+ * - rootkey.$SIGID
+ * - vblock_A.$SIGID
+ * - vblock_B.$SIGID
+ * If $SIGID starts with 'sig-id-in-*' then we have to replace it by VPD value
+ * 'custom_label_tag' as '$MODEL-$CLTAG'.
+ */
+
+static const char * const SETVARS_IMAGE_MAIN = "IMAGE_MAIN",
+ * const SETVARS_IMAGE_EC = "IMAGE_EC",
+ * const SETVARS_IMAGE_PD = "IMAGE_PD",
+ * const SETVARS_SIGNATURE_ID = "SIGNATURE_ID",
+ * const SIG_ID_IN_VPD_PREFIX = "sig-id-in",
+ * const DIR_KEYSET = "keyset",
+ * const DIR_MODELS = "models",
+ * const DEFAULT_MODEL_NAME = "default",
+ * const VPD_CUSTOM_LABEL_TAG = "custom_label_tag",
+ * const VPD_CUSTOM_LABEL_TAG_LEGACY = "whitelabel_tag",
+ * const VPD_CUSTOMIZATION_ID = "customization_id",
+ * const ENV_VAR_MODEL_DIR = "${MODEL_DIR}",
+ * const PATH_STARTSWITH_KEYSET = "keyset/",
+ * const PATH_SIGNER_CONFIG = "signer_config.csv",
+ * const PATH_ENDSWITH_SETVARS = "/setvars.sh";
+
+/* Utility function to convert a string. */
+static void str_convert(char *s, int (*convert)(int c))
+{
+ int c;
+
+ for (; *s; s++) {
+ c = *s;
+ if (!isascii(c))
+ continue;
+ *s = convert(c);
+ }
+}
+
+/* Returns 1 if name ends by given pattern, otherwise 0. */
+static int str_endswith(const char *name, const char *pattern)
+{
+ size_t name_len = strlen(name), pattern_len = strlen(pattern);
+ if (name_len < pattern_len)
+ return 0;
+ return strcmp(name + name_len - pattern_len, pattern) == 0;
+}
+
+/* Returns 1 if name starts by given pattern, otherwise 0. */
+static int str_startswith(const char *name, const char *pattern)
+{
+ return strncmp(name, pattern, strlen(pattern)) == 0;
+}
+
+/* Returns the VPD value by given key name, or NULL on error (or no value). */
+static char *vpd_get_value(const char *fpath, const char *key)
+{
+ char *command, *result;
+
+ assert(fpath);
+ ASPRINTF(&command, "vpd -g %s -f %s 2>/dev/null", key, fpath);
+ result = host_shell(command);
+ free(command);
+
+ if (result && !*result) {
+ free(result);
+ result = NULL;
+ }
+ return result;
+}
+
+/*
+ * Reads and parses a setvars type file from archive, then stores into config.
+ * Returns 0 on success (at least one entry found), otherwise failure.
+ */
+static int model_config_parse_setvars_file(
+ struct model_config *cfg, struct u_archive *archive,
+ const char *fpath)
+{
+ uint8_t *data;
+ uint32_t len;
+
+ char *ptr_line = NULL, *ptr_token = NULL;
+ char *line, *k, *v;
+ int valid = 0;
+
+ if (archive_read_file(archive, fpath, &data, &len, NULL) != 0) {
+ ERROR("Failed reading: %s\n", fpath);
+ return -1;
+ }
+
+ /* Valid content should end with \n, or \"; ensure ASCIIZ for parsing */
+ if (len)
+ data[len - 1] = '\0';
+
+ for (line = strtok_r((char *)data, "\n\r", &ptr_line); line;
+ line = strtok_r(NULL, "\n\r", &ptr_line)) {
+ char *expand_path = NULL;
+ int found_valid = 1;
+
+ /* Format: KEY="value" */
+ k = strtok_r(line, "=", &ptr_token);
+ if (!k)
+ continue;
+ v = strtok_r(NULL, "\"", &ptr_token);
+ if (!v)
+ continue;
+
+ /* Some legacy updaters may be still using ${MODEL_DIR}. */
+ if (str_startswith(v, ENV_VAR_MODEL_DIR)) {
+ ASPRINTF(&expand_path, "%s/%s%s", DIR_MODELS, cfg->name,
+ v + strlen(ENV_VAR_MODEL_DIR));
+ }
+
+ if (strcmp(k, SETVARS_IMAGE_MAIN) == 0)
+ cfg->image = strdup(v);
+ else if (strcmp(k, SETVARS_IMAGE_EC) == 0)
+ cfg->ec_image = strdup(v);
+ else if (strcmp(k, SETVARS_IMAGE_PD) == 0)
+ cfg->pd_image = strdup(v);
+ else if (strcmp(k, SETVARS_SIGNATURE_ID) == 0) {
+ cfg->signature_id = strdup(v);
+ if (str_startswith(v, SIG_ID_IN_VPD_PREFIX))
+ cfg->is_custom_label = 1;
+ } else
+ found_valid = 0;
+ free(expand_path);
+ valid += found_valid;
+ }
+ free(data);
+ return valid == 0;
+}
+
+/*
+ * Changes the rootkey in firmware GBB to given new key.
+ * Returns 0 on success, otherwise failure.
+ */
+static int change_gbb_rootkey(struct firmware_image *image,
+ const char *section_name,
+ const uint8_t *rootkey, uint32_t rootkey_len)
+{
+ const struct vb2_gbb_header *gbb = find_gbb(image);
+ uint8_t *gbb_rootkey;
+ if (!gbb) {
+ ERROR("Cannot find GBB in image %s.\n", image->file_name);
+ return -1;
+ }
+ if (gbb->rootkey_size < rootkey_len) {
+ ERROR("New root key (%u bytes) larger than GBB (%u bytes).\n",
+ rootkey_len, gbb->rootkey_size);
+ return -1;
+ }
+
+ gbb_rootkey = (uint8_t *)gbb + gbb->rootkey_offset;
+ /* See cmd_gbb_utility: root key must be first cleared with zero. */
+ memset(gbb_rootkey, 0, gbb->rootkey_size);
+ memcpy(gbb_rootkey, rootkey, rootkey_len);
+ return 0;
+}
+
+/*
+ * Changes the VBlock in firmware section to new data.
+ * Returns 0 on success, otherwise failure.
+ */
+static int change_vblock(struct firmware_image *image, const char *section_name,
+ const uint8_t *vblock, uint32_t vblock_len)
+{
+ struct firmware_section section;
+
+ find_firmware_section(§ion, image, section_name);
+ if (!section.data) {
+ ERROR("Need section %s in image %s.\n", section_name,
+ image->file_name);
+ return -1;
+ }
+ if (section.size < vblock_len) {
+ ERROR("'%s' is too small (%zu bytes) for vblock (%u bytes).\n",
+ section_name, section.size, vblock_len);
+ return -1;
+ }
+ memcpy(section.data, vblock, vblock_len);
+ return 0;
+}
+
+/*
+ * Applies a key file to firmware image.
+ * Returns 0 on success, otherwise failure.
+ */
+static int apply_key_file(
+ struct firmware_image *image, const char *path,
+ struct u_archive *archive, const char *section_name,
+ int (*apply)(struct firmware_image *image, const char *section,
+ const uint8_t *data, uint32_t len))
+{
+ int r = 0;
+ uint8_t *data = NULL;
+ uint32_t len;
+
+ r = archive_read_file(archive, path, &data, &len, NULL);
+ if (r == 0) {
+ VB2_DEBUG("Loaded file: %s\n", path);
+ r = apply(image, section_name, data, len);
+ if (r)
+ ERROR("Failed applying %s to %s\n", path, section_name);
+ } else {
+ ERROR("Failed reading: %s\n", path);
+ }
+ free(data);
+ return r;
+}
+
+/*
+ * Modifies a firmware image from patch information specified in model config.
+ * Returns 0 on success, otherwise number of failures.
+ */
+int patch_image_by_model(
+ struct firmware_image *image, const struct model_config *model,
+ struct u_archive *archive)
+{
+ int err = 0;
+ if (model->patches.rootkey)
+ err += !!apply_key_file(
+ image, model->patches.rootkey, archive,
+ FMAP_RO_GBB, change_gbb_rootkey);
+ if (model->patches.vblock_a)
+ err += !!apply_key_file(
+ image, model->patches.vblock_a, archive,
+ FMAP_RW_VBLOCK_A, change_vblock);
+ if (model->patches.vblock_b)
+ err += !!apply_key_file(
+ image, model->patches.vblock_b, archive,
+ FMAP_RW_VBLOCK_B, change_vblock);
+ return err;
+}
+
+/*
+ * Finds available patch files by given model.
+ * Updates `model` argument with path of patch files.
+ */
+static void find_patches_for_model(struct model_config *model,
+ struct u_archive *archive,
+ const char *signature_id)
+{
+ char *path;
+ int i;
+
+ const char * const names[] = {
+ "rootkey",
+ "vblock_A",
+ "vblock_B",
+ };
+
+ char **targets[] = {
+ &model->patches.rootkey,
+ &model->patches.vblock_a,
+ &model->patches.vblock_b,
+ };
+
+ assert(ARRAY_SIZE(names) == ARRAY_SIZE(targets));
+ for (i = 0; i < ARRAY_SIZE(names); i++) {
+ ASPRINTF(&path, "%s/%s.%s", DIR_KEYSET, names[i], signature_id);
+ if (archive_has_entry(archive, path))
+ *targets[i] = path;
+ else
+ free(path);
+ }
+}
+
+/*
+ * Adds and copies one new model config to the existing list of given manifest.
+ * Returns a pointer to the newly allocated config, or NULL on failure.
+ */
+static struct model_config *manifest_add_model(
+ struct manifest *manifest,
+ const struct model_config *cfg)
+{
+ struct model_config *model;
+ manifest->num++;
+ manifest->models = (struct model_config *)realloc(
+ manifest->models, manifest->num * sizeof(*model));
+ if (!manifest->models) {
+ ERROR("Internal error: failed to allocate buffer.\n");
+ return NULL;
+ }
+ model = &manifest->models[manifest->num - 1];
+ memcpy(model, cfg, sizeof(*model));
+ return model;
+}
+
+/*
+ * A callback function for manifest to scan files in archive.
+ * Returns 0 to keep scanning, or non-zero to stop.
+ */
+static int manifest_scan_entries(const char *name, void *arg)
+{
+ struct manifest *manifest = (struct manifest *)arg;
+ struct u_archive *archive = manifest->archive;
+ struct model_config model = {0};
+ char *slash;
+
+ if (str_startswith(name, PATH_STARTSWITH_KEYSET))
+ manifest->has_keyset = 1;
+ if (!str_endswith(name, PATH_ENDSWITH_SETVARS))
+ return 0;
+
+ /* name: models/$MODEL/setvars.sh */
+ model.name = strdup(strchr(name, '/') + 1);
+ slash = strchr(model.name, '/');
+ if (slash)
+ *slash = '\0';
+
+ VB2_DEBUG("Found model <%s> setvars: %s\n", model.name, name);
+ if (model_config_parse_setvars_file(&model, archive, name)) {
+ ERROR("Invalid setvars file: %s\n", name);
+ return 0;
+ }
+
+ /* In legacy setvars.sh, the ec_image and pd_image may not exist. */
+ if (model.ec_image && !archive_has_entry(archive, model.ec_image)) {
+ VB2_DEBUG("Ignore non-exist EC image: %s\n", model.ec_image);
+ free(model.ec_image);
+ model.ec_image = NULL;
+ }
+ if (model.pd_image && !archive_has_entry(archive, model.pd_image)) {
+ VB2_DEBUG("Ignore non-exist PD image: %s\n", model.pd_image);
+ free(model.pd_image);
+ model.pd_image = NULL;
+ }
+
+ /* Find patch files. */
+ if (model.signature_id)
+ find_patches_for_model(&model, archive, model.signature_id);
+
+ return !manifest_add_model(manifest, &model);
+}
+
+/*
+ * A callback function for manifest to scan files in raw /firmware archive.
+ * Returns 0 to keep scanning, or non-zero to stop.
+ */
+static int manifest_scan_raw_entries(const char *name, void *arg)
+{
+ struct manifest *manifest = (struct manifest *)arg;
+ struct u_archive *archive = manifest->archive;
+ struct model_config model = {0};
+ char *ec_name = NULL;
+ int chars_read = 0;
+
+ /*
+ * /build/$BOARD/firmware (or CPFE firmware archives) layout:
+ * - image-${MODEL}{,.serial,.dev...}.bin
+ * - ${MODEL}/ec.bin
+ */
+
+ if (sscanf(name, "image-%m[^.].bin%n", &model.name, &chars_read) != 1)
+ return 0;
+
+ /* Ignore the names with extra modifiers like image-$MODEL.serial.bin */
+ if (!chars_read || name[chars_read]) {
+ free(model.name);
+ return 0;
+ }
+
+ VB2_DEBUG("Found model <%s>: %s\n", model.name, name);
+ model.image = strdup(name);
+
+ ASPRINTF(&ec_name, "%s/ec.bin", model.name);
+ if (archive_has_entry(archive, ec_name))
+ model.ec_image = strdup(ec_name);
+ free(ec_name);
+
+ return !manifest_add_model(manifest, &model);
+}
+
+/* Returns the matched model config from the manifest, or NULL if not found. */
+static struct model_config *manifest_get_model_config(
+ const struct manifest *manifest, const char *name)
+{
+ int i = 0;
+
+ for (i = 0; i < manifest->num; i++) {
+ if (!strcmp(name, manifest->models[i].name))
+ return &manifest->models[i];
+ }
+ return NULL;
+}
+
+/*
+ * Creates the manifest from the 'signer_config.csv' file.
+ * Returns 0 on success (loaded), otherwise failure.
+ */
+static int manifest_from_signer_config(struct manifest *manifest)
+{
+ struct u_archive *archive = manifest->archive;
+ uint32_t size;
+ uint8_t *data;
+ char *s, *tok_ptr = NULL;
+
+ if (!archive_has_entry(archive, PATH_SIGNER_CONFIG))
+ return -1;
+
+ /*
+ * CSV format: model_name,firmware_image,key_id,ec_image
+ *
+ * Note the key_id is not signature_id and won't be used, and ec_image
+ * may be optional (for example sarien).
+ */
+
+ if (archive_read_file(archive, PATH_SIGNER_CONFIG, &data, &size,NULL)) {
+ ERROR("Failed reading: %s\n", PATH_SIGNER_CONFIG);
+ return -1;
+ }
+
+ /* Skip headers. */
+ s = strtok_r((char *)data, "\n", &tok_ptr);
+ if (!s || !strchr(s, ',')) {
+ ERROR("Invalid %s: missing header.\n", PATH_SIGNER_CONFIG);
+ free(data);
+ return -1;
+ }
+
+ for (s = strtok_r(NULL, "\n", &tok_ptr); s != NULL;
+ s = strtok_r(NULL, "\n", &tok_ptr)) {
+
+ struct model_config model = {0};
+ int discard_model = 0;
+
+ /*
+ * Both keyid (%3) and ec_image (%4) are optional so we want to
+ * read at least 2 fields.
+ */
+ if (sscanf(s, "%m[^,],%m[^,],%*[^,],%m[^,]",
+ &model.name, &model.image, &model.ec_image) < 2) {
+ ERROR("Invalid entry(%s): %s\n", PATH_SIGNER_CONFIG, s);
+ discard_model = 1;
+ } else if (strchr(model.name, '-')) {
+ /* format: BaseModel-CustomLabel */
+ char *tok_dash;
+ char *base_model;
+ struct model_config *base_model_config;
+
+ VB2_DEBUG("Found custom-label: %s\n", model.name);
+ discard_model = 1;
+ base_model = strtok_r(model.name, "-", &tok_dash);
+ assert(base_model);
+
+ /*
+ * Currently we assume the base model (e.g., base_model)
+ * is always listed before CL models in the CSV file -
+ * this is based on how the signerbot and the
+ * chromeos-config works today (validated on octopus).
+ */
+ base_model_config = manifest_get_model_config(
+ manifest, base_model);
+
+ if (!base_model_config) {
+ ERROR("Invalid CL-model: %s\n", base_model);
+ } else if (!base_model_config->is_custom_label) {
+ base_model_config->is_custom_label = 1;
+ /*
+ * Rewriting signature_id is not necessary,
+ * but in order to generate the same manifest
+ * from setvars, we want to temporarily use
+ * the special value.
+ */
+ free(base_model_config->signature_id);
+ base_model_config->signature_id = strdup(
+ "sig-id-in-customization-id");
+ }
+ }
+
+ if (discard_model) {
+ free(model.name);
+ free(model.image);
+ free(model.ec_image);
+ continue;
+ }
+
+ model.signature_id = strdup(model.name);
+ if (!manifest_add_model(manifest, &model))
+ break;
+ }
+ free(data);
+ return 0;
+}
+
+/*
+ * Creates the manifest from a simple (legacy) folder with only 1 set of
+ * firmware images.
+ * Returns 0 on success (loaded), otherwise failure.
+ */
+static int manifest_from_simple_folder(struct manifest *manifest)
+{
+ const char * const host_image_name = "image.bin",
+ * const old_host_image_name = "bios.bin",
+ * const ec_name = "ec.bin",
+ * const pd_name = "pd.bin";
+ struct u_archive *archive = manifest->archive;
+ const char *image_name = NULL;
+ struct firmware_image image = {0};
+ struct model_config model = {0};
+
+ /* Try to load from current folder. */
+ if (archive_has_entry(archive, old_host_image_name))
+ image_name = old_host_image_name;
+ else if (archive_has_entry(archive, host_image_name))
+ image_name = host_image_name;
+ else
+ return 1;
+
+ model.image = strdup(image_name);
+ if (archive_has_entry(archive, ec_name))
+ model.ec_image = strdup(ec_name);
+ if (archive_has_entry(archive, pd_name))
+ model.pd_image = strdup(pd_name);
+ /* Extract model name from FWID: $Vendor_$Platform.$Version */
+ if (!load_firmware_image(&image, image_name, archive)) {
+ char *token = NULL;
+ if (strtok(image.ro_version, "_"))
+ token = strtok(NULL, ".");
+ if (token && *token) {
+ str_convert(token, tolower);
+ model.name = strdup(token);
+ }
+ free_firmware_image(&image);
+ }
+ if (!model.name)
+ model.name = strdup(DEFAULT_MODEL_NAME);
+ if (manifest->has_keyset)
+ model.is_custom_label = 1;
+ manifest_add_model(manifest, &model);
+ manifest->default_model = manifest->num - 1;
+
+ return 0;
+}
+
+/**
+ * get_manifest_key() - Wrapper to get the firmware manifest key from crosid
+ *
+ * @manifest_key_out - Output parameter of the firmware manifest key.
+ *
+ * Returns:
+ * - <0 if libcrosid is unavailable or there was an error reading
+ * device data
+ * - >=0 (the matched device index) success
+ */
+static int get_manifest_key(char **manifest_key_out)
+{
+#ifdef HAVE_CROSID
+ return crosid_get_firmware_manifest_key(manifest_key_out);
+#else
+ ERROR("This version of futility was compiled without libcrosid "
+ "(perhaps compiled outside of the Chrome OS build system?) and "
+ "the update command is not fully supported. Either compile "
+ "from the Chrome OS build, or pass --model to manually specify "
+ "the machine model.\n");
+ return -1;
+#endif
+}
+
+/*
+ * Finds the existing model_config from manifest that best matches current
+ * system (as defined by model_name).
+ * Returns a model_config from manifest, or NULL if not found.
+ */
+const struct model_config *manifest_find_model(const struct manifest *manifest,
+ const char *model_name)
+{
+ char *manifest_key = NULL;
+ const struct model_config *model = NULL;
+ int i;
+ int matched_index;
+
+ /*
+ * For manifest with single model defined, we should just return because
+ * there are other mechanisms like platform name check to double confirm
+ * if the firmware is valid.
+ */
+ if (manifest->num == 1)
+ return &manifest->models[0];
+
+ if (!model_name) {
+ matched_index = get_manifest_key(&manifest_key);
+ if (matched_index < 0) {
+ ERROR("Failed to get device identity. "
+ "Run \"crosid -v\" for explanation.\n");
+ return NULL;
+ }
+
+ INFO("Identified the device using libcrosid, "
+ "matched chromeos-config index: %d, "
+ "manifest key (model): %s\n",
+ matched_index, manifest_key);
+ model_name = manifest_key;
+ }
+
+ model = manifest_get_model_config(manifest, model_name);
+
+ if (!model) {
+ ERROR("Unsupported model: '%s'.\n", model_name);
+
+ fprintf(stderr,
+ "The firmware manifest key '%s' is not present in this "
+ "updater archive. The known keys to this updater "
+ "archive are:\n", model_name);
+
+ for (i = 0; i < manifest->num; i++)
+ fprintf(stderr, " %s", manifest->models[i].name);
+ fprintf(stderr, "\n\n");
+ fprintf(stderr,
+ "Perhaps you are trying to use an updater archive for "
+ "the wrong board, or designed for an older OS version "
+ "before this model was supported.\n");
+ fprintf(stderr,
+ "Hint: Read the FIRMWARE_MANIFEST_KEY from the output "
+ "of the crosid command.\n");
+ }
+
+
+ free(manifest_key);
+ return model;
+}
+
+/*
+ * Determines the signature ID to use for custom label.
+ * Returns the signature ID for looking up rootkey and vblock files.
+ * Caller must free the returned string.
+ */
+static char *resolve_signature_id(struct model_config *model, const char *image)
+{
+ int is_unibuild = model->signature_id ? 1 : 0;
+ char *tag = vpd_get_value(image, VPD_CUSTOM_LABEL_TAG);
+ char *sig_id = NULL;
+
+ if (tag == NULL)
+ tag = vpd_get_value(image, VPD_CUSTOM_LABEL_TAG_LEGACY);
+
+ /* Unified build: $model.$tag, or $model (b/126800200). */
+ if (is_unibuild) {
+ if (!tag) {
+ WARN("No VPD '%s' set for custom label. "
+ "Use model name '%s' as default.\n",
+ VPD_CUSTOM_LABEL_TAG, model->name);
+ return strdup(model->name);
+ }
+
+ ASPRINTF(&sig_id, "%s-%s", model->name, tag);
+ free(tag);
+ return sig_id;
+ }
+
+ /* Non-Unibuild: Upper($tag), or Upper(${cid%%-*}). */
+ if (!tag) {
+ char *cid = vpd_get_value(image, VPD_CUSTOMIZATION_ID);
+ if (cid) {
+ /* customization_id in format LOEM[-VARIANT]. */
+ char *dash = strchr(cid, '-');
+ if (dash)
+ *dash = '\0';
+ tag = cid;
+ }
+ }
+ if (tag)
+ str_convert(tag, toupper);
+ return tag;
+}
+
+/*
+ * Applies custom label information to an existing model configuration.
+ * Collects signature ID information from either parameter signature_id or
+ * image file (via VPD) and updates model.patches for key files.
+ * Returns 0 on success, otherwise failure.
+ */
+int model_apply_custom_label(
+ struct model_config *model,
+ struct u_archive *archive,
+ const char *signature_id,
+ const char *image)
+{
+ char *sig_id = NULL;
+ int r = 0;
+
+ if (!signature_id) {
+ sig_id = resolve_signature_id(model, image);
+ signature_id = sig_id;
+ }
+
+ if (signature_id) {
+ VB2_DEBUG("Find custom label patches by signature ID: '%s'.\n",
+ signature_id);
+ find_patches_for_model(model, archive, signature_id);
+ } else {
+ signature_id = "";
+ WARN("No VPD '%s' set for custom label - use default keys.\n",
+ VPD_CUSTOM_LABEL_TAG);
+ }
+ if (!model->patches.rootkey) {
+ ERROR("No keys found for signature_id: '%s'\n", signature_id);
+ r = 1;
+ } else {
+ INFO("Applied for custom label: %s\n", signature_id);
+ }
+ free(sig_id);
+ return r;
+}
+
+/*
+ * Creates a new manifest object by scanning files in archive.
+ * Returns the manifest on success, otherwise NULL for failure.
+ */
+struct manifest *new_manifest_from_archive(struct u_archive *archive)
+{
+ struct manifest manifest = {0}, *new_manifest;
+
+ manifest.archive = archive;
+ manifest.default_model = -1;
+
+ VB2_DEBUG("Try to build a manifest from *%s\n", PATH_ENDSWITH_SETVARS);
+ archive_walk(archive, &manifest, manifest_scan_entries);
+
+ if (manifest.num == 0) {
+ VB2_DEBUG("Try to build a manifest from %s\n",
+ PATH_SIGNER_CONFIG);
+ manifest_from_signer_config(&manifest);
+ }
+ if (manifest.num == 0) {
+ VB2_DEBUG("Try to build a manifest from a */firmware folder\n");
+ archive_walk(archive, &manifest, manifest_scan_raw_entries);
+ }
+ if (manifest.num == 0) {
+ VB2_DEBUG("Try to build a manifest from a simple folder\n");
+ manifest_from_simple_folder(&manifest);
+ }
+
+ VB2_DEBUG("%d model(s) loaded.\n", manifest.num);
+ if (!manifest.num) {
+ ERROR("No valid configurations found from archive.\n");
+ return NULL;
+ }
+
+ new_manifest = (struct manifest *)malloc(sizeof(manifest));
+ if (!new_manifest) {
+ ERROR("Internal error: memory allocation error.\n");
+ return NULL;
+ }
+ memcpy(new_manifest, &manifest, sizeof(manifest));
+ return new_manifest;
+}
+
+/* Releases all resources allocated by given manifest object. */
+void delete_manifest(struct manifest *manifest)
+{
+ int i;
+ assert(manifest);
+ for (i = 0; i < manifest->num; i++) {
+ struct model_config *model = &manifest->models[i];
+ free(model->name);
+ free(model->signature_id);
+ free(model->image);
+ free(model->ec_image);
+ free(model->pd_image);
+ free(model->patches.rootkey);
+ free(model->patches.vblock_a);
+ free(model->patches.vblock_b);
+ }
+ free(manifest->models);
+ free(manifest);
+}
+
+static const char *get_gbb_key_hash(const struct vb2_gbb_header *gbb,
+ int32_t offset, int32_t size)
+{
+ struct vb2_packed_key *key;
+
+ if (!gbb)
+ return "<No GBB>";
+ key = (struct vb2_packed_key *)((uint8_t *)gbb + offset);
+ if (vb2_packed_key_looks_ok(key, size))
+ return "<Invalid key>";
+ return packed_key_sha1_string(key);
+}
+
+/* Prints the information of given image file in JSON format. */
+static void print_json_image(
+ const char *name, const char *fpath, struct model_config *m,
+ struct u_archive *archive, int indent, int is_host)
+{
+ struct firmware_image image = {0};
+ const struct vb2_gbb_header *gbb = NULL;
+ if (!fpath)
+ return;
+ if (load_firmware_image(&image, fpath, archive))
+ return;
+ if (!is_host)
+ printf(",\n");
+ printf("%*s\"%s\": { \"versions\": { \"ro\": \"%s\", \"rw\": \"%s\" },",
+ indent, "", name, image.ro_version, image.rw_version_a);
+ indent += 2;
+ if (is_host) {
+ if (patch_image_by_model(&image, m, archive))
+ ERROR("Failed to patch images by model: %s\n", m->name);
+ else
+ gbb = find_gbb(&image);
+ }
+ if (gbb != NULL) {
+ printf("\n%*s\"keys\": { \"root\": \"%s\", ",
+ indent, "",
+ get_gbb_key_hash(gbb, gbb->rootkey_offset,
+ gbb->rootkey_size));
+ printf("\"recovery\": \"%s\" },",
+ get_gbb_key_hash(gbb, gbb->recovery_key_offset,
+ gbb->recovery_key_size));
+ }
+ printf("\n%*s\"image\": \"%s\" }", indent, "", fpath);
+ free_firmware_image(&image);
+}
+
+/* Prints the information of objects in manifest (models and images) in JSON. */
+void print_json_manifest(const struct manifest *manifest)
+{
+ int i, indent;
+ struct u_archive *ar = manifest->archive;
+
+ printf("{\n");
+ for (i = 0, indent = 2; i < manifest->num; i++) {
+ struct model_config *m = &manifest->models[i];
+ printf("%s%*s\"%s\": {\n", i ? ",\n" : "", indent, "", m->name);
+ indent += 2;
+ print_json_image("host", m->image, m, ar, indent, 1);
+ print_json_image("ec", m->ec_image, m, ar, indent, 0);
+ print_json_image("pd", m->pd_image, m, ar, indent, 0);
+ if (m->patches.rootkey) {
+ struct patch_config *p = &m->patches;
+ printf(",\n%*s\"patches\": { \"rootkey\": \"%s\", "
+ "\"vblock_a\": \"%s\", \"vblock_b\": \"%s\" }",
+ indent, "", p->rootkey, p->vblock_a,
+ p->vblock_b);
+ }
+ if (m->signature_id)
+ printf(",\n%*s\"signature_id\": \"%s\"", indent, "",
+ m->signature_id);
+ printf("\n }");
+ indent -= 2;
+ assert(indent == 2);
+ }
+ printf("\n}\n");
+}
diff --git a/futility/updater_quirks.c b/futility/updater_quirks.c
index c8140c1..73b7c2f 100644
--- a/futility/updater_quirks.c
+++ b/futility/updater_quirks.c
@@ -56,18 +56,23 @@
{ .match = "Google_Scarlet.", .quirks = "min_platform_version=1" },
{ .match = "Google_Trogdor.", .quirks = "min_platform_version=2" },
- /* Legacy white label units. */
- { .match = "Google_Enguarde.", .quirks = "allow_empty_wltag" },
- { .match = "Google_Expresso.", .quirks = "allow_empty_wltag" },
- { .match = "Google_Hana.", .quirks = "allow_empty_wltag" },
- { .match = "Google_Veyron_Jaq.", .quirks = "allow_empty_wltag" },
- { .match = "Google_Veyron_Jerry.", .quirks = "allow_empty_wltag" },
- { .match = "Google_Veyron_Mighty.", .quirks = "allow_empty_wltag" },
- { .match = "Google_Reks.", .quirks = "allow_empty_wltag" },
- { .match = "Google_Relm.", .quirks = "allow_empty_wltag" },
- { .match = "Google_Wizpig.", .quirks = "allow_empty_wltag" },
+ /* Legacy custom label units. */
+ { .match = "Google_Hana.", .quirks = "allow_empty_custom_label_tag" },
+ { .match = "Google_Reks.", .quirks = "allow_empty_custom_label_tag" },
+ { .match = "Google_Relm.", .quirks = "allow_empty_custom_label_tag" },
+ { .match = "Google_Wizpig.", .quirks = "allow_empty_custom_label_tag" },
+ { .match = "Google_Enguarde.",
+ .quirks = "allow_empty_custom_label_tag" },
+ { .match = "Google_Expresso.",
+ .quirks = "allow_empty_custom_label_tag" },
+ { .match = "Google_Veyron_Jaq.",
+ .quirks = "allow_empty_custom_label_tag" },
+ { .match = "Google_Veyron_Jerry.",
+ .quirks = "allow_empty_custom_label_tag" },
+ { .match = "Google_Veyron_Mighty.",
+ .quirks = "allow_empty_custom_label_tag" },
- { .match = "Google_Phaser.", .quirks = "override_signature_id" },
+ { .match = "Google_Phaser.", .quirks = "override_signature_id" },
};
/* Preserves meta data and reload image contents from given file path. */
@@ -479,9 +484,9 @@
"dedicated FMAP section.";
quirks->apply = quirk_eve_smm_store;
- quirks = &cfg->quirks[QUIRK_ALLOW_EMPTY_WLTAG];
- quirks->name = "allow_empty_wltag";
- quirks->help = "chromium/906962; allow devices without white label "
+ quirks = &cfg->quirks[QUIRK_ALLOW_EMPTY_CUSTOM_LABEL_TAG];
+ quirks->name = "allow_empty_custom_label_tag";
+ quirks->help = "chromium/906962; allow devices without custom label "
"tags set to use default keys.";
quirks->apply = NULL; /* Simple config. */
@@ -516,6 +521,11 @@
quirks->name = "extra_retries";
quirks->help = "Extra retries when writing to system firmware.";
quirks->apply = NULL; /* Simple config. */
+
+ quirks = &cfg->quirks[QUIRK_EXTERNAL_FLASHROM];
+ quirks->name = "external_flashrom";
+ quirks->help = "Use external flashrom to access the system firmware.";
+ quirks->apply = NULL; /* Simple config. */
}
/*
diff --git a/futility/updater_utils.c b/futility/updater_utils.c
index 18e4000..d879f78 100644
--- a/futility/updater_utils.c
+++ b/futility/updater_utils.c
@@ -209,7 +209,7 @@
* failure, or IMAGE_PARSE_FAILURE for non-vboot images.
*/
int load_firmware_image(struct firmware_image *image, const char *file_name,
- struct archive *archive)
+ struct u_archive *archive)
{
if (!file_name) {
ERROR("No file name given\n");
@@ -419,7 +419,7 @@
static int host_get_wp_hw(void)
{
/* wpsw refers to write protection 'switch', not 'software'. */
- return VbGetSystemPropertyInt("wpsw_cur");
+ return VbGetSystemPropertyInt("wpsw_cur") ? WP_ENABLED : WP_DISABLED;
}
/* A helper function to return "fw_vboot2" system property. */
@@ -456,16 +456,21 @@
* Helper function to detect type of Servo board attached to host.
* Returns a string as programmer parameter on success, otherwise NULL.
*/
-char *host_detect_servo(int *need_prepare_ptr)
+char *host_detect_servo(const char **prepare_ctrl_name)
{
const char *servo_port = getenv(ENV_SERVOD_PORT);
const char *servo_name = getenv(ENV_SERVOD_NAME);
char *servo_type = host_shell("dut-control -o servo_type 2>/dev/null");
const char *programmer = NULL;
char *ret = NULL;
- int need_prepare = 0; /* To prepare by dut-control cpu_fw_spi:on */
char *servo_serial = NULL;
+ static const char * const cpu_fw_spi = "cpu_fw_spi";
+ static const char * const ccd_cpu_fw_spi = "ccd_cpu_fw_spi";
+
+ /* By default, no control is needed. */
+ *prepare_ctrl_name = NULL;
+
/* Get serial name if servo port is provided. */
if ((servo_port && *servo_port) || (servo_name && *servo_name)) {
const char *cmd = "dut-control -o serialname 2>/dev/null";
@@ -475,6 +480,9 @@
if (strstr(servo_type, "with_servo_micro"))
cmd = ("dut-control -o servo_micro_serialname"
" 2>/dev/null");
+ else if (strstr(servo_type, "with_c2d2"))
+ cmd = ("dut-control -o c2d2_serialname"
+ " 2>/dev/null");
else if (strstr(servo_type, "with_ccd"))
cmd = "dut-control -o ccd_serialname 2>/dev/null";
@@ -489,15 +497,20 @@
} else if (strstr(servo_type, "servo_micro")) {
VB2_DEBUG("Selected Servo Micro.\n");
programmer = "raiden_debug_spi";
- need_prepare = 1;
+ *prepare_ctrl_name = cpu_fw_spi;
+ } else if (strstr(servo_type, "c2d2")) {
+ VB2_DEBUG("Selected C2D2.\n");
+ programmer = "raiden_debug_spi";
+ *prepare_ctrl_name = cpu_fw_spi;
} else if (strstr(servo_type, "ccd_cr50") ||
strstr(servo_type, "ccd_gsc")) {
VB2_DEBUG("Selected CCD.\n");
- programmer = "raiden_debug_spi:target=AP";
+ programmer = "raiden_debug_spi:target=AP,custom_rst=true";
+ *prepare_ctrl_name = ccd_cpu_fw_spi;
} else {
VB2_DEBUG("Selected Servo V2.\n");
programmer = "ft2232_spi:type=google-servo-v2";
- need_prepare = 1;
+ *prepare_ctrl_name = cpu_fw_spi;
}
if (programmer) {
@@ -513,29 +526,250 @@
free(servo_type);
free(servo_serial);
- *need_prepare_ptr = need_prepare;
return ret;
}
+/*
+ * Returns 1 if the programmers in image1 and image2 are the same.
+ */
+static int is_the_same_programmer(const struct firmware_image *image1,
+ const struct firmware_image *image2)
+{
+ assert(image1 && image2);
+
+ /* Including if both are NULL. */
+ if (image1->programmer == image2->programmer)
+ return 1;
+
+ /* Not the same if either one is NULL. */
+ if (!image1->programmer || !image2->programmer)
+ return 0;
+
+ return strcmp(image1->programmer, image2->programmer) == 0;
+}
+
+enum flash_command {
+ FLASH_READ = 0,
+ FLASH_WRITE,
+};
+
+/* Converts the flashrom_params to an equivalent flashrom command. */
+static char *get_flashrom_command(enum flash_command flash_cmd,
+ struct flashrom_params *params,
+ const char *image_name,
+ const char *contents_name)
+{
+ int i, len = 0;
+ char *partial = NULL;
+ char *cmd = NULL;
+
+ if (!image_name)
+ image_name = "<IMAGE>";
+ if (!contents_name)
+ contents_name = "<OLD-IMAGE>";
+
+ for (i = 0; params->regions && params->regions[i]; i++)
+ len += strlen(params->regions[i]) + strlen(" -i ");
+
+ if (len) {
+ partial = (char *)malloc(len + 1);
+ if (!partial) {
+ ERROR("Failed to allocate a string buffer.\n");
+ return NULL;
+ }
+
+ partial[0] = '\0';
+ for (i = 0; params->regions[i]; i++) {
+ strcat(partial, " -i ");
+ strcat(partial, params->regions[i]);
+ }
+ assert(strlen(partial) == len);
+ }
+
+ switch (flash_cmd) {
+ case FLASH_READ:
+ ASPRINTF(&cmd, "flashrom -r %s -p %s%s%s",
+ image_name,
+ params->image->programmer,
+ params->verbose > 1 ? " -V" : "",
+ partial ? partial : "");
+ break;
+
+ case FLASH_WRITE:
+ ASPRINTF(&cmd, "flashrom -w %s -p %s%s%s%s%s%s",
+ image_name,
+ params->image->programmer,
+ params->flash_contents ? " --flash-contents " : "",
+ params->flash_contents ? contents_name : "",
+ params->noverify ? " --noverify" : "",
+ params->verbose > 1 ? " -V" : "",
+ partial ? partial : "");
+ break;
+
+ default:
+ ERROR("Unknown command: %d.\n", flash_cmd);
+ break;
+ }
+ free(partial);
+ return cmd;
+}
+
+/*
+ * Emulates writing a firmware image to the system.
+ * Returns 0 if success, non-zero if error.
+ */
+static int emulate_write_firmware(const char *filename,
+ const struct firmware_image *image,
+ const char * const sections[])
+{
+ int i, errorcnt = 0;
+ struct firmware_image to_image = {0};
+
+ INFO("Writing from %s to %s (emu=%s).\n",
+ image->file_name, image->programmer, filename);
+
+ if (load_firmware_image(&to_image, filename, NULL)) {
+ ERROR("Cannot load image from %s.\n", filename);
+ return -1;
+ }
+
+ if (image->size != to_image.size) {
+ ERROR("Image size is different (%s:%d != %s:%d)\n",
+ image->file_name, image->size, to_image.file_name,
+ to_image.size);
+ errorcnt++;
+ goto exit;
+ }
+
+ if (!sections) {
+ VB2_DEBUG(" - write the whole image.\n");
+ memmove(to_image.data, image->data, image->size);
+ }
+ for (i = 0; sections && sections[i]; i++) {
+ VB2_DEBUG(" - write the section: %s.\n", sections[i]);
+ if (preserve_firmware_section(image, &to_image, sections[i])) {
+ ERROR("Failed to write the section: %s\n", sections[i]);
+ errorcnt++;
+ /*
+ * Exit the loop, but still write the file to reflect
+ * the partial changes - same as real flashrom behavior.
+ */
+ break;
+ }
+ }
+
+ if (vb2_write_file(filename, to_image.data, to_image.size)) {
+ ERROR("Failed writing to file: %s\n", filename);
+ errorcnt++;
+ goto exit;
+ }
+
+exit:
+ free_firmware_image(&to_image);
+ return errorcnt;
+}
+
+static int external_flashrom(enum flash_command flash_cmd,
+ struct flashrom_params *params,
+ struct tempfile *tempfiles)
+{
+ int r;
+ char *cmd;
+ const char *image_name = NULL, *contents_name = NULL;
+
+ switch (flash_cmd) {
+ case FLASH_READ:
+ image_name = create_temp_file(tempfiles);
+ break;
+
+ case FLASH_WRITE:
+ image_name = get_firmware_image_temp_file(
+ params->image, tempfiles);
+ if (params->flash_contents)
+ contents_name = get_firmware_image_temp_file(
+ params->flash_contents, tempfiles);
+ break;
+
+ default:
+ ERROR("Unknown command: %d\n", flash_cmd);
+ return -1;
+ }
+
+ cmd = get_flashrom_command(flash_cmd, params, image_name,
+ contents_name);
+ if (!cmd)
+ return -1;
+
+ VB2_DEBUG(cmd);
+ r = system(cmd);
+ free(cmd);
+ if (r)
+ return r;
+
+ switch (flash_cmd) {
+ case FLASH_READ:
+ r = load_firmware_image(params->image, image_name, NULL);
+ break;
+ default:
+ break;
+ }
+
+ return r;
+}
+
+static int read_flash(struct flashrom_params *params,
+ struct updater_config *cfg)
+{
+ if (get_config_quirk(QUIRK_EXTERNAL_FLASHROM, cfg))
+ return external_flashrom(FLASH_READ, params, &cfg->tempfiles);
+
+ return flashrom_read_image(params->image, NULL, params->verbose);
+}
+
+static int write_flash(struct flashrom_params *params,
+ struct updater_config *cfg)
+{
+ int r;
+
+ if (get_config_quirk(QUIRK_EXTERNAL_FLASHROM, cfg))
+ return external_flashrom(FLASH_WRITE, params, &cfg->tempfiles);
+
+ r = flashrom_write_image(params->image,
+ params->regions,
+ params->flash_contents,
+ !params->noverify,
+ params->verbose);
+ /*
+ * Force a newline to flush stdout in case if
+ * flashrom_write_image left some messages in the buffer.
+ */
+ fprintf(stdout, "\n");
+ return r;
+}
/*
* Loads the active system firmware image (usually from SPI flash chip).
* Returns 0 if success, non-zero if error.
*/
-int load_system_firmware(struct firmware_image *image,
- struct tempfile *tempfiles,
- int retries, int verbosity)
+int load_system_firmware(struct updater_config *cfg,
+ struct firmware_image *image)
{
int r, i;
+ char *cmd;
+ const int tries = 1 + get_config_quirk(QUIRK_EXTRA_RETRIES, cfg);
+ struct flashrom_params params = {0};
- INFO("flasrhom -r <IMAGE> -p %s%s\n",
- image->programmer,
- verbosity ? " -V" : "");
+ params.image = image;
+ params.verbose = cfg->verbosity + 1; /* libflashrom verbose 1 = WARN. */
- for (i = 1, r = -1; i <= retries && r != 0; i++) {
+ cmd = get_flashrom_command(FLASH_READ, ¶ms, NULL, NULL);
+ INFO("%s\n", cmd);
+ free(cmd);
+
+ for (i = 1, r = -1; i <= tries && r != 0; i++, params.verbose++) {
if (i > 1)
- WARN("Retry reading firmware (%d/%d)...\n", i, retries);
- r = flashrom_read_image(image, NULL, verbosity + 1);
+ WARN("Retry reading firmware (%d/%d)...\n", i, tries);
+ r = read_flash(¶ms, cfg);
}
if (!r)
r = parse_firmware_image(image);
@@ -548,49 +782,38 @@
* FMAP section names (and ended with a NULL).
* Returns 0 if success, non-zero if error.
*/
-int write_system_firmware(const struct firmware_image *image,
- const struct firmware_image *diff_image,
- const char * const sections[],
- struct tempfile *tempfiles,
- int do_verify, int retries, int verbosity)
+int write_system_firmware(struct updater_config *cfg,
+ const struct firmware_image *image,
+ const char * const sections[])
{
- int r, i, len = 0;
- char *partial = NULL;
+ int r = 0, i;
+ char *cmd;
+ const int tries = 1 + get_config_quirk(QUIRK_EXTRA_RETRIES, cfg);
+ struct flashrom_params params = {0};
+ struct firmware_image *flash_contents = NULL;
- for (i = 0; sections && sections[i]; i++)
- len += strlen(sections[i]) + strlen(" -i ");
- if (len) {
- partial = (char *)malloc(len + 1);
- if (!partial) {
- ERROR("Failed to allocate a string buffer.\n");
- return -1;
- }
- partial[0] = '\0';
- for (i = 0; sections[i]; i++) {
- strcat(partial, " -i ");
- strcat(partial, sections[i]);
- }
- assert(strlen(partial) == len);
- }
+ if (cfg->emulation)
+ return emulate_write_firmware(cfg->emulation, image, sections);
- INFO("flashrom -w <IMAGE> -p %s%s%s%s%s\n",
- image->programmer,
- diff_image ? " --flash-contents <DIFF_IMAGE>" : "",
- do_verify ? "" : " --noverify",
- verbosity > 1 ? " -V" : "",
- partial ? partial : "");
- free(partial);
+ if (cfg->use_diff_image && cfg->image_current.data &&
+ is_the_same_programmer(&cfg->image_current, image))
+ flash_contents = &cfg->image_current;
- for (i = 1, r = -1; i <= retries && r != 0; i++) {
+ params.image = (struct firmware_image *)image;
+ params.flash_contents = flash_contents;
+ params.regions = sections;
+ params.noverify = !cfg->do_verify;
+ params.noverify_all = true;
+ params.verbose = cfg->verbosity + 1; /* libflashrom verbose 1 = WARN. */
+
+ cmd = get_flashrom_command(FLASH_WRITE, ¶ms, NULL, NULL);
+ INFO("%s\n", cmd);
+ free(cmd);
+
+ for (i = 1, r = -1; i <= tries && r != 0; i++, params.verbose++) {
if (i > 1)
- WARN("Retry writing firmware (%d/%d)...\n", i, retries);
- r = flashrom_write_image(image, sections, diff_image, do_verify,
- verbosity + 1);
- /*
- * Force a newline to flush stdout in case if
- * flashrom_write_image left some messages in the buffer.
- */
- fprintf(stdout, "\n");
+ WARN("Retry writing firmware (%d/%d)...\n", i, tries);
+ r = write_flash(¶ms, cfg);
}
return r;
}
diff --git a/futility/updater_utils.h b/futility/updater_utils.h
index 3eb1d33..a99c38c 100644
--- a/futility/updater_utils.h
+++ b/futility/updater_utils.h
@@ -8,6 +8,7 @@
#ifndef VBOOT_REFERENCE_FUTILITY_UPDATER_UTILS_H_
#define VBOOT_REFERENCE_FUTILITY_UPDATER_UTILS_H_
+#include <stdbool.h>
#include <stdio.h>
#include "fmap.h"
@@ -15,7 +16,7 @@
ERROR("Failed to allocate memory, abort.\n"); exit(1); } while (0)
/* Structure(s) declared in updater_archive */
-struct archive;
+struct u_archive;
/* flashrom programmers. */
static const char * const PROG_HOST = "host",
@@ -57,6 +58,23 @@
/* Include definition of 'struct firmware_image;' */
#include "flashrom.h"
+/* Parameters when invoking flashrom. */
+struct flashrom_params {
+ struct firmware_image *image; /* The firmware image to read/write. */
+ const struct firmware_image *flash_contents; /* --flash-contents */
+ const char *const *regions; /* -i: only read/write <region> */
+ bool noverify; /* -n: don't auto-verify */
+ bool noverify_all; /* -N: verify included regions only */
+ int verbose; /* -V: more verbose output */
+ /* Supported by libflashrom but no exported by flashrom_drv:
+ * - force
+ * - noverify_all
+ * Not supported by libflashrom:
+ * - do_not_diff
+ * - ignore_lock
+ */
+};
+
enum {
IMAGE_LOAD_SUCCESS = 0,
IMAGE_READ_FAILURE = -1,
@@ -71,15 +89,17 @@
* failure, or IMAGE_PARSE_FAILURE for non-vboot images.
*/
int load_firmware_image(struct firmware_image *image, const char *file_name,
- struct archive *archive);
+ struct u_archive *archive);
+
+/* Structure(s) declared in updater.h */
+struct updater_config;
/*
* Loads the active system firmware image (usually from SPI flash chip).
* Returns 0 if success, non-zero if error.
*/
-int load_system_firmware(struct firmware_image *image,
- struct tempfile *tempfiles,
- int retries, int verbosity);
+int load_system_firmware(struct updater_config *cfg,
+ struct firmware_image *image);
/* Frees the allocated resource from a firmware image object. */
void free_firmware_image(struct firmware_image *image);
@@ -98,11 +118,9 @@
* FMAP section names (and ended with a NULL).
* Returns 0 if success, non-zero if error.
*/
-int write_system_firmware(const struct firmware_image *image,
- const struct firmware_image *diff_image,
- const char * const sections[],
- struct tempfile *tempfiles,
- int do_verify, int retries, int verbosity);
+int write_system_firmware(struct updater_config *cfg,
+ const struct firmware_image *image,
+ const char * const sections[]);
struct firmware_section {
uint8_t *data;
@@ -182,7 +200,7 @@
* Helper function to detect type of Servo board attached to host.
* Returns a string as programmer parameter on success, otherwise NULL.
*/
-char *host_detect_servo(int *need_prepare_ptr);
+char *host_detect_servo(const char **prepare_ctrl_name);
/*
* Returns 1 if a given file (cbfs_entry_name) exists inside a particular CBFS
diff --git a/futility/vb2_helper.c b/futility/vb2_helper.c
index 4d676a6..a8452db 100644
--- a/futility/vb2_helper.c
+++ b/futility/vb2_helper.c
@@ -60,7 +60,7 @@
return 1;
}
-int ft_show_vb21_pubkey(const char *name, uint8_t *buf, uint32_t len,
+int show_vb21_pubkey_buf(const char *name, uint8_t *buf, uint32_t len,
void *data)
{
struct vb2_public_key key;
@@ -91,6 +91,22 @@
return 0;
}
+int ft_show_vb21_pubkey(const char *name, void *data)
+{
+ int fd = -1;
+ uint8_t *buf;
+ uint32_t len;
+ int rv;
+
+ if (futil_open_and_map_file(name, &fd, FILE_RO, &buf, &len))
+ return 1;
+
+ rv = show_vb21_pubkey_buf(name, buf, len, data);
+
+ futil_unmap_and_close_file(fd, FILE_RO, buf, len);
+ return rv;
+}
+
static int vb2_private_key_sha1sum(struct vb2_private_key *key, uint8_t *digest)
{
uint8_t *buf;
@@ -106,15 +122,23 @@
return 1;
}
-int ft_show_vb21_privkey(const char *name, uint8_t *buf, uint32_t len,
- void *data)
+int ft_show_vb21_privkey(const char *name, void *data)
{
struct vb2_private_key *key = 0;
uint8_t sha1sum[VB2_SHA1_DIGEST_SIZE];
+ int fd = -1;
+ uint8_t *buf;
+ uint32_t len;
+ int rv = 0;
- if (VB2_SUCCESS != vb21_private_key_unpack(&key, buf, len))
+ if (futil_open_and_map_file(name, &fd, FILE_RO, &buf, &len))
return 1;
+ if (VB2_SUCCESS != vb21_private_key_unpack(&key, buf, len)) {
+ rv = 1;
+ goto done;
+ }
+
printf("Private key file: %s\n", name);
printf(" Vboot API: 2.1\n");
printf(" Desc: \"%s\"\n", key->desc ? key->desc : "");
@@ -132,7 +156,9 @@
printf("\n");
}
vb2_private_key_free(key);
- return 0;
+done:
+ futil_unmap_and_close_file(fd, FILE_RO, buf, len);
+ return rv;
}
static RSA *rsa_from_buffer(uint8_t *buf, uint32_t len)
@@ -172,7 +198,7 @@
return FILE_TYPE_UNKNOWN;
}
-int ft_show_pem(const char *name, uint8_t *buf, uint32_t len, void *data)
+int ft_show_pem(const char *name, void *data)
{
RSA *rsa_key;
uint8_t *keyb;
@@ -180,6 +206,13 @@
uint32_t keyb_len;
int i, bits;
const BIGNUM *rsa_key_n, *rsa_key_d;
+ int fd = -1;
+ uint8_t *buf;
+ uint32_t len;
+ int rv = 0;
+
+ if (futil_open_and_map_file(name, &fd, FILE_RO, &buf, &len))
+ return 1;
/* We're called only after ft_recognize_pem, so this should work. */
rsa_key = rsa_from_buffer(buf, len);
@@ -197,7 +230,8 @@
if (vb_keyb_from_rsa(rsa_key, &keyb, &keyb_len)) {
printf(" Key sha1sum: <error>");
RSA_free(rsa_key);
- return 1;
+ rv = 1;
+ goto done;
}
printf(" Key sha1sum: ");
@@ -209,5 +243,7 @@
free(keyb);
RSA_free(rsa_key);
- return 0;
+done:
+ futil_unmap_and_close_file(fd, FILE_RO, buf, len);
+ return rv;
}
diff --git a/host/arch/x86/lib/crossystem_arch.c b/host/arch/x86/lib/crossystem_arch.c
index d48cf87..4040ddc 100644
--- a/host/arch/x86/lib/crossystem_arch.c
+++ b/host/arch/x86/lib/crossystem_arch.c
@@ -734,6 +734,8 @@
{ "INTC1055:00", FindGpioChipOffsetByLabel },
{ "INTC1056:00", FindGpioChipOffsetByLabel },
{ "INTC1057:00", FindGpioChipOffsetByLabel },
+ /* INTC108x are for Meteor Lake */
+ { "INTC1083:00", FindGpioChipOffsetByLabel },
/* INT3453 are for GLK */
{ "INT3453:00", FindGpioChipOffsetByLabel },
{ "INT3453:01", FindGpioChipOffsetByLabel },
diff --git a/host/lib/cbfstool.c b/host/lib/cbfstool.c
new file mode 100644
index 0000000..8f54706
--- /dev/null
+++ b/host/lib/cbfstool.c
@@ -0,0 +1,72 @@
+/* Copyright 2022 The ChromiumOS Authors.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "2common.h"
+#include "2return_codes.h"
+#include "subprocess.h"
+#include "cbfstool.h"
+
+static const char *get_cbfstool_path(void)
+{
+ static const char *cbfstool = NULL;
+
+ if (cbfstool)
+ return cbfstool;
+
+ const char *env_cbfstool = getenv(ENV_CBFSTOOL);
+ if (env_cbfstool && env_cbfstool[0] != '\0') {
+ cbfstool = strdup(env_cbfstool);
+ return cbfstool;
+ }
+
+ cbfstool = DEFAULT_CBFSTOOL;
+ return cbfstool;
+}
+
+vb2_error_t cbfstool_truncate(const char *file, const char *region,
+ size_t *new_size)
+{
+ int status;
+ char output_buffer[128];
+ const char *cbfstool = get_cbfstool_path();
+
+ struct subprocess_target output = {
+ .type = TARGET_BUFFER_NULL_TERMINATED,
+ .buffer = {
+ .buf = output_buffer,
+ .size = sizeof(output_buffer),
+ },
+ };
+ const char *const argv[] = {
+ cbfstool, file, "truncate", "-r", region, NULL,
+ };
+
+ VB2_DEBUG("Calling: %s '%s' truncate -r '%s'\n", cbfstool, file,
+ region);
+ status = subprocess_run(argv, &subprocess_null, &output,
+ &subprocess_null);
+
+ if (status < 0) {
+ fprintf(stderr, "%s(): cbfstool invocation failed: %m\n",
+ __func__);
+ exit(1);
+ }
+
+ /* Positive exit code means something is wrong with image. Return zero
+ as new size, because it might be problem with missing CBFS.*/
+ if (status > 0) {
+ *new_size = 0;
+ return VB2_ERROR_CBFSTOOL;
+ }
+
+ if (sscanf(output_buffer, "%zi", new_size) != 1) {
+ VB2_DEBUG("Failed to parse command output. Unexpected "
+ "output.\n");
+ *new_size = 0;
+ return VB2_ERROR_CBFSTOOL;
+ }
+
+ return VB2_SUCCESS;
+}
diff --git a/host/lib/crossystem.c b/host/lib/crossystem.c
index a5427c2..6d55335 100644
--- a/host/lib/crossystem.c
+++ b/host/lib/crossystem.c
@@ -38,7 +38,8 @@
typedef enum VdatStringField {
VDAT_STRING_DEPRECATED_TIMERS = 0, /* Timer values */
VDAT_STRING_LOAD_FIRMWARE_DEBUG, /* LoadFirmware() debug info */
- VDAT_STRING_DEPRECATED_LOAD_KERNEL_DEBUG, /* LoadKernel() debug info */
+ VDAT_STRING_DEPRECATED_LOAD_KERNEL_DEBUG, /* vb2api_load_kernel()
+ debug info */
VDAT_STRING_MAINFW_ACT /* Active main firmware */
} VdatStringField;
diff --git a/host/lib/flashrom_drv.c b/host/lib/flashrom_drv.c
index 1d9e3fd..19d6384 100644
--- a/host/lib/flashrom_drv.c
+++ b/host/lib/flashrom_drv.c
@@ -189,12 +189,14 @@
}
}
flashrom_layout_set(flashctx, layout);
+ } else if (image->size != len) {
+ r = -1;
+ goto err_cleanup;
}
- flashrom_flag_set(flashctx, FLASHROM_FLAG_VERIFY_WHOLE_CHIP, true);
- flashrom_flag_set(flashctx, FLASHROM_FLAG_VERIFY_AFTER_WRITE, true);
- if (!do_verify)
- flashrom_flag_set(flashctx, FLASHROM_FLAG_VERIFY_AFTER_WRITE, false);
+ flashrom_flag_set(flashctx, FLASHROM_FLAG_VERIFY_WHOLE_CHIP, false);
+ flashrom_flag_set(flashctx, FLASHROM_FLAG_VERIFY_AFTER_WRITE,
+ do_verify);
r |= flashrom_image_write(flashctx, image->data, image->size,
diff_image ? diff_image->data : NULL);
diff --git a/host/lib/include/cbfstool.h b/host/lib/include/cbfstool.h
new file mode 100644
index 0000000..1343d40
--- /dev/null
+++ b/host/lib/include/cbfstool.h
@@ -0,0 +1,12 @@
+/* Copyright 2022 The ChromiumOS Authors.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "2return_codes.h"
+
+#define ENV_CBFSTOOL "CBFSTOOL"
+#define DEFAULT_CBFSTOOL "cbfstool"
+
+vb2_error_t cbfstool_truncate(const char *file, const char *region,
+ size_t *new_size);
diff --git a/scripts/image_signing/common.sh b/scripts/image_signing/common.sh
index efa00a2..81bcac3 100644
--- a/scripts/image_signing/common.sh
+++ b/scripts/image_signing/common.sh
@@ -136,5 +136,24 @@
sudo setfattr -n security.selinux -v "u:object_r:cros_conf_file:s0" "$1"
}
+# Extracts a firmware updater bundle (for firmware image binaries) file
+# (generated by src/platform/firmware/pack_firmware.sh).
+# Args: INPUT_FILE OUTPUT_DIR
+extract_firmware_bundle() {
+ local input="$(readlink -f "$1")"
+ local output_dir="$2"
+ if [[ ! -s "${input}" ]]; then
+ return 1
+ elif grep -q '^##CUTHERE##' "${input}"; then
+ # Bundle supports self-extraction.
+ "${input}" --sb_extract "${output_dir}" ||
+ die "Extracting firmware autoupdate (--sb_extract) failed."
+ else
+ # Legacy bundle - try uudecode.
+ uudecode -o - "${input}" | tar -C "${output_dir}" -zxf - 2>/dev/null ||
+ die "Extracting firmware autoupdate failed."
+ fi
+}
+
# This will override the trap set in common_minmal.sh
trap "cleanup" INT TERM EXIT
diff --git a/scripts/image_signing/ensure_amd_psp_flags.sh b/scripts/image_signing/ensure_amd_psp_flags.sh
new file mode 100755
index 0000000..efccb69
--- /dev/null
+++ b/scripts/image_signing/ensure_amd_psp_flags.sh
@@ -0,0 +1,115 @@
+#!/bin/bash
+# Copyright 2022 The ChromiumOS Authors.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Load common constants and variables.
+. "$(dirname "$0")/common.sh"
+
+# Abort on error and uninitialized variables.
+set -eu
+
+declare -A -r REQUIRED_BIT_MASKS=(
+ # Bit 58 - PSP_S0I3_RESUME_VERSTAGE - Run PSP verstage during S0i3 resume.
+ # Checks that FW images have not been tampered with when exiting S0i3.
+ [guybrush]="$((1 << 58))"
+ [zork]="0x0"
+)
+
+declare -A -r FORBIDDEN_BIT_MASKS=(
+ [guybrush]="0x0"
+ [zork]="0x0"
+)
+
+# Grunt uses an old firmware format that amdfwread cannot read.
+# See b/233787191 for skyrim.
+BOARD_IGNORE_LIST=(grunt skyrim)
+
+usage() {
+ echo "$0: Validate AMD PSP soft-fuse flags contained in a ChromeOS image." \
+ "These flags can have security implications and control debug features."
+ echo "Usage $0 <board> <image>"
+}
+
+main() {
+ if [[ $# -ne 2 ]]; then
+ usage
+ exit 1
+ fi
+
+ local board="$1"
+ local image="$2"
+
+ # Check the ignore list.
+ if [[ " ${BOARD_IGNORE_LIST[*]} " == *" ${board} "* ]]; then
+ echo "Skipping ignore-listed board ${board}"
+ exit 0
+ fi
+
+ # Mount the image.
+ local loopdev rootfs
+ if [[ -d "${image}" ]]; then
+ rootfs="${image}"
+ else
+ rootfs="$(make_temp_dir)"
+ loopdev="$(loopback_partscan "${image}")"
+ mount_loop_image_partition_ro "${loopdev}" 3 "${rootfs}"
+ fi
+
+ local firmware_bundle shellball_dir
+ firmware_bundle="${rootfs}/usr/sbin/chromeos-firmwareupdate"
+ shellball_dir="$(make_temp_dir)"
+
+ # Get the board specific bit masks.
+ local required_bit_mask forbidden_bit_mask
+
+ if [[ ! -v "REQUIRED_BIT_MASKS[${board}]" ]]; then
+ die "Missing PSP required bit mask set for ${board}"
+ fi
+
+ if [[ ! -v "FORBIDDEN_BIT_MASKS[${board}]" ]]; then
+ die "Missing PSP forbidden bit mask set for ${board}"
+ fi
+
+ required_bit_mask="${REQUIRED_BIT_MASKS[${board}]}"
+ forbidden_bit_mask="${FORBIDDEN_BIT_MASKS[${board}]}"
+
+ # Extract our firmware.
+ if ! extract_firmware_bundle "${firmware_bundle}" "${shellball_dir}"; then
+ die "Failed to extract firmware bundle"
+ fi
+
+ # Find our images and check the soft-fuse bits in each.
+ declare -a images
+ readarray -t images < <(find "${shellball_dir}" -iname 'bios-*')
+
+ local image
+ for image in "${images[@]}"; do
+ local soft_fuse soft_fuse_output forbidden_set missing_set
+ if ! soft_fuse_output="$(amdfwread --soft-fuse "${image}")"; then
+ die "'amdfwread --soft-fuse ${image}' failed"
+ fi
+
+ # Output format from amdfwread is Soft-fuse:value, where value is in hex.
+ soft_fuse="$(echo "${soft_fuse_output}" | \
+ sed -E -n 's/Soft-fuse:(0[xX][0-9a-fA-F]+)/\1/p')"
+ if [[ -z "${soft_fuse}" ]]; then
+ die "Could not parse Soft-fuse value from output: '${soft_fuse_output}'"
+ fi
+
+ forbidden_set="$((soft_fuse & forbidden_bit_mask))"
+ if [[ "${forbidden_set}" != 0 ]]; then
+ local forbidden_hex
+ forbidden_hex="$(printf %#x "${forbidden_set}")"
+ die "${image}: Forbidden AMD PSP soft-fuse bits set: ${forbidden_hex}"
+ fi
+
+ missing_set="$((~soft_fuse & required_bit_mask))"
+ if [[ "${missing_set}" != 0 ]]; then
+ local missing_hex
+ missing_hex="$(printf %#x "${missing_set}")"
+ die "${image}: Required AMD PSP soft-fuse bits not set: ${missing_hex}"
+ fi
+ done
+}
+main "$@"
diff --git a/scripts/image_signing/gbb_flags_common.sh b/scripts/image_signing/gbb_flags_common.sh
index ed51f15..ae50c10 100755
--- a/scripts/image_signing/gbb_flags_common.sh
+++ b/scripts/image_signing/gbb_flags_common.sh
@@ -62,10 +62,23 @@
flashrom -p "${programmer}" -i GBB --noverify-all -w "${file}"
}
-get_programmer_for_servo() {
+CPU_FW_SPI="${FLAGS_FALSE}"
+
+enable_cpu_fw_spi() {
+ dut-control cpu_fw_spi:on >/dev/null
+ CPU_FW_SPI="${FLAGS_TRUE}"
+}
+
+maybe_disable_cpu_fw_spi() {
+ if [ "${CPU_FW_SPI}" = "${FLAGS_TRUE}" ]; then
+ dut-control cpu_fw_spi:off >/dev/null
+ fi
+}
+trap "maybe_disable_cpu_fw_spi" EXIT
+
+update_programmer_for_servo() {
local servo_type
local serial
- local programmer
servo_type=$(dut-control -o servo_type 2>/dev/null) || \
die "Failed to get servo information. Is servod running?"
case "${servo_type}" in
@@ -84,10 +97,8 @@
esac
case "${servo_type}" in
*servo_micro*|*c2d2*)
- # TODO(sammc): Support servo micro, servo v2 and C2D2. This requires
- # toggling cpu_fw_spi via dut-control before and after running flashrom.
- # C2D2 additionally requires a working cpu_fw_spi implementation.
- die "Unsupported servo type ${servo_type}"
+ programmer="raiden_debug_spi:serial=${serial}"
+ enable_cpu_fw_spi
;;
*ccd_cr50*|*ccd_gsc*)
programmer="raiden_debug_spi:target=AP,serial=${serial}"
@@ -96,5 +107,4 @@
die "Unsupported servo type ${servo_type}"
;;
esac
- echo "${programmer}"
}
diff --git a/scripts/image_signing/get_gbb_flags.sh b/scripts/image_signing/get_gbb_flags.sh
index 1191e9f..84acaa0 100755
--- a/scripts/image_signing/get_gbb_flags.sh
+++ b/scripts/image_signing/get_gbb_flags.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/bin/bash
#
# Copyright 2017 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
@@ -30,7 +30,7 @@
if [ -z "${FLAGS_file}" ]; then
image_file="$(make_temp_file)"
if [ "${FLAGS_servo}" = "${FLAGS_TRUE}" ]; then
- programmer=$(get_programmer_for_servo)
+ update_programmer_for_servo
fi
flashrom_read "${image_file}" "${programmer}"
fi
diff --git a/scripts/image_signing/make_dev_firmware.sh b/scripts/image_signing/make_dev_firmware.sh
index 0db5638..20c8414 100755
--- a/scripts/image_signing/make_dev_firmware.sh
+++ b/scripts/image_signing/make_dev_firmware.sh
@@ -167,8 +167,6 @@
local recovery_pubkey="${FLAGS_keys}/recovery_key.vbpubk"
local firmware_keyblock="${FLAGS_keys}/firmware.keyblock"
local firmware_prvkey="${FLAGS_keys}/firmware_data_key.vbprivk"
- local dev_firmware_keyblock="${FLAGS_keys}/dev_firmware.keyblock"
- local dev_firmware_prvkey="${FLAGS_keys}/dev_firmware_data_key.vbprivk"
local kernel_sub_pubkey="${FLAGS_keys}/kernel_subkey.vbpubk"
local ec_efs_pubkey="${FLAGS_keys}/key_ec_efs.vbpubk2"
local ec_efs_prvkey="${FLAGS_keys}/key_ec_efs.vbprik2"
@@ -281,8 +279,6 @@
echo "Using keyblocks (developer, normal)..."
else
echo "Using keyblocks (normal, normal)..."
- dev_firmware_prvkey="$firmware_prvkey"
- dev_firmware_keyblock="$firmware_keyblock"
fi
debug_msg "Extract firmware version and data key version"
@@ -351,8 +347,6 @@
"${IMAGE_BIOS}" \
"${firmware_prvkey}" \
"${firmware_keyblock}" \
- "${dev_firmware_prvkey}" \
- "${dev_firmware_keyblock}" \
"${kernel_sub_pubkey}" \
"${firmware_version}" \
${optional_opts} ||
diff --git a/scripts/image_signing/resign_firmwarefd.sh b/scripts/image_signing/resign_firmwarefd.sh
index d4cb5b8..ea23315 100755
--- a/scripts/image_signing/resign_firmwarefd.sh
+++ b/scripts/image_signing/resign_firmwarefd.sh
@@ -20,20 +20,12 @@
DST_FD=$2
FIRMWARE_DATAKEY=$3
FIRMWARE_KEYBLOCK=$4
-DEV_FIRMWARE_DATAKEY=$5
-DEV_FIRMWARE_KEYBLOCK=$6
-KERNEL_SUBKEY=$7
+KERNEL_SUBKEY=$5
# optional
-VERSION=$8
-PREAMBLE_FLAG=$9
-LOEM_OUTPUT_DIR=${10}
-LOEMID=${11}
-
-if [ ! -e $DEV_FIRMWARE_KEYBLOCK ] || [ ! -e $DEV_FIRMWARE_DATAKEY ] ; then
- echo "No dev firmware keyblock/datakey found. Reusing normal keys."
- DEV_FIRMWARE_KEYBLOCK="$FIRMWARE_KEYBLOCK"
- DEV_FIRMWARE_DATAKEY="$FIRMWARE_DATAKEY"
-fi
+VERSION=$6
+PREAMBLE_FLAG=$7
+LOEM_OUTPUT_DIR=$8
+LOEMID=$9
# pass optional args
[ -n "$VERSION" ] && VERSION="--version $VERSION"
@@ -44,8 +36,6 @@
exec ${FUTILITY} sign \
--signprivate $FIRMWARE_DATAKEY \
--keyblock $FIRMWARE_KEYBLOCK \
- --devsign $DEV_FIRMWARE_DATAKEY \
- --devkeyblock $DEV_FIRMWARE_KEYBLOCK \
--kernelkey $KERNEL_SUBKEY \
$VERSION \
$PREAMBLE_FLAG \
diff --git a/scripts/image_signing/set_gbb_flags.sh b/scripts/image_signing/set_gbb_flags.sh
index 3057da5..57fd4c0 100755
--- a/scripts/image_signing/set_gbb_flags.sh
+++ b/scripts/image_signing/set_gbb_flags.sh
@@ -55,7 +55,7 @@
if [ -z "${FLAGS_file}" ]; then
image_file="$(make_temp_file)"
if [ "${FLAGS_servo}" = "${FLAGS_TRUE}" ]; then
- programmer=$(get_programmer_for_servo)
+ update_programmer_for_servo
fi
flashrom_read "${image_file}" "${programmer}"
diff --git a/scripts/image_signing/sign_android_image.sh b/scripts/image_signing/sign_android_image.sh
index 5af1aa6..6b65545 100755
--- a/scripts/image_signing/sign_android_image.sh
+++ b/scripts/image_signing/sign_android_image.sh
@@ -250,6 +250,48 @@
sudo find "${dir}" -exec stat -c '%n:%u:%g:%a' {} + | sort
}
+# Snapshot capabilities in a directory recursively.
+snapshot_capabilities() {
+ local dir=$1
+ sudo find "${dir}" -exec getcap {} + | sort
+}
+
+# Apply capabilities to files in |dir| as specified by |capabilities_list|.
+# See b/179170462.
+apply_capabilities() {
+ local dir=$1
+ local capabilities_list=$2
+ local entry
+
+ while read -ra entry; do
+ if [[ ${#entry[@]} -lt 2 ]]; then
+ error "Unexpected output in capabilities_list of '${entry[*]}'"
+ return 1
+ fi
+ # Output of getcap is either |{file} {capabilities}| or
+ # |{file} = {capabilities}|, so take the first and last element of each
+ # line.
+ info "Setting capabilities ${entry[${#entry[@]}-1]} for ${entry[0]}"
+ sudo setcap "${entry[${#entry[@]}-1]}" "${entry[0]}"
+ done < "${capabilities_list}"
+
+ return 0
+}
+
+# Integrity check that capabilities are unchanged.
+capabilities_integrity_check() {
+ local system_mnt=$1
+ local working_dir=$2
+ snapshot_capabilities "${system_mnt}" > "${working_dir}/capabilities.new"
+ local d
+ if ! d=$(diff "${working_dir}"/capabilities.{orig,new}); then
+ error "Unexpected change of capabilities, diff \n${d}"
+ return 1
+ fi
+
+ return 0
+}
+
# Integrity check that image content is unchanged.
image_content_integrity_check() {
local system_mnt=$1
@@ -265,6 +307,12 @@
return 0
}
+list_image_files() {
+ local unsquashfs=$1
+ local system_img=$2
+ "${unsquashfs}" -l "${system_img}" | grep ^squashfs-root
+}
+
sign_android_internal() {
local root_fs_dir=$1
local key_dir=$2
@@ -330,8 +378,17 @@
local working_dir=$(make_temp_dir)
local system_mnt="${working_dir}/mnt"
+ local system_capabilities_orig="${working_dir}/capabilities.orig"
- info "Unpacking squashfs system image to ${system_mnt}"
+ # Extract with xattrs so we can read and audit capabilities. See b/179170462.
+ info "Unpacking squashfs system image with xattrs to ${system_mnt}"
+ sudo "${unsquashfs}" -x -f -no-progress -d "${system_mnt}" "${system_img}"
+ snapshot_capabilities "${system_mnt}" > "${system_capabilities_orig}"
+ sudo rm -rf "${system_mnt}"
+
+ info "Unpacking squashfs system image without xattrs to ${system_mnt}"
+ list_image_files "${unsquashfs}" "${system_img}" > \
+ "${working_dir}/image_file_list.orig"
sudo "${unsquashfs}" -no-xattrs -f -no-progress -d "${system_mnt}" "${system_img}"
snapshot_file_properties "${system_mnt}" > "${working_dir}/properties.orig"
@@ -399,6 +456,14 @@
info "Packages cache ${packages_cache} does not exist. Skip regeneration."
fi
+ # Apply original capabilities to system image and verify correctness.
+ if ! apply_capabilities "${system_mnt}" "${system_capabilities_orig}"; then
+ return 1
+ fi
+ if ! capabilities_integrity_check "${system_mnt}" "${working_dir}"; then
+ return 1
+ fi
+
info "Repacking squashfs image with compression flags '${compression_flags}'"
local old_size=$(stat -c '%s' "${system_img}")
# Remove old system image to prevent mksquashfs tries to merge both images.
@@ -408,6 +473,17 @@
-no-progress
local new_size=$(stat -c '%s' "${system_img}")
info "Android system image size change: ${old_size} -> ${new_size}"
+
+ list_image_files "${unsquashfs}" "${system_img}" > \
+ "${working_dir}/image_file_list.new"
+ if d=$(grep -v -F -x -f "${working_dir}"/image_file_list.{new,orig}); then
+ # If we have a line in image_file_list.orig which does not appear in
+ # image_file_list.new, it means some files are removed during signing
+ # process. Here we have already deleted the original Android image so
+ # cannot retry.
+ die "Unexpected change of file list\n${d}"
+ fi
+
return 0
}
diff --git a/scripts/image_signing/sign_firmware.sh b/scripts/image_signing/sign_firmware.sh
index 0e7ac7c..ebc6cdc 100755
--- a/scripts/image_signing/sign_firmware.sh
+++ b/scripts/image_signing/sign_firmware.sh
@@ -57,8 +57,6 @@
"${temp_fw}" \
"${key_dir}/firmware_data_key${loem_key}.vbprivk" \
"${key_dir}/firmware${loem_key}.keyblock" \
- "${key_dir}/dev_firmware_data_key${loem_key}.vbprivk" \
- "${key_dir}/dev_firmware${loem_key}.keyblock" \
"${key_dir}/kernel_subkey.vbpubk" \
"${firmware_version}" \
"" \
diff --git a/scripts/image_signing/sign_gsc_firmware.sh b/scripts/image_signing/sign_gsc_firmware.sh
index af7b7da..a5945ce 100755
--- a/scripts/image_signing/sign_gsc_firmware.sh
+++ b/scripts/image_signing/sign_gsc_firmware.sh
@@ -148,13 +148,11 @@
# needs to be verified and in certain cases altered.
#
# The function verifies that the input manifest is a proper json file, and
-# that the manifest conforms to GSC version numbering and board ID flags
-# conventions for various build images:
-#
-# - only binaries where version is set to CR50_NODE_LOCKED_VERSION can be
-# converted to node locked images. Board IDs for node locked images come
-# from signing instructions, and the config1 manifest field value must have
-# the 0x80000000 bit set.
+# that the manifest conforms to GSC board ID flags conventions for various
+# build images:
+
+# - board IDs for node locked images come from signing instructions, and the
+# config1 manifest field value must have the 0x80000000 bit set.
#
# - when signing pre-pvt binaries (major version number is even) the 0x10
# flags bit must be set.
@@ -198,11 +196,6 @@
if [[ -z ${INSN_DEVICE_ID:-} ]]; then
die "Node locked target without Device ID value"
fi
- # Case of a node locked image, it must have the fixed version.
- if [[ "${epoch}.${major}.${minor}" != "${CR50_NODE_LOCKED_VERSION}" ]]
- then
- die "Won't create node locked images for version $epoch.$major.$minor"
- fi
local sub
local devid0
diff --git a/scripts/image_signing/sign_official_build.sh b/scripts/image_signing/sign_official_build.sh
index 2f2621d..22cfa8c 100755
--- a/scripts/image_signing/sign_official_build.sh
+++ b/scripts/image_signing/sign_official_build.sh
@@ -330,25 +330,6 @@
disable_rw_mount "${rootfs}"
}
-# Extracts a firmware updater bundle (for firmware image binaries) file
-# (generated by src/platform/firmware/pack_firmware.sh).
-# Args: INPUT_FILE OUTPUT_DIR
-extract_firmware_bundle() {
- local input="$(readlink -f "$1")"
- local output_dir="$2"
- if [ ! -s "${input}" ]; then
- return 1
- elif grep -q '^##CUTHERE##' "${input}"; then
- # Bundle supports self-extraction.
- "$input" --sb_extract "${output_dir}" ||
- die "Extracting firmware autoupdate (--sb_extract) failed."
- else
- # Legacy bundle - try uudecode.
- uudecode -o - ${input} | tar -C ${output_dir} -zxf - 2>/dev/null ||
- die "Extracting firmware autoupdate failed."
- fi
-}
-
# Repacks firmware updater bundle content from given folder.
# Args: INPUT_DIR TARGET_SCRIPT
repack_firmware_bundle() {
@@ -515,14 +496,6 @@
local signprivate="${KEY_DIR}/firmware_data_key${key_suffix}.vbprivk"
local keyblock="${KEY_DIR}/firmware${key_suffix}.keyblock"
- local devsign="${KEY_DIR}/dev_firmware_data_key${key_suffix}.vbprivk"
- local devkeyblock="${KEY_DIR}/dev_firmware${key_suffix}.keyblock"
-
- if [ ! -e "${devsign}" ] || [ ! -e "${devkeyblock}" ] ; then
- echo "No dev firmware keyblock/datakey found. Reusing normal keys."
- devsign="${signprivate}"
- devkeyblock="${keyblock}"
- fi
# Path to bios.bin.
local bios_path="${shellball_dir}/${bios_image}"
@@ -566,8 +539,6 @@
echo "Signing Bios with:" ${FUTILITY} sign \
--signprivate "${signprivate}" \
--keyblock "${keyblock}" \
- --devsign "${devsign}" \
- --devkeyblock "${devkeyblock}" \
--kernelkey "${KEY_DIR}/kernel_subkey.vbpubk" \
--version "${FIRMWARE_VERSION}" \
"${extra_args[@]}" \
@@ -576,8 +547,6 @@
${FUTILITY} sign \
--signprivate "${signprivate}" \
--keyblock "${keyblock}" \
- --devsign "${devsign}" \
- --devkeyblock "${devkeyblock}" \
--kernelkey "${KEY_DIR}/kernel_subkey.vbpubk" \
--version "${FIRMWARE_VERSION}" \
"${extra_args[@]}" \
diff --git a/scripts/keygeneration/accessory/create_new_gsc_key.sh b/scripts/keygeneration/accessory/create_new_gsc_key.sh
new file mode 100755
index 0000000..a7e81c1
--- /dev/null
+++ b/scripts/keygeneration/accessory/create_new_gsc_key.sh
@@ -0,0 +1,77 @@
+#!/bin/bash
+
+# Copyright 2022 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.
+
+# Load common constants and functions.
+. "$(dirname "$0")/../common.sh"
+
+usage() {
+ cat <<EOF
+Usage: ${PROG} [options] <key_file_base_name>
+
+Options:
+ -o, --output_dir <dir>: Where to write the keys (default is cwd)
+EOF
+
+ if [[ $# -ne 0 ]]; then
+ die "$*"
+ else
+ exit 0
+ fi
+}
+
+generate_rsa3070_key() {
+ local base_name="$1"
+ local len="3070"
+
+ echo "creating ${base_name} key pair..."
+
+ # Make the RSA key pair.
+ openssl genrsa -F4 -out "${base_name}.pem" "${len}"
+ openssl rsa -in "${base_name}.pem" -outform PEM \
+ -pubout -out "${base_name}.pem.pub"
+}
+
+main() {
+ set -euo pipefail
+
+ local base_name
+ local output_dir="${PWD}"
+
+ base_name=""
+ while [[ $# -gt 0 ]]; do
+ case "$1" in
+ -h|--help)
+ usage
+ ;;
+ -o|--output_dir)
+ output_dir="$2"
+ if [[ ! -d "${output_dir}" ]]; then
+ die "output dir (${output_dir}) doesn't exist."
+ fi
+ shift
+ ;;
+ -*)
+ usage "Unknown option: $1"
+ ;;
+ *)
+ if [[ -z ${base_name} ]]; then
+ base_name="$1"
+ else
+ usage "Unknown argument $1"
+ fi
+ ;;
+ esac
+ shift
+ done
+
+ if [[ -z ${base_name} ]]; then
+ usage "Key file base name missing"
+ fi
+
+ generate_rsa3070_key "${output_dir}/${base_name}"
+}
+
+main "$@"
diff --git a/scripts/keygeneration/create_new_keys.sh b/scripts/keygeneration/create_new_keys.sh
index 2e1fd22..4a2ad33 100755
--- a/scripts/keygeneration/create_new_keys.sh
+++ b/scripts/keygeneration/create_new_keys.sh
@@ -14,7 +14,6 @@
Usage: ${PROG} [options]
Options:
- --devkeyblock Also generate developer firmware keyblock and data key
--android Also generate android keys
--uefi Also generate UEFI keys
--8k Use 8k keys instead of 4k (enables options below)
@@ -36,8 +35,6 @@
main() {
set -e
- # Flag to indicate whether we should be generating a developer keyblock flag.
- local dev_keyblock="false"
local android_keys="false"
local uefi_keys="false"
local root_key_algoid=${ROOT_KEY_ALGOID}
@@ -50,11 +47,6 @@
while [[ $# -gt 0 ]]; do
case $1 in
- --devkeyblock)
- echo "Will also generate developer firmware keyblock and data key."
- dev_keyblock="true"
- ;;
-
--android)
echo "Will also generate Android keys."
android_keys="true"
@@ -158,9 +150,6 @@
make_pair ec_data_key ${EC_DATAKEY_ALGOID} ${eckey_version}
make_pair root_key ${root_key_algoid}
make_pair firmware_data_key ${FIRMWARE_DATAKEY_ALGOID} ${fkey_version}
- if [[ "${dev_keyblock}" == "true" ]]; then
- make_pair dev_firmware_data_key ${DEV_FIRMWARE_DATAKEY_ALGOID} ${fkey_version}
- fi
make_pair kernel_subkey ${KERNEL_SUBKEY_ALGOID} ${ksubkey_version}
make_pair kernel_data_key ${KERNEL_DATAKEY_ALGOID} ${kdatakey_version}
@@ -178,11 +167,6 @@
# Ditto EC keyblock
make_keyblock ec ${EC_KEYBLOCK_MODE} ec_data_key ec_root_key
- if [[ "${dev_keyblock}" == "true" ]]; then
- # Create the dev firmware keyblock for use only in Developer mode.
- make_keyblock dev_firmware ${DEV_FIRMWARE_KEYBLOCK_MODE} dev_firmware_data_key root_key
- fi
-
# Create the recovery kernel keyblock for use only in Recovery mode.
make_keyblock recovery_kernel ${RECOVERY_KERNEL_KEYBLOCK_MODE} recovery_kernel_data_key recovery_key
diff --git a/tests/cgpt_fuzzer.c b/tests/cgpt_fuzzer.c
index d440ee8..6762bc3 100644
--- a/tests/cgpt_fuzzer.c
+++ b/tests/cgpt_fuzzer.c
@@ -25,7 +25,7 @@
static struct MockDisk mock_disk;
-vb2_error_t VbExDiskRead(VbExDiskHandle_t h, uint64_t lba_start,
+vb2_error_t VbExDiskRead(vb2ex_disk_handle_t h, uint64_t lba_start,
uint64_t lba_count, void *buffer)
{
size_t lba_size = mock_disk.size >> mock_disk.sector_shift;
diff --git a/tests/cgptlib_test.c b/tests/cgptlib_test.c
index 6fd7c32..f614977 100644
--- a/tests/cgptlib_test.c
+++ b/tests/cgptlib_test.c
@@ -9,10 +9,10 @@
#include "../cgpt/cgpt.h"
#include "cgptlib_internal.h"
#include "cgptlib_test.h"
+#include "common/tests.h"
#include "crc32.h"
#include "crc32_test.h"
#include "gpt.h"
-#include "test_common.h"
/*
* Testing partition layout (sector_bytes=512)
diff --git a/tests/chromeos_config_tests.c b/tests/chromeos_config_tests.c
index 2408d8c..6b24a33 100644
--- a/tests/chromeos_config_tests.c
+++ b/tests/chromeos_config_tests.c
@@ -11,8 +11,8 @@
#include "2common.h"
#include "2return_codes.h"
#include "chromeos_config.h"
+#include "common/tests.h"
#include "host_misc.h"
-#include "test_common.h"
static struct {
const char *path;
diff --git a/tests/common.sh b/tests/common.sh
index e69692b..a207922 100644
--- a/tests/common.sh
+++ b/tests/common.sh
@@ -5,7 +5,7 @@
# found in the LICENSE file.
# Determine script directory.
-SCRIPT_DIR="$(dirname $(realpath "${BASH_SOURCE[0]}"))"
+SCRIPT_DIR="$(dirname "$(realpath "${BASH_SOURCE[0]}")")"
ROOT_DIR="$(dirname "${SCRIPT_DIR}")"
SRCDIR="${SRCDIR:-${ROOT_DIR}}"
BUILD="${BUILD:-${ROOT_DIR}/build}"
@@ -19,8 +19,8 @@
TESTCASE_DIR="${SCRIPT_DIR}/testcases"
TESTKEY_SCRATCH_DIR="${TEST_DIR}/testkeys"
-if [ ! -d ${TESTKEY_SCRATCH_DIR} ]; then
- mkdir -p ${TESTKEY_SCRATCH_DIR}
+if [ ! -d "${TESTKEY_SCRATCH_DIR}" ]; then
+ mkdir -p "${TESTKEY_SCRATCH_DIR}"
fi
# Color output encodings.
@@ -53,7 +53,8 @@
*) lev=0
;;
esac
- local x=$(caller $lev)
+ local x
+ x=$(caller $lev)
local cline=${x%% *}
local cfunc=${x#* }
cfunc=${cfunc##*/}
@@ -65,7 +66,6 @@
}
function check_test_keys {
- [ -d ${TESTKEY_DIR} ] || \
+ [ -d "${TESTKEY_DIR}" ] || \
error 1 "You must run gen_test_keys.sh to generate test keys first."
}
-
diff --git a/tests/common/boot_mode.c b/tests/common/boot_mode.c
new file mode 100644
index 0000000..342b790
--- /dev/null
+++ b/tests/common/boot_mode.c
@@ -0,0 +1,48 @@
+/* Copyright 2022 The ChromiumOS Authors.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ *
+ * Some helper function related to boot mode.
+ */
+
+#include "2api.h"
+#include "2misc.h"
+#include "2nvstorage.h"
+#include "common/boot_mode.h"
+#include "common/tests.h"
+
+void _set_boot_mode(struct vb2_context *ctx, enum vb2_boot_mode boot_mode,
+ uint32_t recovery_reason, ...)
+{
+ struct vb2_shared_data *sd = vb2_get_sd(ctx);
+
+ switch (boot_mode) {
+ case VB2_BOOT_MODE_MANUAL_RECOVERY:
+ TEST_NEQ(recovery_reason, 0,
+ "recovery_reason should be set in recovery mode");
+ ctx->flags |= VB2_CONTEXT_RECOVERY_MODE;
+ sd->recovery_reason = recovery_reason;
+ ctx->flags |= VB2_CONTEXT_FORCE_RECOVERY_MODE;
+ ctx->flags |= VB2_CONTEXT_EC_TRUSTED;
+ break;
+ case VB2_BOOT_MODE_BROKEN_SCREEN:
+ TEST_NEQ(recovery_reason, 0,
+ "recovery_reason should be set in recovery mode");
+ ctx->flags |= VB2_CONTEXT_RECOVERY_MODE;
+ sd->recovery_reason = recovery_reason;
+ break;
+ case VB2_BOOT_MODE_DIAGNOSTICS:
+ vb2_nv_set(ctx, VB2_NV_DIAG_REQUEST, 1);
+ break;
+ case VB2_BOOT_MODE_DEVELOPER:
+ ctx->flags |= VB2_CONTEXT_DEVELOPER_MODE;
+ break;
+ case VB2_BOOT_MODE_NORMAL:
+ break;
+ default:
+ TEST_TRUE(0, "SET_BOOT_MODE: Undefined boot mode");
+ return;
+ }
+ vb2_set_boot_mode(ctx);
+ TEST_EQ(ctx->boot_mode, boot_mode, "Validity check for set boot mode");
+}
diff --git a/tests/common/boot_mode.h b/tests/common/boot_mode.h
new file mode 100644
index 0000000..bd6a3fd
--- /dev/null
+++ b/tests/common/boot_mode.h
@@ -0,0 +1,20 @@
+/* Copyright 2022 The ChromiumOS Authors.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "2api.h"
+
+void _set_boot_mode(struct vb2_context *ctx, enum vb2_boot_mode boot_mode,
+ uint32_t recovery_reason, ...);
+
+/*
+ * Set the boot mode to the expected boot mode with the recovery reason if
+ * given. Also, set the corresponding ctx flag.
+ *
+ * @param ctx Vboot context.
+ * @param boot_mode Boot mode to be set.
+ * @param recovery_reason Recovery reason set to sd->recovery_reason.
+ */
+#define SET_BOOT_MODE(ctx, boot_mode, ...) \
+ _set_boot_mode(ctx, boot_mode, ##__VA_ARGS__, 0)
diff --git a/tests/test_common.c b/tests/common/tests.c
similarity index 98%
rename from tests/test_common.c
rename to tests/common/tests.c
index 2ce3a5d..7df1613 100644
--- a/tests/test_common.c
+++ b/tests/common/tests.c
@@ -10,7 +10,7 @@
#include <string.h>
#include "2common.h"
-#include "test_common.h"
+#include "common/tests.h"
/* Global test success flag. */
int gTestSuccess = 1;
diff --git a/tests/test_common.h b/tests/common/tests.h
similarity index 96%
rename from tests/test_common.h
rename to tests/common/tests.h
index c3da880..656e2d9 100644
--- a/tests/test_common.h
+++ b/tests/common/tests.h
@@ -3,8 +3,8 @@
* found in the LICENSE file.
*/
-#ifndef VBOOT_REFERENCE_TEST_COMMON_H_
-#define VBOOT_REFERENCE_TEST_COMMON_H_
+#ifndef VBOOT_REFERENCE_COMMON_TESTS_H_
+#define VBOOT_REFERENCE_COMMON_TESTS_H_
#include <setjmp.h>
#include <stdio.h>
@@ -164,4 +164,4 @@
abort(); \
} while (0)
-#endif /* VBOOT_REFERENCE_TEST_COMMON_H_ */
+#endif /* VBOOT_REFERENCE_COMMON_TESTS_H_ */
diff --git a/tests/timer_utils.c b/tests/common/timer_utils.c
similarity index 100%
rename from tests/timer_utils.c
rename to tests/common/timer_utils.c
diff --git a/tests/timer_utils.h b/tests/common/timer_utils.h
similarity index 79%
rename from tests/timer_utils.h
rename to tests/common/timer_utils.h
index 8cafdf9..b2a424a 100644
--- a/tests/timer_utils.h
+++ b/tests/common/timer_utils.h
@@ -3,8 +3,8 @@
* found in the LICENSE file.
*/
-#ifndef VBOOT_REFERENCE_TIMER_UTILS_H_
-#define VBOOT_REFERENCE_TIMER_UTILS_H_
+#ifndef VBOOT_REFERENCE_COMMON_TIMER_UTILS_H_
+#define VBOOT_REFERENCE_COMMON_TIMER_UTILS_H_
#include <inttypes.h>
#include <time.h>
@@ -23,4 +23,4 @@
/* Get duration in milliseconds. */
uint32_t GetDurationMsecs(ClockTimerState* ct);
-#endif /* VBOOT_REFERENCE_TIMER_UTILS_H_ */
+#endif /* VBOOT_REFERENCE_COMMON_TIMER_UTILS_H_ */
diff --git a/tests/crc32_test.c b/tests/crc32_test.c
index 1d1d8cd..ee60cc0 100644
--- a/tests/crc32_test.c
+++ b/tests/crc32_test.c
@@ -4,9 +4,9 @@
*/
#include "cgptlib_test.h"
+#include "common/tests.h"
#include "crc32.h"
#include "crc32_test.h"
-#include "test_common.h"
#define MAX_VECTOR_LEN 256
diff --git a/tests/devkeys/arv_platform.keyblock b/tests/devkeys/arv_platform.keyblock
new file mode 100644
index 0000000..f3c976c
--- /dev/null
+++ b/tests/devkeys/arv_platform.keyblock
Binary files differ
diff --git a/tests/external_rsa_signer.sh b/tests/external_rsa_signer.sh
index 0724b87..405df42 100755
--- a/tests/external_rsa_signer.sh
+++ b/tests/external_rsa_signer.sh
@@ -1,9 +1,13 @@
#!/bin/bash
+# Copyright (c) 2010 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.
+
if [ $# -ne 1 ]; then
echo "Usage: $0 <private_key_pem_file>"
echo "Reads data to sign from stdin, encrypted data is output to stdout"
exit 1
fi
-openssl rsautl -sign -inkey $1
+openssl rsautl -sign -inkey "$1"
diff --git a/tests/futility/data/README b/tests/futility/data/README
index 6723f3d..3d577b8 100644
--- a/tests/futility/data/README
+++ b/tests/futility/data/README
@@ -1,6 +1,7 @@
These are officially signed BIOS images from existing Chromebooks.
- bios_mario_mp.bin uses old names for the FMAP areas
- bios_zgb_mp.bin RW firmware A and B are different
bios_link_mp.bin uses the RO_NORMAL flag to skip RW firmware validation
bios_peppy_mp.bin doesn't do any of those things
+
+This is dev-signed BIOS image with CBFS support:
+ bios_voxel_dev.bin
diff --git a/tests/futility/data/bios_mario_mp.bin b/tests/futility/data/bios_mario_mp.bin
deleted file mode 100644
index 8a6e8c5..0000000
--- a/tests/futility/data/bios_mario_mp.bin
+++ /dev/null
Binary files differ
diff --git a/tests/futility/data/bios_peppy_dev.bad_keyblock_data_key_offset_too_big.xxd.patch b/tests/futility/data/bios_peppy_dev.bad_keyblock_data_key_offset_too_big.xxd.patch
new file mode 100644
index 0000000..cb79555
--- /dev/null
+++ b/tests/futility/data/bios_peppy_dev.bad_keyblock_data_key_offset_too_big.xxd.patch
@@ -0,0 +1 @@
+00200050: b808 0000 0000 0000 0804 0000 0000 0000 ................
diff --git a/tests/futility/data/bios_peppy_dev.bad_keyblock_data_key_size_big.xxd.patch b/tests/futility/data/bios_peppy_dev.bad_keyblock_data_key_size_big.xxd.patch
new file mode 100644
index 0000000..8667c3f
--- /dev/null
+++ b/tests/futility/data/bios_peppy_dev.bad_keyblock_data_key_size_big.xxd.patch
@@ -0,0 +1 @@
+00200050: 2000 0000 0000 0000 3412 0100 0000 0000 .......4.......
diff --git a/tests/futility/data/bios_peppy_dev.bad_keyblock_fmap_too_small.xxd.patch b/tests/futility/data/bios_peppy_dev.bad_keyblock_fmap_too_small.xxd.patch
new file mode 100644
index 0000000..2c01f2a
--- /dev/null
+++ b/tests/futility/data/bios_peppy_dev.bad_keyblock_fmap_too_small.xxd.patch
@@ -0,0 +1,2 @@
+00610100: 0000 0000 0000 0000 0100 0000 2000 6e00 ............ .n.
+00610110: 0000 5642 4c4f 434b 5f41 0000 0000 0000 ..VBLOCK_A......
diff --git a/tests/futility/data/bios_peppy_dev.bad_keyblock_fmap_too_small_for_whole.xxd.patch b/tests/futility/data/bios_peppy_dev.bad_keyblock_fmap_too_small_for_whole.xxd.patch
new file mode 100644
index 0000000..3d79703
--- /dev/null
+++ b/tests/futility/data/bios_peppy_dev.bad_keyblock_fmap_too_small_for_whole.xxd.patch
@@ -0,0 +1,2 @@
+00610100: 0000 0000 0000 0000 0100 0000 2000 b608 ............ ...
+00610110: 0000 5642 4c4f 434b 5f41 0000 0000 0000 ..VBLOCK_A......
diff --git a/tests/futility/data/bios_peppy_dev.bad_keyblock_hash_data_size_too_small.xxd.patch b/tests/futility/data/bios_peppy_dev.bad_keyblock_hash_data_size_too_small.xxd.patch
new file mode 100644
index 0000000..4f284d9
--- /dev/null
+++ b/tests/futility/data/bios_peppy_dev.bad_keyblock_hash_data_size_too_small.xxd.patch
@@ -0,0 +1 @@
+00200040: 6c00 0000 0000 0000 1700 0000 0000 0000 l...............
diff --git a/tests/futility/data/bios_peppy_dev.bad_keyblock_hash_invalid_contents.xxd.patch b/tests/futility/data/bios_peppy_dev.bad_keyblock_hash_invalid_contents.xxd.patch
new file mode 100644
index 0000000..8b5fefd
--- /dev/null
+++ b/tests/futility/data/bios_peppy_dev.bad_keyblock_hash_invalid_contents.xxd.patch
@@ -0,0 +1 @@
+00200470: babb 3f4b 95db d458 4142 4344 4142 4344 ..?K...XABCDABCD
diff --git a/tests/futility/data/bios_peppy_dev.bad_keyblock_hash_offset_too_big.xxd.patch b/tests/futility/data/bios_peppy_dev.bad_keyblock_hash_offset_too_big.xxd.patch
new file mode 100644
index 0000000..1a7044c
--- /dev/null
+++ b/tests/futility/data/bios_peppy_dev.bad_keyblock_hash_offset_too_big.xxd.patch
@@ -0,0 +1 @@
+00200030: 9808 0000 0000 0000 4000 0000 0000 0000 ........@.......
diff --git a/tests/futility/data/bios_peppy_dev.bad_keyblock_hash_size_too_big.xxd.patch b/tests/futility/data/bios_peppy_dev.bad_keyblock_hash_size_too_big.xxd.patch
new file mode 100644
index 0000000..e6d90bf
--- /dev/null
+++ b/tests/futility/data/bios_peppy_dev.bad_keyblock_hash_size_too_big.xxd.patch
@@ -0,0 +1 @@
+00200030: 4804 0000 0000 0000 b808 0000 0000 0000 H...............
diff --git a/tests/futility/data/bios_peppy_dev.bad_keyblock_invalid_magic.xxd.patch b/tests/futility/data/bios_peppy_dev.bad_keyblock_invalid_magic.xxd.patch
new file mode 100644
index 0000000..00015e2
--- /dev/null
+++ b/tests/futility/data/bios_peppy_dev.bad_keyblock_invalid_magic.xxd.patch
@@ -0,0 +1 @@
+00200000: 4142 4344 4143 4244 0200 0000 0100 0000 ABCDACBD........
diff --git a/tests/futility/data/bios_peppy_dev.bad_keyblock_invalid_major_version.xxd.patch b/tests/futility/data/bios_peppy_dev.bad_keyblock_invalid_major_version.xxd.patch
new file mode 100644
index 0000000..637b90a
--- /dev/null
+++ b/tests/futility/data/bios_peppy_dev.bad_keyblock_invalid_major_version.xxd.patch
@@ -0,0 +1 @@
+00200000: 4348 524f 4d45 4f53 0200 0000 0200 0000 CHROMEOS........
diff --git a/tests/futility/data/bios_peppy_dev.bad_keyblock_size_not_fully_signed.xxd.patch b/tests/futility/data/bios_peppy_dev.bad_keyblock_size_not_fully_signed.xxd.patch
new file mode 100644
index 0000000..1a24d43
--- /dev/null
+++ b/tests/futility/data/bios_peppy_dev.bad_keyblock_size_not_fully_signed.xxd.patch
@@ -0,0 +1 @@
+00200010: 7604 0000 0000 0000 a004 0000 0000 0000 v...............
diff --git a/tests/futility/data/bios_peppy_dev.bad_preamble_body_signature_offset_too_big.xxd.patch b/tests/futility/data/bios_peppy_dev.bad_preamble_body_signature_offset_too_big.xxd.patch
new file mode 100644
index 0000000..31408e5
--- /dev/null
+++ b/tests/futility/data/bios_peppy_dev.bad_preamble_body_signature_offset_too_big.xxd.patch
@@ -0,0 +1 @@
+00200900: 0100 0000 0000 0000 7408 0000 0000 0000 ........t.......
diff --git a/tests/futility/data/bios_peppy_dev.bad_preamble_body_signature_size_too_big.xxd.patch b/tests/futility/data/bios_peppy_dev.bad_preamble_body_signature_size_too_big.xxd.patch
new file mode 100644
index 0000000..083cfbe
--- /dev/null
+++ b/tests/futility/data/bios_peppy_dev.bad_preamble_body_signature_size_too_big.xxd.patch
@@ -0,0 +1 @@
+00200910: 7408 0000 0000 0000 183c 0200 0000 0000 t........<......
diff --git a/tests/futility/data/bios_peppy_dev.bad_preamble_fmap_too_small.xxd.patch b/tests/futility/data/bios_peppy_dev.bad_preamble_fmap_too_small.xxd.patch
new file mode 100644
index 0000000..0f0968d
--- /dev/null
+++ b/tests/futility/data/bios_peppy_dev.bad_preamble_fmap_too_small.xxd.patch
@@ -0,0 +1,2 @@
+00610100: 0000 0000 0000 0000 0100 0000 2000 ee08 ............ ...
+00610110: 0000 5642 4c4f 434b 5f41 0000 0000 0000 ..VBLOCK_A......
diff --git a/tests/futility/data/bios_peppy_dev.bad_preamble_fmap_too_small_for_whole.xxd.patch b/tests/futility/data/bios_peppy_dev.bad_preamble_fmap_too_small_for_whole.xxd.patch
new file mode 100644
index 0000000..bd75624
--- /dev/null
+++ b/tests/futility/data/bios_peppy_dev.bad_preamble_fmap_too_small_for_whole.xxd.patch
@@ -0,0 +1,2 @@
+00610100: 0000 0000 0000 0000 0100 0000 2000 2411 ............ .$.
+00610110: 0000 5642 4c4f 434b 5f41 0000 0000 0000 ..VBLOCK_A......
diff --git a/tests/futility/data/bios_peppy_dev.bad_preamble_header_version_major.xxd.patch b/tests/futility/data/bios_peppy_dev.bad_preamble_header_version_major.xxd.patch
new file mode 100644
index 0000000..456a753
--- /dev/null
+++ b/tests/futility/data/bios_peppy_dev.bad_preamble_header_version_major.xxd.patch
@@ -0,0 +1 @@
+002008d0: 7406 0000 0000 0000 0300 0000 0100 0000 t...............
diff --git a/tests/futility/data/bios_peppy_dev.bad_preamble_header_version_minor.xxd.patch b/tests/futility/data/bios_peppy_dev.bad_preamble_header_version_minor.xxd.patch
new file mode 100644
index 0000000..140b44e
--- /dev/null
+++ b/tests/futility/data/bios_peppy_dev.bad_preamble_header_version_minor.xxd.patch
@@ -0,0 +1 @@
+002008d0: 7406 0000 0000 0000 0200 0000 0000 0000 t...............
diff --git a/tests/futility/data/bios_peppy_dev.bad_preamble_kernel_subkey_offset_too_big.xxd.patch b/tests/futility/data/bios_peppy_dev.bad_preamble_kernel_subkey_offset_too_big.xxd.patch
new file mode 100644
index 0000000..3c5a14c
--- /dev/null
+++ b/tests/futility/data/bios_peppy_dev.bad_preamble_kernel_subkey_offset_too_big.xxd.patch
@@ -0,0 +1 @@
+002008f0: 7408 0000 0000 0000 0700 0000 0000 0000 t...............
diff --git a/tests/futility/data/bios_peppy_dev.bad_preamble_kernel_subkey_size_too_big.xxd.patch b/tests/futility/data/bios_peppy_dev.bad_preamble_kernel_subkey_size_too_big.xxd.patch
new file mode 100644
index 0000000..3c5a14c
--- /dev/null
+++ b/tests/futility/data/bios_peppy_dev.bad_preamble_kernel_subkey_size_too_big.xxd.patch
@@ -0,0 +1 @@
+002008f0: 7408 0000 0000 0000 0700 0000 0000 0000 t...............
diff --git a/tests/futility/data/bios_peppy_dev.bad_preamble_signature_data_size_too_big.xxd.patch b/tests/futility/data/bios_peppy_dev.bad_preamble_signature_data_size_too_big.xxd.patch
new file mode 100644
index 0000000..f23f2e1
--- /dev/null
+++ b/tests/futility/data/bios_peppy_dev.bad_preamble_signature_data_size_too_big.xxd.patch
@@ -0,0 +1 @@
+002008d0: 8408 0000 0000 0000 0200 0000 0100 0000 ................
diff --git a/tests/futility/data/bios_peppy_dev.bad_preamble_signature_data_size_too_small.xxd.patch b/tests/futility/data/bios_peppy_dev.bad_preamble_signature_data_size_too_small.xxd.patch
new file mode 100644
index 0000000..b02b497
--- /dev/null
+++ b/tests/futility/data/bios_peppy_dev.bad_preamble_signature_data_size_too_small.xxd.patch
@@ -0,0 +1 @@
+002008d0: 6400 0000 0000 0000 0200 0000 0100 0000 d...............
diff --git a/tests/futility/data/bios_peppy_dev.bad_preamble_signature_invalid_contents.xxd.patch b/tests/futility/data/bios_peppy_dev.bad_preamble_signature_invalid_contents.xxd.patch
new file mode 100644
index 0000000..0fed2fe
--- /dev/null
+++ b/tests/futility/data/bios_peppy_dev.bad_preamble_signature_invalid_contents.xxd.patch
@@ -0,0 +1,2 @@
+00200f20: 78c9 3a24 85ab ca17 498e c238 4142 4344 x.:$....I..8ABCD
+00200f30: 4142 4344 1cef bf68 b86b cdbc 3782 9f85 ABCD...h.k..7...
diff --git a/tests/futility/data/bios_peppy_dev.bad_preamble_signature_offset_too_big.xxd.patch b/tests/futility/data/bios_peppy_dev.bad_preamble_signature_offset_too_big.xxd.patch
new file mode 100644
index 0000000..5159fef
--- /dev/null
+++ b/tests/futility/data/bios_peppy_dev.bad_preamble_signature_offset_too_big.xxd.patch
@@ -0,0 +1 @@
+002008c0: 7408 0000 0000 0000 0002 0000 0000 0000 t...............
diff --git a/tests/futility/data/bios_peppy_dev.bad_preamble_signature_size_too_big.xxd.patch b/tests/futility/data/bios_peppy_dev.bad_preamble_signature_size_too_big.xxd.patch
new file mode 100644
index 0000000..9afc0ab
--- /dev/null
+++ b/tests/futility/data/bios_peppy_dev.bad_preamble_signature_size_too_big.xxd.patch
@@ -0,0 +1 @@
+002008c0: 6c06 0000 0000 0000 7408 0000 0000 0000 l.......t.......
diff --git a/tests/futility/data/bios_peppy_dev.bin b/tests/futility/data/bios_peppy_dev.bin
new file mode 100644
index 0000000..f241cd0
--- /dev/null
+++ b/tests/futility/data/bios_peppy_dev.bin
Binary files differ
diff --git a/tests/futility/data/bios_voxel_dev.bin b/tests/futility/data/bios_voxel_dev.bin
new file mode 100644
index 0000000..7cd8535
--- /dev/null
+++ b/tests/futility/data/bios_voxel_dev.bin
Binary files differ
diff --git a/tests/futility/data/bios_voxel_dev.no_b_slot.xxd.patch b/tests/futility/data/bios_voxel_dev.no_b_slot.xxd.patch
new file mode 100644
index 0000000..6a01277
--- /dev/null
+++ b/tests/futility/data/bios_voxel_dev.no_b_slot.xxd.patch
@@ -0,0 +1,20 @@
+01804030: 0000 0000 0000 1e00 0000 0000 0000 5000 ..............P.
+018043a0: 0000 0000 0000 0000 0000 c0ff 4f01 4000 ............O.@.
+018043b0: 0000 5257 5f46 5749 445f 4200 0000 0000 ..RW_FWID_B.....
+018043d0: 0000 0000 0000 5001 0000 3000 4d45 5f52 ......P...0.ME_R
+018043e0: 575f 4200 0000 0000 0000 0000 0000 0000 W_B.............
+018043f0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
+01804400: 8001 0000 8000 5750 5f52 4f00 0000 0000 ......WP_RO.....
+01804420: 0000 0000 0000 0000 0000 8001 0040 0000 .............@..
+01804430: 524f 5f56 5044 0000 0000 0000 0000 0000 RO_VPD..........
+01804450: 0800 0040 8001 00c0 7f00 524f 5f53 4543 ...@......RO_SEC
+01804460: 5449 4f4e 0000 0000 0000 0000 0000 0000 TION............
+01804470: 0000 0000 0000 0000 0000 0000 0040 8001 .............@..
+01804480: 0008 0000 464d 4150 0000 0000 0000 0000 ....FMAP........
+018044a0: 0000 0000 0000 0048 8001 4000 0000 524f .......H..@...RO
+018044b0: 5f46 5249 4400 0000 0000 0000 0000 0000 _FRID...........
+018044d0: 0050 8001 0000 0700 4742 4200 0000 0000 .P......GBB.....
+018044f0: 0000 0000 0000 0000 0000 0050 8701 00b0 ...........P....
+01804500: 7800 434f 5245 424f 4f54 0000 0000 0000 x.COREBOOT......
+01804520: 0000 0000 0050 8701 00b0 7800 434f 5245 .....P....x.CORE
+01804530: 424f 4f54 0000 0000 0000 0000 0000 0000 BOOT............
diff --git a/tests/futility/data/bios_zgb_mp.bin b/tests/futility/data/bios_zgb_mp.bin
deleted file mode 100644
index c85d820..0000000
--- a/tests/futility/data/bios_zgb_mp.bin
+++ /dev/null
Binary files differ
diff --git a/tests/futility/data_bios_voxel_dev.bin_expect.txt b/tests/futility/data_bios_voxel_dev.bin_expect.txt
new file mode 100644
index 0000000..60cd1ea
--- /dev/null
+++ b/tests/futility/data_bios_voxel_dev.bin_expect.txt
@@ -0,0 +1,6 @@
+b11d74edd286c144e1135b49e7f0bc20cf041f10
+c14bd720b70d97394257e3e826bd8f43de48d4ed
+e2c1c92d7d7aa7dfed5e8375edd30b7ae52b7450
+5d2b220899c4403d564092ada3f12d3cc4483223
+e2c1c92d7d7aa7dfed5e8375edd30b7ae52b7450
+5d2b220899c4403d564092ada3f12d3cc4483223
diff --git a/tests/futility/data_bios_zgb_mp.bin_expect.txt b/tests/futility/data_bios_zgb_mp.bin_expect.txt
deleted file mode 100644
index 2a021ce..0000000
--- a/tests/futility/data_bios_zgb_mp.bin_expect.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-9f59876c7f7dc881f02d934786c6b7c2c17dcaac
-9bd99a594c45b6739899a17ec29ac2289ee75463
-a0e4415cd4e271802504cce3a211b54562178fc8
-5d2b220899c4403d564092ada3f12d3cc4483223
-e2c1c92d7d7aa7dfed5e8375edd30b7ae52b7450
-5d2b220899c4403d564092ada3f12d3cc4483223
diff --git a/tests/futility/expect_output/show.tests_futility_data_bios_mario_mp.bin b/tests/futility/expect_output/show.tests_futility_data_bios_mario_mp.bin
deleted file mode 100644
index 6039855..0000000
--- a/tests/futility/expect_output/show.tests_futility_data_bios_mario_mp.bin
+++ /dev/null
@@ -1,63 +0,0 @@
-BIOS: tests/futility/data/bios_mario_mp.bin
-GBB header: GBB Area
- Version: 1.0
- Flags: 0x00000000
- Regions: offset size
- hwid 0x00000080 0x00000100
- bmpvf 0x00001180 0x0003de80
- rootkey 0x00000180 0x00001000
- recovery_key 0x0003f000 0x00001000
- Size: 0x00040000 / 0x00040000
-GBB content:
- HWID: {9D799111-A88A-439E-9E1F-FBBB41B00A9A}
- digest: <none>
- Root Key:
- Vboot API: 1.0
- Algorithm: 11 RSA8192 SHA512
- Key Version: 1
- Key sha1sum: 541f467a7d8747f55ae9087ee4e34155f5ee3cd7
- Recovery Key:
- Vboot API: 1.0
- Algorithm: 11 RSA8192 SHA512
- Key Version: 1
- Key sha1sum: 5d0d163b824cab5ae4f23fb2cc012e2a4124f4fe
-Firmware body: Firmware A Data
- Offset: 0x00040000
- Size: 0x000d0000
-Firmware body: Firmware B Data
- Offset: 0x00120000
- Size: 0x000d0000
-Keyblock: Firmware A Key
- Signature: valid
- Size: 0x8b8
- Flags: 7 !DEV DEV !REC
- Data key algorithm: 8 RSA4096 SHA512
- Data key version: 1
- Data key sha1sum: cd72cfb929765f82baba0a01ed937a73f502f6c5
-Firmware Preamble:
- Size: 2164
- Header version: 2.1
- Firmware version: 1
- Kernel key algorithm: 8 RSA4096 SHA512
- Kernel key version: 1
- Kernel key sha1sum: e39e019cb5df3e874f443721540cb261a88c58ef
- Firmware body size: 851968
- Preamble flags: 0
-Body verification succeeded.
-Keyblock: Firmware B Key
- Signature: valid
- Size: 0x8b8
- Flags: 7 !DEV DEV !REC
- Data key algorithm: 8 RSA4096 SHA512
- Data key version: 1
- Data key sha1sum: cd72cfb929765f82baba0a01ed937a73f502f6c5
-Firmware Preamble:
- Size: 2164
- Header version: 2.1
- Firmware version: 1
- Kernel key algorithm: 8 RSA4096 SHA512
- Kernel key version: 1
- Kernel key sha1sum: e39e019cb5df3e874f443721540cb261a88c58ef
- Firmware body size: 851968
- Preamble flags: 0
-Body verification succeeded.
diff --git a/tests/futility/expect_output/show.tests_futility_data_bios_peppy_mp.bin b/tests/futility/expect_output/show.tests_futility_data_bios_peppy_mp.bin
new file mode 100644
index 0000000..88733c9
--- /dev/null
+++ b/tests/futility/expect_output/show.tests_futility_data_bios_peppy_mp.bin
@@ -0,0 +1,63 @@
+BIOS: tests/futility/data/bios_peppy_mp.bin
+GBB header: GBB
+ Version: 1.1
+ Flags: 0x00000039
+ Regions: offset size
+ hwid 0x00000080 0x00000100
+ bmpvf 0x00001180 0x000ece80
+ rootkey 0x00000180 0x00001000
+ recovery_key 0x000ee000 0x00001000
+ Size: 0x000ef000 / 0x000ef000
+GBB content:
+ HWID: X86 PEPPY TEST 4211
+ digest: <none>
+ Root Key:
+ Vboot API: 1.0
+ Algorithm: 11 RSA8192 SHA512
+ Key Version: 1
+ Key sha1sum: fc68bcb88bf9af1907289a9f377d658b3b9fe5b0
+ Recovery Key:
+ Vboot API: 1.0
+ Algorithm: 11 RSA8192 SHA512
+ Key Version: 1
+ Key sha1sum: bf39d0d3e30cbf6a121416d04df4603ad5310779
+Firmware body: FW_MAIN_A
+ Offset: 0x00210000
+ Size: 0x000c0000
+Firmware body: FW_MAIN_B
+ Offset: 0x00300000
+ Size: 0x000c0000
+Keyblock: VBLOCK_A
+ Signature: valid
+ Size: 0x8b8
+ Flags: 7 !DEV DEV !REC
+ Data key algorithm: 8 RSA4096 SHA512
+ Data key version: 1
+ Data key sha1sum: f917ad29e36aa8a286f978c1aa0550ea31c6a561
+Firmware Preamble:
+ Size: 2164
+ Header version: 2.1
+ Firmware version: 2
+ Kernel key algorithm: 7 RSA4096 SHA256
+ Kernel key version: 2
+ Kernel key sha1sum: cc05423373b76acbec23ec45dfa3696a2ea6dc0f
+ Firmware body size: 146456
+ Preamble flags: 0
+Body verification succeeded.
+Keyblock: VBLOCK_B
+ Signature: valid
+ Size: 0x8b8
+ Flags: 7 !DEV DEV !REC
+ Data key algorithm: 8 RSA4096 SHA512
+ Data key version: 1
+ Data key sha1sum: f917ad29e36aa8a286f978c1aa0550ea31c6a561
+Firmware Preamble:
+ Size: 2164
+ Header version: 2.1
+ Firmware version: 2
+ Kernel key algorithm: 7 RSA4096 SHA256
+ Kernel key version: 2
+ Kernel key sha1sum: cc05423373b76acbec23ec45dfa3696a2ea6dc0f
+ Firmware body size: 146456
+ Preamble flags: 0
+Body verification succeeded.
diff --git a/tests/futility/expect_output/show.tests_futility_data_bios_zgb_mp.bin b/tests/futility/expect_output/show.tests_futility_data_bios_zgb_mp.bin
deleted file mode 100644
index 2f9f807..0000000
--- a/tests/futility/expect_output/show.tests_futility_data_bios_zgb_mp.bin
+++ /dev/null
@@ -1,63 +0,0 @@
-BIOS: tests/futility/data/bios_zgb_mp.bin
-GBB header: GBB
- Version: 1.0
- Flags: 0x00000000
- Regions: offset size
- hwid 0x00000080 0x00000100
- bmpvf 0x00001180 0x0003de80
- rootkey 0x00000180 0x00001000
- recovery_key 0x0003f000 0x00001000
- Size: 0x00040000 / 0x00040000
-GBB content:
- HWID: {FA42644C-CF3A-4692-A9D3-1A667CB232E9}
- digest: <none>
- Root Key:
- Vboot API: 1.0
- Algorithm: 11 RSA8192 SHA512
- Key Version: 1
- Key sha1sum: 9f59876c7f7dc881f02d934786c6b7c2c17dcaac
- Recovery Key:
- Vboot API: 1.0
- Algorithm: 11 RSA8192 SHA512
- Key Version: 1
- Key sha1sum: 9bd99a594c45b6739899a17ec29ac2289ee75463
-Firmware body: FW_MAIN_A
- Offset: 0x00030000
- Size: 0x000dffc0
-Firmware body: FW_MAIN_B
- Offset: 0x00120000
- Size: 0x000dffc0
-Keyblock: VBLOCK_A
- Signature: valid
- Size: 0x8b8
- Flags: 6 DEV !REC
- Data key algorithm: 8 RSA4096 SHA512
- Data key version: 1
- Data key sha1sum: a78aaa1691c2125ef8ccefa1a8a6bea92d38fae6
-Firmware Preamble:
- Size: 2164
- Header version: 2.1
- Firmware version: 2
- Kernel key algorithm: 7 RSA4096 SHA256
- Kernel key version: 2
- Kernel key sha1sum: 0c9fd5b03ab47d37924ba8a7beb64039d84ed0e1
- Firmware body size: 917440
- Preamble flags: 0
-Body verification succeeded.
-Keyblock: VBLOCK_B
- Signature: valid
- Size: 0x8b8
- Flags: 7 !DEV DEV !REC
- Data key algorithm: 8 RSA4096 SHA512
- Data key version: 1
- Data key sha1sum: 4fe08ed739069d6834b68612eb707998a0825f34
-Firmware Preamble:
- Size: 2164
- Header version: 2.1
- Firmware version: 2
- Kernel key algorithm: 7 RSA4096 SHA256
- Kernel key version: 2
- Kernel key sha1sum: 0c9fd5b03ab47d37924ba8a7beb64039d84ed0e1
- Firmware body size: 917440
- Preamble flags: 0
-Body verification succeeded.
diff --git a/tests/futility/models/whitetip/setvars.sh b/tests/futility/models/customtip/setvars.sh
similarity index 87%
rename from tests/futility/models/whitetip/setvars.sh
rename to tests/futility/models/customtip/setvars.sh
index 4b9cb40..a4bb55a 100755
--- a/tests/futility/models/whitetip/setvars.sh
+++ b/tests/futility/models/customtip/setvars.sh
@@ -7,14 +7,14 @@
# particular model. The pack_firmware.py script uses this to create a working
# setvars-model.sh script.
-# Version information for model whitetip
+# Version information for model customtip
TARGET_RO_FWID="Google_Coral.10068.45.0"
TARGET_FWID="Google_Coral.10068.45.0"
TARGET_ECID="coral_v1.1.7272-0b44fba22"
TARGET_PDID=""
TARGET_PLATFORM="Google_Coral"
-# Image and key files for model whitetip
+# Image and key files for model customtip
IMAGE_MAIN="images/bios_coral.bin"
IMAGE_EC=""
IMAGE_PD=""
diff --git a/tests/futility/run_test_scripts.sh b/tests/futility/run_test_scripts.sh
index f224bdf..aeb3477 100755
--- a/tests/futility/run_test_scripts.sh
+++ b/tests/futility/run_test_scripts.sh
@@ -62,11 +62,11 @@
if [ ! "$rc" ]; then
echo -e "${COL_GREEN}PASSED${COL_STOP}"
: $(( pass++ ))
- rm -f ${OUTDIR}/$j.{stdout,stderr,return}
+ rm -f "${OUTDIR}/$j".{stdout,stderr,return}
else
echo -e "${COL_RED}FAILED (${rc:-0}). Stdout is recorded in" \
"${OUTDIR}/$j.stdout${COL_STOP}"
- cat ${OUTDIR}/$j.stderr
+ cat "${OUTDIR}/$j.stderr"
fi
done
diff --git a/tests/futility/test_create.sh b/tests/futility/test_create.sh
index 55c648c..77c7eb4 100755
--- a/tests/futility/test_create.sh
+++ b/tests/futility/test_create.sh
@@ -15,7 +15,7 @@
# Demonstrate that we can recreate the same vb1 keys without the .keyb files
for sig in rsa1024 rsa2048 rsa4096 rsa8192; do
for hash in sha1 sha256 sha512; do
- ${FUTILITY} --vb1 create --hash_alg "${hash}" \
+ "${FUTILITY}" --vb1 create --hash_alg "${hash}" \
"${TESTKEYS}/key_${sig}.pem" "${TMP}_key_${sig}.${hash}"
cmp "${TESTKEYS}/key_${sig}.${hash}.vbprivk" \
"${TMP}_key_${sig}.${hash}.vbprivk"
@@ -29,7 +29,7 @@
# prove anything until we've used them to sign some stuff, though.
for sig in rsa1024 rsa2048 rsa4096 rsa8192; do
for hash in sha1 sha256 sha512; do
- ${FUTILITY} --vb21 create --hash_alg "${hash}" \
+ "${FUTILITY}" --vb21 create --hash_alg "${hash}" \
"${TESTKEYS}/key_${sig}.pem" "${TMP}_key_${sig}.${hash}"
done
done
@@ -37,12 +37,12 @@
# Demonstrate that the sha1sums are the same for all the keys created from the
# same .pem files, both public and private, vb1 and vb21.
for sig in rsa1024 rsa2048 rsa4096 rsa8192; do
- pem_sum=$(${FUTILITY} show "${TESTKEYS}/key_${sig}.pem" |
+ pem_sum=$("${FUTILITY}" show "${TESTKEYS}/key_${sig}.pem" |
awk '/sha1sum/ {print $3}')
# expect only one
- [ $(echo "$pem_sum" | wc -w) = 1 ]
- num_keys=$(echo ${TMP}_key_${sig}.* | wc -w)
- key_sums=$(${FUTILITY} show ${TMP}_key_${sig}.* |
+ [ "$(echo "$pem_sum" | wc -w)" = 1 ]
+ num_keys=$(echo "${TMP}_key_${sig}".* | wc -w)
+ key_sums=$("${FUTILITY}" show "${TMP}_key_${sig}".* |
awk '/sha1sum:|ID:/ {print $NF}')
num_sums=$(echo "$key_sums" | wc -w)
# expect one sha1sum (or ID) line per file
@@ -57,7 +57,7 @@
# the private key.
for sig in rsa1024 rsa2048 rsa4096 rsa8192; do
for hash in sha1 sha256 sha512; do
- ${FUTILITY} --vb21 create --hash_alg "${hash}" \
+ "${FUTILITY}" --vb21 create --hash_alg "${hash}" \
"${TESTKEYS}/key_${sig}.pub.pem" "${TMP}_key_${sig}.pubonly.${hash}"
cmp "${TMP}_key_${sig}.pubonly.${hash}.vbpubk2" \
"${TMP}_key_${sig}.${hash}.vbpubk2"
@@ -65,5 +65,5 @@
done
# cleanup
-rm -rf ${TMP}*
+rm -rf "${TMP}"*
exit 0
diff --git a/tests/futility/test_dump_fmap.sh b/tests/futility/test_dump_fmap.sh
index 5ae2e97..b8e418a 100755
--- a/tests/futility/test_dump_fmap.sh
+++ b/tests/futility/test_dump_fmap.sh
@@ -51,5 +51,5 @@
# cleanup
-rm -f ${TMP}* FMAP SI_DESC FOO
+rm -f "${TMP}"* FMAP SI_DESC FOO
exit 0
diff --git a/tests/futility/test_file_types.c b/tests/futility/test_file_types.c
index 3f88872..ee433ba 100644
--- a/tests/futility/test_file_types.c
+++ b/tests/futility/test_file_types.c
@@ -10,7 +10,7 @@
#include "file_type.h"
#include "futility.h"
-#include "test_common.h"
+#include "common/tests.h"
/*
* Files that exemplify each type.
@@ -26,8 +26,7 @@
{FILE_TYPE_KEYBLOCK, "tests/devkeys/kernel.keyblock"},
{FILE_TYPE_FW_PREAMBLE, "tests/futility/data/fw_vblock.bin"},
{FILE_TYPE_GBB, "tests/futility/data/fw_gbb.bin"},
- {FILE_TYPE_BIOS_IMAGE, "tests/futility/data/bios_zgb_mp.bin"},
- {FILE_TYPE_OLD_BIOS_IMAGE, "tests/futility/data/bios_mario_mp.bin"},
+ {FILE_TYPE_BIOS_IMAGE, "tests/futility/data/bios_peppy_mp.bin"},
{FILE_TYPE_KERN_PREAMBLE, "tests/futility/data/kern_preamble.bin"},
{FILE_TYPE_RAW_FIRMWARE, }, /* need a test for this */
{FILE_TYPE_RAW_KERNEL, }, /* need a test for this */
diff --git a/tests/futility/test_file_types.sh b/tests/futility/test_file_types.sh
index 4b7a9fb..313e408 100755
--- a/tests/futility/test_file_types.sh
+++ b/tests/futility/test_file_types.sh
@@ -16,13 +16,13 @@
# Args are <expected_type>, <file_to_probe>
test_case() {
local result
- result=$(${FUTILITY} show -t "${SRCDIR}/$2" | awk '{print $NF}')
+ result=$("${FUTILITY}" show -t "${SRCDIR}/$2" | awk '{print $NF}')
[ "$1" = "$result" ]
}
# Arg is <file_to_probe>
fail_case() {
- if ${FUTILITY} show -t "$1" ; then false; else true; fi
+ if "${FUTILITY}" show -t "$1" ; then false; else true; fi
}
# Known types
@@ -32,8 +32,7 @@
test_case "keyblock" "tests/devkeys/kernel.keyblock"
test_case "fw_pre" "tests/futility/data/fw_vblock.bin"
test_case "gbb" "tests/futility/data/fw_gbb.bin"
-test_case "bios" "tests/futility/data/bios_zgb_mp.bin"
-test_case "oldbios" "tests/futility/data/bios_mario_mp.bin"
+test_case "bios" "tests/futility/data/bios_peppy_mp.bin"
test_case "kernel" "tests/futility/data/kern_preamble.bin"
# We don't have a way to identify these (yet?)
# test_case "RAW_FIRMWARE"
@@ -55,22 +54,23 @@
# often won't work, but it certainly shouldn't core dump.
# We'll ask futility to tell us what types it supports
-TYPES=$(${FUTILITY} show --type help | awk '/^ +/ {print $1}')
+TYPES=$("${FUTILITY}" show --type help | awk '/^ +/ {print $1}')
# And we'll just reuse the same files above.
-FILES=$(awk '/^test_case / {print $NF}' $0 | tr -d '"')
+FILES=$(awk '/^test_case / {print $NF}' "$0" | tr -d '"')
# futility should normally exit with either 0 or 1. Make sure that happens.
# NOTE: /bin/bash returns values > 125 for special problems like signals.
# I welcome patches to do this more portably.
for type in $TYPES; do
for file in $FILES; do
- ${FUTILITY} show --type ${type} "${SRCDIR}/${file}" && rc=$? || rc=$?
+ "${FUTILITY}" show --type "${type}" "${SRCDIR}/${file}" && \
+ rc=$? || rc=$?
[ "$rc" -le 2 ]
done
done
# cleanup
-rm -rf ${TMP}*
+rm -rf "${TMP}"*
exit 0
diff --git a/tests/futility/test_gbb_utility.sh b/tests/futility/test_gbb_utility.sh
index bdfa262..5b783c4 100755
--- a/tests/futility/test_gbb_utility.sh
+++ b/tests/futility/test_gbb_utility.sh
@@ -15,56 +15,58 @@
# First, let's test the basic functionality
# For simplicity, we'll use the same size for all properties.
-${FUTILITY} gbb -c 16,0x10,16,0x10 ${TMP}.blob
+"${FUTILITY}" gbb -c 16,0x10,16,0x10 "${TMP}.blob"
# Flags
-${FUTILITY} gbb -s --flags=0xdeadbeef ${TMP}.blob
-${FUTILITY} gbb -g --flags ${TMP}.blob | grep -i 0xdeadbeef
+"${FUTILITY}" gbb -s --flags=0xdeadbeef "${TMP}.blob"
+"${FUTILITY}" gbb -g --flags "${TMP}.blob" | grep -i 0xdeadbeef
# HWID length should include the terminating null - this is too long
-if ${FUTILITY} gbb -s --hwid="0123456789ABCDEF" ${TMP}.blob; then
+if "${FUTILITY}" gbb -s --hwid="0123456789ABCDEF" "${TMP}.blob"; then
false;
fi
# This works
-${FUTILITY} gbb -s --hwid="0123456789ABCDE" ${TMP}.blob
+"${FUTILITY}" gbb -s --hwid="0123456789ABCDE" "${TMP}.blob"
# Read it back?
-${FUTILITY} gbb -g ${TMP}.blob | grep "0123456789ABCDE"
+"${FUTILITY}" gbb -g "${TMP}.blob" | grep "0123456789ABCDE"
# Same kind of tests for the other fields, but they need binary files.
# too long
-dd if=/dev/urandom bs=17 count=1 of=${TMP}.data1.toolong
-dd if=/dev/urandom bs=17 count=1 of=${TMP}.data2.toolong
-if ${FUTILITY} gbb -s --rootkey ${TMP}.data1.toolong ${TMP}.blob; then false; fi
-if ${FUTILITY} gbb -s --recoverykey ${TMP}.data2.toolong ${TMP}.blob; then false; fi
+dd if=/dev/urandom bs=17 count=1 of="${TMP}.data1.toolong"
+dd if=/dev/urandom bs=17 count=1 of="${TMP}.data2.toolong"
+if "${FUTILITY}" gbb -s --rootkey "${TMP}.data1.toolong" "${TMP}.blob";
+ then false; fi
+if "${FUTILITY}" gbb -s --recoverykey "${TMP}.data2.toolong" "${TMP}.blob";
+ then false; fi
# shorter than max should be okay, though
-dd if=/dev/urandom bs=10 count=1 of=${TMP}.data1.short
-dd if=/dev/urandom bs=10 count=1 of=${TMP}.data2.short
-${FUTILITY} gbb -s \
- --rootkey ${TMP}.data1.short \
- --recoverykey ${TMP}.data2.short ${TMP}.blob
+dd if=/dev/urandom bs=10 count=1 of="${TMP}.data1.short"
+dd if=/dev/urandom bs=10 count=1 of="${TMP}.data2.short"
+"${FUTILITY}" gbb -s \
+ --rootkey "${TMP}.data1.short" \
+ --recoverykey "${TMP}.data2.short" "${TMP}.blob"
# read 'em back
-${FUTILITY} gbb -g \
- --rootkey ${TMP}.read1 \
- --recoverykey ${TMP}.read2 ${TMP}.blob
+"${FUTILITY}" gbb -g \
+ --rootkey "${TMP}.read1" \
+ --recoverykey "${TMP}.read2" "${TMP}.blob"
# Verify (but remember, it's short)
-cmp -n 10 ${TMP}.data1.short ${TMP}.read1
-cmp -n 10 ${TMP}.data2.short ${TMP}.read2
+cmp -n 10 "${TMP}.data1.short" "${TMP}.read1"
+cmp -n 10 "${TMP}.data2.short" "${TMP}.read2"
# Okay
-dd if=/dev/urandom bs=16 count=1 of=${TMP}.data1
-dd if=/dev/urandom bs=16 count=1 of=${TMP}.data2
-dd if=/dev/urandom bs=16 count=1 of=${TMP}.data3
-${FUTILITY} gbb -s --rootkey ${TMP}.data1 ${TMP}.blob
-${FUTILITY} gbb -s --recoverykey ${TMP}.data2 ${TMP}.blob
+dd if=/dev/urandom bs=16 count=1 of="${TMP}.data1"
+dd if=/dev/urandom bs=16 count=1 of="${TMP}.data2"
+dd if=/dev/urandom bs=16 count=1 of="${TMP}.data3"
+"${FUTILITY}" gbb -s --rootkey "${TMP}.data1" "${TMP}.blob"
+"${FUTILITY}" gbb -s --recoverykey "${TMP}.data2" "${TMP}.blob"
# Read 'em back.
-${FUTILITY} gbb -g --rootkey ${TMP}.read1 ${TMP}.blob
-${FUTILITY} gbb -g --recoverykey ${TMP}.read2 ${TMP}.blob
+"${FUTILITY}" gbb -g --rootkey "${TMP}.read1" "${TMP}.blob"
+"${FUTILITY}" gbb -g --recoverykey "${TMP}.read2" "${TMP}.blob"
# Verify
-cmp ${TMP}.data1 ${TMP}.read1
-cmp ${TMP}.data2 ${TMP}.read2
+cmp "${TMP}.data1" "${TMP}.read1"
+cmp "${TMP}.data2" "${TMP}.read2"
# Okay, creating GBB blobs seems to work. Now let's make sure that corrupted
@@ -100,82 +102,85 @@
#
# bad major_version
-cat ${TMP}.blob | ${REPLACE} 0x4 2 > ${TMP}.blob.bad
-if ${FUTILITY} gbb ${TMP}.blob.bad; then false; fi
+"${REPLACE}" 0x4 2 < "${TMP}.blob" > "${TMP}.blob.bad"
+if "${FUTILITY}" gbb "${TMP}.blob.bad"; then false; fi
# header size too large
-cat ${TMP}.blob | ${REPLACE} 0x8 0x81 > ${TMP}.blob.bad
-if ${FUTILITY} gbb ${TMP}.blob.bad; then false; fi
+"${REPLACE}" 0x8 0x81 < "${TMP}.blob" > "${TMP}.blob.bad"
+if "${FUTILITY}" gbb "${TMP}.blob.bad"; then false; fi
# header size too small
-cat ${TMP}.blob | ${REPLACE} 0x8 0x7f > ${TMP}.blob.bad
-if ${FUTILITY} gbb ${TMP}.blob.bad; then false; fi
+"${REPLACE}" 0x8 0x7f < "${TMP}.blob" > "${TMP}.blob.bad"
+if "${FUTILITY}" gbb "${TMP}.blob.bad"; then false; fi
# HWID not null-terminated is invalid
-cat ${TMP}.blob | ${REPLACE} 0x8f 0x41 > ${TMP}.blob.bad
-if ${FUTILITY} gbb ${TMP}.blob.bad; then false; fi
+"${REPLACE}" 0x8f 0x41 < "${TMP}.blob" > "${TMP}.blob.bad"
+if "${FUTILITY}" gbb "${TMP}.blob.bad"; then false; fi
# HWID of length zero is okay
-cat ${TMP}.blob | ${REPLACE} 0x14 0x00 > ${TMP}.blob.ok
-${FUTILITY} gbb ${TMP}.blob.ok
+"${REPLACE}" 0x14 0x00 < "${TMP}.blob" > "${TMP}.blob.ok"
+"${FUTILITY}" gbb "${TMP}.blob.ok"
# And HWID of length 1 consisting only of '\0' is okay, too.
-cat ${TMP}.blob | ${REPLACE} 0x14 0x01 | ${REPLACE} 0x80 0x00 > ${TMP}.blob.ok
-${FUTILITY} gbb ${TMP}.blob.ok
+"${REPLACE}" 0x14 0x01 < "${TMP}.blob" | "${REPLACE}" 0x80 0x00 \
+ > "${TMP}.blob.ok"
+"${FUTILITY}" gbb "${TMP}.blob.ok"
# zero-length HWID not null-terminated is invalid
-cat ${TMP}.blob | ${REPLACE} 0x8f 0x41 > ${TMP}.blob.bad
-if ${FUTILITY} gbb ${TMP}.blob.bad; then false; fi
+"${REPLACE}" 0x8f 0x41 < "${TMP}.blob" > "${TMP}.blob.bad"
+if "${FUTILITY}" gbb "${TMP}.blob.bad"; then false; fi
# hwid_offset < GBB_HEADER_SIZE is invalid
-cat ${TMP}.blob | ${REPLACE} 0x10 0x7f > ${TMP}.blob.bad
-if ${FUTILITY} gbb ${TMP}.blob.bad; then false; fi
-cat ${TMP}.blob | ${REPLACE} 0x10 0x00 > ${TMP}.blob.bad
-if ${FUTILITY} gbb ${TMP}.blob.bad; then false; fi
+"${REPLACE}" 0x10 0x7f < "${TMP}.blob" > "${TMP}.blob.bad"
+if "${FUTILITY}" gbb "${TMP}.blob.bad"; then false; fi
+"${REPLACE}" 0x10 0x00 < "${TMP}.blob" > "${TMP}.blob.bad"
+if "${FUTILITY}" gbb "${TMP}.blob.bad"; then false; fi
# rootkey_offset < GBB_HEADER_SIZE is invalid
-cat ${TMP}.blob | ${REPLACE} 0x18 0x7f > ${TMP}.blob.bad
-if ${FUTILITY} gbb ${TMP}.blob.bad; then false; fi
-cat ${TMP}.blob | ${REPLACE} 0x18 0x00 > ${TMP}.blob.bad
-if ${FUTILITY} gbb ${TMP}.blob.bad; then false; fi
+"${REPLACE}" 0x18 0x7f < "${TMP}.blob" > "${TMP}.blob.bad"
+if "${FUTILITY}" gbb "${TMP}.blob.bad"; then false; fi
+"${REPLACE}" 0x18 0x00 < "${TMP}.blob" > "${TMP}.blob.bad"
+if "${FUTILITY}" gbb "${TMP}.blob.bad"; then false; fi
# recovery_key_offset < GBB_HEADER_SIZE is invalid
-cat ${TMP}.blob | ${REPLACE} 0x28 0x7f > ${TMP}.blob.bad
-if ${FUTILITY} gbb ${TMP}.blob.bad; then false; fi
-cat ${TMP}.blob | ${REPLACE} 0x28 0x00 > ${TMP}.blob.bad
-if ${FUTILITY} gbb ${TMP}.blob.bad; then false; fi
+"${REPLACE}" 0x28 0x7f < "${TMP}.blob" > "${TMP}.blob.bad"
+if "${FUTILITY}" gbb "${TMP}.blob.bad"; then false; fi
+"${REPLACE}" 0x28 0x00 < "${TMP}.blob" > "${TMP}.blob.bad"
+if "${FUTILITY}" gbb "${TMP}.blob.bad"; then false; fi
# hwid: offset + size == end of file is okay; beyond is invalid
-cat ${TMP}.blob | ${REPLACE} 0x14 0x40 > ${TMP}.blob.bad
-${FUTILITY} gbb -g ${TMP}.blob.bad
-cat ${TMP}.blob | ${REPLACE} 0x14 0x41 > ${TMP}.blob.bad
-if ${FUTILITY} gbb -g ${TMP}.blob.bad; then false; fi
+"${REPLACE}" 0x14 0x40 < "${TMP}.blob" > "${TMP}.blob.bad"
+"${FUTILITY}" gbb -g "${TMP}.blob.bad"
+"${REPLACE}" 0x14 0x41 < "${TMP}.blob" > "${TMP}.blob.bad"
+if "${FUTILITY}" gbb -g "${TMP}.blob.bad"; then false; fi
# rootkey: offset + size == end of file is okay; beyond is invalid
-cat ${TMP}.blob | ${REPLACE} 0x1c 0x30 > ${TMP}.blob.bad
-${FUTILITY} gbb -g ${TMP}.blob.bad
-cat ${TMP}.blob | ${REPLACE} 0x1c 0x31 > ${TMP}.blob.bad
-if ${FUTILITY} gbb -g ${TMP}.blob.bad; then false; fi
+"${REPLACE}" 0x1c 0x30 < "${TMP}.blob" > "${TMP}.blob.bad"
+"${FUTILITY}" gbb -g "${TMP}.blob.bad"
+"${REPLACE}" 0x1c 0x31 < "${TMP}.blob" > "${TMP}.blob.bad"
+if "${FUTILITY}" gbb -g "${TMP}.blob.bad"; then false; fi
# recovery_key: offset + size == end of file is okay; beyond is invalid
-cat ${TMP}.blob | ${REPLACE} 0x2c 0x10 > ${TMP}.blob.bad
-${FUTILITY} gbb -g ${TMP}.blob.bad
-cat ${TMP}.blob | ${REPLACE} 0x2c 0x11 > ${TMP}.blob.bad
-if ${FUTILITY} gbb -g ${TMP}.blob.bad; then false; fi
+"${REPLACE}" 0x2c 0x10 < "${TMP}.blob" > "${TMP}.blob.bad"
+"${FUTILITY}" gbb -g "${TMP}.blob.bad"
+"${REPLACE}" 0x2c 0x11 < "${TMP}.blob" > "${TMP}.blob.bad"
+if "${FUTILITY}" gbb -g "${TMP}.blob.bad"; then false; fi
# hwid_size == 0 doesn't complain, but can't be set
-cat ${TMP}.blob | ${REPLACE} 0x14 0x00 > ${TMP}.blob.bad
-${FUTILITY} gbb -g ${TMP}.blob.bad
-if ${FUTILITY} gbb -s --hwid="A" ${TMP}.blob.bad; then false; fi
+"${REPLACE}" 0x14 0x00 < "${TMP}.blob" > "${TMP}.blob.bad"
+"${FUTILITY}" gbb -g "${TMP}.blob.bad"
+if "${FUTILITY}" gbb -s --hwid="A" "${TMP}.blob.bad"; then false; fi
# rootkey_size == 0 gives warning, gets nothing, can't be set
-cat ${TMP}.blob | ${REPLACE} 0x1c 0x00 > ${TMP}.blob.bad
-${FUTILITY} gbb -g --rootkey ${TMP}.read1 ${TMP}.blob.bad
-if ${FUTILITY} gbb -s --rootkey ${TMP}.data1 ${TMP}.blob.bad; then false; fi
+"${REPLACE}" 0x1c 0x00 < "${TMP}.blob" > "${TMP}.blob.bad"
+"${FUTILITY}" gbb -g --rootkey "${TMP}.read1" "${TMP}.blob.bad"
+if "${FUTILITY}" gbb -s --rootkey "${TMP}.data1" "${TMP}.blob.bad";
+ then false; fi
# recovery_key_size == 0 gives warning, gets nothing, can't be set
-cat ${TMP}.blob | ${REPLACE} 0x2c 0x00 > ${TMP}.blob.bad
-${FUTILITY} gbb -g --recoverykey ${TMP}.read2 ${TMP}.blob.bad
-if ${FUTILITY} gbb -s --recoverykey ${TMP}.data2 ${TMP}.blob.bad; then false; fi
+"${REPLACE}" 0x2c 0x00 < "${TMP}.blob" > "${TMP}.blob.bad"
+"${FUTILITY}" gbb -g --recoverykey "${TMP}.read2" "${TMP}.blob.bad"
+if "${FUTILITY}" gbb -s --recoverykey "${TMP}.data2" "${TMP}.blob.bad";
+ then false; fi
# GBB v1.2 adds a sha256 digest field in what was previously padding:
@@ -189,21 +194,21 @@
# See that the digest is updated properly.
hwid="123456789ABCDEF"
-${FUTILITY} gbb -s --hwid=${hwid} ${TMP}.blob
+"${FUTILITY}" gbb -s --hwid="${hwid}" "${TMP}.blob"
expect=$(echo -n "$hwid" | sha256sum | cut -d ' ' -f 1)
-[ $(echo -n ${expect} | wc -c) == "64" ]
-${FUTILITY} gbb -g --digest ${TMP}.blob | grep ${expect}
+[ "$(echo -n "${expect}" | wc -c)" == "64" ]
+"${FUTILITY}" gbb -g --digest "${TMP}.blob" | grep "${expect}"
# Garble the digest, see that it's noticed.
# (assuming these zeros aren't present)
-cat ${TMP}.blob | ${REPLACE} 0x33 0x00 0x00 0x00 0x00 0x00 > ${TMP}.blob.bad
-${FUTILITY} gbb -g --digest ${TMP}.blob.bad | grep '0000000000'
-${FUTILITY} gbb -g --digest ${TMP}.blob.bad | grep 'invalid'
+"${REPLACE}" 0x33 0x00 0x00 0x00 0x00 0x00 < "${TMP}.blob" > "${TMP}.blob.bad"
+"${FUTILITY}" gbb -g --digest "${TMP}.blob.bad" | grep '0000000000'
+"${FUTILITY}" gbb -g --digest "${TMP}.blob.bad" | grep 'invalid'
# Garble the HWID. The digest is unchanged, but now invalid.
-cat ${TMP}.blob | ${REPLACE} 0x84 0x70 0x71 0x72 > ${TMP}.blob.bad
-${FUTILITY} gbb -g --digest ${TMP}.blob.bad | grep 'invalid'
+"${REPLACE}" 0x84 0x70 0x71 0x72 < "${TMP}.blob" > "${TMP}.blob.bad"
+"${FUTILITY}" gbb -g --digest "${TMP}.blob.bad" | grep 'invalid'
# cleanup
-rm -f ${TMP}*
+rm -f "${TMP}"*
exit 0
diff --git a/tests/futility/test_load_fmap.sh b/tests/futility/test_load_fmap.sh
index a93b71f..7821243 100755
--- a/tests/futility/test_load_fmap.sh
+++ b/tests/futility/test_load_fmap.sh
@@ -10,34 +10,34 @@
cd "$OUTDIR"
-IN=${SCRIPT_DIR}/futility/data/bios_link_mp.bin
-BIOS=${TMP}.bios.bin
+IN="${SCRIPT_DIR}/futility/data/bios_link_mp.bin"
+BIOS="${TMP}.bios.bin"
-cp ${IN} ${BIOS}
+cp "${IN}" "${BIOS}"
-AREAS="RW_SECTION_A VBLOCK_B BOOT_STUB"
-
+AREAS=(RW_SECTION_A VBLOCK_B BOOT_STUB)
+set -x
# Extract good blobs first
-${FUTILITY} dump_fmap -x ${BIOS} ${AREAS}
+"${FUTILITY}" dump_fmap -x "${BIOS}" "${AREAS[@]}"
# Save the good blobs, make same-size random blobs, create command
-CMDS=""
-for a in ${AREAS}; do
- size=$(stat -c '%s' $a)
- mv $a $a.good
- dd if=/dev/urandom of=$a.rand bs=$size count=1
- CMDS="$CMDS $a:$a.rand"
+CMDS=( )
+for a in "${AREAS[@]}"; do
+ size=$(stat -c '%s' "$a")
+ mv "$a" "$a.good"
+ dd if=/dev/urandom of="$a.rand" bs="$size" count=1
+ CMDS+=("$a:$a.rand")
done
# Poke the new blobs in
-${FUTILITY} load_fmap ${BIOS} ${CMDS}
+"${FUTILITY}" load_fmap "${BIOS}" "${CMDS[@]}"
# Pull them back out and see if they match
-${FUTILITY} dump_fmap -x ${BIOS} ${AREAS}
-for a in ${AREAS}; do
- cmp $a $a.rand
+"${FUTILITY}" dump_fmap -x "${BIOS}" "${AREAS[@]}"
+for a in "${AREAS[@]}"; do
+ cmp "$a" "$a.rand"
done
# cleanup
-rm -f ${TMP}* ${AREAS} *.rand *.good
+rm -f "${TMP}"* "${AREAS[@]}" ./*.rand ./*.good
exit 0
diff --git a/tests/futility/test_main.sh b/tests/futility/test_main.sh
index 2e5f4dc..725abe3 100755
--- a/tests/futility/test_main.sh
+++ b/tests/futility/test_main.sh
@@ -10,55 +10,57 @@
cd "$OUTDIR"
# No args returns nonzero exit code
-${FUTILITY} && false
+"${FUTILITY}" && false
# It's weird but okay if the command is a full path.
-${FUTILITY} /fake/path/to/help > "$TMP"
+"${FUTILITY}" /fake/path/to/help > "$TMP"
grep Usage "$TMP"
# Make sure logging does something.
LOG="/tmp/futility.log"
-[ -f ${LOG} ] && mv ${LOG} ${LOG}.backup
-touch ${LOG}
-${FUTILITY} help
-grep ${FUTILITY} ${LOG}
-rm -f ${LOG}
-[ -f ${LOG}.backup ] && mv ${LOG}.backup ${LOG}
+[ -f "${LOG}" ] && mv "${LOG}" "${LOG}.backup"
+touch "${LOG}"
+"${FUTILITY}" help
+grep "${FUTILITY}" "${LOG}"
+rm -f "${LOG}"
+[ -f "${LOG}.backup" ] && mv "${LOG}.backup" "${LOG}"
# Use some known digests to verify that things work...
-DEVKEYS=${SRCDIR}/tests/devkeys
+DEVKEYS="${SRCDIR}/tests/devkeys"
SHA=e78ce746a037837155388a1096212ded04fb86eb
# all progs in the pipelines should work
set -o pipefail
# If it's invoked as the name of a command we know, it should do that command
-ln -sf ${FUTILITY} vbutil_key
-./vbutil_key --unpack ${DEVKEYS}/installer_kernel_data_key.vbpubk | grep ${SHA}
-ln -sf ${FUTILITY} vbutil_keyblock
-./vbutil_keyblock --unpack ${DEVKEYS}/installer_kernel.keyblock | grep ${SHA}
-cp ${FUTILITY} show
-./show ${SCRIPT_DIR}/futility/data/rec_kernel_part.bin | grep ${SHA}
+ln -sf "${FUTILITY}" vbutil_key
+./vbutil_key --unpack "${DEVKEYS}/installer_kernel_data_key.vbpubk" | \
+ grep "${SHA}"
+ln -sf "${FUTILITY}" vbutil_keyblock
+./vbutil_keyblock --unpack "${DEVKEYS}/installer_kernel.keyblock" | \
+ grep "${SHA}"
+cp "${FUTILITY}" show
+./show "${SCRIPT_DIR}/futility/data/rec_kernel_part.bin" | grep "${SHA}"
# If it's invoked by any other name, expect the command to be the first arg.
-ln -sf ${FUTILITY} muggle
-./muggle vbutil_key --unpack ${DEVKEYS}/installer_kernel_data_key.vbpubk \
- | grep ${SHA}
-ln -sf ${FUTILITY} buggle
-./buggle vbutil_keyblock --unpack ${DEVKEYS}/installer_kernel.keyblock \
- | grep ${SHA}
-cp ${FUTILITY} boo
-./boo show ${SCRIPT_DIR}/futility/data/rec_kernel_part.bin | grep ${SHA}
+ln -sf "${FUTILITY}" muggle
+./muggle vbutil_key --unpack "${DEVKEYS}/installer_kernel_data_key.vbpubk" \
+ | grep "${SHA}"
+ln -sf "${FUTILITY}" buggle
+./buggle vbutil_keyblock --unpack "${DEVKEYS}/installer_kernel.keyblock" \
+ | grep "${SHA}"
+cp "${FUTILITY}" boo
+./boo show "${SCRIPT_DIR}/futility/data/rec_kernel_part.bin" | grep "${SHA}"
# we expect the first command fail, but the output to match anyway
set +o pipefail
# If it can't figure out the command at all, it should complain.
-${FUTILITY} muggle | grep Usage:
+"${FUTILITY}" muggle | grep Usage:
./buggle futility | grep Usage:
./boo | grep Usage:
# cleanup
-rm -f ${TMP}* vbutil_key vbutil_keyblock show muggle buggle boo
+rm -f "${TMP}"* vbutil_key vbutil_keyblock show muggle buggle boo
exit 0
diff --git a/tests/futility/test_not_really.c b/tests/futility/test_not_really.c
index 3cfc3ed..9bffb1a 100644
--- a/tests/futility/test_not_really.c
+++ b/tests/futility/test_not_really.c
@@ -6,7 +6,7 @@
#include <stdio.h>
#include "2struct.h"
-#include "test_common.h"
+#include "common/tests.h"
int main(int argc, char *argv[])
{
diff --git a/tests/futility/test_rwsig.sh b/tests/futility/test_rwsig.sh
index 2bd70ce..3a0a6e3 100755
--- a/tests/futility/test_rwsig.sh
+++ b/tests/futility/test_rwsig.sh
@@ -10,7 +10,7 @@
cd "$OUTDIR"
DATADIR="${SCRIPT_DIR}/futility/data"
-TESTKEYS=${SRCDIR}/tests/testkeys
+TESTKEYS="${SRCDIR}/tests/testkeys"
SIGS="1024 2048 2048_exp3 3072_exp3 4096 8192"
HASHES="SHA1 SHA256 SHA512"
@@ -18,13 +18,13 @@
set -o pipefail
-infile=${DATADIR}/hammer_dev.bin
-outfile=${TMP}.hammer_dev.bin
-cp ${infile} ${outfile}
+infile="${DATADIR}/hammer_dev.bin"
+outfile="${TMP}.hammer_dev.bin"
+cp "${infile}" "${outfile}"
# Signing without private key should extract EC_RW.bin
-${FUTILITY} sign --type rwsig --version 2 ${outfile}
-cmp ${infile} ${outfile}
-cmp ${EC_RW} ${DATADIR}/${EC_RW}
+"${FUTILITY}" sign --type rwsig --version 2 "${outfile}"
+cmp "${infile}" "${outfile}"
+cmp "${EC_RW}" "${DATADIR}/${EC_RW}"
for s in $SIGS; do
echo -n "$s " 1>&3
@@ -34,31 +34,32 @@
outkeys=${TMP}.${s}_${h}
outfile=${TMP}.${s}_${h}.bin
- ${FUTILITY} create --desc "Test key" --hash_alg ${h} \
- ${pemfile} ${outkeys}
+ "${FUTILITY}" create --desc "Test key" --hash_alg "${h}" \
+ "${pemfile}" "${outkeys}"
# The input file should be correctly signed to start with
- ${FUTILITY} show --type rwsig ${infile}
+ "${FUTILITY}" show --type rwsig "${infile}"
# Using the wrong key to verify it should fail
- if ${FUTILITY} show --type rwsig --pubkey ${outkeys}.vbpubk2 \
- ${infile}; then
+ if "${FUTILITY}" show --type rwsig --pubkey "${outkeys}.vbpubk2" \
+ "${infile}"; then
exit 1
fi
- cp ${infile} ${outfile}
+ cp "${infile}" "${outfile}"
# Sign ec.bin with a new private key
- ${FUTILITY} sign --type rwsig --prikey ${outkeys}.vbprik2 \
- --version 2 ${outfile}
+ "${FUTILITY}" sign --type rwsig --prikey "${outkeys}.vbprik2" \
+ --version 2 "${outfile}"
# Check EC_RW.bin is produced
- [[ -e ${EC_RW} ]]
+ [[ -e "${EC_RW}" ]]
- ${FUTILITY} show --type rwsig --pubkey ${outkeys}.vbpubk2 ${outfile}
- ${FUTILITY} show --type rwsig ${outfile}
+ "${FUTILITY}" show --type rwsig --pubkey "${outkeys}.vbpubk2" \
+ "${outfile}"
+ "${FUTILITY}" show --type rwsig "${outfile}"
done
done
# cleanup
-rm -rf ${TMP}*
+rm -rf "${TMP}"*
exit 0
diff --git a/tests/futility/test_show_contents.sh b/tests/futility/test_show_contents.sh
index e040362..9b3431d 100755
--- a/tests/futility/test_show_contents.sh
+++ b/tests/futility/test_show_contents.sh
@@ -16,8 +16,7 @@
tests/devkeys/kernel.keyblock
tests/futility/data/fw_vblock.bin
tests/futility/data/fw_gbb.bin
- tests/futility/data/bios_zgb_mp.bin
- tests/futility/data/bios_mario_mp.bin
+ tests/futility/data/bios_peppy_mp.bin
tests/futility/data/kern_preamble.bin
tests/futility/data/sample.vbpubk2
tests/futility/data/sample.vbprik2
@@ -29,7 +28,7 @@
outfile="show.${file//\//_}"
gotfile="${OUTDIR}/${outfile}"
wantfile="${SRCDIR}/tests/futility/expect_output/${outfile}"
- ( cd "${SRCDIR}" && ${FUTILITY} show "${file}" ) | tee "${gotfile}"
+ ( cd "${SRCDIR}" && "${FUTILITY}" show "${file}" ) | tee "${gotfile}"
# Uncomment this to update the expected output
#cp "${gotfile}" "${wantfile}"
@@ -48,7 +47,7 @@
outfile="vbutil_key.${file//\//_}"
gotfile="${OUTDIR}/${outfile}"
wantfile="${SRCDIR}/tests/futility/expect_output/${outfile}"
- ( cd "${SRCDIR}" && ${FUTILITY} vbutil_key --unpack "${file}" ) \
+ ( cd "${SRCDIR}" && "${FUTILITY}" vbutil_key --unpack "${file}" ) \
| tee "${gotfile}"
# Uncomment this to update the expected output
@@ -63,7 +62,7 @@
outfile="vbutil_keyblock.${file//\//_}"
gotfile="${OUTDIR}/${outfile}"
wantfile="${SRCDIR}/tests/futility/expect_output/${outfile}"
-( cd "${SRCDIR}" && ${FUTILITY} vbutil_keyblock --unpack "${file}" \
+( cd "${SRCDIR}" && "${FUTILITY}" vbutil_keyblock --unpack "${file}" \
--signpubkey "tests/devkeys/kernel_subkey.vbpubk" ) \
| tee "${gotfile}"
@@ -83,7 +82,7 @@
# arbitrary non-zero numbers so we can verify they're printed
# properly.
dd bs=1024 count=16 if=/dev/urandom of="${TMP}.fw_main"
-${FUTILITY} vbutil_firmware --vblock "${TMP}.vblock.old" \
+"${FUTILITY}" vbutil_firmware --vblock "${TMP}.vblock.old" \
--keyblock "${KEYDIR}/firmware.keyblock" \
--signprivate "${KEYDIR}/firmware_data_key.vbprivk" \
--version 12 \
@@ -92,7 +91,7 @@
--flags 42
# Verify
-${FUTILITY} vbutil_firmware --verify "${TMP}.vblock.old" \
+"${FUTILITY}" vbutil_firmware --verify "${TMP}.vblock.old" \
--signpubkey "${KEYDIR}/root_key.vbpubk" \
--fv "${TMP}.fw_main" | tee "${gotfile}"
@@ -103,5 +102,5 @@
# cleanup
-rm -rf "${TMP}*"
+rm -rf "${TMP}"*
exit 0
diff --git a/tests/futility/test_show_kernel.sh b/tests/futility/test_show_kernel.sh
index 151cf46..f2610a3 100755
--- a/tests/futility/test_show_kernel.sh
+++ b/tests/futility/test_show_kernel.sh
@@ -9,52 +9,52 @@
# Work in scratch directory
cd "$OUTDIR"
-DEVKEYS=${SRCDIR}/tests/devkeys
-TESTKEYS=${SRCDIR}/tests/testkeys
+DEVKEYS="${SRCDIR}/tests/devkeys"
+TESTKEYS="${SRCDIR}/tests/testkeys"
echo 'Creating test kernel'
# Dummy kernel data
-echo "hi there" > ${TMP}.config.txt
-dd if=/dev/urandom bs=16384 count=1 of=${TMP}.bootloader.bin
-dd if=/dev/urandom bs=32768 count=1 of=${TMP}.kernel.bin
+echo "hi there" > "${TMP}.config.txt"
+dd if=/dev/urandom bs=16384 count=1 of="${TMP}.bootloader.bin"
+dd if=/dev/urandom bs=32768 count=1 of="${TMP}.kernel.bin"
# Pack kernel data key using original vboot utilities.
-${FUTILITY} vbutil_key --pack ${TMP}.datakey.test \
- --key ${TESTKEYS}/key_rsa2048.keyb --algorithm 4
+"${FUTILITY}" vbutil_key --pack "${TMP}.datakey.test" \
+ --key "${TESTKEYS}/key_rsa2048.keyb" --algorithm 4
# Keyblock with kernel data key is signed by kernel subkey
# Flags=5 means dev=0 rec=0
-${FUTILITY} vbutil_keyblock --pack ${TMP}.keyblock.test \
- --datapubkey ${TMP}.datakey.test \
+"${FUTILITY}" vbutil_keyblock --pack "${TMP}.keyblock.test" \
+ --datapubkey "${TMP}.datakey.test" \
--flags 5 \
- --signprivate ${DEVKEYS}/kernel_subkey.vbprivk
+ --signprivate "${DEVKEYS}/kernel_subkey.vbprivk"
# Kernel preamble is signed with the kernel data key
-${FUTILITY} vbutil_kernel \
- --pack ${TMP}.kernel.test \
- --keyblock ${TMP}.keyblock.test \
- --signprivate ${TESTKEYS}/key_rsa2048.sha256.vbprivk \
+"${FUTILITY}" vbutil_kernel \
+ --pack "${TMP}.kernel.test" \
+ --keyblock "${TMP}.keyblock.test" \
+ --signprivate "${TESTKEYS}/key_rsa2048.sha256.vbprivk" \
--version 1 \
--arch arm \
- --vmlinuz ${TMP}.kernel.bin \
- --bootloader ${TMP}.bootloader.bin \
- --config ${TMP}.config.txt
+ --vmlinuz "${TMP}.kernel.bin" \
+ --bootloader "${TMP}.bootloader.bin" \
+ --config "${TMP}.config.txt"
echo 'Verifying test kernel'
# Verify the kernel
-${FUTILITY} show ${TMP}.kernel.test \
- --publickey ${DEVKEYS}/kernel_subkey.vbpubk \
- | egrep 'Signature.*valid'
+"${FUTILITY}" show "${TMP}.kernel.test" \
+ --publickey "${DEVKEYS}/kernel_subkey.vbpubk" \
+ | grep -E 'Signature.*valid'
echo 'Test kernel blob looks good'
# Mess up the padding, make sure it fails.
rc=0
-${FUTILITY} show ${TMP}.kernel.test \
+"${FUTILITY}" show "${TMP}.kernel.test" \
--pad 0x100 \
- --publickey ${DEVKEYS}/kernel_subkey.vbpubk \
+ --publickey "${DEVKEYS}/kernel_subkey.vbpubk" \
|| rc=$?
[ $rc -ne 0 ]
[ $rc -lt 128 ]
@@ -63,9 +63,9 @@
# Look waaaaaay off the end of the file, make sure it fails.
rc=0
-${FUTILITY} show ${TMP}.kernel.test \
+"${FUTILITY}" show "${TMP}.kernel.test" \
--pad 0x100000 \
- --publickey ${DEVKEYS}/kernel_subkey.vbpubk \
+ --publickey "${DEVKEYS}/kernel_subkey.vbpubk" \
|| rc=$?
[ $rc -ne 0 ]
[ $rc -lt 128 ]
@@ -73,5 +73,5 @@
echo 'Really invalid args are still invalid'
# cleanup
-rm -rf ${TMP}*
+rm -rf "${TMP}"*
exit 0
diff --git a/tests/futility/test_show_usbpd1.sh b/tests/futility/test_show_usbpd1.sh
index b5553aa..3998fa7 100755
--- a/tests/futility/test_show_usbpd1.sh
+++ b/tests/futility/test_show_usbpd1.sh
@@ -24,23 +24,24 @@
for test in $TESTS; do
- infile=${DATADIR}/${test}.unsigned
+ infile="${DATADIR}/${test}.unsigned"
for h in $HASHES; do
- pemfile=${TESTKEYS}/key_rsa${s}.pem
- outfile=${TMP}.${test}_${s}_${h}.new
+ pemfile="${TESTKEYS}/key_rsa${s}.pem"
+ outfile="${TMP}.${test}_${s}_${h}.new"
# sign it
- ${FUTILITY} sign --type usbpd1 --pem ${pemfile} ${infile} ${outfile}
+ "${FUTILITY}" sign --type usbpd1 --pem "${pemfile}" "${infile}" \
+ "${outfile}"
# make sure it identifies correctly
- ${FUTILITY} verify ${outfile}
+ "${FUTILITY}" verify "${outfile}"
done
done
done
# cleanup
-rm -rf ${TMP}*
+rm -rf "${TMP}"*
exit 0
diff --git a/tests/futility/test_show_vs_verify.sh b/tests/futility/test_show_vs_verify.sh
index 4981a38..c0c0872 100755
--- a/tests/futility/test_show_vs_verify.sh
+++ b/tests/futility/test_show_vs_verify.sh
@@ -10,67 +10,67 @@
cd "$OUTDIR"
# some stuff we'll need
-DEVKEYS=${SRCDIR}/tests/devkeys
+DEVKEYS="${SRCDIR}/tests/devkeys"
# The show command exits with 0 if the data is consistent.
# The verify command exits with 0 only if all the data is verified.
#### keyblock
-${FUTILITY} show ${DEVKEYS}/firmware.keyblock
+"${FUTILITY}" show "${DEVKEYS}/firmware.keyblock"
-if ${FUTILITY} verify ${DEVKEYS}/firmware.keyblock ; then false; fi
+if "${FUTILITY}" verify "${DEVKEYS}/firmware.keyblock" ; then false; fi
-${FUTILITY} verify ${DEVKEYS}/firmware.keyblock \
- --publickey ${DEVKEYS}/root_key.vbpubk
+"${FUTILITY}" verify "${DEVKEYS}/firmware.keyblock" \
+ --publickey "${DEVKEYS}/root_key.vbpubk"
#### firmware vblock
# Get some bits to look at
-${FUTILITY} dump_fmap -x ${SCRIPT_DIR}/futility/data/bios_peppy_mp.bin \
- GBB:${TMP}.gbb VBLOCK_A:${TMP}.vblock_a FW_MAIN_A:${TMP}.fw_main_a
-${FUTILITY} gbb -g -k ${TMP}.rootkey ${TMP}.gbb
+"${FUTILITY}" dump_fmap -x "${SCRIPT_DIR}/futility/data/bios_peppy_mp.bin" \
+ "GBB:${TMP}.gbb" "VBLOCK_A:${TMP}.vblock_a" "FW_MAIN_A:${TMP}.fw_main_a"
+"${FUTILITY}" gbb -g -k "${TMP}.rootkey" "${TMP}.gbb"
-${FUTILITY} show ${TMP}.vblock_a
+"${FUTILITY}" show "${TMP}.vblock_a"
-${FUTILITY} show ${TMP}.vblock_a --publickey ${TMP}.rootkey
+"${FUTILITY}" show "${TMP}.vblock_a" --publickey "${TMP}.rootkey"
-${FUTILITY} show ${TMP}.vblock_a \
- --publickey ${TMP}.rootkey \
- --fv ${TMP}.fw_main_a
+"${FUTILITY}" show "${TMP}.vblock_a" \
+ --publickey "${TMP}.rootkey" \
+ --fv "${TMP}.fw_main_a"
-if ${FUTILITY} verify ${TMP}.vblock_a ; then false ; fi
+if "${FUTILITY}" verify "${TMP}.vblock_a" ; then false ; fi
-if ${FUTILITY} verify ${TMP}.vblock_a \
- --publickey ${TMP}.rootkey ; then false ; fi
+if "${FUTILITY}" verify "${TMP}.vblock_a" \
+ --publickey "${TMP}.rootkey" ; then false ; fi
-${FUTILITY} verify ${TMP}.vblock_a \
- --publickey ${TMP}.rootkey \
- --fv ${TMP}.fw_main_a
+"${FUTILITY}" verify "${TMP}.vblock_a" \
+ --publickey "${TMP}.rootkey" \
+ --fv "${TMP}.fw_main_a"
#### kernel partition
-${FUTILITY} show ${SCRIPT_DIR}/futility/data/rec_kernel_part.bin
+"${FUTILITY}" show "${SCRIPT_DIR}/futility/data/rec_kernel_part.bin"
-${FUTILITY} show ${SCRIPT_DIR}/futility/data/rec_kernel_part.bin \
- --publickey ${DEVKEYS}/kernel_subkey.vbpubk
+"${FUTILITY}" show "${SCRIPT_DIR}/futility/data/rec_kernel_part.bin" \
+ --publickey "${DEVKEYS}/kernel_subkey.vbpubk"
-${FUTILITY} show ${SCRIPT_DIR}/futility/data/rec_kernel_part.bin \
- --publickey ${DEVKEYS}/recovery_key.vbpubk
+"${FUTILITY}" show "${SCRIPT_DIR}/futility/data/rec_kernel_part.bin" \
+ --publickey "${DEVKEYS}/recovery_key.vbpubk"
-if ${FUTILITY} verify ${SCRIPT_DIR}/futility/data/rec_kernel_part.bin ; \
+if "${FUTILITY}" verify "${SCRIPT_DIR}/futility/data/rec_kernel_part.bin" ; \
then false ; fi
-if ${FUTILITY} verify ${SCRIPT_DIR}/futility/data/rec_kernel_part.bin \
- --publickey ${DEVKEYS}/kernel_subkey.vbpubk ; then false ; fi
+if "${FUTILITY}" verify "${SCRIPT_DIR}/futility/data/rec_kernel_part.bin" \
+ --publickey "${DEVKEYS}/kernel_subkey.vbpubk" ; then false ; fi
-${FUTILITY} verify ${SCRIPT_DIR}/futility/data/rec_kernel_part.bin \
- --publickey ${DEVKEYS}/recovery_key.vbpubk
+"${FUTILITY}" verify "${SCRIPT_DIR}/futility/data/rec_kernel_part.bin" \
+ --publickey "${DEVKEYS}/recovery_key.vbpubk"
# cleanup
-rm -rf ${TMP}*
+rm -rf "${TMP}"*
exit 0
diff --git a/tests/futility/test_sign_firmware.sh b/tests/futility/test_sign_firmware.sh
index fa5529c..fe8462c 100755
--- a/tests/futility/test_sign_firmware.sh
+++ b/tests/futility/test_sign_firmware.sh
@@ -3,44 +3,98 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-me=${0##*/}
-TMP="$me.tmp"
+me="${0##*/}"
+TMP="${me}.tmp"
# Work in scratch directory
cd "$OUTDIR"
-KEYDIR=${SRCDIR}/tests/devkeys
+KEYDIR="${SRCDIR}/tests/devkeys"
+DATADIR="${SCRIPT_DIR}/futility/data"
# The input BIOS images are all signed with MP keys. We resign them with dev
# keys, which means we can precalculate the expected results. Note that the
# script does not change the root or recovery keys in the GBB.
INFILES="
-${SCRIPT_DIR}/futility/data/bios_link_mp.bin
-${SCRIPT_DIR}/futility/data/bios_mario_mp.bin
-${SCRIPT_DIR}/futility/data/bios_peppy_mp.bin
+${DATADIR}/bios_link_mp.bin
+${DATADIR}/bios_peppy_mp.bin
+"
+
+# BIOS image containing CBFS RW/A and RW/B, and signed with developer keys.
+GOOD_CBFS="${DATADIR}/bios_voxel_dev.bin"
+
+# BIOS image containing CBFS RW/A and RW/B, and signed with developer keys.
+INFILES="${INFILES}
+${GOOD_CBFS}
"
# We also want to test that we can sign an image without any valid firmware
# preambles. That one won't be able to tell how much of the FW_MAIN region is
# the valid firmware, so it'll have to sign the entire region.
-GOOD_VBLOCKS=${SCRIPT_DIR}/futility/data/bios_peppy_mp.bin
+GOOD_VBLOCKS="${DATADIR}/bios_peppy_mp.bin"
ONEMORE=bios_peppy_mp_no_vblock.bin
-cp ${GOOD_VBLOCKS} ${ONEMORE}
-${FUTILITY} load_fmap ${ONEMORE} VBLOCK_A:/dev/urandom VBLOCK_B:/dev/zero
+CLEAN_B=bios_peppy_mp_clean_b_slot.bin
+cp "${GOOD_VBLOCKS}" "${ONEMORE}"
+cp "${GOOD_VBLOCKS}" "${CLEAN_B}"
+
+GOOD_DEV="${DATADIR}/bios_peppy_dev.bin"
+
+NO_B_SLOT_PATCH="${DATADIR}/bios_voxel_dev.no_b_slot.xxd.patch"
+
+BAD_KEYBLOCK_PATCHES=(
+"${DATADIR}/bios_peppy_dev.bad_keyblock_data_key_offset_too_big.xxd.patch"
+"${DATADIR}/bios_peppy_dev.bad_keyblock_data_key_size_big.xxd.patch"
+"${DATADIR}/bios_peppy_dev.bad_keyblock_hash_data_size_too_small.xxd.patch"
+"${DATADIR}/bios_peppy_dev.bad_keyblock_hash_invalid_contents.xxd.patch"
+"${DATADIR}/bios_peppy_dev.bad_keyblock_hash_offset_too_big.xxd.patch"
+"${DATADIR}/bios_peppy_dev.bad_keyblock_hash_size_too_big.xxd.patch"
+"${DATADIR}/bios_peppy_dev.bad_keyblock_invalid_magic.xxd.patch"
+"${DATADIR}/bios_peppy_dev.bad_keyblock_invalid_major_version.xxd.patch"
+"${DATADIR}/bios_peppy_dev.bad_keyblock_size_not_fully_signed.xxd.patch"
+)
+
+BAD_PREAMBLE_PATCHES=(
+"${DATADIR}/bios_peppy_dev.bad_preamble_body_signature_offset_too_big.xxd.patch"
+"${DATADIR}/bios_peppy_dev.bad_preamble_body_signature_size_too_big.xxd.patch"
+"${DATADIR}/bios_peppy_dev.bad_preamble_header_version_major.xxd.patch"
+"${DATADIR}/bios_peppy_dev.bad_preamble_header_version_minor.xxd.patch"
+"${DATADIR}/bios_peppy_dev.bad_preamble_kernel_subkey_offset_too_big.xxd.patch"
+"${DATADIR}/bios_peppy_dev.bad_preamble_kernel_subkey_size_too_big.xxd.patch"
+"${DATADIR}/bios_peppy_dev.bad_preamble_signature_data_size_too_big.xxd.patch"
+"${DATADIR}/bios_peppy_dev.bad_preamble_signature_data_size_too_small.xxd.patch"
+"${DATADIR}/bios_peppy_dev.bad_preamble_signature_invalid_contents.xxd.patch"
+"${DATADIR}/bios_peppy_dev.bad_preamble_signature_offset_too_big.xxd.patch"
+"${DATADIR}/bios_peppy_dev.bad_preamble_signature_size_too_big.xxd.patch"
+)
+
+BAD_FMAP_KEYBLOCK_PATCHES=(
+"${DATADIR}/bios_peppy_dev.bad_keyblock_fmap_too_small_for_whole.xxd.patch"
+"${DATADIR}/bios_peppy_dev.bad_keyblock_fmap_too_small.xxd.patch"
+)
+
+BAD_FMAP_PREAMBLE_PATCHES=(
+"${DATADIR}/bios_peppy_dev.bad_preamble_fmap_too_small_for_whole.xxd.patch"
+"${DATADIR}/bios_peppy_dev.bad_preamble_fmap_too_small.xxd.patch"
+)
+
+"${FUTILITY}" load_fmap "${ONEMORE}" VBLOCK_A:/dev/urandom VBLOCK_B:/dev/zero
INFILES="${INFILES} ${ONEMORE}"
-set -o pipefail
+# args: xxd_patch_file input_file
+function apply_xxd_patch {
+ xxd -r "${1}" "${2}"
+}
-# We've removed dev_firmware keyblock and private keys from ToT test key dir.
-# It's currently only available on few legacy (alex, zgb) devices' key folders
-# on signer bot. Add them to ${KEYDIR} if you need to test that.
-DEV_FIRMWARE_PARAMS=""
-if [ -f "${KEYDIR}/dev_firmware.keyblock" ]; then
- DEV_FIRMWARE_PARAMS="
- -S ${KEYDIR}/dev_firmware_data_key.vbprivk
- -B ${KEYDIR}/dev_firmware.keyblock"
- INFILES="${INFILES} ${SCRIPT_DIR}/futility/data/bios_zgb_mp.bin"
-fi
+# args: file1 file2
+function cmp_first_line {
+ cmp <(head -n1 "${1}") <(head -n1 "${2}")
+}
+
+function cmp_last_line {
+ cmp <(tail -n1 "${1}") <(tail -n1 "${2}")
+}
+
+set -o pipefail
count=0
for infile in $INFILES; do
@@ -48,140 +102,391 @@
base=${infile##*/}
: $(( count++ ))
- echo -n "$count " 1>&3
+ echo -n "${count} " 1>&3
- outfile=${TMP}.${base}.new
+ outfile="${TMP}.${base}.new"
loemid="loem"
- loemdir=${TMP}.${base}_dir
+ loemdir="${TMP}.${base}_dir"
- mkdir -p ${loemdir}
+ mkdir -p "${loemdir}"
- # resign_firmwarefd.sh works on BIOS image files. The args are:
- #
- # infile
- # outfile
- # firmware_datakey
- # firmware_keyblock
- # dev_firmware_datakey (these are only used if RW A & RW B differ)
- # dev_firmware_keyblock
- # kernel_subkey
- # firmware_version
- # preamble_flag
- # loem_output_dir (optional: dir for copy of new vblocks)
- # loemid (optional: copy new vblocks using this name)
- #
- #OLD ${BIN_DIR}/resign_firmwarefd.sh \
- #OLD ${infile} \
- #OLD ${outfile} \
- #OLD ${KEYDIR}/firmware_data_key.vbprivk \
- #OLD ${KEYDIR}/firmware.keyblock \
- #OLD ${KEYDIR}/dev_firmware_data_key.vbprivk \
- #OLD ${KEYDIR}/dev_firmware.keyblock \
- #OLD ${KEYDIR}/kernel_subkey.vbpubk \
- #OLD 14 \
- #OLD 8 \
- #OLD ${loemdir} \
- #OLD ${loemid}
-
- ${FUTILITY} sign \
- -s ${KEYDIR}/firmware_data_key.vbprivk \
- -b ${KEYDIR}/firmware.keyblock \
- ${DEV_FIRMWARE_PARAMS} \
- -k ${KEYDIR}/kernel_subkey.vbpubk \
+ "${FUTILITY}" sign \
+ -K "${KEYDIR}" \
-v 14 \
-f 8 \
- -d ${loemdir} \
- -l ${loemid} \
- ${infile} ${outfile}
+ -d "${loemdir}" \
+ -l "${loemid}" \
+ "${infile}" "${outfile}"
# check the firmware version and preamble flags
- m=$(${FUTILITY} verify --publickey ${KEYDIR}/root_key.vbpubk ${outfile} \
- | egrep 'Firmware version: +14$|Preamble flags: +8$' | wc -l)
- [ "$m" = "4" ]
+ m=$("${FUTILITY}" verify --publickey "${KEYDIR}/root_key.vbpubk" \
+ "${outfile}" | grep -c -E 'Firmware version: +14$|Preamble flags: +8$')
+ [ "${m}" = "4" ]
# check the sha1sums
- ${FUTILITY} verify --publickey ${KEYDIR}/root_key.vbpubk ${outfile} \
+ "${FUTILITY}" verify --publickey "${KEYDIR}/root_key.vbpubk" "${outfile}" \
| grep sha1sum \
- | sed -e 's/.*: \+//' > ${TMP}.${base}.sha.new
- cmp ${SCRIPT_DIR}/futility/data_${base}_expect.txt ${TMP}.${base}.sha.new
+ | sed -e 's/.*: \+//' > "${TMP}.${base}.sha.new"
+ cmp "${SCRIPT_DIR}/futility/data_${base}_expect.txt" "${TMP}.${base}.sha.new"
# and the LOEM stuff
- ${FUTILITY} dump_fmap -x ${outfile} \
- FW_MAIN_A:${loemdir}/fw_main_A FW_MAIN_B:${loemdir}/fw_main_B \
- "Firmware A Data":${loemdir}/fw_main_A \
- "Firmware B Data":${loemdir}/fw_main_B
+ "${FUTILITY}" dump_fmap -x "${outfile}" \
+ "FW_MAIN_A:${loemdir}/fw_main_A" "FW_MAIN_B:${loemdir}/fw_main_B"
-
- ${FUTILITY} verify --publickey ${KEYDIR}/root_key.vbpubk \
- --fv ${loemdir}/fw_main_A \
- ${loemdir}/vblock_A.${loemid} | grep sha1sum \
- | sed -e 's/.*: \+//' > ${loemdir}/loem.sha.new
- ${FUTILITY} verify --publickey ${KEYDIR}/root_key.vbpubk \
- --fv ${loemdir}/fw_main_B \
- ${loemdir}/vblock_B.${loemid} | grep sha1sum \
- | sed -e 's/.*: \+//' >> ${loemdir}/loem.sha.new
+ "${FUTILITY}" verify --publickey "${KEYDIR}/root_key.vbpubk" \
+ --fv "${loemdir}/fw_main_A" \
+ "${loemdir}/vblock_A.${loemid}" | grep sha1sum \
+ | sed -e 's/.*: \+//' > "${loemdir}/loem.sha.new"
+ "${FUTILITY}" verify --publickey "${KEYDIR}/root_key.vbpubk" \
+ --fv "${loemdir}/fw_main_B" \
+ "${loemdir}/vblock_B.${loemid}" | grep sha1sum \
+ | sed -e 's/.*: \+//' >> "${loemdir}/loem.sha.new"
# the vblocks don't have root or recovery keys
- tail -4 ${SCRIPT_DIR}/futility/data_${base}_expect.txt > ${loemdir}/sha.expect
- cmp ${loemdir}/sha.expect ${loemdir}/loem.sha.new
+ tail -4 "${SCRIPT_DIR}/futility/data_${base}_expect.txt" \
+ > "${loemdir}/sha.expect"
+ cmp "${loemdir}/sha.expect" "${loemdir}/loem.sha.new"
done
# Make sure that the BIOS with the good vblocks signed the right size.
-GOOD_OUT=${TMP}.${GOOD_VBLOCKS##*/}.new
-MORE_OUT=${TMP}.${ONEMORE##*/}.new
+GOOD_OUT="${TMP}.${GOOD_VBLOCKS##*/}.new"
+MORE_OUT="${TMP}.${ONEMORE##*/}.new"
+GOOD_CBFS_OUT="${TMP}.${GOOD_CBFS##*/}.new"
-${FUTILITY} verify --publickey ${KEYDIR}/root_key.vbpubk ${GOOD_OUT} \
- | awk '/Firmware body size:/ {print $4}' > ${TMP}.good.body
-${FUTILITY} dump_fmap -p ${GOOD_OUT} \
- | awk '/FW_MAIN_/ {print $3}' > ${TMP}.good.fw_main
+"${FUTILITY}" verify --publickey "${KEYDIR}/root_key.vbpubk" "${GOOD_OUT}" \
+ | awk '/Firmware body size:/ {print $4}' > "${TMP}.good.body"
+"${FUTILITY}" dump_fmap -p "${GOOD_OUT}" \
+ | awk '/FW_MAIN_/ {print $3}' > "${TMP}.good.fw_main"
# This should fail because they're different
-if cmp ${TMP}.good.body ${TMP}.good.fw_main; then false; fi
+if cmp "${TMP}.good.body" "${TMP}.good.fw_main"; then false; fi
# Make sure that the BIOS with the bad vblocks signed the whole fw body
-${FUTILITY} verify --publickey ${KEYDIR}/root_key.vbpubk ${MORE_OUT} \
- | awk '/Firmware body size:/ {print $4}' > ${TMP}.onemore.body
-${FUTILITY} dump_fmap -p ${MORE_OUT} \
- | awk '/FW_MAIN_/ {print $3}' > ${TMP}.onemore.fw_main
+"${FUTILITY}" verify --publickey "${KEYDIR}/root_key.vbpubk" "${MORE_OUT}" \
+ | awk '/Firmware body size:/ {print $4}' > "${TMP}.onemore.body"
+"${FUTILITY}" dump_fmap -p "${MORE_OUT}" \
+ | awk '/FW_MAIN_/ {print $3}' > "${TMP}.onemore.fw_main"
# These should match
-cmp ${TMP}.onemore.body ${TMP}.onemore.fw_main
-cmp ${TMP}.onemore.body ${TMP}.good.fw_main
+cmp "${TMP}.onemore.body" "${TMP}.onemore.fw_main"
+cmp "${TMP}.onemore.body" "${TMP}.good.fw_main"
+
+"${FUTILITY}" verify --publickey "${KEYDIR}/root_key.vbpubk" \
+ "${GOOD_CBFS_OUT}" \
+ | awk '/Firmware body size:/ {print $4}' > "${TMP}.good_cbfs.body"
+"${FUTILITY}" dump_fmap -p "${GOOD_CBFS_OUT}" \
+ | awk '/FW_MAIN_/ {print $3}' > "${TMP}.good_cbfs.fw_main"
+if cmp "${TMP}.good_cbfs.body" "${TMP}.good_cbfs.fw_main"; then false; fi
-# Sign the last one again but don't specify the version or the preamble flags.
-# The version should default to 1, but the preamble flags should be preserved.
+# Sign CBFS image after adding new files. Size should increase but still be
+# smaller than FlashMap size.
: $(( count++ ))
-echo -n "$count " 1>&3
+echo -n "${count} " 1>&3
-${FUTILITY} sign \
- -s ${KEYDIR}/firmware_data_key.vbprivk \
- -b ${KEYDIR}/firmware.keyblock \
- ${DEV_FIRMWARE_PARAMS} \
- -k ${KEYDIR}/kernel_subkey.vbpubk \
- ${MORE_OUT} ${MORE_OUT}.2
+cp "${GOOD_CBFS_OUT}" "${GOOD_CBFS_OUT}.1"
+truncate -s 512 "${TMP}.zero_512"
+cbfstool "${GOOD_CBFS_OUT}.1" expand -r FW_MAIN_A,FW_MAIN_B
+cbfstool "${GOOD_CBFS_OUT}.1" add \
+ -r FW_MAIN_A,FW_MAIN_B -f "${TMP}.zero_512" -n new-data-file -t raw
-m=$(${FUTILITY} verify --publickey ${KEYDIR}/root_key.vbpubk ${MORE_OUT}.2 \
- | egrep 'Firmware version: +1$|Preamble flags: +8$' | wc -l)
-[ "$m" = "4" ]
+"${FUTILITY}" sign \
+ -s "${KEYDIR}/firmware_data_key.vbprivk" \
+ -K "${KEYDIR}" \
+ "${GOOD_CBFS_OUT}.1"
+
+"${FUTILITY}" verify --publickey "${KEYDIR}/root_key.vbpubk" \
+ "${GOOD_CBFS_OUT}.1" \
+ | awk '/Firmware body size:/ {print $4}' > "${TMP}.good_cbfs.1.body"
+"${FUTILITY}" dump_fmap -p "${GOOD_CBFS_OUT}" \
+ | awk '/FW_MAIN_/ {print $3}' > "${TMP}.good_cbfs.1.fw_main"
+
+# Check if size increased, but also if it was correctly truncated,
+# so it does not span over whole FlashMap area.
+[[ $(head -n1 "${TMP}.good_cbfs.body") \
+ < $(head -n1 "${TMP}.good_cbfs.1.body") ]]
+[[ $(tail -n1 "${TMP}.good_cbfs.body") \
+ < $(tail -n1 "${TMP}.good_cbfs.1.body") ]]
+[[ $(head -n1 "${TMP}.good_cbfs.1.body") \
+ < $(head -n1 "${TMP}.good_cbfs.1.fw_main") ]]
+[[ $(tail -n1 "${TMP}.good_cbfs.1.body") \
+ < $(tail -n1 "${TMP}.good_cbfs.1.fw_main") ]]
+
+
+# Sign image again but don't specify the version or the preamble flags.
+# The firmware version and preamble flags should be preserved.
+# NOTICE: Version preservation behavior changed from defaulting to 1.
+: $(( count++ ))
+echo -n "${count} " 1>&3
+
+"${FUTILITY}" sign \
+ -b "${KEYDIR}/firmware.keyblock" \
+ -K "${KEYDIR}" \
+ "${MORE_OUT}" "${MORE_OUT}.2"
+
+m=$("${FUTILITY}" verify --publickey "${KEYDIR}/root_key.vbpubk" \
+ "${MORE_OUT}.2" | grep -c -E 'Firmware version: +14$|Preamble flags: +8$')
+[ "${m}" = "4" ]
# If the original preamble is not present, the preamble flags should be zero.
: $(( count++ ))
-echo -n "$count " 1>&3
+echo -n "${count} " 1>&3
-${FUTILITY} load_fmap ${MORE_OUT} VBLOCK_A:/dev/urandom VBLOCK_B:/dev/zero
-${FUTILITY} sign \
- -s ${KEYDIR}/firmware_data_key.vbprivk \
- -b ${KEYDIR}/firmware.keyblock \
- ${DEV_FIRMWARE_PARAMS} \
- -k ${KEYDIR}/kernel_subkey.vbpubk \
- ${MORE_OUT} ${MORE_OUT}.3
+"${FUTILITY}" load_fmap "${MORE_OUT}" VBLOCK_A:/dev/urandom VBLOCK_B:/dev/zero
+"${FUTILITY}" sign \
+ -k "${KEYDIR}/kernel_subkey.vbpubk" \
+ -K "${KEYDIR}" \
+ "${MORE_OUT}" "${MORE_OUT}.3"
-m=$(${FUTILITY} verify --publickey ${KEYDIR}/root_key.vbpubk ${MORE_OUT}.3 \
- | egrep 'Firmware version: +1$|Preamble flags: +0$' | wc -l)
-[ "$m" = "4" ]
+m=$("${FUTILITY}" verify --publickey "${KEYDIR}/root_key.vbpubk" \
+ "${MORE_OUT}.3" | grep -c -E 'Firmware version: +1$|Preamble flags: +0$')
+[ "${m}" = "4" ]
+
+
+# Check signing when B slot is empty
+: $(( count++ ))
+echo -n "${count} " 1>&3
+
+"${FUTILITY}" load_fmap "${CLEAN_B}" VBLOCK_B:/dev/zero FW_MAIN_B:/dev/zero
+"${FUTILITY}" sign \
+ -s "${KEYDIR}/firmware_data_key.vbprivk" \
+ -b "${KEYDIR}/firmware.keyblock" \
+ -K "${KEYDIR}" \
+ "${CLEAN_B}" "${CLEAN_B}.1"
+
+"${FUTILITY}" verify --publickey "${KEYDIR}/root_key.vbpubk" "${CLEAN_B}.1" \
+ | awk '/Firmware body size:/ {print $4}' > "${TMP}.clean_b.body"
+"${FUTILITY}" dump_fmap -p "${CLEAN_B}.1" \
+ | awk '/FW_MAIN_/ {print $3}' > "${TMP}.clean_b.fw_main"
+
+# These should not be equal, as FW_MAIN_A size should be kept intact, when size
+# of FW_MAIN_B should be taken from FlashMap.
+if cmp "${TMP}.clean_b.body" "${TMP}.clean_b.fw_main" ; then false; fi
+if cmp "${TMP}.clean_b.body" "${TMP}.good.body" ; then false; fi
+cmp_first_line "${TMP}.clean_b.body" "${TMP}.good.body"
+cmp_last_line "${TMP}.clean_b.body" "${TMP}.clean_b.fw_main"
+
+# Version for slot A should be kept intact, while for B slot it should default
+# to 1. All flags should be zero.
+m=$("${FUTILITY}" verify --publickey "${KEYDIR}/root_key.vbpubk" \
+ "${CLEAN_B}.1" \
+ | grep -c -E \
+ 'Firmware version: +1$|Preamble flags: +0$|Firmware version: +2$')
+[ "${m}" = "4" ]
+
+# Check signing when there is no B slot
+: $(( count++ ))
+echo -n "${count} " 1>&3
+
+NO_B_SLOT="${TMP}.${GOOD_CBFS##*/}.no_b_slot"
+NO_B_SLOT_SIGNED_IMG="${NO_B_SLOT}.signed"
+
+cp "${GOOD_CBFS}" "${NO_B_SLOT}"
+apply_xxd_patch "${NO_B_SLOT_PATCH}" "${NO_B_SLOT}"
+
+"${FUTILITY}" sign \
+ -s "${KEYDIR}/firmware_data_key.vbprivk" \
+ -k "${KEYDIR}/kernel_subkey.vbpubk" \
+ -K "${KEYDIR}" \
+ -v 1 \
+ "${NO_B_SLOT}" "${NO_B_SLOT_SIGNED_IMG}"
+
+"${FUTILITY}" verify --publickey "${KEYDIR}/root_key.vbpubk" \
+ "${NO_B_SLOT_SIGNED_IMG}" \
+ | awk '/Firmware body size:/ {print $4}' > "${TMP}.no_b_slot.body"
+"${FUTILITY}" dump_fmap -p "${NO_B_SLOT_SIGNED_IMG}" \
+ | awk '/FW_MAIN_/ {print $3}' > "${TMP}.no_b_slot.fw_main"
+
+if cmp "${TMP}.no_b_slot.body" "${TMP}.no_b_slot.fw_main" ; then false; fi
+cmp "${TMP}.no_b_slot.body" <(tail -n1 "${TMP}.good_cbfs.body")
+
+m=$("${FUTILITY}" verify --publickey "${KEYDIR}/root_key.vbpubk" \
+ "${NO_B_SLOT_SIGNED_IMG}" \
+ | grep -c -E 'Firmware version: +1$|Preamble flags: +0$')
+[ "${m}" = "2" ]
+
+# Check signing when cbfstool reports incorrect size
+# Signing should fail, as it should not be possible for CBFS contents to be
+# bigger than FlashMap size of the area
+: $(( count++ ))
+echo -n "${count} " 1>&3
+
+CBFSTOOL_STUB="$(realpath "${TMP}.cbfs_stub.sh")"
+echo -en 'echo "0xFFEEDD0"; exit 0;' > "${CBFSTOOL_STUB}"
+chmod +x "${CBFSTOOL_STUB}"
+
+if CBFSTOOL="${CBFSTOOL_STUB}" "${FUTILITY}" sign \
+ -b "${KEYDIR}/firmware.keyblock" \
+ -k "${KEYDIR}/kernel_subkey.vbpubk" \
+ -K "${KEYDIR}" \
+ -v 1 \
+ "${GOOD_CBFS}" "${TMP}.1.${GOOD_CBFS##*/}"
+then
+ false
+fi
+
+# Redefine cbfstool stub to return valid value for FW_MAIN_A and invalid for
+# FW_MAIN_B size. With this behavior futility should fail to sign this image,
+# as cbfstool should never return incorrect size (larger than area).
+cp "${GOOD_CBFS}" "${TMP}.good_cbfs.bin"
+FW_MAIN_A_SIZE="$(printf '0x%x' \
+ "$(cbfstool "${TMP}.good_cbfs.bin" truncate -r FW_MAIN_A)")"
+MARK_FILE="$(realpath "${TMP}.mark1")"
+rm -f "${MARK_FILE}"
+
+cat << EOF > "${CBFSTOOL_STUB}"
+#!/usr/bin/env bash
+if ! [ -f "${MARK_FILE}" ]; then
+ echo "${FW_MAIN_A_SIZE}";
+ echo 1 > "${MARK_FILE}";
+else
+ echo 0xFFFFAA0;
+fi
+exit 0;
+EOF
+
+if CBFSTOOL="${CBFSTOOL_STUB}" "${FUTILITY}" sign \
+ -K "${KEYDIR}" \
+ -v 1 \
+ "${GOOD_CBFS}" "${TMP}.2.${GOOD_CBFS##*/}"
+then
+ false
+fi
+
+
+# Check various incorrect values in VBLOCK (keyblock and preamble)
+: $(( count++ ))
+echo -n "${count} " 1>&3
+
+bad_counter=1
+for keyblock_patch in "${BAD_KEYBLOCK_PATCHES[@]}"; do
+ echo -n "${count}.${bad_counter} " 1>&3
+ BAD_IN="${TMP}.${GOOD_DEV##*/}.bad.${bad_counter}.in.bin"
+ BAD_OUT="${TMP}.${GOOD_DEV##*/}.bad.${bad_counter}.out.bin"
+ cp "${GOOD_DEV}" "${BAD_IN}"
+ apply_xxd_patch "${keyblock_patch}" "${BAD_IN}"
+
+ FUTIL_OUTPUT="$(if "${FUTILITY}" verify \
+ --publickey "${KEYDIR}/root_key.vbpubk" "${BAD_IN}"; \
+ then false; fi)"
+ grep -q 'VBLOCK_A keyblock component is invalid' <<< "${FUTIL_OUTPUT}"
+
+ FUTIL_OUTPUT="$("${FUTILITY}" sign \
+ -K "${KEYDIR}" \
+ "${BAD_IN}" "${BAD_OUT}" 2>&1)"
+ grep -q 'VBLOCK_A keyblock is invalid' <<< "${FUTIL_OUTPUT}"
+
+ "${FUTILITY}" verify --publickey "${KEYDIR}/root_key.vbpubk" "${BAD_OUT}" \
+ | awk '/Firmware body size:/ {print $4}' > "${BAD_OUT}.body"
+ "${FUTILITY}" dump_fmap -p "${BAD_OUT}" \
+ | awk '/FW_MAIN_/ {print $3}' > "${BAD_OUT}.fw_main"
+
+ cmp "${BAD_OUT}.fw_main" "${TMP}.good.fw_main"
+ cmp_first_line "${BAD_OUT}.body" "${TMP}.good.fw_main"
+ cmp_last_line "${BAD_OUT}.body" "${TMP}.good.body"
+
+ : $(( bad_counter++ ))
+done
+
+for vblock_patch in "${BAD_PREAMBLE_PATCHES[@]}"; do
+ echo -n "${count}.${bad_counter} " 1>&3
+ BAD_IN="${TMP}.${GOOD_DEV##*/}.bad.${bad_counter}.in.bin"
+ BAD_OUT="${TMP}.${GOOD_DEV##*/}.bad.${bad_counter}.out.bin"
+ cp "${GOOD_DEV}" "${BAD_IN}"
+ apply_xxd_patch "${vblock_patch}" "${BAD_IN}"
+
+ FUTIL_OUTPUT="$(if "${FUTILITY}" verify \
+ --publickey "${KEYDIR}/root_key.vbpubk" "${BAD_IN}"; \
+ then false; fi)"
+ grep -q 'VBLOCK_A is invalid' <<< "${FUTIL_OUTPUT}"
+
+ FUTIL_OUTPUT="$("${FUTILITY}" sign \
+ -K "${KEYDIR}" \
+ "${BAD_IN}" "${BAD_OUT}" 2>&1)"
+ grep -q 'VBLOCK_A preamble is invalid' <<< "${FUTIL_OUTPUT}"
+
+ "${FUTILITY}" verify --publickey "${KEYDIR}/root_key.vbpubk" "${BAD_OUT}" \
+ | awk '/Firmware body size:/ {print $4}' > "${BAD_OUT}.body"
+ "${FUTILITY}" dump_fmap -p "${BAD_OUT}" \
+ | awk '/FW_MAIN_/ {print $3}' > "${BAD_OUT}.fw_main"
+
+ cmp "${BAD_OUT}.fw_main" "${TMP}.good.fw_main"
+ cmp_first_line "${BAD_OUT}.body" "${TMP}.good.fw_main"
+ cmp_last_line "${BAD_OUT}.body" "${TMP}.good.body"
+
+ : $(( bad_counter++ ))
+done
+
+for vblock_patch in "${BAD_FMAP_KEYBLOCK_PATCHES[@]}"; do
+ echo -n "${count}.${bad_counter} " 1>&3
+ BAD_IN="${TMP}.${GOOD_DEV##*/}.bad.${bad_counter}.in.bin"
+ BAD_OUT="${TMP}.${GOOD_DEV##*/}.bad.${bad_counter}.out.bin"
+ cp "${GOOD_DEV}" "${BAD_IN}"
+ apply_xxd_patch "${vblock_patch}" "${BAD_IN}"
+
+ FUTIL_OUTPUT="$(if "${FUTILITY}" verify \
+ --publickey "${KEYDIR}/root_key.vbpubk" "${BAD_IN}"; \
+ then false; fi)"
+ grep -q 'VBLOCK_A keyblock component is invalid' <<< "${FUTIL_OUTPUT}"
+
+ FUTIL_OUTPUT="$(if "${FUTILITY}" sign \
+ -K "${KEYDIR}" \
+ "${BAD_IN}" "${BAD_OUT}" 2>&1; \
+ then false; fi)"
+ m="$(grep -c -E \
+ 'VBLOCK_A keyblock is invalid|Keyblock and preamble do not fit in VBLOCK' \
+ <<< "${FUTIL_OUTPUT}")"
+ [ "${m}" = "2" ]
+
+ : $(( bad_counter++ ))
+done
+
+echo -n "${count}.${bad_counter} " 1>&3
+BAD_IN="${TMP}.${GOOD_DEV##*/}.bad.${bad_counter}.in.bin"
+BAD_OUT="${TMP}.${GOOD_DEV##*/}.bad.${bad_counter}.out.bin"
+cp "${GOOD_DEV}" "${BAD_IN}"
+apply_xxd_patch "${BAD_FMAP_PREAMBLE_PATCHES[0]}" "${BAD_IN}"
+
+FUTIL_OUTPUT="$(if "${FUTILITY}" verify \
+ --publickey "${KEYDIR}/root_key.vbpubk" "${BAD_IN}"; \
+ then false; fi)"
+grep -q 'VBLOCK_A is invalid' <<< "${FUTIL_OUTPUT}"
+
+FUTIL_OUTPUT="$(if "${FUTILITY}" sign \
+ -K "${KEYDIR}" \
+ "${BAD_IN}" "${BAD_OUT}" 2>&1; \
+ then false; fi)"
+m="$(grep -c -E \
+ 'VBLOCK_A preamble is invalid|Keyblock and preamble do not fit in VBLOCK' \
+ <<< "${FUTIL_OUTPUT}")"
+[ "${m}" = "2" ]
+
+: $(( bad_counter++ ))
+
+echo -n "${count}.${bad_counter} " 1>&3
+BAD_IN="${TMP}.${GOOD_DEV##*/}.bad.${bad_counter}.in.bin"
+BAD_OUT="${TMP}.${GOOD_DEV##*/}.bad.${bad_counter}.out.bin"
+cp "${GOOD_DEV}" "${BAD_IN}"
+apply_xxd_patch "${BAD_FMAP_PREAMBLE_PATCHES[1]}" "${BAD_IN}"
+
+FUTIL_OUTPUT="$(if "${FUTILITY}" verify \
+ --publickey "${KEYDIR}/root_key.vbpubk" "${BAD_IN}"; \
+ then false; fi)"
+grep -q 'VBLOCK_A is invalid' <<< "${FUTIL_OUTPUT}"
+
+FUTIL_OUTPUT="$(if "${FUTILITY}" sign \
+ -K "${KEYDIR}" \
+ "${BAD_IN}" "${BAD_OUT}" 2>&1; \
+ then false; fi)"
+m="$(grep -c -E \
+ -e 'VBLOCK_A is invalid\. Keyblock and preamble do not fit' \
+ -e 'Keyblock and preamble do not fit in VBLOCK' \
+ <<< "${FUTIL_OUTPUT}")"
+[ "${m}" = "2" ]
+
+: $(( bad_counter++ ))
# cleanup
-rm -rf ${TMP}* ${ONEMORE}
+rm -rf "${TMP}"* "${ONEMORE}"
exit 0
diff --git a/tests/futility/test_sign_fw_main.sh b/tests/futility/test_sign_fw_main.sh
index face801..e22f907 100755
--- a/tests/futility/test_sign_fw_main.sh
+++ b/tests/futility/test_sign_fw_main.sh
@@ -9,38 +9,36 @@
# Work in scratch directory
cd "$OUTDIR"
-KEYDIR=${SRCDIR}/tests/devkeys
+KEYDIR="${SRCDIR}/tests/devkeys"
# create a firmware blob
-dd bs=1024 count=16 if=/dev/urandom of=${TMP}.fw_main
+dd bs=1024 count=16 if=/dev/urandom of="${TMP}.fw_main"
# try the old way
-${FUTILITY} vbutil_firmware --vblock ${TMP}.vblock.old \
- --keyblock ${KEYDIR}/firmware.keyblock \
- --signprivate ${KEYDIR}/firmware_data_key.vbprivk \
+"${FUTILITY}" vbutil_firmware --vblock "${TMP}.vblock.old" \
+ --keyblock "${KEYDIR}/firmware.keyblock" \
+ --signprivate "${KEYDIR}/firmware_data_key.vbprivk" \
--version 12 \
- --fv ${TMP}.fw_main \
- --kernelkey ${KEYDIR}/kernel_subkey.vbpubk \
+ --fv "${TMP}.fw_main" \
+ --kernelkey "${KEYDIR}/kernel_subkey.vbpubk" \
--flags 42
# verify
-${FUTILITY} vbutil_firmware --verify ${TMP}.vblock.old \
- --signpubkey ${KEYDIR}/root_key.vbpubk \
- --fv ${TMP}.fw_main
+"${FUTILITY}" vbutil_firmware --verify "${TMP}.vblock.old" \
+ --signpubkey "${KEYDIR}/root_key.vbpubk" \
+ --fv "${TMP}.fw_main"
# and the new way
-${FUTILITY} --debug sign \
- --signprivate ${KEYDIR}/firmware_data_key.vbprivk \
- --keyblock ${KEYDIR}/firmware.keyblock \
- --kernelkey ${KEYDIR}/kernel_subkey.vbpubk \
+"${FUTILITY}" --debug sign \
+ --keyset "${KEYDIR}" \
--version 12 \
- --fv ${TMP}.fw_main \
+ --fv "${TMP}.fw_main" \
--flags 42 \
- ${TMP}.vblock.new
+ "${TMP}.vblock.new"
# They should match
-cmp ${TMP}.vblock.old ${TMP}.vblock.new
+cmp "${TMP}.vblock.old" "${TMP}.vblock.new"
# cleanup
-rm -rf ${TMP}*
+rm -rf "${TMP}"*
exit 0
diff --git a/tests/futility/test_sign_kernel.sh b/tests/futility/test_sign_kernel.sh
index d252745..bba1164 100755
--- a/tests/futility/test_sign_kernel.sh
+++ b/tests/futility/test_sign_kernel.sh
@@ -11,11 +11,11 @@
DEVKEYS=${SRCDIR}/tests/devkeys
-echo "hi there" > ${TMP}.config.txt
-echo "hello boys" > ${TMP}.config2.txt
-dd if=/dev/urandom bs=512 count=1 of=${TMP}.bootloader.bin
-dd if=/dev/urandom bs=512 count=1 of=${TMP}.bootloader2.bin
-dd if=/dev/urandom bs=1M count=16 of=${TMP}.kern_partition
+echo "hi there" > "${TMP}.config.txt"
+echo "hello boys" > "${TMP}.config2.txt"
+dd if=/dev/urandom bs=512 count=1 of="${TMP}.bootloader.bin"
+dd if=/dev/urandom bs=512 count=1 of="${TMP}.bootloader2.bin"
+dd if=/dev/urandom bs=1M count=16 of="${TMP}.kern_partition"
# default padding
padding=49152
@@ -26,273 +26,278 @@
echo -n "${arch}: 1 " 1>&3
# pack it up the old way
- ${FUTILITY} --debug vbutil_kernel \
- --pack ${TMP}.blob1.${arch} \
- --keyblock ${DEVKEYS}/recovery_kernel.keyblock \
- --signprivate ${DEVKEYS}/recovery_kernel_data_key.vbprivk \
+ "${FUTILITY}" --debug vbutil_kernel \
+ --pack "${TMP}.blob1.${arch}" \
+ --keyblock "${DEVKEYS}/recovery_kernel.keyblock" \
+ --signprivate "${DEVKEYS}/recovery_kernel_data_key.vbprivk" \
--version 1 \
- --config ${TMP}.config.txt \
- --bootloader ${TMP}.bootloader.bin \
- --vmlinuz ${SCRIPT_DIR}/futility/data/vmlinuz-${arch}.bin \
- --arch ${arch} \
- --pad ${padding} \
+ --config "${TMP}.config.txt" \
+ --bootloader "${TMP}.bootloader.bin" \
+ --vmlinuz "${SCRIPT_DIR}/futility/data/vmlinuz-${arch}.bin" \
+ --arch "${arch}" \
+ --pad "${padding}" \
--kloadaddr 0x11000
# verify the old way
- ${FUTILITY} vbutil_kernel --verify ${TMP}.blob1.${arch} \
- --pad ${padding} \
- --signpubkey ${DEVKEYS}/recovery_key.vbpubk > ${TMP}.verify1
+ "${FUTILITY}" vbutil_kernel --verify "${TMP}.blob1.${arch}" \
+ --pad "${padding}" \
+ --signpubkey "${DEVKEYS}/recovery_key.vbpubk" > "${TMP}.verify1"
# pack it up the new way
- ${FUTILITY} --debug sign \
- --keyblock ${DEVKEYS}/recovery_kernel.keyblock \
- --signprivate ${DEVKEYS}/recovery_kernel_data_key.vbprivk \
+ "${FUTILITY}" --debug sign \
+ --keyset "${DEVKEYS}/recovery_" \
--version 1 \
- --config ${TMP}.config.txt \
- --bootloader ${TMP}.bootloader.bin \
- --vmlinuz ${SCRIPT_DIR}/futility/data/vmlinuz-${arch}.bin \
- --arch ${arch} \
- --pad ${padding} \
+ --config "${TMP}.config.txt" \
+ --bootloader "${TMP}.bootloader.bin" \
+ --vmlinuz "${SCRIPT_DIR}/futility/data/vmlinuz-${arch}.bin" \
+ --arch "${arch}" \
+ --pad "${padding}" \
--kloadaddr 0x11000 \
- --outfile ${TMP}.blob2.${arch}
+ --outfile "${TMP}.blob2.${arch}"
- ${FUTILITY} vbutil_kernel --verify ${TMP}.blob2.${arch} \
- --pad ${padding} \
- --signpubkey ${DEVKEYS}/recovery_key.vbpubk > ${TMP}.verify2
+ "${FUTILITY}" vbutil_kernel --verify "${TMP}.blob2.${arch}" \
+ --pad "${padding}" \
+ --signpubkey "${DEVKEYS}/recovery_key.vbpubk" > "${TMP}.verify2"
# they should be identical
- cmp ${TMP}.blob1.${arch} ${TMP}.blob2.${arch}
- diff ${TMP}.verify1 ${TMP}.verify2
+ cmp "${TMP}.blob1.${arch}" "${TMP}.blob2.${arch}"
+ diff "${TMP}.verify1" "${TMP}.verify2"
echo -n "2 " 1>&3
# repack it the old way
- ${FUTILITY} --debug vbutil_kernel \
- --repack ${TMP}.blob3.${arch} \
- --oldblob ${TMP}.blob1.${arch} \
- --signprivate ${DEVKEYS}/kernel_data_key.vbprivk \
- --keyblock ${DEVKEYS}/kernel.keyblock \
+ "${FUTILITY}" --debug vbutil_kernel \
+ --repack "${TMP}.blob3.${arch}" \
+ --oldblob "${TMP}.blob1.${arch}" \
+ --signprivate "${DEVKEYS}/kernel_data_key.vbprivk" \
+ --keyblock "${DEVKEYS}/kernel.keyblock" \
--version 2 \
- --pad ${padding} \
- --config ${TMP}.config2.txt \
- --bootloader ${TMP}.bootloader2.bin
+ --pad "${padding}" \
+ --config "${TMP}.config2.txt" \
+ --bootloader "${TMP}.bootloader2.bin"
# verify the old way
- ${FUTILITY} vbutil_kernel --verify ${TMP}.blob3.${arch} \
- --pad ${padding} \
- --signpubkey ${DEVKEYS}/kernel_subkey.vbpubk > ${TMP}.verify3
+ "${FUTILITY}" vbutil_kernel --verify "${TMP}.blob3.${arch}" \
+ --pad "${padding}" \
+ --signpubkey "${DEVKEYS}/kernel_subkey.vbpubk" > "${TMP}.verify3"
# repack it the new way
- ${FUTILITY} --debug sign \
- --signprivate ${DEVKEYS}/kernel_data_key.vbprivk \
- --keyblock ${DEVKEYS}/kernel.keyblock \
+ "${FUTILITY}" --debug sign \
+ --keyset "${DEVKEYS}" \
+ --keyblock "${DEVKEYS}/kernel.keyblock" \
--version 2 \
- --pad ${padding} \
- --config ${TMP}.config2.txt \
- --bootloader ${TMP}.bootloader2.bin \
- ${TMP}.blob2.${arch} \
- ${TMP}.blob4.${arch}
+ --pad "${padding}" \
+ --config "${TMP}.config2.txt" \
+ --bootloader "${TMP}.bootloader2.bin" \
+ "${TMP}.blob2.${arch}" \
+ "${TMP}.blob4.${arch}"
- ${FUTILITY} vbutil_kernel --verify ${TMP}.blob4.${arch} \
- --pad ${padding} \
- --signpubkey ${DEVKEYS}/kernel_subkey.vbpubk > ${TMP}.verify4
+ "${FUTILITY}" vbutil_kernel --verify "${TMP}.blob4.${arch}" \
+ --pad "${padding}" \
+ --signpubkey "${DEVKEYS}/kernel_subkey.vbpubk" > "${TMP}.verify4"
# they should be identical
- cmp ${TMP}.blob3.${arch} ${TMP}.blob4.${arch}
- diff ${TMP}.verify3 ${TMP}.verify4
+ cmp "${TMP}.blob3.${arch}" "${TMP}.blob4.${arch}"
+ diff "${TMP}.verify3" "${TMP}.verify4"
echo -n "3 " 1>&3
# repack it the new way, in-place
- cp ${TMP}.blob2.${arch} ${TMP}.blob5.${arch}
- ${FUTILITY} --debug sign \
- --signprivate ${DEVKEYS}/kernel_data_key.vbprivk \
- --keyblock ${DEVKEYS}/kernel.keyblock \
+ cp "${TMP}.blob2.${arch}" "${TMP}.blob5.${arch}"
+ "${FUTILITY}" --debug sign \
+ --signprivate "${DEVKEYS}/kernel_data_key.vbprivk" \
+ --keyblock "${DEVKEYS}/kernel.keyblock" \
--version 2 \
- --pad ${padding} \
- --config ${TMP}.config2.txt \
- --bootloader ${TMP}.bootloader2.bin \
- ${TMP}.blob5.${arch}
+ --pad "${padding}" \
+ --config "${TMP}.config2.txt" \
+ --bootloader "${TMP}.bootloader2.bin" \
+ "${TMP}.blob5.${arch}"
- ${FUTILITY} vbutil_kernel --verify ${TMP}.blob5.${arch} \
- --pad ${padding} \
- --signpubkey ${DEVKEYS}/kernel_subkey.vbpubk > ${TMP}.verify5
+ "${FUTILITY}" vbutil_kernel --verify "${TMP}.blob5.${arch}" \
+ --pad "${padding}" \
+ --signpubkey "${DEVKEYS}/kernel_subkey.vbpubk" > "${TMP}.verify5"
# they should be identical
- cmp ${TMP}.blob3.${arch} ${TMP}.blob5.${arch}
- diff ${TMP}.verify3 ${TMP}.verify5
+ cmp "${TMP}.blob3.${arch}" "${TMP}.blob5.${arch}"
+ diff "${TMP}.verify3" "${TMP}.verify5"
# and now just the vblocks...
echo -n "4 " 1>&3
# pack the old way
- ${FUTILITY} vbutil_kernel \
- --pack ${TMP}.blob1.${arch}.vb1 \
+ "${FUTILITY}" vbutil_kernel \
+ --pack "${TMP}.blob1.${arch}.vb1" \
--vblockonly \
- --keyblock ${DEVKEYS}/recovery_kernel.keyblock \
- --signprivate ${DEVKEYS}/recovery_kernel_data_key.vbprivk \
+ --keyblock "${DEVKEYS}/recovery_kernel.keyblock" \
+ --signprivate "${DEVKEYS}/recovery_kernel_data_key.vbprivk" \
--version 1 \
- --config ${TMP}.config.txt \
- --bootloader ${TMP}.bootloader.bin \
- --vmlinuz ${SCRIPT_DIR}/futility/data/vmlinuz-${arch}.bin \
- --arch ${arch} \
- --pad ${padding} \
+ --config "${TMP}.config.txt" \
+ --bootloader "${TMP}.bootloader.bin" \
+ --vmlinuz "${SCRIPT_DIR}/futility/data/vmlinuz-${arch}.bin" \
+ --arch "${arch}" \
+ --pad "${padding}" \
--kloadaddr 0x11000
# compare this new vblock with the one from the full pack
- dd bs=${padding} count=1 if=${TMP}.blob1.${arch} of=${TMP}.blob1.${arch}.vb0
- cmp ${TMP}.blob1.${arch}.vb0 ${TMP}.blob1.${arch}.vb1
+ dd bs="${padding}" count=1 if="${TMP}.blob1.${arch}" \
+ of="${TMP}.blob1.${arch}.vb0"
+ cmp "${TMP}.blob1.${arch}.vb0" "${TMP}.blob1.${arch}.vb1"
# pack the new way
- ${FUTILITY} --debug sign \
- --keyblock ${DEVKEYS}/recovery_kernel.keyblock \
- --signprivate ${DEVKEYS}/recovery_kernel_data_key.vbprivk \
+ "${FUTILITY}" --debug sign \
+ --keyblock "${DEVKEYS}/recovery_kernel.keyblock" \
+ --signprivate "${DEVKEYS}/recovery_kernel_data_key.vbprivk" \
--version 1 \
- --config ${TMP}.config.txt \
- --bootloader ${TMP}.bootloader.bin \
- --vmlinuz ${SCRIPT_DIR}/futility/data/vmlinuz-${arch}.bin \
- --arch ${arch} \
- --pad ${padding} \
+ --config "${TMP}.config.txt" \
+ --bootloader "${TMP}.bootloader.bin" \
+ --vmlinuz "${SCRIPT_DIR}/futility/data/vmlinuz-${arch}.bin" \
+ --arch "${arch}" \
+ --pad "${padding}" \
--kloadaddr 0x11000 \
--vblockonly \
- ${TMP}.blob2.${arch}.vb1
+ "${TMP}.blob2.${arch}.vb1"
# compare this new vblock with the one from the full pack
- dd bs=${padding} count=1 if=${TMP}.blob2.${arch} of=${TMP}.blob2.${arch}.vb0
- cmp ${TMP}.blob2.${arch}.vb0 ${TMP}.blob2.${arch}.vb1
+ dd bs="${padding}" count=1 if="${TMP}.blob2.${arch}" \
+ of="${TMP}.blob2.${arch}.vb0"
+ cmp "${TMP}.blob2.${arch}.vb0" "${TMP}.blob2.${arch}.vb1"
echo -n "5 " 1>&3
# now repack the old way, again emitting just the vblock
- ${FUTILITY} vbutil_kernel \
- --repack ${TMP}.blob3.${arch}.vb1 \
+ "${FUTILITY}" vbutil_kernel \
+ --repack "${TMP}.blob3.${arch}.vb1" \
--vblockonly \
- --oldblob ${TMP}.blob1.${arch} \
- --signprivate ${DEVKEYS}/kernel_data_key.vbprivk \
- --keyblock ${DEVKEYS}/kernel.keyblock \
+ --oldblob "${TMP}.blob1.${arch}" \
+ --signprivate "${DEVKEYS}/kernel_data_key.vbprivk" \
+ --keyblock "${DEVKEYS}/kernel.keyblock" \
--version 2 \
- --pad ${padding} \
- --config ${TMP}.config2.txt \
- --bootloader ${TMP}.bootloader2.bin
+ --pad "${padding}" \
+ --config "${TMP}.config2.txt" \
+ --bootloader "${TMP}.bootloader2.bin"
# compare the full repacked vblock with the new repacked vblock
- dd bs=${padding} count=1 if=${TMP}.blob3.${arch} of=${TMP}.blob3.${arch}.vb0
- cmp ${TMP}.blob3.${arch}.vb0 ${TMP}.blob3.${arch}.vb1
+ dd bs="${padding}" count=1 if="${TMP}.blob3.${arch}" \
+ of="${TMP}.blob3.${arch}.vb0"
+ cmp "${TMP}.blob3.${arch}.vb0" "${TMP}.blob3.${arch}.vb1"
# extract just the kernel blob
- dd bs=${padding} skip=1 if=${TMP}.blob3.${arch} of=${TMP}.blob3.${arch}.kb0
+ dd bs="${padding}" skip=1 if="${TMP}.blob3.${arch}" \
+ of="${TMP}.blob3.${arch}.kb0"
# and verify it using the new vblock (no way to do that with vbutil_kernel)
- ${FUTILITY} --debug verify \
- --pad ${padding} \
- --publickey ${DEVKEYS}/kernel_subkey.vbpubk \
- --fv ${TMP}.blob3.${arch}.kb0 \
- ${TMP}.blob3.${arch}.vb1 > ${TMP}.verify3v
+ "${FUTILITY}" --debug verify \
+ --pad "${padding}" \
+ --publickey "${DEVKEYS}/kernel_subkey.vbpubk" \
+ --fv "${TMP}.blob3.${arch}.kb0" \
+ "${TMP}.blob3.${arch}.vb1" > "${TMP}.verify3v"
# repack the new way
- ${FUTILITY} --debug sign \
- --signprivate ${DEVKEYS}/kernel_data_key.vbprivk \
- --keyblock ${DEVKEYS}/kernel.keyblock \
+ "${FUTILITY}" --debug sign \
+ --signprivate "${DEVKEYS}/kernel_data_key.vbprivk" \
+ --keyblock "${DEVKEYS}/kernel.keyblock" \
--version 2 \
- --config ${TMP}.config2.txt \
- --bootloader ${TMP}.bootloader2.bin \
- --pad ${padding} \
+ --config "${TMP}.config2.txt" \
+ --bootloader "${TMP}.bootloader2.bin" \
+ --pad "${padding}" \
--vblockonly \
- ${TMP}.blob2.${arch} \
- ${TMP}.blob4.${arch}.vb1 \
+ "${TMP}.blob2.${arch}" \
+ "${TMP}.blob4.${arch}.vb1" \
# compare the full repacked vblock with the new repacked vblock
- dd bs=${padding} count=1 if=${TMP}.blob4.${arch} of=${TMP}.blob4.${arch}.vb0
- cmp ${TMP}.blob4.${arch}.vb0 ${TMP}.blob4.${arch}.vb1
+ dd bs="${padding}" count=1 if="${TMP}.blob4.${arch}" \
+ of="${TMP}.blob4.${arch}.vb0"
+ cmp "${TMP}.blob4.${arch}.vb0" "${TMP}.blob4.${arch}.vb1"
# extract just the kernel blob
- dd bs=${padding} skip=1 if=${TMP}.blob4.${arch} of=${TMP}.blob4.${arch}.kb0
+ dd bs="${padding}" skip=1 if="${TMP}.blob4.${arch}" \
+ of="${TMP}.blob4.${arch}.kb0"
# and verify it using the new vblock (no way to do that with vbutil_kernel)
- ${FUTILITY} --debug verify \
- --pad ${padding} \
- --publickey ${DEVKEYS}/kernel_subkey.vbpubk \
- --fv ${TMP}.blob4.${arch}.kb0 \
- ${TMP}.blob4.${arch}.vb1 > ${TMP}.verify4v
+ "${FUTILITY}" --debug verify \
+ --pad "${padding}" \
+ --publickey "${DEVKEYS}/kernel_subkey.vbpubk" \
+ --fv "${TMP}.blob4.${arch}.kb0" \
+ "${TMP}.blob4.${arch}.vb1" > "${TMP}.verify4v"
echo -n "6 " 1>&3
# Now lets repack some kernel partitions, not just blobs.
- cp ${TMP}.kern_partition ${TMP}.part1.${arch}
- dd if=${TMP}.blob1.${arch} of=${TMP}.part1.${arch} conv=notrunc
+ cp "${TMP}.kern_partition" "${TMP}.part1.${arch}"
+ dd if="${TMP}.blob1.${arch}" of="${TMP}.part1.${arch}" conv=notrunc
# Make sure the partitions verify
- ${FUTILITY} vbutil_kernel --verify ${TMP}.part1.${arch} \
- --pad ${padding} \
- --signpubkey ${DEVKEYS}/recovery_key.vbpubk > ${TMP}.verify6
+ "${FUTILITY}" vbutil_kernel --verify "${TMP}.part1.${arch}" \
+ --pad "${padding}" \
+ --signpubkey "${DEVKEYS}/recovery_key.vbpubk" > "${TMP}.verify6"
# The partition should verify the same way as the blob
- diff ${TMP}.verify1 ${TMP}.verify6
+ diff "${TMP}.verify1" "${TMP}.verify6"
# repack it the old way
- ${FUTILITY} --debug vbutil_kernel \
- --repack ${TMP}.part6.${arch} \
- --oldblob ${TMP}.part1.${arch} \
- --signprivate ${DEVKEYS}/kernel_data_key.vbprivk \
- --keyblock ${DEVKEYS}/kernel.keyblock \
+ "${FUTILITY}" --debug vbutil_kernel \
+ --repack "${TMP}.part6.${arch}" \
+ --oldblob "${TMP}.part1.${arch}" \
+ --signprivate "${DEVKEYS}/kernel_data_key.vbprivk" \
+ --keyblock "${DEVKEYS}/kernel.keyblock" \
--version 2 \
- --pad ${padding} \
- --config ${TMP}.config2.txt \
- --bootloader ${TMP}.bootloader2.bin
+ --pad "${padding}" \
+ --config "${TMP}.config2.txt" \
+ --bootloader "${TMP}.bootloader2.bin"
# verify the old way
- ${FUTILITY} vbutil_kernel --verify ${TMP}.part6.${arch} \
- --pad ${padding} \
- --signpubkey ${DEVKEYS}/kernel_subkey.vbpubk > ${TMP}.verify6.old
+ "${FUTILITY}" vbutil_kernel --verify "${TMP}.part6.${arch}" \
+ --pad "${padding}" \
+ --signpubkey "${DEVKEYS}/kernel_subkey.vbpubk" > "${TMP}.verify6.old"
# this "partition" should actually be the same as the old-way blob
- cmp ${TMP}.blob3.${arch} ${TMP}.part6.${arch}
+ cmp "${TMP}.blob3.${arch}" "${TMP}.part6.${arch}"
# repack it the new way, in-place
- cp ${TMP}.part1.${arch} ${TMP}.part6.${arch}.new1
- ${FUTILITY} --debug sign \
- --signprivate ${DEVKEYS}/kernel_data_key.vbprivk \
- --keyblock ${DEVKEYS}/kernel.keyblock \
+ cp "${TMP}.part1.${arch}" "${TMP}.part6.${arch}.new1"
+ "${FUTILITY}" --debug sign \
+ --signprivate "${DEVKEYS}/kernel_data_key.vbprivk" \
+ --keyblock "${DEVKEYS}/kernel.keyblock" \
--version 2 \
- --pad ${padding} \
- --config ${TMP}.config2.txt \
- --bootloader ${TMP}.bootloader2.bin \
- ${TMP}.part6.${arch}.new1
+ --pad "${padding}" \
+ --config "${TMP}.config2.txt" \
+ --bootloader "${TMP}.bootloader2.bin" \
+ "${TMP}.part6.${arch}.new1"
- ${FUTILITY} vbutil_kernel --verify ${TMP}.part6.${arch}.new1 \
- --pad ${padding} \
- --signpubkey ${DEVKEYS}/kernel_subkey.vbpubk > ${TMP}.verify6.new1
+ "${FUTILITY}" vbutil_kernel --verify "${TMP}.part6.${arch}.new1" \
+ --pad "${padding}" \
+ --signpubkey "${DEVKEYS}/kernel_subkey.vbpubk" > "${TMP}.verify6.new1"
# The verification should be indentical
- diff ${TMP}.verify6.old ${TMP}.verify6.new1
+ diff "${TMP}.verify6.old" "${TMP}.verify6.new1"
# But the content should only match up to the size of the kernel blob, since
# we're modifying an entire partition in-place.
- blobsize=$(stat -c '%s' ${TMP}.part6.${arch})
- cmp -n ${blobsize} ${TMP}.part6.${arch} ${TMP}.part6.${arch}.new1
+ blobsize=$(stat -c '%s' "${TMP}.part6.${arch}")
+ cmp -n "${blobsize}" "${TMP}.part6.${arch}" "${TMP}.part6.${arch}.new1"
# The rest of the partition should be unchanged.
- cmp -i ${blobsize} ${TMP}.part1.${arch} ${TMP}.part6.${arch}.new1
+ cmp -i "${blobsize}" "${TMP}.part1.${arch}" "${TMP}.part6.${arch}.new1"
# repack it the new way, from input to output
- cp ${TMP}.part1.${arch} ${TMP}.part1.${arch}.in
- ${FUTILITY} --debug sign \
- --signprivate ${DEVKEYS}/kernel_data_key.vbprivk \
- --keyblock ${DEVKEYS}/kernel.keyblock \
+ cp "${TMP}.part1.${arch}" "${TMP}.part1.${arch}.in"
+ "${FUTILITY}" --debug sign \
+ --signprivate "${DEVKEYS}/kernel_data_key.vbprivk" \
+ --keyblock "${DEVKEYS}/kernel.keyblock" \
--version 2 \
- --pad ${padding} \
- --config ${TMP}.config2.txt \
- --bootloader ${TMP}.bootloader2.bin \
- ${TMP}.part1.${arch}.in \
- ${TMP}.part6.${arch}.new2
+ --pad "${padding}" \
+ --config "${TMP}.config2.txt" \
+ --bootloader "${TMP}.bootloader2.bin" \
+ "${TMP}.part1.${arch}.in" \
+ "${TMP}.part6.${arch}.new2"
- ${FUTILITY} vbutil_kernel --verify ${TMP}.part6.${arch}.new2 \
- --pad ${padding} \
- --signpubkey ${DEVKEYS}/kernel_subkey.vbpubk > ${TMP}.verify6.new2
+ "${FUTILITY}" vbutil_kernel --verify "${TMP}.part6.${arch}.new2" \
+ --pad "${padding}" \
+ --signpubkey "${DEVKEYS}/kernel_subkey.vbpubk" > "${TMP}.verify6.new2"
# The input file should not have changed (just being sure).
- cmp ${TMP}.part1.${arch} ${TMP}.part1.${arch}.in
+ cmp "${TMP}.part1.${arch}" "${TMP}.part1.${arch}.in"
# The verification should be indentical
- diff ${TMP}.verify6.old ${TMP}.verify6.new2
+ diff "${TMP}.verify6.old" "${TMP}.verify6.new2"
# And creating a new output file should only emit a blob's worth
- cmp ${TMP}.part6.${arch} ${TMP}.part6.${arch}.new2
+ cmp "${TMP}.part6.${arch}" "${TMP}.part6.${arch}.new2"
# Note: We specifically do not test repacking with a different --kloadaddr,
# because the old way has a bug and does not update params->cmd_line_ptr to
@@ -304,5 +309,5 @@
try_arch arm
# cleanup
-rm -rf ${TMP}*
+rm -rf "${TMP}"*
exit 0
diff --git a/tests/futility/test_sign_keyblocks.sh b/tests/futility/test_sign_keyblocks.sh
index f689c89..75d367d 100755
--- a/tests/futility/test_sign_keyblocks.sh
+++ b/tests/futility/test_sign_keyblocks.sh
@@ -16,95 +16,95 @@
# Create a copy of an existing keyblock, using the old way
-${FUTILITY} vbutil_keyblock --pack ${TMP}.keyblock0 \
- --datapubkey ${DEVKEYS}/firmware_data_key.vbpubk \
+"${FUTILITY}" vbutil_keyblock --pack "${TMP}.keyblock0" \
+ --datapubkey "${DEVKEYS}/firmware_data_key.vbpubk" \
--flags 23 \
- --signprivate ${DEVKEYS}/root_key.vbprivk
+ --signprivate "${DEVKEYS}/root_key.vbprivk"
# Check it.
-${FUTILITY} vbutil_keyblock --unpack ${TMP}.keyblock0 \
- --signpubkey ${DEVKEYS}/root_key.vbpubk
+"${FUTILITY}" vbutil_keyblock --unpack "${TMP}.keyblock0" \
+ --signpubkey "${DEVKEYS}/root_key.vbpubk"
# It should be the same as the dev-key firmware keyblock
-cmp ${DEVKEYS}/firmware.keyblock ${TMP}.keyblock0
+cmp "${DEVKEYS}/firmware.keyblock" "${TMP}.keyblock0"
# Now create it the new way
-${FUTILITY} --debug sign \
- --datapubkey ${DEVKEYS}/firmware_data_key.vbpubk \
+"${FUTILITY}" --debug sign \
+ --datapubkey "${DEVKEYS}/firmware_data_key.vbpubk" \
--flags 23 \
- --signprivate ${DEVKEYS}/root_key.vbprivk \
- --outfile ${TMP}.keyblock1
+ --signprivate "${DEVKEYS}/root_key.vbprivk" \
+ --outfile "${TMP}.keyblock1"
# It should be the same too.
-cmp ${DEVKEYS}/firmware.keyblock ${TMP}.keyblock1
+cmp "${DEVKEYS}/firmware.keyblock" "${TMP}.keyblock1"
# Create a keyblock without signing it.
# old way
-${FUTILITY} vbutil_keyblock --pack ${TMP}.keyblock0 \
- --datapubkey ${DEVKEYS}/firmware_data_key.vbpubk \
+"${FUTILITY}" vbutil_keyblock --pack "${TMP}.keyblock0" \
+ --datapubkey "${DEVKEYS}/firmware_data_key.vbpubk" \
--flags 14
# new way
-${FUTILITY} --debug sign \
+"${FUTILITY}" --debug sign \
--flags 14 \
- ${DEVKEYS}/firmware_data_key.vbpubk \
- ${TMP}.keyblock1
+ "${DEVKEYS}/firmware_data_key.vbpubk" \
+ "${TMP}.keyblock1"
-cmp ${TMP}.keyblock0 ${TMP}.keyblock1
+cmp "${TMP}.keyblock0" "${TMP}.keyblock1"
# Create one using PEM args
# old way
-${FUTILITY} vbutil_keyblock --pack ${TMP}.keyblock2 \
- --datapubkey ${DEVKEYS}/firmware_data_key.vbpubk \
- --signprivate_pem ${TESTKEYS}/key_rsa4096.pem \
+"${FUTILITY}" vbutil_keyblock --pack "${TMP}.keyblock2" \
+ --datapubkey "${DEVKEYS}/firmware_data_key.vbpubk" \
+ --signprivate_pem "${TESTKEYS}/key_rsa4096.pem" \
--pem_algorithm 8 \
--flags 9
# verify it
-${FUTILITY} vbutil_keyblock --unpack ${TMP}.keyblock2 \
- --signpubkey ${TESTKEYS}/key_rsa4096.sha512.vbpubk
+"${FUTILITY}" vbutil_keyblock --unpack "${TMP}.keyblock2" \
+ --signpubkey "${TESTKEYS}/key_rsa4096.sha512.vbpubk"
# new way
-${FUTILITY} --debug sign \
- --pem_signpriv ${TESTKEYS}/key_rsa4096.pem \
+"${FUTILITY}" --debug sign \
+ --pem_signpriv "${TESTKEYS}/key_rsa4096.pem" \
--pem_algo 8 \
--flags 9 \
- ${DEVKEYS}/firmware_data_key.vbpubk \
- ${TMP}.keyblock3
+ "${DEVKEYS}/firmware_data_key.vbpubk" \
+ "${TMP}.keyblock3"
-cmp ${TMP}.keyblock2 ${TMP}.keyblock3
+cmp "${TMP}.keyblock2" "${TMP}.keyblock3"
# Try it with an external signer
# old way
-${FUTILITY} vbutil_keyblock --pack ${TMP}.keyblock4 \
- --datapubkey ${DEVKEYS}/firmware_data_key.vbpubk \
- --signprivate_pem ${TESTKEYS}/key_rsa4096.pem \
+"${FUTILITY}" vbutil_keyblock --pack "${TMP}.keyblock4" \
+ --datapubkey "${DEVKEYS}/firmware_data_key.vbpubk" \
+ --signprivate_pem "${TESTKEYS}/key_rsa4096.pem" \
--pem_algorithm 8 \
--flags 19 \
- --externalsigner ${SIGNER}
+ --externalsigner "${SIGNER}"
# verify it
-${FUTILITY} vbutil_keyblock --unpack ${TMP}.keyblock4 \
- --signpubkey ${TESTKEYS}/key_rsa4096.sha512.vbpubk
+"${FUTILITY}" vbutil_keyblock --unpack "${TMP}.keyblock4" \
+ --signpubkey "${TESTKEYS}/key_rsa4096.sha512.vbpubk"
# new way
-${FUTILITY} --debug sign \
- --pem_signpriv ${TESTKEYS}/key_rsa4096.pem \
+"${FUTILITY}" --debug sign \
+ --pem_signpriv "${TESTKEYS}/key_rsa4096.pem" \
--pem_algo 8 \
- --pem_external ${SIGNER} \
+ --pem_external "${SIGNER}" \
--flags 19 \
- ${DEVKEYS}/firmware_data_key.vbpubk \
- ${TMP}.keyblock5
+ "${DEVKEYS}/firmware_data_key.vbpubk" \
+ "${TMP}.keyblock5"
-cmp ${TMP}.keyblock4 ${TMP}.keyblock5
+cmp "${TMP}.keyblock4" "${TMP}.keyblock5"
# cleanup
-rm -rf ${TMP}*
+rm -rf "${TMP}"*
exit 0
diff --git a/tests/futility/test_sign_usbpd1.sh b/tests/futility/test_sign_usbpd1.sh
index 48e64eb..2324fae 100755
--- a/tests/futility/test_sign_usbpd1.sh
+++ b/tests/futility/test_sign_usbpd1.sh
@@ -24,33 +24,33 @@
: $(( count++ ))
echo -n "$count " 1>&3
- pemfile=${DATADIR}/${test}.pem
- infile=${DATADIR}/${test}.unsigned
- goodfile=${DATADIR}/${test}.signed
- outfile=${TMP}.${test}.new
+ pemfile="${DATADIR}/${test}.pem"
+ infile="${DATADIR}/${test}.unsigned"
+ goodfile="${DATADIR}/${test}.signed"
+ outfile="${TMP}.${test}.new"
# Signing the whole thing with futility should produce identical results
- ${FUTILITY} sign --type usbpd1 --pem ${pemfile} ${infile} ${outfile}
- cmp ${goodfile} ${outfile}
+ "${FUTILITY}" sign --type usbpd1 --pem "${pemfile}" "${infile}" "${outfile}"
+ cmp "${goodfile}" "${outfile}"
# Now try signing just the RW part
- size=$(stat -c '%s' ${infile})
+ size=$(stat -c '%s' "${infile}")
half=$(( size / 2 ))
- newin=${TMP}.${test}.rw_in
- dd if=${infile} bs=${half} count=1 skip=1 of=${newin}
+ newin="${TMP}.${test}.rw_in"
+ dd if="${infile}" bs="${half}" count=1 skip=1 of="${newin}"
newgood=${TMP}.${test}.rw_ok
- dd if=${goodfile} bs=${half} count=1 skip=1 of=${newgood}
- newout=${TMP}.${test}.rw_out
+ dd if="${goodfile}" bs="${half}" count=1 skip=1 of="${newgood}"
+ newout="${TMP}.${test}.rw_out"
# Sign the RW part alone
- ${FUTILITY} sign --type usbpd1 --pem ${pemfile} \
+ "${FUTILITY}" sign --type usbpd1 --pem "${pemfile}" \
--ro_size 0 \
- ${newin} ${newout}
- cmp ${newgood} ${newout}
+ "${newin}" "${newout}"
+ cmp "${newgood}" "${newout}"
done
# cleanup
-rm -rf ${TMP}*
+rm -rf "${TMP}"*
exit 0
diff --git a/tests/futility/test_update.sh b/tests/futility/test_update.sh
index 25c5543..8d8a559 100755
--- a/tests/futility/test_update.sh
+++ b/tests/futility/test_update.sh
@@ -40,12 +40,12 @@
set -o pipefail
# In all the test scenario, we want to test "updating from PEPPY to LINK".
-TO_IMAGE=${TMP}.src.link
-FROM_IMAGE=${TMP}.src.peppy
+TO_IMAGE="${TMP}.src.link"
+FROM_IMAGE="${TMP}.src.peppy"
TO_HWID="X86 LINK TEST 6638"
FROM_HWID="X86 PEPPY TEST 4211"
-cp -f ${LINK_BIOS} ${TO_IMAGE}
-cp -f ${PEPPY_BIOS} ${FROM_IMAGE}
+cp -f "${LINK_BIOS}" "${TO_IMAGE}"
+cp -f "${PEPPY_BIOS}" "${FROM_IMAGE}"
"${FUTILITY}" load_fmap "${FROM_IMAGE}" \
RO_VPD:"${RO_VPD_BLOB}" RW_VPD:"${RO_VPD_BLOB}"
cp -f "${FROM_IMAGE}" "${FROM_IMAGE}".unpatched
@@ -57,29 +57,34 @@
local data="$4"
# NAME OFFSET SIZE
- local fmap_info="$(${FUTILITY} dump_fmap -p ${file} ${section})"
- local base="$(echo "${fmap_info}" | sed 's/^[^ ]* //; s/ [^ ]*$//')"
- local offset=$((base + section_offset))
+ local fmap_info
+ local base
+ local offset
+
+ fmap_info="$("${FUTILITY}" dump_fmap -p "${file}" "${section}")"
+ base="$(echo "${fmap_info}" | sed 's/^[^ ]* //; s/ [^ ]*$//')"
+ offset=$((base + section_offset))
echo "offset: ${offset}"
- printf "${data}" | dd of="${file}" bs=1 seek="${offset}" conv=notrunc
+ printf "%b" "${data}" | dd of="${file}" bs=1 seek="${offset}" \
+ conv=notrunc
}
# PEPPY and LINK have different platform element ("Google_Link" and
# "Google_Peppy") in firmware ID so we want to hack them by changing
# "Google_" to "Google.".
-patch_file ${TO_IMAGE} RW_FWID_A 0 Google.
-patch_file ${TO_IMAGE} RW_FWID_B 0 Google.
-patch_file ${TO_IMAGE} RO_FRID 0 Google.
-patch_file ${FROM_IMAGE} RW_FWID_A 0 Google.
-patch_file ${FROM_IMAGE} RW_FWID_B 0 Google.
-patch_file ${FROM_IMAGE} RO_FRID 0 Google.
+patch_file "${TO_IMAGE}" RW_FWID_A 0 Google.
+patch_file "${TO_IMAGE}" RW_FWID_B 0 Google.
+patch_file "${TO_IMAGE}" RO_FRID 0 Google.
+patch_file "${FROM_IMAGE}" RW_FWID_A 0 Google.
+patch_file "${FROM_IMAGE}" RW_FWID_B 0 Google.
+patch_file "${FROM_IMAGE}" RO_FRID 0 Google.
unpack_image() {
local folder="${TMP}.$1"
local image="$2"
mkdir -p "${folder}"
- (cd "${folder}" && ${FUTILITY} dump_fmap -x "../${image}")
- ${FUTILITY} gbb -g --rootkey="${folder}/rootkey" "${image}"
+ (cd "${folder}" && "${FUTILITY}" dump_fmap -x "../${image}")
+ "${FUTILITY}" gbb -g --rootkey="${folder}/rootkey" "${image}"
}
# Unpack images so we can prepare expected results by individual sections.
@@ -114,19 +119,19 @@
cp -f "${FROM_IMAGE}" "${TMP}.expected.legacy"
"${FUTILITY}" gbb -s --hwid="${FROM_HWID}" "${TMP}.expected.full"
"${FUTILITY}" load_fmap "${TMP}.expected.full" \
- RW_VPD:${TMP}.from/RW_VPD \
- RO_VPD:${TMP}.from/RO_VPD
+ "RW_VPD:${TMP}.from/RW_VPD" \
+ "RO_VPD:${TMP}.from/RO_VPD"
"${FUTILITY}" load_fmap "${TMP}.expected.rw" \
- RW_SECTION_A:${TMP}.to/RW_SECTION_A \
- RW_SECTION_B:${TMP}.to/RW_SECTION_B \
- RW_SHARED:${TMP}.to/RW_SHARED \
- RW_LEGACY:${TMP}.to/RW_LEGACY
+ "RW_SECTION_A:${TMP}.to/RW_SECTION_A" \
+ "RW_SECTION_B:${TMP}.to/RW_SECTION_B" \
+ "RW_SHARED:${TMP}.to/RW_SHARED" \
+ "RW_LEGACY:${TMP}.to/RW_LEGACY"
"${FUTILITY}" load_fmap "${TMP}.expected.a" \
- RW_SECTION_A:${TMP}.to/RW_SECTION_A
+ "RW_SECTION_A:${TMP}.to/RW_SECTION_A"
"${FUTILITY}" load_fmap "${TMP}.expected.b" \
- RW_SECTION_B:${TMP}.to/RW_SECTION_B
+ "RW_SECTION_B:${TMP}.to/RW_SECTION_B"
"${FUTILITY}" load_fmap "${TMP}.expected.legacy" \
- RW_LEGACY:${TMP}.to/RW_LEGACY
+ "RW_LEGACY:${TMP}.to/RW_LEGACY"
cp -f "${TMP}.expected.full" "${TMP}.expected.full.gbb12"
patch_file "${TMP}.expected.full.gbb12" GBB 6 "\x02"
"${FUTILITY}" gbb -s --hwid="${FROM_HWID}" "${TMP}.expected.full.gbb12"
@@ -149,7 +154,7 @@
# FMAP_AREA_PRESERVE (\010=0x08).
TO_IMAGE_WIPE_RW_VPD="${TO_IMAGE}.wipe_rw_vpd"
cp -f "${TO_IMAGE}" "${TO_IMAGE_WIPE_RW_VPD}"
-patch_file ${TO_IMAGE_WIPE_RW_VPD} FMAP 0x3fc "$(printf '\010')"
+patch_file "${TO_IMAGE_WIPE_RW_VPD}" FMAP 0x3fc "$(printf '\010')"
cp -f "${TMP}.expected.full" "${TMP}.expected.full.empty_rw_vpd"
"${FUTILITY}" load_fmap "${TMP}.expected.full.empty_rw_vpd" \
RW_VPD:"${TMP}.to/RW_VPD"
@@ -371,20 +376,20 @@
--quirks preserve_me \
-i "${TO_IMAGE}" --wp=0 --sys_props 0,0x10001,1
-# Test archive and manifest.
+# Test archive and manifest. CL_TAG is for custom_label_tag.
A="${TMP}.archive"
mkdir -p "${A}/bin"
-echo 'echo "${WL_TAG}"' >"${A}/bin/vpd"
+echo "echo \"\${CL_TAG}\"" >"${A}/bin/vpd"
chmod +x "${A}/bin/vpd"
cp -f "${LINK_BIOS}" "${A}/bios.bin"
echo "TEST: Manifest (--manifest, bios.bin)"
-${FUTILITY} update -a "${A}" --manifest >"${TMP}.json.out"
+"${FUTILITY}" update -a "${A}" --manifest >"${TMP}.json.out"
cmp "${TMP}.json.out" "${SCRIPT_DIR}/futility/link_bios.manifest.json"
mv -f "${A}/bios.bin" "${A}/image.bin"
echo "TEST: Manifest (--manifest, image.bin)"
-${FUTILITY} update -a "${A}" --manifest >"${TMP}.json.out"
+"${FUTILITY}" update -a "${A}" --manifest >"${TMP}.json.out"
cmp "${TMP}.json.out" "${SCRIPT_DIR}/futility/link_image.manifest.json"
@@ -395,44 +400,46 @@
echo "TEST: Output (--mode=output)"
mkdir -p "${TMP}.output"
-${FUTILITY} update -i "${LINK_BIOS}" --mode=output --output_dir="${TMP}.output"
+"${FUTILITY}" update -i "${LINK_BIOS}" --mode=output \
+ --output_dir="${TMP}.output"
cmp "${LINK_BIOS}" "${TMP}.output/image.bin"
mkdir -p "${A}/keyset"
cp -f "${LINK_BIOS}" "${A}/image.bin"
-cp -f "${TMP}.to/rootkey" "${A}/keyset/rootkey.WL"
-cp -f "${TMP}.to/VBLOCK_A" "${A}/keyset/vblock_A.WL"
-cp -f "${TMP}.to/VBLOCK_B" "${A}/keyset/vblock_B.WL"
-${FUTILITY} gbb -s --rootkey="${TMP}.from/rootkey" "${A}/image.bin"
-${FUTILITY} load_fmap "${A}/image.bin" VBLOCK_A:"${TMP}.from/VBLOCK_A"
-${FUTILITY} load_fmap "${A}/image.bin" VBLOCK_B:"${TMP}.from/VBLOCK_B"
+cp -f "${TMP}.to/rootkey" "${A}/keyset/rootkey.CL"
+cp -f "${TMP}.to/VBLOCK_A" "${A}/keyset/vblock_A.CL"
+cp -f "${TMP}.to/VBLOCK_B" "${A}/keyset/vblock_B.CL"
+"${FUTILITY}" gbb -s --rootkey="${TMP}.from/rootkey" "${A}/image.bin"
+"${FUTILITY}" load_fmap "${A}/image.bin" VBLOCK_A:"${TMP}.from/VBLOCK_A"
+"${FUTILITY}" load_fmap "${A}/image.bin" VBLOCK_B:"${TMP}.from/VBLOCK_B"
-test_update "Full update (--archive, whitelabel, no VPD)" \
- "${A}/image.bin" "!Need VPD set for white" \
+test_update "Full update (--archive, custom label, no VPD)" \
+ "${A}/image.bin" "!Need VPD set for custom" \
-a "${A}" --wp=0 --sys_props 0,0x10001,1,3
-test_update "Full update (--archive, whitelabel, no VPD - factory mode)" \
+test_update "Full update (--archive, custom label, no VPD - factory mode)" \
"${LINK_BIOS}" "${A}/image.bin" \
-a "${A}" --wp=0 --sys_props 0,0x10001,1,3 --mode=factory
-test_update "Full update (--archive, whitelabel, no VPD - quirk mode)" \
+test_update "Full update (--archive, custom label, no VPD - quirk mode)" \
"${LINK_BIOS}" "${A}/image.bin" \
- -a "${A}" --wp=0 --sys_props 0,0x10001,1,3 --quirks=allow_empty_wltag
+ -a "${A}" --wp=0 --sys_props 0,0x10001,1,3 \
+ --quirks=allow_empty_custom_label_tag
-test_update "Full update (--archive, WL, single package)" \
+test_update "Full update (--archive, custom label, single package)" \
"${A}/image.bin" "${LINK_BIOS}" \
- -a "${A}" --wp=0 --sys_props 0,0x10001,1,3 --signature_id=WL
+ -a "${A}" --wp=0 --sys_props 0,0x10001,1,3 --signature_id=CL
-WL_TAG="WL" PATH="${A}/bin:${PATH}" \
- test_update "Full update (--archive, WL, fake vpd)" \
+CL_TAG="CL" PATH="${A}/bin:${PATH}" \
+ test_update "Full update (--archive, custom label, fake vpd)" \
"${A}/image.bin" "${LINK_BIOS}" \
-a "${A}" --wp=0 --sys_props 0,0x10001,1,3
echo "TEST: Output (-a, --mode=output)"
mkdir -p "${TMP}.outa"
cp -f "${A}/image.bin" "${TMP}.emu"
-WL_TAG="WL" PATH="${A}/bin:${PATH}" \
- ${FUTILITY} update -a "${A}" --mode=output --emu="${TMP}.emu" \
+CL_TAG="CL" PATH="${A}/bin:${PATH}" \
+ "${FUTILITY}" update -a "${A}" --mode=output --emu="${TMP}.emu" \
--output_dir="${TMP}.outa"
cmp "${LINK_BIOS}" "${TMP}.outa/image.bin"
@@ -442,13 +449,13 @@
mv "${A}/image.bin" "${A}/images/bios_coral.bin"
cp -f "${PEPPY_BIOS}" "${A}/images/bios_peppy.bin"
cp -f "${LINK_BIOS}" "${A}/images/bios_link.bin"
-cp -f "${TMP}.to/rootkey" "${A}/keyset/rootkey.whitetip-wl"
-cp -f "${TMP}.to/VBLOCK_A" "${A}/keyset/vblock_A.whitetip-wl"
-cp -f "${TMP}.to/VBLOCK_B" "${A}/keyset/vblock_B.whitetip-wl"
+cp -f "${TMP}.to/rootkey" "${A}/keyset/rootkey.customtip-cl"
+cp -f "${TMP}.to/VBLOCK_A" "${A}/keyset/vblock_A.customtip-cl"
+cp -f "${TMP}.to/VBLOCK_B" "${A}/keyset/vblock_B.customtip-cl"
cp -f "${PEPPY_BIOS}" "${FROM_IMAGE}.ap"
cp -f "${LINK_BIOS}" "${FROM_IMAGE}.al"
-patch_file ${FROM_IMAGE}.ap FW_MAIN_A 0 "corrupted"
-patch_file ${FROM_IMAGE}.al FW_MAIN_A 0 "corrupted"
+patch_file "${FROM_IMAGE}.ap" FW_MAIN_A 0 "corrupted"
+patch_file "${FROM_IMAGE}.al" FW_MAIN_A 0 "corrupted"
test_update "Full update (--archive, model=link)" \
"${FROM_IMAGE}.al" "${LINK_BIOS}" \
-a "${A}" --wp=0 --sys_props 0,0x10001,1,3 --model=link
@@ -458,28 +465,28 @@
test_update "Full update (--archive, model=unknown)" \
"${FROM_IMAGE}.ap" "!Unsupported model: 'unknown'" \
-a "${A}" --wp=0 --sys_props 0,0x10001,1,3 --model=unknown
-test_update "Full update (--archive, model=whitetip, signature_id=WL)" \
+test_update "Full update (--archive, model=customtip, signature_id=CL)" \
"${FROM_IMAGE}.al" "${LINK_BIOS}" \
- -a "${A}" --wp=0 --sys_props 0,0x10001,1,3 --model=whitetip \
- --signature_id=whitetip-wl
+ -a "${A}" --wp=0 --sys_props 0,0x10001,1,3 --model=customtip \
+ --signature_id=customtip-cl
-WL_TAG="wl" PATH="${A}/bin:${PATH}" \
- test_update "Full update (-a, model=WL, fake VPD)" \
+CL_TAG="cl" PATH="${A}/bin:${PATH}" \
+ test_update "Full update (-a, model=customtip, fake VPD)" \
"${FROM_IMAGE}.al" "${LINK_BIOS}" \
- -a "${A}" --wp=0 --sys_props 0,0x10001,1,3 --model=whitetip
+ -a "${A}" --wp=0 --sys_props 0,0x10001,1,3 --model=customtip
-# WL-Unibuild without default keys
-test_update "Full update (--a, model=WL, no VPD, no default keys)" \
- "${FROM_IMAGE}.al" "!Need VPD set for white" \
- -a "${A}" --wp=0 --sys_props 0,0x10001,1,3 --model=whitetip
+# Custom label + Unibuild without default keys
+test_update "Full update (--a, model=customtip, no VPD, no default keys)" \
+ "${FROM_IMAGE}.al" "!Need VPD set for custom" \
+ -a "${A}" --wp=0 --sys_props 0,0x10001,1,3 --model=customtip
-# WL-Unibuild with default keys as model name
-cp -f "${TMP}.to/rootkey" "${A}/keyset/rootkey.whitetip"
-cp -f "${TMP}.to/VBLOCK_A" "${A}/keyset/vblock_A.whitetip"
-cp -f "${TMP}.to/VBLOCK_B" "${A}/keyset/vblock_B.whitetip"
-test_update "Full update (-a, model=WL, no VPD, default keys)" \
+# Custom label + Unibuild with default keys as model name
+cp -f "${TMP}.to/rootkey" "${A}/keyset/rootkey.customtip"
+cp -f "${TMP}.to/VBLOCK_A" "${A}/keyset/vblock_A.customtip"
+cp -f "${TMP}.to/VBLOCK_B" "${A}/keyset/vblock_B.customtip"
+test_update "Full update (-a, model=customtip, no VPD, default keys)" \
"${FROM_IMAGE}.al" "${LINK_BIOS}" \
- -a "${A}" --wp=0 --sys_props 0,0x10001,1,3 --model=whitetip
+ -a "${A}" --wp=0 --sys_props 0,0x10001,1,3 --model=customtip
# Test special programmer
if type flashrom >/dev/null 2>&1; then
@@ -507,13 +514,16 @@
echo "min_platform_version=3" >"${TMP}.quirk"
cp -f "${TO_IMAGE}" "${TO_IMAGE}.quirk"
- ${FUTILITY} dump_fmap -x "${TO_IMAGE}" "BOOT_STUB:${TMP}.cbfs"
+ "${FUTILITY}" dump_fmap -x "${TO_IMAGE}" "BOOT_STUB:${TMP}.cbfs"
# Create a fake CBFS using FW_MAIN_A size.
truncate -s $((0x000dffc0)) "${TMP}.cbfs"
- ${FUTILITY} load_fmap "${TO_IMAGE}.quirk" "FW_MAIN_A:${TMP}.cbfs"
+ "${FUTILITY}" load_fmap "${TO_IMAGE}.quirk" "FW_MAIN_A:${TMP}.cbfs"
cbfstool "${TO_IMAGE}.quirk" add -r FW_MAIN_A -n updater_quirks \
-f "${TMP}.quirk" -t raw
test_update "Full update (failure by CBFS quirks)" \
"${FROM_IMAGE}" "!Need platform version >= 3 (current is 2)" \
-i "${TO_IMAGE}.quirk" --wp=0 --sys_props 0,0x10001,1,2
fi
+
+rm -rf "${TMP}"*
+exit 0
diff --git a/tests/gen_fuzz_test_cases.sh b/tests/gen_fuzz_test_cases.sh
index 2b4255d..3e4ca99 100755
--- a/tests/gen_fuzz_test_cases.sh
+++ b/tests/gen_fuzz_test_cases.sh
@@ -12,7 +12,7 @@
. "$(dirname "$0")/common.sh"
# Use a different directory for fuzzing test cases.
-TESTKEY_DIR=${TESTKEY_DIR:-$(realpath ${SCRIPT_DIR}/../tests/testkeys)}
+TESTKEY_DIR=${TESTKEY_DIR:-$(realpath "${SCRIPT_DIR}"/../tests/testkeys)}
TESTCASE_DIR=${BUILD_DIR}/fuzz_testcases
TEST_IMAGE_FILE=${TESTCASE_DIR}/testimage
TEST_IMAGE_SIZE=500000
@@ -26,42 +26,43 @@
echo "Generating keyblocks..."
# Firmware keyblock - RSA8192/SHA512 root key, RSA4096/SHA512 firmware
# signing key.
- ${FUTILITY} vbutil_keyblock \
- --pack ${TESTCASE_DIR}/firmware.keyblock \
- --datapubkey ${TESTKEY_DIR}/key_rsa4096.sha512.vbpubk \
- --signprivate ${TESTKEY_DIR}/key_rsa8192.sha1.vbprivk
+ "${FUTILITY}" vbutil_keyblock \
+ --pack "${TESTCASE_DIR}/firmware.keyblock" \
+ --datapubkey "${TESTKEY_DIR}/key_rsa4096.sha512.vbpubk" \
+ --signprivate "${TESTKEY_DIR}/key_rsa8192.sha1.vbprivk"
# Kernel keyblock - RSA4096/SHA512 kernel signing subkey, RSA4096/SHA512
# kernel signing key.
- ${FUTILITY} vbutil_keyblock \
- --pack ${TESTCASE_DIR}/kernel.keyblock \
- --datapubkey ${TESTKEY_DIR}/key_rsa4096.sha512.vbpubk \
- --signprivate ${TESTKEY_DIR}/key_rsa4096.sha1.vbprivk \
+ "${FUTILITY}" vbutil_keyblock \
+ --pack "${TESTCASE_DIR}/kernel.keyblock" \
+ --datapubkey "${TESTKEY_DIR}/key_rsa4096.sha512.vbpubk" \
+ --signprivate "${TESTKEY_DIR}/key_rsa4096.sha1.vbprivk" \
--flags 15
echo "Generating signed firmware test image..."
- ${FUTILITY} vbutil_firmware \
- --vblock ${TESTCASE_DIR}/firmware.vblock \
- --keyblock ${TESTCASE_DIR}/firmware.keyblock\
- --signprivate ${TESTKEY_DIR}/key_rsa4096.sha256.vbprivk \
+ "${FUTILITY}" vbutil_firmware \
+ --vblock "${TESTCASE_DIR}/firmware.vblock" \
+ --keyblock "${TESTCASE_DIR}/firmware.keyblock" \
+ --signprivate "${TESTKEY_DIR}/key_rsa4096.sha256.vbprivk" \
--version 1 \
- --fv $1 \
- --kernelkey ${TESTKEY_DIR}/key_rsa4096.sha512.vbpubk
+ --fv "$1" \
+ --kernelkey "${TESTKEY_DIR}/key_rsa4096.sha512.vbpubk"
# TODO(gauravsh): ALso test with (optional) flags.
- cp ${TESTKEY_DIR}/key_rsa8192.sha512.vbpubk ${TESTCASE_DIR}/root_key.vbpubk
+ cp "${TESTKEY_DIR}/key_rsa8192.sha512.vbpubk" \
+ "${TESTCASE_DIR}/root_key.vbpubk"
echo "Generating signed kernel test image..."
- ${FUTILITY} vbutil_kernel \
- --pack ${TESTCASE_DIR}/kernel.vblock.image \
- --keyblock ${TESTCASE_DIR}/kernel.keyblock \
- --signprivate ${TESTKEY_DIR}/key_rsa4096.sha256.vbprivk \
+ "${FUTILITY}" vbutil_kernel \
+ --pack "${TESTCASE_DIR}/kernel.vblock.image" \
+ --keyblock "${TESTCASE_DIR}/kernel.keyblock" \
+ --signprivate "${TESTKEY_DIR}/key_rsa4096.sha256.vbprivk" \
--version 1 \
- --vmlinuz ${TEST_IMAGE_FILE} \
- --bootloader ${TEST_BOOTLOADER_FILE} \
- --config ${TEST_CONFIG_FILE}
+ --vmlinuz "${TEST_IMAGE_FILE}" \
+ --bootloader "${TEST_BOOTLOADER_FILE}" \
+ --config "${TEST_CONFIG_FILE}"
# TODO(gauravsh): Also test with (optional) padding.
- cp ${TESTKEY_DIR}/key_rsa4096.sha512.vbpubk \
- ${TESTCASE_DIR}/firmware_key.vbpubk
+ cp "${TESTKEY_DIR}/key_rsa4096.sha512.vbpubk" \
+ "${TESTCASE_DIR}/firmware_key.vbpubk"
}
function pre_work {
@@ -69,18 +70,17 @@
# NOTE: The kernel and config file can't really be random, but the bootloader
# can. That's probably close enough.
echo "Generating test image file..."
- dd if=/dev/urandom of=${TEST_IMAGE_FILE} bs=${TEST_IMAGE_SIZE} count=1
+ dd if=/dev/urandom of="${TEST_IMAGE_FILE}" bs="${TEST_IMAGE_SIZE}" count=1
echo "Generating test bootloader file..."
# TODO(gauravsh): Use a valid bootloader here?
- dd if=/dev/urandom of=${TEST_BOOTLOADER_FILE} bs=${TEST_BOOTLOADER_SIZE} \
+ dd if=/dev/urandom of="${TEST_BOOTLOADER_FILE}" bs="${TEST_BOOTLOADER_SIZE}" \
count=1
echo "Generating test config file..."
# TODO(gauravsh): Use a valid config file here?
- dd if=/dev/urandom of=${TEST_CONFIG_FILE} bs=${TEST_CONFIG_SIZE} count=1
+ dd if=/dev/urandom of="${TEST_CONFIG_FILE}" bs="${TEST_CONFIG_SIZE}" count=1
}
-mkdir -p ${TESTCASE_DIR}
+mkdir -p "${TESTCASE_DIR}"
pre_work
check_test_keys
-generate_fuzzing_images ${TEST_IMAGE_FILE}
-
+generate_fuzzing_images "${TEST_IMAGE_FILE}"
diff --git a/tests/gen_test_cases.sh b/tests/gen_test_cases.sh
index 540fc2a..80ed90c 100755
--- a/tests/gen_test_cases.sh
+++ b/tests/gen_test_cases.sh
@@ -17,17 +17,17 @@
function generate_test_signatures {
echo "Generating test signatures..."
algorithmcounter=0
- for keylen in ${key_lengths[@]}
+ for keylen in "${key_lengths[@]}"
do
- for hashalgo in ${hash_algos[@]}
+ for hashalgo in "${hash_algos[@]}"
do
- openssl dgst -${hashalgo} -binary ${TEST_FILE} > \
- ${TEST_FILE}.${hashalgo}.digest
- ${BIN_DIR}/signature_digest_utility $algorithmcounter \
- ${TEST_FILE} | openssl rsautl \
- -sign -pkcs -inkey ${TESTKEY_DIR}/key_rsa${keylen}.pem \
- > ${TEST_FILE}.rsa${keylen}_${hashalgo}.sig
- let algorithmcounter=algorithmcounter+1
+ openssl dgst "-${hashalgo}" -binary "${TEST_FILE}" > \
+ "${TEST_FILE}.${hashalgo}.digest"
+ "${BIN_DIR}/signature_digest_utility" "$algorithmcounter" \
+ "${TEST_FILE}" | openssl rsautl \
+ -sign -pkcs -inkey "${TESTKEY_DIR}/key_rsa${keylen}.pem" \
+ > "${TEST_FILE}.rsa${keylen}_${hashalgo}.sig"
+ algorithmcounter=$((algorithmcounter + 1))
done
done
}
@@ -39,10 +39,10 @@
echo "(skipping, file already exists)"
return
fi
- dd if=/dev/urandom of=${TEST_FILE} bs=${TEST_FILE_SIZE} count=1
+ dd if=/dev/urandom of="${TEST_FILE}" bs="${TEST_FILE_SIZE}" count=1
}
-mkdir -p ${TESTCASE_DIR}
+mkdir -p "${TESTCASE_DIR}"
check_test_keys
generate_test_file
generate_test_signatures
diff --git a/tests/gen_test_keys.sh b/tests/gen_test_keys.sh
index 04315ac..37722fb 100755
--- a/tests/gen_test_keys.sh
+++ b/tests/gen_test_keys.sh
@@ -17,11 +17,11 @@
function generate_keys {
key_index=0
key_name_base="${TESTKEY_DIR}/key_rsa"
- for i in ${key_lengths[@]}
+ for i in "${key_lengths[@]}"
do
key_base="${key_name_base}${i}"
if [ -f "${key_base}.keyb" ]; then
- key_index=$((${key_index} + 1))
+ key_index=$((key_index + 1))
continue
fi
@@ -33,34 +33,33 @@
bits="${i%%_exp${exp}}"
fi
- openssl genrsa -${exp} -out ${key_base}.pem ${bits}
+ openssl genrsa "-${exp}" -out "${key_base}.pem" "${bits}"
# Generate self-signed certificate from key.
- openssl req -batch -new -x509 -key ${key_base}.pem \
- -out ${key_base}.crt
+ openssl req -batch -new -x509 -key "${key_base}.pem" \
+ -out "${key_base}.crt"
# Generate pre-processed key for use by RSA signature verification code.
- ${BIN_DIR}/dumpRSAPublicKey -cert ${key_base}.crt \
- > ${key_base}.keyb
+ "${BIN_DIR}/dumpRSAPublicKey" -cert "${key_base}.crt" > "${key_base}.keyb"
alg_index=0
- for sha_type in ${sha_types[@]}
+ for sha_type in "${sha_types[@]}"
do
- alg=$((${key_index} * 3 + ${alg_index}))
+ alg=$((key_index * 3 + alg_index))
# wrap the public key
- ${FUTILITY} vbutil_key \
+ "${FUTILITY}" vbutil_key \
--pack "${key_base}.sha${sha_type}.vbpubk" \
--key "${key_base}.keyb" \
--version 1 \
--algorithm ${alg}
# wrap the private key
- ${FUTILITY} vbutil_key \
+ "${FUTILITY}" vbutil_key \
--pack "${key_base}.sha${sha_type}.vbprivk" \
--key "${key_base}.pem" \
--algorithm ${alg}
- alg_index=$((${alg_index} + 1))
+ alg_index=$((alg_index} + 1))
done
- key_index=$((${key_index} + 1))
+ key_index=$((key_index + 1))
done
}
diff --git a/tests/gen_test_vbpubks.sh b/tests/gen_test_vbpubks.sh
index 8ea2759..a318d3d 100755
--- a/tests/gen_test_vbpubks.sh
+++ b/tests/gen_test_vbpubks.sh
@@ -11,16 +11,16 @@
function generate_vpubks {
algorithmcounter=0
- for keylen in ${key_lengths[@]}
+ for keylen in "${key_lengths[@]}"
do
- for hashalgo in ${hash_algos[@]}
+ for hashalgo in "${hash_algos[@]}"
do
- ${FUTILITY} vbutil_key --pack \
- --in ${TESTKEY_DIR}/key_rsa${keylen}.keyb \
- --out ${TESTKEY_DIR}/key_rsa${keylen}.${hashalgo}.vbpubk \
+ "${FUTILITY}" vbutil_key --pack \
+ --in "${TESTKEY_DIR}/key_rsa${keylen}.keyb" \
+ --out "${TESTKEY_DIR}/key_rsa${keylen}.${hashalgo}.vbpubk" \
--version 1 \
- --algorithm ${algorithmcounter}
- let algorithmcounter=algorithmcounter+1
+ --algorithm "${algorithmcounter}"
+ algorithmcounter=$((algorithmcounter + 1))
done
done
}
diff --git a/tests/gpt_misc_tests.c b/tests/gpt_misc_tests.c
index e0a8d56..e7ffccf 100644
--- a/tests/gpt_misc_tests.c
+++ b/tests/gpt_misc_tests.c
@@ -8,8 +8,8 @@
#include "2api.h"
#include "cgptlib.h"
#include "cgptlib_internal.h"
+#include "common/tests.h"
#include "gpt.h"
-#include "test_common.h"
#define LOGCALL(fmt, args...) sprintf(call_log + strlen(call_log), fmt, ##args)
#define TEST_CALLS(expect_log) TEST_STR_EQ(call_log, expect_log, " calls")
@@ -29,7 +29,7 @@
static int disk_read_to_fail;
static int disk_write_to_fail;
-static VbExDiskHandle_t handle;
+static vb2ex_disk_handle_t handle;
static uint8_t mock_disk[MOCK_SECTOR_SIZE * MOCK_SECTOR_COUNT];
static GptHeader *mock_gpt_primary =
(GptHeader*)&mock_disk[MOCK_SECTOR_SIZE * 1];
@@ -91,7 +91,7 @@
/* Mocks */
-vb2_error_t VbExDiskRead(VbExDiskHandle_t h, uint64_t lba_start,
+vb2_error_t VbExDiskRead(vb2ex_disk_handle_t h, uint64_t lba_start,
uint64_t lba_count, void *buffer)
{
LOGCALL("VbExDiskRead(h, %d, %d)\n", (int)lba_start, (int)lba_count);
@@ -105,7 +105,7 @@
return VB2_SUCCESS;
}
-vb2_error_t VbExDiskWrite(VbExDiskHandle_t h, uint64_t lba_start,
+vb2_error_t VbExDiskWrite(vb2ex_disk_handle_t h, uint64_t lba_start,
uint64_t lba_count, const void *buffer)
{
LOGCALL("VbExDiskWrite(h, %d, %d)\n", (int)lba_start, (int)lba_count);
@@ -207,7 +207,7 @@
* Invalidate primary GPT header and check that it is
* repaired by GptRepair().
*
- * This would normally be called by LoadKernel()->GptInit()
+ * This would normally be called by vb2api_load_kernel()->GptInit()
* but this callback is mocked in these tests.
*/
ResetMocks();
@@ -232,7 +232,7 @@
* Invalidate secondary GPT header and check that it can be
* repaired by GptRepair().
*
- * This would normally be called by LoadKernel()->GptInit()
+ * This would normally be called by vb2api_load_kernel()->GptInit()
* but this callback is mocked in these tests.
*/
ResetMocks();
diff --git a/tests/hmac_test.c b/tests/hmac_test.c
index ed77d7b..708711f 100644
--- a/tests/hmac_test.c
+++ b/tests/hmac_test.c
@@ -10,7 +10,7 @@
#include "2sha.h"
#include "2hmac.h"
-#include "test_common.h"
+#include "common/tests.h"
const char short_key[] = "key";
const char message[] = "The quick brown fox jumps over the lazy dog";
diff --git a/tests/load_kernel_tests.sh b/tests/load_kernel_tests.sh
index 45eedf4..cd1bd63 100755
--- a/tests/load_kernel_tests.sh
+++ b/tests/load_kernel_tests.sh
@@ -27,21 +27,21 @@
dd if=/dev/urandom bs=32768 count=1 of="dummy_kernel.bin"
# Pack kernel data key using original vboot utilities.
-${FUTILITY} vbutil_key --pack datakey.test \
- --key ${TESTKEY_DIR}/key_rsa2048.keyb --algorithm 4
+"${FUTILITY}" vbutil_key --pack datakey.test \
+ --key "${TESTKEY_DIR}/key_rsa2048.keyb" --algorithm 4
# Keyblock with kernel data key is signed by kernel subkey
# Flags=21 means dev=0 rec=0 minios=0
-${FUTILITY} vbutil_keyblock --pack keyblock.test \
+"${FUTILITY}" vbutil_keyblock --pack keyblock.test \
--datapubkey datakey.test \
--flags 21 \
- --signprivate ${SCRIPT_DIR}/devkeys/kernel_subkey.vbprivk
+ --signprivate "${SCRIPT_DIR}/devkeys/kernel_subkey.vbprivk"
# Kernel preamble is signed with the kernel data key
-${FUTILITY} vbutil_kernel \
+"${FUTILITY}" vbutil_kernel \
--pack "kernel.test" \
--keyblock "keyblock.test" \
- --signprivate ${TESTKEY_DIR}/key_rsa2048.sha256.vbprivk \
+ --signprivate "${TESTKEY_DIR}/key_rsa2048.sha256.vbprivk" \
--version 1 \
--arch arm \
--vmlinuz "dummy_kernel.bin" \
@@ -51,9 +51,9 @@
echo 'Verifying test kernel'
# Verify the kernel
-${FUTILITY} vbutil_kernel \
+"${FUTILITY}" vbutil_kernel \
--verify "kernel.test" \
- --signpubkey ${SCRIPT_DIR}/devkeys/kernel_subkey.vbpubk
+ --signpubkey "${SCRIPT_DIR}/devkeys/kernel_subkey.vbpubk"
happy 'Kernel verification succeeded'
@@ -69,7 +69,7 @@
# And verify it using futility
echo 'Verifying test disk image'
-${BUILD_RUN}/tests/verify_kernel disk.test \
- ${SCRIPT_DIR}/devkeys/kernel_subkey.vbpubk
+"${BUILD_RUN}/tests/verify_kernel" disk.test \
+ "${SCRIPT_DIR}/devkeys/kernel_subkey.vbpubk"
happy 'Image verification succeeded'
diff --git a/tests/run_cgpt_tests.sh b/tests/run_cgpt_tests.sh
index 3f18624..7f59205 100755
--- a/tests/run_cgpt_tests.sh
+++ b/tests/run_cgpt_tests.sh
@@ -10,27 +10,26 @@
. "$(dirname "$0")/common.sh"
CGPT=$(readlink -f "$1")
-[ -x "$CGPT" ] || error "Can't execute $CGPT"
+[ -x ""${CGPT}"" ] || error "Can't execute $CGPT"
-MTD="${@:2}"
+MTD=("${@:2}")
# Run tests in a dedicated directory for easy cleanup or debugging.
DIR="${TEST_DIR}/cgpt_test_dir"
[ -d "$DIR" ] || mkdir -p "$DIR"
-warning "testing $CGPT in $DIR"
+warning "testing "${CGPT}" in $DIR"
cd "$DIR"
assert_fail() {
set +e
- "$@" 2>/dev/null
- if [ $? == 0 ]; then
+ if "$@" 2>/dev/null; then
error "$*" " should have failed but did not"
fi
set -e
}
# Test failure on non existing file.
-assert_fail ${CGPT} show $MTD blah_404_haha
+assert_fail "${CGPT}" show "${MTD[@]}" blah_404_haha
echo "Create an empty file to use as the device..."
NUM_SECTORS=1000
@@ -76,264 +75,271 @@
RANDOM_DRIVE_GUID='12345678-0000-1111-2222-123456789ABC'
-$CGPT create $MTD ${DEV}
+"${CGPT}" create "${MTD[@]}" ${DEV}
run_basic_tests() {
echo "Create a bunch of partitions, using the real GUID types..."
- $CGPT add $MTD -b ${DATA_START} -s ${DATA_SIZE} -t ${DATA_GUID} \
+ "${CGPT}" add "${MTD[@]}" -b ${DATA_START} -s ${DATA_SIZE} -t ${DATA_GUID} \
-l "${DATA_LABEL}" ${DEV}
- $CGPT add $MTD -b ${KERN_START} -s ${KERN_SIZE} -t ${KERN_GUID} \
+ "${CGPT}" add "${MTD[@]}" -b ${KERN_START} -s ${KERN_SIZE} -t ${KERN_GUID} \
-l "${KERN_LABEL}" ${DEV}
- $CGPT add $MTD -b ${ROOTFS_START} -s ${ROOTFS_SIZE} -t ${ROOTFS_GUID} \
- -l "${ROOTFS_LABEL}" ${DEV}
- $CGPT add $MTD -b ${ESP_START} -s ${ESP_SIZE} -t ${ESP_GUID} \
+ "${CGPT}" add "${MTD[@]}" -b ${ROOTFS_START} -s ${ROOTFS_SIZE} \
+ -t ${ROOTFS_GUID} -l "${ROOTFS_LABEL}" ${DEV}
+ "${CGPT}" add "${MTD[@]}" -b ${ESP_START} -s ${ESP_SIZE} -t ${ESP_GUID} \
-l "${ESP_LABEL}" ${DEV}
- $CGPT add $MTD -b ${FUTURE_START} -s ${FUTURE_SIZE} -t ${FUTURE_GUID} \
- -l "${FUTURE_LABEL}" ${DEV}
- $CGPT add $MTD -b ${RANDOM_START} -s ${RANDOM_SIZE} -t ${RANDOM_GUID} \
- -l "${RANDOM_LABEL}" ${DEV}
+ "${CGPT}" add "${MTD[@]}" -b ${FUTURE_START} -s ${FUTURE_SIZE} \
+ -t ${FUTURE_GUID} -l "${FUTURE_LABEL}" ${DEV}
+ "${CGPT}" add "${MTD[@]}" -b ${RANDOM_START} -s ${RANDOM_SIZE} \
+ -t ${RANDOM_GUID} -l "${RANDOM_LABEL}" ${DEV}
echo "Extract the start and size of given partitions..."
- X=$($CGPT show $MTD -b -i $DATA_NUM ${DEV})
- Y=$($CGPT show $MTD -s -i $DATA_NUM ${DEV})
+ X=$("${CGPT}" show "${MTD[@]}" -b -i $DATA_NUM ${DEV})
+ Y=$("${CGPT}" show "${MTD[@]}" -s -i $DATA_NUM ${DEV})
[ "$X $Y" = "$DATA_START $DATA_SIZE" ] || error
- X=$($CGPT show $MTD -b -i $KERN_NUM ${DEV})
- Y=$($CGPT show $MTD -s -i $KERN_NUM ${DEV})
+ X=$("${CGPT}" show "${MTD[@]}" -b -i $KERN_NUM ${DEV})
+ Y=$("${CGPT}" show "${MTD[@]}" -s -i $KERN_NUM ${DEV})
[ "$X $Y" = "$KERN_START $KERN_SIZE" ] || error
- X=$($CGPT show $MTD -b -i $ROOTFS_NUM ${DEV})
- Y=$($CGPT show $MTD -s -i $ROOTFS_NUM ${DEV})
+ X=$("${CGPT}" show "${MTD[@]}" -b -i $ROOTFS_NUM ${DEV})
+ Y=$("${CGPT}" show "${MTD[@]}" -s -i $ROOTFS_NUM ${DEV})
[ "$X $Y" = "$ROOTFS_START $ROOTFS_SIZE" ] || error
- X=$($CGPT show $MTD -b -i $ESP_NUM ${DEV})
- Y=$($CGPT show $MTD -s -i $ESP_NUM ${DEV})
+ X=$("${CGPT}" show "${MTD[@]}" -b -i $ESP_NUM ${DEV})
+ Y=$("${CGPT}" show "${MTD[@]}" -s -i $ESP_NUM ${DEV})
[ "$X $Y" = "$ESP_START $ESP_SIZE" ] || error
- X=$($CGPT show $MTD -b -i $FUTURE_NUM ${DEV})
- Y=$($CGPT show $MTD -s -i $FUTURE_NUM ${DEV})
+ X=$("${CGPT}" show "${MTD[@]}" -b -i $FUTURE_NUM ${DEV})
+ Y=$("${CGPT}" show "${MTD[@]}" -s -i $FUTURE_NUM ${DEV})
[ "$X $Y" = "$FUTURE_START $FUTURE_SIZE" ] || error
- X=$($CGPT show $MTD -b -i $RANDOM_NUM ${DEV})
- Y=$($CGPT show $MTD -s -i $RANDOM_NUM ${DEV})
+ X=$("${CGPT}" show "${MTD[@]}" -b -i $RANDOM_NUM ${DEV})
+ Y=$("${CGPT}" show "${MTD[@]}" -s -i $RANDOM_NUM ${DEV})
[ "$X $Y" = "$RANDOM_START $RANDOM_SIZE" ] || error
echo "Change the beginning..."
DATA_START=$((DATA_START + 10))
- $CGPT add $MTD -i 1 -b ${DATA_START} ${DEV} || error
- X=$($CGPT show $MTD -b -i 1 ${DEV})
+ "${CGPT}" add "${MTD[@]}" -i 1 -b ${DATA_START} ${DEV} || error
+ X=$("${CGPT}" show "${MTD[@]}" -b -i 1 ${DEV})
[ "$X" = "$DATA_START" ] || error
echo "Change the size..."
DATA_SIZE=$((DATA_SIZE + 10))
- $CGPT add $MTD -i 1 -s ${DATA_SIZE} ${DEV} || error
- X=$($CGPT show $MTD -s -i 1 ${DEV})
+ "${CGPT}" add "${MTD[@]}" -i 1 -s ${DATA_SIZE} ${DEV} || error
+ X=$("${CGPT}" show "${MTD[@]}" -s -i 1 ${DEV})
[ "$X" = "$DATA_SIZE" ] || error
echo "Change the type..."
- $CGPT add $MTD -i 1 -t reserved ${DEV} || error
- X=$($CGPT show $MTD -t -i 1 ${DEV} | tr 'A-Z' 'a-z')
+ "${CGPT}" add "${MTD[@]}" -i 1 -t reserved ${DEV} || error
+ X=$("${CGPT}" show "${MTD[@]}" -t -i 1 ${DEV} | tr '[:upper:]' '[:lower:]')
[ "$X" = "$FUTURE_GUID" ] || error
# arbitrary value
- $CGPT add $MTD -i 1 -t 610a563a-a55c-4ae0-ab07-86e5bb9db67f ${DEV} || error
- X=$($CGPT show $MTD -t -i 1 ${DEV})
+ "${CGPT}" add "${MTD[@]}" -i 1 -t 610a563a-a55c-4ae0-ab07-86e5bb9db67f \
+ ${DEV} || error
+ X=$("${CGPT}" show "${MTD[@]}" -t -i 1 ${DEV})
[ "$X" = "610A563A-A55C-4AE0-AB07-86E5BB9DB67F" ] || error
- $CGPT add $MTD -i 1 -t data ${DEV} || error
- X=$($CGPT show $MTD -t -i 1 ${DEV} | tr 'A-Z' 'a-z')
+ "${CGPT}" add "${MTD[@]}" -i 1 -t data ${DEV} || error
+ X=$("${CGPT}" show "${MTD[@]}" -t -i 1 ${DEV} | tr '[:upper:]' '[:lower:]')
[ "$X" = "$DATA_GUID" ] || error
- ORIG_ID=$($CGPT show $MTD -v ${DEV} | \
+ ORIG_ID=$("${CGPT}" show "${MTD[@]}" -v ${DEV} | \
grep -i "disk uuid" | head -1 | awk ' { print $3 } ' )
[ ! "$ORIG_ID" = "$RANDOM_DRIVE_GUID" ] || error
- $CGPT edit $MTD -u ${RANDOM_DRIVE_GUID} ${DEV} || error
- X=$($CGPT show $MTD -v ${DEV} | grep -i "disk uuid" | \
+ "${CGPT}" edit "${MTD[@]}" -u ${RANDOM_DRIVE_GUID} ${DEV} || error
+ X=$("${CGPT}" show "${MTD[@]}" -v ${DEV} | grep -i "disk uuid" | \
head -1 | awk ' { print $3 } ' )
[ "$X" = "${RANDOM_DRIVE_GUID}" ] || error
- $CGPT edit $MTD -u ${ORIG_ID} ${DEV} || error
- X=$($CGPT show $MTD -v ${DEV} | grep -i "disk uuid" | \
+ "${CGPT}" edit "${MTD[@]}" -u "${ORIG_ID}" ${DEV} || error
+ X=$("${CGPT}" show "${MTD[@]}" -v ${DEV} | grep -i "disk uuid" | \
head -1 | awk ' { print $3 } ' )
[ "$X" = "${ORIG_ID}" ] || error
}
run_basic_tests
-ORIG_ID=$($CGPT show $MTD -v ${DEV} | \
+ORIG_ID=$("${CGPT}" show "${MTD[@]}" -v ${DEV} | \
grep -i "disk uuid" | awk ' { print $3 } ' )
[ ! "$ORIG_ID" = "$RANDOM_DRIVE_GUID" ] || error
-$CGPT edit $MTD -u ${RANDOM_DRIVE_GUID} ${DEV} || error
-X=$($CGPT show $MTD -v ${DEV} | grep -i "disk uuid" | \
+"${CGPT}" edit "${MTD[@]}" -u ${RANDOM_DRIVE_GUID} ${DEV} || error
+X=$("${CGPT}" show "${MTD[@]}" -v ${DEV} | grep -i "disk uuid" | \
head -1 | awk ' { print $3 } ' )
[ "$X" = "${RANDOM_DRIVE_GUID}" ] || error
-$CGPT edit $MTD -u ${ORIG_ID} ${DEV} || error
-X=$($CGPT show $MTD -v ${DEV} | grep -i "disk uuid" | \
+"${CGPT}" edit "${MTD[@]}" -u "${ORIG_ID}" ${DEV} || error
+X=$("${CGPT}" show "${MTD[@]}" -v ${DEV} | grep -i "disk uuid" | \
awk ' { print $3 } ' )
[ "$X" = "${ORIG_ID}" ] || error
echo "Set the boot partition.."
-$CGPT boot $MTD -i ${KERN_NUM} ${DEV} >/dev/null
+"${CGPT}" boot "${MTD[@]}" -i ${KERN_NUM} ${DEV} >/dev/null
echo "Check the PMBR's idea of the boot partition..."
-X=$($CGPT boot $MTD ${DEV})
-Y=$($CGPT show $MTD -u -i $KERN_NUM $DEV)
+X=$("${CGPT}" boot "${MTD[@]}" ${DEV})
+Y=$("${CGPT}" show "${MTD[@]}" -u -i $KERN_NUM $DEV)
[ "$X" = "$Y" ] || error
# Input: sequence of priorities
# Output: ${DEV} has kernel partitions with the given priorities
make_pri() {
local idx=0
- $CGPT create $MTD ${DEV}
+ "${CGPT}" create "${MTD[@]}" ${DEV}
for pri in "$@"; do
idx=$((idx+1))
- $CGPT add $MTD -t kernel -l "kern$idx" -b $((100 + 2 * $idx)) -s 1 -P $pri ${DEV}
+ "${CGPT}" add "${MTD[@]}" -t kernel -l "kern$idx" -b $((100 + 2 * idx)) \
+ -s 1 -P $pri ${DEV}
done
}
# Output: returns string containing priorities of all kernels
get_pri() {
- echo $(
- for idx in $($CGPT find $MTD -t kernel ${DEV} | sed -e s@${DEV}@@); do
- $CGPT show $MTD -i $idx -P ${DEV}
+ local output=()
+ for idx in $("${CGPT}" find "${MTD[@]}" -t kernel ${DEV} | sed -e s@${DEV}@@);
+ do
+ output+=("$("${CGPT}" show "${MTD[@]}" -i "$idx" -P ${DEV})")
done
- )
+ echo "${output[@]}"
}
# Input: list of priorities
# Operation: expects ${DEV} to contain those kernel priorities
assert_pri() {
local expected="$*"
- local actual=$(get_pri)
+ local actual
+ actual=$(get_pri)
[ "$actual" = "$expected" ] || \
error 1 "expected priority \"$expected\", actual priority \"$actual\""
}
# no kernels at all. This should do nothing.
-$CGPT create $MTD ${DEV}
+"${CGPT}" create "${MTD[@]}" ${DEV}
run_prioritize_tests() {
echo "Test the cgpt prioritize command..."
- $CGPT add $MTD -t rootfs -b 100 -s 1 ${DEV}
- $CGPT prioritize $MTD ${DEV}
+ "${CGPT}" add "${MTD[@]}" -t rootfs -b 100 -s 1 ${DEV}
+ "${CGPT}" prioritize "${MTD[@]}" ${DEV}
assert_pri ""
# common install/upgrade sequence
make_pri 2 0 0
- $CGPT prioritize $MTD -i 1 ${DEV}
+ "${CGPT}" prioritize "${MTD[@]}" -i 1 ${DEV}
assert_pri 1 0 0
- $CGPT prioritize $MTD -i 2 ${DEV}
+ "${CGPT}" prioritize "${MTD[@]}" -i 2 ${DEV}
assert_pri 1 2 0
- $CGPT prioritize $MTD -i 1 ${DEV}
+ "${CGPT}" prioritize "${MTD[@]}" -i 1 ${DEV}
assert_pri 2 1 0
- $CGPT prioritize $MTD -i 2 ${DEV}
+ "${CGPT}" prioritize "${MTD[@]}" -i 2 ${DEV}
assert_pri 1 2 0
# lots of kernels, all same starting priority, should go to priority 1
make_pri 8 8 8 8 8 8 8 8 8 8 8 0 0 8
- $CGPT prioritize $MTD ${DEV}
+ "${CGPT}" prioritize "${MTD[@]}" ${DEV}
assert_pri 1 1 1 1 1 1 1 1 1 1 1 0 0 1
# now raise them all up again
- $CGPT prioritize $MTD -P 4 ${DEV}
+ "${CGPT}" prioritize "${MTD[@]}" -P 4 ${DEV}
assert_pri 4 4 4 4 4 4 4 4 4 4 4 0 0 4
# set one of them higher, should leave the rest alone
- $CGPT prioritize $MTD -P 5 -i 3 ${DEV}
+ "${CGPT}" prioritize "${MTD[@]}" -P 5 -i 3 ${DEV}
assert_pri 4 4 5 4 4 4 4 4 4 4 4 0 0 4
# set one of them lower, should bring the rest down
- $CGPT prioritize $MTD -P 3 -i 4 ${DEV}
+ "${CGPT}" prioritize "${MTD[@]}" -P 3 -i 4 ${DEV}
assert_pri 1 1 2 3 1 1 1 1 1 1 1 0 0 1
# raise a group by including the friends of one partition
- $CGPT prioritize $MTD -P 6 -i 1 -f ${DEV}
+ "${CGPT}" prioritize "${MTD[@]}" -P 6 -i 1 -f ${DEV}
assert_pri 6 6 4 5 6 6 6 6 6 6 6 0 0 6
# resurrect one, should not affect the others
make_pri 0 0 0 0 0 0 0 0 0 0 0 0 0 0
- $CGPT prioritize $MTD -i 2 ${DEV}
+ "${CGPT}" prioritize "${MTD[@]}" -i 2 ${DEV}
assert_pri 0 1 0 0 0 0 0 0 0 0 0 0 0 0
# resurrect one and all its friends
make_pri 0 0 0 0 0 0 0 0 1 2 0 0 0 0
- $CGPT prioritize $MTD -P 5 -i 2 -f ${DEV}
+ "${CGPT}" prioritize "${MTD[@]}" -P 5 -i 2 -f ${DEV}
assert_pri 5 5 5 5 5 5 5 5 3 4 5 5 5 5
# no options should maintain the same order
- $CGPT prioritize $MTD ${DEV}
+ "${CGPT}" prioritize "${MTD[@]}" ${DEV}
assert_pri 3 3 3 3 3 3 3 3 1 2 3 3 3 3
# squish all the ranks
make_pri 1 1 2 2 3 3 4 4 5 5 0 6 7 7
- $CGPT prioritize $MTD -P 6 ${DEV}
+ "${CGPT}" prioritize "${MTD[@]}" -P 6 ${DEV}
assert_pri 1 1 1 1 2 2 3 3 4 4 0 5 6 6
# squish the ranks by not leaving room
make_pri 1 1 2 2 3 3 4 4 5 5 0 6 7 7
- $CGPT prioritize $MTD -P 7 -i 3 ${DEV}
+ "${CGPT}" prioritize "${MTD[@]}" -P 7 -i 3 ${DEV}
assert_pri 1 1 7 1 2 2 3 3 4 4 0 5 6 6
# squish the ranks while bringing the friends along
make_pri 1 1 2 2 3 3 4 4 5 5 0 6 7 7
- $CGPT prioritize $MTD -P 6 -i 3 -f ${DEV}
+ "${CGPT}" prioritize "${MTD[@]}" -P 6 -i 3 -f ${DEV}
assert_pri 1 1 6 6 1 1 2 2 3 3 0 4 5 5
# squish them pretty hard
make_pri 1 1 2 2 3 3 4 4 5 5 0 6 7 7
- $CGPT prioritize $MTD -P 2 ${DEV}
+ "${CGPT}" prioritize "${MTD[@]}" -P 2 ${DEV}
assert_pri 1 1 1 1 1 1 1 1 1 1 0 1 2 2
# squish them really really hard (nobody gets reduced to zero, though)
make_pri 1 1 2 2 3 3 4 4 5 5 0 6 7 7
- $CGPT prioritize $MTD -P 1 -i 3 ${DEV}
+ "${CGPT}" prioritize "${MTD[@]}" -P 1 -i 3 ${DEV}
assert_pri 1 1 1 1 1 1 1 1 1 1 0 1 1 1
make_pri 15 15 14 14 13 13 12 12 11 11 10 10 9 9 8 8 7 7 6 6 5 5 4 4 3 3 2 2 1 1 0
- $CGPT prioritize $MTD -i 3 ${DEV}
+ "${CGPT}" prioritize "${MTD[@]}" -i 3 ${DEV}
assert_pri 14 14 15 13 12 12 11 11 10 10 9 9 8 8 7 7 6 6 5 5 4 4 3 3 2 2 1 1 1 1 0
- $CGPT prioritize $MTD -i 5 ${DEV}
+ "${CGPT}" prioritize "${MTD[@]}" -i 5 ${DEV}
assert_pri 13 13 14 12 15 11 10 10 9 9 8 8 7 7 6 6 5 5 4 4 3 3 2 2 1 1 1 1 1 1 0
# but if I bring friends I don't have to squish
- $CGPT prioritize $MTD -i 1 -f ${DEV}
+ "${CGPT}" prioritize "${MTD[@]}" -i 1 -f ${DEV}
assert_pri 15 15 13 12 14 11 10 10 9 9 8 8 7 7 6 6 5 5 4 4 3 3 2 2 1 1 1 1 1 1 0
}
run_prioritize_tests
echo "Test cgpt repair command"
-$CGPT repair $MTD ${DEV}
-($CGPT show $MTD ${DEV} | grep -q INVALID) && error
+"${CGPT}" repair "${MTD[@]}" ${DEV}
+("${CGPT}" show "${MTD[@]}" ${DEV} | grep -q INVALID) && error
# Zero primary header and partition table and try to repair it.
dd if=/dev/zero of=${DEV} conv=notrunc bs=512 count=33 2>/dev/null
-$CGPT show $MTD ${DEV} | grep -q INVALID
-$CGPT repair $MTD ${DEV}
-($CGPT show $MTD ${DEV} | grep -q INVALID) && error
+"${CGPT}" show "${MTD[@]}" ${DEV} | grep -q INVALID
+"${CGPT}" repair "${MTD[@]}" ${DEV}
+("${CGPT}" show "${MTD[@]}" ${DEV} | grep -q INVALID) && error
# Zero secondary header and partition table and try to repair it.
-dd if=/dev/zero of=${DEV} seek=$(($NUM_SECTORS - 33)) conv=notrunc bs=512 count=33 2>/dev/null
-$CGPT show $MTD ${DEV} | grep -q INVALID
-$CGPT repair $MTD ${DEV}
-($CGPT show $MTD ${DEV} | grep -q INVALID) && error
+dd if=/dev/zero of=${DEV} seek=$((NUM_SECTORS - 33)) conv=notrunc bs=512 \
+ count=33 2>/dev/null
+"${CGPT}" show "${MTD[@]}" ${DEV} | grep -q INVALID
+"${CGPT}" repair "${MTD[@]}" ${DEV}
+("${CGPT}" show "${MTD[@]}" ${DEV} | grep -q INVALID) && error
echo "Test with IGNOREME primary GPT..."
-$CGPT create $MTD ${DEV}
-$CGPT legacy $MTD -p ${DEV}
-$CGPT show $MTD ${DEV} | egrep -q "IGNORED.*Pri GPT" 2>/dev/null
-($CGPT show $MTD ${DEV} | grep -q "Pri GPT table" 2>/dev/null) && error
-$CGPT repair $MTD ${DEV} 2>/dev/null
-$CGPT show $MTD ${DEV} | egrep -q "IGNORED.*Pri GPT" 2>/dev/null
-($CGPT show $MTD ${DEV} | grep -q "Pri GPT table" 2>/dev/null) && error
-$CGPT legacy $MTD -e ${DEV} 2>/dev/null
-($CGPT show $MTD ${DEV} | egrep -q "IGNORED.*Pri GPT") && error
-$CGPT show $MTD ${DEV} | grep -q "Pri GPT table"
+"${CGPT}" create "${MTD[@]}" ${DEV}
+"${CGPT}" legacy "${MTD[@]}" -p ${DEV}
+"${CGPT}" show "${MTD[@]}" ${DEV} | grep -q -E "IGNORED.*Pri GPT" 2>/dev/null
+("${CGPT}" show "${MTD[@]}" ${DEV} | grep -q "Pri GPT table" 2>/dev/null) && \
+ error
+"${CGPT}" repair "${MTD[@]}" ${DEV} 2>/dev/null
+"${CGPT}" show "${MTD[@]}" ${DEV} | grep -q -E "IGNORED.*Pri GPT" 2>/dev/null
+("${CGPT}" show "${MTD[@]}" ${DEV} | grep -q "Pri GPT table" 2>/dev/null) && \
+ error
+"${CGPT}" legacy "${MTD[@]}" -e ${DEV} 2>/dev/null
+("${CGPT}" show "${MTD[@]}" ${DEV} | grep -q -E "IGNORED.*Pri GPT") && error
+"${CGPT}" show "${MTD[@]}" ${DEV} | grep -q "Pri GPT table"
-$CGPT create $MTD ${DEV}
-$CGPT legacy $MTD -p ${DEV}
+"${CGPT}" create "${MTD[@]}" ${DEV}
+"${CGPT}" legacy "${MTD[@]}" -p ${DEV}
run_basic_tests 2>/dev/null
-$CGPT create $MTD ${DEV}
-$CGPT legacy $MTD -p ${DEV}
+"${CGPT}" create "${MTD[@]}" ${DEV}
+"${CGPT}" legacy "${MTD[@]}" -p ${DEV}
run_prioritize_tests 2>/dev/null
# Now make sure that we don't need write access if we're just looking.
@@ -341,48 +347,47 @@
chmod 0444 ${DEV}
# These should fail
-$CGPT create $MTD -z ${DEV} 2>/dev/null && error
-$CGPT add $MTD -i 2 -P 3 ${DEV} 2>/dev/null && error
-$CGPT repair $MTD ${DEV} 2>/dev/null && error
-$CGPT prioritize $MTD -i 3 ${DEV} 2>/dev/null && error
+"${CGPT}" create "${MTD[@]}" -z ${DEV} 2>/dev/null && error
+"${CGPT}" add "${MTD[@]}" -i 2 -P 3 ${DEV} 2>/dev/null && error
+"${CGPT}" repair "${MTD[@]}" ${DEV} 2>/dev/null && error
+"${CGPT}" prioritize "${MTD[@]}" -i 3 ${DEV} 2>/dev/null && error
# Most 'boot' usage should fail too.
-$CGPT boot $MTD -p ${DEV} 2>/dev/null && error
+"${CGPT}" boot "${MTD[@]}" -p ${DEV} 2>/dev/null && error
dd if=/dev/zero of=fake_mbr.bin bs=100 count=1 2>/dev/null
-$CGPT boot $MTD -b fake_mbr.bin ${DEV} 2>/dev/null && error
-$CGPT boot $MTD -i 2 ${DEV} 2>/dev/null && error
+"${CGPT}" boot "${MTD[@]}" -b fake_mbr.bin ${DEV} 2>/dev/null && error
+"${CGPT}" boot "${MTD[@]}" -i 2 ${DEV} 2>/dev/null && error
-$CGPT boot $MTD ${DEV} >/dev/null
-$CGPT show $MTD ${DEV} >/dev/null
-$CGPT find $MTD -t kernel ${DEV} >/dev/null
+"${CGPT}" boot "${MTD[@]}" ${DEV} >/dev/null
+"${CGPT}" show "${MTD[@]}" ${DEV} >/dev/null
+"${CGPT}" find "${MTD[@]}" -t kernel ${DEV} >/dev/null
# Enable write access again to test boundary in off device storage
chmod 600 ${DEV}
# GPT too small
dd if=/dev/zero of=${DEV} bs=5632 count=1
-assert_fail $CGPT create -D 1024 ${DEV}
+assert_fail ""${CGPT}"" create -D 1024 ${DEV}
# GPT is just right for 16 entries (512 + 512 + 16 * 128) * 2 = 6144
dd if=/dev/zero of=${DEV} bs=6144 count=1
-$CGPT create -D 1024 ${DEV}
+"${CGPT}" create -D 1024 ${DEV}
# Create a small 8K file to simulate Flash NOR section
dd if=/dev/zero of=${DEV} bs=8K count=1
# Drive size is not multiple of 512
-assert_fail $CGPT create -D 511 ${DEV}
-assert_fail $CGPT create -D 513 ${DEV}
-MTD="-D 1024"
+assert_fail ""${CGPT}"" create -D 511 ${DEV}
+assert_fail ""${CGPT}"" create -D 513 ${DEV}
# Create a GPT table for a device of 1024 bytes (2 sectors)
-$CGPT create $MTD ${DEV}
+"${CGPT}" create -D 1024 ${DEV}
# Make sure number of entries is reasonable for 8KiB GPT
-X=$($CGPT show -D 1024 -d ${DEV} | grep -c "Number of entries: 24")
+X=$("${CGPT}" show -D 1024 -d ${DEV} | grep -c "Number of entries: 24")
[ "$X" = "2" ] || error
# This fails because header verification is off due to different drive size
-assert_fail $CGPT show ${DEV}
+assert_fail ""${CGPT}"" show ${DEV}
# But this passes because we pass in correct drive size
-$CGPT show $MTD ${DEV}
+"${CGPT}" show -D 1024 ${DEV}
# This fails because beginning sector is over the size of the device
-assert_fail $CGPT add $MTD -b 2 -s 1 -t data ${DEV}
+assert_fail ""${CGPT}"" add -D 1024 -b 2 -s 1 -t data ${DEV}
# This fails because partition size is over the size of the device
-assert_fail $CGPT add $MTD -b 0 -s 3 -t data ${DEV}
+assert_fail ""${CGPT}"" add -D 1024 -b 0 -s 3 -t data ${DEV}
echo "Done."
diff --git a/tests/run_preamble_tests.sh b/tests/run_preamble_tests.sh
index 429213c..2390215 100755
--- a/tests/run_preamble_tests.sh
+++ b/tests/run_preamble_tests.sh
@@ -34,10 +34,8 @@
for rr in $algs; do
if [ "$r" = "$rr" ]; then
what="verify"
- cmp="-ne"
else
what="reject"
- cmp="-eq"
fi
: $(( tests++ ))
echo -n "${what} fw_${d}_${r}.vblock with root_${rr}.vbpubk ... "
@@ -45,7 +43,9 @@
--verify "${V2DIR}/fw_${d}_${r}.vblock" \
--signpubkey "${DATADIR}/root_${rr}.vbpubk" \
--fv "${DATADIR}/FWDATA" >/dev/null 2>&1
- if [ "$?" "$cmp" 0 ]; then
+ if [[ ( $? != 0 && $what == "verify" ) || \
+ ( $? == 0 && $what == "reject" ) ]]
+ then
echo -e "${COL_RED}FAILED${COL_STOP}"
: $(( errs++ ))
else
@@ -62,17 +62,17 @@
for rr in $algs; do
if [ "$r" = "$rr" ]; then
what="verify"
- cmp="-ne"
else
what="reject"
- cmp="-eq"
fi
: $(( tests++ ))
echo -n "${what} kern_${d}_${r}.vblock with root_${rr}.vbpubk ... "
"${FUTILITY}" vbutil_kernel \
--verify "${V2DIR}/kern_${d}_${r}.vblock" \
--signpubkey "${DATADIR}/root_${rr}.vbpubk" >/dev/null 2>&1
- if [ "$?" "$cmp" 0 ]; then
+ if [[ ( $? != 0 && $what == "verify" ) || \
+ ( $? == 0 && $what == "reject" ) ]]
+ then
echo -e "${COL_RED}FAILED${COL_STOP}"
: $(( errs++ ))
else
@@ -88,9 +88,9 @@
for r in $algs; do
: $(( tests++ ))
echo -n "verify kern_${d}_${r}.vblock with hash only ... "
- "${FUTILITY}" vbutil_kernel \
+ if ! "${FUTILITY}" vbutil_kernel \
--verify "${V2DIR}/kern_${d}_${r}.vblock" >/dev/null 2>&1
- if [ "$?" -ne 0 ]; then
+ then
echo -e "${COL_RED}FAILED${COL_STOP}"
: $(( errs++ ))
else
diff --git a/tests/run_vbutil_kernel_arg_tests.sh b/tests/run_vbutil_kernel_arg_tests.sh
index 95317ec..6367662 100755
--- a/tests/run_vbutil_kernel_arg_tests.sh
+++ b/tests/run_vbutil_kernel_arg_tests.sh
@@ -44,7 +44,7 @@
while [ "$b" -lt "${#BOOT_VALS[*]}" ]; do
echo -n "pack kern_${k}_${b}.vblock ... "
: $(( tests++ ))
- "${FUTILITY}" vbutil_kernel \
+ if ! "${FUTILITY}" vbutil_kernel \
--pack "${TMPDIR}/kern_${k}_${b}.vblock" \
--keyblock "${KEYBLOCK}" \
--signprivate "${SIGNPRIVATE}" \
@@ -53,7 +53,7 @@
--config "${CONFIG}" \
"${KERN_VALS[$k]}" \
"${BOOT_VALS[$k]}" >/dev/null
- if [ "$?" -ne 0 ]; then
+ then
echo -e "${COL_RED}FAILED${COL_STOP}"
: $(( errs++ ))
else
@@ -65,12 +65,12 @@
done
# Now unpack it
-for v in ${TMPDIR}/kern_*.vblock; do
+for v in "${TMPDIR}"/kern_*.vblock; do
: $(( tests++ ))
vv=$(basename "$v")
echo -n "verify $vv ... "
- "${FUTILITY}" vbutil_kernel --verify "$v" >/dev/null
- if [ "$?" -ne 0 ]; then
+ if ! "${FUTILITY}" vbutil_kernel --verify "$v" >/dev/null
+ then
echo -e "${COL_RED}FAILED${COL_STOP}"
: $(( errs++ ))
else
@@ -78,9 +78,9 @@
fi
: $(( tests++ ))
echo -n "verify $vv signed ... "
- "${FUTILITY}" vbutil_kernel --verify "$v" \
+ if ! "${FUTILITY}" vbutil_kernel --verify "$v" \
--signpubkey "${SIGNPUBLIC}" >/dev/null
- if [ "$?" -ne 0 ]; then
+ then
echo -e "${COL_RED}FAILED${COL_STOP}"
: $(( errs++ ))
else
@@ -100,7 +100,7 @@
USB_SIGNPUBKEY="${DEVKEYS}/recovery_key.vbpubk"
echo -n "pack USB kernel ... "
: $(( tests++ ))
-"${FUTILITY}" vbutil_kernel \
+if ! "${FUTILITY}" vbutil_kernel \
--pack "${USB_KERN}" \
--keyblock "${USB_KEYBLOCK}" \
--signprivate "${USB_SIGNPRIVATE}" \
@@ -109,7 +109,7 @@
--bootloader "${BIG}" \
--vmlinuz "${BIG}" \
--arch arm
-if [ "$?" -ne 0 ]; then
+then
echo -e "${COL_RED}FAILED${COL_STOP}"
: $(( errs++ ))
else
@@ -119,10 +119,10 @@
# And verify it.
echo -n "verify USB kernel ... "
: $(( tests++ ))
-"${FUTILITY}" vbutil_kernel \
+if ! "${FUTILITY}" vbutil_kernel \
--verify "${USB_KERN}" \
--signpubkey "${USB_SIGNPUBKEY}" >/dev/null
-if [ "$?" -ne 0 ]; then
+then
echo -e "${COL_RED}FAILED${COL_STOP}"
: $(( errs++ ))
else
@@ -139,13 +139,13 @@
SSD_SIGNPUBKEY="${DEVKEYS}/kernel_subkey.vbpubk"
echo -n "repack to SSD kernel ... "
: $(( tests++ ))
-"${FUTILITY}" vbutil_kernel \
+if ! "${FUTILITY}" vbutil_kernel \
--repack "${SSD_KERN}" \
--vblockonly \
--keyblock "${SSD_KEYBLOCK}" \
--signprivate "${SSD_SIGNPRIVATE}" \
--oldblob "${TMPDIR}/usb_kern.bin" >/dev/null
-if [ "$?" -ne 0 ]; then
+then
echo -e "${COL_RED}FAILED${COL_STOP}"
: $(( errs++ ))
else
@@ -155,14 +155,14 @@
# To verify it, we have to replace the vblock from the original image.
tempfile="${TMPDIR}/foo.bin"
cat "${SSD_KERN}" > "$tempfile"
-dd if="${USB_KERN}" bs=65536 skip=1 >> $tempfile 2>/dev/null
+dd if="${USB_KERN}" bs=65536 skip=1 >> "$tempfile" 2>/dev/null
echo -n "verify SSD kernel ... "
: $(( tests++ ))
-"${FUTILITY}" vbutil_kernel \
+if ! "${FUTILITY}" vbutil_kernel \
--verify "$tempfile" \
--signpubkey "${SSD_SIGNPUBKEY}" >/dev/null
-if [ "$?" -ne 0 ]; then
+then
echo -e "${COL_RED}FAILED${COL_STOP}"
: $(( errs++ ))
else
@@ -170,7 +170,7 @@
fi
# Finally make sure that the kernel command line stays good.
-orig=$(cat "${CONFIG}" | tr '\012' ' ')
+orig=$(tr '\012' ' ' < "${CONFIG}")
packed=$("${FUTILITY}" dump_kernel_config "${USB_KERN}")
echo -n "check USB kernel config ..."
: $(( tests++ ))
@@ -184,7 +184,7 @@
repacked=$("${FUTILITY}" dump_kernel_config "${tempfile}")
echo -n "check SSD kernel config ..."
: $(( tests++ ))
-if [ "$orig" != "$packed" ]; then
+if [ "$orig" != "$repacked" ]; then
echo -e "${COL_RED}FAILED${COL_STOP}"
: $(( errs++ ))
else
diff --git a/tests/run_vbutil_tests.sh b/tests/run_vbutil_tests.sh
index 84f66d1..b9db2a7 100755
--- a/tests/run_vbutil_tests.sh
+++ b/tests/run_vbutil_tests.sh
@@ -18,21 +18,19 @@
echo -e "For signing key ${COL_YELLOW}RSA-$keylen/$hashalgo${COL_STOP}:"
# Pack the key
- ${FUTILITY} vbutil_key \
- --pack ${TESTKEY_SCRATCH_DIR}/key_alg${algonum}.vbpubk \
- --key ${TESTKEY_DIR}/key_rsa${keylen}.keyb \
+ if ! "${FUTILITY}" vbutil_key \
+ --pack "${TESTKEY_SCRATCH_DIR}/key_alg${algonum}.vbpubk" \
+ --key "${TESTKEY_DIR}/key_rsa${keylen}.keyb" \
--version 1 \
- --algorithm $algonum
- if [ $? -ne 0 ]
+ --algorithm "${algonum}"
then
return_code=255
fi
# Unpack the key
# TODO: should verify we get the same key back out?
- ${FUTILITY} vbutil_key \
- --unpack ${TESTKEY_SCRATCH_DIR}/key_alg${algonum}.vbpubk
- if [ $? -ne 0 ]
+ if ! "${FUTILITY}" vbutil_key \
+ --unpack "${TESTKEY_SCRATCH_DIR}/key_alg${algonum}.vbpubk"
then
return_code=255
fi
@@ -40,12 +38,12 @@
function test_vbutil_key_all {
algorithmcounter=0
- for keylen in ${key_lengths[@]}
+ for keylen in "${key_lengths[@]}"
do
- for hashalgo in ${hash_algos[@]}
+ for hashalgo in "${hash_algos[@]}"
do
- test_vbutil_key_single $algorithmcounter $keylen $hashalgo
- let algorithmcounter=algorithmcounter+1
+ test_vbutil_key_single "$algorithmcounter" "$keylen" "$hashalgo"
+ algorithmcounter=$((algorithmcounter + 1))
done
done
}
@@ -72,49 +70,45 @@
keyblockfile="${TESTKEY_SCRATCH_DIR}/"
keyblockfile+="sign${signing_algonum}_data"
keyblockfile+="${data_algonum}.keyblock"
- rm -f ${keyblockfile}
+ rm -f "${keyblockfile}"
# Wrap private key
- ${FUTILITY} vbutil_key \
- --pack ${TESTKEY_SCRATCH_DIR}/key_alg${algonum}.vbprivk \
- --key ${TESTKEY_DIR}/key_rsa${signing_keylen}.pem \
- --algorithm $signing_algonum
- if [ $? -ne 0 ]
+ if ! "${FUTILITY}" vbutil_key \
+ --pack "${TESTKEY_SCRATCH_DIR}/key_alg${algonum}.vbprivk" \
+ --key "${TESTKEY_DIR}/key_rsa${signing_keylen}.pem" \
+ --algorithm "${signing_algonum}"
then
echo -e "${COL_RED}Wrap vbprivk${COL_STOP}"
return_code=255
fi
# Wrap public key
- ${FUTILITY} vbutil_key \
- --pack ${TESTKEY_SCRATCH_DIR}/key_alg${algonum}.vbpubk \
- --key ${TESTKEY_DIR}/key_rsa${signing_keylen}.keyb \
- --algorithm $signing_algonum
- if [ $? -ne 0 ]
+ if ! "${FUTILITY}" vbutil_key \
+ --pack "${TESTKEY_SCRATCH_DIR}/key_alg${algonum}.vbpubk" \
+ --key "${TESTKEY_DIR}/key_rsa${signing_keylen}.keyb" \
+ --algorithm "${signing_algonum}"
then
echo -e "${COL_RED}Wrap vbpubk${COL_STOP}"
return_code=255
fi
# Pack
- ${FUTILITY} vbutil_keyblock --pack ${keyblockfile} \
+ if ! "${FUTILITY}" vbutil_keyblock --pack "${keyblockfile}" \
--datapubkey \
- ${TESTKEY_SCRATCH_DIR}/key_alg${data_algonum}.vbpubk \
+ "${TESTKEY_SCRATCH_DIR}/key_alg${data_algonum}.vbpubk" \
--signprivate \
- ${TESTKEY_SCRATCH_DIR}/key_alg${algonum}.vbprivk
- if [ $? -ne 0 ]
+ "${TESTKEY_SCRATCH_DIR}/key_alg${algonum}.vbprivk"
then
echo -e "${COL_RED}Pack${COL_STOP}"
return_code=255
fi
# Unpack
- ${FUTILITY} vbutil_keyblock --unpack ${keyblockfile} \
+ if ! "${FUTILITY}" vbutil_keyblock --unpack "${keyblockfile}" \
--datapubkey \
- ${TESTKEY_SCRATCH_DIR}/key_alg${data_algonum}.vbpubk2 \
+ "${TESTKEY_SCRATCH_DIR}/key_alg${data_algonum}.vbpubk2" \
--signpubkey \
- ${TESTKEY_SCRATCH_DIR}/key_alg${algonum}.vbpubk
- if [ $? -ne 0 ]
+ "${TESTKEY_SCRATCH_DIR}/key_alg${algonum}.vbpubk"
then
echo -e "${COL_RED}Unpack${COL_STOP}"
return_code=255
@@ -122,8 +116,8 @@
# Check
if ! cmp -s \
- ${TESTKEY_SCRATCH_DIR}/key_alg${data_algonum}.vbpubk \
- ${TESTKEY_SCRATCH_DIR}/key_alg${data_algonum}.vbpubk2
+ "${TESTKEY_SCRATCH_DIR}/key_alg${data_algonum}.vbpubk" \
+ "${TESTKEY_SCRATCH_DIR}/key_alg${data_algonum}.vbpubk2"
then
echo -e "${COL_RED}Check${COL_STOP}"
return_code=255
@@ -134,27 +128,24 @@
external signer.${COL_STOP}"
# Pack using external signer
# Pack
- ${FUTILITY} vbutil_keyblock --pack ${keyblockfile} \
+ if ! "${FUTILITY}" vbutil_keyblock --pack "${keyblockfile}" \
--datapubkey \
- ${TESTKEY_SCRATCH_DIR}/key_alg${data_algonum}.vbpubk \
+ "${TESTKEY_SCRATCH_DIR}/key_alg${data_algonum}.vbpubk" \
--signprivate_pem \
- ${TESTKEY_DIR}/key_rsa${signing_keylen}.pem \
+ "${TESTKEY_DIR}/key_rsa${signing_keylen}.pem" \
--pem_algorithm "${signing_algonum}" \
--externalsigner "${SCRIPT_DIR}/external_rsa_signer.sh"
-
- if [ $? -ne 0 ]
then
echo -e "${COL_RED}Pack${COL_STOP}"
return_code=255
fi
# Unpack
- ${FUTILITY} vbutil_keyblock --unpack ${keyblockfile} \
+ if ! "${FUTILITY}" vbutil_keyblock --unpack "${keyblockfile}" \
--datapubkey \
- ${TESTKEY_SCRATCH_DIR}/key_alg${data_algonum}.vbpubk2 \
+ "${TESTKEY_SCRATCH_DIR}/key_alg${data_algonum}.vbpubk2" \
--signpubkey \
- ${TESTKEY_SCRATCH_DIR}/key_alg${signing_algonum}.vbpubk
- if [ $? -ne 0 ]
+ "${TESTKEY_SCRATCH_DIR}/key_alg${signing_algonum}.vbpubk"
then
echo -e "${COL_RED}Unpack${COL_STOP}"
return_code=255
@@ -162,8 +153,8 @@
# Check
if ! cmp -s \
- ${TESTKEY_SCRATCH_DIR}/key_alg${data_algonum}.vbpubk \
- ${TESTKEY_SCRATCH_DIR}/key_alg${data_algonum}.vbpubk2
+ "${TESTKEY_SCRATCH_DIR}/key_alg${data_algonum}.vbpubk" \
+ "${TESTKEY_SCRATCH_DIR}/key_alg${data_algonum}.vbpubk2"
then
echo -e "${COL_RED}Check${COL_STOP}"
return_code=255
@@ -177,22 +168,22 @@
# kernel signing algorithm
signing_algorithmcounter=0
data_algorithmcounter=0
- for signing_keylen in ${key_lengths[@]}
+ for signing_keylen in "${key_lengths[@]}"
do
- for signing_hashalgo in ${hash_algos[@]}
+ for signing_hashalgo in "${hash_algos[@]}"
do
- let data_algorithmcounter=0
- for datakeylen in ${key_lengths[@]}
+ data_algorithmcounter=0
+ for datakeylen in "${key_lengths[@]}"
do
- for datahashalgo in ${hash_algos[@]}
+ for datahashalgo in "${hash_algos[@]}"
do
test_vbutil_keyblock_single \
- $signing_algorithmcounter $signing_keylen $signing_hashalgo \
- $data_algorithmcounter $data_keylen $data_hashalgo
- let data_algorithmcounter=data_algorithmcounter+1
+ "$signing_algorithmcounter" "$signing_keylen" "$signing_hashalgo" \
+ "$data_algorithmcounter" "$data_keylen" "$data_hashalgo"
+ data_algorithmcounter=$((data_algorithmcounter + 1))
done
done
- let signing_algorithmcounter=signing_algorithmcounter+1
+ signing_algorithmcounter=$((signing_algorithmcounter + 1))
done
done
}
@@ -223,4 +214,3 @@
fi
exit $return_code
-
diff --git a/tests/sha_benchmark.c b/tests/sha_benchmark.c
index 27b1c10..d7ba31a 100644
--- a/tests/sha_benchmark.c
+++ b/tests/sha_benchmark.c
@@ -10,8 +10,8 @@
#include "2common.h"
#include "2sha.h"
#include "2sysincludes.h"
+#include "common/timer_utils.h"
#include "host_common.h"
-#include "timer_utils.h"
#define TEST_BUFFER_SIZE 4000000
diff --git a/tests/subprocess_tests.c b/tests/subprocess_tests.c
index 75d6e49..d65618f 100644
--- a/tests/subprocess_tests.c
+++ b/tests/subprocess_tests.c
@@ -7,7 +7,7 @@
#include <string.h>
#include "subprocess.h"
-#include "test_common.h"
+#include "common/tests.h"
#define TEST_STRING "hello world"
#define TEST_STRING_LN TEST_STRING "\n"
diff --git a/tests/test_using_qemu.sh b/tests/test_using_qemu.sh
index 081d963..5ed2974 100755
--- a/tests/test_using_qemu.sh
+++ b/tests/test_using_qemu.sh
@@ -24,11 +24,11 @@
# Don't exit on error, so we can capture the error code
set +e
-sudo chroot ${SYSROOT} ${QEMU_RUN} \
+sudo chroot "${SYSROOT}" "${QEMU_RUN}" \
-E LD_LIBRARY_PATH=/lib64:/lib:/usr/lib64:/usr/lib \
- -E HOME=${HOME} \
- -E BUILD=${BUILD_RUN} \
- -- $*
+ -E HOME="${HOME}" \
+ -E BUILD="${BUILD_RUN}" \
+ -- "$@"
exit_code=$?
set -e
diff --git a/tests/tlcl_tests.c b/tests/tlcl_tests.c
index 328abbe..62d34af 100644
--- a/tests/tlcl_tests.c
+++ b/tests/tlcl_tests.c
@@ -11,8 +11,8 @@
#include <string.h>
#include "2api.h"
+#include "common/tests.h"
#include "host_common.h"
-#include "test_common.h"
#include "tlcl.h"
#include "tlcl_internal.h"
diff --git a/tests/tpm_lite/tpmtest_fastenable.c b/tests/tpm_lite/tpmtest_fastenable.c
index a93dfd7..226a41f 100644
--- a/tests/tpm_lite/tpmtest_fastenable.c
+++ b/tests/tpm_lite/tpmtest_fastenable.c
@@ -15,7 +15,7 @@
#include <stdio.h>
#include "host_common.h"
-#include "test_common.h"
+#include "common/tests.h"
#include "tlcl.h"
#include "tlcl_tests.h"
diff --git a/tests/tpm_lite/tpmtest_globallock.c b/tests/tpm_lite/tpmtest_globallock.c
index 14f16de..52f7c8e 100644
--- a/tests/tpm_lite/tpmtest_globallock.c
+++ b/tests/tpm_lite/tpmtest_globallock.c
@@ -11,7 +11,7 @@
#include <stdlib.h>
#include "host_common.h"
-#include "test_common.h"
+#include "common/tests.h"
#include "tlcl.h"
#include "tlcl_tests.h"
diff --git a/tests/tpm_lite/tpmtest_redefine_unowned.c b/tests/tpm_lite/tpmtest_redefine_unowned.c
index 0f89870..45bcd93 100644
--- a/tests/tpm_lite/tpmtest_redefine_unowned.c
+++ b/tests/tpm_lite/tpmtest_redefine_unowned.c
@@ -11,7 +11,7 @@
#include <stdlib.h>
#include "host_common.h"
-#include "test_common.h"
+#include "common/tests.h"
#include "tlcl.h"
#include "tlcl_tests.h"
diff --git a/tests/tpm_lite/tpmtest_spaceperm.c b/tests/tpm_lite/tpmtest_spaceperm.c
index 8c9232b..70f2b99 100644
--- a/tests/tpm_lite/tpmtest_spaceperm.c
+++ b/tests/tpm_lite/tpmtest_spaceperm.c
@@ -11,7 +11,7 @@
#include <stdlib.h>
#include "host_common.h"
-#include "test_common.h"
+#include "common/tests.h"
#include "tlcl.h"
#include "tlcl_tests.h"
diff --git a/tests/tpm_lite/tpmtest_writelimit.c b/tests/tpm_lite/tpmtest_writelimit.c
index 05e4a17..71562b0 100644
--- a/tests/tpm_lite/tpmtest_writelimit.c
+++ b/tests/tpm_lite/tpmtest_writelimit.c
@@ -12,7 +12,7 @@
#include "2common.h"
#include "host_common.h"
-#include "test_common.h"
+#include "common/tests.h"
#include "tlcl.h"
#include "tlcl_tests.h"
diff --git a/tests/vb20_api_kernel_tests.c b/tests/vb20_api_kernel_tests.c
index b835251..bc585b4 100644
--- a/tests/vb20_api_kernel_tests.c
+++ b/tests/vb20_api_kernel_tests.c
@@ -14,7 +14,7 @@
#include "2rsa.h"
#include "2secdata.h"
#include "2sysincludes.h"
-#include "test_common.h"
+#include "common/tests.h"
#include "vboot_struct.h"
/* Common context for tests */
diff --git a/tests/vb20_kernel_tests.c b/tests/vb20_kernel_tests.c
index 8766114..05f21ab 100644
--- a/tests/vb20_kernel_tests.c
+++ b/tests/vb20_kernel_tests.c
@@ -14,7 +14,7 @@
#include "2rsa.h"
#include "2secdata.h"
#include "2sysincludes.h"
-#include "test_common.h"
+#include "common/tests.h"
/* Common context for tests */
static uint8_t workbuf[VB2_KERNEL_WORKBUF_RECOMMENDED_SIZE]
diff --git a/tests/vb20_rsa_padding_tests.c b/tests/vb20_rsa_padding_tests.c
index 90ff42a..68c32a9 100644
--- a/tests/vb20_rsa_padding_tests.c
+++ b/tests/vb20_rsa_padding_tests.c
@@ -9,10 +9,10 @@
#include "2common.h"
#include "2rsa.h"
#include "2sysincludes.h"
+#include "common/tests.h"
#include "file_keys.h"
#include "host_key.h"
#include "rsa_padding_test.h"
-#include "test_common.h"
vb2_error_t hwcrypto_modexp_return_value = VB2_SUCCESS;
vb2_error_t vb2ex_hwcrypto_modexp(const struct vb2_public_key *key,
diff --git a/tests/vb21_host_common2_tests.c b/tests/vb21_host_common2_tests.c
index b2ceb95..61ba986 100644
--- a/tests/vb21_host_common2_tests.c
+++ b/tests/vb21_host_common2_tests.c
@@ -12,11 +12,11 @@
#include "2common.h"
#include "2rsa.h"
#include "2sysincludes.h"
+#include "common/tests.h"
#include "host_common.h"
#include "host_common21.h"
#include "host_key21.h"
#include "host_signature21.h"
-#include "test_common.h"
#include "util_misc.h"
static const uint8_t test_data[] = "This is some test data to sign.";
diff --git a/tests/vb21_host_common_tests.c b/tests/vb21_host_common_tests.c
index 3ab5dbc..385a0c2 100644
--- a/tests/vb21_host_common_tests.c
+++ b/tests/vb21_host_common_tests.c
@@ -8,10 +8,10 @@
#include "2common.h"
#include "2rsa.h"
#include "2sysincludes.h"
+#include "common/tests.h"
#include "host_common21.h"
#include "host_key21.h"
#include "host_signature21.h"
-#include "test_common.h"
static const uint8_t test_data[] = "This is some test data to sign.";
diff --git a/tests/vb21_host_key_tests.c b/tests/vb21_host_key_tests.c
index e8eef9b..e0a1105 100644
--- a/tests/vb21_host_key_tests.c
+++ b/tests/vb21_host_key_tests.c
@@ -11,10 +11,10 @@
#include "2common.h"
#include "2rsa.h"
#include "2sysincludes.h"
+#include "common/tests.h"
#include "host_common.h"
#include "host_common21.h"
#include "host_key21.h"
-#include "test_common.h"
/* Test only the algorithms we use */
struct alg_combo {
diff --git a/tests/vb21_host_misc_tests.c b/tests/vb21_host_misc_tests.c
index f437803..dbf12e0 100644
--- a/tests/vb21_host_misc_tests.c
+++ b/tests/vb21_host_misc_tests.c
@@ -10,10 +10,10 @@
#include "2common.h"
#include "2sysincludes.h"
+#include "common/tests.h"
#include "host_common.h"
#include "host_common21.h"
#include "host_misc.h"
-#include "test_common.h"
static void misc_tests(void)
{
diff --git a/tests/vb21_host_sig_tests.c b/tests/vb21_host_sig_tests.c
index f337eaa..4a9abff 100644
--- a/tests/vb21_host_sig_tests.c
+++ b/tests/vb21_host_sig_tests.c
@@ -11,11 +11,11 @@
#include "2common.h"
#include "2rsa.h"
#include "2sysincludes.h"
+#include "common/tests.h"
#include "host_common.h"
#include "host_common21.h"
#include "host_key21.h"
#include "host_signature21.h"
-#include "test_common.h"
/* Test only the algorithms we use */
struct alg_combo {
diff --git a/tests/vb2_api_tests.c b/tests/vb2_api_tests.c
index 15c9bd1..ca2f7e9 100644
--- a/tests/vb2_api_tests.c
+++ b/tests/vb2_api_tests.c
@@ -14,7 +14,7 @@
#include "2rsa.h"
#include "2secdata.h"
#include "2sysincludes.h"
-#include "test_common.h"
+#include "common/tests.h"
/* Common context for tests */
@@ -135,8 +135,10 @@
vb2_error_t vb2_check_dev_switch(struct vb2_context *c)
{
- if (force_dev_mode)
+ if (force_dev_mode) {
+ c->flags |= VB2_CONTEXT_DEVELOPER_MODE;
sd->flags |= VB2_SD_FLAG_DEV_MODE_ENABLED;
+ }
return retval_vb2_check_dev_switch;
}
diff --git a/tests/vb2_auxfw_sync_tests.c b/tests/vb2_auxfw_sync_tests.c
index bcdd67a..b9c869a 100644
--- a/tests/vb2_auxfw_sync_tests.c
+++ b/tests/vb2_auxfw_sync_tests.c
@@ -13,9 +13,8 @@
#include "2misc.h"
#include "2nvstorage.h"
#include "2sysincludes.h"
+#include "common/tests.h"
#include "host_common.h"
-#include "load_kernel_fw.h"
-#include "test_common.h"
#include "vboot_struct.h"
/* Mock data */
@@ -25,7 +24,8 @@
static struct vb2_shared_data *sd;
static struct vb2_gbb_header gbb;
-static vb2_error_t auxfw_retval;
+static vb2_error_t auxfw_check_retval;
+static vb2_error_t auxfw_update_retval;
static int auxfw_update_req;
static enum vb2_auxfw_update_severity auxfw_mock_severity;
static enum vb2_auxfw_update_severity auxfw_update_severity;
@@ -46,7 +46,8 @@
memset(&gbb, 0, sizeof(gbb));
- auxfw_retval = VB2_SUCCESS;
+ auxfw_check_retval = VB2_SUCCESS;
+ auxfw_update_retval = VB2_SUCCESS;
auxfw_mock_severity = VB2_AUXFW_NO_UPDATE;
auxfw_update_severity = VB2_AUXFW_NO_UPDATE;
auxfw_mock_display_available = 1;
@@ -65,7 +66,7 @@
{
*severity = auxfw_mock_severity;
auxfw_update_severity = auxfw_mock_severity;
- return VB2_SUCCESS;
+ return auxfw_check_retval;
}
vb2_error_t vb2ex_auxfw_update(void)
@@ -77,7 +78,7 @@
if (auxfw_update_severity != VB2_AUXFW_NO_DEVICE &&
auxfw_update_severity != VB2_AUXFW_NO_UPDATE)
auxfw_update_req = 1;
- return auxfw_retval;
+ return auxfw_update_retval;
}
vb2_error_t vb2ex_auxfw_finalize(struct vb2_context *c)
@@ -152,7 +153,13 @@
ResetMocks();
auxfw_mock_severity = VB2_AUXFW_FAST_UPDATE;
- auxfw_retval = VB2_ERROR_UNKNOWN;
+ auxfw_check_retval = VB2_ERROR_UNKNOWN;
+ test_auxsync(VB2_ERROR_UNKNOWN, VB2_RECOVERY_AUXFW_UPDATE,
+ "Error checking auxfw");
+
+ ResetMocks();
+ auxfw_mock_severity = VB2_AUXFW_FAST_UPDATE;
+ auxfw_update_retval = VB2_ERROR_UNKNOWN;
test_auxsync(VB2_ERROR_UNKNOWN, VB2_RECOVERY_AUXFW_UPDATE,
"Error updating auxfw");
}
diff --git a/tests/vb2_common2_tests.c b/tests/vb2_common2_tests.c
index 5f065f8..e793e57 100644
--- a/tests/vb2_common2_tests.c
+++ b/tests/vb2_common2_tests.c
@@ -12,10 +12,10 @@
#include "2common.h"
#include "2rsa.h"
#include "2sysincludes.h"
+#include "common/tests.h"
#include "file_keys.h"
#include "host_common.h"
#include "host_key21.h"
-#include "test_common.h"
static const uint8_t test_data[] = "This is some test data to sign.";
static const uint32_t test_size = sizeof(test_data);
diff --git a/tests/vb2_common3_tests.c b/tests/vb2_common3_tests.c
index 5805204..8e7a20c 100644
--- a/tests/vb2_common3_tests.c
+++ b/tests/vb2_common3_tests.c
@@ -10,12 +10,12 @@
#include "2common.h"
#include "2rsa.h"
#include "2sysincludes.h"
+#include "common/tests.h"
#include "file_keys.h"
#include "host_common.h"
#include "host_keyblock.h"
#include "host_key.h"
#include "host_signature.h"
-#include "test_common.h"
static void resign_keyblock(struct vb2_keyblock *h,
const struct vb2_private_key *key)
diff --git a/tests/vb2_common_tests.c b/tests/vb2_common_tests.c
index d76c402..beb8461 100644
--- a/tests/vb2_common_tests.c
+++ b/tests/vb2_common_tests.c
@@ -7,7 +7,7 @@
#include "2common.h"
#include "2sysincludes.h"
-#include "test_common.h"
+#include "common/tests.h"
#include "vboot_struct.h" /* For old struct sizes */
/* Mock data */
diff --git a/tests/vb2_crypto_tests.c b/tests/vb2_crypto_tests.c
index c7d6676..6696feb 100644
--- a/tests/vb2_crypto_tests.c
+++ b/tests/vb2_crypto_tests.c
@@ -12,7 +12,7 @@
#include "2rsa.h"
#include "2sha.h"
#include "2sysincludes.h"
-#include "test_common.h"
+#include "common/tests.h"
#include "vboot_host.h"
static void hash_algorithm_name_tests(void)
diff --git a/tests/vb2_ec_sync_tests.c b/tests/vb2_ec_sync_tests.c
index f4631b7..f317561 100644
--- a/tests/vb2_ec_sync_tests.c
+++ b/tests/vb2_ec_sync_tests.c
@@ -10,9 +10,8 @@
#include "2nvstorage.h"
#include "2secdata.h"
#include "2sysincludes.h"
+#include "common/tests.h"
#include "host_common.h"
-#include "load_kernel_fw.h"
-#include "test_common.h"
#include "vboot_struct.h"
/* Mock data */
diff --git a/tests/vb2_firmware_tests.c b/tests/vb2_firmware_tests.c
index 681e5d6..933f608 100644
--- a/tests/vb2_firmware_tests.c
+++ b/tests/vb2_firmware_tests.c
@@ -14,7 +14,7 @@
#include "2rsa.h"
#include "2secdata.h"
#include "2sysincludes.h"
-#include "test_common.h"
+#include "common/tests.h"
/* Common context for tests */
static uint8_t workbuf[VB2_FIRMWARE_WORKBUF_RECOMMENDED_SIZE]
diff --git a/tests/vb2_firmware_tests.sh b/tests/vb2_firmware_tests.sh
index 88b6e6a..51803e2 100755
--- a/tests/vb2_firmware_tests.sh
+++ b/tests/vb2_firmware_tests.sh
@@ -50,34 +50,41 @@
local fw_algo=$2
local kern_algo=$3
- local root_rsa="$(algo_to_rsa ${root_algo})"
- local fw_rsa="$(algo_to_rsa ${fw_algo})"
- local kern_rsa="$(algo_to_rsa ${kern_algo})"
+ local root_rsa
+ local fw_rsa
+ local kern_rsa
+ root_rsa="$(algo_to_rsa "${root_algo}")"
+ fw_rsa="$(algo_to_rsa "${fw_algo}")"
+ kern_rsa="$(algo_to_rsa "${kern_algo}")"
- local root_sha="$(algo_to_sha ${root_algo})"
- local fw_sha="$(algo_to_sha ${fw_algo})"
- local kern_sha="$(algo_to_sha ${kern_algo})"
+ local root_sha
+ local fw_sha
+ root_sha="$(algo_to_sha "${root_algo}")"
+ fw_sha="$(algo_to_sha "${fw_algo}")"
# Pack keys using original vboot utilities
- ${FUTILITY} vbutil_key --pack rootkey.test \
- --key "${TESTKEY_DIR}/key_${root_rsa}.keyb" --algorithm ${root_algo}
- ${FUTILITY} vbutil_key --pack fwsubkey.test \
- --key "${TESTKEY_DIR}/key_${fw_rsa}.keyb" --algorithm ${fw_algo}
- ${FUTILITY} vbutil_key --pack kernkey.test \
- --key "${TESTKEY_DIR}/key_${kern_rsa}.keyb" --algorithm ${kern_algo}
+ "${FUTILITY}" vbutil_key --pack rootkey.test \
+ --key "${TESTKEY_DIR}/key_${root_rsa}.keyb" \
+ --algorithm "${root_algo}"
+ "${FUTILITY}" vbutil_key --pack fwsubkey.test \
+ --key "${TESTKEY_DIR}/key_${fw_rsa}.keyb" \
+ --algorithm "${fw_algo}"
+ "${FUTILITY}" vbutil_key --pack kernkey.test \
+ --key "${TESTKEY_DIR}/key_${kern_rsa}.keyb" \
+ --algorithm "${kern_algo}"
# Create a GBB with the root key
- ${FUTILITY} gbb -c 128,2400,0,0 gbb.test
- ${FUTILITY} gbb gbb.test -s --hwid='Test GBB' \
+ "${FUTILITY}" gbb -c 128,2400,0,0 gbb.test
+ "${FUTILITY}" gbb gbb.test -s --hwid='Test GBB' \
--rootkey=rootkey.test
# Keyblock with firmware subkey is signed by root key
- ${FUTILITY} vbutil_keyblock --pack keyblock.test \
+ "${FUTILITY}" vbutil_keyblock --pack keyblock.test \
--datapubkey fwsubkey.test \
--signprivate "${TESTKEY_DIR}/key_${root_rsa}.${root_sha}.vbprivk"
# Firmware preamble is signed with the firmware subkey
- ${FUTILITY} vbutil_firmware \
+ "${FUTILITY}" vbutil_firmware \
--vblock vblock.test \
--keyblock keyblock.test \
--signprivate "${TESTKEY_DIR}/key_${fw_rsa}.${fw_sha}.vbprivk" \
@@ -89,7 +96,7 @@
"(root=${root_algo}, fw=${fw_algo}, kernel=${kern_algo})"
# Verify the firmware using vboot2 checks
- ${BUILD_RUN}/tests/vb20_verify_fw gbb.test vblock.test body.test
+ "${BUILD_RUN}/tests/vb20_verify_fw" gbb.test vblock.test body.test
happy 'vb2_verify_fw succeeded'
}
diff --git a/tests/vb2_gbb_tests.c b/tests/vb2_gbb_tests.c
index 047fa42..51ebcf6 100644
--- a/tests/vb2_gbb_tests.c
+++ b/tests/vb2_gbb_tests.c
@@ -7,7 +7,7 @@
#include "2common.h"
#include "2misc.h"
-#include "test_common.h"
+#include "common/tests.h"
/* Mock data */
static char gbb_data[4096 + sizeof(struct vb2_gbb_header)];
diff --git a/tests/vb2_host_flashrom_tests.c b/tests/vb2_host_flashrom_tests.c
index 815657d..7cebc5e 100644
--- a/tests/vb2_host_flashrom_tests.c
+++ b/tests/vb2_host_flashrom_tests.c
@@ -18,10 +18,10 @@
#include "2common.h"
#include "2return_codes.h"
+#include "common/tests.h"
#include "host_misc.h"
#include "flashrom.h"
#include "subprocess.h"
-#include "test_common.h"
#define MOCK_TMPFILE_NAME "/tmp/vb2_unittest"
#define MOCK_ROM_CONTENTS "bloop123"
diff --git a/tests/vb2_host_key_tests.c b/tests/vb2_host_key_tests.c
index 82dd357..9c6fe28 100644
--- a/tests/vb2_host_key_tests.c
+++ b/tests/vb2_host_key_tests.c
@@ -6,8 +6,8 @@
*/
#include "2common.h"
+#include "common/tests.h"
#include "host_common.h"
-#include "test_common.h"
/* Public key utility functions */
static void public_key_tests(void)
diff --git a/tests/vb2_host_nvdata_flashrom_tests.c b/tests/vb2_host_nvdata_flashrom_tests.c
index 068b23a..719f1d1 100644
--- a/tests/vb2_host_nvdata_flashrom_tests.c
+++ b/tests/vb2_host_nvdata_flashrom_tests.c
@@ -17,9 +17,9 @@
#include "2constants.h"
#include "2nvstorage.h"
#include "2return_codes.h"
+#include "common/tests.h"
#include "crossystem_vbnv.h"
#include "flashrom.h"
-#include "test_common.h"
/* Mocked flashrom only supports host programmer, and RW_NVRAM
region. */
diff --git a/tests/vb2_kernel_tests.c b/tests/vb2_kernel_tests.c
index 0b3e94c..6d32eb2 100644
--- a/tests/vb2_kernel_tests.c
+++ b/tests/vb2_kernel_tests.c
@@ -7,15 +7,13 @@
#include "2api.h"
#include "2common.h"
-#include "2kernel.h"
#include "2misc.h"
#include "2nvstorage.h"
#include "2rsa.h"
#include "2secdata.h"
#include "2sysincludes.h"
-#include "test_common.h"
-#include "vboot_struct.h"
-#include "vboot_api.h"
+#include "common/boot_mode.h"
+#include "common/tests.h"
/* Common context for tests */
static uint8_t workbuf[VB2_KERNEL_WORKBUF_RECOMMENDED_SIZE]
@@ -24,7 +22,7 @@
static struct vb2_shared_data *sd;
static struct vb2_fw_preamble *fwpre;
static const char fw_kernel_key_data[36] = "Test kernel key data";
-static enum vb2_boot_mode *boot_mode;
+static struct vb2_kernel_params kparams;
/* Mocked function data */
@@ -36,14 +34,19 @@
static int mock_read_res_fail_on_call;
static int mock_secdata_fwmp_check_retval;
-static int mock_vbtlk_expect_fixed;
-static int mock_vbtlk_expect_removable;
-static vb2_error_t mock_vbtlk_retval;
+static int mock_commit_data_called;
+static int mock_ec_sync_called;
+static int mock_ec_sync_retval;
+static int mock_battery_cutoff_called;
+static int mock_kernel_flag;
+static int mock_kernel_flag_set;
+static int mock_kernel_version;
/* Type of test to reset for */
enum reset_type {
FOR_PHASE1,
- FOR_NORMAL_BOOT,
+ FOR_PHASE2,
+ FOR_FINALIZE,
};
static void reset_common_data(enum reset_type t)
@@ -52,22 +55,23 @@
memset(workbuf, 0xaa, sizeof(workbuf));
+ memset(&kparams, 0, sizeof(kparams));
+
TEST_SUCC(vb2api_init(workbuf, sizeof(workbuf), &ctx),
"vb2api_init failed");
sd = vb2_get_sd(ctx);
vb2_nv_init(ctx);
- vb2api_secdata_kernel_create(ctx);
- vb2_secdata_kernel_init(ctx);
- vb2_secdata_kernel_set(ctx, VB2_SECDATA_KERNEL_VERSIONS, 0x20002);
-
mock_read_res_fail_on_call = 0;
mock_secdata_fwmp_check_retval = VB2_SUCCESS;
- mock_vbtlk_expect_fixed = 0;
- mock_vbtlk_expect_removable = 0;
- mock_vbtlk_retval = VB2_SUCCESS;
-
+ mock_commit_data_called = 0;
+ mock_ec_sync_called = 0;
+ mock_ec_sync_retval = VB2_SUCCESS;
+ mock_battery_cutoff_called = 0;
+ mock_kernel_flag = 0;
+ mock_kernel_flag_set = 0;
+ mock_kernel_version = 0x10002;
/* Recovery key in mock GBB */
memset(&mock_gbb, 0, sizeof(mock_gbb));
@@ -82,15 +86,8 @@
mock_gbb.h.recovery_key_size =
mock_gbb.recovery_key.key_offset +
mock_gbb.recovery_key.key_size;
-
- /* For boot_mode */
- boot_mode = (enum vb2_boot_mode *)&ctx->boot_mode;
- if (t == FOR_PHASE1)
- *boot_mode = VB2_BOOT_MODE_BROKEN_SCREEN;
- else if (t == FOR_NORMAL_BOOT)
- *boot_mode = VB2_BOOT_MODE_NORMAL;
- else
- *boot_mode = VB2_BOOT_MODE_UNDEFINED;
+ mock_gbb.h.major_version = VB2_GBB_MAJOR_VER;
+ mock_gbb.h.minor_version = VB2_GBB_MINOR_VER;
if (t == FOR_PHASE1) {
uint8_t *kdata;
@@ -108,6 +105,11 @@
sd->preamble_size = sizeof(*fwpre) + k->key_size;
vb2_set_workbuf_used(ctx,
sd->preamble_offset + sd->preamble_size);
+ } else if (t == FOR_FINALIZE) {
+ SET_BOOT_MODE(ctx, VB2_BOOT_MODE_NORMAL);
+ vb2_nv_set(ctx, VB2_NV_KERNEL_MAX_ROLLFORWARD, 0xffffffff);
+ sd->kernel_version_secdata = mock_kernel_version;
+ sd->kernel_version = mock_kernel_version;
}
};
@@ -118,6 +120,34 @@
return mock_secdata_fwmp_check_retval;
}
+vb2_error_t vb2api_ec_sync(struct vb2_context *c)
+{
+ mock_ec_sync_called = 1;
+ return mock_ec_sync_retval;
+}
+
+vb2_error_t vb2api_auxfw_sync(struct vb2_context *c)
+{
+ return VB2_SUCCESS;
+}
+
+vb2_error_t vb2ex_ec_battery_cutoff(void)
+{
+ TEST_EQ(mock_ec_sync_called, 1,
+ " battery cutoff must happen after EC sync");
+ mock_battery_cutoff_called = 1;
+ return VB2_SUCCESS;
+}
+
+const uint8_t *vb2_secdata_kernel_get_ec_hash(struct vb2_context *c)
+{
+ /*
+ * Return NULL to prevent EC reboot due to
+ * VB2_SD_FLAG_ECSYNC_HMIR_UPDATED.
+ */
+ return NULL;
+}
+
struct vb2_gbb_header *vb2_get_gbb(struct vb2_context *c)
{
return &mock_gbb.h;
@@ -149,24 +179,41 @@
return VB2_SUCCESS;
}
-vb2_error_t VbTryLoadKernel(struct vb2_context *c, uint32_t disk_flags)
+vb2_error_t vb2ex_commit_data(struct vb2_context *c)
{
- /*
- * TODO: Currently we don't have a good way of testing for an ordered
- * sequence of VB_DISK_FLAG_FIXED and then VB_DISK_FLAG_REMOVABLE. If
- * both are set, then just assume success.
- */
- if (mock_vbtlk_expect_fixed && mock_vbtlk_expect_removable)
- return mock_vbtlk_retval;
+ mock_commit_data_called = 1;
+ return VB2_SUCCESS;
+}
- TEST_EQ(!!mock_vbtlk_expect_fixed,
- !!(disk_flags & VB_DISK_FLAG_FIXED),
- " VbTryLoadKernel unexpected fixed disk call");
- TEST_EQ(!!mock_vbtlk_expect_removable,
- !!(disk_flags & VB_DISK_FLAG_REMOVABLE),
- " VbTryLoadKernel unexpected removable disk call");
+void vb2_secdata_kernel_set(struct vb2_context *c,
+ enum vb2_secdata_kernel_param param,
+ uint32_t value)
+{
+ switch (param) {
+ case VB2_SECDATA_KERNEL_FLAGS:
+ mock_kernel_flag = value;
+ mock_kernel_flag_set = 1;
+ break;
+ case VB2_SECDATA_KERNEL_VERSIONS:
+ mock_kernel_version = value;
+ break;
+ default:
+ vb2ex_abort();
+ }
+}
- return mock_vbtlk_retval;
+uint32_t vb2_secdata_kernel_get(struct vb2_context *c,
+ enum vb2_secdata_kernel_param param)
+{
+ switch (param) {
+ case VB2_SECDATA_KERNEL_FLAGS:
+ return mock_kernel_flag;
+ case VB2_SECDATA_KERNEL_VERSIONS:
+ return mock_kernel_version;
+ default:
+ vb2ex_abort();
+ }
+ return 0;
}
/* Tests */
@@ -178,6 +225,7 @@
/* Test successful call */
reset_common_data(FOR_PHASE1);
+ SET_BOOT_MODE(ctx, VB2_BOOT_MODE_NORMAL);
TEST_SUCC(vb2api_kernel_phase1(ctx), "phase1 good");
/* Make sure normal key was loaded */
TEST_EQ(sd->kernel_key_offset, sd->preamble_offset +
@@ -194,12 +242,12 @@
TEST_EQ(k->key_size, sizeof(fw_kernel_key_data), " key_size");
TEST_EQ(memcmp((uint8_t *)k + k->key_offset, fw_kernel_key_data,
k->key_size), 0, " key data");
- TEST_EQ(sd->kernel_version_secdata, 0x20002,
+ TEST_EQ(sd->kernel_version_secdata, 0x10002,
" secdata_kernel version");
/* Test successful call in recovery mode */
reset_common_data(FOR_PHASE1);
- ctx->flags |= VB2_CONTEXT_RECOVERY_MODE;
+ SET_BOOT_MODE(ctx, VB2_BOOT_MODE_BROKEN_SCREEN, 123);
/* No preamble needed in recovery mode */
sd->workbuf_used = sd->preamble_offset;
sd->preamble_offset = sd->preamble_size = 0;
@@ -220,12 +268,12 @@
TEST_EQ(memcmp((uint8_t *)k + k->key_offset,
mock_gbb.recovery_key_data, k->key_size), 0,
" key data");
- TEST_EQ(sd->kernel_version_secdata, 0x20002,
+ TEST_EQ(sd->kernel_version_secdata, 0x10002,
" secdata_kernel version");
/* Test flags for experimental features in non-recovery path */
reset_common_data(FOR_PHASE1);
- ctx->flags &= ~VB2_CONTEXT_RECOVERY_MODE;
+ SET_BOOT_MODE(ctx, VB2_BOOT_MODE_NORMAL);
TEST_SUCC(vb2api_kernel_phase1(ctx), "phase1 non-rec good");
/* Make sure phone recovery functionality is enabled, but UI disabled */
TEST_EQ(vb2api_phone_recovery_enabled(ctx), 1,
@@ -239,26 +287,15 @@
/*
* Test flags are unchanged for experimental features in recovery path
*/
-
- /* Set 8 bits to 0 */
reset_common_data(FOR_PHASE1);
- ctx->flags |= VB2_CONTEXT_RECOVERY_MODE;
- vb2_secdata_kernel_set(ctx, VB2_SECDATA_KERNEL_FLAGS, 0);
+ SET_BOOT_MODE(ctx, VB2_BOOT_MODE_BROKEN_SCREEN, 123);
TEST_SUCC(vb2api_kernel_phase1(ctx), "phase1 rec good");
- TEST_EQ(vb2_secdata_kernel_get(ctx, VB2_SECDATA_KERNEL_FLAGS), 0,
- "VB2_SECDATA_KERNEL_FLAGS remains unchanged in recovery path");
-
- /* Set 8 bits to 1 */
- reset_common_data(FOR_PHASE1);
- ctx->flags |= VB2_CONTEXT_RECOVERY_MODE;
- vb2_secdata_kernel_set(ctx, VB2_SECDATA_KERNEL_FLAGS, UINT8_MAX);
- TEST_SUCC(vb2api_kernel_phase1(ctx), "phase1 rec good");
- TEST_EQ(vb2_secdata_kernel_get(ctx, VB2_SECDATA_KERNEL_FLAGS),
- UINT8_MAX,
+ TEST_EQ(mock_kernel_flag_set, 0,
"VB2_SECDATA_KERNEL_FLAGS remains unchanged in recovery path");
/* Bad secdata_fwmp causes failure in normal mode only */
reset_common_data(FOR_PHASE1);
+ SET_BOOT_MODE(ctx, VB2_BOOT_MODE_NORMAL);
mock_secdata_fwmp_check_retval = VB2_ERROR_SECDATA_FWMP_CRC;
TEST_EQ(vb2api_kernel_phase1(ctx), mock_secdata_fwmp_check_retval,
"phase1 bad secdata_fwmp");
@@ -266,15 +303,15 @@
VB2_RECOVERY_SECDATA_FWMP_INIT, " recovery reason");
reset_common_data(FOR_PHASE1);
+ SET_BOOT_MODE(ctx, VB2_BOOT_MODE_BROKEN_SCREEN, 123);
mock_secdata_fwmp_check_retval = VB2_ERROR_SECDATA_FWMP_CRC;
- ctx->flags |= VB2_CONTEXT_RECOVERY_MODE;
TEST_SUCC(vb2api_kernel_phase1(ctx), "phase1 bad secdata_fwmp rec");
TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST),
VB2_RECOVERY_NOT_REQUESTED, " no recovery");
/* Failures while reading recovery key */
reset_common_data(FOR_PHASE1);
- ctx->flags |= VB2_CONTEXT_RECOVERY_MODE;
+ SET_BOOT_MODE(ctx, VB2_BOOT_MODE_BROKEN_SCREEN, 123);
mock_gbb.h.recovery_key_size = sd->workbuf_size - 1;
mock_gbb.recovery_key.key_size =
mock_gbb.h.recovery_key_size - sizeof(mock_gbb.recovery_key);
@@ -282,60 +319,179 @@
"phase1 rec workbuf key");
TEST_EQ(sd->kernel_key_offset, 0, " workbuf key offset");
TEST_EQ(sd->kernel_key_size, 0, " workbuf key size");
- mock_gbb.h.flags |= VB2_GBB_FLAG_FORCE_MANUAL_RECOVERY;
- *boot_mode = VB2_BOOT_MODE_MANUAL_RECOVERY;
+ SET_BOOT_MODE(ctx, VB2_BOOT_MODE_MANUAL_RECOVERY,
+ VB2_RECOVERY_RO_MANUAL);
TEST_ABORT(vb2api_kernel_phase1(ctx), " fatal for manual recovery");
reset_common_data(FOR_PHASE1);
- ctx->flags |= VB2_CONTEXT_RECOVERY_MODE;
+ SET_BOOT_MODE(ctx, VB2_BOOT_MODE_BROKEN_SCREEN, 123);
mock_read_res_fail_on_call = 1;
TEST_EQ(vb2api_kernel_phase1(ctx), VB2_SUCCESS,
"phase1 rec gbb read key");
TEST_EQ(sd->kernel_key_offset, 0, " workbuf key offset");
TEST_EQ(sd->kernel_key_size, 0, " workbuf key size");
- mock_gbb.h.flags |= VB2_GBB_FLAG_FORCE_MANUAL_RECOVERY;
- *boot_mode = VB2_BOOT_MODE_MANUAL_RECOVERY;
+ SET_BOOT_MODE(ctx, VB2_BOOT_MODE_MANUAL_RECOVERY,
+ VB2_RECOVERY_RO_MANUAL);
mock_read_res_fail_on_call = 1;
TEST_ABORT(vb2api_kernel_phase1(ctx), " fatal for manual recovery");
/* Failures while parsing subkey from firmware preamble */
reset_common_data(FOR_PHASE1);
+ SET_BOOT_MODE(ctx, VB2_BOOT_MODE_NORMAL);
sd->preamble_size = 0;
TEST_EQ(vb2api_kernel_phase1(ctx), VB2_ERROR_API_KPHASE1_PREAMBLE,
"phase1 fw preamble");
}
-static void normal_boot_tests(void)
+static void phase2_tests(void)
{
- reset_common_data(FOR_NORMAL_BOOT);
- mock_vbtlk_expect_fixed = 1;
- TEST_EQ(vb2_normal_boot(ctx), VB2_SUCCESS,
- "vb2_normal_boot() returns VB2_SUCCESS");
+ reset_common_data(FOR_PHASE2);
+ SET_BOOT_MODE(ctx, VB2_BOOT_MODE_NORMAL);
+ TEST_SUCC(vb2api_kernel_phase2(ctx), "Normal mode");
+ TEST_EQ(mock_ec_sync_called, 1, " EC sync");
- reset_common_data(FOR_NORMAL_BOOT);
- mock_vbtlk_expect_fixed = 1;
- mock_vbtlk_retval = VB2_ERROR_MOCK;
- TEST_EQ(vb2_normal_boot(ctx), VB2_ERROR_MOCK,
- "vb2_normal_boot() returns VB2_ERROR_MOCK");
-
- reset_common_data(FOR_NORMAL_BOOT);
+ reset_common_data(FOR_PHASE2);
+ SET_BOOT_MODE(ctx, VB2_BOOT_MODE_NORMAL);
vb2_nv_set(ctx, VB2_NV_DISPLAY_REQUEST, 1);
- TEST_EQ(vb2_normal_boot(ctx), VB2_REQUEST_REBOOT,
- "vb2_normal_boot() reboot to reset NVRAM display request");
+ TEST_EQ(vb2api_kernel_phase2(ctx), VB2_REQUEST_REBOOT,
+ "Normal mode with display request: rebooting");
TEST_EQ(vb2_nv_get(ctx, VB2_NV_DISPLAY_REQUEST), 0,
" display request reset");
- reset_common_data(FOR_NORMAL_BOOT);
+ reset_common_data(FOR_PHASE2);
+ SET_BOOT_MODE(ctx, VB2_BOOT_MODE_DEVELOPER);
+ TEST_SUCC(vb2api_kernel_phase2(ctx), "Developer mode");
+ TEST_EQ(mock_ec_sync_called, 1, " EC sync");
+
+ reset_common_data(FOR_PHASE2);
+ SET_BOOT_MODE(ctx, VB2_BOOT_MODE_DIAGNOSTICS);
+ TEST_SUCC(vb2api_kernel_phase2(ctx), "Diagnostics mode");
+ TEST_EQ(mock_ec_sync_called, 1, " EC sync");
+
+ /* Commit data for recovery mode */
+ reset_common_data(FOR_PHASE2);
+ SET_BOOT_MODE(ctx, VB2_BOOT_MODE_MANUAL_RECOVERY,
+ VB2_RECOVERY_RO_MANUAL);
+ TEST_SUCC(vb2api_kernel_phase2(ctx), "Manual recovery mode");
+ TEST_EQ(mock_commit_data_called, 1, " commit data");
+ TEST_EQ(mock_ec_sync_called, 0, " EC sync");
+
+ reset_common_data(FOR_PHASE2);
+ SET_BOOT_MODE(ctx, VB2_BOOT_MODE_BROKEN_SCREEN, 123);
+ TEST_SUCC(vb2api_kernel_phase2(ctx), "Broken screen mode");
+ TEST_EQ(mock_commit_data_called, 1, " commit data");
+ TEST_EQ(mock_ec_sync_called, 0, " EC sync");
+
+ /* Boot recovery - memory retraining */
+ reset_common_data(FOR_PHASE2);
+ SET_BOOT_MODE(ctx, VB2_BOOT_MODE_MANUAL_RECOVERY,
+ VB2_RECOVERY_TRAIN_AND_REBOOT);
+ TEST_EQ(vb2api_kernel_phase2(ctx), VB2_REQUEST_REBOOT,
+ "Recovery train and reboot");
+
+ /* Clear VB2_NV_DIAG_REQUEST */
+ reset_common_data(FOR_PHASE2);
+ SET_BOOT_MODE(ctx, VB2_BOOT_MODE_NORMAL);
vb2_nv_set(ctx, VB2_NV_DIAG_REQUEST, 1);
- TEST_EQ(vb2_normal_boot(ctx), VB2_REQUEST_REBOOT,
- "vb2_normal_boot() reboot to reset NVRAM diag request");
+ TEST_SUCC(vb2api_kernel_phase2(ctx), "Normal mode with DIAG_REQUEST");
TEST_EQ(vb2_nv_get(ctx, VB2_NV_DIAG_REQUEST), 0,
- " diag request reset");}
+ " clear VB2_NV_DIAG_REQUEST");
+ TEST_EQ(mock_commit_data_called, 1, " commit data");
+
+ reset_common_data(FOR_PHASE2);
+ SET_BOOT_MODE(ctx, VB2_BOOT_MODE_DIAGNOSTICS);
+ vb2_nv_set(ctx, VB2_NV_DIAG_REQUEST, 1);
+ TEST_SUCC(vb2api_kernel_phase2(ctx), "Diagnostics mode");
+ TEST_EQ(vb2_nv_get(ctx, VB2_NV_DIAG_REQUEST), 0,
+ " clear VB2_NV_DIAG_REQUEST");
+ TEST_EQ(mock_commit_data_called, 1, " commit data");
+
+ /* Battery cutoff called after EC sync */
+ reset_common_data(FOR_PHASE2);
+ SET_BOOT_MODE(ctx, VB2_BOOT_MODE_NORMAL);
+ vb2_nv_set(ctx, VB2_NV_BATTERY_CUTOFF_REQUEST, 1);
+ TEST_EQ(vb2api_kernel_phase2(ctx), VB2_REQUEST_SHUTDOWN,
+ "Set VB2_NV_BATTERY_CUTOFF_REQUEST");
+ TEST_EQ(mock_battery_cutoff_called, 1,
+ " battery_cutoff called after EC sync");
+
+ /* Return EC sync error */
+ reset_common_data(FOR_PHASE2);
+ SET_BOOT_MODE(ctx, VB2_BOOT_MODE_NORMAL);
+ mock_ec_sync_retval = VB2_ERROR_MOCK;
+ TEST_EQ(vb2api_kernel_phase2(ctx), VB2_ERROR_MOCK,
+ "Return EC sync error");
+
+ /* Undefined boot mode */
+ reset_common_data(FOR_PHASE2);
+ TEST_EQ(vb2api_kernel_phase2(ctx), VB2_ERROR_ESCAPE_NO_BOOT,
+ "Undefined boot mode");
+}
+
+static void finalize_tests(void)
+{
+ /* Kernel version roll forward */
+ reset_common_data(FOR_FINALIZE);
+ sd->kernel_version = 0x20003;
+ TEST_EQ(vb2api_kernel_finalize(ctx), VB2_SUCCESS,
+ "Kernel version roll forward");
+ TEST_EQ(mock_kernel_version, 0x20003, " kernel version");
+
+ reset_common_data(FOR_FINALIZE);
+ vb2_nv_set(ctx, VB2_NV_FW_RESULT, VB2_FW_RESULT_TRYING);
+ sd->kernel_version = 0x20003;
+ TEST_EQ(vb2api_kernel_finalize(ctx), VB2_SUCCESS,
+ "Don't roll forward kernel when trying new FW");
+ TEST_EQ(mock_kernel_version, 0x10002, " kernel version");
+
+ reset_common_data(FOR_FINALIZE);
+ vb2_nv_set(ctx, VB2_NV_KERNEL_MAX_ROLLFORWARD, 0x30005);
+ sd->kernel_version = 0x40006;
+ TEST_EQ(vb2api_kernel_finalize(ctx), VB2_SUCCESS,
+ "Limit max roll forward");
+ TEST_EQ(mock_kernel_version, 0x30005, " kernel version");
+
+ reset_common_data(FOR_FINALIZE);
+ vb2_nv_set(ctx, VB2_NV_KERNEL_MAX_ROLLFORWARD, 0x10001);
+ sd->kernel_version = 0x40006;
+ TEST_EQ(vb2api_kernel_finalize(ctx), VB2_SUCCESS,
+ "Max roll forward can't rollback");
+ TEST_EQ(mock_kernel_version, 0x10002, " kernel version");
+
+ /* NO_BOOT with EC sync support */
+ reset_common_data(FOR_FINALIZE);
+ ctx->flags |= VB2_CONTEXT_NO_BOOT;
+ ctx->flags |= VB2_CONTEXT_EC_SYNC_SUPPORTED;
+ TEST_EQ(vb2api_kernel_finalize(ctx), VB2_ERROR_ESCAPE_NO_BOOT,
+ "Recovery for NO_BOOT escape");
+ TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST),
+ VB2_RECOVERY_ESCAPE_NO_BOOT, " recovery_reason");
+
+ /* NO_BOOT with EC sync disabled */
+ reset_common_data(FOR_FINALIZE);
+ ctx->flags |= VB2_CONTEXT_NO_BOOT;
+ ctx->flags |= VB2_CONTEXT_EC_SYNC_SUPPORTED;
+ mock_gbb.h.flags |= VB2_GBB_FLAG_DISABLE_EC_SOFTWARE_SYNC;
+ TEST_SUCC(vb2api_kernel_finalize(ctx),
+ "NO_BOOT ignored with gbb DISABLE_EC_SOFTWARE_SYNC");
+
+ /* Normal case with EC sync support */
+ reset_common_data(FOR_FINALIZE);
+ ctx->flags |= VB2_CONTEXT_EC_SYNC_SUPPORTED;
+ TEST_SUCC(vb2api_kernel_finalize(ctx), "Disable VB2_CONTEXT_NO_BOOT");
+
+ /* NO_BOOT without EC sync support */
+ reset_common_data(FOR_FINALIZE);
+ ctx->flags |= VB2_CONTEXT_NO_BOOT;
+ TEST_SUCC(vb2api_kernel_finalize(ctx),
+ "Disable VB2_CONTEXT_EC_SYNC_SUPPORTED");
+}
int main(int argc, char* argv[])
{
phase1_tests();
- normal_boot_tests();
+ phase2_tests();
+ finalize_tests();
return gTestSuccess ? 0 : 255;
}
diff --git a/tests/vb2_keyblock_fuzzer.c b/tests/vb2_keyblock_fuzzer.c
index 2aa83e1..cd211c4 100644
--- a/tests/vb2_keyblock_fuzzer.c
+++ b/tests/vb2_keyblock_fuzzer.c
@@ -9,7 +9,6 @@
#include "2rsa.h"
#include "2rsa_private.h"
#include "2secdata.h"
-#include "vboot_test.h"
static struct vb2_context *ctx;
static uint8_t workbuf[VB2_FIRMWARE_WORKBUF_RECOMMENDED_SIZE]
diff --git a/tests/vboot_kernel2_tests.c b/tests/vb2_load_kernel2_tests.c
similarity index 78%
rename from tests/vboot_kernel2_tests.c
rename to tests/vb2_load_kernel2_tests.c
index 5fc66f1..dfb06fb 100644
--- a/tests/vboot_kernel2_tests.c
+++ b/tests/vb2_load_kernel2_tests.c
@@ -10,8 +10,8 @@
#include "2misc.h"
#include "2nvstorage.h"
#include "2secdata.h"
-#include "load_kernel_fw.h"
-#include "test_common.h"
+#include "common/boot_mode.h"
+#include "common/tests.h"
#include "vboot_api.h"
#define MAX_MOCK_KERNELS 10
@@ -20,7 +20,7 @@
/* Internal struct to simulate a stream for sector-based disks */
struct disk_stream {
/* Disk handle */
- VbExDiskHandle_t handle;
+ vb2ex_disk_handle_t handle;
/* Next sector to read */
uint64_t sector;
@@ -47,10 +47,9 @@
static struct vb2_workbuf wb;
static uint8_t workbuf[VB2_KERNEL_WORKBUF_RECOMMENDED_SIZE]
__attribute__((aligned(VB2_WORKBUF_ALIGN)));
-static enum vb2_boot_mode *boot_mode;
-static VbSelectAndLoadKernelParams lkp;
-static VbDiskInfo disk_info;
+static struct vb2_kernel_params lkp;
+static struct vb2_disk_info disk_info;
static struct vb2_keyblock kbh;
static struct vb2_kernel_preamble kph;
static uint8_t kernel_buffer[80000];
@@ -59,8 +58,6 @@
static int kernel_count;
static struct mock_kernel *cur_kernel;
-static int mock_tpm_set_mode_calls;
-
static void add_mock_kernel(uint64_t sector, vb2_error_t rv)
{
if (kernel_count >= ARRAY_SIZE(kernels)) {
@@ -83,8 +80,8 @@
vb2_secdata_kernel_init(ctx);
ctx->flags = VB2_CONTEXT_RECOVERY_MODE;
- boot_mode = (enum vb2_boot_mode *)&ctx->boot_mode;
- *boot_mode = VB2_BOOT_MODE_MANUAL_RECOVERY;
+ SET_BOOT_MODE(ctx, VB2_BOOT_MODE_MANUAL_RECOVERY,
+ VB2_RECOVERY_RO_MANUAL);
sd = vb2_get_sd(ctx);
sd->kernel_version_secdata = 0xabcdef | (1 << 24);
@@ -92,12 +89,11 @@
memset(&lkp, 0, sizeof(lkp));
lkp.kernel_buffer = kernel_buffer;
lkp.kernel_buffer_size = sizeof(kernel_buffer);
- lkp.disk_handle = (VbExDiskHandle_t)1;
memset(&disk_info, 0, sizeof(disk_info));
disk_info.bytes_per_lba = 512;
disk_info.lba_count = 1024;
- disk_info.handle = lkp.disk_handle;
+ disk_info.handle = (vb2ex_disk_handle_t)1;
memset(&kbh, 0, sizeof(kbh));
kbh.data_key.key_version = 2;
@@ -118,13 +114,11 @@
memset(&kernels, 0, sizeof(kernels));
kernel_count = 0;
cur_kernel = NULL;
-
- mock_tpm_set_mode_calls = 0;
}
/* Mocks */
-vb2_error_t VbExStreamOpen(VbExDiskHandle_t handle, uint64_t lba_start,
+vb2_error_t VbExStreamOpen(vb2ex_disk_handle_t handle, uint64_t lba_start,
uint64_t lba_count, VbExStream_t *stream)
{
struct disk_stream *s;
@@ -248,12 +242,6 @@
return cur_kernel->rv;
}
-vb2_error_t vb2ex_tpm_set_mode(enum vb2_tpm_mode mode_val)
-{
- mock_tpm_set_mode_calls++;
- return VB2_SUCCESS;
-}
-
/* Make sure nothing tested here ever calls this directly. */
void vb2api_fail(struct vb2_context *c, uint8_t reason, uint8_t subcode)
{
@@ -268,55 +256,57 @@
disk_info.bytes_per_lba = KBUF_SIZE;
disk_info.lba_count = 1;
add_mock_kernel(0, VB2_SUCCESS);
- TEST_SUCC(LoadMiniOsKernel(ctx, &lkp, &disk_info, 0),
+ TEST_SUCC(vb2api_load_minios_kernel(ctx, &lkp, &disk_info, 0),
"{valid kernel}");
- TEST_EQ(mock_tpm_set_mode_calls, 1,
- " TPM disabled");
+ TEST_PTR_EQ(lkp.disk_handle, disk_info.handle,
+ " fill disk_handle when success");
reset_common_data();
disk_info.bytes_per_lba = KBUF_SIZE;
disk_info.lba_count = 1;
- TEST_EQ(LoadMiniOsKernel(ctx, &lkp, &disk_info, 0),
+ TEST_EQ(vb2api_load_minios_kernel(ctx, &lkp, &disk_info, 0),
VB2_ERROR_LK_NO_KERNEL_FOUND, "{no kernel}");
- TEST_EQ(mock_tpm_set_mode_calls, 0,
- " TPM not disabled");
reset_common_data();
disk_info.bytes_per_lba = KBUF_SIZE;
disk_info.lba_count = 2;
add_mock_kernel(1, VB2_SUCCESS);
- TEST_SUCC(LoadMiniOsKernel(ctx, &lkp, &disk_info, 0),
+ TEST_SUCC(vb2api_load_minios_kernel(ctx, &lkp, &disk_info, 0),
"{no kernel, valid kernel}");
TEST_EQ(cur_kernel->sector, 1, " select kernel");
+ TEST_PTR_EQ(lkp.disk_handle, disk_info.handle,
+ " fill disk_handle when success");
reset_common_data();
disk_info.bytes_per_lba = KBUF_SIZE;
disk_info.lba_count = 2;
add_mock_kernel(0, VB2_ERROR_MOCK);
add_mock_kernel(1, VB2_SUCCESS);
- TEST_SUCC(LoadMiniOsKernel(ctx, &lkp, &disk_info, 0),
+ TEST_SUCC(vb2api_load_minios_kernel(ctx, &lkp, &disk_info, 0),
"{invalid kernel, valid kernel}");
TEST_EQ(cur_kernel->sector, 1, " select second kernel");
+ TEST_PTR_EQ(lkp.disk_handle, disk_info.handle,
+ " fill disk_handle when success");
reset_common_data();
disk_info.bytes_per_lba = KBUF_SIZE;
disk_info.lba_count = 2;
add_mock_kernel(0, VB2_ERROR_MOCK);
add_mock_kernel(1, VB2_ERROR_MOCK);
- TEST_EQ(LoadMiniOsKernel(ctx, &lkp, &disk_info, 0),
+ TEST_EQ(vb2api_load_minios_kernel(ctx, &lkp, &disk_info, 0),
VB2_ERROR_LK_NO_KERNEL_FOUND,
"{invalid kernel, invalid kernel}");
- TEST_EQ(mock_tpm_set_mode_calls, 0,
- " TPM not disabled");
reset_common_data();
disk_info.bytes_per_lba = KBUF_SIZE;
disk_info.lba_count = 2;
add_mock_kernel(0, VB2_SUCCESS);
add_mock_kernel(1, VB2_SUCCESS);
- TEST_SUCC(LoadMiniOsKernel(ctx, &lkp, &disk_info, 0),
+ TEST_SUCC(vb2api_load_minios_kernel(ctx, &lkp, &disk_info, 0),
"{valid kernel, valid kernel} minios_priority=0");
TEST_EQ(cur_kernel->sector, 0, " select first kernel");
+ TEST_PTR_EQ(lkp.disk_handle, disk_info.handle,
+ " fill disk_handle when success");
reset_common_data();
disk_info.bytes_per_lba = KBUF_SIZE;
@@ -324,19 +314,23 @@
add_mock_kernel(0, VB2_SUCCESS);
add_mock_kernel(1, VB2_SUCCESS);
vb2_nv_set(ctx, VB2_NV_MINIOS_PRIORITY, 1);
- TEST_SUCC(LoadMiniOsKernel(ctx, &lkp, &disk_info, 0),
+ TEST_SUCC(vb2api_load_minios_kernel(ctx, &lkp, &disk_info, 0),
"{valid kernel, valid kernel} minios_priority=1");
TEST_EQ(cur_kernel->sector, 1, " select second kernel");
+ TEST_PTR_EQ(lkp.disk_handle, disk_info.handle,
+ " fill disk_handle when success");
reset_common_data();
disk_info.bytes_per_lba = KBUF_SIZE;
disk_info.lba_count = 2;
add_mock_kernel(0, VB2_SUCCESS);
add_mock_kernel(1, VB2_SUCCESS);
- TEST_SUCC(LoadMiniOsKernel(ctx, &lkp, &disk_info,
- VB_MINIOS_FLAG_NON_ACTIVE),
+ TEST_SUCC(vb2api_load_minios_kernel(ctx, &lkp, &disk_info,
+ VB2_MINIOS_FLAG_NON_ACTIVE),
"{valid kernel, valid kernel} minios_priority=0 non-active");
TEST_EQ(cur_kernel->sector, 1, " select second kernel");
+ TEST_PTR_EQ(lkp.disk_handle, disk_info.handle,
+ " fill disk_handle when success");
reset_common_data();
disk_info.bytes_per_lba = KBUF_SIZE;
@@ -344,8 +338,8 @@
add_mock_kernel(0, VB2_ERROR_MOCK);
add_mock_kernel(1, VB2_SUCCESS);
vb2_nv_set(ctx, VB2_NV_MINIOS_PRIORITY, 1);
- TEST_EQ(LoadMiniOsKernel(ctx, &lkp, &disk_info,
- VB_MINIOS_FLAG_NON_ACTIVE),
+ TEST_EQ(vb2api_load_minios_kernel(ctx, &lkp, &disk_info,
+ VB2_MINIOS_FLAG_NON_ACTIVE),
VB2_ERROR_LK_NO_KERNEL_FOUND,
"{invalid kernel, valid kernel} minios_priority=1 non-active");
@@ -353,7 +347,7 @@
disk_info.bytes_per_lba = VB2_KEYBLOCK_MAGIC_SIZE;
disk_info.lba_count = 4;
add_mock_kernel(1, VB2_SUCCESS);
- TEST_EQ(LoadMiniOsKernel(ctx, &lkp, &disk_info, 0),
+ TEST_EQ(vb2api_load_minios_kernel(ctx, &lkp, &disk_info, 0),
VB2_ERROR_LK_NO_KERNEL_FOUND,
"valid kernel header near start of disk (disk too small)");
@@ -361,7 +355,7 @@
disk_info.bytes_per_lba = VB2_KEYBLOCK_MAGIC_SIZE;
disk_info.lba_count = 1000;
add_mock_kernel(999, VB2_SUCCESS);
- TEST_EQ(LoadMiniOsKernel(ctx, &lkp, &disk_info, 0),
+ TEST_EQ(vb2api_load_minios_kernel(ctx, &lkp, &disk_info, 0),
VB2_ERROR_LK_NO_KERNEL_FOUND,
"valid kernel header near end of disk");
@@ -369,36 +363,46 @@
disk_info.bytes_per_lba = 1024;
disk_info.lba_count = 128;
add_mock_kernel(63, VB2_SUCCESS);
- TEST_SUCC(LoadMiniOsKernel(ctx, &lkp, &disk_info, 0),
+ TEST_SUCC(vb2api_load_minios_kernel(ctx, &lkp, &disk_info, 0),
"start/end overlap assuming >128 MB search range (start)");
+ TEST_PTR_EQ(lkp.disk_handle, disk_info.handle,
+ " fill disk_handle when success");
reset_common_data();
disk_info.bytes_per_lba = 1024;
disk_info.lba_count = 128;
add_mock_kernel(64, VB2_SUCCESS);
- TEST_SUCC(LoadMiniOsKernel(ctx, &lkp, &disk_info, 0),
+ TEST_SUCC(vb2api_load_minios_kernel(ctx, &lkp, &disk_info, 0),
"start/end overlap assuming >128 MB search range (end)");
+ TEST_PTR_EQ(lkp.disk_handle, disk_info.handle,
+ " fill disk_handle when success");
reset_common_data();
disk_info.bytes_per_lba = 128;
disk_info.lba_count = 1024;
add_mock_kernel(3, VB2_SUCCESS);
- TEST_SUCC(LoadMiniOsKernel(ctx, &lkp, &disk_info, 0),
+ TEST_SUCC(vb2api_load_minios_kernel(ctx, &lkp, &disk_info, 0),
"kernel at last sector in batch assuming 512 KB batches");
+ TEST_PTR_EQ(lkp.disk_handle, disk_info.handle,
+ " fill disk_handle when success");
reset_common_data();
disk_info.bytes_per_lba = 256;
disk_info.lba_count = 1024;
add_mock_kernel(3, VB2_SUCCESS);
- TEST_SUCC(LoadMiniOsKernel(ctx, &lkp, &disk_info, 0),
+ TEST_SUCC(vb2api_load_minios_kernel(ctx, &lkp, &disk_info, 0),
"kernel at last sector in batch assuming 1 MB batches");
+ TEST_PTR_EQ(lkp.disk_handle, disk_info.handle,
+ " fill disk_handle when success");
reset_common_data();
disk_info.bytes_per_lba = 512;
disk_info.lba_count = 1024;
add_mock_kernel(3, VB2_SUCCESS);
- TEST_SUCC(LoadMiniOsKernel(ctx, &lkp, &disk_info, 0),
+ TEST_SUCC(vb2api_load_minios_kernel(ctx, &lkp, &disk_info, 0),
"kernel at last sector in batch assuming 2 MB batches");
+ TEST_PTR_EQ(lkp.disk_handle, disk_info.handle,
+ " fill disk_handle when success");
reset_common_data();
kbh.keyblock_flags = VB2_KEYBLOCK_FLAG_DEVELOPER_0
@@ -407,8 +411,10 @@
disk_info.bytes_per_lba = KBUF_SIZE;
disk_info.lba_count = 2;
add_mock_kernel(0, VB2_SUCCESS);
- TEST_SUCC(LoadMiniOsKernel(ctx, &lkp, &disk_info, 0),
+ TEST_SUCC(vb2api_load_minios_kernel(ctx, &lkp, &disk_info, 0),
"kernel with minios keyblock flag");
+ TEST_PTR_EQ(lkp.disk_handle, disk_info.handle,
+ " fill disk_handle when success");
reset_common_data();
kbh.keyblock_flags = VB2_KEYBLOCK_FLAG_DEVELOPER_0
@@ -417,7 +423,7 @@
disk_info.bytes_per_lba = KBUF_SIZE;
disk_info.lba_count = 2;
add_mock_kernel(0, VB2_SUCCESS);
- TEST_EQ(LoadMiniOsKernel(ctx, &lkp, &disk_info, 0),
+ TEST_EQ(vb2api_load_minios_kernel(ctx, &lkp, &disk_info, 0),
VB2_ERROR_LK_NO_KERNEL_FOUND,
"kernel with !minios keyblock flag");
@@ -427,7 +433,7 @@
add_mock_kernel(0, VB2_SUCCESS);
sd->kernel_version_secdata = 5 << 24;
kph.kernel_version = 4;
- TEST_EQ(LoadMiniOsKernel(ctx, &lkp, &disk_info, 0),
+ TEST_EQ(vb2api_load_minios_kernel(ctx, &lkp, &disk_info, 0),
VB2_ERROR_LK_NO_KERNEL_FOUND,
"kernel version too old");
@@ -437,7 +443,7 @@
add_mock_kernel(0, VB2_SUCCESS);
sd->kernel_version_secdata = 5 << 24;
kph.kernel_version = 0x100;
- TEST_EQ(LoadMiniOsKernel(ctx, &lkp, &disk_info, 0),
+ TEST_EQ(vb2api_load_minios_kernel(ctx, &lkp, &disk_info, 0),
VB2_ERROR_LK_NO_KERNEL_FOUND,
"kernel version greater than 0xff");
@@ -447,8 +453,10 @@
add_mock_kernel(0, VB2_SUCCESS);
sd->kernel_version_secdata = 5 << 24;
kph.kernel_version = 6;
- TEST_SUCC(LoadMiniOsKernel(ctx, &lkp, &disk_info, 0),
- "newer kernel version");
+ TEST_SUCC(vb2api_load_minios_kernel(ctx, &lkp, &disk_info, 0),
+ "newer kernel version");
+ TEST_PTR_EQ(lkp.disk_handle, disk_info.handle,
+ " fill disk_handle when success");
}
int main(void)
diff --git a/tests/vboot_kernel_tests.c b/tests/vb2_load_kernel_tests.c
similarity index 66%
rename from tests/vboot_kernel_tests.c
rename to tests/vb2_load_kernel_tests.c
index 1f77cc5..bb6f348 100644
--- a/tests/vboot_kernel_tests.c
+++ b/tests/vb2_load_kernel_tests.c
@@ -13,9 +13,9 @@
#include "2secdata_struct.h"
#include "cgptlib.h"
#include "cgptlib_internal.h"
+#include "common/boot_mode.h"
+#include "common/tests.h"
#include "gpt.h"
-#include "load_kernel_fw.h"
-#include "test_common.h"
#include "vboot_api.h"
/* Mock kernel partition */
@@ -40,8 +40,8 @@
static int gpt_flag_external;
static struct vb2_gbb_header gbb;
-static VbSelectAndLoadKernelParams lkp;
-static VbDiskInfo disk_info;
+static struct vb2_kernel_params lkp;
+static struct vb2_disk_info disk_info;
static struct vb2_keyblock kbh;
static struct vb2_kernel_preamble kph;
static struct vb2_secdata_fwmp *fwmp;
@@ -51,7 +51,6 @@
static struct vb2_context *ctx;
static struct vb2_shared_data *sd;
static struct vb2_packed_key mock_key;
-static enum vb2_boot_mode *boot_mode;
/**
* Reset mock data (for use before each test)
@@ -76,13 +75,12 @@
memset(&lkp, 0, sizeof(lkp));
lkp.kernel_buffer = kernel_buffer;
lkp.kernel_buffer_size = sizeof(kernel_buffer);
- lkp.disk_handle = (VbExDiskHandle_t)1;
memset(&disk_info, 0, sizeof(disk_info));
disk_info.bytes_per_lba = 512;
disk_info.streaming_lba_count = 1024;
disk_info.lba_count = 1024;
- disk_info.handle = lkp.disk_handle;
+ disk_info.handle = (vb2ex_disk_handle_t)1;
memset(&kbh, 0, sizeof(kbh));
kbh.data_key.key_version = 2;
@@ -115,8 +113,7 @@
fwmp = (struct vb2_secdata_fwmp *)ctx->secdata_fwmp;
memcpy(&fwmp->dev_key_hash, mock_digest, sizeof(fwmp->dev_key_hash));
- boot_mode = (enum vb2_boot_mode *)&ctx->boot_mode;
- *boot_mode = VB2_BOOT_MODE_NORMAL;
+ SET_BOOT_MODE(ctx, VB2_BOOT_MODE_NORMAL);
// TODO: more workbuf fields - flags, secdata_firmware
@@ -156,7 +153,7 @@
return VB2_SUCCESS;
}
-vb2_error_t VbExDiskRead(VbExDiskHandle_t h, uint64_t lba_start,
+vb2_error_t VbExDiskRead(vb2ex_disk_handle_t h, uint64_t lba_start,
uint64_t lba_count, void *buffer)
{
if ((int)lba_start == disk_read_to_fail)
@@ -165,7 +162,7 @@
return VB2_SUCCESS;
}
-int AllocAndReadGptData(VbExDiskHandle_t disk_handle, GptData *gptdata)
+int AllocAndReadGptData(vb2ex_disk_handle_t disk_handle, GptData *gptdata)
{
return GPT_SUCCESS;
}
@@ -197,7 +194,7 @@
return GPT_SUCCESS;
}
-int WriteAndFreeGptData(VbExDiskHandle_t disk_handle, GptData *gptdata)
+int WriteAndFreeGptData(vb2ex_disk_handle_t disk_handle, GptData *gptdata)
{
return GPT_SUCCESS;
}
@@ -279,31 +276,34 @@
TEST_TRUE(0, " called vb2api_fail()");
}
-static void TestLoadKernel(int expect_retval, const char *test_name)
+static void test_load_kernel(vb2_error_t expect_retval, const char *test_name)
{
- TEST_EQ(LoadKernel(ctx, &lkp, &disk_info), expect_retval, test_name);
+ TEST_EQ(vb2api_load_kernel(ctx, &lkp, &disk_info), expect_retval,
+ test_name);
+ if (expect_retval == VB2_SUCCESS)
+ TEST_PTR_EQ(lkp.disk_handle, disk_info.handle,
+ " fill disk_handle when success");
}
/**
- * Trivial invalid calls to LoadKernel()
+ * Trivial invalid calls to vb2api_load_kernel()
*/
-static void InvalidParamsTest(void)
+static void invalid_params_tests(void)
{
ResetMocks();
gpt_init_fail = 1;
- TestLoadKernel(VB2_ERROR_LK_NO_KERNEL_FOUND, "Bad GPT");
+ test_load_kernel(VB2_ERROR_LK_NO_KERNEL_FOUND, "Bad GPT");
/* This causes the stream open call to fail */
ResetMocks();
- lkp.disk_handle = NULL;
disk_info.handle = NULL;
- TestLoadKernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND, "Bad disk handle");
+ test_load_kernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND, "Bad disk handle");
}
-static void LoadKernelTest(void)
+static void load_kernel_tests(void)
{
ResetMocks();
- TestLoadKernel(0, "First kernel good");
+ test_load_kernel(VB2_SUCCESS, "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");
@@ -314,312 +314,311 @@
ResetMocks();
mock_parts[1].start = 300;
mock_parts[1].size = 150;
- TestLoadKernel(0, "Two good kernels");
+ test_load_kernel(VB2_SUCCESS, "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;
- TestLoadKernel(VB2_ERROR_LK_NO_KERNEL_FOUND, "No kernels");
+ test_load_kernel(VB2_ERROR_LK_NO_KERNEL_FOUND, "No kernels");
/* Skip kernels which are too small */
ResetMocks();
mock_parts[0].size = 10;
- TestLoadKernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND, "Too small");
+ test_load_kernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND, "Too small");
ResetMocks();
disk_read_to_fail = 100;
- TestLoadKernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
- "Fail reading kernel start");
+ test_load_kernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
+ "Fail reading kernel start");
ResetMocks();
keyblock_verify_fail = 1;
- TestLoadKernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
- "Fail key block sig");
+ test_load_kernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
+ "Fail key block sig");
/* In dev mode, fail if hash is bad too */
ResetMocks();
- ctx->flags |= VB2_CONTEXT_DEVELOPER_MODE;
- *boot_mode = VB2_BOOT_MODE_DEVELOPER;
+ SET_BOOT_MODE(ctx, VB2_BOOT_MODE_DEVELOPER);
keyblock_verify_fail = 2;
- TestLoadKernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
- "Fail key block dev hash");
+ test_load_kernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
+ "Fail key block dev hash");
/* But just bad sig is ok */
ResetMocks();
- ctx->flags |= VB2_CONTEXT_DEVELOPER_MODE;
- *boot_mode = VB2_BOOT_MODE_DEVELOPER;
+ SET_BOOT_MODE(ctx, VB2_BOOT_MODE_DEVELOPER);
keyblock_verify_fail = 1;
- TestLoadKernel(0, "Succeed keyblock dev sig");
+ test_load_kernel(VB2_SUCCESS, "Succeed keyblock dev sig");
TEST_EQ(sd->flags & VB2_SD_FLAG_KERNEL_SIGNED, 0, " use hash");
/* In dev mode and requiring signed kernel, fail if sig is bad */
ResetMocks();
- ctx->flags |= VB2_CONTEXT_DEVELOPER_MODE;
- *boot_mode = VB2_BOOT_MODE_DEVELOPER;
+ SET_BOOT_MODE(ctx, VB2_BOOT_MODE_DEVELOPER);
vb2_nv_set(ctx, VB2_NV_DEV_BOOT_SIGNED_ONLY, 1);
keyblock_verify_fail = 1;
- TestLoadKernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
- "Fail key block dev sig");
+ test_load_kernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
+ "Fail key block dev sig");
ResetMocks();
- ctx->flags |= VB2_CONTEXT_DEVELOPER_MODE;
- *boot_mode = VB2_BOOT_MODE_DEVELOPER;
+ SET_BOOT_MODE(ctx, VB2_BOOT_MODE_DEVELOPER);
fwmp->flags |= VB2_SECDATA_FWMP_DEV_ENABLE_OFFICIAL_ONLY;
keyblock_verify_fail = 1;
- TestLoadKernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
- "Fail key block dev sig fwmp");
+ test_load_kernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
+ "Fail key block dev sig fwmp");
/* Check keyblock flags */
ResetMocks();
kbh.keyblock_flags = VB2_KEYBLOCK_FLAG_RECOVERY_0
| VB2_KEYBLOCK_FLAG_DEVELOPER_1
| VB2_KEYBLOCK_FLAG_MINIOS_0;
- TestLoadKernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
- "Keyblock dev flag mismatch");
+ test_load_kernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
+ "Keyblock dev flag mismatch");
ResetMocks();
kbh.keyblock_flags = VB2_KEYBLOCK_FLAG_RECOVERY_1
| VB2_KEYBLOCK_FLAG_DEVELOPER_0
| VB2_KEYBLOCK_FLAG_MINIOS_0;
- TestLoadKernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
- "Keyblock rec flag mismatch");
+ test_load_kernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
+ "Keyblock rec flag mismatch");
ResetMocks();
kbh.keyblock_flags = VB2_KEYBLOCK_FLAG_RECOVERY_0
| VB2_KEYBLOCK_FLAG_DEVELOPER_0
| VB2_KEYBLOCK_FLAG_MINIOS_1;
- TestLoadKernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
- "Keyblock minios flag mismatch");
+ test_load_kernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
+ "Keyblock minios flag mismatch");
ResetMocks();
- ctx->flags |= VB2_CONTEXT_RECOVERY_MODE;
- *boot_mode = VB2_BOOT_MODE_MANUAL_RECOVERY;
+ SET_BOOT_MODE(ctx, VB2_BOOT_MODE_MANUAL_RECOVERY,
+ VB2_RECOVERY_RO_MANUAL);
kbh.keyblock_flags = VB2_KEYBLOCK_FLAG_RECOVERY_1
| VB2_KEYBLOCK_FLAG_DEVELOPER_1
| VB2_KEYBLOCK_FLAG_MINIOS_0;
- TestLoadKernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
- "Keyblock recdev flag mismatch");
+ test_load_kernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
+ "Keyblock recdev flag mismatch");
ResetMocks();
- ctx->flags |= VB2_CONTEXT_RECOVERY_MODE;
- *boot_mode = VB2_BOOT_MODE_MANUAL_RECOVERY;
+ SET_BOOT_MODE(ctx, VB2_BOOT_MODE_MANUAL_RECOVERY,
+ VB2_RECOVERY_RO_MANUAL);
kbh.keyblock_flags = VB2_KEYBLOCK_FLAG_RECOVERY_1
| VB2_KEYBLOCK_FLAG_DEVELOPER_0
| VB2_KEYBLOCK_FLAG_MINIOS_0;
- TestLoadKernel(0, "Keyblock rec flag okay");
+ test_load_kernel(VB2_SUCCESS, "Keyblock rec flag okay");
ResetMocks();
- ctx->flags |= VB2_CONTEXT_RECOVERY_MODE | VB2_CONTEXT_DEVELOPER_MODE;
- *boot_mode = VB2_BOOT_MODE_MANUAL_RECOVERY;
+ SET_BOOT_MODE(ctx, VB2_BOOT_MODE_MANUAL_RECOVERY,
+ VB2_RECOVERY_RO_MANUAL);
+ ctx->flags |= VB2_CONTEXT_DEVELOPER_MODE;
kbh.keyblock_flags = VB2_KEYBLOCK_FLAG_RECOVERY_1
| VB2_KEYBLOCK_FLAG_DEVELOPER_0
| VB2_KEYBLOCK_FLAG_MINIOS_0;
- TestLoadKernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
- "Keyblock rec!dev flag mismatch");
+ test_load_kernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
+ "Keyblock rec!dev flag mismatch");
ResetMocks();
- ctx->flags |= VB2_CONTEXT_RECOVERY_MODE | VB2_CONTEXT_DEVELOPER_MODE;
- *boot_mode = VB2_BOOT_MODE_MANUAL_RECOVERY;
+ SET_BOOT_MODE(ctx, VB2_BOOT_MODE_MANUAL_RECOVERY,
+ VB2_RECOVERY_RO_MANUAL);
+ ctx->flags |= VB2_CONTEXT_DEVELOPER_MODE;
kbh.keyblock_flags = VB2_KEYBLOCK_FLAG_RECOVERY_1
| VB2_KEYBLOCK_FLAG_DEVELOPER_1
| VB2_KEYBLOCK_FLAG_MINIOS_0;
- TestLoadKernel(0, "Keyblock recdev flag okay");
+ test_load_kernel(VB2_SUCCESS, "Keyblock recdev flag okay");
/* Check keyblock flags (dev mode + signed kernel required) */
ResetMocks();
- ctx->flags |= VB2_CONTEXT_DEVELOPER_MODE;
- *boot_mode = VB2_BOOT_MODE_DEVELOPER;
+ SET_BOOT_MODE(ctx, VB2_BOOT_MODE_DEVELOPER);
vb2_nv_set(ctx, VB2_NV_DEV_BOOT_SIGNED_ONLY, 1);
kbh.keyblock_flags = VB2_KEYBLOCK_FLAG_RECOVERY_1
| VB2_KEYBLOCK_FLAG_DEVELOPER_0
| VB2_KEYBLOCK_FLAG_MINIOS_0;
- TestLoadKernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
- "Keyblock dev flag mismatch (signed kernel required)");
+ test_load_kernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
+ "Keyblock dev flag mismatch (signed kernel required)");
ResetMocks();
- ctx->flags |= VB2_CONTEXT_DEVELOPER_MODE;
- *boot_mode = VB2_BOOT_MODE_DEVELOPER;
+ SET_BOOT_MODE(ctx, VB2_BOOT_MODE_DEVELOPER);
fwmp->flags |= VB2_SECDATA_FWMP_DEV_ENABLE_OFFICIAL_ONLY;
kbh.keyblock_flags = VB2_KEYBLOCK_FLAG_RECOVERY_1
| VB2_KEYBLOCK_FLAG_DEVELOPER_0
| VB2_KEYBLOCK_FLAG_MINIOS_0;
- TestLoadKernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
- "Keyblock dev flag mismatch (signed kernel required)");
+ test_load_kernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
+ "Keyblock dev flag mismatch (signed kernel required)");
ResetMocks();
- ctx->flags |= VB2_CONTEXT_DEVELOPER_MODE;
- *boot_mode = VB2_BOOT_MODE_DEVELOPER;
+ SET_BOOT_MODE(ctx, VB2_BOOT_MODE_DEVELOPER);
fwmp->flags |= VB2_SECDATA_FWMP_DEV_ENABLE_OFFICIAL_ONLY;
kbh.keyblock_flags = VB2_KEYBLOCK_FLAG_RECOVERY_0
| VB2_KEYBLOCK_FLAG_DEVELOPER_0
| VB2_KEYBLOCK_FLAG_MINIOS_1;
- TestLoadKernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
- "Keyblock dev flag mismatch (signed kernel required)");
+ test_load_kernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
+ "Keyblock dev flag mismatch (signed kernel required)");
ResetMocks();
- ctx->flags |= VB2_CONTEXT_DEVELOPER_MODE;
- *boot_mode = VB2_BOOT_MODE_DEVELOPER;
+ SET_BOOT_MODE(ctx, VB2_BOOT_MODE_DEVELOPER);
vb2_nv_set(ctx, VB2_NV_DEV_BOOT_SIGNED_ONLY, 1);
kbh.keyblock_flags = VB2_KEYBLOCK_FLAG_RECOVERY_0
| VB2_KEYBLOCK_FLAG_DEVELOPER_1
| VB2_KEYBLOCK_FLAG_MINIOS_0;
- TestLoadKernel(0, "Keyblock dev flag okay (signed kernel required)");
+ test_load_kernel(VB2_SUCCESS,
+ "Keyblock dev flag okay (signed kernel required)");
/* Check kernel key version */
ResetMocks();
kbh.data_key.key_version = 1;
- TestLoadKernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
- "Keyblock kernel key rollback");
+ test_load_kernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
+ "Keyblock kernel key rollback");
ResetMocks();
kbh.data_key.key_version = 0x10000;
- TestLoadKernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
- "Keyblock kernel key version too big");
+ test_load_kernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
+ "Keyblock kernel key version too big");
ResetMocks();
kbh.data_key.key_version = 3;
- TestLoadKernel(0, "Keyblock version roll forward");
+ test_load_kernel(VB2_SUCCESS, "Keyblock version roll forward");
TEST_EQ(sd->kernel_version, 0x30001, " SD version");
ResetMocks();
kbh.data_key.key_version = 3;
mock_parts[1].start = 300;
mock_parts[1].size = 150;
- TestLoadKernel(0, "Two kernels roll forward");
+ test_load_kernel(VB2_SUCCESS, "Two kernels roll forward");
TEST_EQ(mock_part_next, 2, " read both");
TEST_EQ(sd->kernel_version, 0x30001, " SD version");
ResetMocks();
kbh.data_key.key_version = 1;
- *boot_mode = VB2_BOOT_MODE_DEVELOPER;
- TestLoadKernel(0, "Key version ignored in dev mode");
+ SET_BOOT_MODE(ctx, VB2_BOOT_MODE_DEVELOPER);
+ test_load_kernel(VB2_SUCCESS, "Key version ignored in dev mode");
ResetMocks();
kbh.data_key.key_version = 1;
- *boot_mode = VB2_BOOT_MODE_MANUAL_RECOVERY;
- TestLoadKernel(0, "Key version ignored in rec mode");
+ SET_BOOT_MODE(ctx, VB2_BOOT_MODE_MANUAL_RECOVERY,
+ VB2_RECOVERY_RO_MANUAL);
+ test_load_kernel(VB2_SUCCESS, "Key version ignored in rec mode");
ResetMocks();
unpack_key_fail = 2;
- TestLoadKernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND, "Bad data key");
+ test_load_kernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND, "Bad data key");
ResetMocks();
preamble_verify_fail = 1;
- TestLoadKernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND, "Bad preamble");
+ test_load_kernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND, "Bad preamble");
ResetMocks();
kph.kernel_version = 0;
- TestLoadKernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
- "Kernel version rollback");
+ test_load_kernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
+ "Kernel version rollback");
ResetMocks();
kph.kernel_version = 0;
- *boot_mode = VB2_BOOT_MODE_DEVELOPER;
- TestLoadKernel(0, "Kernel version ignored in dev mode");
+ SET_BOOT_MODE(ctx, VB2_BOOT_MODE_DEVELOPER);
+ test_load_kernel(VB2_SUCCESS, "Kernel version ignored in dev mode");
ResetMocks();
kph.kernel_version = 0;
- *boot_mode = VB2_BOOT_MODE_MANUAL_RECOVERY;
- TestLoadKernel(0, "Kernel version ignored in rec mode");
+ SET_BOOT_MODE(ctx, VB2_BOOT_MODE_MANUAL_RECOVERY,
+ VB2_RECOVERY_RO_MANUAL);
+ test_load_kernel(VB2_SUCCESS, "Kernel version ignored in rec mode");
/* Check kernel version (dev mode + signed kernel required) */
ResetMocks();
kbh.data_key.key_version = 0;
- *boot_mode = VB2_BOOT_MODE_DEVELOPER;
+ SET_BOOT_MODE(ctx, VB2_BOOT_MODE_DEVELOPER);
vb2_nv_set(ctx, VB2_NV_DEV_BOOT_SIGNED_ONLY, 1);
- TestLoadKernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
- "Keyblock key version checked in dev mode "
- "(signed kernel required)");
+ test_load_kernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
+ "Keyblock key version checked in dev mode "
+ "(signed kernel required)");
ResetMocks();
kbh.data_key.key_version = 0;
- *boot_mode = VB2_BOOT_MODE_DEVELOPER;
+ SET_BOOT_MODE(ctx, VB2_BOOT_MODE_DEVELOPER);
fwmp->flags |= VB2_SECDATA_FWMP_DEV_ENABLE_OFFICIAL_ONLY;
- TestLoadKernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
- "Keyblock key version checked in dev mode "
- "(signed kernel required)");
+ test_load_kernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
+ "Keyblock key version checked in dev mode "
+ "(signed kernel required)");
/* Check developer key hash - bad */
ResetMocks();
- *boot_mode = VB2_BOOT_MODE_DEVELOPER;
+ SET_BOOT_MODE(ctx, VB2_BOOT_MODE_DEVELOPER);
fwmp->flags |= VB2_SECDATA_FWMP_DEV_USE_KEY_HASH;
fwmp->dev_key_hash[0]++;
- TestLoadKernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
- "Fail keyblock dev fwmp hash");
+ test_load_kernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
+ "Fail keyblock dev fwmp hash");
/* Check developer key hash - bad (recovery mode) */
ResetMocks();
- *boot_mode = VB2_BOOT_MODE_MANUAL_RECOVERY;
+ SET_BOOT_MODE(ctx, VB2_BOOT_MODE_MANUAL_RECOVERY,
+ VB2_RECOVERY_RO_MANUAL);
fwmp->flags |= VB2_SECDATA_FWMP_DEV_USE_KEY_HASH;
fwmp->dev_key_hash[0]++;
- TestLoadKernel(0, "Bad keyblock dev fwmp hash ignored in rec mode");
+ test_load_kernel(VB2_SUCCESS,
+ "Bad keyblock dev fwmp hash ignored in rec mode");
/* Check developer key hash - good */
ResetMocks();
- *boot_mode = VB2_BOOT_MODE_DEVELOPER;
+ SET_BOOT_MODE(ctx, VB2_BOOT_MODE_DEVELOPER);
fwmp->flags |= VB2_SECDATA_FWMP_DEV_USE_KEY_HASH;
- TestLoadKernel(0, "Good keyblock dev fwmp hash");
+ test_load_kernel(VB2_SUCCESS, "Good keyblock dev fwmp hash");
ResetMocks();
kph.preamble_size |= 0x07;
- TestLoadKernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
- "Kernel body offset");
+ test_load_kernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
+ "Kernel body offset");
ResetMocks();
kph.preamble_size += 65536;
- TestLoadKernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
- "Kernel body offset huge");
+ test_load_kernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
+ "Kernel body offset huge");
/* Check getting kernel load address from header */
ResetMocks();
kph.body_load_address = (size_t)kernel_buffer;
lkp.kernel_buffer = NULL;
- TestLoadKernel(0, "Get load address from preamble");
+ test_load_kernel(VB2_SUCCESS, "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;
- TestLoadKernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
- "Kernel too big for buffer");
+ test_load_kernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
+ "Kernel too big for buffer");
ResetMocks();
mock_parts[0].size = 130;
- TestLoadKernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
- "Kernel too big for partition");
+ test_load_kernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
+ "Kernel too big for partition");
ResetMocks();
kph.body_signature.data_size = 8192;
- TestLoadKernel(0, "Kernel tiny");
+ test_load_kernel(VB2_SUCCESS, "Kernel tiny");
ResetMocks();
disk_read_to_fail = 228;
- TestLoadKernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
- "Fail reading kernel data");
+ test_load_kernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
+ "Fail reading kernel data");
ResetMocks();
verify_data_fail = 1;
- TestLoadKernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND, "Bad data");
+ test_load_kernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND, "Bad data");
/* Check that EXTERNAL_GPT flag makes it down */
ResetMocks();
- disk_info.flags |= VB_DISK_FLAG_EXTERNAL_GPT;
- TestLoadKernel(0, "Succeed external GPT");
+ disk_info.flags |= VB2_DISK_FLAG_EXTERNAL_GPT;
+ test_load_kernel(VB2_SUCCESS, "Succeed external GPT");
TEST_EQ(gpt_flag_external, 1, "GPT was external");
/* Check recovery from unreadble primary GPT */
ResetMocks();
disk_read_to_fail = 1;
- TestLoadKernel(0, "Can't read disk");
+ test_load_kernel(VB2_SUCCESS, "Can't read disk");
}
int main(void)
{
- InvalidParamsTest();
- LoadKernelTest();
+ invalid_params_tests();
+ load_kernel_tests();
return gTestSuccess ? 0 : 255;
}
diff --git a/tests/vb2_misc2_tests.c b/tests/vb2_misc2_tests.c
new file mode 100644
index 0000000..403e2f6
--- /dev/null
+++ b/tests/vb2_misc2_tests.c
@@ -0,0 +1,128 @@
+/* Copyright 2022 The ChromiumOS Authors.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ *
+ * Tests for vb2_set_boot_mode.
+ */
+
+#include "2api.h"
+#include "2common.h"
+#include "2misc.h"
+#include "2nvstorage.h"
+#include "common/tests.h"
+
+/* Mock data */
+
+static uint8_t workbuf[VB2_KERNEL_WORKBUF_RECOMMENDED_SIZE]
+ __attribute__((aligned(VB2_WORKBUF_ALIGN)));
+static struct vb2_context *ctx;
+static struct vb2_shared_data *sd;
+static struct vb2_gbb_header gbb;
+
+static int mock_diagnostic_ui_enabled;
+
+/* Mock functions */
+
+struct vb2_gbb_header *vb2_get_gbb(struct vb2_context *c)
+{
+ return &gbb;
+}
+
+int vb2api_diagnostic_ui_enabled(struct vb2_context *c)
+{
+ return mock_diagnostic_ui_enabled;
+}
+
+static void reset_common_data(void)
+{
+ memset(workbuf, 0xaa, sizeof(workbuf));
+
+ memset(&gbb, 0, sizeof(gbb));
+
+ TEST_SUCC(vb2api_init(workbuf, sizeof(workbuf), &ctx),
+ "vb2api_init failed");
+ sd = vb2_get_sd(ctx);
+
+ vb2_nv_init(ctx);
+
+ mock_diagnostic_ui_enabled = 0;
+}
+
+static void set_boot_mode_tests(void)
+{
+ /* Normal boot */
+ reset_common_data();
+ vb2_set_boot_mode(ctx);
+ TEST_EQ(ctx->boot_mode, VB2_BOOT_MODE_NORMAL, "Normal boot");
+
+ /* Check that NV_DIAG_REQUEST triggers diagnostic mode */
+ reset_common_data();
+ mock_diagnostic_ui_enabled = 1;
+ vb2_nv_set(ctx, VB2_NV_DIAG_REQUEST, 1);
+ vb2_set_boot_mode(ctx);
+ TEST_EQ(ctx->boot_mode, VB2_BOOT_MODE_DIAGNOSTICS,
+ "Normal boot with diag UI enabled");
+
+ reset_common_data();
+ vb2_nv_set(ctx, VB2_NV_DIAG_REQUEST, 1);
+ vb2_set_boot_mode(ctx);
+ TEST_EQ(ctx->boot_mode, VB2_BOOT_MODE_NORMAL,
+ "Normal boot with diag UI disabled");
+
+ /* Developer boot */
+ reset_common_data();
+ ctx->flags |= VB2_CONTEXT_DEVELOPER_MODE;
+ sd->flags |= VB2_SD_FLAG_DEV_MODE_ENABLED;
+ vb2_set_boot_mode(ctx);
+ TEST_EQ(ctx->boot_mode, VB2_BOOT_MODE_DEVELOPER, "Dev boot");
+
+ /* Recovery boot */
+ reset_common_data();
+ sd->recovery_reason = 123;
+ ctx->flags |= VB2_CONTEXT_RECOVERY_MODE;
+ vb2_set_boot_mode(ctx);
+ TEST_EQ(ctx->boot_mode, VB2_BOOT_MODE_BROKEN_SCREEN, "Broken screen");
+
+ reset_common_data();
+ sd->recovery_reason = VB2_RECOVERY_RO_MANUAL;
+ ctx->flags |= VB2_CONTEXT_RECOVERY_MODE;
+ gbb.flags |= VB2_GBB_FLAG_FORCE_MANUAL_RECOVERY;
+ vb2_set_boot_mode(ctx);
+ TEST_EQ(ctx->boot_mode, VB2_BOOT_MODE_MANUAL_RECOVERY,
+ "Manual recovery: forced by GBB flags");
+
+ reset_common_data();
+ sd->recovery_reason = VB2_RECOVERY_RO_MANUAL;
+ ctx->flags |= VB2_CONTEXT_FORCE_RECOVERY_MODE;
+ ctx->flags |= VB2_CONTEXT_EC_TRUSTED;
+ vb2_set_boot_mode(ctx);
+ TEST_EQ(ctx->boot_mode, VB2_BOOT_MODE_MANUAL_RECOVERY,
+ "Manual recovery: physical rec switch");
+
+ reset_common_data();
+ ctx->flags |= VB2_CONTEXT_EC_TRUSTED;
+ vb2_set_boot_mode(ctx);
+ TEST_NEQ(ctx->boot_mode, VB2_BOOT_MODE_MANUAL_RECOVERY,
+ "VB2_CONTEXT_FORCE_RECOVERY_MODE is not set");
+
+ reset_common_data();
+ ctx->flags |= VB2_CONTEXT_FORCE_RECOVERY_MODE;
+ ctx->flags |= VB2_CONTEXT_NO_BOOT;
+ ctx->flags |= VB2_CONTEXT_EC_TRUSTED;
+ vb2_set_boot_mode(ctx);
+ TEST_NEQ(ctx->boot_mode, VB2_BOOT_MODE_MANUAL_RECOVERY,
+ "Block manual recovery if NO_BOOT");
+
+ reset_common_data();
+ ctx->flags |= VB2_CONTEXT_FORCE_RECOVERY_MODE;
+ vb2_set_boot_mode(ctx);
+ TEST_NEQ(ctx->boot_mode, VB2_BOOT_MODE_MANUAL_RECOVERY,
+ "Block manual recovery for untrusted EC");
+}
+
+int main(void)
+{
+ set_boot_mode_tests();
+
+ return gTestSuccess ? 0 : 255;
+}
diff --git a/tests/vb2_misc_tests.c b/tests/vb2_misc_tests.c
index 99f8bae..4add8d0 100644
--- a/tests/vb2_misc_tests.c
+++ b/tests/vb2_misc_tests.c
@@ -11,7 +11,8 @@
#include "2nvstorage.h"
#include "2secdata.h"
#include "2sysincludes.h"
-#include "test_common.h"
+#include "common/boot_mode.h"
+#include "common/tests.h"
/* Common context for tests */
static uint8_t workbuf[VB2_FIRMWARE_WORKBUF_RECOMMENDED_SIZE]
@@ -22,7 +23,6 @@
static struct vb2_shared_data *sd;
static struct vb2_gbb_header gbb;
static struct vb2_secdata_fwmp *fwmp;
-static enum vb2_boot_mode *boot_mode;
/* Mocked function data */
static enum vb2_resource_index mock_resource_index;
@@ -54,8 +54,7 @@
mock_tpm_clear_called = 0;
mock_tpm_clear_retval = VB2_SUCCESS;
- boot_mode = (enum vb2_boot_mode *)&ctx->boot_mode;
- *boot_mode = VB2_BOOT_MODE_NORMAL;
+ SET_BOOT_MODE(ctx, VB2_BOOT_MODE_NORMAL);
};
/* Mocked functions */
@@ -655,7 +654,8 @@
" dev mode flag not set");
reset_common_data();
- *boot_mode = VB2_BOOT_MODE_MANUAL_RECOVERY;
+ SET_BOOT_MODE(ctx, VB2_BOOT_MODE_MANUAL_RECOVERY,
+ VB2_RECOVERY_RO_MANUAL);
TEST_SUCC(vb2api_enable_developer_mode(ctx),
"vb2api_enable_developer_mode - success");
TEST_NEQ(vb2_secdata_firmware_get(ctx, VB2_SECDATA_FIRMWARE_FLAGS) &
@@ -664,17 +664,16 @@
/* secdata_firmware not initialized, aborts */
reset_common_data();
- *boot_mode = VB2_BOOT_MODE_MANUAL_RECOVERY;
+ SET_BOOT_MODE(ctx, VB2_BOOT_MODE_MANUAL_RECOVERY,
+ VB2_RECOVERY_RO_MANUAL);
sd->status &= ~VB2_SD_STATUS_SECDATA_FIRMWARE_INIT;
sd->status |= VB2_SD_STATUS_RECOVERY_DECIDED;
- TEST_ABORT(vb2api_enable_developer_mode(ctx),
- "secdata_firmware no init, enable dev mode aborted");
+ TEST_SUCC(vb2api_enable_developer_mode(ctx),
+ "secdata_firmware no init, enable dev mode ignored");
sd->status |= VB2_SD_STATUS_SECDATA_FIRMWARE_INIT;
TEST_EQ(vb2_secdata_firmware_get(ctx, VB2_SECDATA_FIRMWARE_FLAGS) &
VB2_SECDATA_FIRMWARE_FLAG_DEV_MODE, 0,
" dev mode flag not set");
- TEST_EQ(vb2_nv_get(ctx, VB2_NV_DEV_BOOT_EXTERNAL), 0,
- " NV_DEV_BOOT_EXTERNAL not set");
}
static void tpm_clear_tests(void)
@@ -816,9 +815,7 @@
/* Manual recovery */
reset_common_data();
- *boot_mode = VB2_BOOT_MODE_MANUAL_RECOVERY;
- sd->recovery_reason = 4;
- ctx->flags |= VB2_CONTEXT_RECOVERY_MODE;
+ SET_BOOT_MODE(ctx, VB2_BOOT_MODE_MANUAL_RECOVERY, 4);
vb2_nv_set(ctx, VB2_NV_RECOVERY_REQUEST, 5);
vb2_nv_set(ctx, VB2_NV_RECOVERY_SUBCODE, 13);
vb2_clear_recovery(ctx);
@@ -829,9 +826,7 @@
/* Broken screen */
reset_common_data();
- *boot_mode = VB2_BOOT_MODE_BROKEN_SCREEN;
- sd->recovery_reason = 4;
- ctx->flags |= VB2_CONTEXT_RECOVERY_MODE;
+ SET_BOOT_MODE(ctx, VB2_BOOT_MODE_BROKEN_SCREEN, 4);
vb2_nv_set(ctx, VB2_NV_RECOVERY_REQUEST, 5);
vb2_nv_set(ctx, VB2_NV_RECOVERY_SUBCODE, 13);
vb2_clear_recovery(ctx);
diff --git a/tests/vb2_nvstorage_tests.c b/tests/vb2_nvstorage_tests.c
index 94bcfca..8734f72 100644
--- a/tests/vb2_nvstorage_tests.c
+++ b/tests/vb2_nvstorage_tests.c
@@ -16,7 +16,7 @@
#include "2nvstorage_fields.h"
#include "2nvstorage.h"
#include "2sysincludes.h"
-#include "test_common.h"
+#include "common/tests.h"
/* Single NV storage field to test */
struct nv_field {
diff --git a/tests/vb2_preamble_fuzzer.c b/tests/vb2_preamble_fuzzer.c
index 186ee9f..92c240e 100644
--- a/tests/vb2_preamble_fuzzer.c
+++ b/tests/vb2_preamble_fuzzer.c
@@ -9,7 +9,6 @@
#include "2rsa.h"
#include "2rsa_private.h"
#include "2secdata.h"
-#include "vboot_test.h"
static struct vb2_context *ctx;
static uint8_t workbuf[VB2_FIRMWARE_WORKBUF_RECOMMENDED_SIZE]
diff --git a/tests/vb2_recovery_reasons_tests.c b/tests/vb2_recovery_reasons_tests.c
index 5def4d2..8d05862 100644
--- a/tests/vb2_recovery_reasons_tests.c
+++ b/tests/vb2_recovery_reasons_tests.c
@@ -6,7 +6,7 @@
*/
#include "2recovery_reasons.h"
-#include "test_common.h"
+#include "common/tests.h"
static void get_recovery_reason_string_tests(void)
{
diff --git a/tests/vb2_rsa_tests.sh b/tests/vb2_rsa_tests.sh
index 903d38d..58d99b2 100755
--- a/tests/vb2_rsa_tests.sh
+++ b/tests/vb2_rsa_tests.sh
@@ -16,24 +16,24 @@
function test_signatures {
algorithmcounter=0
- for keylen in ${key_lengths[@]}
+ for keylen in "${key_lengths[@]}"
do
- for hashalgo in ${hash_algos[@]}
+ for hashalgo in "${hash_algos[@]}"
do
echo -e "For ${COL_YELLOW}RSA-$keylen and $hashalgo${COL_STOP}:"
- ${BIN_DIR}/verify_data $algorithmcounter \
- ${TESTKEY_DIR}/key_rsa${keylen}.keyb \
- ${TEST_FILE}.rsa${keylen}_${hashalgo}.sig \
- ${TEST_FILE}
- if [ $? -ne 0 ]
+ if ! "${BIN_DIR}/verify_data" "$algorithmcounter" \
+ "${TESTKEY_DIR}/key_rsa${keylen}.keyb" \
+ "${TEST_FILE}.rsa${keylen}_${hashalgo}.sig" \
+ "${TEST_FILE}"
then
return_code=255
fi
- let algorithmcounter=algorithmcounter+1
+ algorithmcounter=$((algorithmcounter + 1))
done
done
echo -e "Peforming ${COL_YELLOW}PKCS #1 v1.5 Padding Tests${COL_STOP}..."
- ${TEST_DIR}/vb20_rsa_padding_tests ${TESTKEY_DIR}/rsa_padding_test_pubkey.keyb
+ "${TEST_DIR}/vb20_rsa_padding_tests" \
+ "${TESTKEY_DIR}/rsa_padding_test_pubkey.keyb"
}
check_test_keys
@@ -41,4 +41,3 @@
test_signatures
exit $return_code
-
diff --git a/tests/vb2_rsa_utility_tests.c b/tests/vb2_rsa_utility_tests.c
index 4ad5a95..057b4b0 100644
--- a/tests/vb2_rsa_utility_tests.c
+++ b/tests/vb2_rsa_utility_tests.c
@@ -10,11 +10,10 @@
#include "2rsa.h"
#include "2rsa_private.h"
#include "2sysincludes.h"
+#include "common/tests.h"
#include "file_keys.h"
#include "rsa_padding_test.h"
-#include "test_common.h"
#include "vboot_api.h"
-#include "vboot_test.h"
/**
* Test RSA utility funcs
diff --git a/tests/vb2_secdata_firmware_tests.c b/tests/vb2_secdata_firmware_tests.c
index c1b0a73..0520cc0 100644
--- a/tests/vb2_secdata_firmware_tests.c
+++ b/tests/vb2_secdata_firmware_tests.c
@@ -12,7 +12,7 @@
#include "2secdata.h"
#include "2secdata_struct.h"
#include "2sysincludes.h"
-#include "test_common.h"
+#include "common/tests.h"
static uint8_t workbuf[VB2_FIRMWARE_WORKBUF_RECOMMENDED_SIZE]
__attribute__((aligned(VB2_WORKBUF_ALIGN)));
diff --git a/tests/vb2_secdata_fwmp_tests.c b/tests/vb2_secdata_fwmp_tests.c
index 79b0f55..eabe671 100644
--- a/tests/vb2_secdata_fwmp_tests.c
+++ b/tests/vb2_secdata_fwmp_tests.c
@@ -9,7 +9,7 @@
#include "2misc.h"
#include "2secdata.h"
#include "2secdata_struct.h"
-#include "test_common.h"
+#include "common/tests.h"
static uint8_t workbuf[VB2_FIRMWARE_WORKBUF_RECOMMENDED_SIZE]
__attribute__((aligned(VB2_WORKBUF_ALIGN)));
diff --git a/tests/vb2_secdata_kernel_tests.c b/tests/vb2_secdata_kernel_tests.c
index dc41f1a..a84e04e 100644
--- a/tests/vb2_secdata_kernel_tests.c
+++ b/tests/vb2_secdata_kernel_tests.c
@@ -12,8 +12,7 @@
#include "2secdata.h"
#include "2secdata_struct.h"
#include "2sysincludes.h"
-#include "test_common.h"
-#include "vboot_test.h"
+#include "common/tests.h"
static uint8_t workbuf[VB2_FIRMWARE_WORKBUF_RECOMMENDED_SIZE]
__attribute__((aligned(VB2_WORKBUF_ALIGN)));
diff --git a/tests/vb2_sha256_x86_tests.c b/tests/vb2_sha256_x86_tests.c
index 06ba12e..e17d395 100644
--- a/tests/vb2_sha256_x86_tests.c
+++ b/tests/vb2_sha256_x86_tests.c
@@ -10,8 +10,8 @@
#include "2api.h"
#include "2sha.h"
+#include "common/tests.h"
#include "sha_test_vectors.h"
-#include "test_common.h"
vb2_error_t vb2_digest_buffer(const uint8_t *buf, uint32_t size,
enum vb2_hash_algorithm hash_alg, uint8_t *digest,
diff --git a/tests/vb2_sha_api_tests.c b/tests/vb2_sha_api_tests.c
index cb58f7b..6ed0b74 100644
--- a/tests/vb2_sha_api_tests.c
+++ b/tests/vb2_sha_api_tests.c
@@ -8,7 +8,7 @@
#include "2return_codes.h"
#include "2sha.h"
#include "2sysincludes.h"
-#include "test_common.h"
+#include "common/tests.h"
uint8_t mock_sha1[] = {0x1, 0x3, 0x5, 0x2, 0x4, 0x6, 0xa, 0xb, 0xc, 0xd,
0xd, 0xe, 0xa, 0xd, 0xb, 0xe, 0xe, 0xf, 0x0, 0xf0};
diff --git a/tests/vb2_sha_tests.c b/tests/vb2_sha_tests.c
index a14af65..40cf42f 100644
--- a/tests/vb2_sha_tests.c
+++ b/tests/vb2_sha_tests.c
@@ -11,8 +11,8 @@
#include "2rsa.h"
#include "2sha.h"
#include "2sysincludes.h"
+#include "common/tests.h"
#include "sha_test_vectors.h"
-#include "test_common.h"
static void sha1_tests(void)
{
diff --git a/tests/vboot_api_kernel4_tests.c b/tests/vboot_api_kernel4_tests.c
deleted file mode 100644
index 60d87c6..0000000
--- a/tests/vboot_api_kernel4_tests.c
+++ /dev/null
@@ -1,343 +0,0 @@
-/* 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.
- *
- * Tests for vboot_api_kernel, part 4 - select and load kernel
- */
-
-#include "2api.h"
-#include "2common.h"
-#include "2misc.h"
-#include "2nvstorage.h"
-#include "2secdata.h"
-#include "2sysincludes.h"
-#include "host_common.h"
-#include "load_kernel_fw.h"
-#include "test_common.h"
-#include "tlcl.h"
-#include "tss_constants.h"
-#include "vboot_struct.h"
-#include "vboot_test.h"
-
-/* Mock data */
-
-static uint8_t workbuf[VB2_KERNEL_WORKBUF_RECOMMENDED_SIZE]
- __attribute__((aligned(VB2_WORKBUF_ALIGN)));
-static struct vb2_context *ctx;
-static struct vb2_shared_data *sd;
-static VbSelectAndLoadKernelParams kparams;
-static struct vb2_gbb_header gbb;
-
-static uint32_t kernel_version;
-static uint32_t new_version;
-static vb2_error_t vbboot_retval;
-static int commit_data_called;
-static vb2_error_t secdata_kernel_init_retval;
-static vb2_error_t secdata_fwmp_init_retval;
-static vb2_error_t kernel_phase1_retval;
-static uint32_t current_recovery_reason;
-static uint32_t expected_recovery_reason;
-
-static int mock_diagnostic_ui_enabled;
-
-static void reset_common_data(void)
-{
- memset(&kparams, 0, sizeof(kparams));
-
- memset(&gbb, 0, sizeof(gbb));
- gbb.major_version = VB2_GBB_MAJOR_VER;
- gbb.minor_version = VB2_GBB_MINOR_VER;
- gbb.flags = 0;
-
- TEST_SUCC(vb2api_init(workbuf, sizeof(workbuf), &ctx),
- "vb2api_init failed");
- sd = vb2_get_sd(ctx);
- sd->flags |= VB2_SD_FLAG_DISPLAY_AVAILABLE;
- ctx->flags |= VB2_CONTEXT_NO_SECDATA_FWMP;
- sd->preamble_size = 1;
-
- vb2_nv_init(ctx);
- vb2_nv_set(ctx, VB2_NV_KERNEL_MAX_ROLLFORWARD, 0xffffffff);
- commit_data_called = 0;
-
- kernel_version = new_version = 0x10002;
- vbboot_retval = VB2_SUCCESS;
- secdata_kernel_init_retval = VB2_SUCCESS;
- secdata_fwmp_init_retval = VB2_SUCCESS;
- kernel_phase1_retval = VB2_SUCCESS;
- current_recovery_reason = 0;
- expected_recovery_reason = 0;
-
- mock_diagnostic_ui_enabled = 0;
-
- sd->status |= VB2_SD_STATUS_SECDATA_KERNEL_INIT;
- sd->status |= VB2_SD_STATUS_SECDATA_FWMP_INIT;
-}
-
-static void test_slk(vb2_error_t retval, int recovery_reason, const char *desc)
-{
- if (sd->recovery_reason)
- ctx->flags |= VB2_CONTEXT_RECOVERY_MODE;
-
- expected_recovery_reason = recovery_reason;
- /* The VbSelectAndLoadKernel directly leverages the value at
- ctx->boot_mode, so we have to call vb2_set_boot_mode first. */
- vb2_set_boot_mode(ctx);
- TEST_EQ(VbSelectAndLoadKernel(ctx, &kparams), retval, desc);
- TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST),
- recovery_reason, " recovery reason");
-}
-
-/* Mock functions */
-
-struct vb2_gbb_header *vb2_get_gbb(struct vb2_context *c)
-{
- return &gbb;
-}
-
-vb2_error_t vb2api_kernel_phase1(struct vb2_context *c)
-{
- sd->kernel_version_secdata = kernel_version;
- sd->kernel_version = kernel_version;
- return kernel_phase1_retval;
-}
-
-vb2_error_t vb2ex_commit_data(struct vb2_context *c)
-{
- current_recovery_reason = vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST);
- commit_data_called = 1;
- return VB2_SUCCESS;
-}
-
-vb2_error_t vb2_secdata_fwmp_init(struct vb2_context *c)
-{
- return secdata_fwmp_init_retval;
-}
-
-void vb2_secdata_kernel_set(struct vb2_context *c,
- enum vb2_secdata_kernel_param param,
- uint32_t value)
-{
- kernel_version = value;
-}
-
-vb2_error_t VbTryLoadKernel(struct vb2_context *c, uint32_t disk_flags)
-{
- sd->kernel_version = new_version;
-
- if (vbboot_retval == -1)
- return VB2_ERROR_MOCK;
-
- return vbboot_retval;
-}
-
-static vb2_error_t boot_dev(struct vb2_context *c)
-{
- if (vbboot_retval == -2)
- return VB2_ERROR_MOCK;
-
- return vbboot_retval;
-}
-
-vb2_error_t vb2ex_developer_ui(struct vb2_context *c)
-{
- return boot_dev(c);
-}
-
-static void rec_check(struct vb2_context *c)
-{
- TEST_EQ(current_recovery_reason, expected_recovery_reason,
- " recovery reason");
- TEST_TRUE(commit_data_called, " commit data");
-}
-
-vb2_error_t vb2ex_manual_recovery_ui(struct vb2_context *c)
-{
- rec_check(c);
- if (vbboot_retval == -3)
- return VB2_ERROR_MOCK;
- return vbboot_retval;
-}
-
-vb2_error_t vb2ex_broken_screen_ui(struct vb2_context *c)
-{
- rec_check(c);
- if (vbboot_retval == -4)
- return VB2_ERROR_MOCK;
- return vbboot_retval;
-}
-
-vb2_error_t vb2ex_diagnostic_ui(struct vb2_context *c)
-{
- if (vbboot_retval == -5)
- return VB2_ERROR_MOCK;
-
- return vbboot_retval;
-}
-
-int vb2api_diagnostic_ui_enabled(struct vb2_context *c)
-{
- return mock_diagnostic_ui_enabled;
-}
-
-vb2_error_t vb2ex_tpm_set_mode(enum vb2_tpm_mode mode_val)
-{
- return VB2_SUCCESS;
-}
-
-/* Tests */
-
-static void select_and_load_kernel_tests(void)
-{
- /* Normal boot */
- reset_common_data();
- test_slk(0, 0, "Normal");
- TEST_EQ(kernel_version, 0x10002, " version");
- TEST_NEQ(sd->status & VB2_SD_STATUS_EC_SYNC_COMPLETE, 0,
- " EC sync complete");
- TEST_FALSE(commit_data_called, " no commit data");
-
- /* Check EC sync toggling */
- reset_common_data();
- ctx->flags |= VB2_CONTEXT_EC_SYNC_SUPPORTED;
- gbb.flags |= VB2_GBB_FLAG_DISABLE_EC_SOFTWARE_SYNC;
- test_slk(0, 0, "EC sync disabled by GBB");
- TEST_NEQ(sd->status & VB2_SD_STATUS_EC_SYNC_COMPLETE, 0,
- " EC sync complete");
-
- reset_common_data();
- ctx->flags |= VB2_CONTEXT_EC_SYNC_SUPPORTED;
- test_slk(0, 0, "Normal with EC sync");
- TEST_NEQ(sd->status & VB2_SD_STATUS_EC_SYNC_COMPLETE, 0,
- " EC sync complete");
-
- reset_common_data();
- new_version = 0x20003;
- test_slk(0, 0, "Roll forward");
- TEST_EQ(kernel_version, 0x20003, " version");
-
- reset_common_data();
- vb2_nv_set(ctx, VB2_NV_FW_RESULT, VB2_FW_RESULT_TRYING);
- new_version = 0x20003;
- test_slk(0, 0, "Don't roll forward kernel when trying new FW");
- TEST_EQ(kernel_version, 0x10002, " version");
-
- reset_common_data();
- vb2_nv_set(ctx, VB2_NV_KERNEL_MAX_ROLLFORWARD, 0x30005);
- new_version = 0x40006;
- test_slk(0, 0, "Limit max roll forward");
- TEST_EQ(kernel_version, 0x30005, " version");
-
- reset_common_data();
- vb2_nv_set(ctx, VB2_NV_KERNEL_MAX_ROLLFORWARD, 0x10001);
- new_version = 0x40006;
- test_slk(0, 0, "Max roll forward can't rollback");
- TEST_EQ(kernel_version, 0x10002, " version");
-
- /* Boot normal */
- reset_common_data();
- vbboot_retval = -1;
- test_slk(VB2_ERROR_MOCK, 0, "Normal boot bad");
-
- /* Check that NV_DIAG_REQUEST triggers diagnostic UI */
- reset_common_data();
- mock_diagnostic_ui_enabled = 1;
- vb2_nv_set(ctx, VB2_NV_DIAG_REQUEST, 1);
- vbboot_retval = -5;
- test_slk(VB2_ERROR_MOCK, 0,
- "Normal boot with diag enabled");
- TEST_EQ(vb2_nv_get(ctx, VB2_NV_DIAG_REQUEST), 0,
- " diag not requested");
-
- reset_common_data();
- vb2_nv_set(ctx, VB2_NV_DIAG_REQUEST, 1);
- test_slk(VB2_REQUEST_REBOOT, 0,
- "Normal boot with diag disabled (reboot to unset)");
-
- /* Boot normal - phase1 failure */
- reset_common_data();
- kernel_phase1_retval = VB2_ERROR_MOCK;
- test_slk(VB2_ERROR_MOCK, 0, "Normal phase1 failure");
-
- /* Recovery - VB2_ERROR_ESCAPE_NO_BOOT */
- reset_common_data();
- ctx->flags |= VB2_CONTEXT_NO_BOOT;
- ctx->flags |= VB2_CONTEXT_EC_SYNC_SUPPORTED;
- test_slk(VB2_ERROR_ESCAPE_NO_BOOT,
- VB2_RECOVERY_ESCAPE_NO_BOOT, "Recovery for NO_BOOT escape");
-
- /* Boot normal - VB2_ERROR_ESCAPE_NO_BOOT */
- reset_common_data();
- ctx->flags |= VB2_CONTEXT_NO_BOOT;
- ctx->flags |= VB2_CONTEXT_EC_SYNC_SUPPORTED;
- gbb.flags |= VB2_GBB_FLAG_DISABLE_EC_SOFTWARE_SYNC;
- test_slk(VB2_SUCCESS, 0, "DISABLE_EC_SOFTWARE_SYNC ignores NO_BOOT");
-
- /* Boot dev */
- reset_common_data();
- ctx->flags |= VB2_CONTEXT_DEVELOPER_MODE;
- vbboot_retval = -2;
- test_slk(VB2_ERROR_MOCK, 0, "Dev boot bad");
- TEST_FALSE(commit_data_called, " no commit data");
-
- reset_common_data();
- ctx->flags |= VB2_CONTEXT_DEVELOPER_MODE;
- new_version = 0x20003;
- test_slk(0, 0, "Dev doesn't roll forward");
- TEST_EQ(kernel_version, 0x10002, " version");
-
- /* Boot dev - phase1 failure */
- reset_common_data();
- ctx->flags |= VB2_CONTEXT_DEVELOPER_MODE;
- kernel_phase1_retval = VB2_ERROR_MOCK;
- test_slk(VB2_ERROR_MOCK, 0, "Dev phase1 failure");
-
- /* Boot recovery */
- reset_common_data();
- sd->recovery_reason = 123;
- vbboot_retval = -4;
- test_slk(VB2_ERROR_MOCK, 0, "Recovery boot bad");
- TEST_TRUE(commit_data_called, " commit data");
-
- reset_common_data();
- sd->recovery_reason = 123;
- new_version = 0x20003;
- test_slk(0, 0, "Recovery doesn't roll forward");
- TEST_EQ(kernel_version, 0x10002, " version");
- TEST_TRUE(commit_data_called, " commit data");
-
- /* Boot recovery - phase1 failure */
- reset_common_data();
- sd->recovery_reason = 123;
- kernel_phase1_retval = VB2_ERROR_MOCK;
- test_slk(VB2_ERROR_MOCK, 0, "Recovery phase1 failure");
- TEST_FALSE(commit_data_called, " no commit data");
-
- /* Boot recovery - memory retraining */
- reset_common_data();
- sd->recovery_reason = VB2_RECOVERY_TRAIN_AND_REBOOT;
- test_slk(VB2_REQUEST_REBOOT, 0, "Recovery train and reboot");
- TEST_FALSE(commit_data_called, " no commit data");
-
- /* Boot BROKEN recovery */
- reset_common_data();
- sd->recovery_reason = 123;
- vb2_nv_set(ctx, VB2_NV_RECOVERY_SUBCODE, 13);
- test_slk(0, 0, "BROKEN recovery");
- TEST_TRUE(commit_data_called, " commit data");
-
- /* Boot manual recovery */
- reset_common_data();
- sd->recovery_reason = VB2_RECOVERY_RO_MANUAL;
- vb2_nv_set(ctx, VB2_NV_RECOVERY_SUBCODE, 13);
- ctx->flags &= VB2_CONTEXT_FORCE_RECOVERY_MODE;
- test_slk(0, 0, "Manual recovery");
- TEST_TRUE(commit_data_called, " commit data");
-}
-
-int main(void)
-{
- select_and_load_kernel_tests();
-
- return gTestSuccess ? 0 : 255;
-}
diff --git a/tests/vboot_api_kernel_tests.c b/tests/vboot_api_kernel_tests.c
deleted file mode 100644
index b66c432..0000000
--- a/tests/vboot_api_kernel_tests.c
+++ /dev/null
@@ -1,642 +0,0 @@
-/* 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.
- *
- * Tests for VbTryLoadKernel()
- */
-
-#include "2common.h"
-#include "2misc.h"
-#include "2nvstorage.h"
-#include "2sysincludes.h"
-#include "load_kernel_fw.h"
-#include "test_common.h"
-#include "vboot_api.h"
-#include "vboot_test.h"
-
-#define MAX_TEST_DISKS 10
-#define DEFAULT_COUNT -1
-
-typedef struct {
- uint64_t bytes_per_lba;
- uint64_t lba_count;
- uint32_t flags;
- const char *diskname;
-} disk_desc_t;
-
-typedef struct {
- const char *name;
-
- /* inputs for test case */
- uint32_t ctx_flags;
- uint32_t want_flags;
- vb2_error_t diskgetinfo_return_val;
- disk_desc_t disks_to_provide[MAX_TEST_DISKS];
- int disk_count_to_return;
- vb2_error_t loadkernel_return_val[MAX_TEST_DISKS];
- uint8_t external_expected[MAX_TEST_DISKS];
-
- /* outputs from test */
- uint32_t expected_recovery_request_val;
- const char *expected_to_find_disk;
- const char *expected_to_load_disk;
- uint32_t expected_return_val;
-
-} test_case_t;
-
-/****************************************************************************/
-/* Test cases */
-
-static const char pickme[] = "correct choice";
-#define DONT_CARE ((const char *)42)
-
-test_case_t normal_tests[] = {
- {
- .name = "first drive (removable)",
- .ctx_flags = 0,
- .want_flags = VB_DISK_FLAG_REMOVABLE | VB_DISK_FLAG_FIXED,
- .disks_to_provide = {
- {4096, 100, VB_DISK_FLAG_REMOVABLE, pickme},
- {4096, 100, VB_DISK_FLAG_FIXED, "holygrail"},
- },
- .disk_count_to_return = DEFAULT_COUNT,
- .diskgetinfo_return_val = VB2_SUCCESS,
- .loadkernel_return_val = {0},
- .external_expected = {0},
-
- .expected_recovery_request_val = VB2_RECOVERY_NOT_REQUESTED,
- .expected_to_find_disk = pickme,
- .expected_to_load_disk = pickme,
- .expected_return_val = VB2_SUCCESS
- },
- {
- .name = "first drive (fixed)",
- .ctx_flags = 0,
- .want_flags = VB_DISK_FLAG_REMOVABLE | VB_DISK_FLAG_FIXED,
- .disks_to_provide = {
- {4096, 100, VB_DISK_FLAG_FIXED, pickme},
- {4096, 100, VB_DISK_FLAG_REMOVABLE, "holygrail"},
- },
- .disk_count_to_return = DEFAULT_COUNT,
- .diskgetinfo_return_val = VB2_SUCCESS,
- .loadkernel_return_val = {0},
- .external_expected = {0},
-
- .expected_recovery_request_val = VB2_RECOVERY_NOT_REQUESTED,
- .expected_to_find_disk = pickme,
- .expected_to_load_disk = pickme,
- .expected_return_val = VB2_SUCCESS
- },
- {
- .name = "first removable drive",
- .ctx_flags = 0,
- .want_flags = VB_DISK_FLAG_REMOVABLE,
- .disks_to_provide = {
- /* too small */
- {512, 10, VB_DISK_FLAG_REMOVABLE, 0},
- /* wrong LBA */
- {511, 100, VB_DISK_FLAG_REMOVABLE, 0},
- /* not a power of 2 */
- {2047, 100, VB_DISK_FLAG_REMOVABLE, 0},
- /* wrong type */
- {512, 100, VB_DISK_FLAG_FIXED, 0},
- /* wrong flags */
- {512, 100, 0, 0},
- /* still wrong flags */
- {512, 100, -1, 0},
- {4096, 100, VB_DISK_FLAG_REMOVABLE, pickme},
- /* already got one */
- {512, 100, VB_DISK_FLAG_REMOVABLE, "holygrail"},
- },
- .disk_count_to_return = DEFAULT_COUNT,
- .diskgetinfo_return_val = VB2_SUCCESS,
- .loadkernel_return_val = {0},
- .external_expected = {0},
-
- .expected_recovery_request_val = VB2_RECOVERY_NOT_REQUESTED,
- .expected_to_find_disk = pickme,
- .expected_to_load_disk = pickme,
- .expected_return_val = VB2_SUCCESS
- },
- {
- .name = "first removable drive (skip external GPT)",
- .ctx_flags = 0,
- .want_flags = VB_DISK_FLAG_REMOVABLE,
- .disks_to_provide = {
- /* too small */
- {512, 10, VB_DISK_FLAG_REMOVABLE, 0},
- /* wrong LBA */
- {511, 100, VB_DISK_FLAG_REMOVABLE, 0},
- /* not a power of 2 */
- {2047, 100, VB_DISK_FLAG_REMOVABLE, 0},
- /* wrong type */
- {512, 100, VB_DISK_FLAG_FIXED, 0},
- /* wrong flags */
- {512, 100, 0, 0},
- /* still wrong flags */
- {512, 100, -1, 0},
- {512, 100,
- VB_DISK_FLAG_REMOVABLE | VB_DISK_FLAG_EXTERNAL_GPT,
- pickme},
- /* already got one */
- {512, 100, VB_DISK_FLAG_REMOVABLE, "holygrail"},
- },
- .disk_count_to_return = DEFAULT_COUNT,
- .diskgetinfo_return_val = VB2_SUCCESS,
- .loadkernel_return_val = {0, 0},
- .external_expected = {1, 0},
-
- .expected_recovery_request_val = VB2_RECOVERY_NOT_REQUESTED,
- .expected_to_find_disk = pickme,
- .expected_to_load_disk = pickme,
- .expected_return_val = VB2_SUCCESS
- },
- {
- .name = "second removable drive",
- .ctx_flags = 0,
- .want_flags = VB_DISK_FLAG_REMOVABLE,
- .disks_to_provide = {
- /* wrong flags */
- {512, 100, 0, 0},
- {512, 100, VB_DISK_FLAG_REMOVABLE, "not yet"},
- {512, 100, VB_DISK_FLAG_REMOVABLE, pickme},
- },
- .disk_count_to_return = DEFAULT_COUNT,
- .diskgetinfo_return_val = VB2_SUCCESS,
- .loadkernel_return_val = {VB2_ERROR_LK_INVALID_KERNEL_FOUND, 0},
-
- .expected_recovery_request_val = VB2_RECOVERY_NOT_REQUESTED,
- .expected_to_find_disk = pickme,
- .expected_to_load_disk = pickme,
- .expected_return_val = VB2_SUCCESS
- },
- {
- .name = "first fixed drive",
- .ctx_flags = 0,
- .want_flags = VB_DISK_FLAG_FIXED,
- .disks_to_provide = {
- /* too small */
- {512, 10, VB_DISK_FLAG_FIXED, 0},
- /* wrong LBA */
- {511, 100, VB_DISK_FLAG_FIXED, 0},
- /* not a power of 2 */
- {2047, 100, VB_DISK_FLAG_REMOVABLE, 0},
- /* wrong type */
- {512, 100, VB_DISK_FLAG_REMOVABLE, 0},
- /* wrong flags */
- {512, 100, 0, 0},
- /* still wrong flags */
- {512, 100, -1, 0},
- /* flags */
- {512, 100, VB_DISK_FLAG_REMOVABLE|VB_DISK_FLAG_FIXED,
- 0},
- {512, 100, VB_DISK_FLAG_FIXED, pickme},
- /* already got one */
- {512, 100, VB_DISK_FLAG_FIXED, "holygrail"},
- },
- .disk_count_to_return = DEFAULT_COUNT,
- .diskgetinfo_return_val = VB2_SUCCESS,
- .loadkernel_return_val = {0},
-
- .expected_recovery_request_val = VB2_RECOVERY_NOT_REQUESTED,
- .expected_to_find_disk = pickme,
- .expected_to_load_disk = pickme,
- .expected_return_val = VB2_SUCCESS
- },
- {
- .name = "no drives at all",
- .ctx_flags = 0,
- .want_flags = VB_DISK_FLAG_FIXED,
- .disks_to_provide = {},
- .disk_count_to_return = DEFAULT_COUNT,
- .diskgetinfo_return_val = VB2_SUCCESS,
-
- .expected_recovery_request_val = VB2_RECOVERY_RW_NO_DISK,
- .expected_to_find_disk = 0,
- .expected_to_load_disk = 0,
- .expected_return_val = VB2_ERROR_LK_NO_DISK_FOUND
- },
- {
- .name = "VbExDiskGetInfo() error",
- .ctx_flags = 0,
- .want_flags = VB_DISK_FLAG_FIXED,
- .disks_to_provide = {
- {512, 10, VB_DISK_FLAG_REMOVABLE, 0},
- {512, 100, VB_DISK_FLAG_FIXED, 0},
- },
- .disk_count_to_return = DEFAULT_COUNT,
- .diskgetinfo_return_val = VB2_ERROR_UNKNOWN,
-
- .expected_recovery_request_val = VB2_RECOVERY_RW_NO_DISK,
- .expected_to_find_disk = 0,
- .expected_to_load_disk = 0,
- .expected_return_val = VB2_ERROR_LK_NO_DISK_FOUND,
- },
- {
- .name = "invalid kernel",
- .ctx_flags = 0,
- .want_flags = VB_DISK_FLAG_FIXED,
- .disks_to_provide = {
- /* too small */
- {512, 10, VB_DISK_FLAG_FIXED, 0},
- /* wrong LBA */
- {511, 100, VB_DISK_FLAG_FIXED, 0},
- /* not a power of 2 */
- {2047, 100, VB_DISK_FLAG_FIXED, 0},
- /* wrong type */
- {512, 100, VB_DISK_FLAG_REMOVABLE, 0},
- /* wrong flags */
- {512, 100, 0, 0},
- /* still wrong flags */
- {512, 100, -1, 0},
- /* doesn't load */
- {512, 100, VB_DISK_FLAG_FIXED, "corrupted kernel"},
- /* doesn't load */
- {512, 100, VB_DISK_FLAG_FIXED, "stateful partition"},
- },
- .disk_count_to_return = DEFAULT_COUNT,
- .diskgetinfo_return_val = VB2_SUCCESS,
- .loadkernel_return_val = {VB2_ERROR_LK_INVALID_KERNEL_FOUND,
- VB2_ERROR_LK_NO_KERNEL_FOUND},
-
- .expected_recovery_request_val = VB2_RECOVERY_RW_INVALID_OS,
- .expected_to_find_disk = DONT_CARE,
- .expected_to_load_disk = 0,
- .expected_return_val = VB2_ERROR_LK_INVALID_KERNEL_FOUND,
- },
- {
- .name = "invalid kernel, order flipped",
- .ctx_flags = 0,
- .want_flags = VB_DISK_FLAG_FIXED,
- .disks_to_provide = {
- {512, 1000, VB_DISK_FLAG_FIXED, "stateful partition"},
- {512, 1000, VB_DISK_FLAG_FIXED, "corrupted kernel"},
- },
- .disk_count_to_return = DEFAULT_COUNT,
- .diskgetinfo_return_val = VB2_SUCCESS,
- .loadkernel_return_val = {VB2_ERROR_LK_NO_KERNEL_FOUND,
- VB2_ERROR_LK_INVALID_KERNEL_FOUND},
-
- .expected_recovery_request_val = VB2_RECOVERY_RW_INVALID_OS,
- .expected_to_find_disk = DONT_CARE,
- .expected_to_load_disk = 0,
- .expected_return_val = VB2_ERROR_LK_INVALID_KERNEL_FOUND,
- },
- {
- .name = "no Chrome OS partitions",
- .ctx_flags = 0,
- .want_flags = VB_DISK_FLAG_FIXED,
- .disks_to_provide = {
- {512, 100, VB_DISK_FLAG_FIXED, "stateful partition"},
- {512, 1000, VB_DISK_FLAG_FIXED, "Chrubuntu"},
- },
- .disk_count_to_return = DEFAULT_COUNT,
- .diskgetinfo_return_val = VB2_SUCCESS,
- .loadkernel_return_val = {VB2_ERROR_LK_NO_KERNEL_FOUND,
- VB2_ERROR_LK_NO_KERNEL_FOUND},
-
- .expected_recovery_request_val = VB2_RECOVERY_RW_NO_KERNEL,
- .expected_to_find_disk = DONT_CARE,
- .expected_to_load_disk = 0,
- .expected_return_val = VB2_ERROR_LK_NO_KERNEL_FOUND,
- },
- {
- .name = "invalid kernel (removable)",
- .ctx_flags = 0,
- .want_flags = VB_DISK_FLAG_REMOVABLE,
- .disks_to_provide = {
- {512, 100, VB_DISK_FLAG_REMOVABLE, "corrupted"},
- {512, 100, VB_DISK_FLAG_REMOVABLE, "data"},
- },
- .disk_count_to_return = DEFAULT_COUNT,
- .diskgetinfo_return_val = VB2_SUCCESS,
- .loadkernel_return_val = {VB2_ERROR_LK_INVALID_KERNEL_FOUND,
- VB2_ERROR_LK_NO_KERNEL_FOUND},
-
- .expected_recovery_request_val = VB2_RECOVERY_RW_INVALID_OS,
- .expected_to_find_disk = DONT_CARE,
- .expected_to_load_disk = 0,
- .expected_return_val = VB2_ERROR_LK_INVALID_KERNEL_FOUND,
- },
- {
- .name = "invalid kernel (removable, rec mode)",
- .ctx_flags = VB2_CONTEXT_RECOVERY_MODE,
- .want_flags = VB_DISK_FLAG_REMOVABLE,
- .disks_to_provide = {
- {512, 100, VB_DISK_FLAG_REMOVABLE, "corrupted"},
- {512, 100, VB_DISK_FLAG_REMOVABLE, "data"},
- },
- .disk_count_to_return = DEFAULT_COUNT,
- .diskgetinfo_return_val = VB2_SUCCESS,
- .loadkernel_return_val = {VB2_ERROR_LK_INVALID_KERNEL_FOUND,
- VB2_ERROR_LK_NO_KERNEL_FOUND},
-
- .expected_recovery_request_val = VB2_RECOVERY_NOT_REQUESTED,
- .expected_to_find_disk = DONT_CARE,
- .expected_to_load_disk = 0,
- .expected_return_val = VB2_ERROR_LK_INVALID_KERNEL_FOUND,
- },
- {
- .name = "invalid kernel (removable, dev mode)",
- .ctx_flags = VB2_CONTEXT_DEVELOPER_MODE,
- .want_flags = VB_DISK_FLAG_REMOVABLE,
- .disks_to_provide = {
- {512, 100, VB_DISK_FLAG_REMOVABLE, "corrupted"},
- {512, 100, VB_DISK_FLAG_REMOVABLE, "data"},
- },
- .disk_count_to_return = DEFAULT_COUNT,
- .diskgetinfo_return_val = VB2_SUCCESS,
- .loadkernel_return_val = {VB2_ERROR_LK_INVALID_KERNEL_FOUND,
- VB2_ERROR_LK_NO_KERNEL_FOUND},
-
- .expected_recovery_request_val = VB2_RECOVERY_NOT_REQUESTED,
- .expected_to_find_disk = DONT_CARE,
- .expected_to_load_disk = 0,
- .expected_return_val = VB2_ERROR_LK_INVALID_KERNEL_FOUND,
- },
- {
- .name = "no kernel (removable)",
- .ctx_flags = 0,
- .want_flags = VB_DISK_FLAG_REMOVABLE,
- .disks_to_provide = {
- {512, 100, VB_DISK_FLAG_REMOVABLE, "data"},
- },
- .disk_count_to_return = DEFAULT_COUNT,
- .diskgetinfo_return_val = VB2_SUCCESS,
- .loadkernel_return_val = {VB2_ERROR_LK_NO_KERNEL_FOUND},
-
- .expected_recovery_request_val = VB2_RECOVERY_RW_NO_KERNEL,
- .expected_to_find_disk = DONT_CARE,
- .expected_to_load_disk = 0,
- .expected_return_val = VB2_ERROR_LK_NO_KERNEL_FOUND,
- },
- {
- .name = "no kernel (removable, rec mode)",
- .ctx_flags = VB2_CONTEXT_RECOVERY_MODE,
- .want_flags = VB_DISK_FLAG_REMOVABLE,
- .disks_to_provide = {
- {512, 100, VB_DISK_FLAG_REMOVABLE, "data"},
- },
- .disk_count_to_return = DEFAULT_COUNT,
- .diskgetinfo_return_val = VB2_SUCCESS,
- .loadkernel_return_val = {VB2_ERROR_LK_NO_KERNEL_FOUND},
-
- .expected_recovery_request_val = VB2_RECOVERY_NOT_REQUESTED,
- .expected_to_find_disk = DONT_CARE,
- .expected_to_load_disk = 0,
- .expected_return_val = VB2_ERROR_LK_NO_KERNEL_FOUND,
- },
-};
-
-test_case_t minios_tests[] = {
- {
- .name = "pick first fixed drive",
- .ctx_flags = 0,
- .disks_to_provide = {
- {4096, 100, VB_DISK_FLAG_REMOVABLE, 0},
- {4096, 100, VB_DISK_FLAG_FIXED, pickme},
- {4096, 100, VB_DISK_FLAG_FIXED, "holygrail"},
- },
- .disk_count_to_return = DEFAULT_COUNT,
- .diskgetinfo_return_val = VB2_SUCCESS,
- .loadkernel_return_val = {0},
- .external_expected = {0},
-
- .expected_recovery_request_val = VB2_RECOVERY_NOT_REQUESTED,
- .expected_to_find_disk = pickme,
- .expected_to_load_disk = pickme,
- .expected_return_val = VB2_SUCCESS
- },
- {
- .name = "skip failed fixed drive",
- .ctx_flags = 0,
- .disks_to_provide = {
- {4096, 100, VB_DISK_FLAG_FIXED, "holygrail"},
- {4096, 100, VB_DISK_FLAG_FIXED, pickme},
- },
- .disk_count_to_return = DEFAULT_COUNT,
- .diskgetinfo_return_val = VB2_SUCCESS,
- .loadkernel_return_val = {VB2_ERROR_LK_INVALID_KERNEL_FOUND, 0},
- .external_expected = {0},
-
- .expected_recovery_request_val = VB2_RECOVERY_NOT_REQUESTED,
- .expected_to_find_disk = pickme,
- .expected_to_load_disk = pickme,
- .expected_return_val = VB2_SUCCESS
- },
-};
-
-/****************************************************************************/
-
-/* Mock data */
-static VbDiskInfo mock_disks[MAX_TEST_DISKS];
-static test_case_t *t;
-static int load_kernel_calls;
-static int lk_normal_calls;
-static int lk_minios_calls;
-static uint32_t got_recovery_request_val;
-static const char *got_find_disk;
-static const char *got_load_disk;
-static uint32_t got_return_val;
-static uint32_t got_external_mismatch;
-static uint8_t workbuf[VB2_KERNEL_WORKBUF_RECOMMENDED_SIZE]
- __attribute__((aligned(VB2_WORKBUF_ALIGN)));
-static struct vb2_context *ctx;
-static struct VbSelectAndLoadKernelParams kparams;
-
-/**
- * Reset mock data (for use before each test)
- */
-static void ResetMocks(test_case_t *test_case)
-{
- TEST_SUCC(vb2api_init(workbuf, sizeof(workbuf), &ctx),
- "vb2api_init failed");
-
- memset(&kparams, 0, sizeof(VbSelectAndLoadKernelParams));
- *VbApiKernelGetParamsPtr() = &kparams;
-
-
- memset(&mock_disks, 0, sizeof(mock_disks));
- load_kernel_calls = 0;
- lk_normal_calls = 0;
- lk_minios_calls = 0;
-
- got_recovery_request_val = VB2_RECOVERY_NOT_REQUESTED;
- got_find_disk = 0;
- got_load_disk = 0;
- got_return_val = 0xdeadbeef;
-
- t = test_case;
-}
-
-static int is_nonzero(const void *vptr, size_t count)
-{
- const char *p = (const char *)vptr;
- while (count--)
- if (*p++)
- return 1;
-
- return 0;
-}
-
-/****************************************************************************/
-/* Mocked verification functions */
-
-vb2_error_t VbExDiskGetInfo(VbDiskInfo **infos_ptr, uint32_t *count,
- uint32_t disk_flags)
-{
- int i;
- int num_disks = 0;
-
- VB2_DEBUG("My %s\n", __FUNCTION__);
-
- *infos_ptr = mock_disks;
-
- for(i = 0; i < MAX_TEST_DISKS; i++) {
- if (is_nonzero(&t->disks_to_provide[i],
- sizeof(t->disks_to_provide[i]))) {
- mock_disks[num_disks].bytes_per_lba =
- t->disks_to_provide[i].bytes_per_lba;
- mock_disks[num_disks].lba_count =
- mock_disks[num_disks].streaming_lba_count =
- t->disks_to_provide[i].lba_count;
- mock_disks[num_disks].flags =
- t->disks_to_provide[i].flags;
- mock_disks[num_disks].handle = (VbExDiskHandle_t)
- t->disks_to_provide[i].diskname;
- VB2_DEBUG(" mock_disk[%d] %" PRIu64 " %" PRIu64
- " %#x %s\n", i,
- mock_disks[num_disks].bytes_per_lba,
- mock_disks[num_disks].lba_count,
- mock_disks[num_disks].flags,
- (mock_disks[num_disks].handle
- ? (char *)mock_disks[num_disks].handle
- : "0"));
- num_disks++;
- } else {
- mock_disks[num_disks].handle =
- (VbExDiskHandle_t)"INVALID";
- }
- }
-
- if (t->disk_count_to_return >= 0)
- *count = t->disk_count_to_return;
- else
- *count = num_disks;
-
- VB2_DEBUG(" *count=%" PRIu32 "\n", *count);
- VB2_DEBUG(" return %#x\n", t->diskgetinfo_return_val);
-
- return t->diskgetinfo_return_val;
-}
-
-vb2_error_t VbExDiskFreeInfo(VbDiskInfo *infos,
- VbExDiskHandle_t preserve_handle)
-{
- got_load_disk = (const char *)preserve_handle;
- VB2_DEBUG("%s(): got_load_disk = %s\n", __FUNCTION__,
- got_load_disk ? got_load_disk : "0");
- return VB2_SUCCESS;
-}
-
-static vb2_error_t LoadKernelImpl(struct vb2_context *c,
- VbSelectAndLoadKernelParams *params,
- VbDiskInfo *disk_info)
-{
- got_find_disk = (const char *)params->disk_handle;
- VB2_DEBUG("%s(%d): got_find_disk = %s\n", __FUNCTION__,
- load_kernel_calls,
- got_find_disk ? got_find_disk : "0");
- if (t->external_expected[load_kernel_calls] !=
- !!(disk_info->flags & VB_DISK_FLAG_EXTERNAL_GPT))
- got_external_mismatch++;
- return t->loadkernel_return_val[load_kernel_calls++];
-}
-
-vb2_error_t LoadKernel(struct vb2_context *c,
- VbSelectAndLoadKernelParams *params,
- VbDiskInfo *disk_info)
-{
- lk_normal_calls++;
- return LoadKernelImpl(c, params, disk_info);
-}
-
-vb2_error_t LoadMiniOsKernel(struct vb2_context *c,
- VbSelectAndLoadKernelParams *params,
- VbDiskInfo *disk_info, uint32_t minios_flags)
-{
- lk_minios_calls++;
- return LoadKernelImpl(c, params, disk_info);
-}
-
-void vb2_nv_set(struct vb2_context *c,
- enum vb2_nv_param param,
- uint32_t value)
-{
- if (param != VB2_NV_RECOVERY_REQUEST)
- return;
- VB2_DEBUG("%s(): got_recovery_request_val = %d (%#x)\n", __FUNCTION__,
- value, value);
- got_recovery_request_val = value;
-}
-
-/****************************************************************************/
-
-static void VbTryLoadKernelTest(void)
-{
- int i;
- int num_tests = ARRAY_SIZE(normal_tests);
-
- for (i = 0; i < num_tests; i++) {
- printf("Test case: %s ...\n", normal_tests[i].name);
- ResetMocks(&normal_tests[i]);
- ctx->flags = t->ctx_flags;
- TEST_EQ(VbTryLoadKernel(ctx, t->want_flags),
- t->expected_return_val, " return value");
- TEST_EQ(got_recovery_request_val,
- t->expected_recovery_request_val, " recovery_request");
- if (t->expected_to_find_disk != DONT_CARE) {
- TEST_PTR_EQ(got_find_disk, t->expected_to_find_disk,
- " find disk");
- TEST_PTR_EQ(got_load_disk, t->expected_to_load_disk,
- " load disk");
- }
- TEST_EQ(got_external_mismatch, 0, " external GPT errors");
- }
- TEST_EQ(lk_normal_calls, load_kernel_calls, " LoadKernel called");
- TEST_EQ(lk_minios_calls, 0, " LoadMiniOsKernel not called");
-}
-
-static void VbTryLoadMiniOsKernelTest(void)
-{
- int i;
- int num_tests = ARRAY_SIZE(minios_tests);
-
- for (i = 0; i < num_tests; i++) {
- printf("Test case: %s ...\n", minios_tests[i].name);
- ResetMocks(&minios_tests[i]);
- ctx->flags = t->ctx_flags;
- TEST_EQ(VbTryLoadMiniOsKernel(ctx, 0),
- t->expected_return_val, " return value");
- TEST_EQ(got_recovery_request_val,
- t->expected_recovery_request_val, " recovery_request");
- if (t->expected_to_find_disk != DONT_CARE) {
- TEST_PTR_EQ(got_find_disk, t->expected_to_find_disk,
- " find disk");
- TEST_PTR_EQ(got_load_disk, t->expected_to_load_disk,
- " load disk");
- }
- TEST_EQ(got_external_mismatch, 0, " external GPT errors");
- }
- TEST_EQ(lk_normal_calls, 0, " LoadKernel not called");
- TEST_EQ(lk_minios_calls, load_kernel_calls,
- " LoadMiniOsKernel called");
-}
-
-int main(void)
-{
- VbTryLoadKernelTest();
- VbTryLoadMiniOsKernelTest();
-
- return gTestSuccess ? 0 : 255;
-}
diff --git a/tests/verify_kernel.c b/tests/verify_kernel.c
index a79f33a..8af4791 100644
--- a/tests/verify_kernel.c
+++ b/tests/verify_kernel.c
@@ -14,7 +14,6 @@
#include "host_common.h"
#include "util_misc.h"
#include "vboot_api.h"
-#include "load_kernel_fw.h"
static uint8_t workbuf[VB2_KERNEL_WORKBUF_RECOMMENDED_SIZE]
__attribute__((aligned(VB2_WORKBUF_ALIGN)));
@@ -23,13 +22,13 @@
static uint8_t *diskbuf;
-static VbSelectAndLoadKernelParams params;
-static VbDiskInfo disk_info;
+static struct vb2_kernel_params params;
+static struct vb2_disk_info disk_info;
-vb2_error_t VbExDiskRead(VbExDiskHandle_t handle, uint64_t lba_start,
+vb2_error_t VbExDiskRead(vb2ex_disk_handle_t handle, uint64_t lba_start,
uint64_t lba_count, void *buffer)
{
- if (handle != (VbExDiskHandle_t)1)
+ if (handle != (vb2ex_disk_handle_t)1)
return VB2_ERROR_UNKNOWN;
if (lba_start >= disk_info.streaming_lba_count)
return VB2_ERROR_UNKNOWN;
@@ -40,10 +39,10 @@
return VB2_SUCCESS;
}
-vb2_error_t VbExDiskWrite(VbExDiskHandle_t handle, uint64_t lba_start,
+vb2_error_t VbExDiskWrite(vb2ex_disk_handle_t handle, uint64_t lba_start,
uint64_t lba_count, const void *buffer)
{
- if (handle != (VbExDiskHandle_t)1)
+ if (handle != (vb2ex_disk_handle_t)1)
return VB2_ERROR_UNKNOWN;
if (lba_start >= disk_info.streaming_lba_count)
return VB2_ERROR_UNKNOWN;
@@ -87,8 +86,7 @@
}
/* Set up params */
- params.disk_handle = (VbExDiskHandle_t)1;
- disk_info.handle = (VbExDiskHandle_t)1;
+ disk_info.handle = (vb2ex_disk_handle_t)1;
disk_info.bytes_per_lba = 512;
disk_info.streaming_lba_count = disk_bytes / 512;
disk_info.lba_count = disk_info.streaming_lba_count;
@@ -123,8 +121,8 @@
}
/*
- * LoadKernel() cares only about VBNV_DEV_BOOT_SIGNED_ONLY, and only in
- * dev mode. So just use defaults for nv storage.
+ * vb2api_load_kernel() cares only about VBNV_DEV_BOOT_SIGNED_ONLY, and
+ * only in dev mode. So just use defaults for nv storage.
*/
vb2_nv_init(ctx);
/* We need to init kernel secdata for
@@ -134,9 +132,10 @@
vb2_secdata_kernel_init(ctx);
/* Try loading kernel */
- rv = LoadKernel(ctx, ¶ms, &disk_info);
+ rv = vb2api_load_kernel(ctx, ¶ms, &disk_info);
if (rv != VB2_SUCCESS) {
- fprintf(stderr, "LoadKernel() failed with code %d\n", rv);
+ fprintf(stderr, "vb2api_load_kernel() failed with code %d\n",
+ rv);
return 1;
}
diff --git a/utility/load_kernel_test.c b/utility/load_kernel_test.c
index 405fced..565161e 100644
--- a/utility/load_kernel_test.c
+++ b/utility/load_kernel_test.c
@@ -15,7 +15,6 @@
#include "2misc.h"
#include "2sysincludes.h"
#include "host_common.h"
-#include "load_kernel_fw.h"
#define LBA_BYTES 512
#define KERNEL_BUFFER_SIZE 0xA00000
@@ -25,13 +24,13 @@
static struct vb2_shared_data *sd;
/* Global variables for stub functions */
-static VbSelectAndLoadKernelParams lkp;
-static VbDiskInfo disk_info;
+static struct vb2_kernel_params lkp;
+static struct vb2_disk_info disk_info;
static FILE *image_file = NULL;
/* Boot device stub implementations to read from the image file */
-vb2_error_t VbExDiskRead(VbExDiskHandle_t handle, uint64_t lba_start,
+vb2_error_t VbExDiskRead(vb2ex_disk_handle_t handle, uint64_t lba_start,
uint64_t lba_count, void *buffer)
{
printf("Read(%" PRIu64 ", %" PRIu64 ")\n", lba_start, lba_count);
@@ -56,7 +55,7 @@
}
-vb2_error_t VbExDiskWrite(VbExDiskHandle_t handle, uint64_t lba_start,
+vb2_error_t VbExDiskWrite(vb2ex_disk_handle_t handle, uint64_t lba_start,
uint64_t lba_count, const void *buffer)
{
printf("Write(%" PRIu64 ", %" PRIu64 ")\n", lba_start, lba_count);
@@ -99,7 +98,7 @@
int errorcnt = 0;
char *e = 0;
- memset(&lkp, 0, sizeof(VbSelectAndLoadKernelParams));
+ memset(&lkp, 0, sizeof(lkp));
disk_info.bytes_per_lba = LBA_BYTES;
int boot_flags = BOOT_FLAG_RECOVERY;
@@ -243,9 +242,9 @@
if (boot_flags & BOOT_FLAG_DEVELOPER)
ctx->flags |= VB2_CONTEXT_DEVELOPER_MODE;
- /* Call LoadKernel() */
- rv = LoadKernel(ctx, &lkp, &disk_info);
- printf("LoadKernel() returned %d\n", rv);
+ /* Call vb2api_load_kernel() */
+ rv = vb2api_load_kernel(ctx, &lkp, &disk_info);
+ printf("vb2api_load_kernel() returned %d\n", rv);
if (VB2_SUCCESS == rv) {
printf("Partition number: %u\n", lkp.partition_number);