cbfstool: Expand CBFS verification validity check
This patch adds a new line to `cbfstool print -v` output that records the overall CBFS verification health of the image. While this info was already visible from individual fields before, it's nice to have a one-stop location to see "this is a good image" without having to carefully parse a lot of output manually. Also add a few lines to the Makefile that check whether this field is valid for the final image (it always should be, but hopefully this check will allow us to catch regressions like the one fixed by CB:64547 sooner in the future). BUG=b:233263447 Signed-off-by: Julius Werner <jwerner@chromium.org> Change-Id: I1b74b01a55b22294556007aaee835d0fdb9e1c63 Reviewed-on: https://review.coreboot.org/c/coreboot/+/64657 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Yu-Ping Wu <yupingso@google.com>
This commit is contained in:
parent
bb1e37e76b
commit
423cd06fa6
|
@ -1162,6 +1162,13 @@ endif # CONFIG_CPU_INTEL_FIRMWARE_INTERFACE_TABLE
|
||||||
$(CBFSTOOL) $@ layout
|
$(CBFSTOOL) $@ layout
|
||||||
@printf " CBFSPRINT $(subst $(obj)/,,$(@))\n\n"
|
@printf " CBFSPRINT $(subst $(obj)/,,$(@))\n\n"
|
||||||
$(CBFSTOOL) $@ print -r $(subst $(spc),$(comma),$(all-regions))
|
$(CBFSTOOL) $@ print -r $(subst $(spc),$(comma),$(all-regions))
|
||||||
|
ifeq ($(CONFIG_CBFS_VERIFICATION),y)
|
||||||
|
line=$$($(CBFSTOOL) $@ print -kv 2>/dev/null | grep -F '[CBFS VERIFICATION (COREBOOT)]') ;\
|
||||||
|
if ! printf "$$line" | grep -q 'fully valid'; then \
|
||||||
|
echo "CBFS verification error: $$line" ;\
|
||||||
|
exit 1 ;\
|
||||||
|
fi
|
||||||
|
endif # CONFIG_CBFS_VERIFICATION
|
||||||
|
|
||||||
cbfs-files-y += $(CONFIG_CBFS_PREFIX)/romstage
|
cbfs-files-y += $(CONFIG_CBFS_PREFIX)/romstage
|
||||||
$(CONFIG_CBFS_PREFIX)/romstage-file := $(objcbfs)/romstage.elf
|
$(CONFIG_CBFS_PREFIX)/romstage-file := $(objcbfs)/romstage.elf
|
||||||
|
|
|
@ -1499,6 +1499,23 @@ static int cbfs_layout(void)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static enum cb_err verify_walker(__unused cbfs_dev_t dev, size_t offset,
|
||||||
|
const union cbfs_mdata *mdata, size_t already_read, void *arg)
|
||||||
|
{
|
||||||
|
uint32_t type = be32toh(mdata->h.type);
|
||||||
|
uint32_t data_offset = be32toh(mdata->h.offset);
|
||||||
|
if (verification_exclude(type))
|
||||||
|
return CB_CBFS_NOT_FOUND;
|
||||||
|
assert(already_read == data_offset);
|
||||||
|
const struct vb2_hash *hash = cbfs_file_hash(mdata);
|
||||||
|
if (!hash)
|
||||||
|
return CB_ERR;
|
||||||
|
void *file_data = arg + offset + data_offset;
|
||||||
|
if (vb2_hash_verify(file_data, be32toh(mdata->h.len), hash) != VB2_SUCCESS)
|
||||||
|
return CB_CBFS_HASH_MISMATCH;
|
||||||
|
return CB_CBFS_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
static int cbfs_print(void)
|
static int cbfs_print(void)
|
||||||
{
|
{
|
||||||
struct cbfs_image image;
|
struct cbfs_image image;
|
||||||
|
@ -1515,29 +1532,33 @@ static int cbfs_print(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
|
const char *verification_state = "fully valid";
|
||||||
struct mh_cache *mhc = get_mh_cache();
|
struct mh_cache *mhc = get_mh_cache();
|
||||||
if (mhc->cbfs_hash.algo == VB2_HASH_INVALID)
|
if (mhc->cbfs_hash.algo == VB2_HASH_INVALID)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
struct vb2_hash real_hash = { .algo = mhc->cbfs_hash.algo };
|
struct vb2_hash real_hash = { .algo = mhc->cbfs_hash.algo };
|
||||||
enum cb_err err = cbfs_walk(&image, NULL, NULL, &real_hash,
|
enum cb_err err = cbfs_walk(&image, verify_walker, buffer_get(&image.buffer),
|
||||||
CBFS_WALK_WRITEBACK_HASH);
|
&real_hash, CBFS_WALK_WRITEBACK_HASH);
|
||||||
if (err != CB_CBFS_NOT_FOUND) {
|
if (err == CB_CBFS_HASH_MISMATCH)
|
||||||
ERROR("Unexpected cbfs_walk() error %d\n", err);
|
verification_state = "invalid file hashes";
|
||||||
return 1;
|
else if (err != CB_CBFS_NOT_FOUND)
|
||||||
}
|
verification_state = "missing file hashes";
|
||||||
char *hash_str = bintohex(real_hash.raw,
|
char *hash_str = bintohex(real_hash.raw,
|
||||||
vb2_digest_size(real_hash.algo));
|
vb2_digest_size(real_hash.algo));
|
||||||
printf("[METADATA HASH]\t%s:%s",
|
printf("[METADATA HASH]\t%s:%s",
|
||||||
vb2_get_hash_algorithm_name(real_hash.algo), hash_str);
|
vb2_get_hash_algorithm_name(real_hash.algo), hash_str);
|
||||||
if (!strcmp(param.region_name, SECTION_NAME_PRIMARY_CBFS)) {
|
if (!strcmp(param.region_name, SECTION_NAME_PRIMARY_CBFS)) {
|
||||||
if (!memcmp(mhc->cbfs_hash.raw, real_hash.raw,
|
if (!memcmp(mhc->cbfs_hash.raw, real_hash.raw,
|
||||||
vb2_digest_size(real_hash.algo)))
|
vb2_digest_size(real_hash.algo))) {
|
||||||
printf(":valid");
|
printf(":valid");
|
||||||
else
|
} else {
|
||||||
printf(":invalid");
|
printf(":invalid");
|
||||||
|
verification_state = "invalid metadata hash";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
printf("[CBFS VERIFICATION (%s)]\t%s\n", param.region_name, verification_state);
|
||||||
free(hash_str);
|
free(hash_str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue