drivers/hwid_dmi: Populate SMBIOS product name from CBFS hwid file

Add driver to read 'hwid' file from CBFS and use it for SMBIOS product
name. Processes the ChromeOS-format HWID string by removing prefix
after colon, trimming whitespace, and extracting base name before
any hyphen/space. Returned string is normalized to have the first
character/letter capitalized, and the rest lower case. If no HWID file
is found in CBFS, the fallback is CONFIG_MAINBOARD_SMBIOS_PRODUCT_NAME.

This driver is intended to allow ChromeOS devices running upstream
coreboot to persist their board's unique HWID and use it as the SMBIOS
board name, but it is not limited to that function.

TEST=tested in MrChromebox downstream. Multiple devices which use the
same ChromeOS board but differ in HWID can use the same firmware image
and still be properly identified.

Change-Id: I1af1df4c79858d23ef71400abe72f41eec6c25c6
Signed-off-by: Matt DeVillier <matt.devillier@gmail.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/90063
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Martin L Roth <gaumless@gmail.com>
This commit is contained in:
Matt DeVillier 2025-11-01 11:42:36 -05:00
commit ddb3f0b17f
3 changed files with 112 additions and 0 deletions

View file

@ -0,0 +1,12 @@
## SPDX-License-Identifier: GPL-2.0-only
config DRIVERS_HWID_DMI
bool "HWID from CBFS for SMBIOS product name"
default n
help
Enable this option to read the hardware ID (HWID) from a
file in CBFS and use it to populate the SMBIOS product name.
The driver will read a file named 'hwid' from CBFS, process it
to extract the base HWID (trimming whitespace, removing 'hwid:'
prefix, and dropping everything after hyphen or space), and
use it as the SMBIOS system product name.

View file

@ -0,0 +1,3 @@
## SPDX-License-Identifier: GPL-2.0-only
ramstage-$(CONFIG_DRIVERS_HWID_DMI) += hwid_dmi.c

View file

@ -0,0 +1,97 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#include <cbfs.h>
#include <console/console.h>
#include <ctype.h>
#include <smbios.h>
#include <string.h>
#define MAX_HWID_LENGTH 0x100
/*
* Process the HWID string according to requirements:
* - If a colon is found, delete everything before it
* - Trim leading/trailing whitespace
* - Drop anything after hyphen or space
*
* Examples:
* - 'hardware_id: NOCTURNE D5B-A5F-B47-H6A-A5L' --> Nocturne
* - 'BANSHEE-UZTQ B4B-D3A-F3F-D8A-A7O' --> Banshee
*/
static void process_hwid(char *hwid)
{
char *src = hwid;
char *dst = hwid;
char *colon;
char *end;
if (!hwid || !*hwid)
return;
/* Look for a colon and skip everything before it */
colon = strchr(hwid, ':');
if (colon) {
src = colon + 1; /* Start after the colon */
}
/* Trim leading whitespace */
while (*src && isspace((unsigned char)*src))
src++;
/* Copy characters until we hit a hyphen, space, or end of string */
while (*src && *src != '-' && !isspace((unsigned char)*src)) {
*dst++ = *src++;
}
/* Null terminate */
*dst = '\0';
/* Trim trailing whitespace (shouldn't be any based on the logic above, but just in case) */
end = dst - 1;
while (end >= hwid && isspace((unsigned char)*end)) {
*end = '\0';
end--;
}
/* Normalize casing: capitalize first character, lowercase the rest */
if (*hwid) {
char *p = hwid;
*p = toupper((unsigned char)*p);
for (p = hwid + 1; *p; p++)
*p = tolower((unsigned char)*p);
}
}
const char *smbios_system_product_name(void)
{
static char hwid_str[MAX_HWID_LENGTH + 1] = {0};
/* Return cached value if already loaded */
if (hwid_str[0] != '\0')
return hwid_str;
/* Try to load HWID from CBFS */
size_t hwid_len = cbfs_load("hwid", hwid_str, MAX_HWID_LENGTH);
if (hwid_len > 0) {
/* Ensure null termination */
hwid_str[hwid_len] = '\0';
/* Process the HWID string */
process_hwid(hwid_str);
/* Check if we have a valid string after processing */
if (hwid_str[0] != '\0') {
printk(BIOS_INFO, "HWID: Using '%s' as product name\n", hwid_str);
return hwid_str;
}
}
/* Fall back to default if file not found or processing resulted in empty string */
printk(BIOS_WARNING, "HWID: File not found or invalid, using default product name\n");
strncpy(hwid_str, CONFIG_MAINBOARD_SMBIOS_PRODUCT_NAME, MAX_HWID_LENGTH);
hwid_str[MAX_HWID_LENGTH] = '\0';
return hwid_str;
}