Amol N Sukerkar has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/32148
Change subject: security/vboot: Added logic to authenticate firmware using VBOOT library version 2.1 ......................................................................
security/vboot: Added logic to authenticate firmware using VBOOT library version 2.1
This feature adds logic to authenticate Coreboot stages using VBOOT libraries version 2.1
Users of this feature will need to enable CONFIG_VBOOT_STAGE_VERIFICATION to enable the corresponding logic in Coreboot to authenticate the VBLOCK version 2.1 and the Coreboot stage hashes.
TEST=Create a coreboot.rom image which has keyblock and VBLOCK with VBOOT version 2.1 structures. This is done by enabling CONFIG_VBOOT_STAGE_VERIFICATION. Verify that the image boots to authenticated payload.
Change-Id: Ie06d51d180d4c8a872d678d6bd5c67de0efffca2 Signed-off-by: Sukerkar, Amol N amol.n.sukerkar@intel.com --- M src/security/vboot/Kconfig M src/security/vboot/Makefile.inc M src/security/vboot/vboot_handoff.c M src/security/vboot/vboot_loader.c A src/security/vboot/vboot_logic_ex.c 5 files changed, 475 insertions(+), 3 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/48/32148/1
diff --git a/src/security/vboot/Kconfig b/src/security/vboot/Kconfig index ca25423..e7bd3f9 100644 --- a/src/security/vboot/Kconfig +++ b/src/security/vboot/Kconfig @@ -2,6 +2,7 @@ ## ## Copyright (C) 2014 The ChromiumOS Authors. All rights reserved. ## Copyright (C) 2018 Siemens AG +## Copyright (C) 2019 Intel Corp. All rights reserved. ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by @@ -53,6 +54,12 @@ help Have two update partitions beside the RO partition.
+config VBOOT_STAGE_VERIFICATION + bool "Verify stages with vboot 2.1" + default n + help + Enables vboot verification for each stage + config VBOOT_VBNV_CMOS bool default n @@ -323,18 +330,52 @@ config VBOOT_ROOT_KEY string "Root key (public)" default "$(VBOOT_SOURCE)/tests/devkeys/root_key.vbpubk" + depends on !VBOOT_STAGE_VERIFICATION
config VBOOT_RECOVERY_KEY string "Recovery key (public)" default "$(VBOOT_SOURCE)/tests/devkeys/recovery_key.vbpubk" + depends on !VBOOT_STAGE_VERIFICATION
config VBOOT_FIRMWARE_PRIVKEY string "Firmware key (private)" default "$(VBOOT_SOURCE)/tests/devkeys/firmware_data_key.vbprivk" + depends on !VBOOT_STAGE_VERIFICATION
config VBOOT_KERNEL_KEY string "Kernel subkey (public)" default "$(VBOOT_SOURCE)/tests/devkeys/kernel_subkey.vbpubk" + depends on !VBOOT_STAGE_VERIFICATION + +config VBOOT_2_1_ROOT_KEY + string "Root Key version 2.1 (public)" + default "$(VBOOT_SOURCE)/tests/devkeys/root_key.vbpubk2" + depends on VBOOT_STAGE_VERIFICATION + +config VBOOT_2_1_PRIVATE_KEY + string "Root Key version 2.1 (private)" + default "$(VBOOT_SOURCE)/tests/devkeys/root_key.vbprik2" + depends on VBOOT_STAGE_VERIFICATION + +config VBOOT_2_1_FW_PRE_PUBLIC_KEY + string "FW Preamble Key version 2.1 (public)" + default "$(VBOOT_SOURCE)/tests/devkeys/fw_pre.vbpubk2" + depends on VBOOT_STAGE_VERIFICATION + +config VBOOT_2_1_FW_PRE_PRIVATE_KEY + string "FW PREAMBLE Key version 2.1 (private)" + default "$(VBOOT_SOURCE)/tests/devkeys/fw_pre.vbprik2" + depends on VBOOT_STAGE_VERIFICATION + +config VBOOT_2_1_RAMSTAGE_HASH_KEY + string "Coreboot RAMStage Stage Hashing Key(private)" + default "$(VBOOT_SOURCE)/tests/devkeys/rhash.vbprik2" + depends on VBOOT_STAGE_VERIFICATION + +config VBOOT_2_1_PAYLOAD_HASH_KEY + string "Coreboot PAYLOAD Stage Hashing Key(private)" + default "$(VBOOT_SOURCE)/tests/devkeys/phash.vbprik2" + depends on VBOOT_STAGE_VERIFICATION
config VBOOT_KEYBLOCK string "Keyblock to use for the RW regions" diff --git a/src/security/vboot/Makefile.inc b/src/security/vboot/Makefile.inc index 6d2096d..a65b066 100644 --- a/src/security/vboot/Makefile.inc +++ b/src/security/vboot/Makefile.inc @@ -3,6 +3,7 @@ ## ## Copyright (C) 2014 The ChromiumOS Authors. All rights reserved. ## Copyright (C) 2018 Siemens AG +## Copyright (C) 2019 Intel Corp. All rights reserved. ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by @@ -35,16 +36,27 @@ bootblock-y += vbnv.c verstage-y += vbnv.c romstage-y += vbnv.c +postcar-$(CONFIG_VBOOT_STAGE_VERIFICATION) += vbnv.c ramstage-y += vbnv.c
bootblock-$(CONFIG_VBOOT_VBNV_CMOS) += vbnv_cmos.c verstage-$(CONFIG_VBOOT_VBNV_CMOS) += vbnv_cmos.c romstage-$(CONFIG_VBOOT_VBNV_CMOS) += vbnv_cmos.c + +ifeq ($(CONFIG_VBOOT_STAGE_VERIFICATION),y) +postcar-$(CONFIG_VBOOT_VBNV_CMOS) += vbnv_cmos.c +endif + ramstage-$(CONFIG_VBOOT_VBNV_CMOS) += vbnv_cmos.c
bootblock-$(CONFIG_VBOOT_VBNV_CMOS_BACKUP_TO_FLASH) += vbnv_flash.c verstage-$(CONFIG_VBOOT_VBNV_CMOS_BACKUP_TO_FLASH) += vbnv_flash.c romstage-$(CONFIG_VBOOT_VBNV_CMOS_BACKUP_TO_FLASH) += vbnv_flash.c + +ifeq ($(CONFIG_VBOOT_STAGE_VERIFICATION),y) +postcar-$(CONFIG_VBOOT_VBNV_CMOS_BACKUP_TO_FLASH) += vbnv_flash.c +endif + ramstage-$(CONFIG_VBOOT_VBNV_CMOS_BACKUP_TO_FLASH) += vbnv_flash.c
bootblock-$(CONFIG_VBOOT_VBNV_EC) += vbnv_ec.c @@ -77,12 +89,26 @@ endif
bootblock-y += common.c + +ifeq ($(CONFIG_VBOOT_STAGE_VERIFICATION),y) +verstage-y += vboot_logic_ex.c +else verstage-y += vboot_logic.c +endif +postcar-$(CONFIG_VBOOT_STAGE_VERIFICATION) += vboot_logic_ex.c +ramstage-$(CONFIG_VBOOT_STAGE_VERIFICATION) += vboot_logic_ex.c + verstage-y += common.c verstage-$(CONFIG_VBOOT_SEPARATE_VERSTAGE) += verstage.c ifeq (${CONFIG_VBOOT_MOCK_SECDATA},y) verstage-y += secdata_mock.c romstage-$(CONFIG_VBOOT_SEPARATE_VERSTAGE) += secdata_mock.c + +ifeq ($(CONFIG_VBOOT_STAGE_VERIFICATION),y) +postcar-$(CONFIG_VBOOT_SEPARATE_VERSTAGE) += secdata_mock.c +ramstage-$(CONFIG_VBOOT_SEPARATE_VERSTAGE) += secdata_mock.c +endif + else verstage-y += secdata_tpm.c romstage-$(CONFIG_VBOOT_SEPARATE_VERSTAGE) += secdata_tpm.c @@ -101,7 +127,11 @@ # call with $1 = stage name to create rules for building the library # for the stage and adding it to the stage's set of object files. define vboot-for-stage +ifeq ($(CONFIG_VBOOT_STAGE_VERIFICATION),y) +VB2_LIB_$(1) = $(obj)/external/vboot_reference-$(1)/vboot_fw21.a +else VB2_LIB_$(1) = $(obj)/external/vboot_reference-$(1)/vboot_fw20.a +endif VBOOT_CFLAGS_$(1) += $$(call vboot-fixup-includes,$$(CPPFLAGS_$(1))) VBOOT_CFLAGS_$(1) += $$(CFLAGS_$(1)) VBOOT_CFLAGS_$(1) += $$(call vboot-fixup-includes,$$($(1)-c-ccopts)) @@ -116,7 +146,8 @@ $(MAKE) -C $(VBOOT_SOURCE) \ BUILD=$$(abspath $$(dir $$(VB2_LIB_$(1)))) \ V=$(V) \ - fwlib20 + $(if $(filter y,$(CONFIG_VBOOT_STAGE_VERIFICATION)), \ + fwlib21, fwlib20)
$(1)-srcs += $$(VB2_LIB_$(1))
@@ -129,6 +160,11 @@ $(eval $(call vboot-for-stage,ramstage)) $(eval $(call vboot-for-stage,postcar))
+ifeq ($(CONFIG_VBOOT_STAGE_VERIFICATION),y) +postcar-srcs += $(VB2_LIB) +ramstage-srcs += $(VB2_LIB) +endif + ifeq ($(CONFIG_VBOOT_SEPARATE_VERSTAGE),y)
$(eval $(call vboot-for-stage,verstage)) @@ -236,12 +272,21 @@ $(obj)/gbb.region: $(obj)/gbb.stub @printf " SETUP GBB\n" cp $< $@.tmp +ifeq ($(CONFIG_VBOOT_STAGE_VERIFICATION), y) + $(FUTILITY) gbb_utility -s \ + --hwid="$(CONFIG_GBB_HWID)" \ + --rootkey="$(CONFIG_VBOOT_2_1_ROOT_KEY)" \ + --flags=$(GBB_FLAGS) \ + $@.tmp +else $(FUTILITY) gbb_utility -s \ --hwid="$(CONFIG_GBB_HWID)" \ --rootkey="$(CONFIG_VBOOT_ROOT_KEY)" \ --recoverykey="$(CONFIG_VBOOT_RECOVERY_KEY)" \ --flags=$(GBB_FLAGS) \ $@.tmp +endif # CONFIG_VBOOT_STAGE_VERIFICATION + ifneq ($(CONFIG_GBB_BMPFV_FILE),) $(FUTILITY) gbb_utility -s \ --bmpfv="$(CONFIG_GBB_BMPFV_FILE)" \ @@ -288,6 +333,47 @@ mv $@.tmp2 $@ rm -f $@.tmp $@.tmp.size
+ifeq ($(CONFIG_VBOOT_STAGE_VERIFICATION), y) +# Extract RAMStage and PAYLOAD and hash them +# Since we are booting from FW_MAIN_A, RAMStage and payload are +# extracted from FW_MAIN_A. +$(obj)/ramstage.hash: $(obj)/coreboot.rom + @printf " CREATE RAMSTAGE HASH\n" + $(CBFSTOOL) $< print -r FW_MAIN_A > $<.tmp + python $(VBOOT_SOURCE)/compute_hash.py -i $<.tmp -o $@.tmp -c $< -f ramstage + $(FUTILITY) --vb21 sign \ + --type rwsig \ + --prikey "$(CONFIG_VBOOT_2_1_RAMSTAGE_HASH_KEY)" \ + $@.tmp $@ + rm -f $<.tmp $@.tmp + +$(obj)/payload.hash: $(obj)/coreboot.rom + @printf " CREATE PAYLOAD HASH\n" + $(CBFSTOOL) $< print -r FW_MAIN_A > $<.tmp + python $(VBOOT_SOURCE)/compute_hash.py -i $<.tmp -o $@.tmp -c $< -f payload + $(FUTILITY) --vb21 sign \ + --type rwsig \ + --prikey "$(CONFIG_VBOOT_2_1_PAYLOAD_HASH_KEY)" \ + $@.tmp $@ + rm -f $<.tmp $@.tmp + +$(obj)/firmware.kb21: $(FUTILITY) + $(FUTILITY) vbutil_keyblock \ + --pack21 $@ \ + --signprivate "$(CONFIG_VBOOT_2_1_PRIVATE_KEY)" \ + --datapubkey "$(CONFIG_VBOOT_2_1_FW_PRE_PUBLIC_KEY)" \ + --flags $(CONFIG_VBOOT_KEYBLOCK_PREAMBLE_FLAGS) + +$(obj)/VBLOCK_%.bin: $(obj)/FW_MAIN_%.bin $(FUTILITY) \ + $(obj)/ramstage.hash $(obj)/payload.hash $(obj)/firmware.kb21 + $(FUTILITY) vbutil_firmware \ + --vblock21 $@ \ + --keyblock "$(top)/$(obj)/firmware.kb21" \ + --signprepriv "$(CONFIG_VBOOT_2_1_FW_PRE_PRIVATE_KEY)" \ + --hashdir "$(top)/$(obj)" \ + --version $(CONFIG_VBOOT_KEYBLOCK_VERSION) \ + --flags $(CONFIG_VBOOT_KEYBLOCK_PREAMBLE_FLAGS) +else $(obj)/VBLOCK_%.bin: $(obj)/FW_MAIN_%.bin $(FUTILITY) $(FUTILITY) vbutil_firmware \ --vblock $@ \ @@ -297,6 +383,7 @@ --fv $< \ --kernelkey "$(CONFIG_VBOOT_KERNEL_KEY)" \ --flags $(CONFIG_VBOOT_KEYBLOCK_PREAMBLE_FLAGS) +endif # CONFIG_VBOOT_STAGE_VERIFICATION
ifeq ($(CONFIG_VBOOT_SLOTS_RW_AB),y) files_added:: $(obj)/VBLOCK_A.bin $(obj)/VBLOCK_B.bin @@ -314,3 +401,4 @@ endif
endif # CONFIG_VBOOT + diff --git a/src/security/vboot/vboot_handoff.c b/src/security/vboot/vboot_handoff.c index 1f6d4ee..c8980b6 100644 --- a/src/security/vboot/vboot_handoff.c +++ b/src/security/vboot/vboot_handoff.c @@ -2,6 +2,7 @@ * This file is part of the coreboot project. * * Copyright (C) 2013 Google, Inc. + * Copyright (C) 2019 Intel Corp. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -170,10 +171,12 @@ * Therefore, the vboot results would not be initialized so don't * automatically add results when cbmem comes online. */ -#if !CONFIG(VBOOT_STARTS_IN_ROMSTAGE) +#if !IS_ENABLED(CONFIG_VBOOT_STARTS_IN_ROMSTAGE) && \ + !IS_ENABLED(CONFIG_VBOOT_STAGE_VERIFICATION) static void vb2_fill_handoff_cbmem(int unused) { vboot_fill_handoff(); } ROMSTAGE_CBMEM_INIT_HOOK(vb2_fill_handoff_cbmem) #endif + diff --git a/src/security/vboot/vboot_loader.c b/src/security/vboot/vboot_loader.c index 0640ebd..e09a314 100644 --- a/src/security/vboot/vboot_loader.c +++ b/src/security/vboot/vboot_loader.c @@ -2,6 +2,7 @@ * This file is part of the coreboot project. * * Copyright 2015 Google, Inc. + * Copyright 2019 Intel Corp. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -60,6 +61,16 @@ return 0; }
+/* This is the helper function that decides when the stage verification + * code should be called. */ +static int stage_verification_should_run(void) +{ + if (IS_ENABLED(CONFIG_VBOOT_STAGE_VERIFICATION)) + return ENV_POSTCAR | ENV_RAMSTAGE; + + return 0; +} + static int vboot_executed CAR_GLOBAL;
int vboot_logic_executed(void) @@ -86,9 +97,11 @@
static void vboot_prepare(void) { - if (verification_should_run()) { + if (verification_should_run() || + stage_verification_should_run()) { /* Note: this path is not used for VBOOT_RETURN_FROM_VERSTAGE */ verstage_main(); + car_set_var(vboot_executed, 1); vboot_save_recovery_reason_vbnv(); } else if (verstage_should_load()) { @@ -154,3 +167,4 @@ .prepare = vboot_prepare, .locate = vboot_locate, }; + diff --git a/src/security/vboot/vboot_logic_ex.c b/src/security/vboot/vboot_logic_ex.c new file mode 100644 index 0000000..7a735a9 --- /dev/null +++ b/src/security/vboot/vboot_logic_ex.c @@ -0,0 +1,326 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2019 Intel Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <security/tpm/antirollback.h> +#include <arch/exception.h> +#include <assert.h> +#include <bootmode.h> +#include <console/console.h> +#include <console/vtxprintf.h> +#include <delay.h> +#include <string.h> +#include <timestamp.h> +#include <vb2_api.h> +#include <security/vboot/misc.h> +#include <security/vboot/vbnv.h> + +#include <cbfs.h> +#include <cbmem.h> +#include <rmodule.h> + +/* For individual stage verification design, only + * RW Region A is relevant. So, force CBFS to bot + * from RW Region A */ +static void reset_fw_slot(struct vb2_context *ctx) +{ + ctx->flags &= ~VB2_CONTEXT_FW_SLOT_B; +} + +/* Decide which RW region we are booting from */ +static int is_slot_a(struct vb2_context *ctx) +{ + return !(ctx->flags & VB2_CONTEXT_FW_SLOT_B); +} + +/* exports */ + +void vb2ex_printf (const char *func, const char *fmt, ...) +{ + va_list args; + + if (func) + printk(BIOS_INFO, "VB2:%s() ", func); + + va_start(args, fmt); + vprintk(BIOS_INFO, fmt, args); + va_end(args); + + return; +} + +int vb2ex_tpm_clear_owner(struct vb2_context *ctx) +{ + uint32_t rv; + printk(BIOS_INFO, "Clearing TPM owner\n"); + rv = tpm_clear_and_reenable(); + if (rv) + return VB2_ERROR_EX_TPM_CLEAR_OWNER; + return VB2_SUCCESS; +} + +int vb2ex_read_resource(struct vb2_context *ctx, + enum vb2_resource_index index, + uint32_t offset, + void *buf, + uint32_t size) +{ + struct region_device rdev; + const char *name; + + switch (index) { + case VB2_RES_GBB: + name = "GBB"; + break; + case VB2_RES_FW_VBLOCK: + if (is_slot_a(ctx)) + name = "VBLOCK_A"; + else + name = "VBLOCK_B"; + break; + default: + return VB2_ERROR_EX_READ_RESOURCE_INDEX; + } + + if (vboot_named_region_device(name, &rdev)) + return VB2_ERROR_EX_READ_RESOURCE_SIZE; + + if (rdev_readat(&rdev, buf, offset, size) != size) + return VB2_ERROR_EX_READ_RESOURCE_SIZE; + + return VB2_SUCCESS; +} + +/* No-op stubs that can be overridden by SoCs with hardware crypto support. */ +__attribute__((weak)) +int vb2ex_hwcrypto_digest_init(enum vb2_hash_algorithm hash_alg, + uint32_t data_size) +{ + return VB2_ERROR_EX_HWCRYPTO_UNSUPPORTED; +} + +__attribute__((weak)) +int vb2ex_hwcrypto_digest_extend(const uint8_t *buf, uint32_t size) +{ + BUG(); /* Should never get called if init() returned an error. */ + return VB2_ERROR_UNKNOWN; +} + +__attribute__((weak)) +int vb2ex_hwcrypto_digest_finalize(uint8_t *digest, uint32_t digest_size) +{ + BUG(); /* Should never get called if init() returned an error. */ + return VB2_ERROR_UNKNOWN; +} + +static int locate_firmware(struct vb2_context *ctx, + struct region_device *fw_main) +{ + const char *name = "FW_MAIN_A"; + + if (is_slot_a(ctx)) + name = "FW_MAIN_A"; + else + name = "FW_MAIN_B"; + + return vboot_named_region_device(name, fw_main); +} + +/** + * Save non-volatile and/or secure data if needed. + */ +static void save_if_needed(struct vb2_context *ctx) +{ + if (ctx->flags & VB2_CONTEXT_NVDATA_CHANGED) { + printk(BIOS_INFO, "Saving nvdata\n"); + save_vbnv(ctx->nvdata); + ctx->flags &= ~VB2_CONTEXT_NVDATA_CHANGED; + } + if (ctx->flags & VB2_CONTEXT_SECDATA_CHANGED) { + printk(BIOS_INFO, "Saving secdata\n"); + antirollback_write_space_firmware(ctx); + ctx->flags &= ~VB2_CONTEXT_SECDATA_CHANGED; + } +} + +/* VB2 context initialization helper function */ +static void init_ctx(struct vb2_context *ctx) +{ + int rv; + + /* Set up context and work buffer */ + vboot_init_work_context(ctx); + + /* Initialize and read nvdata from non-volatile storage. */ + vbnv_init(ctx->nvdata); + + /* This function is required as it reads secdata (use mock secdat) + * If secdata is not valid, call to vb2api_fw_phase1 will fail. So, + * even if this is not required in the current context, call it. */ + antirollback_read_space_firmware(ctx); + + /* Do early init (set up secdata and NVRAM, load GBB) */ + printk(BIOS_INFO, "Phase 1\n"); + rv = vb2api_fw_phase1(ctx); + if (rv) { + printk(BIOS_INFO, "Reboot requested (%x)\n", rv); + save_if_needed(ctx); + vboot_reboot(); + } + + /* Determine which firmware slot to boot (based on NVRAM) */ + printk(BIOS_INFO, "Phase 2\n"); + rv = vb2api_fw_phase2(ctx); + reset_fw_slot(ctx); + if (rv) { + printk(BIOS_INFO, "Reboot requested (%x)\n", rv); + save_if_needed(ctx); + vboot_reboot(); + } +} + +/* hash verification helper function */ +static int verify_hash(struct vb2_context *ctx, void *map, + const struct vb2_id *id) +{ + int rv; + uint32_t size = 0; + + printk(BIOS_INFO, "Phase 4\n"); + + /* init hash */ + rv = vb21api_init_hash(ctx, id, &size); + if (rv) + return rv; + + /* extend hash over the body */ + rv = vb2api_extend_hash(ctx,(uint8_t *)map, size); + if (rv) + return rv; + + /* check hash */ + rv = vb21api_check_hash(ctx); + if (rv) + return rv; + + return rv; +} + +/* initialize the VB2 context in VERStage, so + * we know which RW partition to boot the rest + * of the stages from */ +static void init_ctx_verstage(void) +{ + struct vb2_context ctx; + struct region_device fw_main; + int rv; + + init_ctx(&ctx); + + rv = locate_firmware(&ctx, &fw_main); + if (rv) + die("Failed to read FMAP to locate firmware"); + + printk(BIOS_INFO, "Slot %c is selected\n", is_slot_a(&ctx) ? 'A' : 'B'); + + vboot_set_selected_region(region_device_region(&fw_main)); +} + +/* Veify the stage to be executed */ +static void verify_stage(void) +{ + struct vb2_context ctx; + struct region_device fw_main; + int rv; + const struct region_device *fh = NULL; + size_t fsize = 0; + void *map = NULL; + struct cbfsf file; + const struct vb2_id* id; + + /* For each stage to be verified, extract map and + * hashing algo */ + if (ENV_POSTCAR) { + printk(BIOS_INFO, "Verify ramstage\n"); + id = vb2_hash_id(VB2_HASH_SHA256); + struct prog stage = PROG_INIT(PROG_RAMSTAGE, + CONFIG_CBFS_PREFIX "/ramstage"); + + /* load stage */ + if (cbfs_boot_locate(&file, prog_name(&stage), NULL)) + die("failed to load stage"); + + cbfs_file_data(prog_rdev(&stage), &file); + fh = &stage.rdev; + + fsize = region_device_sz(fh); + map = rdev_mmap(fh, 0, fsize); + if (!map) printk(BIOS_INFO, "ERROR: Mapping failed\n"); + } else if (ENV_RAMSTAGE) { + printk(BIOS_INFO, "Verify payload\n"); + id = vb2_hash_id(VB2_HASH_SHA512); + struct prog stage = PROG_INIT(PROG_PAYLOAD, + CONFIG_CBFS_PREFIX "/payload"); + + /* load stage */ + if (cbfs_boot_locate(&file, prog_name(&stage), NULL)) + die("failed to load stage"); + + cbfs_file_data(prog_rdev(&stage), &file); + fh = &stage.rdev; + + fsize = region_device_sz(fh); + map = rdev_mmap(fh, 0, fsize); + if (!map) printk(BIOS_INFO, "ERROR: Mapping failed\n"); + } else + die("Impossible"); + + //get_stage_attr(&map, &id); + /* initialize the vb context and read the NV data */ + init_ctx(&ctx); + + rv = locate_firmware(&ctx, &fw_main); + if (rv) + die("Failed to read FMAP to locate firmware"); + + /* Try the slot (verify its keyblock and preamble) */ + printk(BIOS_INFO, "Phase 3\n"); + rv = vb21api_fw_phase3(&ctx); + if (rv) { + printk(BIOS_INFO, "Reboot requested (%x)\n", rv); + save_if_needed(&ctx); + vboot_reboot(); + } + + /* verify the hash */ + rv = verify_hash(&ctx, map, id); + if (rv) { + printk(BIOS_ERR, "ERROR:0x%x ", rv); + die("Stage Verification Failed"); + } + + rdev_munmap(fh, map); + + printk(BIOS_INFO, "stage verified successfully, proceed...\n"); +} + +/* Main Entry Point for Stage Verification */ +void verstage_main(void) +{ + if (ENV_VERSTAGE) + init_ctx_verstage(); + else if (ENV_POSTCAR || ENV_RAMSTAGE) + verify_stage(); +} +