ec_sync: Run EFS2 in romstage
EFS2 allows EC RO to enable PD for special cases. When doing so, it sets NO_BOOT flag to avoid booting the OS. AP needs to get NO_BOOT flag from Cr50 and enforce that. This patch makes verstage get a boot mode and a mirrored hash stored in kernel secdata from Cr50. This patch also makes romstage write an expected EC hash (a.k.a. Hexp) to Cr50 (if there is an update). BUG=b:147298634, chromium:1045217, b:148259137 BRANCH=none TEST=Verify software sync succeeds on Puff. Signed-off-by: dnojiri <dnojiri@chromium.org> Change-Id: I1f387b6e920205b9cc4c8536561f2a279c36413d Reviewed-on: https://review.coreboot.org/c/coreboot/+/40389 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Julius Werner <jwerner@chromium.org>
This commit is contained in:
parent
622c6b84ab
commit
dff56a056c
@ -71,6 +71,12 @@ uint32_t antirollback_read_space_firmware(struct vb2_context *ctx);
|
|||||||
*/
|
*/
|
||||||
uint32_t antirollback_write_space_firmware(struct vb2_context *ctx);
|
uint32_t antirollback_write_space_firmware(struct vb2_context *ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read and write kernel space in TPM.
|
||||||
|
*/
|
||||||
|
uint32_t antirollback_read_space_kernel(struct vb2_context *ctx);
|
||||||
|
uint32_t antirollback_write_space_kernel(struct vb2_context *ctx);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Lock must be called.
|
* Lock must be called.
|
||||||
*/
|
*/
|
||||||
|
@ -50,7 +50,7 @@ void vboot_sync_ec(void)
|
|||||||
ctx->flags |= VB2_CONTEXT_EC_SYNC_SUPPORTED;
|
ctx->flags |= VB2_CONTEXT_EC_SYNC_SUPPORTED;
|
||||||
|
|
||||||
retval = vb2api_ec_sync(ctx);
|
retval = vb2api_ec_sync(ctx);
|
||||||
vboot_save_nvdata_only(ctx);
|
vboot_save_data(ctx);
|
||||||
|
|
||||||
switch (retval) {
|
switch (retval) {
|
||||||
case VB2_SUCCESS:
|
case VB2_SUCCESS:
|
||||||
|
@ -53,6 +53,17 @@ vb2_error_t antirollback_write_space_firmware(struct vb2_context *ctx)
|
|||||||
return VB2_SUCCESS;
|
return VB2_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vb2_error_t antirollback_read_space_kernel(struct vb2_context *ctx)
|
||||||
|
{
|
||||||
|
vb2api_secdata_kernel_create(ctx);
|
||||||
|
return VB2_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
vb2_error_t antirollback_write_space_kernel(struct vb2_context *ctx)
|
||||||
|
{
|
||||||
|
return VB2_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
vb2_error_t antirollback_lock_space_firmware(void)
|
vb2_error_t antirollback_lock_space_firmware(void)
|
||||||
{
|
{
|
||||||
return VB2_SUCCESS;
|
return VB2_SUCCESS;
|
||||||
|
@ -80,6 +80,22 @@ static uint32_t read_space_firmware(struct vb2_context *ctx)
|
|||||||
return TPM_E_CORRUPTED_STATE;
|
return TPM_E_CORRUPTED_STATE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t antirollback_read_space_kernel(struct vb2_context *ctx)
|
||||||
|
{
|
||||||
|
uint8_t size = VB2_SECDATA_KERNEL_MIN_SIZE;
|
||||||
|
|
||||||
|
RETURN_ON_FAILURE(tlcl_read(KERNEL_NV_INDEX, ctx->secdata_kernel,
|
||||||
|
size));
|
||||||
|
|
||||||
|
if (vb2api_secdata_kernel_check(ctx, &size)
|
||||||
|
== VB2_ERROR_SECDATA_KERNEL_INCOMPLETE)
|
||||||
|
/* Re-read. vboot will run the check and handle errors. */
|
||||||
|
RETURN_ON_FAILURE(tlcl_read(KERNEL_NV_INDEX,
|
||||||
|
ctx->secdata_kernel, size));
|
||||||
|
|
||||||
|
return TPM_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
static uint32_t read_space_rec_hash(uint8_t *data)
|
static uint32_t read_space_rec_hash(uint8_t *data)
|
||||||
{
|
{
|
||||||
RETURN_ON_FAILURE(tlcl_read(REC_HASH_NV_INDEX, data,
|
RETURN_ON_FAILURE(tlcl_read(REC_HASH_NV_INDEX, data,
|
||||||
@ -440,6 +456,15 @@ uint32_t antirollback_write_space_firmware(struct vb2_context *ctx)
|
|||||||
VB2_SECDATA_FIRMWARE_SIZE);
|
VB2_SECDATA_FIRMWARE_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t antirollback_write_space_kernel(struct vb2_context *ctx)
|
||||||
|
{
|
||||||
|
/* Learn the expected size. */
|
||||||
|
uint8_t size = VB2_SECDATA_KERNEL_MIN_SIZE;
|
||||||
|
vb2api_secdata_kernel_check(ctx, &size);
|
||||||
|
|
||||||
|
return write_secdata(KERNEL_NV_INDEX, ctx->secdata_kernel, size);
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t antirollback_read_space_rec_hash(uint8_t *data, uint32_t size)
|
uint32_t antirollback_read_space_rec_hash(uint8_t *data, uint32_t size)
|
||||||
{
|
{
|
||||||
if (size != REC_HASH_NV_SIZE) {
|
if (size != REC_HASH_NV_SIZE) {
|
||||||
|
@ -61,7 +61,6 @@ static inline void vboot_run_logic(void) {}
|
|||||||
static inline int vboot_locate_cbfs(struct region_device *rdev) { return -1; }
|
static inline int vboot_locate_cbfs(struct region_device *rdev) { return -1; }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void vboot_save_nvdata_only(struct vb2_context *ctx);
|
|
||||||
void vboot_save_data(struct vb2_context *ctx);
|
void vboot_save_data(struct vb2_context *ctx);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include <cbmem.h>
|
#include <cbmem.h>
|
||||||
#include <fmap.h>
|
#include <fmap.h>
|
||||||
#include <security/tpm/tspi/crtm.h>
|
#include <security/tpm/tspi/crtm.h>
|
||||||
|
#include <security/tpm/tss/vendor/cr50/cr50.h>
|
||||||
#include <security/vboot/misc.h>
|
#include <security/vboot/misc.h>
|
||||||
#include <security/vboot/vbnv.h>
|
#include <security/vboot/vbnv.h>
|
||||||
#include <security/vboot/tpm_common.h>
|
#include <security/vboot/tpm_common.h>
|
||||||
@ -207,10 +208,21 @@ static vb2_error_t hash_body(struct vb2_context *ctx,
|
|||||||
return VB2_SUCCESS;
|
return VB2_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
void vboot_save_nvdata_only(struct vb2_context *ctx)
|
void vboot_save_data(struct vb2_context *ctx)
|
||||||
{
|
{
|
||||||
assert(!(ctx->flags & (VB2_CONTEXT_SECDATA_FIRMWARE_CHANGED |
|
if (ctx->flags & VB2_CONTEXT_SECDATA_FIRMWARE_CHANGED &&
|
||||||
VB2_CONTEXT_SECDATA_KERNEL_CHANGED)));
|
(CONFIG(VBOOT_MOCK_SECDATA) || tlcl_lib_init() == VB2_SUCCESS)) {
|
||||||
|
printk(BIOS_INFO, "Saving secdata firmware\n");
|
||||||
|
antirollback_write_space_firmware(ctx);
|
||||||
|
ctx->flags &= ~VB2_CONTEXT_SECDATA_FIRMWARE_CHANGED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctx->flags & VB2_CONTEXT_SECDATA_KERNEL_CHANGED &&
|
||||||
|
(CONFIG(VBOOT_MOCK_SECDATA) || tlcl_lib_init() == VB2_SUCCESS)) {
|
||||||
|
printk(BIOS_INFO, "Saving secdata kernel\n");
|
||||||
|
antirollback_write_space_kernel(ctx);
|
||||||
|
ctx->flags &= ~VB2_CONTEXT_SECDATA_KERNEL_CHANGED;
|
||||||
|
}
|
||||||
|
|
||||||
if (ctx->flags & VB2_CONTEXT_NVDATA_CHANGED) {
|
if (ctx->flags & VB2_CONTEXT_NVDATA_CHANGED) {
|
||||||
printk(BIOS_INFO, "Saving nvdata\n");
|
printk(BIOS_INFO, "Saving nvdata\n");
|
||||||
@ -219,23 +231,57 @@ void vboot_save_nvdata_only(struct vb2_context *ctx)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void vboot_save_data(struct vb2_context *ctx)
|
|
||||||
{
|
|
||||||
if (ctx->flags & VB2_CONTEXT_SECDATA_FIRMWARE_CHANGED) {
|
|
||||||
printk(BIOS_INFO, "Saving secdata\n");
|
|
||||||
antirollback_write_space_firmware(ctx);
|
|
||||||
ctx->flags &= ~VB2_CONTEXT_SECDATA_FIRMWARE_CHANGED;
|
|
||||||
}
|
|
||||||
|
|
||||||
vboot_save_nvdata_only(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint32_t extend_pcrs(struct vb2_context *ctx)
|
static uint32_t extend_pcrs(struct vb2_context *ctx)
|
||||||
{
|
{
|
||||||
return vboot_extend_pcr(ctx, 0, BOOT_MODE_PCR) ||
|
return vboot_extend_pcr(ctx, 0, BOOT_MODE_PCR) ||
|
||||||
vboot_extend_pcr(ctx, 1, HWID_DIGEST_PCR);
|
vboot_extend_pcr(ctx, 1, HWID_DIGEST_PCR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define EC_EFS_BOOT_MODE_NORMAL 0x00
|
||||||
|
#define EC_EFS_BOOT_MODE_NO_BOOT 0x01
|
||||||
|
|
||||||
|
static const char *get_boot_mode_string(uint8_t boot_mode)
|
||||||
|
{
|
||||||
|
if (boot_mode == EC_EFS_BOOT_MODE_NORMAL)
|
||||||
|
return "NORMAL";
|
||||||
|
else if (boot_mode == EC_EFS_BOOT_MODE_NO_BOOT)
|
||||||
|
return "NO_BOOT";
|
||||||
|
else
|
||||||
|
return "UNDEFINED";
|
||||||
|
}
|
||||||
|
|
||||||
|
static void check_boot_mode(struct vb2_context *ctx)
|
||||||
|
{
|
||||||
|
uint8_t boot_mode;
|
||||||
|
int rv;
|
||||||
|
|
||||||
|
rv = tlcl_cr50_get_boot_mode(&boot_mode);
|
||||||
|
switch (rv) {
|
||||||
|
case TPM_E_NO_SUCH_COMMAND:
|
||||||
|
printk(BIOS_WARNING, "Cr50 does not support GET_BOOT_MODE.\n");
|
||||||
|
/* Proceed to legacy boot model. */
|
||||||
|
return;
|
||||||
|
case TPM_SUCCESS:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printk(BIOS_ERR,
|
||||||
|
"Communication error in getting Cr50 boot mode.\n");
|
||||||
|
if (ctx->flags & VB2_CONTEXT_RECOVERY_MODE)
|
||||||
|
/* Continue to boot in recovery mode */
|
||||||
|
return;
|
||||||
|
vb2api_fail(ctx, VB2_RECOVERY_CR50_BOOT_MODE, rv);
|
||||||
|
vboot_save_data(ctx);
|
||||||
|
vboot_reboot();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
printk(BIOS_INFO, "Cr50 says boot_mode is %s(0x%02x).\n",
|
||||||
|
get_boot_mode_string(boot_mode), boot_mode);
|
||||||
|
|
||||||
|
if (boot_mode == EC_EFS_BOOT_MODE_NO_BOOT)
|
||||||
|
ctx->flags |= VB2_CONTEXT_NO_BOOT;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Verify and select the firmware in the RW image
|
* Verify and select the firmware in the RW image
|
||||||
*
|
*
|
||||||
@ -268,8 +314,10 @@ void verstage_main(void)
|
|||||||
* check the return value here because vb2api_fw_phase1 will catch
|
* check the return value here because vb2api_fw_phase1 will catch
|
||||||
* invalid secdata and tell us what to do (=reboot). */
|
* invalid secdata and tell us what to do (=reboot). */
|
||||||
timestamp_add_now(TS_START_TPMINIT);
|
timestamp_add_now(TS_START_TPMINIT);
|
||||||
if (vboot_setup_tpm(ctx) == TPM_SUCCESS)
|
if (vboot_setup_tpm(ctx) == TPM_SUCCESS) {
|
||||||
antirollback_read_space_firmware(ctx);
|
antirollback_read_space_firmware(ctx);
|
||||||
|
antirollback_read_space_kernel(ctx);
|
||||||
|
}
|
||||||
timestamp_add_now(TS_END_TPMINIT);
|
timestamp_add_now(TS_END_TPMINIT);
|
||||||
|
|
||||||
if (get_recovery_mode_switch()) {
|
if (get_recovery_mode_switch()) {
|
||||||
@ -359,6 +407,9 @@ void verstage_main(void)
|
|||||||
timestamp_add_now(TS_END_TPMPCR);
|
timestamp_add_now(TS_END_TPMPCR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (CONFIG(TPM_CR50))
|
||||||
|
check_boot_mode(ctx);
|
||||||
|
|
||||||
/* Lock TPM */
|
/* Lock TPM */
|
||||||
|
|
||||||
timestamp_add_now(TS_START_TPMLOCK);
|
timestamp_add_now(TS_START_TPMLOCK);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user