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 <swb...@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