coreboot/src/security/vboot/common.c
Joel Kitching 8a3bc3be92 vboot: correct workbuf size when VBOOT_STARTS_IN_ROMSTAGE
Part of the design of vboot persistent context is that the workbuf gets
placed in CBMEM and stays there for depthcharge to use in kernel
verification.  As such, the space allocated in CBMEM needs to be at least
VB2_KERNEL_WORKBUF_RECOMMENDED_SIZE.

In the VBOOT_STARTS_IN_ROMSTAGE case, prior to this CL, vboot_get_context()
would get invoked for the first time after CBMEM comes up, and it would
only allocate VB2_FIRMWARE_WORKBUF_RECOMMENDED_SIZE.

Initialize the workbuf directly in vboot_setup_cbmem() instead with the
correct VB2_KERNEL_WORKBUF_RECOMMENDED_SIZE.

BUG=b:124141368, chromium:994060
TEST=make clean && make test-abuild
TEST=boot on GOOGLE_EVE with VBOOT_STARTS_IN_ROMSTAGE set
BRANCH=none

Change-Id: Ie09c39f960b3f14f3a64c648eee6ca3f23214d9a
Signed-off-by: Joel Kitching <kitching@google.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/38778
Reviewed-by: Aaron Durbin <adurbin@chromium.org>
Reviewed-by: Raul Rangel <rrangel@chromium.org>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
2020-02-10 21:25:14 +00:00

111 lines
3 KiB
C

/*
* This file is part of the coreboot project.
*
* Copyright (C) 2014 The ChromiumOS Authors. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <assert.h>
#include <cbmem.h>
#include <console/console.h>
#include <fmap.h>
#include <stdint.h>
#include <symbols.h>
#include <vb2_api.h>
#include <security/vboot/misc.h>
#include <security/vboot/symbols.h>
#include <security/vboot/vboot_common.h>
static struct vb2_context *vboot_ctx;
static void *vboot_get_workbuf(void)
{
void *wb = NULL;
if (cbmem_possibly_online())
wb = cbmem_find(CBMEM_ID_VBOOT_WORKBUF);
if (wb == NULL && CONFIG(VBOOT_STARTS_IN_BOOTBLOCK) &&
preram_symbols_available())
wb = _vboot2_work;
assert(wb != NULL);
return wb;
}
struct vb2_context *vboot_get_context(void)
{
void *wb;
/* Return if context has already been initialized/restored. */
if (vboot_ctx)
return vboot_ctx;
wb = vboot_get_workbuf();
/* Restore context from a previous stage. */
if (vboot_logic_executed()) {
assert(vb2api_reinit(wb, &vboot_ctx) == VB2_SUCCESS);
return vboot_ctx;
}
assert(verification_should_run());
/* Initialize vb2_shared_data and friends. */
assert(vb2api_init(wb, VB2_FIRMWARE_WORKBUF_RECOMMENDED_SIZE,
&vboot_ctx) == VB2_SUCCESS);
return vboot_ctx;
}
int vboot_locate_firmware(struct vb2_context *ctx, struct region_device *fw)
{
const char *name;
if (vboot_is_firmware_slot_a(ctx))
name = "FW_MAIN_A";
else
name = "FW_MAIN_B";
int ret = fmap_locate_area_as_rdev(name, fw);
if (ret)
return ret;
/* Truncate area to the size that was actually signed by vboot. */
return rdev_chain(fw, fw, 0, vb2api_get_firmware_size(ctx));
}
static void vboot_setup_cbmem(int unused)
{
vb2_error_t rv;
const size_t cbmem_size = VB2_KERNEL_WORKBUF_RECOMMENDED_SIZE;
void *wb_cbmem = cbmem_add(CBMEM_ID_VBOOT_WORKBUF, cbmem_size);
assert(wb_cbmem != NULL);
/*
* For platforms where VBOOT_STARTS_IN_BOOTBLOCK, vboot verification
* occurs before CBMEM is brought online, using pre-RAM. In order to
* make vboot data structures available downstream, copy vboot workbuf
* from SRAM/CAR into CBMEM.
*
* For platforms where VBOOT_STARTS_IN_ROMSTAGE, verification occurs
* after CBMEM is brought online. Directly initialize vboot data
* structures in CBMEM, which will also be available downstream.
*/
if (CONFIG(VBOOT_STARTS_IN_BOOTBLOCK))
rv = vb2api_relocate(wb_cbmem, _vboot2_work, cbmem_size,
&vboot_ctx);
else
rv = vb2api_init(wb_cbmem, cbmem_size, &vboot_ctx);
assert(rv == VB2_SUCCESS);
}
ROMSTAGE_CBMEM_INIT_HOOK(vboot_setup_cbmem)