diff --git a/include/chid.h b/include/chid.h
new file mode 100644
index 00000000000..5746ba88c32
--- /dev/null
+++ b/include/chid.h
@@ -0,0 +1,106 @@
+/* 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>
+
+/**
+ * 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,
+};
+
+/**
+ * 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);
+
+#endif
diff --git a/lib/Kconfig b/lib/Kconfig
index ed35c1f0b30..c45a98313aa 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -1187,6 +1187,15 @@ config SMBIOS_PARSER
 	help
 	  A simple parser for SMBIOS data.
 
+config CHID
+	bool "Support Microsoft Computer Hardware IDs (CHIDs)"
+	depends on SMBIOS_PARSER
+	default y if ARCH_EFI_ARM || SANDBOX
+	help
+	  Provides support for Microsoft Computer Hardware IDs (CHIDs) which
+	  can be used to identify a board so that the correct devicetree is
+	  used with it.
+
 source "lib/optee/Kconfig"
 
 config TEST_FDTDEC
diff --git a/lib/Makefile b/lib/Makefile
index bcca308e0d8..af191913873 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -29,6 +29,8 @@ obj-y += charset.o
 endif
 endif
 
+obj-$(CONFIG_CHID) += chid.o
+
 ifdef CONFIG_USB_TTY
 obj-y += circbuf.o
 else
diff --git a/lib/chid.c b/lib/chid.c
new file mode 100644
index 00000000000..10e9b8fecae
--- /dev/null
+++ b/lib/chid.c
@@ -0,0 +1,73 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Computer Hardware Identifiers (Windows CHID) support
+ *
+ * This implements the Microsoft Computer Hardware ID specification
+ * used by Windows Update and fwupd for hardware identification.
+ *
+ * See: https://github.com/fwupd/fwupd/blob/main/docs/hwids.md
+ * See: https://docs.microsoft.com/en-us/windows-hardware/drivers/install/specifying-hardware-ids-for-a-computer
+ *
+ * Copyright 2025 Simon Glass <sjg@chromium.org>
+ */
+
+#define LOG_CATEGORY	LOGC_ACPI
+
+#include <chid.h>
+#include <errno.h>
+#include <smbios.h>
+#include <asm/global_data.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int chid_from_smbios(struct chid_data *chid)
+{
+	const struct smbios_type0 *bios;
+	const struct smbios_type1 *sys;
+	const struct smbios_type2 *board;
+	const struct smbios_type3 *encl;
+	struct smbios_info info;
+	int ret;
+
+	/* Clear the structure first */
+	memset(chid, '\0', sizeof(*chid));
+
+	ret = smbios_locate(gd_smbios_start(), &info);
+	if (ret)
+		return ret;
+
+	/* Extract BIOS Information (Type 0) */
+	bios = smbios_get_header(&info, SMBIOS_BIOS_INFORMATION);
+	if (!bios)
+		return log_msg_ret("cf0", -ENOENT);
+
+	chid->bios_vendor = smbios_string(&bios->hdr, bios->vendor);
+	chid->bios_version = smbios_string(&bios->hdr, bios->bios_ver);
+	chid->bios_major = bios->bios_major_release;
+	chid->bios_minor = bios->bios_minor_release;
+
+	/* Extract System Information (Type 1) */
+	sys = smbios_get_header(&info, SMBIOS_SYSTEM_INFORMATION);
+	if (!sys)
+		return log_msg_ret("cf1", -ENOENT);
+	chid->manuf = smbios_string(&sys->hdr, sys->manufacturer);
+	chid->product_name = smbios_string(&sys->hdr, sys->product_name);
+	chid->family = smbios_string(&sys->hdr, sys->family);
+	chid->product_sku = smbios_string(&sys->hdr, sys->sku_number);
+
+	/* Extract Baseboard Information (Type 2) */
+	board = smbios_get_header(&info, SMBIOS_BOARD_INFORMATION);
+	if (board) {
+		chid->board_manuf = smbios_string(&board->hdr,
+						  board->manufacturer);
+		chid->board_product = smbios_string(&board->hdr,
+						    board->product_name);
+	}
+
+	/* Extract System Enclosure Information (Type 3) */
+	encl = smbios_get_header(&info, SMBIOS_SYSTEM_ENCLOSURE);
+	if (encl)
+		chid->enclosure_type = encl->chassis_type;
+
+	return 0;
+}
