[Concept,17/25] chid: Add subcommand for dealing with variants

Message ID 20250903133639.3235920-18-sjg@u-boot.org
State New
Headers
Series Selection of devicetree using CHIDs |

Commit Message

Simon Glass Sept. 3, 2025, 1:36 p.m. UTC
  From: Simon Glass <sjg@chromium.org>

Add a 'chid list' command to display the values for all CHID variants.
Also add 'chid detail' to see all details about a variant.

Co-developed-by: Claude <noreply@anthropic.com>
Signed-off-by: Simon Glass <sjg@chromium.org>
---

 cmd/chid.c             | 95 +++++++++++++++++++++++++++++++++++++++++-
 doc/usage/cmd/chid.rst | 32 ++++++++++++++
 include/chid.h         |  9 ++++
 lib/chid.c             |  9 ++++
 test/cmd/chid.c        | 48 +++++++++++++++++++++
 5 files changed, 191 insertions(+), 2 deletions(-)
  

Patch

diff --git a/cmd/chid.c b/cmd/chid.c
index 096f88e3c44..f61e8370f84 100644
--- a/cmd/chid.c
+++ b/cmd/chid.c
@@ -8,6 +8,8 @@ 
 #include <chid.h>
 #include <command.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[])
@@ -36,8 +38,97 @@  static int do_chid_show(struct cmd_tbl *cmdtp, int flag, int argc,
 	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;
+}
+
 U_BOOT_LONGHELP(chid,
-	"show - Show CHID data extracted from SMBIOS");
+	"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(show, 1, 1, do_chid_show));
+	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));
diff --git a/doc/usage/cmd/chid.rst b/doc/usage/cmd/chid.rst
index d24f213df0f..77e6f57654d 100644
--- a/doc/usage/cmd/chid.rst
+++ b/doc/usage/cmd/chid.rst
@@ -8,7 +8,9 @@  Synopsis
 
 ::
 
+    chid list
     chid show
+    chid detail <variant>
 
 Description
 -----------
@@ -30,6 +32,12 @@  show
     Show the relevant SMBIOS values for the current board. These are used to
     calculate CHIDs.
 
+list
+    Display all 15 CHID variants with their generated UUIDs
+
+detail <variant>
+    Display details for a specific CHID variant (0-14), including which
+    SMBIOS fields are used and the generated UUID
 
 Examples
 --------
@@ -50,6 +58,30 @@  Examples
     Enclosure Type:    2
     =>
 
+This shows how to obtain the CHIDs for all variants::
+
+    => chid list
+    HardwareID-00: 133e2a0f-2299-5874-b475-40f5a1744a35
+    HardwareID-01: a9648aa2-bb0e-5e53-95d7-432ac18f041f
+    HardwareID-02: cbb458c8-4d1a-5898-9a2c-6657c6664a9a
+    HardwareID-03: a07db1d8-e0f9-5d47-a507-8c358eb7edf4
+    HardwareID-04: 5efd2af9-23d6-5fe6-bdb0-e040b9e5b054
+    HardwareID-05: 48aede6f-65db-51a5-8905-fdabdbc0685e
+    HardwareID-06: d1c25f0a-6eb8-5c23-961c-e46694384fa0
+    HardwareID-07: 84398dad-5de1-553b-87b9-1b7c4b02c505
+    HardwareID-08: ed1fa480-f06b-52ba-b203-56562c52c7e2
+    HardwareID-09: c0185db1-6111-5432-955a-e5ecdac0d351
+    HardwareID-10: 6b7ad4ae-1f41-52dd-8499-ab9ab9e8688c
+    HardwareID-11: 72523836-a3fc-57b0-8d3c-4ce56cbf6b96
+    HardwareID-12: e93b37fb-5592-55dd-8e4b-9df3fbc9abde
+    HardwareID-13: d67e233f-5cad-541c-87f8-ee9bca569e5e
+    HardwareID-14: 45c5e2e7-db48-556b-aae4-0a03c5a15eae
+
+Show details for a specific variant::
+
+    => chid detail 14
+    HardwareID-14: 45c5e2e7-db48-556b-aae4-0a03c5a15eae
+    Fields: Manufacturer
 
 Configuration
 -------------
diff --git a/include/chid.h b/include/chid.h
index 0ea2053b08c..cad24b1ab16 100644
--- a/include/chid.h
+++ b/include/chid.h
@@ -157,4 +157,13 @@  const char *chid_get_field_name(enum chid_field_t field);
  */
 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);
+
 #endif
diff --git a/lib/chid.c b/lib/chid.c
index 1522ae04c79..84e6195c889 100644
--- a/lib/chid.c
+++ b/lib/chid.c
@@ -22,6 +22,7 @@ 
 #include <asm/global_data.h>
 #include <linux/bitops.h>
 #include <linux/utf.h>
+#include <linux/kernel.h>
 #include <u-boot/uuid.h>
 
 DECLARE_GLOBAL_DATA_PTR;
@@ -296,3 +297,11 @@  u32 chid_get_variant_fields(int variant)
 
 	return variants[variant].fields;
 }
+
+const char *chid_get_variant_name(int variant)
+{
+	if (variant < 0 || variant >= CHID_VARIANT_COUNT)
+		return "Invalid";
+
+	return variants[variant].name;
+}
diff --git a/test/cmd/chid.c b/test/cmd/chid.c
index 4b28db2abde..9968e7dc518 100644
--- a/test/cmd/chid.c
+++ b/test/cmd/chid.c
@@ -43,3 +43,51 @@  static int cmd_chid_invalid_test(struct unit_test_state *uts)
 	return 0;
 }
 CMD_TEST(cmd_chid_invalid_test, UTF_CONSOLE);
+
+/* Test the 'chid list' command */
+static int cmd_chid_list_test(struct unit_test_state *uts)
+{
+	/* Test chid list command runs successfully */
+	ut_assertok(run_command("chid list", 0));
+
+	/* Just verify that some output is produced - exact CHIDs vary */
+	return 0;
+}
+CMD_TEST(cmd_chid_list_test, UTF_CONSOLE);
+
+/* Test the 'chid detail' command */
+static int cmd_chid_detail_test(struct unit_test_state *uts)
+{
+	/* Test chid detail command for variant 14 (manufacturer only) */
+	ut_assertok(run_command("chid detail 14", 0));
+
+	ut_assert_nextlinen("HardwareID-14: ");
+	ut_assert_nextline("Fields: Manufacturer");
+	ut_assert_console_end();
+
+	/* Test chid detail command for variant 0 (most specific) */
+	ut_assertok(run_command("chid detail 0", 0));
+
+	ut_assert_nextlinen("HardwareID-00: ");
+	ut_assert_nextline(
+		"Fields: Manufacturer + Family + ProductName + ProductSku + "
+		"BiosVendor + BiosVersion + BiosMajorRelease + "
+		"BiosMinorRelease");
+	ut_assert_console_end();
+
+	return 0;
+}
+CMD_TEST(cmd_chid_detail_test, UTF_CONSOLE);
+
+/* Test chid detail with invalid variant */
+static int cmd_chid_detail_invalid_test(struct unit_test_state *uts)
+{
+	/* Test chid detail with invalid variant number - should fail */
+	ut_asserteq(1, run_command("chid detail 15", 0));
+
+	/* Test chid detail with negative variant number - should fail */
+	ut_asserteq(1, run_command("chid detail -1", 0));
+
+	return 0;
+}
+CMD_TEST(cmd_chid_detail_invalid_test, 0);