[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