summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAaron Durbin <adurbin@chromium.org>2015-10-07 16:03:41 -0500
committerAaron Durbin <adurbin@gmail.com>2015-10-11 23:57:29 +0000
commitb593366e349673cd4ef5b933849f78e6e958d626 (patch)
tree5489ec29157dbf096b42313c057d5a3fbe84859a
parented253c8fd80573b2182aa5fd27033750cff48c0b (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>
-rw-r--r--src/commonlib/include/commonlib/cbmem_id.h2
-rw-r--r--src/vendorcode/google/chromeos/vboot2/common.c81
-rw-r--r--src/vendorcode/google/chromeos/vboot2/misc.h3
-rw-r--r--src/vendorcode/google/chromeos/vboot2/vboot_handoff.c14
-rw-r--r--src/vendorcode/google/chromeos/vboot2/vboot_loader.c14
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(&reg, rdev);
+ return vboot_region_device(&region, 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();
}