util/cbfstool: Check for metadata hash in verstage

Metadata Hash is usually present inside the first segment of BIOS. On
board where vboot starts in bootblock, it is present in bootblock. On
boards where vboot starts before bootblock, it is present in file
containing verstage. Update cbfstool to check for metadata hash in file
containing verstage besides bootblock.

Add a new CBFS file type for the concerned file and exclude it from CBFS
verification.

BUG=b:227809919
TEST=Build and boot to OS in Skyrim with CBFS verification enabled using
x86 and PSP verstages.

Change-Id: Ib4dfba6a9cdbda0ef367b812f671c90e5f90caf8
Signed-off-by: Karthikeyan Ramasubramanian <kramasub@google.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/66942
Reviewed-by: Julius Werner <jwerner@chromium.org>
Reviewed-by: Yu-Ping Wu <yupingso@google.com>
Reviewed-by: Raul Rangel <rrangel@chromium.org>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
This commit is contained in:
Karthikeyan Ramasubramanian 2022-09-20 23:00:00 -06:00 committed by Raul Rangel
parent ab82a9f9b4
commit da5d0251f5
3 changed files with 18 additions and 9 deletions

View File

@ -36,6 +36,7 @@ enum cbfs_type {
CBFS_TYPE_MMA = 0x62, CBFS_TYPE_MMA = 0x62,
CBFS_TYPE_EFI = 0x63, CBFS_TYPE_EFI = 0x63,
CBFS_TYPE_STRUCT = 0x70, CBFS_TYPE_STRUCT = 0x70,
CBFS_TYPE_AMDFW = 0x80,
CBFS_TYPE_CMOS_DEFAULT = 0xaa, CBFS_TYPE_CMOS_DEFAULT = 0xaa,
CBFS_TYPE_SPD = 0xab, CBFS_TYPE_SPD = 0xab,
CBFS_TYPE_MRC_CACHE = 0xac, CBFS_TYPE_MRC_CACHE = 0xac,

View File

@ -52,6 +52,7 @@ static struct typedesc_t filetypes[] unused = {
{CBFS_TYPE_STRUCT, "struct"}, {CBFS_TYPE_STRUCT, "struct"},
{CBFS_TYPE_DELETED, "deleted"}, {CBFS_TYPE_DELETED, "deleted"},
{CBFS_TYPE_NULL, "null"}, {CBFS_TYPE_NULL, "null"},
{CBFS_TYPE_AMDFW, "amdfw"},
{0, NULL} {0, NULL}
}; };

View File

@ -148,7 +148,7 @@ static struct mh_cache *get_mh_cache(void)
if (!fmap) if (!fmap)
goto no_metadata_hash; goto no_metadata_hash;
/* Find the bootblock. If there is a "BOOTBLOCK" FMAP section, it's /* Find the metadata_hash container. If there is a "BOOTBLOCK" FMAP section, it's
there. If not, it's a normal file in the primary CBFS section. */ there. If not, it's a normal file in the primary CBFS section. */
size_t offset, size; size_t offset, size;
struct buffer buffer; struct buffer buffer;
@ -161,22 +161,27 @@ static struct mh_cache *get_mh_cache(void)
size = buffer.size; size = buffer.size;
} else { } else {
struct cbfs_image cbfs; struct cbfs_image cbfs;
struct cbfs_file *bootblock; struct cbfs_file *mh_container;
if (!partitioned_file_read_region(&buffer, param.image_file, if (!partitioned_file_read_region(&buffer, param.image_file,
SECTION_NAME_PRIMARY_CBFS)) SECTION_NAME_PRIMARY_CBFS))
goto no_metadata_hash; goto no_metadata_hash;
mhc.region = SECTION_NAME_PRIMARY_CBFS; mhc.region = SECTION_NAME_PRIMARY_CBFS;
if (cbfs_image_from_buffer(&cbfs, &buffer, param.headeroffset)) if (cbfs_image_from_buffer(&cbfs, &buffer, param.headeroffset))
goto no_metadata_hash; goto no_metadata_hash;
bootblock = cbfs_get_entry(&cbfs, "bootblock"); mh_container = cbfs_get_entry(&cbfs, "bootblock");
if (!bootblock || be32toh(bootblock->type) != CBFS_TYPE_BOOTBLOCK) if (!mh_container || be32toh(mh_container->type) != CBFS_TYPE_BOOTBLOCK) {
/* Check for apu/amdfw file */
mh_container = cbfs_get_entry(&cbfs, "apu/amdfw");
if (!mh_container || be32toh(mh_container->type) != CBFS_TYPE_AMDFW)
goto no_metadata_hash; goto no_metadata_hash;
offset = (void *)bootblock + be32toh(bootblock->offset) -
buffer_get(&cbfs.buffer);
size = be32toh(bootblock->len);
} }
/* Find and validate the metadata hash anchor inside the bootblock and offset = (void *)mh_container + be32toh(mh_container->offset) -
buffer_get(&cbfs.buffer);
size = be32toh(mh_container->len);
}
/* Find and validate the metadata hash anchor inside the containing file and
record its exact byte offset from the start of the FMAP region. */ record its exact byte offset from the start of the FMAP region. */
struct metadata_hash_anchor *anchor = memmem(buffer_get(&buffer) + offset, struct metadata_hash_anchor *anchor = memmem(buffer_get(&buffer) + offset,
size, METADATA_HASH_ANCHOR_MAGIC, sizeof(anchor->magic)); size, METADATA_HASH_ANCHOR_MAGIC, sizeof(anchor->magic));
@ -264,7 +269,8 @@ static int maybe_update_fmap_hash(void)
{ {
if (strcmp(param.region_name, SECTION_NAME_BOOTBLOCK) && if (strcmp(param.region_name, SECTION_NAME_BOOTBLOCK) &&
strcmp(param.region_name, SECTION_NAME_FMAP) && strcmp(param.region_name, SECTION_NAME_FMAP) &&
param.type != CBFS_TYPE_BOOTBLOCK) param.type != CBFS_TYPE_BOOTBLOCK &&
param.type != CBFS_TYPE_AMDFW)
return 0; /* FMAP and bootblock didn't change. */ return 0; /* FMAP and bootblock didn't change. */
struct mh_cache *mhc = get_mh_cache(); struct mh_cache *mhc = get_mh_cache();
@ -285,6 +291,7 @@ static bool verification_exclude(enum cbfs_type type)
case CBFS_TYPE_BOOTBLOCK: case CBFS_TYPE_BOOTBLOCK:
case CBFS_TYPE_CBFSHEADER: case CBFS_TYPE_CBFSHEADER:
case CBFS_TYPE_INTEL_FIT: case CBFS_TYPE_INTEL_FIT:
case CBFS_TYPE_AMDFW:
return true; return true;
default: default:
return false; return false;