Add a new 'chid compat' subcommand that finds the compatible string
matching the current hardware's CHID and sets the fdtcompat environment
variable. This examines the devicetree under /chid for nodes with
hardware-id child nodes containing CHID data that matches the system's
generated CHIDs.
The command prints the found compatible string to the console and
automatically sets the fdtcompat environment variable for use by
other U-Boot commands.
Series-to: concept
Cover-letter:
Selection of devicetree using CHIDs
This series implements support for Microsoft's Computer Hardware
Identifier (CHID) specification in U-Boot. CHIDs provide a standardised
way to identify hardware configurations using SMBIOS data, enabling
automatic selection of appropriate device tree overlays and drivers when
the firmware itself lacks support for devicetree.
The CHID system generates UUIDs from various combinations of hardware
information (manufacturer, product name, BIOS version, etc.) creating a
hierarchy from most to least specific. This allows U-Boot to
automatically select the correct devicetree compatible-string for the
hardware on which it running.
This series includes:
* Core CHID Infrastructure:
- UUID v5 generation with Microsoft's CHID namespace
- Support for all 15 CHID variants (HardwareID-00 through HardwareID-14)
- SMBIOS data extraction and processing
* Devicetree Integration:
- hwids_to_dtsi.py script to convert CHID files to devicetree .dtsi
- Automatic inclusion of the .dtsi into the board'' devicetree
- Runtime compatible-string-selection based on hardware CHIDs
* chid command:
- chid show - show current hardware information and generated CHIDs
- chid list - list all supported CHID variants and generated UUIDs
- chid variants - show information about CHID variant restrictions
- chid compat - select the compatible string for current hardware
* ARM/EFI Support:
- CHID mappings for a selection of ARM-based Windows devices
- Support for Qualcomm Snapdragon platforms (MSM8998, SC7180, SC8180X,
SC8280XP, SDM850, X1E series)
* Testing:
- Sandbox tests using mock SMBIOS data
- CI integration for hwids_to_dtsi validation
- Validation against Microsoft's ComputerHardwareIds.exe output
Documentation is provided for this new subsystem and associated
commands.
END
Co-developed-by: Claude <noreply@anthropic.com>
Signed-off-by: Simon Glass <sjg@chromium.org>
Series-links: 1:22
161 lines
4.0 KiB
C
161 lines
4.0 KiB
C
// SPDX-License-Identifier: GPL-2.0+
|
|
/*
|
|
* Command for Computer Hardware Identifiers (Windows CHID)
|
|
*
|
|
* Copyright 2025 Simon Glass <sjg@chromium.org>
|
|
*/
|
|
|
|
#include <chid.h>
|
|
#include <command.h>
|
|
#include <env.h>
|
|
#include <vsprintf.h>
|
|
#include <linux/bitops.h>
|
|
#include <u-boot/uuid.h>
|
|
|
|
static int do_chid_show(struct cmd_tbl *cmdtp, int flag, int argc,
|
|
char *const argv[])
|
|
{
|
|
struct chid_data chid;
|
|
int ret;
|
|
|
|
ret = chid_from_smbios(&chid);
|
|
if (ret) {
|
|
printf("Failed to get CHID data from SMBIOS (err=%dE)\n", ret);
|
|
return CMD_RET_FAILURE;
|
|
}
|
|
|
|
printf("Manufacturer: %s\n", chid.manuf);
|
|
printf("Family: %s\n", chid.family);
|
|
printf("Product Name: %s\n", chid.product_name);
|
|
printf("Product SKU: %s\n", chid.product_sku);
|
|
printf("Baseboard Manuf: %s\n", chid.board_manuf);
|
|
printf("Baseboard Product: %s\n", chid.board_product);
|
|
printf("BIOS Vendor: %s\n", chid.bios_vendor);
|
|
printf("BIOS Version: %s\n", chid.bios_version);
|
|
printf("BIOS Major: %u\n", chid.bios_major);
|
|
printf("BIOS Minor: %u\n", chid.bios_minor);
|
|
printf("Enclosure Type: %u\n", chid.enclosure_type);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int do_chid_list(struct cmd_tbl *cmdtp, int flag, int argc,
|
|
char *const argv[])
|
|
{
|
|
char chid_str[UUID_STR_LEN + 1];
|
|
u8 chid_bytes[UUID_LEN];
|
|
struct chid_data chid;
|
|
int variant, ret;
|
|
|
|
ret = chid_from_smbios(&chid);
|
|
if (ret) {
|
|
printf("Failed to get CHID data from SMBIOS (err=%d)\n", ret);
|
|
return CMD_RET_FAILURE;
|
|
}
|
|
|
|
for (variant = 0; variant < CHID_VARIANT_COUNT; variant++) {
|
|
ret = chid_generate(variant, &chid, chid_bytes);
|
|
if (ret) {
|
|
printf("%s: <generation failed>\n",
|
|
chid_get_variant_name(variant));
|
|
continue;
|
|
}
|
|
|
|
uuid_bin_to_str(chid_bytes, chid_str, UUID_STR_FORMAT_STD);
|
|
printf("%s: %s\n", chid_get_variant_name(variant), chid_str);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int do_chid_detail(struct cmd_tbl *cmdtp, int flag, int argc,
|
|
char *const argv[])
|
|
{
|
|
char chid_str[UUID_STR_LEN + 1];
|
|
u8 chid_bytes[UUID_LEN];
|
|
struct chid_data chid;
|
|
int fields, field;
|
|
int variant, ret;
|
|
bool first;
|
|
|
|
if (argc != 2) {
|
|
printf("Usage: chid show <variant>\n");
|
|
return CMD_RET_USAGE;
|
|
}
|
|
|
|
variant = simple_strtol(argv[1], NULL, 10);
|
|
if (variant < 0 || variant >= CHID_VARIANT_COUNT) {
|
|
printf("Invalid variant %d (must be 0-%d)\n", variant,
|
|
CHID_VARIANT_COUNT - 1);
|
|
return CMD_RET_FAILURE;
|
|
}
|
|
|
|
ret = chid_from_smbios(&chid);
|
|
if (ret) {
|
|
printf("Failed to get CHID data from SMBIOS (err=%dE)\n", ret);
|
|
return CMD_RET_FAILURE;
|
|
}
|
|
|
|
ret = chid_generate(variant, &chid, chid_bytes);
|
|
if (ret) {
|
|
printf("Failed to generate CHID variant %d (err=%dE)\n",
|
|
variant, ret);
|
|
return CMD_RET_FAILURE;
|
|
}
|
|
|
|
uuid_bin_to_str(chid_bytes, chid_str, UUID_STR_FORMAT_STD);
|
|
printf("%s: %s\n", chid_get_variant_name(variant), chid_str);
|
|
|
|
/* Show which fields are used */
|
|
printf("Fields: ");
|
|
fields = chid_get_variant_fields(variant);
|
|
first = true;
|
|
|
|
for (field = 0; field < CHID_COUNT; field++) {
|
|
if (fields & BIT(field)) {
|
|
if (!first)
|
|
printf(" + ");
|
|
printf("%s", chid_get_field_name(field));
|
|
first = 0;
|
|
}
|
|
}
|
|
printf("\n");
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int do_chid_compat(struct cmd_tbl *cmdtp, int flag, int argc,
|
|
char *const argv[])
|
|
{
|
|
const char *compat;
|
|
int ret;
|
|
|
|
ret = chid_select(&compat);
|
|
if (ret) {
|
|
printf("No compatible string found (err=%d)\n", ret);
|
|
return CMD_RET_FAILURE;
|
|
}
|
|
|
|
printf("%s\n", compat);
|
|
|
|
ret = env_set("fdtcompat", compat);
|
|
if (ret) {
|
|
printf("Failed to set fdtcompat environment variable (err=%d)\n", ret);
|
|
return CMD_RET_FAILURE;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
U_BOOT_LONGHELP(chid,
|
|
"compat - Find compatible string and set fdtcompat env var\n"
|
|
"list - List all CHID variants\n"
|
|
"show - Show CHID data extracted from SMBIOS\n"
|
|
"detail <variant> - Show details for a specific CHID variant (0-14)");
|
|
|
|
U_BOOT_CMD_WITH_SUBCMDS(chid, "Computer Hardware ID utilities", chid_help_text,
|
|
U_BOOT_SUBCMD_MKENT(compat, 1, 1, do_chid_compat),
|
|
U_BOOT_SUBCMD_MKENT(list, 1, 1, do_chid_list),
|
|
U_BOOT_SUBCMD_MKENT(show, 1, 1, do_chid_show),
|
|
U_BOOT_SUBCMD_MKENT(detail, 2, 1, do_chid_detail));
|