diff options
author | Aaron Durbin <adurbin@chromium.org> | 2015-10-07 16:03:41 -0500 |
---|---|---|
committer | Aaron Durbin <adurbin@gmail.com> | 2015-10-11 23:57:29 +0000 |
commit | b593366e349673cd4ef5b933849f78e6e958d626 (patch) | |
tree | 5489ec29157dbf096b42313c057d5a3fbe84859a /src | |
parent | ed253c8fd80573b2182aa5fd27033750cff48c0b (diff) |
vboot: prepare for x86 verstage
In order to support x86 verstage proper the work buffer
needs to live in cache-as-ram. However, after cache-as-ram
is torn down one still needs the verification results to
know which slot was selected. Though the platforms with
a dedicated SRAM can just use the work buffer in SRAM, the
x86 cache-as-ram platforms need a place to stash the
results. For that situation cbmem is employed. This works
because when cbmem is initialized cache-as-ram is still
enabled. The VBOOT_DYNAMIC_WORK_BUFFER case assumes
verified boot doesn't start until after cbmem is up. That
doesn't change, but it's a goal to get rid of that option
entirely once all other x86 platforms are moved over to
pre-romstage vboot.
BUG=chrome-os-partner:44827
BRANCH=None
TEST=Built and booted glados with pre-romstage verification
as well as VBOOT_DYNAMIC_WORK_BUFFER case.
Change-Id: I7eacd0edb2b6ca52b59b74075d17c00b50676d4c
Signed-off-by: Aaron Durbin <adurbin@chromium.org>
Reviewed-on: http://review.coreboot.org/11821
Tested-by: build bot (Jenkins)
Reviewed-by: Patrick Georgi <pgeorgi@google.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/commonlib/include/commonlib/cbmem_id.h | 2 | ||||
-rw-r--r-- | src/vendorcode/google/chromeos/vboot2/common.c | 81 | ||||
-rw-r--r-- | src/vendorcode/google/chromeos/vboot2/misc.h | 3 | ||||
-rw-r--r-- | src/vendorcode/google/chromeos/vboot2/vboot_handoff.c | 14 | ||||
-rw-r--r-- | src/vendorcode/google/chromeos/vboot2/vboot_loader.c | 14 |
5 files changed, 99 insertions, 15 deletions
diff --git a/src/commonlib/include/commonlib/cbmem_id.h b/src/commonlib/include/commonlib/cbmem_id.h index 6812c41cc1..4a5b66082b 100644 --- a/src/commonlib/include/commonlib/cbmem_id.h +++ b/src/commonlib/include/commonlib/cbmem_id.h @@ -65,6 +65,7 @@ #define CBMEM_ID_TCPA_LOG 0x54435041 #define CBMEM_ID_TIMESTAMP 0x54494d45 #define CBMEM_ID_VBOOT_HANDOFF 0x780074f0 +#define CBMEM_ID_VBOOT_SEL_REG 0x780074f1 #define CBMEM_ID_VBOOT_WORKBUF 0x78007343 #define CBMEM_ID_WIFI_CALIBRATION 0x57494649 @@ -108,6 +109,7 @@ { CBMEM_ID_TCPA_LOG, "TCPA LOG " }, \ { CBMEM_ID_TIMESTAMP, "TIME STAMP " }, \ { CBMEM_ID_VBOOT_HANDOFF, "VBOOT " }, \ + { CBMEM_ID_VBOOT_SEL_REG, "VBOOT SEL " }, \ { CBMEM_ID_VBOOT_WORKBUF, "VBOOT WORK " }, \ { CBMEM_ID_WIFI_CALIBRATION, "WIFI CLBR " }, #endif /* _CBMEM_ID_H_ */ diff --git a/src/vendorcode/google/chromeos/vboot2/common.c b/src/vendorcode/google/chromeos/vboot2/common.c index a33fb8e98e..663ffd892b 100644 --- a/src/vendorcode/google/chromeos/vboot2/common.c +++ b/src/vendorcode/google/chromeos/vboot2/common.c @@ -28,6 +28,11 @@ #include "../vboot_handoff.h" #include "misc.h" +struct selected_region { + uint32_t offset; + uint32_t size; +}; + /* * this is placed at the start of the vboot work buffer. selected_region is used * for the verstage to return the location of the selected slot. buffer is used @@ -35,8 +40,7 @@ * stage boundaries. */ struct vb2_working_data { - uint32_t selected_region_offset; - uint32_t selected_region_size; + struct selected_region selected_region; /* offset of the buffer from the start of this struct */ uint32_t buffer_offset; uint32_t buffer_size; @@ -61,6 +65,30 @@ static size_t vb2_working_data_size(void) return _vboot2_work_size; } +static struct selected_region *vb2_selected_region(void) +{ + struct selected_region *sel_reg = NULL; + + /* Ramstage always uses cbmem as a source of truth. */ + if (ENV_RAMSTAGE) + sel_reg = cbmem_find(CBMEM_ID_VBOOT_SEL_REG); + else if (ENV_ROMSTAGE) { + /* Try cbmem first. Fall back on working data if not found. */ + sel_reg = cbmem_find(CBMEM_ID_VBOOT_SEL_REG); + + if (sel_reg == NULL) { + struct vb2_working_data *wd = vboot_get_working_data(); + sel_reg = &wd->selected_region; + } + } else { + /* Stages such as bootblock and verstage use working data. */ + struct vb2_working_data *wd = vboot_get_working_data(); + sel_reg = &wd->selected_region; + } + + return sel_reg; +} + void vb2_init_work_context(struct vb2_context *ctx) { struct vb2_working_data *wd; @@ -93,28 +121,57 @@ struct vb2_shared_data *vb2_get_shared_data(void) int vb2_get_selected_region(struct region_device *rdev) { - const struct vb2_working_data *wd = vboot_get_working_data(); - struct region reg = { - .offset = wd->selected_region_offset, - .size = wd->selected_region_size, + const struct selected_region *reg = vb2_selected_region(); + struct region region = { + .offset = reg->offset, + .size = reg->size, }; - return vboot_region_device(®, rdev); + return vboot_region_device(®ion, rdev); } void vb2_set_selected_region(struct region_device *rdev) { - struct vb2_working_data *wd = vboot_get_working_data(); - wd->selected_region_offset = region_device_offset(rdev); - wd->selected_region_size = region_device_sz(rdev); + struct selected_region *reg = vb2_selected_region(); + reg->offset = region_device_offset(rdev); + reg->size = region_device_sz(rdev); } int vboot_is_slot_selected(void) { - const struct vb2_working_data *wd = vboot_get_working_data(); - return wd->selected_region_size > 0; + const struct selected_region *reg = vb2_selected_region(); + return reg->size > 0; } int vboot_is_readonly_path(void) { return !vboot_is_slot_selected(); } + +void vb2_store_selected_region(void) +{ + const struct vb2_working_data *wd; + struct selected_region *sel_reg; + + /* Always use the working data in this path since it's the object + * which has the result.. */ + wd = vboot_get_working_data(); + + sel_reg = cbmem_add(CBMEM_ID_VBOOT_SEL_REG, sizeof(*sel_reg)); + + sel_reg->offset = wd->selected_region.offset; + sel_reg->size = wd->selected_region.size; +} + +/* + * For platforms that employ VBOOT_DYNAMIC_WORK_BUFFER, the vboot + * verification doesn't happen until after cbmem is brought online. + * Therefore, the selected region contents would not be initialized + * so don't automatically add results when cbmem comes online. + */ +#if !IS_ENABLED(CONFIG_VBOOT_DYNAMIC_WORK_BUFFER) +static void vb2_store_selected_region_cbmem(int unused) +{ + vb2_store_selected_region(); +} +ROMSTAGE_CBMEM_INIT_HOOK(vb2_store_selected_region_cbmem) +#endif diff --git a/src/vendorcode/google/chromeos/vboot2/misc.h b/src/vendorcode/google/chromeos/vboot2/misc.h index fbbc46ef5c..2c26461ad4 100644 --- a/src/vendorcode/google/chromeos/vboot2/misc.h +++ b/src/vendorcode/google/chromeos/vboot2/misc.h @@ -39,4 +39,7 @@ void vb2_set_selected_region(struct region_device *rdev); int vboot_is_slot_selected(void); int vboot_is_readonly_path(void); +/* Store the selected region in cbmem for later use. */ +void vb2_store_selected_region(void); + #endif /* __CHROMEOS_VBOOT2_MISC_H__ */ diff --git a/src/vendorcode/google/chromeos/vboot2/vboot_handoff.c b/src/vendorcode/google/chromeos/vboot2/vboot_handoff.c index bf7d6542eb..769e2679ef 100644 --- a/src/vendorcode/google/chromeos/vboot2/vboot_handoff.c +++ b/src/vendorcode/google/chromeos/vboot2/vboot_handoff.c @@ -171,3 +171,17 @@ void vboot_fill_handoff(void) rdev_munmap(&fw_main, fw_info); } + +/* + * For platforms that employ VBOOT_DYNAMIC_WORK_BUFFER, the vboot + * verification doesn't happen until after cbmem is brought online. + * Therefore, the vboot results would not be initialized so don't + * automatically add results when cbmem comes online. + */ +#if !IS_ENABLED(CONFIG_VBOOT_DYNAMIC_WORK_BUFFER) +static void vb2_fill_handoff_cbmem(int unused) +{ + vboot_fill_handoff(); +} +ROMSTAGE_CBMEM_INIT_HOOK(vb2_fill_handoff_cbmem) +#endif diff --git a/src/vendorcode/google/chromeos/vboot2/vboot_loader.c b/src/vendorcode/google/chromeos/vboot2/vboot_loader.c index bb7bc4c828..d2e77586e8 100644 --- a/src/vendorcode/google/chromeos/vboot2/vboot_loader.c +++ b/src/vendorcode/google/chromeos/vboot2/vboot_loader.c @@ -98,10 +98,18 @@ static int vboot_active(struct asset *asset) return 0; } - /* Fill in vboot handoff structure before moving to ramstage so all - * downstream users have access to vboot results. */ - if (ENV_ROMSTAGE) + /* + * Fill in vboot cbmem objects before moving to ramstage so all + * downstream users have access to vboot results. This path only + * applies to platforms employing VBOOT_DYNAMIC_WORK_BUFFER because + * cbmem comes online prior to vboot verification taking place. For + * other platforms the vboot cbmem objects are initialized when + * cbmem comes online. + */ + if (ENV_ROMSTAGE && IS_ENABLED(CONFIG_VBOOT_DYNAMIC_WORK_BUFFER)) { + vb2_store_selected_region(); vboot_fill_handoff(); + } return vboot_is_slot_selected(); } |