From 2332c7459ebb81c4dd4c3cc8b19beca820e93968 Mon Sep 17 00:00:00 2001 From: Joel Kitching Date: Wed, 23 Oct 2019 15:01:37 +0800 Subject: vboot: use vboot persistent context vb2_context object is now stored on the workbuf as part of vb2_shared_data. Use vboot's new API functions vb2api_init and vb2api_relocate to create and move the workbuf. BUG=b:124141368, chromium:994060 TEST=Build locally BRANCH=none Change-Id: I051be1e47bf79b15a1689d49a5d4c031e9363dfa Signed-off-by: Joel Kitching Also-Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/coreboot/+/1902339 Reviewed-on: https://review.coreboot.org/c/coreboot/+/36300 Tested-by: build bot (Jenkins) Reviewed-by: Patrick Georgi Reviewed-by: Stefan Reinauer Reviewed-by: Maulik V Vaghela --- src/security/vboot/common.c | 74 ++++++++++++++++++++++++++------------------- 1 file changed, 43 insertions(+), 31 deletions(-) (limited to 'src/security/vboot/common.c') diff --git a/src/security/vboot/common.c b/src/security/vboot/common.c index 626fbc52a4..043748cbef 100644 --- a/src/security/vboot/common.c +++ b/src/security/vboot/common.c @@ -24,6 +24,8 @@ #include #include +static struct vb2_context *vboot_ctx CAR_GLOBAL; + struct vboot_working_data *vboot_get_working_data(void) { struct vboot_working_data *wd = NULL; @@ -40,43 +42,45 @@ struct vboot_working_data *vboot_get_working_data(void) return wd; } -void vboot_init_work_context(struct vb2_context *ctx) +static inline void *vboot_get_workbuf(struct vboot_working_data *wd) +{ + return (void *)((uintptr_t)wd + wd->buffer_offset); +} + +struct vb2_context *vboot_get_context(void) { + struct vb2_context **vboot_ctx_ptr = car_get_var_ptr(&vboot_ctx); struct vboot_working_data *wd; - /* First initialize the working data region. */ + /* Return if context has already been initialized/restored. */ + if (*vboot_ctx_ptr) + return *vboot_ctx_ptr; + wd = vboot_get_working_data(); - memset(wd, 0, VB2_FIRMWARE_WORKBUF_RECOMMENDED_SIZE); + + /* Restore context from a previous stage. */ + if (vboot_logic_executed()) { + assert(vb2api_reinit(vboot_get_workbuf(wd), + vboot_ctx_ptr) == VB2_SUCCESS); + return *vboot_ctx_ptr; + } + + assert(verification_should_run()); /* * vboot prefers 16-byte alignment. This takes away 16 bytes * from the VBOOT2_WORK region, but the vboot devs said that's okay. */ + memset(wd, 0, sizeof(*wd)); wd->buffer_offset = ALIGN_UP(sizeof(*wd), 16); wd->buffer_size = VB2_FIRMWARE_WORKBUF_RECOMMENDED_SIZE - wd->buffer_offset; - /* Initialize the vb2_context. */ - memset(ctx, 0, sizeof(*ctx)); - ctx->workbuf = (void *)vboot_get_shared_data(); - ctx->workbuf_size = wd->buffer_size; -} + /* Initialize vb2_shared_data and friends. */ + assert(vb2api_init(vboot_get_workbuf(wd), wd->buffer_size, + vboot_ctx_ptr) == VB2_SUCCESS); -void vboot_finalize_work_context(struct vb2_context *ctx) -{ - /* - * Shrink buffer_size so that vboot_migrate_cbmem knows how - * much of vboot_working_data needs to be copied into CBMEM - * (if applicable), and so that downstream users know how much - * of the workbuf is currently used. - */ - vboot_get_working_data()->buffer_size = ctx->workbuf_used; -} - -struct vb2_shared_data *vboot_get_shared_data(void) -{ - struct vboot_working_data *wd = vboot_get_working_data(); - return (void *)((uintptr_t)wd + wd->buffer_offset); + return *vboot_ctx_ptr; } int vboot_get_selected_region(struct region *region) @@ -126,17 +130,25 @@ int vboot_is_slot_selected(void) */ static void vboot_migrate_cbmem(int unused) { - const struct vboot_working_data *wd_preram = + const size_t cbmem_size = VB2_KERNEL_WORKBUF_RECOMMENDED_SIZE; + struct vboot_working_data *wd_preram = (struct vboot_working_data *)_vboot2_work; - size_t cbmem_size = wd_preram->buffer_offset + wd_preram->buffer_size; struct vboot_working_data *wd_cbmem = cbmem_add(CBMEM_ID_VBOOT_WORKBUF, cbmem_size); assert(wd_cbmem != NULL); - - printk(BIOS_DEBUG, - "VBOOT: copying vboot_working_data (%zu bytes) to CBMEM...\n", - cbmem_size); - memcpy(wd_cbmem, wd_preram, cbmem_size); + memcpy(wd_cbmem, wd_preram, sizeof(struct vboot_working_data)); + /* + * TODO(chromium:1021452): buffer_size is uint16_t and not large enough + * to hold the kernel verification workbuf size. The only code which + * reads this value is in lb_vboot_workbuf() for lb_range->range_size. + * This value being zero doesn't cause any problems, since it is never + * read downstream. Fix or deprecate vboot_working_data. + */ + wd_cbmem->buffer_size = 0; + vb2api_relocate(vboot_get_workbuf(wd_cbmem), + vboot_get_workbuf(wd_preram), + cbmem_size - wd_cbmem->buffer_offset, + car_get_var_ptr(&vboot_ctx)); } ROMSTAGE_CBMEM_INIT_HOOK(vboot_migrate_cbmem) #else @@ -144,7 +156,7 @@ static void vboot_setup_cbmem(int unused) { struct vboot_working_data *wd_cbmem = cbmem_add(CBMEM_ID_VBOOT_WORKBUF, - VB2_FIRMWARE_WORKBUF_RECOMMENDED_SIZE); + VB2_KERNEL_WORKBUF_RECOMMENDED_SIZE); assert(wd_cbmem != NULL); } ROMSTAGE_CBMEM_INIT_HOOK(vboot_setup_cbmem) -- cgit v1.2.3