From cf2978f4b6c9372a37464e1c494ab3bb0100e6a7 Mon Sep 17 00:00:00 2001 From: Jian-Jia Su Date: Wed, 16 Jul 2025 20:18:03 +0800 Subject: [PATCH] drivers/vpd: Search VPD info at 0x0 first We used to put SMBIOS header and other data before VPD. That is not the case anymore. New device will write the VPD starting at 0 instead of 0x600. Search VPD at 0x0 to support this. TEST=build and boot google/geralt. VPD is found both at 0 and at 0x600. Change-Id: I7072f7c646b6b55d11bc06dba5674828246fa1d0 Signed-off-by: Jian-Jia Su Reviewed-on: https://review.coreboot.org/c/coreboot/+/88466 Tested-by: build bot (Jenkins) Reviewed-by: Julius Werner --- src/drivers/vpd/vpd.c | 49 ++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 26 deletions(-) diff --git a/src/drivers/vpd/vpd.c b/src/drivers/vpd/vpd.c index 9e12967cf3..56b09263c3 100644 --- a/src/drivers/vpd/vpd.c +++ b/src/drivers/vpd/vpd.c @@ -43,6 +43,8 @@ static struct region_device ro_vpd, rw_vpd; /* * Initializes a region_device to represent the requested VPD 2.0 formatted * region on flash. On errors rdev->size will be set to 0. + * Check google_vpd_info at offset 0 first. If not found, fall back to + * GOOGLE_VPD_2_0_OFFSET. */ static void init_vpd_rdev(const char *fmap_name, struct region_device *rdev) { @@ -57,36 +59,31 @@ static void init_vpd_rdev(const char *fmap_name, struct region_device *rdev) size = region_device_sz(rdev); - if ((size < GOOGLE_VPD_2_0_OFFSET + sizeof(info)) || - rdev_chain(rdev, rdev, GOOGLE_VPD_2_0_OFFSET, - size - GOOGLE_VPD_2_0_OFFSET)) { - printk(BIOS_ERR, "%s: Too small (%d) for Google VPD 2.0.\n", - __func__, size); - goto fail; - } - - /* Try if we can find a google_vpd_info, otherwise read whole VPD. */ - if (rdev_readat(rdev, &info, 0, sizeof(info)) != sizeof(info)) { - printk(BIOS_ERR, "Failed to read %s header.\n", - fmap_name); - goto fail; - } - - if (memcmp(info.header.magic, VPD_INFO_MAGIC, sizeof(info.header.magic)) - == 0) { - if (rdev_chain(rdev, rdev, sizeof(info), info.size)) { - printk(BIOS_ERR, "%s info size too large.\n", + size_t possible_offsets[] = {0x0, GOOGLE_VPD_2_0_OFFSET}; + for (int i = 0; i < ARRAY_SIZE(possible_offsets); i++) { + size_t offset = possible_offsets[i]; + if (size < offset + sizeof(info)) { + printk(BIOS_ERR, + "%s: Too small (%d) for Google VPD 2.0.\n", + __func__, size); + goto fail; + } + if (rdev_readat(rdev, &info, offset, sizeof(info)) != sizeof(info)) { + printk(BIOS_ERR, "Failed to read %s header.\n", fmap_name); goto fail; } - } else if (info.header.tlv.type == VPD_TYPE_TERMINATOR || - info.header.tlv.type == VPD_TYPE_IMPLICIT_TERMINATOR) { - printk(BIOS_WARNING, "%s is uninitialized or empty.\n", - fmap_name); - goto fail; + if (memcmp(info.header.magic, VPD_INFO_MAGIC, sizeof(info.header.magic)) == 0) { + if (rdev_chain(rdev, rdev, offset + sizeof(info), info.size) == 0) { + return; + } else { + printk(BIOS_ERR, "%s info size too large.\n", + fmap_name); + goto fail; + } + } } - - return; + printk(BIOS_WARNING, "%s is uninitialized.\n", fmap_name); fail: memset(rdev, 0, sizeof(*rdev));