From 6d720f38e06d14cc8a89635f66dc124dcd5ac150 Mon Sep 17 00:00:00 2001 From: Aaron Durbin Date: Tue, 8 Dec 2015 17:00:23 -0600 Subject: cbfs/vboot: remove firmware component support The Chrome OS verified boot path supported multiple CBFS instances in the boot media as well as stand-alone assets sitting in each vboot RW slot. Remove the support for the stand-alone assets and always use CBFS accesses as the way to retrieve data. This is implemented by adding a cbfs_locator object which is queried for locating the current CBFS. Additionally, it is also signalled prior to when a program is about to be loaded by coreboot for the subsequent stage/payload. This provides the same opportunity as previous for vboot to hook in and perform its logic. BUG=chromium:445938 BRANCH=None TEST=Built and ran on glados. CQ-DEPEND=CL:307121,CL:31691,CL:31690 Change-Id: I6a3a15feb6edd355d6ec252c36b6f7885b383099 Signed-off-by: Aaron Durbin Reviewed-on: https://review.coreboot.org/12689 Tested-by: build bot (Jenkins) Tested-by: Raptor Engineering Automated Test Stand Reviewed-by: Patrick Georgi Reviewed-by: Stefan Reinauer --- src/vendorcode/google/chromeos/Kconfig | 1 + src/vendorcode/google/chromeos/vboot2/Kconfig | 51 -------- src/vendorcode/google/chromeos/vboot2/common.c | 24 ++-- src/vendorcode/google/chromeos/vboot2/misc.h | 7 +- .../google/chromeos/vboot2/vboot_handoff.c | 31 ----- .../google/chromeos/vboot2/vboot_loader.c | 130 +++++++-------------- .../google/chromeos/vboot2/vboot_logic.c | 2 +- src/vendorcode/google/chromeos/vboot_handoff.h | 18 +-- 8 files changed, 62 insertions(+), 202 deletions(-) (limited to 'src/vendorcode') diff --git a/src/vendorcode/google/chromeos/Kconfig b/src/vendorcode/google/chromeos/Kconfig index aae611cde2..87fc024b61 100644 --- a/src/vendorcode/google/chromeos/Kconfig +++ b/src/vendorcode/google/chromeos/Kconfig @@ -28,6 +28,7 @@ config CHROMEOS select ELOG if SPI_FLASH select COLLECT_TIMESTAMPS select VBOOT_VERIFY_FIRMWARE + select MULTIPLE_CBFS_INSTANCES help Enable ChromeOS specific features like the GPIO sub table in the coreboot table. NOTE: Enabling this option on an unsupported diff --git a/src/vendorcode/google/chromeos/vboot2/Kconfig b/src/vendorcode/google/chromeos/vboot2/Kconfig index 66659ddad1..7580d8d50c 100644 --- a/src/vendorcode/google/chromeos/vboot2/Kconfig +++ b/src/vendorcode/google/chromeos/vboot2/Kconfig @@ -68,57 +68,6 @@ config CHIPSET_PROVIDES_VERSTAGE_MAIN_SYMBOL help The chipset code provides their own main() entry point. -# These VBOOT_X_INDEX are the position of X in FW_MAIN_A/B region. The index -# table is created by cros_bundle_firmware at build time based on the positions -# of the blobs listed in fmap.dts and stored at the top of FW_MAIN_A/B region. -# Unfortunately, there is no programmatical link between the blob list and the -# index number here. -config VBOOT_ROMSTAGE_INDEX - hex "Romstage component index" - default 2 - depends on VBOOT_VERIFY_FIRMWARE - help - This is the index of the romstage component in the verified - firmware block. - -config VBOOT_RAMSTAGE_INDEX - hex "Ramstage component index" - default 1 - depends on VBOOT_VERIFY_FIRMWARE - help - This is the index of the ramstage component in the verified - firmware block. - -config VBOOT_REFCODE_INDEX - hex "Reference code firmware index" - default 1 - depends on VBOOT_VERIFY_FIRMWARE - help - This is the index of the reference code component in the verified - firmware block. - -config VBOOT_BOOT_LOADER_INDEX - hex "Bootloader component index" - default 0 - depends on VBOOT_VERIFY_FIRMWARE - help - This is the index of the bootloader component in the verified - firmware block. - -config VBOOT_SECURE_OS_INDEX - hex "ARM64 Secure OS index" - default 0x5 - depends on VBOOT_VERIFY_FIRMWARE - help - Secure OS software component used on ARM64 machines. - -config VBOOT_BL31_INDEX - hex "ARM64 BL31 index" - default 0x4 - depends on VBOOT_VERIFY_FIRMWARE - help - This is the index of the BL31 program on ARM64 machines. - config VBOOT_DYNAMIC_WORK_BUFFER bool "Vboot's work buffer is dynamically allocated." default y if ARCH_ROMSTAGE_X86_32 && !SEPARATE_VERSTAGE diff --git a/src/vendorcode/google/chromeos/vboot2/common.c b/src/vendorcode/google/chromeos/vboot2/common.c index fbad1126f8..4282408535 100644 --- a/src/vendorcode/google/chromeos/vboot2/common.c +++ b/src/vendorcode/google/chromeos/vboot2/common.c @@ -115,21 +115,27 @@ struct vb2_shared_data *vb2_get_shared_data(void) return (void *)((uintptr_t)wd + wd->buffer_offset); } -int vb2_get_selected_region(struct region_device *rdev) +int vb2_get_selected_region(struct region *region) { const struct selected_region *reg = vb2_selected_region(); - struct region region = { - .offset = reg->offset, - .size = reg->size, - }; - return vboot_region_device(®ion, rdev); + + if (reg == NULL) + return -1; + + if (reg->offset == 0 && reg->size == 0) + return -1; + + region->offset = reg->offset; + region->size = reg->size; + + return 0; } -void vb2_set_selected_region(struct region_device *rdev) +void vb2_set_selected_region(const struct region *region) { struct selected_region *reg = vb2_selected_region(); - reg->offset = region_device_offset(rdev); - reg->size = region_device_sz(rdev); + reg->offset = region_offset(region); + reg->size = region_sz(region); } int vboot_is_slot_selected(void) diff --git a/src/vendorcode/google/chromeos/vboot2/misc.h b/src/vendorcode/google/chromeos/vboot2/misc.h index 75874c86b8..fc9d2547cb 100644 --- a/src/vendorcode/google/chromeos/vboot2/misc.h +++ b/src/vendorcode/google/chromeos/vboot2/misc.h @@ -22,16 +22,13 @@ struct vb2_context; struct vb2_shared_data; void vboot_fill_handoff(void); -void *vboot_load_stage(int stage_index, - struct region *fw_main, - struct vboot_components *fw_info); void vb2_init_work_context(struct vb2_context *ctx); struct vb2_shared_data *vb2_get_shared_data(void); /* Returns 0 on success. < 0 on failure. */ -int vb2_get_selected_region(struct region_device *rdev); -void vb2_set_selected_region(struct region_device *rdev); +int vb2_get_selected_region(struct region *region); +void vb2_set_selected_region(const struct region *region); int vboot_is_slot_selected(void); int vboot_is_readonly_path(void); diff --git a/src/vendorcode/google/chromeos/vboot2/vboot_handoff.c b/src/vendorcode/google/chromeos/vboot2/vboot_handoff.c index dc3515f459..246aefecee 100644 --- a/src/vendorcode/google/chromeos/vboot2/vboot_handoff.c +++ b/src/vendorcode/google/chromeos/vboot2/vboot_handoff.c @@ -120,12 +120,8 @@ static void fill_vboot_handoff(struct vboot_handoff *vboot_handoff, void vboot_fill_handoff(void) { - int i; struct vboot_handoff *vh; struct vb2_shared_data *sd; - struct region_device fw_main; - struct vboot_components *fw_info; - size_t metadata_sz; sd = vb2_get_shared_data(); sd->workbuf_hash_offset = 0; @@ -142,33 +138,6 @@ void vboot_fill_handoff(void) /* needed until we finish transtion to vboot2 for kernel verification */ fill_vboot_handoff(vh, sd); - - /* Nothing left to do in readonly path. */ - if (vboot_is_readonly_path()) - return; - - if (IS_ENABLED(CONFIG_MULTIPLE_CBFS_INSTANCES)) - return; - - if (vb2_get_selected_region(&fw_main)) - die("No component metadata.\n"); - - metadata_sz = sizeof(*fw_info); - metadata_sz += MAX_PARSED_FW_COMPONENTS * sizeof(fw_info->entries[0]); - - fw_info = rdev_mmap(&fw_main, 0, metadata_sz); - - if (fw_info == NULL) - die("failed to locate firmware components\n"); - - /* these offset & size are used to load a rw boot loader */ - for (i = 0; i < fw_info->num_components; i++) { - vh->components[i].address = region_device_offset(&fw_main); - vh->components[i].address += fw_info->entries[i].offset; - vh->components[i].size = fw_info->entries[i].size; - } - - rdev_munmap(&fw_main, fw_info); } /* diff --git a/src/vendorcode/google/chromeos/vboot2/vboot_loader.c b/src/vendorcode/google/chromeos/vboot2/vboot_loader.c index b5570dd7ca..5fdd0261cf 100644 --- a/src/vendorcode/google/chromeos/vboot2/vboot_loader.c +++ b/src/vendorcode/google/chromeos/vboot2/vboot_loader.c @@ -13,7 +13,7 @@ * GNU General Public License for more details. */ -#include +#include #include #include #include @@ -59,7 +59,34 @@ static int verstage_should_load(void) return 0; } -static int vboot_active(struct asset *asset) +static int vboot_executed CAR_GLOBAL; + +static int vboot_logic_executed(void) +{ + /* If this stage is supposed to run the vboot logic ensure it has been + * executed. */ + if (verification_should_run() && car_get_var(vboot_executed)) + return 1; + + /* If this stage is supposed to load verstage and verstage is returning + * back to the calling stage check that it has been executed. */ + if (verstage_should_load() && IS_ENABLED(CONFIG_RETURN_FROM_VERSTAGE)) + if (car_get_var(vboot_executed)) + return 1; + + /* Handle all other stages post vboot execution. */ + if (!ENV_BOOTBLOCK) { + if (IS_ENABLED(CONFIG_VBOOT_STARTS_IN_BOOTBLOCK)) + return 1; + if (IS_ENABLED(CONFIG_VBOOT_STARTS_IN_ROMSTAGE) && + !ENV_ROMSTAGE) + return 1; + } + + return 0; +} + +static void vboot_prepare(void) { int run_verification; @@ -67,6 +94,7 @@ static int vboot_active(struct asset *asset) if (run_verification) { verstage_main(); + car_set_var(vboot_executed, 1); } else if (verstage_should_load()) { struct cbfsf file; struct prog verstage = @@ -91,7 +119,9 @@ static int vboot_active(struct asset *asset) * runtime, but this provides a hint to the compiler for dead * code elimination below. */ if (!IS_ENABLED(CONFIG_RETURN_FROM_VERSTAGE)) - return 0; + return; + + car_set_var(vboot_executed, 1); } /* @@ -106,103 +136,27 @@ static int vboot_active(struct asset *asset) vb2_store_selected_region(); vboot_fill_handoff(); } - - return vboot_is_slot_selected(); } -static int vboot_locate_by_components(const struct region_device *fw_main, - struct asset *asset) +static int vboot_locate(struct cbfs_props *props) { - struct vboot_components *fw_info; - size_t metadata_sz; - size_t offset; - size_t size; - struct region_device *fw = asset_rdev(asset); - int fw_index = 0; - - if (asset_type(asset) == ASSET_ROMSTAGE) - fw_index = CONFIG_VBOOT_ROMSTAGE_INDEX; - else if (asset_type(asset) == ASSET_RAMSTAGE) - fw_index = CONFIG_VBOOT_RAMSTAGE_INDEX; - else if (asset_type(asset) == ASSET_PAYLOAD) - fw_index = CONFIG_VBOOT_BOOT_LOADER_INDEX; - else if (asset_type(asset) == ASSET_REFCODE) - fw_index = CONFIG_VBOOT_REFCODE_INDEX; - else if (asset_type(asset) == ASSET_BL31) - fw_index = CONFIG_VBOOT_BL31_INDEX; - else - die("Invalid program type for vboot."); - - metadata_sz = sizeof(*fw_info); - metadata_sz += MAX_PARSED_FW_COMPONENTS * sizeof(fw_info->entries[0]); - - fw_info = rdev_mmap(fw_main, 0, metadata_sz); - - if (fw_info == NULL) { - printk(BIOS_INFO, "No component metadata.\n"); - return -1; - } + struct region selected_region; - if (fw_index >= fw_info->num_components) { - printk(BIOS_INFO, "invalid index: %d\n", fw_index); - rdev_munmap(fw_main, fw_info); + /* Don't honor vboot results until the vboot logic has run. */ + if (!vboot_logic_executed()) return -1; - } - - offset = fw_info->entries[fw_index].offset; - size = fw_info->entries[fw_index].size; - rdev_munmap(fw_main, fw_info); - if (rdev_chain(fw, fw_main, offset, size)) { - printk(BIOS_INFO, "invalid offset or size\n"); + if (vb2_get_selected_region(&selected_region)) return -1; - } - return 0; -} - -static int vboot_locate_by_multi_cbfs(const struct region_device *fw_main, - struct asset *asset) -{ - struct cbfsf file; - - if (cbfs_locate(&file, fw_main, asset_name(asset), NULL)) - return -1; - - cbfs_file_data(asset_rdev(asset), &file); + props->offset = region_offset(&selected_region); + props->size = region_sz(&selected_region); return 0; } -static int vboot_asset_locate(const struct region_device *fw_main, - struct asset *asset) -{ - if (IS_ENABLED(CONFIG_MULTIPLE_CBFS_INSTANCES)) - return vboot_locate_by_multi_cbfs(fw_main, asset); - else - return vboot_locate_by_components(fw_main, asset); -} - -/* This function is only called when vboot_active() returns 1. That - * means we are taking vboot paths. */ -static int vboot_locate(struct asset *asset) -{ - struct region_device fw_main; - - /* Code size optimization. We'd never actually get called under the - * followin cirumstances because verstage was loaded and ran -- never - * returning. */ - if (verstage_should_load() && !IS_ENABLED(CONFIG_RETURN_FROM_VERSTAGE)) - return 0; - - if (vb2_get_selected_region(&fw_main)) - die("failed to reference selected region\n"); - - return vboot_asset_locate(&fw_main, asset); -} - -const struct asset_provider vboot_provider = { +const struct cbfs_locator vboot_locator = { .name = "VBOOT", - .is_active = vboot_active, + .prepare = vboot_prepare, .locate = vboot_locate, }; diff --git a/src/vendorcode/google/chromeos/vboot2/vboot_logic.c b/src/vendorcode/google/chromeos/vboot2/vboot_logic.c index c580829d52..b72de93245 100644 --- a/src/vendorcode/google/chromeos/vboot2/vboot_logic.c +++ b/src/vendorcode/google/chromeos/vboot2/vboot_logic.c @@ -323,6 +323,6 @@ void verstage_main(void) } printk(BIOS_INFO, "Slot %c is selected\n", is_slot_a(&ctx) ? 'A' : 'B'); - vb2_set_selected_region(&fw_main); + vb2_set_selected_region(region_device_region(&fw_main)); timestamp_add_now(TS_END_VBOOT); } diff --git a/src/vendorcode/google/chromeos/vboot_handoff.h b/src/vendorcode/google/chromeos/vboot_handoff.h index 4b88e829a6..f06044403d 100644 --- a/src/vendorcode/google/chromeos/vboot_handoff.h +++ b/src/vendorcode/google/chromeos/vboot_handoff.h @@ -21,30 +21,14 @@ #include "chromeos.h" #include "vboot_common.h" -/* - * The vboot handoff structure keeps track of a maximum number of firmware - * components in the verfieid RW area of flash. This is not a restriction on - * the number of components packed in a firmware block. It's only the maximum - * number of parsed firmware components (address and size) included in the - * handoff structure. - */ -#define MAX_PARSED_FW_COMPONENTS 6 - -struct firmware_component { - uint32_t address; - uint32_t size; -} __attribute__((packed)); - /* * The vboot_handoff structure contains the data to be consumed by downstream * firmware after firmware selection has been completed. Namely it provides - * vboot shared data as well as the flags from VbInit. As noted above a finite - * number of components are parsed from the verfieid firmare region. + * vboot shared data as well as the flags from VbInit. */ struct vboot_handoff { VbInitParams init_params; uint32_t selected_firmware; - struct firmware_component components[MAX_PARSED_FW_COMPONENTS]; char shared_data[VB_SHARED_DATA_MIN_SIZE]; } __attribute__((packed)); -- cgit v1.2.3