diff options
-rw-r--r-- | src/vendorcode/google/chromeos/vbnv_flash.c | 28 | ||||
-rw-r--r-- | src/vendorcode/google/chromeos/vboot2/misc.h | 18 | ||||
-rw-r--r-- | src/vendorcode/google/chromeos/vboot2/vboot_handoff.c | 19 | ||||
-rw-r--r-- | src/vendorcode/google/chromeos/vboot2/vboot_loader.c | 67 | ||||
-rw-r--r-- | src/vendorcode/google/chromeos/vboot2/verstage.c | 43 | ||||
-rw-r--r-- | src/vendorcode/google/chromeos/vboot_common.c | 45 | ||||
-rw-r--r-- | src/vendorcode/google/chromeos/vboot_common.h | 14 |
7 files changed, 104 insertions, 130 deletions
diff --git a/src/vendorcode/google/chromeos/vbnv_flash.c b/src/vendorcode/google/chromeos/vbnv_flash.c index 976793a6a7..656c3ea2a2 100644 --- a/src/vendorcode/google/chromeos/vbnv_flash.c +++ b/src/vendorcode/google/chromeos/vbnv_flash.c @@ -19,8 +19,6 @@ * TODO: Make this CAR-friendly in case we use it on x86 some day. */ -#include <cbfs.h> -#include <cbfs_core.h> #include <console/console.h> #include <spi_flash.h> #include <string.h> @@ -32,7 +30,7 @@ #define BLOB_SIZE VB2_NVDATA_SIZE /* FMAP descriptor of the NVRAM area */ -static struct region nvram_region; +static struct region_device nvram_region; /* offset of the current nvdata in SPI flash */ static int blob_offset = -1; @@ -73,8 +71,8 @@ static int init_vbnv(void) int offset; int i; - vboot_locate_region("RW_NVRAM", &nvram_region); - if (region_sz(&nvram_region) < BLOB_SIZE) { + if (vboot_named_region_device("RW_NVRAM", &nvram_region) || + region_device_sz(&nvram_region) < BLOB_SIZE) { printk(BIOS_ERR, "%s: failed to locate NVRAM\n", __func__); return 1; } @@ -83,8 +81,8 @@ static int init_vbnv(void) for (i = 0; i < BLOB_SIZE; i++) empty_blob[i] = erase_value(); - offset = region_offset(&nvram_region); - top_offset = offset + region_sz(&nvram_region) - BLOB_SIZE; + offset = 0; + top_offset = region_device_sz(&nvram_region) - BLOB_SIZE; /* * after the loop, offset is supposed to point the blob right before @@ -92,8 +90,8 @@ static int init_vbnv(void) * empty blob, or the base of the region if the nvram has never been * used. */ - for (i = offset; i <= top_offset; i += BLOB_SIZE) { - if (vboot_get_region(i, BLOB_SIZE, buf) == NULL) { + for (i = 0; i <= top_offset; i += BLOB_SIZE) { + if (rdev_readat(&nvram_region, buf, i, BLOB_SIZE) < 0) { printk(BIOS_ERR, "failed to read nvdata\n"); return 1; } @@ -103,7 +101,7 @@ static int init_vbnv(void) } /* reread the nvdata and write it to the cache */ - if (vboot_get_region(offset, BLOB_SIZE, cache) == NULL) { + if (rdev_readat(&nvram_region, cache, offset, BLOB_SIZE) < 0) { printk(BIOS_ERR, "failed to read nvdata\n"); return 1; } @@ -130,8 +128,8 @@ static int erase_nvram(void) if (vbnv_flash_probe()) return 1; - if (spi_flash->erase(spi_flash, region_offset(&nvram_region), - region_sz(&nvram_region))) { + if (spi_flash->erase(spi_flash, region_device_offset(&nvram_region), + region_device_sz(&nvram_region))) { printk(BIOS_ERR, "failed to erase nvram\n"); return 1; } @@ -171,14 +169,16 @@ void save_vbnv(const uint8_t *vbnv_copy) if (new_offset > top_offset) { if (erase_nvram()) return; /* error */ - new_offset = region_offset(&nvram_region); + new_offset = 0; } break; } } if (!vbnv_flash_probe() && - !spi_flash->write(spi_flash, new_offset, BLOB_SIZE, vbnv_copy)) { + !spi_flash->write(spi_flash, + region_device_offset(&nvram_region) + new_offset, + BLOB_SIZE, vbnv_copy)) { /* write was successful. safely move pointer forward */ blob_offset = new_offset; memcpy(cache, vbnv_copy, BLOB_SIZE); diff --git a/src/vendorcode/google/chromeos/vboot2/misc.h b/src/vendorcode/google/chromeos/vboot2/misc.h index 1b3f41eb6f..d4f9f48cf0 100644 --- a/src/vendorcode/google/chromeos/vboot2/misc.h +++ b/src/vendorcode/google/chromeos/vboot2/misc.h @@ -46,18 +46,22 @@ struct vb2_working_data * const vboot_get_working_data(void); size_t vb2_working_data_size(void); void *vboot_get_work_buffer(struct vb2_working_data *wd); -static inline void vb2_get_selected_region(struct vb2_working_data *wd, - struct region *region) +/* Returns 0 on success. < 0 on failure. */ +static inline int vb2_get_selected_region(struct vb2_working_data *wd, + struct region_device *rdev) { - region->offset = wd->selected_region_offset; - region->size = wd->selected_region_size; + struct region reg = { + .offset = wd->selected_region_offset, + .size = wd->selected_region_size, + }; + return vboot_region_device(®, rdev); } static inline void vb2_set_selected_region(struct vb2_working_data *wd, - struct region *region) + struct region_device *rdev) { - wd->selected_region_offset = region_offset(region); - wd->selected_region_size = region_sz(region); + wd->selected_region_offset = region_device_offset(rdev); + wd->selected_region_size = region_device_sz(rdev); } static inline int vboot_is_slot_selected(struct vb2_working_data *wd) diff --git a/src/vendorcode/google/chromeos/vboot2/vboot_handoff.c b/src/vendorcode/google/chromeos/vboot2/vboot_handoff.c index e7e0d99632..955d72fa43 100644 --- a/src/vendorcode/google/chromeos/vboot2/vboot_handoff.c +++ b/src/vendorcode/google/chromeos/vboot2/vboot_handoff.c @@ -127,8 +127,9 @@ void vboot_fill_handoff(void) int i; struct vboot_handoff *vh; struct vb2_shared_data *sd; - struct region fw_main; + struct region_device fw_main; struct vboot_components *fw_info; + size_t metadata_sz; struct vb2_working_data *wd = vboot_get_working_data(); sd = vboot_get_work_buffer(wd); @@ -151,15 +152,23 @@ void vboot_fill_handoff(void) if (vboot_is_readonly_path(wd)) return; - vb2_get_selected_region(wd, &fw_main); - fw_info = vboot_locate_components(&fw_main); + if (vb2_get_selected_region(wd, &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_offset(&fw_main) + fw_info->entries[i].offset; + 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 1129cd13c3..226578bc8c 100644 --- a/src/vendorcode/google/chromeos/vboot2/vboot_loader.c +++ b/src/vendorcode/google/chromeos/vboot2/vboot_loader.c @@ -25,6 +25,7 @@ #include <rules.h> #include <string.h> #include "misc.h" +#include "../vboot_handoff.h" #include "../symbols.h" /* The stage loading code is compiled and entered from multiple stages. The @@ -121,10 +122,11 @@ static int vboot_loader_active(struct prog *prog) if (IS_ENABLED(CONFIG_MULTIPLE_CBFS_INSTANCES) && run_verification) { /* RW A or B */ - struct region fw_main; + struct region_device fw_main; - vb2_get_selected_region(wd, &fw_main); - cbfs_set_header_offset(region_offset(&fw_main)); + if (vb2_get_selected_region(wd, &fw_main)) + die("failed to reference selected region\n"); + cbfs_set_header_offset(region_device_offset(&fw_main)); } return 1; } @@ -132,25 +134,35 @@ static int vboot_loader_active(struct prog *prog) return 0; } -static int vboot_fw_region(int fw_index, struct region *fw_main, - struct vboot_components *fw_info, - struct region *fc) +static int vboot_fw_region(int fw_index, const struct region_device *fw_main, + struct region_device *fw) { - size_t fw_main_end; - size_t fc_end; + struct vboot_components *fw_info; + size_t metadata_sz; + size_t offset; + size_t size; + + 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; + } if (fw_index >= fw_info->num_components) { printk(BIOS_INFO, "invalid stage index: %d\n", fw_index); + rdev_munmap(fw_main, fw_info); return -1; } - fc->offset = region_offset(fw_main) + fw_info->entries[fw_index].offset; - fc->size = fw_info->entries[fw_index].size; + offset = fw_info->entries[fw_index].offset; + size = fw_info->entries[fw_index].size; + rdev_munmap(fw_main, fw_info); - fw_main_end = region_offset(fw_main) + region_sz(fw_main); - fc_end = region_offset(fc) + region_sz(fc); - - if (region_sz(fc) == 0 || fc_end > fw_main_end) { + if (rdev_chain(fw, fw_main, offset, size)) { printk(BIOS_INFO, "invalid stage address or size\n"); return -1; } @@ -163,8 +175,7 @@ static int vboot_fw_region(int fw_index, struct region *fw_main, static int vboot_prepare(struct prog *prog) { struct vb2_working_data *wd; - struct region fw_main; - struct vboot_components *fw_info; + 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 @@ -198,29 +209,26 @@ static int vboot_prepare(struct prog *prog) } wd = vboot_get_working_data(); - vb2_get_selected_region(wd, &fw_main); - fw_info = vboot_locate_components(&fw_main); - if (fw_info == NULL) - die("failed to locate firmware components\n"); + if (vb2_get_selected_region(wd, &fw_main)) + die("failed to reference selected region\n"); /* Load payload in ramstage. */ if (ENV_RAMSTAGE) { - struct region payload; + struct region_device payload; void *payload_ptr; if (vboot_fw_region(CONFIG_VBOOT_BOOT_LOADER_INDEX, - &fw_main, fw_info, &payload)) + &fw_main, &payload)) die("Couldn't load payload."); - payload_ptr = vboot_get_region(region_offset(&payload), - region_sz(&payload), NULL); + payload_ptr = rdev_mmap_full(&payload); if (payload_ptr == NULL) die("Couldn't load payload."); - prog_set_area(prog, payload_ptr, region_sz(&payload)); + prog_set_area(prog, payload_ptr, region_device_sz(&payload)); } else { - struct region stage; + struct region_device stage; int stage_index = 0; if (prog->type == PROG_ROMSTAGE) @@ -230,7 +238,7 @@ static int vboot_prepare(struct prog *prog) else die("Invalid program type for vboot."); - if (vboot_fw_region(stage_index, &fw_main, fw_info, &stage)) + if (vboot_fw_region(stage_index, &fw_main, &stage)) die("Vboot stage load failed."); if (ENV_ROMSTAGE && IS_ENABLED(CONFIG_RELOCATABLE_RAMSTAGE)) { @@ -240,8 +248,7 @@ static int vboot_prepare(struct prog *prog) .prog = prog, }; - stage_ptr = vboot_get_region(region_offset(&stage), - region_sz(&stage), NULL); + stage_ptr = rdev_mmap_full(&stage); if (stage_ptr == NULL) die("Vboot couldn't load stage."); @@ -249,7 +256,7 @@ static int vboot_prepare(struct prog *prog) if (rmodule_stage_load(&rmod_ram, stage_ptr)) die("Vboot couldn't load stage"); } else { - size_t offset = region_offset(&stage); + size_t offset = region_device_offset(&stage); if (cbfs_load_prog_stage_by_offset(CBFS_DEFAULT_MEDIA, prog, offset)) diff --git a/src/vendorcode/google/chromeos/vboot2/verstage.c b/src/vendorcode/google/chromeos/vboot2/verstage.c index 249053cffe..bc7846a37d 100644 --- a/src/vendorcode/google/chromeos/vboot2/verstage.c +++ b/src/vendorcode/google/chromeos/vboot2/verstage.c @@ -67,27 +67,28 @@ int vb2ex_read_resource(struct vb2_context *ctx, void *buf, uint32_t size) { - struct region region; + struct region_device rdev; + const char *name; switch (index) { case VB2_RES_GBB: - vboot_locate_region("GBB", ®ion); + name = "GBB"; break; case VB2_RES_FW_VBLOCK: if (is_slot_a(ctx)) - vboot_locate_region("VBLOCK_A", ®ion); + name = "VBLOCK_A"; else - vboot_locate_region("VBLOCK_B", ®ion); + name = "VBLOCK_B"; break; default: return VB2_ERROR_EX_READ_RESOURCE_INDEX; } - if (offset + size > region_sz(®ion)) + if (vboot_named_region_device(name, &rdev)) return VB2_ERROR_EX_READ_RESOURCE_SIZE; - if (vboot_get_region(region_offset(®ion) + offset, size, buf) == NULL) - return VB2_ERROR_UNKNOWN; + if (rdev_readat(&rdev, buf, offset, size) != size) + return VB2_ERROR_EX_READ_RESOURCE_SIZE; return VB2_SUCCESS; } @@ -114,7 +115,7 @@ int vb2ex_hwcrypto_digest_finalize(uint8_t *digest, uint32_t digest_size) return VB2_ERROR_UNKNOWN; } -static int hash_body(struct vb2_context *ctx, struct region *fw_main) +static int hash_body(struct vb2_context *ctx, struct region_device *fw_main) { uint64_t load_ts; uint32_t expected_size; @@ -132,8 +133,8 @@ static int hash_body(struct vb2_context *ctx, struct region *fw_main) load_ts = timestamp_get(); timestamp_add(TS_START_HASH_BODY, load_ts); - expected_size = region_sz(fw_main); - offset = region_offset(fw_main); + expected_size = region_device_sz(fw_main); + offset = 0; /* Start the body hash */ rv = vb2api_init_hash(ctx, VB2_HASH_TAG_FW_BODY, &expected_size); @@ -143,17 +144,15 @@ static int hash_body(struct vb2_context *ctx, struct region *fw_main) /* Extend over the body */ while (expected_size) { uint64_t temp_ts; - void *b; if (block_size > expected_size) block_size = expected_size; temp_ts = timestamp_get(); - b = vboot_get_region(offset, block_size, block); - if (b == NULL) + if (rdev_readat(fw_main, block, offset, block_size) < 0) return VB2_ERROR_UNKNOWN; load_ts += timestamp_get() - temp_ts; - rv = vb2api_extend_hash(ctx, b, block_size); + rv = vb2api_extend_hash(ctx, block, block_size); if (rv) return rv; @@ -174,17 +173,17 @@ static int hash_body(struct vb2_context *ctx, struct region *fw_main) return VB2_SUCCESS; } -static int locate_firmware(struct vb2_context *ctx, struct region *fw_main) +static int locate_firmware(struct vb2_context *ctx, + struct region_device *fw_main) { + const char *name; + if (is_slot_a(ctx)) - vboot_locate_region("FW_MAIN_A", fw_main); + name = "FW_MAIN_A"; else - vboot_locate_region("FW_MAIN_B", fw_main); - - if (region_sz(fw_main) == 0) - return 1; + name = "FW_MAIN_B"; - return 0; + return vboot_named_region_device(name, fw_main); } /** @@ -219,7 +218,7 @@ static uint32_t extend_pcrs(struct vb2_context *ctx) void verstage_main(void) { struct vb2_context ctx; - struct region fw_main; + struct region_device fw_main; struct vb2_working_data *wd = vboot_get_working_data(); int rv; timestamp_add_now(TS_START_VBOOT); diff --git a/src/vendorcode/google/chromeos/vboot_common.c b/src/vendorcode/google/chromeos/vboot_common.c index 1db9d96aea..2fd29b6bfe 100644 --- a/src/vendorcode/google/chromeos/vboot_common.c +++ b/src/vendorcode/google/chromeos/vboot_common.c @@ -31,34 +31,14 @@ #include "vboot_common.h" #include "vboot_handoff.h" -void vboot_locate_region(const char *name, struct region *region) +int vboot_named_region_device(const char *name, struct region_device *rdev) { - if (fmap_locate_area(name, region)) - region->size = 0; + return fmap_locate_area_as_rdev(name, rdev); } -void *vboot_get_region(size_t offset, size_t size, void *dest) +int vboot_region_device(const struct region *reg, struct region_device *rdev) { - const struct region_device *boot_dev; - struct region_device rdev; - - boot_device_init(); - boot_dev = boot_device_ro(); - - if (boot_dev == NULL) - return NULL; - - if (rdev_chain(&rdev, boot_dev, offset, size)) - return NULL; - - /* Each call will leak a mapping. */ - if (dest == NULL) - return rdev_mmap_full(&rdev); - - if (rdev_readat(&rdev, dest, 0, size) != size) - return NULL; - - return dest; + return boot_device_ro_subregion(reg, rdev); } int vboot_get_handoff_info(void **addr, uint32_t *size) @@ -75,23 +55,6 @@ int vboot_get_handoff_info(void **addr, uint32_t *size) return 0; } -/* This will leak a mapping of a fw region */ -struct vboot_components *vboot_locate_components(struct region *region) -{ - size_t req_size; - struct vboot_components *vbc; - - req_size = sizeof(*vbc); - req_size += sizeof(struct vboot_component_entry) * - MAX_PARSED_FW_COMPONENTS; - - vbc = vboot_get_region(region_offset(region), req_size, NULL); - if (vbc && vbc->num_components > MAX_PARSED_FW_COMPONENTS) - vbc = NULL; - - return vbc; -} - void vboot_reboot(void) { if (IS_ENABLED(CONFIG_CONSOLE_CBMEM_DUMP_TO_UART)) diff --git a/src/vendorcode/google/chromeos/vboot_common.h b/src/vendorcode/google/chromeos/vboot_common.h index 4b034667fc..a7d77a6723 100644 --- a/src/vendorcode/google/chromeos/vboot_common.h +++ b/src/vendorcode/google/chromeos/vboot_common.h @@ -36,16 +36,8 @@ struct vboot_components { struct vboot_component_entry entries[0]; } __attribute__((packed)); -void vboot_locate_region(const char *name, struct region *region); - -struct vboot_components *vboot_locate_components(struct region *region); - -/* - * This is a dual purpose routine. If dest is non-NULL the region at - * offset_addr will be read into the area pointed to by dest. If dest - * is NULL,the region will be mapped to a memory location. NULL is - * returned on error else the location of the requested region. - */ -void *vboot_get_region(size_t offset, size_t size, void *dest); +/* The following functions return 0 on success, < 0 on error. */ +int vboot_named_region_device(const char *name, struct region_device *rdev); +int vboot_region_device(const struct region *reg, struct region_device *rdev); #endif /* VBOOT_COMMON_H */ |