Files
u-boot/include/chid.h
Simon Glass af47c2554d chid: Implement selection of the compatible string
Search the available CHIDs to determine the device on which U-Boot is
running. Use this to select the correct compatible string.

Signed-off-by: Simon Glass <sjg@chromium.org>
2025-09-04 07:08:25 -06:00

231 lines
6.6 KiB
C

/* SPDX-License-Identifier: GPL-2.0+ */
/*
* Computer Hardware Identifiers (Windows CHID)
*
* See: https://github.com/fwupd/fwupd/blob/main/docs/hwids.md
*
* Copyright 2025 Simon Glass <sjg@chromium.org>
*/
#ifndef __chid_h
#define __chid_h
#include <linux/types.h>
#include <stdbool.h>
/**
* enum chid_field_t - fields we pick up from SMBIOS tables
*
* Used as BIT(x) values that can be ORed together to define which fields are
* used in each CHID variant.
*
* The table and field name is shown here (see smbios.h). All are strings
* except those noted as int.
*
* @CHID_MANUF: SMBIOS Type 1 (System Information): manufacturer
* @CHID_FAMILY: SMBIOS Type 1 (System Information): family
* @CHID_PRODUCT_NAME: SMBIOS Type 1 (System Information): product_name
* @CHID_PRODUCT_SKU: SMBIOS Type 1 (System Information): sku_number
* @CHID_BOARD_MANUF: SMBIOS Type 2 (Baseboard Information): manufacturer
* @CHID_BOARD_PRODUCT: SMBIOS Type 2 (Baseboard Information): product_name
* @CHID_BIOS_VENDOR: SMBIOS Type 0 (BIOS Information): vendor
* @CHID_BIOS_VERSION: SMBIOS Type 0 (BIOS Information): bios_ver
* @CHID_BIOS_MAJOR: SMBIOS Type 0 (BIOS Information): bios_major_release (int)
* @CHID_BIOS_MINOR: SMBIOS Type 0 (BIOS Information): bios_minor_release (int)
* @CHID_ENCLOSURE_TYPE: SMBIOS Type 3 (System Enclosure): chassis_type (int)
* @CHID_COUNT: Number of CHID fields
*/
enum chid_field_t {
CHID_MANUF,
CHID_FAMILY,
CHID_PRODUCT_NAME,
CHID_PRODUCT_SKU,
CHID_BOARD_MANUF,
CHID_BOARD_PRODUCT,
CHID_BIOS_VENDOR,
CHID_BIOS_VERSION,
CHID_BIOS_MAJOR,
CHID_BIOS_MINOR,
CHID_ENCLOSURE_TYPE,
CHID_COUNT,
};
/*
* enum chid_variant_id - Microsoft CHID hardware ID variants
*
* This covers HardwareID-00 through HardwareID-14
*/
enum chid_variant_id {
CHID_00, /* Most specific */
CHID_01,
CHID_02,
CHID_03,
CHID_04,
CHID_05,
CHID_06,
CHID_07,
CHID_08,
CHID_09,
CHID_10,
CHID_11,
CHID_12,
CHID_13,
CHID_14, /* Least specific */
CHID_VARIANT_COUNT
};
/**
* struct chid_variant - defines which fields are used in each CHID variant
*
* @name: Human-readable name for debugging
* @fields: Bitmask of fields (BIT(CHID_xxx) values ORed together)
*/
struct chid_variant {
const char *name;
u32 fields;
};
/**
* struct chid_data - contains SMBIOS field values to use in calculating CHID
*
* There is one field here for each item in enum chid_field_t
*
* @manuf: System manufacturer string
* @family: Product family string
* @product_name: Product name string
* @product_sku: Product SKU string
* @board_manuf: Baseboard manufacturer string
* @board_product: Baseboard product string
* @bios_vendor: BIOS vendor string
* @bios_version: BIOS version string
* @bios_major: BIOS major version number
* @bios_minor: BIOS minor version number
* @enclosure_type: System enclosure type
*/
struct chid_data {
const char *manuf;
const char *family;
const char *product_name;
const char *product_sku;
const char *board_manuf;
const char *board_product;
const char *bios_vendor;
const char *bios_version;
u8 bios_major;
u8 bios_minor;
u8 enclosure_type;
};
/**
* chid_from_smbios() - Extract CHID data from SMBIOS tables
*
* @chid: Pointer to CHID data structure to fill
*
* Return: 0 if OK, -ENOENT if a required table is missing (SMBIOS types 0-1),
* other -ve error code if the SMBIOS tables cannot be found (see
* smbios_locate())
*/
int chid_from_smbios(struct chid_data *chid);
/**
* chid_generate() - Generate a specific CHID variant
*
* @variant: Which CHID variant to generate (0-14)
* @data: SMBIOS data to use for generation
* @chid: Output buffer for the generated CHID (16 bytes)
*
* Return: 0 if OK, -ve error code on failure
*/
int chid_generate(int variant, const struct chid_data *data, u8 chid[16]);
/**
* chid_get_field_name() - Get display name of a specific CHID field
*
* @field: Which CHID field
*
* Return: String containing the field name
*/
const char *chid_get_field_name(enum chid_field_t field);
/**
* chid_get_variant_fields() - Get the fields mask for a CHID variant
*
* @variant: Which CHID variant (0-14)
*
* Return: Bitmask of fields used by this variant
*/
u32 chid_get_variant_fields(int variant);
/**
* chid_get_variant_name() - Get the name of a CHID variant
*
* @variant: Which CHID variant (0-14)
*
* Return: String containing the variant name (e.g., "HardwareID-00")
*/
const char *chid_get_variant_name(int variant);
/**
* chid_variant_allowed() - Check if a CHID variant is permitted
*
* @variant: Which CHID variant (enum chid_variant_id)
*
* Some CHID variants are considered too generic and are not permitted:
* - Manufacturer + EnclosureKind (CHID_12)
* - Manufacturer + Family (CHID_11)
* - Manufacturer only (CHID_14)
* - Manufacturer + BaseboardManufacturer + BaseboardProduct (CHID_13)
*
* Return: true if variant is permitted, false if prohibited
*/
bool chid_variant_allowed(enum chid_variant_id variant);
/**
* chid_select_data() - Select compatible string using CHID data
* @chid_data: SMBIOS-derived CHID data to use for matching
* @compatp: Pointer to store the compatible string (if found)
*
* This is the core selection function that can be tested with specific
* CHID data without requiring SMBIOS hardware access.
*
* The selection algorithm:
* 1. Find all CHID nodes in the devicetree
* 2. Calculate match scores for each node based on:
* - Exact CHID match (highest priority)
* - CHID variant specificity
* - Field overlap with provided CHID data
* 3. Return the compatible string from the highest-scoring node
*
* Expected devicetree structure:
* /chid {
* device-node-name {
* compatible = "vendor,device-name";
* variant = <0>; // CHID variant (0-14)
* fields = <0x3cf>; // Bitmask of fields used
* chid = [12 34 56 78 ...]; // UUID_LEN-byte CHID UUID
* };
* };
*
* Return: 0 if compatible string found, -ENOENT if no match, other -ve on error
*/
int chid_select_data(const struct chid_data *chid_data, const char **compatp);
/**
* chid_select() - Select compatible string using CHID and SMBIOS
*
* This function examines CHID information in the devicetree and compares it
* with the current system's SMBIOS data to select the most appropriate
* compatible string for the hardware platform.
*
* This is a convenience wrapper around chid_select_data()
* that automatically extracts SMBIOS data from the current system.
*
* @compatp: Returns pointer to compatible string if found
* Return: 0 if OK, -ENOENT if no suitable match, other -ve on error
*/
int chid_select(const char **compatp);
#endif