[Concept,25/25] cmd: chid: Add 'compat' subcommand to find compatible string

Message ID 20250903133639.3235920-26-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 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.

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

 cmd/chid.c             | 26 ++++++++++++++++++++++++++
 doc/usage/cmd/chid.rst | 14 ++++++++++++++
 test/cmd/chid.c        | 32 ++++++++++++++++++++++++++++++++
 3 files changed, 72 insertions(+)
  

Patch

diff --git a/cmd/chid.c b/cmd/chid.c
index f61e8370f84..24c145a6dad 100644
--- a/cmd/chid.c
+++ b/cmd/chid.c
@@ -7,6 +7,7 @@ 
 
 #include <chid.h>
 #include <command.h>
+#include <env.h>
 #include <vsprintf.h>
 #include <linux/bitops.h>
 #include <u-boot/uuid.h>
@@ -123,12 +124,37 @@  static int do_chid_detail(struct cmd_tbl *cmdtp, int flag, int argc,
 	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));
diff --git a/doc/usage/cmd/chid.rst b/doc/usage/cmd/chid.rst
index e96101928d8..9644b28562e 100644
--- a/doc/usage/cmd/chid.rst
+++ b/doc/usage/cmd/chid.rst
@@ -8,6 +8,7 @@  Synopsis
 
 ::
 
+    chid compat
     chid list
     chid show
     chid detail <variant>
@@ -32,6 +33,12 @@  show
     Show the relevant SMBIOS values for the current board. These are used to
     calculate CHIDs.
 
+compat
+    Find the compatible string that matches the current hardware's CHID and
+    set 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.
+
 list
     Display all 15 CHID variants with their generated UUIDs
 
@@ -83,6 +90,13 @@  Show details for a specific variant::
     HardwareID-14: 45c5e2e7-db48-556b-aae4-0a03c5a15eae
     Fields: Manufacturer
 
+Find compatible string and set environment variable::
+
+    => chid compat
+    google,veyron-speedy
+    => printenv fdtcompat
+    fdtcompat=google,veyron-speedy
+
 Configuration
 -------------
 
diff --git a/test/cmd/chid.c b/test/cmd/chid.c
index 9968e7dc518..01bde5d436c 100644
--- a/test/cmd/chid.c
+++ b/test/cmd/chid.c
@@ -7,6 +7,7 @@ 
 
 #include <command.h>
 #include <console.h>
+#include <env.h>
 #include <test/cmd.h>
 #include <test/ut.h>
 #include <version.h>
@@ -91,3 +92,34 @@  static int cmd_chid_detail_invalid_test(struct unit_test_state *uts)
 	return 0;
 }
 CMD_TEST(cmd_chid_detail_invalid_test, 0);
+
+/* Test the 'chid compat' command */
+static int cmd_chid_compat_test(struct unit_test_state *uts)
+{
+	const char *fdtcompat_val;
+	int ret;
+
+	/* Clear any existing fdtcompat environment variable */
+	env_set("fdtcompat", NULL);
+	ut_assertnull(env_get("fdtcompat"));
+
+	/* Run chid compat command - may succeed or fail depending on devicetree */
+	ret = run_command("chid compat", 0);
+
+	if (ret == 0) {
+		/* Command succeeded, check that fdtcompat was set */
+		fdtcompat_val = env_get("fdtcompat");
+		ut_assertnonnull(fdtcompat_val);
+		ut_assert(strlen(fdtcompat_val) > 0);
+		/* Command should print the compatible string it found */
+		ut_assert_nextline(fdtcompat_val);
+	} else {
+		/* Command failed, check expected failure message and no env var set */
+		ut_assert_nextline("No compatible string found");
+		ut_assertnull(env_get("fdtcompat"));
+	}
+
+	ut_assert_console_end();
+	return 0;
+}
+CMD_TEST(cmd_chid_compat_test, UTF_CONSOLE);