[PATCH v4 18/28] coreboot: Dump VPD information in cbsysinfo command
Stephen Boyd
swboyd at chromium.org
Sat May 24 00:58:33 CEST 2025
Coreboot populates a memory copy of the vital product data (VPD) during
boot. Read this data structure and print out the contents in the
cbsysinfo command.
Example: (redacted some things)
Chrome OS VPD: 00000000ffffd000
RO size : 24e
RW size : 122
"region" = "us"
"bluetooth_mac0" = "8C:FD:F0:40:15:28"
"wifi_mac0" = "8C:FD:F0:40:15:22"
"in_accel_x_lid_calibbias" = "38"
"in_accel_y_lid_calibbias" = "11"
...
Signed-off-by: Stephen Boyd <swboyd at chromium.org>
---
cmd/cbsysinfo.c | 34 +++++++++++++++++++++++++++++++++
include/cb_sysinfo.h | 4 ++++
include/coreboot_tables.h | 13 +++++++++++++
lib/coreboot/cb_sysinfo.c | 40 +++++++++++++++++++++++++++++++++++++++
4 files changed, 91 insertions(+)
diff --git a/cmd/cbsysinfo.c b/cmd/cbsysinfo.c
index d6ab71a3db8d..74a66f8c1b9c 100644
--- a/cmd/cbsysinfo.c
+++ b/cmd/cbsysinfo.c
@@ -436,6 +436,40 @@ static void show_table(struct sysinfo_t *info, bool verbose)
print_hex("MTC size", info->mtc_size);
print_ptr("Chrome OS VPD", info->chromeos_vpd);
+ if (info->chromeos_vpd) {
+ struct vpd_cbmem *vpd = info->chromeos_vpd;
+
+ print_hex("RO size", vpd->ro_size);
+ print_hex("RW size", vpd->rw_size);
+
+ unsigned int i = 0;
+ unsigned int len = vpd->ro_size;
+ const u8 *blob = vpd->blob;
+
+ while (i < len) {
+ unsigned int vpd_type = blob[i];
+
+ switch (vpd_type) {
+ case VPD_TYPE_INFO:
+ case VPD_TYPE_STRING:
+ i++;
+ unsigned int key_offset;
+ unsigned int key_len;
+ unsigned int val_offset;
+ unsigned int val_len;
+
+ i = vpd_cbmem_parse_key_value(blob, i, &key_offset, &key_len, &val_offset, &val_len);
+ if (vpd_type == VPD_TYPE_STRING)
+ printf(" \"%.*s\" = \"%.*s\"\n", key_len, blob + key_offset, val_len, blob + val_offset);
+
+ break;
+ default:
+ i++;
+ break;
+ }
+ }
+ }
+
print_ptr("RSDP", info->rsdp);
printf("%-12s: ", "Unimpl.");
if (info->unimpl_count) {
diff --git a/include/cb_sysinfo.h b/include/cb_sysinfo.h
index b2128bb20a19..f6c4f3a5edea 100644
--- a/include/cb_sysinfo.h
+++ b/include/cb_sysinfo.h
@@ -264,6 +264,10 @@ int coreboot_early_init(void);
*/
const struct sysinfo_t *cb_get_sysinfo(void);
+unsigned int vpd_cbmem_parse_key_value(const u8 *blob, unsigned int offset,
+ unsigned int *key_offset, unsigned int *key_len,
+ unsigned int *val_offset, unsigned int *val_len);
+
/**
* fdt_fixup_coreboot() - Add the /firmware/coreboot node to the FDT
*
diff --git a/include/coreboot_tables.h b/include/coreboot_tables.h
index 6e7686e360c5..7d54ff94cf93 100644
--- a/include/coreboot_tables.h
+++ b/include/coreboot_tables.h
@@ -551,6 +551,19 @@ struct cbmem_entry {
#define CBMEM_ID_CONSOLE 0x434f4e53
#define CBMEM_ID_NONE 0x00000000
+struct vpd_cbmem {
+ u32 magic;
+ u32 version;
+ u32 ro_size;
+ u32 rw_size;
+ u8 blob[];
+};
+
+#define VPD_TYPE_TERMINATOR 0x00
+#define VPD_TYPE_STRING 0x01
+#define VPD_TYPE_INFO 0xfe
+#define VPD_TYPE_IMPLICIT_TERMINATOR 0xff
+
/**
* high_table_reserve() - reserve configuration table in high memory
*
diff --git a/lib/coreboot/cb_sysinfo.c b/lib/coreboot/cb_sysinfo.c
index ec9a47242e34..d2e5e6d9bb6e 100644
--- a/lib/coreboot/cb_sysinfo.c
+++ b/lib/coreboot/cb_sysinfo.c
@@ -634,3 +634,43 @@ clean_coreboot:
fdt_del_node_and_alias(blob, node);
}
#endif
+
+/*
+ * Parse the length header that is 7 bits of length and a top bit indicating
+ * "more" to the length.
+ *
+ * | 7 | 6 5 4 3 2 1 0 |
+ * |------+------------------------|
+ * | more | length |
+ *
+ * The "more" bit indicates the next byte after this one has more lower
+ * significant 7 bits. This can be repeated multiple times to make long keys or
+ * values.
+ */
+static unsigned int vpd_cbmem_parse_len(const u8 *blob, unsigned int i,
+ unsigned int *start, unsigned int *_len)
+{
+ u8 more;
+ unsigned int len = 0;
+
+ do {
+ more = blob[i] & 0x80;
+ len <<= 7;
+ len |= blob[i] & 0x7f;
+ i++;
+ } while (more);
+
+ *_len = len;
+ *start = i;
+
+ return i + len;
+}
+
+unsigned int vpd_cbmem_parse_key_value(const u8 *blob, unsigned int offset,
+ unsigned int *key_offset, unsigned int *key_len,
+ unsigned int *val_offset, unsigned int *val_len)
+{
+ offset = vpd_cbmem_parse_len(blob, offset, key_offset, key_len);
+
+ return vpd_cbmem_parse_len(blob, offset, val_offset, val_len);
+}
--
Sent by a computer, using git, on the internet
More information about the U-Boot
mailing list