All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 00/18] Convert extension support to UCLASS and adds its support to boot flows
@ 2025-10-09 14:50 Kory Maincent (TI.com)
  2025-10-09 14:50 ` [PATCH v2 01/18] MAINTAINERS: Add maintainer for extension board support Kory Maincent (TI.com)
                   ` (17 more replies)
  0 siblings, 18 replies; 36+ messages in thread
From: Kory Maincent (TI.com) @ 2025-10-09 14:50 UTC (permalink / raw)
  To: Tom Rini, Simon Glass, Jagan Teki, Andre Przywara, Hans de Goede,
	Mario Six, Stefano Babic, Fabio Estevam, NXP i.MX U-Boot Team,
	Ying-Chun Liu (PaulLiu)
  Cc: Roger Quadros, Bajjuri Praneeth, Thomas Petazzoni, u-boot,
	Kory Maincent (TI.com)

This series converts the extension board framework to use UCLASS as
requested by Simon Glass, then adds extension support to pxe_utils
and bootmeth_efi (not tested) to enable extension boards devicetree load
in the standard boot process.

I can't test the imx8 extension scan enabled by the
imx8mm-cl-iot-gate_defconfig as I don't have this board.
I also can't test the efi bootmeth change as I don't have such board.

Changes in v2:
- Fixes few build errors.
- Add patches to move the extension support and board scan out of XPL
  images build.

Signed-off-by: Kory Maincent (TI.com) <kory.maincent@bootlin.com>
---
Kory Maincent (TI.com) (18):
      MAINTAINERS: Add maintainer for extension board support
      boot: Move extension board support from cmd/ to boot/
      boot: Add UCLASS support for extension boards
      board: ti: Exclude cape detection from XPL builds
      board: ti: Refactor cape detection code for readability
      board: ti: Convert cape detection to use UCLASS framework
      board: sunxi: Exclude DIP detection from XPL builds
      board: sunxi: Refactor CHIP board extension code
      board: sunxi: Convert extension support to UCLASS framework
      board: sandbox: Improve extension board scan implementation
      board: sandbox: Convert extension support to UCLASS framework
      board: compulab: Exclude compulab extension board detection from XPL builds
      board: compulab: Convert imx8mm-cl-iot-gate to UCLASS extension framework
      boot: Remove legacy extension board support
      boot: extension: Move overlay apply custom logic to command level
      boot: pxe_utils: Add extension board devicetree overlay support
      boot: bootmeth_efi: Refactor distro_efi_try_bootflow_files return logic
      boot: bootmeth_efi: Add extension board devicetree overlay support

 MAINTAINERS                                        |   9 +
 .../imx8mm-cl-iot-gate/imx8mm-cl-iot-gate.c        |  67 ++++----
 board/sandbox/sandbox.c                            |  22 ++-
 board/sunxi/Makefile                               |   2 +-
 board/sunxi/chip.c                                 |  32 ++--
 board/ti/common/Makefile                           |   2 +-
 board/ti/common/cape_detect.c                      |  52 +++---
 boot/Kconfig                                       |   3 +
 boot/Makefile                                      |   1 +
 boot/bootmeth_efi.c                                |  78 +++++++--
 boot/extension-uclass.c                            | 138 ++++++++++++++++
 boot/pxe_utils.c                                   |  90 ++++++++++
 cmd/Kconfig                                        |   3 -
 cmd/extension_board.c                              | 183 ++++++++++-----------
 doc/usage/cmd/extension.rst                        |  24 +--
 include/dm/uclass-id.h                             |   1 +
 include/extension_board.h                          |  71 ++++++--
 17 files changed, 547 insertions(+), 231 deletions(-)
---
base-commit: 8e7f8c1248e8adfb525a2a4ea56ebf7e54ff5d7a
change-id: 20250916-feature_sysboot_extension_board-958dd0072565

Best regards,
-- 
Köry Maincent, Bootlin
Embedded Linux and kernel engineering
https://bootlin.com


^ permalink raw reply	[flat|nested] 36+ messages in thread

* [PATCH v2 01/18] MAINTAINERS: Add maintainer for extension board support
  2025-10-09 14:50 [PATCH v2 00/18] Convert extension support to UCLASS and adds its support to boot flows Kory Maincent (TI.com)
@ 2025-10-09 14:50 ` Kory Maincent (TI.com)
  2025-10-10 11:13   ` Simon Glass
  2025-10-10 14:13   ` Mattijs Korpershoek
  2025-10-09 14:50 ` [PATCH v2 02/18] boot: Move extension board support from cmd/ to boot/ Kory Maincent (TI.com)
                   ` (16 subsequent siblings)
  17 siblings, 2 replies; 36+ messages in thread
From: Kory Maincent (TI.com) @ 2025-10-09 14:50 UTC (permalink / raw)
  To: Tom Rini, Simon Glass, Jagan Teki, Andre Przywara, Hans de Goede,
	Mario Six, Stefano Babic, Fabio Estevam, NXP i.MX U-Boot Team,
	Ying-Chun Liu (PaulLiu)
  Cc: Roger Quadros, Bajjuri Praneeth, Thomas Petazzoni, u-boot,
	Kory Maincent (TI.com)

Add myself as maintainer for the extension board support that was
originally added to track ongoing development and maintenance.

Signed-off-by: Kory Maincent (TI.com) <kory.maincent@bootlin.com>
---
 MAINTAINERS | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 12043a1f82e..e411e266c94 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1182,6 +1182,14 @@ F:	scripts/event_dump.py
 F:	test/common/event.c
 F:	test/py/tests/test_event_dump.py
 
+EXTENSION
+M:	Kory Maincent <kory.maincent@bootlin.com>
+S:	Maintained
+F:	board/sunxi/chip.c
+F:	board/ti/common/cape_detect.c
+F:	cmd/extension_board.c
+F:	include/extension_board.h
+
 FASTBOOT
 M:	Mattijs Korpershoek <mkorpershoek@kernel.org>
 S:	Maintained

-- 
2.43.0


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v2 02/18] boot: Move extension board support from cmd/ to boot/
  2025-10-09 14:50 [PATCH v2 00/18] Convert extension support to UCLASS and adds its support to boot flows Kory Maincent (TI.com)
  2025-10-09 14:50 ` [PATCH v2 01/18] MAINTAINERS: Add maintainer for extension board support Kory Maincent (TI.com)
@ 2025-10-09 14:50 ` Kory Maincent (TI.com)
  2025-10-10 11:13   ` Simon Glass
  2025-10-09 14:50 ` [PATCH v2 03/18] boot: Add UCLASS support for extension boards Kory Maincent (TI.com)
                   ` (15 subsequent siblings)
  17 siblings, 1 reply; 36+ messages in thread
From: Kory Maincent (TI.com) @ 2025-10-09 14:50 UTC (permalink / raw)
  To: Tom Rini, Simon Glass, Jagan Teki, Andre Przywara, Hans de Goede,
	Mario Six, Stefano Babic, Fabio Estevam, NXP i.MX U-Boot Team,
	Ying-Chun Liu (PaulLiu)
  Cc: Roger Quadros, Bajjuri Praneeth, Thomas Petazzoni, u-boot,
	Kory Maincent (TI.com)

Relocate extension board support from cmd/ to boot/ directory in
preparation for converting the extension framework to use UCLASS.
Also improve code style by applying reverse Christmas tree ordering.

Signed-off-by: Kory Maincent (TI.com) <kory.maincent@bootlin.com>
---
 MAINTAINERS               |  1 +
 boot/Kconfig              |  3 ++
 boot/Makefile             |  1 +
 boot/extension.c          | 97 ++++++++++++++++++++++++++++++++++++++++++++++
 cmd/Kconfig               |  3 --
 cmd/extension_board.c     | 99 ++---------------------------------------------
 include/extension_board.h | 16 ++++++++
 7 files changed, 122 insertions(+), 98 deletions(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index e411e266c94..c67d5ae9d6b 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1187,6 +1187,7 @@ M:	Kory Maincent <kory.maincent@bootlin.com>
 S:	Maintained
 F:	board/sunxi/chip.c
 F:	board/ti/common/cape_detect.c
+F:	boot/extension.c
 F:	cmd/extension_board.c
 F:	include/extension_board.h
 
diff --git a/boot/Kconfig b/boot/Kconfig
index dd047365754..62aa301f18f 100644
--- a/boot/Kconfig
+++ b/boot/Kconfig
@@ -1906,6 +1906,9 @@ endmenu
 
 endif # OF_LIBFDT
 
+config SUPPORT_EXTENSION_SCAN
+        bool
+
 config USE_BOOTARGS
 	bool "Enable boot arguments"
 	help
diff --git a/boot/Makefile b/boot/Makefile
index 3da6f7a0914..f60d13130b1 100644
--- a/boot/Makefile
+++ b/boot/Makefile
@@ -9,6 +9,7 @@ obj-$(CONFIG_BOOT_RETRY) += bootretry.o
 obj-$(CONFIG_CMD_BOOTM) += bootm.o bootm_os.o
 obj-$(CONFIG_CMD_BOOTZ) += bootm.o bootm_os.o
 obj-$(CONFIG_CMD_BOOTI) += bootm.o bootm_os.o
+obj-$(CONFIG_SUPPORT_EXTENSION_SCAN) += extension.o
 
 obj-$(CONFIG_PXE_UTILS) += pxe_utils.o
 
diff --git a/boot/extension.c b/boot/extension.c
new file mode 100644
index 00000000000..fc9e1d398f4
--- /dev/null
+++ b/boot/extension.c
@@ -0,0 +1,97 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2025 Köry Maincent <kory.maincent@bootlin.com>
+ */
+
+#include <bootdev.h>
+#include <command.h>
+#include <env.h>
+#include <extension_board.h>
+#include <fdt_support.h>
+#include <malloc.h>
+#include <mapmem.h>
+
+int extension_apply(struct extension *extension)
+{
+	ulong extrasize, overlay_addr;
+	struct fdt_header *blob;
+	char *overlay_cmd;
+
+	if (!working_fdt) {
+		printf("No FDT memory address configured. Please configure\n"
+		       "the FDT address via \"fdt addr <address>\" command.\n");
+		return CMD_RET_FAILURE;
+	}
+
+	overlay_cmd = env_get("extension_overlay_cmd");
+	if (!overlay_cmd) {
+		printf("Environment extension_overlay_cmd is missing\n");
+		return CMD_RET_FAILURE;
+	}
+
+	overlay_addr = env_get_hex("extension_overlay_addr", 0);
+	if (!overlay_addr) {
+		printf("Environment extension_overlay_addr is missing\n");
+		return CMD_RET_FAILURE;
+	}
+
+	env_set("extension_overlay_name", extension->overlay);
+	if (run_command(overlay_cmd, 0) != 0)
+		return CMD_RET_FAILURE;
+
+	extrasize = env_get_hex("filesize", 0);
+	if (!extrasize)
+		return CMD_RET_FAILURE;
+
+	fdt_shrink_to_minimum(working_fdt, extrasize);
+
+	blob = map_sysmem(overlay_addr, 0);
+	if (!fdt_valid(&blob))
+		return CMD_RET_FAILURE;
+
+	/* apply method prints messages on error */
+	if (fdt_overlay_apply_verbose(working_fdt, blob))
+		return CMD_RET_FAILURE;
+
+	return CMD_RET_SUCCESS;
+}
+
+int extension_scan(bool show)
+{
+	struct extension *extension, *next;
+	int extension_num;
+
+	list_for_each_entry_safe(extension, next, &extension_list, list) {
+		list_del(&extension->list);
+		free(extension);
+	}
+	extension_num = extension_board_scan(&extension_list);
+	if (show && extension_num >= 0)
+		printf("Found %d extension board(s).\n", extension_num);
+
+	/* either the number of extensions, or -ve for error */
+	return extension_num;
+}
+
+static int extension_bootdev_hunt(struct bootdev_hunter *info, bool show)
+{
+	int ret;
+
+	ret = env_set_hex("extension_overlay_addr",
+			  env_get_hex("fdtoverlay_addr_r", 0));
+	if (ret)
+		return log_msg_ret("env", ret);
+
+	ret = extension_scan(show);
+	if (ret < 0)
+		return log_msg_ret("ext", ret);
+
+	return 0;
+}
+
+/* extensions should have a uclass - for now we use UCLASS_SIMPLE_BUS uclass */
+BOOTDEV_HUNTER(extension_bootdev_hunter) = {
+	.prio		= BOOTDEVP_1_PRE_SCAN,
+	.uclass		= UCLASS_SIMPLE_BUS,
+	.hunt		= extension_bootdev_hunt,
+};
diff --git a/cmd/Kconfig b/cmd/Kconfig
index 29de857ba7c..986eeeba807 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -545,9 +545,6 @@ config CMD_FDT
 	help
 	  Do FDT related setup before booting into the Operating System.
 
-config SUPPORT_EXTENSION_SCAN
-	bool
-
 config CMD_EXTENSION
 	bool "Extension board management command"
 	select CMD_FDT
diff --git a/cmd/extension_board.c b/cmd/extension_board.c
index 317b260bf36..78d937ee6b6 100644
--- a/cmd/extension_board.c
+++ b/cmd/extension_board.c
@@ -4,68 +4,17 @@
  * Köry Maincent, Bootlin, <kory.maincent@bootlin.com>
  */
 
-#include <bootdev.h>
+#include <exports.h>
 #include <command.h>
-#include <dm.h>
-#include <env.h>
-#include <malloc.h>
 #include <extension_board.h>
-#include <mapmem.h>
-#include <linux/libfdt.h>
-#include <fdt_support.h>
 
-static LIST_HEAD(extension_list);
-
-static int extension_apply(struct extension *extension)
-{
-	char *overlay_cmd;
-	ulong extrasize, overlay_addr;
-	struct fdt_header *blob;
-
-	if (!working_fdt) {
-		printf("No FDT memory address configured. Please configure\n"
-		       "the FDT address via \"fdt addr <address>\" command.\n");
-		return CMD_RET_FAILURE;
-	}
-
-	overlay_cmd = env_get("extension_overlay_cmd");
-	if (!overlay_cmd) {
-		printf("Environment extension_overlay_cmd is missing\n");
-		return CMD_RET_FAILURE;
-	}
-
-	overlay_addr = env_get_hex("extension_overlay_addr", 0);
-	if (!overlay_addr) {
-		printf("Environment extension_overlay_addr is missing\n");
-		return CMD_RET_FAILURE;
-	}
-
-	env_set("extension_overlay_name", extension->overlay);
-	if (run_command(overlay_cmd, 0) != 0)
-		return CMD_RET_FAILURE;
-
-	extrasize = env_get_hex("filesize", 0);
-	if (!extrasize)
-		return CMD_RET_FAILURE;
-
-	fdt_shrink_to_minimum(working_fdt, extrasize);
-
-	blob = map_sysmem(overlay_addr, 0);
-	if (!fdt_valid(&blob))
-		return CMD_RET_FAILURE;
-
-	/* apply method prints messages on error */
-	if (fdt_overlay_apply_verbose(working_fdt, blob))
-		return CMD_RET_FAILURE;
-
-	return CMD_RET_SUCCESS;
-}
+LIST_HEAD(extension_list);
 
 static int do_extension_list(struct cmd_tbl *cmdtp, int flag,
 			     int argc, char *const argv[])
 {
-	int i = 0;
 	struct extension *extension;
+	int i = 0;
 
 	if (list_empty(&extension_list)) {
 		printf("No extension registered - Please run \"extension scan\"\n");
@@ -82,23 +31,6 @@ static int do_extension_list(struct cmd_tbl *cmdtp, int flag,
 	return CMD_RET_SUCCESS;
 }
 
-static int extension_scan(bool show)
-{
-	struct extension *extension, *next;
-	int extension_num;
-
-	list_for_each_entry_safe(extension, next, &extension_list, list) {
-		list_del(&extension->list);
-		free(extension);
-	}
-	extension_num = extension_board_scan(&extension_list);
-	if (show && extension_num >= 0)
-		printf("Found %d extension board(s).\n", extension_num);
-
-	/* either the number of extensions, or -ve for error */
-	return extension_num;
-}
-
 static int do_extension_scan(struct cmd_tbl *cmdtp, int flag,
 			     int argc, char *const argv[])
 {
@@ -115,8 +47,8 @@ static int do_extension_apply(struct cmd_tbl *cmdtp, int flag,
 			      int argc, char *const argv[])
 {
 	struct extension *extension = NULL;
-	struct list_head *entry;
 	int i = 0, extension_id, ret;
+	struct list_head *entry;
 
 	if (argc < 2)
 		return CMD_RET_USAGE;
@@ -177,26 +109,3 @@ U_BOOT_CMD(extension, 3, 1, do_extensionops,
 	"extension list - lists available extension(s) board(s)\n"
 	"extension apply <extension number|all> - applies DT overlays corresponding to extension boards\n"
 );
-
-static int extension_bootdev_hunt(struct bootdev_hunter *info, bool show)
-{
-	int ret;
-
-	ret = env_set_hex("extension_overlay_addr",
-			  env_get_hex("fdtoverlay_addr_r", 0));
-	if (ret)
-		return log_msg_ret("env", ret);
-
-	ret = extension_scan(show);
-	if (ret < 0)
-		return log_msg_ret("ext", ret);
-
-	return 0;
-}
-
-/* extensions should have a uclass - for now we use UCLASS_SIMPLE_BUS uclass */
-BOOTDEV_HUNTER(extension_bootdev_hunter) = {
-	.prio		= BOOTDEVP_1_PRE_SCAN,
-	.uclass		= UCLASS_SIMPLE_BUS,
-	.hunt		= extension_bootdev_hunt,
-};
diff --git a/include/extension_board.h b/include/extension_board.h
index 22e4104bc54..3f70416f005 100644
--- a/include/extension_board.h
+++ b/include/extension_board.h
@@ -9,6 +9,8 @@
 
 #include <linux/list.h>
 
+extern struct list_head extension_list;
+
 struct extension {
 	struct list_head list;
 	char name[32];
@@ -30,4 +32,18 @@ struct extension {
  */
 int extension_board_scan(struct list_head *extension_list);
 
+/**
+ * extension_apply - Apply extension board overlay to the devicetree
+ * @extension: Extension to be applied
+ * Return: Zero on success, negative on failure.
+ */
+int extension_apply(struct extension *extension);
+
+/**
+ * extension_scan - Scan extension boards available.
+ * @show: Flag to enable verbose log
+ * Return: Zero on success, negative on failure.
+ */
+int extension_scan(bool show);
+
 #endif /* __EXTENSION_SUPPORT_H */

-- 
2.43.0


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v2 03/18] boot: Add UCLASS support for extension boards
  2025-10-09 14:50 [PATCH v2 00/18] Convert extension support to UCLASS and adds its support to boot flows Kory Maincent (TI.com)
  2025-10-09 14:50 ` [PATCH v2 01/18] MAINTAINERS: Add maintainer for extension board support Kory Maincent (TI.com)
  2025-10-09 14:50 ` [PATCH v2 02/18] boot: Move extension board support from cmd/ to boot/ Kory Maincent (TI.com)
@ 2025-10-09 14:50 ` Kory Maincent (TI.com)
  2025-10-10 11:13   ` Simon Glass
  2025-10-09 14:50 ` [PATCH v2 04/18] board: ti: Exclude cape detection from XPL builds Kory Maincent (TI.com)
                   ` (14 subsequent siblings)
  17 siblings, 1 reply; 36+ messages in thread
From: Kory Maincent (TI.com) @ 2025-10-09 14:50 UTC (permalink / raw)
  To: Tom Rini, Simon Glass, Jagan Teki, Andre Przywara, Hans de Goede,
	Mario Six, Stefano Babic, Fabio Estevam, NXP i.MX U-Boot Team,
	Ying-Chun Liu (PaulLiu)
  Cc: Roger Quadros, Bajjuri Praneeth, Thomas Petazzoni, u-boot,
	Kory Maincent (TI.com)

Introduce UCLASS-based extension board support to enable more
standardized and automatic loading of extension board device tree
overlays in preparation for integration with bootstd and pxe_utils.

Signed-off-by: Kory Maincent (TI.com) <kory.maincent@bootlin.com>
---
 MAINTAINERS                 |   1 +
 boot/Kconfig                |   3 +
 boot/Makefile               |   1 +
 boot/extension-uclass.c     | 196 ++++++++++++++++++++++++++++++++++++++++++++
 cmd/Kconfig                 |   2 +-
 cmd/extension_board.c       |  50 ++++++++++-
 doc/usage/cmd/extension.rst |  24 +++---
 include/dm/uclass-id.h      |   1 +
 include/extension_board.h   |  64 +++++++++++++++
 9 files changed, 326 insertions(+), 16 deletions(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index c67d5ae9d6b..a63ffa14ef5 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1187,6 +1187,7 @@ M:	Kory Maincent <kory.maincent@bootlin.com>
 S:	Maintained
 F:	board/sunxi/chip.c
 F:	board/ti/common/cape_detect.c
+F:	boot/extension-uclass.c
 F:	boot/extension.c
 F:	cmd/extension_board.c
 F:	include/extension_board.h
diff --git a/boot/Kconfig b/boot/Kconfig
index 62aa301f18f..159da81bec5 100644
--- a/boot/Kconfig
+++ b/boot/Kconfig
@@ -1909,6 +1909,9 @@ endif # OF_LIBFDT
 config SUPPORT_EXTENSION_SCAN
         bool
 
+config SUPPORT_DM_EXTENSION_SCAN
+        bool
+
 config USE_BOOTARGS
 	bool "Enable boot arguments"
 	help
diff --git a/boot/Makefile b/boot/Makefile
index f60d13130b1..aa26070fbb8 100644
--- a/boot/Makefile
+++ b/boot/Makefile
@@ -10,6 +10,7 @@ obj-$(CONFIG_CMD_BOOTM) += bootm.o bootm_os.o
 obj-$(CONFIG_CMD_BOOTZ) += bootm.o bootm_os.o
 obj-$(CONFIG_CMD_BOOTI) += bootm.o bootm_os.o
 obj-$(CONFIG_SUPPORT_EXTENSION_SCAN) += extension.o
+obj-$(CONFIG_SUPPORT_DM_EXTENSION_SCAN) += extension-uclass.o
 
 obj-$(CONFIG_PXE_UTILS) += pxe_utils.o
 
diff --git a/boot/extension-uclass.c b/boot/extension-uclass.c
new file mode 100644
index 00000000000..9dfbeb60d20
--- /dev/null
+++ b/boot/extension-uclass.c
@@ -0,0 +1,196 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2025 Köry Maincent <kory.maincent@bootlin.com>
+ */
+
+#include <alist.h>
+#include <command.h>
+#include <dm/device-internal.h>
+#include <dm/lists.h>
+#include <dm/uclass.h>
+#include <env.h>
+#include <extension_board.h>
+#include <fdt_support.h>
+#include <malloc.h>
+#include <mapmem.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* For now, bind the extension device manually if none are found */
+static struct udevice *extension_get_dev(void)
+{
+	struct driver *drv = ll_entry_start(struct driver, driver);
+	const int n_ents = ll_entry_count(struct driver, driver);
+	struct udevice *dev;
+	int i, ret;
+
+	/* These are not needed before relocation */
+	if (!(gd->flags & GD_FLG_RELOC))
+		return NULL;
+
+	uclass_first_device(UCLASS_EXTENSION, &dev);
+	if (dev)
+		return dev;
+
+	/* Create the extension device if not already bound */
+	for (i = 0; i < n_ents; i++, drv++) {
+		if (drv->id == UCLASS_EXTENSION) {
+			char name[32];
+
+			snprintf(name, sizeof(name), "%s_dev", drv->name);
+			ret = device_bind_driver(gd->dm_root, drv->name,
+						 name, &dev);
+			if (ret) {
+				printf("Bind extension driver %s error=%d\n",
+				       drv->name, ret);
+				return NULL;
+			}
+
+			ret = device_probe(dev);
+			if (ret) {
+				printf("Probe extension driver %s error=%d\n",
+				       drv->name, ret);
+				return NULL;
+			}
+
+			/* We manage only one extension driver for now */
+			return dev;
+		}
+	}
+
+	return NULL;
+}
+
+struct alist *dm_extension_get_list(void)
+{
+	struct udevice *dev = extension_get_dev();
+
+	if (!dev)
+		return NULL;
+
+	return dev_get_priv(dev);
+}
+
+int dm_extension_probe(struct udevice *dev)
+{
+	struct alist *extension_list = dev_get_priv(dev);
+
+	alist_init_struct(extension_list, struct extension);
+	return 0;
+}
+
+int dm_extension_remove(struct udevice *dev)
+{
+	struct alist *extension_list = dev_get_priv(dev);
+
+	alist_uninit(extension_list);
+	return 0;
+}
+
+int dm_extension_scan(void)
+{
+	struct alist *extension_list = dm_extension_get_list();
+	struct udevice *dev = extension_get_dev();
+	const struct extension_ops *ops;
+
+	if (!dev || !extension_list)
+		return -ENODEV;
+
+	ops = device_get_ops(dev);
+	if (!ops->scan)
+		return -ENODEV;
+
+	alist_empty(extension_list);
+	return ops->scan(extension_list);
+}
+
+static int _extension_apply(const struct extension *extension)
+{
+	ulong extrasize, overlay_addr;
+	struct fdt_header *blob;
+	char *overlay_cmd;
+	int ret;
+
+	if (!working_fdt) {
+		printf("No FDT memory address configured. Please configure\n"
+		       "the FDT address via \"fdt addr <address>\" command.\n");
+		return -EINVAL;
+	}
+
+	overlay_cmd = env_get("extension_overlay_cmd");
+	if (!overlay_cmd) {
+		printf("Environment extension_overlay_cmd is missing\n");
+		return -EINVAL;
+	}
+
+	overlay_addr = env_get_hex("extension_overlay_addr", 0);
+	if (!overlay_addr) {
+		printf("Environment extension_overlay_addr is missing\n");
+		return -EINVAL;
+	}
+
+	env_set("extension_overlay_name", extension->overlay);
+	ret = run_command(overlay_cmd, 0);
+	if (ret)
+		return ret;
+
+	extrasize = env_get_hex("filesize", 0);
+	if (!extrasize)
+		return -EINVAL;
+
+	fdt_shrink_to_minimum(working_fdt, extrasize);
+
+	blob = map_sysmem(overlay_addr, 0);
+	if (!fdt_valid(&blob)) {
+		printf("Invalid overlay devicetree %s\n", extension->overlay);
+		return -EINVAL;
+	}
+
+	/* Apply method prints messages on error */
+	ret = fdt_overlay_apply_verbose(working_fdt, blob);
+	if (ret)
+		printf("Failed to apply overlay %s\n", extension->overlay);
+
+	return ret;
+}
+
+int dm_extension_apply(int extension_num)
+{
+	struct alist *extension_list = dm_extension_get_list();
+	const struct extension *extension;
+
+	if (!extension_list)
+		return -ENODEV;
+
+	extension = alist_get(extension_list, extension_num,
+			      struct extension);
+	if (!extension) {
+		printf("Wrong extension number\n");
+		return -ENODEV;
+	}
+
+	return _extension_apply(extension);
+}
+
+int dm_extension_apply_all(void)
+{
+	struct alist *extension_list = dm_extension_get_list();
+	const struct extension *extension;
+	int ret;
+
+	if (!extension_list)
+		return -ENODEV;
+
+	alist_for_each(extension, extension_list) {
+		ret = _extension_apply(extension);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+UCLASS_DRIVER(extension) = {
+	.name	= "extension",
+	.id	= UCLASS_EXTENSION,
+};
diff --git a/cmd/Kconfig b/cmd/Kconfig
index 986eeeba807..721bdb87c8a 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -548,7 +548,7 @@ config CMD_FDT
 config CMD_EXTENSION
 	bool "Extension board management command"
 	select CMD_FDT
-	depends on SUPPORT_EXTENSION_SCAN
+	depends on SUPPORT_EXTENSION_SCAN || SUPPORT_DM_EXTENSION_SCAN
 	help
 	  Enables the "extension" command, which allows to detect
 	  extension boards connected to the system, and apply
diff --git a/cmd/extension_board.c b/cmd/extension_board.c
index 78d937ee6b6..d70394f36c7 100644
--- a/cmd/extension_board.c
+++ b/cmd/extension_board.c
@@ -4,6 +4,7 @@
  * Köry Maincent, Bootlin, <kory.maincent@bootlin.com>
  */
 
+#include <alist.h>
 #include <exports.h>
 #include <command.h>
 #include <extension_board.h>
@@ -13,9 +14,28 @@ LIST_HEAD(extension_list);
 static int do_extension_list(struct cmd_tbl *cmdtp, int flag,
 			     int argc, char *const argv[])
 {
+#if CONFIG_IS_ENABLED(SUPPORT_DM_EXTENSION_SCAN)
+	struct alist *dm_extension_list;
+#endif
 	struct extension *extension;
 	int i = 0;
 
+#if CONFIG_IS_ENABLED(SUPPORT_DM_EXTENSION_SCAN)
+	dm_extension_list = dm_extension_get_list();
+
+	if (!alist_get_ptr(dm_extension_list, 0)) {
+		printf("No extension registered - Please run \"extension scan\"\n");
+		return CMD_RET_SUCCESS;
+	}
+
+	alist_for_each(extension, dm_extension_list) {
+		printf("Extension %d: %s\n", i++, extension->name);
+		printf("\tManufacturer: \t\t%s\n", extension->owner);
+		printf("\tVersion: \t\t%s\n", extension->version);
+		printf("\tDevicetree overlay: \t%s\n", extension->overlay);
+		printf("\tOther information: \t%s\n", extension->other);
+	}
+#else
 	if (list_empty(&extension_list)) {
 		printf("No extension registered - Please run \"extension scan\"\n");
 		return CMD_RET_SUCCESS;
@@ -28,6 +48,7 @@ static int do_extension_list(struct cmd_tbl *cmdtp, int flag,
 		printf("\tDevicetree overlay: \t%s\n", extension->overlay);
 		printf("\tOther information: \t%s\n", extension->other);
 	}
+#endif
 	return CMD_RET_SUCCESS;
 }
 
@@ -36,9 +57,19 @@ static int do_extension_scan(struct cmd_tbl *cmdtp, int flag,
 {
 	int extension_num;
 
+#if CONFIG_IS_ENABLED(SUPPORT_DM_EXTENSION_SCAN)
+	extension_num = dm_extension_scan();
+	if (extension_num == -ENODEV)
+		extension_num = 0;
+	else if (extension_num < 0)
+		return CMD_RET_FAILURE;
+
+	printf("Found %d extension board(s).\n", extension_num);
+#else
 	extension_num = extension_scan(true);
-	if (extension_num < 0)
+	if (extension_num < 0 && extension_num != -ENODEV)
 		return CMD_RET_FAILURE;
+#endif
 
 	return CMD_RET_SUCCESS;
 }
@@ -46,22 +77,34 @@ static int do_extension_scan(struct cmd_tbl *cmdtp, int flag,
 static int do_extension_apply(struct cmd_tbl *cmdtp, int flag,
 			      int argc, char *const argv[])
 {
+#if !CONFIG_IS_ENABLED(SUPPORT_DM_EXTENSION_SCAN)
 	struct extension *extension = NULL;
-	int i = 0, extension_id, ret;
 	struct list_head *entry;
+	int i = 0;
+#endif
+	int extension_id, ret;
 
 	if (argc < 2)
 		return CMD_RET_USAGE;
 
 	if (strcmp(argv[1], "all") == 0) {
 		ret = CMD_RET_FAILURE;
+#if CONFIG_IS_ENABLED(SUPPORT_DM_EXTENSION_SCAN)
+		if (dm_extension_apply_all())
+			return CMD_RET_FAILURE;
+#else
 		list_for_each_entry(extension, &extension_list, list) {
 			ret = extension_apply(extension);
 			if (ret != CMD_RET_SUCCESS)
 				break;
 		}
+#endif
 	} else {
 		extension_id = simple_strtol(argv[1], NULL, 10);
+#if CONFIG_IS_ENABLED(SUPPORT_DM_EXTENSION_SCAN)
+		if (dm_extension_apply(extension_id))
+			return CMD_RET_FAILURE;
+#else
 		list_for_each(entry, &extension_list) {
 			if (i == extension_id) {
 				extension = list_entry(entry, struct extension,  list);
@@ -76,9 +119,10 @@ static int do_extension_apply(struct cmd_tbl *cmdtp, int flag,
 		}
 
 		ret = extension_apply(extension);
+#endif
 	}
 
-	return ret;
+	return CMD_RET_SUCCESS;
 }
 
 static struct cmd_tbl cmd_extension[] = {
diff --git a/doc/usage/cmd/extension.rst b/doc/usage/cmd/extension.rst
index 4c261e74951..d82c3fbef0a 100644
--- a/doc/usage/cmd/extension.rst
+++ b/doc/usage/cmd/extension.rst
@@ -25,9 +25,8 @@ Device Tree overlays depending on the detected extension boards.
 
 The "extension" command comes with three sub-commands:
 
- - "extension scan" makes the generic code call the board-specific
-   extension_board_scan() function to retrieve the list of detected
-   extension boards.
+ - "extension scan" makes the generic code call a board-specific extension
+   function to retrieve the list of detected extension boards.
 
  - "extension list" allows to list the detected extension boards.
 
@@ -98,17 +97,18 @@ Simple extension_board_scan function example
 
 .. code-block:: c
 
-    int extension_board_scan(struct list_head *extension_list)
+    static int foo_extension_board_scan(struct alist *extension_list)
     {
-        struct extension *extension;
+        struct extension extension = {0};
 
-        extension = calloc(1, sizeof(struct extension));
-        snprintf(extension->overlay, sizeof(extension->overlay), "overlay.dtbo");
-        snprintf(extension->name, sizeof(extension->name), "extension board");
-        snprintf(extension->owner, sizeof(extension->owner), "sandbox");
-        snprintf(extension->version, sizeof(extension->version), "1.1");
-        snprintf(extension->other, sizeof(extension->other), "Extension board information");
-        list_add_tail(&extension->list, extension_list);
+        snprintf(extension.overlay, sizeof(extension.overlay), "overlay.dtbo");
+        snprintf(extension.name, sizeof(extension.name), "extension board");
+        snprintf(extension.owner, sizeof(extension.owner), "sandbox");
+        snprintf(extension.version, sizeof(extension.version), "1.1");
+        snprintf(extension.other, sizeof(extension.other), "Extension board information");
+        alist_add(extension_list, extension);
 
         return 1;
     }
+
+    U_BOOT_EXTENSION(foo_extension_name, foo_extension_board_scan);
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index 6be59093160..eb6416b5917 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -63,6 +63,7 @@ enum uclass_id {
 	UCLASS_ETH,		/* Ethernet device */
 	UCLASS_ETH_PHY,		/* Ethernet PHY device */
 	UCLASS_EXTCON,		/* External Connector Class */
+	UCLASS_EXTENSION,	/* Extension board */
 	UCLASS_FFA,		/* Arm Firmware Framework for Armv8-A */
 	UCLASS_FFA_EMUL,		/* sandbox FF-A device emulator */
 	UCLASS_FIRMWARE,	/* Firmware */
diff --git a/include/extension_board.h b/include/extension_board.h
index 3f70416f005..78139cd7489 100644
--- a/include/extension_board.h
+++ b/include/extension_board.h
@@ -8,9 +8,51 @@
 #define __EXTENSION_SUPPORT_H
 
 #include <linux/list.h>
+#include <alist.h>
+#include <dm/device.h>
 
 extern struct list_head extension_list;
 
+/**
+ * dm_extension_get_list - Get the extension list
+ * Return: The extension alist pointer, or NULL if no such list exists.
+ */
+struct alist *dm_extension_get_list(void);
+
+/**
+ * dm_extension_probe - Probe extension device
+ * @dev: Extension device that needs to be probed
+ * Return: Zero on success, negative on failure.
+ */
+int dm_extension_probe(struct udevice *dev);
+
+/**
+ * dm_extension_remove - Remove extension device
+ * @dev: Extension device that needs to be removed
+ * Return: Zero on success, negative on failure.
+ */
+int dm_extension_remove(struct udevice *dev);
+
+/**
+ * dm_extension_scan - Scan extension boards available.
+ * Return: Zero on success, negative on failure.
+ */
+int dm_extension_scan(void);
+
+/**
+ * dm_extension_apply - Apply extension board overlay to the devicetree
+ * @extension_num: Extension number to be applied
+ * Return: Zero on success, negative on failure.
+ */
+int dm_extension_apply(int extension_num);
+
+/**
+ * dm_extension_apply_all - Apply all extension board overlays to the
+ *			    devicetree
+ * Return: Zero on success, negative on failure.
+ */
+int dm_extension_apply_all(void);
+
 struct extension {
 	struct list_head list;
 	char name[32];
@@ -20,6 +62,28 @@ struct extension {
 	char other[32];
 };
 
+struct extension_ops {
+	/**
+	 * scan - Add system-specific function to scan extension boards.
+	 * @dev: extension device to use
+	 * Return: The number of extension or a negative value in case of
+	 *	   error.
+	 */
+	int (*scan)(struct alist *extension_list);
+};
+
+#define U_BOOT_EXTENSION(_name, _scan_func) \
+	U_BOOT_DRIVER(_name) = { \
+		.name = #_name, \
+		.id = UCLASS_EXTENSION, \
+		.probe = dm_extension_probe, \
+		.remove = dm_extension_remove, \
+		.ops = &(struct extension_ops) { \
+		       .scan = _scan_func, \
+		       }, \
+		.priv_auto = sizeof(struct alist), \
+	}
+
 /**
  * extension_board_scan - Add system-specific function to scan extension board.
  * @param extension_list	List of extension board information to update.

-- 
2.43.0


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v2 04/18] board: ti: Exclude cape detection from XPL builds
  2025-10-09 14:50 [PATCH v2 00/18] Convert extension support to UCLASS and adds its support to boot flows Kory Maincent (TI.com)
                   ` (2 preceding siblings ...)
  2025-10-09 14:50 ` [PATCH v2 03/18] boot: Add UCLASS support for extension boards Kory Maincent (TI.com)
@ 2025-10-09 14:50 ` Kory Maincent (TI.com)
  2025-10-09 14:50 ` [PATCH v2 05/18] board: ti: Refactor cape detection code for readability Kory Maincent (TI.com)
                   ` (13 subsequent siblings)
  17 siblings, 0 replies; 36+ messages in thread
From: Kory Maincent (TI.com) @ 2025-10-09 14:50 UTC (permalink / raw)
  To: Tom Rini, Simon Glass, Jagan Teki, Andre Przywara, Hans de Goede,
	Mario Six, Stefano Babic, Fabio Estevam, NXP i.MX U-Boot Team,
	Ying-Chun Liu (PaulLiu)
  Cc: Roger Quadros, Bajjuri Praneeth, Thomas Petazzoni, u-boot,
	Kory Maincent (TI.com)

Disable cape detection functionality in XPL (eXtended Program Loader)
images to reduce size and complexity in the early boot stage.

Signed-off-by: Kory Maincent (TI.com) <kory.maincent@bootlin.com>
---

Changes in v2:
- Use PHASE macro instead of XPL check.
- Check SUPPORT_EXTENSION_SCAN instead of CONFIG_CMD_EXTENSION
---
 board/ti/common/Makefile | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/board/ti/common/Makefile b/board/ti/common/Makefile
index caf6b9fa8c1..f58935b4103 100644
--- a/board/ti/common/Makefile
+++ b/board/ti/common/Makefile
@@ -2,6 +2,6 @@
 # Copyright (C) 2015-2016 Texas Instruments Incorporated - https://www.ti.com/
 
 obj-${CONFIG_TI_I2C_BOARD_DETECT} += board_detect.o
-obj-${CONFIG_CMD_EXTENSION} += cape_detect.o
+obj-${CONFIG_$(PHASE_)SUPPORT_EXTENSION_SCAN} += cape_detect.o
 obj-${CONFIG_OF_LIBFDT} += fdt_ops.o
 obj-${CONFIG_ARCH_K3} += k3-ddr.o

-- 
2.43.0


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v2 05/18] board: ti: Refactor cape detection code for readability
  2025-10-09 14:50 [PATCH v2 00/18] Convert extension support to UCLASS and adds its support to boot flows Kory Maincent (TI.com)
                   ` (3 preceding siblings ...)
  2025-10-09 14:50 ` [PATCH v2 04/18] board: ti: Exclude cape detection from XPL builds Kory Maincent (TI.com)
@ 2025-10-09 14:50 ` Kory Maincent (TI.com)
  2025-10-09 14:50 ` [PATCH v2 06/18] board: ti: Convert cape detection to use UCLASS framework Kory Maincent (TI.com)
                   ` (12 subsequent siblings)
  17 siblings, 0 replies; 36+ messages in thread
From: Kory Maincent (TI.com) @ 2025-10-09 14:50 UTC (permalink / raw)
  To: Tom Rini, Simon Glass, Jagan Teki, Andre Przywara, Hans de Goede,
	Mario Six, Stefano Babic, Fabio Estevam, NXP i.MX U-Boot Team,
	Ying-Chun Liu (PaulLiu)
  Cc: Roger Quadros, Bajjuri Praneeth, Thomas Petazzoni, u-boot,
	Kory Maincent (TI.com)

Clean up and reorganize cape detection code structure for improved
maintainability and readability.

Signed-off-by: Kory Maincent (TI.com) <kory.maincent@bootlin.com>
---
 board/ti/common/cape_detect.c | 36 +++++++++++++++++++-----------------
 1 file changed, 19 insertions(+), 17 deletions(-)

diff --git a/board/ti/common/cape_detect.c b/board/ti/common/cape_detect.c
index da805befabc..7786bdda5d1 100644
--- a/board/ti/common/cape_detect.c
+++ b/board/ti/common/cape_detect.c
@@ -24,19 +24,18 @@ static void sanitize_field(char *text, size_t size)
 
 int extension_board_scan(struct list_head *extension_list)
 {
-	struct extension *cape;
-	struct am335x_cape_eeprom_id eeprom_header;
-
-	int num_capes = 0;
-	int ret, i;
-	struct udevice *dev;
 	unsigned char addr;
-
-	char process_cape_part_number[17] = {'0'};
-	char process_cape_version[5] = {'0'};
-	uint8_t cursor = 0;
+	int num_capes = 0;
 
 	for (addr = CAPE_EEPROM_FIRST_ADDR; addr <= CAPE_EEPROM_LAST_ADDR; addr++) {
+		struct am335x_cape_eeprom_id eeprom_header;
+		char process_cape_part_number[17] = {'0'};
+		char process_cape_version[5] = {'0'};
+		struct extension *cape;
+		struct udevice *dev;
+		u8 cursor = 0;
+		int ret, i;
+
 		ret = i2c_get_chip_for_busnum(CONFIG_CAPE_EEPROM_BUS_NUM, addr, 1, &dev);
 		if (ret)
 			continue;
@@ -59,8 +58,8 @@ int extension_board_scan(struct list_head *extension_list)
 		sanitize_field(eeprom_header.part_number, sizeof(eeprom_header.part_number));
 
 		/* Process cape part_number */
-		memset(process_cape_part_number, 0, sizeof(process_cape_part_number));
-		strncpy(process_cape_part_number, eeprom_header.part_number, 16);
+		strlcpy(process_cape_part_number, eeprom_header.part_number,
+			sizeof(process_cape_part_number));
 		/* Some capes end with '.' */
 		for (i = 15; i >= 0; i--) {
 			if (process_cape_part_number[i] == '.')
@@ -70,8 +69,8 @@ int extension_board_scan(struct list_head *extension_list)
 		}
 
 		/* Process cape version */
-		memset(process_cape_version, 0, sizeof(process_cape_version));
-		strncpy(process_cape_version, eeprom_header.version, 4);
+		strlcpy(process_cape_version, eeprom_header.version,
+			sizeof(process_cape_version));
 		for (i = 0; i < 4; i++) {
 			if (process_cape_version[i] == 0)
 				process_cape_version[i] = '0';
@@ -87,9 +86,12 @@ int extension_board_scan(struct list_head *extension_list)
 
 		snprintf(cape->overlay, sizeof(cape->overlay), "%s-%s.dtbo",
 			 process_cape_part_number, process_cape_version);
-		strncpy(cape->name, eeprom_header.board_name, 32);
-		strncpy(cape->version, process_cape_version, 4);
-		strncpy(cape->owner, eeprom_header.manufacturer, 16);
+		strlcpy(cape->name, eeprom_header.board_name,
+			sizeof(eeprom_header.board_name));
+		strlcpy(cape->version, process_cape_version,
+			sizeof(process_cape_version));
+		strlcpy(cape->owner, eeprom_header.manufacturer,
+			sizeof(eeprom_header.manufacturer) + 1);
 		list_add_tail(&cape->list, extension_list);
 		num_capes++;
 	}

-- 
2.43.0


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v2 06/18] board: ti: Convert cape detection to use UCLASS framework
  2025-10-09 14:50 [PATCH v2 00/18] Convert extension support to UCLASS and adds its support to boot flows Kory Maincent (TI.com)
                   ` (4 preceding siblings ...)
  2025-10-09 14:50 ` [PATCH v2 05/18] board: ti: Refactor cape detection code for readability Kory Maincent (TI.com)
@ 2025-10-09 14:50 ` Kory Maincent (TI.com)
  2025-10-09 14:50 ` [PATCH v2 07/18] board: sunxi: Exclude DIP detection from XPL builds Kory Maincent (TI.com)
                   ` (11 subsequent siblings)
  17 siblings, 0 replies; 36+ messages in thread
From: Kory Maincent (TI.com) @ 2025-10-09 14:50 UTC (permalink / raw)
  To: Tom Rini, Simon Glass, Jagan Teki, Andre Przywara, Hans de Goede,
	Mario Six, Stefano Babic, Fabio Estevam, NXP i.MX U-Boot Team,
	Ying-Chun Liu (PaulLiu)
  Cc: Roger Quadros, Bajjuri Praneeth, Thomas Petazzoni, u-boot,
	Kory Maincent (TI.com)

Migrate TI board cape detection from legacy extension support to the
new UCLASS-based extension board framework.

Signed-off-by: Kory Maincent (TI.com) <kory.maincent@bootlin.com>
---
 arch/arm/mach-omap2/am33xx/Kconfig |  2 +-
 arch/arm/mach-omap2/omap5/Kconfig  |  2 +-
 board/ti/common/Makefile           |  2 +-
 board/ti/common/cape_detect.c      | 24 +++++++++++-------------
 4 files changed, 14 insertions(+), 16 deletions(-)

diff --git a/arch/arm/mach-omap2/am33xx/Kconfig b/arch/arm/mach-omap2/am33xx/Kconfig
index dff4f1cf202..77f7938305b 100644
--- a/arch/arm/mach-omap2/am33xx/Kconfig
+++ b/arch/arm/mach-omap2/am33xx/Kconfig
@@ -15,7 +15,7 @@ config TARGET_AM335X_EVM
 	select DM_GPIO
 	select DM_SERIAL
 	select TI_I2C_BOARD_DETECT
-	select SUPPORT_EXTENSION_SCAN
+	select SUPPORT_DM_EXTENSION_SCAN
 	imply CMD_DM
 	imply SPL_DM
 	imply SPL_DM_SEQ_ALIAS
diff --git a/arch/arm/mach-omap2/omap5/Kconfig b/arch/arm/mach-omap2/omap5/Kconfig
index 5394529658b..819490a8cf8 100644
--- a/arch/arm/mach-omap2/omap5/Kconfig
+++ b/arch/arm/mach-omap2/omap5/Kconfig
@@ -38,7 +38,7 @@ config TARGET_AM57XX_EVM
 	select CMD_DDR3
 	select DRA7XX
 	select TI_I2C_BOARD_DETECT
-	select SUPPORT_EXTENSION_SCAN
+	select SUPPORT_DM_EXTENSION_SCAN
 	imply DM_THERMAL
 	imply SCSI
 	imply SPL_THERMAL
diff --git a/board/ti/common/Makefile b/board/ti/common/Makefile
index f58935b4103..b42273d3a5a 100644
--- a/board/ti/common/Makefile
+++ b/board/ti/common/Makefile
@@ -2,6 +2,6 @@
 # Copyright (C) 2015-2016 Texas Instruments Incorporated - https://www.ti.com/
 
 obj-${CONFIG_TI_I2C_BOARD_DETECT} += board_detect.o
-obj-${CONFIG_$(PHASE_)SUPPORT_EXTENSION_SCAN} += cape_detect.o
+obj-${CONFIG_$(PHASE_)SUPPORT_DM_EXTENSION_SCAN} += cape_detect.o
 obj-${CONFIG_OF_LIBFDT} += fdt_ops.o
 obj-${CONFIG_ARCH_K3} += k3-ddr.o
diff --git a/board/ti/common/cape_detect.c b/board/ti/common/cape_detect.c
index 7786bdda5d1..23c93964dc3 100644
--- a/board/ti/common/cape_detect.c
+++ b/board/ti/common/cape_detect.c
@@ -22,7 +22,7 @@ static void sanitize_field(char *text, size_t size)
 	}
 }
 
-int extension_board_scan(struct list_head *extension_list)
+static int ti_extension_board_scan(struct alist *extension_list)
 {
 	unsigned char addr;
 	int num_capes = 0;
@@ -31,7 +31,7 @@ int extension_board_scan(struct list_head *extension_list)
 		struct am335x_cape_eeprom_id eeprom_header;
 		char process_cape_part_number[17] = {'0'};
 		char process_cape_version[5] = {'0'};
-		struct extension *cape;
+		struct extension cape = {0}, *_cape;
 		struct udevice *dev;
 		u8 cursor = 0;
 		int ret, i;
@@ -78,22 +78,20 @@ int extension_board_scan(struct list_head *extension_list)
 
 		printf("BeagleBone Cape: %s (0x%x)\n", eeprom_header.board_name, addr);
 
-		cape = calloc(1, sizeof(struct extension));
-		if (!cape) {
-			printf("Error in memory allocation\n");
-			return num_capes;
-		}
-
-		snprintf(cape->overlay, sizeof(cape->overlay), "%s-%s.dtbo",
+		snprintf(cape.overlay, sizeof(cape.overlay), "%s-%s.dtbo",
 			 process_cape_part_number, process_cape_version);
-		strlcpy(cape->name, eeprom_header.board_name,
+		strlcpy(cape.name, eeprom_header.board_name,
 			sizeof(eeprom_header.board_name));
-		strlcpy(cape->version, process_cape_version,
+		strlcpy(cape.version, process_cape_version,
 			sizeof(process_cape_version));
-		strlcpy(cape->owner, eeprom_header.manufacturer,
+		strlcpy(cape.owner, eeprom_header.manufacturer,
 			sizeof(eeprom_header.manufacturer) + 1);
-		list_add_tail(&cape->list, extension_list);
+		_cape = alist_add(extension_list, cape);
+		if (!_cape)
+			return -ENOMEM;
 		num_capes++;
 	}
 	return num_capes;
 }
+
+U_BOOT_EXTENSION(cape, ti_extension_board_scan);

-- 
2.43.0


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v2 07/18] board: sunxi: Exclude DIP detection from XPL builds
  2025-10-09 14:50 [PATCH v2 00/18] Convert extension support to UCLASS and adds its support to boot flows Kory Maincent (TI.com)
                   ` (5 preceding siblings ...)
  2025-10-09 14:50 ` [PATCH v2 06/18] board: ti: Convert cape detection to use UCLASS framework Kory Maincent (TI.com)
@ 2025-10-09 14:50 ` Kory Maincent (TI.com)
  2025-10-09 14:50 ` [PATCH v2 08/18] board: sunxi: Refactor CHIP board extension code Kory Maincent (TI.com)
                   ` (10 subsequent siblings)
  17 siblings, 0 replies; 36+ messages in thread
From: Kory Maincent (TI.com) @ 2025-10-09 14:50 UTC (permalink / raw)
  To: Tom Rini, Simon Glass, Jagan Teki, Andre Przywara, Hans de Goede,
	Mario Six, Stefano Babic, Fabio Estevam, NXP i.MX U-Boot Team,
	Ying-Chun Liu (PaulLiu)
  Cc: Roger Quadros, Bajjuri Praneeth, Thomas Petazzoni, u-boot,
	Kory Maincent (TI.com)

Disable DIP detection functionality in XPL (eXtended Program Loader)
images to reduce size and complexity in the early boot stage.

Signed-off-by: Kory Maincent (TI.com) <kory.maincent@bootlin.com>
---

Change in v2:
- New patch.
---
 board/sunxi/Makefile | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/board/sunxi/Makefile b/board/sunxi/Makefile
index d96b7897b6c..ee82493117a 100644
--- a/board/sunxi/Makefile
+++ b/board/sunxi/Makefile
@@ -11,4 +11,4 @@ obj-$(CONFIG_SUN7I_GMAC)	+= gmac.o
 obj-$(CONFIG_MACH_SUN4I)	+= dram_sun4i_auto.o
 obj-$(CONFIG_MACH_SUN5I)	+= dram_sun5i_auto.o
 obj-$(CONFIG_MACH_SUN7I)	+= dram_sun5i_auto.o
-obj-$(CONFIG_CHIP_DIP_SCAN)	+= chip.o
+obj-$(CONFIG_$(PHASE_)CHIP_DIP_SCAN)	+= chip.o

-- 
2.43.0


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v2 08/18] board: sunxi: Refactor CHIP board extension code
  2025-10-09 14:50 [PATCH v2 00/18] Convert extension support to UCLASS and adds its support to boot flows Kory Maincent (TI.com)
                   ` (6 preceding siblings ...)
  2025-10-09 14:50 ` [PATCH v2 07/18] board: sunxi: Exclude DIP detection from XPL builds Kory Maincent (TI.com)
@ 2025-10-09 14:50 ` Kory Maincent (TI.com)
  2025-10-09 14:50 ` [PATCH v2 09/18] board: sunxi: Convert extension support to UCLASS framework Kory Maincent (TI.com)
                   ` (9 subsequent siblings)
  17 siblings, 0 replies; 36+ messages in thread
From: Kory Maincent (TI.com) @ 2025-10-09 14:50 UTC (permalink / raw)
  To: Tom Rini, Simon Glass, Jagan Teki, Andre Przywara, Hans de Goede,
	Mario Six, Stefano Babic, Fabio Estevam, NXP i.MX U-Boot Team,
	Ying-Chun Liu (PaulLiu)
  Cc: Roger Quadros, Bajjuri Praneeth, Thomas Petazzoni, u-boot,
	Kory Maincent (TI.com)

Clean up and improve code structure in the sunxi CHIP board extension
detection implementation.

Signed-off-by: Kory Maincent (TI.com) <kory.maincent@bootlin.com>
---

Changes in v2:
- Fix a build error.
---
 board/sunxi/chip.c | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/board/sunxi/chip.c b/board/sunxi/chip.c
index 270af2506d2..5e5ec0d1d89 100644
--- a/board/sunxi/chip.c
+++ b/board/sunxi/chip.c
@@ -42,14 +42,9 @@ struct dip_w1_header {
 
 int extension_board_scan(struct list_head *extension_list)
 {
-	struct extension *dip;
-	struct dip_w1_header w1_header;
 	struct udevice *bus, *dev;
-	u32 vid;
-	u16 pid;
-	int ret;
-
 	int num_dip = 0;
+	int ret;
 
 	sunxi_gpio_set_pull(SUNXI_GPD(2), SUNXI_GPIO_PULL_UP);
 
@@ -60,6 +55,11 @@ int extension_board_scan(struct list_head *extension_list)
 	}
 
 	for_each_w1_device(bus, &dev) {
+		struct dip_w1_header w1_header;
+		struct extension *dip;
+		u32 vid;
+		u16 pid;
+
 		if (w1_get_device_family(dev) != W1_FAMILY_DS2431)
 			continue;
 
@@ -90,8 +90,8 @@ int extension_board_scan(struct list_head *extension_list)
 
 		snprintf(dip->overlay, sizeof(dip->overlay), "dip-%x-%x.dtbo",
 			 vid, pid);
-		strncpy(dip->name, w1_header.product_name, 32);
-		strncpy(dip->owner, w1_header.vendor_name, 32);
+		strlcpy(dip->name, w1_header.product_name, sizeof(dip->name));
+		strlcpy(dip->owner, w1_header.vendor_name, sizeof(dip->owner));
 		list_add_tail(&dip->list, extension_list);
 		num_dip++;
 	}

-- 
2.43.0


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v2 09/18] board: sunxi: Convert extension support to UCLASS framework
  2025-10-09 14:50 [PATCH v2 00/18] Convert extension support to UCLASS and adds its support to boot flows Kory Maincent (TI.com)
                   ` (7 preceding siblings ...)
  2025-10-09 14:50 ` [PATCH v2 08/18] board: sunxi: Refactor CHIP board extension code Kory Maincent (TI.com)
@ 2025-10-09 14:50 ` Kory Maincent (TI.com)
  2025-10-09 14:50 ` [PATCH v2 10/18] board: sandbox: Improve extension board scan implementation Kory Maincent (TI.com)
                   ` (8 subsequent siblings)
  17 siblings, 0 replies; 36+ messages in thread
From: Kory Maincent (TI.com) @ 2025-10-09 14:50 UTC (permalink / raw)
  To: Tom Rini, Simon Glass, Jagan Teki, Andre Przywara, Hans de Goede,
	Mario Six, Stefano Babic, Fabio Estevam, NXP i.MX U-Boot Team,
	Ying-Chun Liu (PaulLiu)
  Cc: Roger Quadros, Bajjuri Praneeth, Thomas Petazzoni, u-boot,
	Kory Maincent (TI.com)

Migrate sunxi board extension detection from legacy implementation to
the new UCLASS-based extension board framework.

Signed-off-by: Kory Maincent (TI.com) <kory.maincent@bootlin.com>
---

Changes in v2:
- Fix build error.
---
 arch/arm/mach-sunxi/Kconfig |  2 +-
 board/sunxi/chip.c          | 22 ++++++++++------------
 2 files changed, 11 insertions(+), 13 deletions(-)

diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
index b04ec671696..f5696199516 100644
--- a/arch/arm/mach-sunxi/Kconfig
+++ b/arch/arm/mach-sunxi/Kconfig
@@ -1223,7 +1223,7 @@ config BLUETOOTH_DT_DEVICE_FIXUP
 
 config CHIP_DIP_SCAN
 	bool "Enable DIPs detection for CHIP board"
-	select SUPPORT_EXTENSION_SCAN
+	select SUPPORT_DM_EXTENSION_SCAN
 	select W1
 	select W1_GPIO
 	select W1_EEPROM
diff --git a/board/sunxi/chip.c b/board/sunxi/chip.c
index 5e5ec0d1d89..96a1c581c73 100644
--- a/board/sunxi/chip.c
+++ b/board/sunxi/chip.c
@@ -40,7 +40,7 @@ struct dip_w1_header {
 	u8      data[16];               /* user data, per-dip specific */
 } __packed;
 
-int extension_board_scan(struct list_head *extension_list)
+static int sunxi_extension_board_scan(struct alist *extension_list)
 {
 	struct udevice *bus, *dev;
 	int num_dip = 0;
@@ -55,8 +55,8 @@ int extension_board_scan(struct list_head *extension_list)
 	}
 
 	for_each_w1_device(bus, &dev) {
+		struct extension dip = {0}, *_dip;
 		struct dip_w1_header w1_header;
-		struct extension *dip;
 		u32 vid;
 		u16 pid;
 
@@ -82,18 +82,16 @@ int extension_board_scan(struct list_head *extension_list)
 		       w1_header.product_name, pid,
 		       w1_header.vendor_name, vid);
 
-		dip = calloc(1, sizeof(struct extension));
-		if (!dip) {
-			printf("Error in memory allocation\n");
-			return num_dip;
-		}
-
-		snprintf(dip->overlay, sizeof(dip->overlay), "dip-%x-%x.dtbo",
+		snprintf(dip.overlay, sizeof(dip.overlay), "dip-%x-%x.dtbo",
 			 vid, pid);
-		strlcpy(dip->name, w1_header.product_name, sizeof(dip->name));
-		strlcpy(dip->owner, w1_header.vendor_name, sizeof(dip->owner));
-		list_add_tail(&dip->list, extension_list);
+		strlcpy(dip.name, w1_header.product_name, sizeof(dip.name));
+		strlcpy(dip.owner, w1_header.vendor_name, sizeof(dip.owner));
+		_dip = alist_add(extension_list, dip);
+		if (!_dip)
+			return -ENOMEM;
 		num_dip++;
 	}
 	return num_dip;
 }
+
+U_BOOT_EXTENSION(dip, sunxi_extension_board_scan);

-- 
2.43.0


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v2 10/18] board: sandbox: Improve extension board scan implementation
  2025-10-09 14:50 [PATCH v2 00/18] Convert extension support to UCLASS and adds its support to boot flows Kory Maincent (TI.com)
                   ` (8 preceding siblings ...)
  2025-10-09 14:50 ` [PATCH v2 09/18] board: sunxi: Convert extension support to UCLASS framework Kory Maincent (TI.com)
@ 2025-10-09 14:50 ` Kory Maincent (TI.com)
  2025-10-10 11:13   ` Simon Glass
  2025-10-09 14:50 ` [PATCH v2 11/18] board: sandbox: Convert extension support to UCLASS framework Kory Maincent (TI.com)
                   ` (7 subsequent siblings)
  17 siblings, 1 reply; 36+ messages in thread
From: Kory Maincent (TI.com) @ 2025-10-09 14:50 UTC (permalink / raw)
  To: Tom Rini, Simon Glass, Jagan Teki, Andre Przywara, Hans de Goede,
	Mario Six, Stefano Babic, Fabio Estevam, NXP i.MX U-Boot Team,
	Ying-Chun Liu (PaulLiu)
  Cc: Roger Quadros, Bajjuri Praneeth, Thomas Petazzoni, u-boot,
	Kory Maincent (TI.com)

Enhance the extension board scanning code in sandbox with better error
handling and code organization.

Signed-off-by: Kory Maincent (TI.com) <kory.maincent@bootlin.com>
---
 board/sandbox/sandbox.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/board/sandbox/sandbox.c b/board/sandbox/sandbox.c
index 0dc23a27dfc..c5d7b9651a9 100644
--- a/board/sandbox/sandbox.c
+++ b/board/sandbox/sandbox.c
@@ -113,11 +113,15 @@ int ft_board_setup(void *fdt, struct bd_info *bd)
 #ifdef CONFIG_CMD_EXTENSION
 int extension_board_scan(struct list_head *extension_list)
 {
-	struct extension *extension;
 	int i;
 
 	for (i = 0; i < 2; i++) {
+		struct extension *extension;
+
 		extension = calloc(1, sizeof(struct extension));
+		if (!extension)
+			return -ENOMEM;
+
 		snprintf(extension->overlay, sizeof(extension->overlay), "overlay%d.dtbo", i);
 		snprintf(extension->name, sizeof(extension->name), "extension board %d", i);
 		snprintf(extension->owner, sizeof(extension->owner), "sandbox");

-- 
2.43.0


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v2 11/18] board: sandbox: Convert extension support to UCLASS framework
  2025-10-09 14:50 [PATCH v2 00/18] Convert extension support to UCLASS and adds its support to boot flows Kory Maincent (TI.com)
                   ` (9 preceding siblings ...)
  2025-10-09 14:50 ` [PATCH v2 10/18] board: sandbox: Improve extension board scan implementation Kory Maincent (TI.com)
@ 2025-10-09 14:50 ` Kory Maincent (TI.com)
  2025-10-10 11:13   ` Simon Glass
  2025-10-09 14:50 ` [PATCH v2 12/18] board: compulab: Exclude compulab extension board detection from XPL builds Kory Maincent (TI.com)
                   ` (6 subsequent siblings)
  17 siblings, 1 reply; 36+ messages in thread
From: Kory Maincent (TI.com) @ 2025-10-09 14:50 UTC (permalink / raw)
  To: Tom Rini, Simon Glass, Jagan Teki, Andre Przywara, Hans de Goede,
	Mario Six, Stefano Babic, Fabio Estevam, NXP i.MX U-Boot Team,
	Ying-Chun Liu (PaulLiu)
  Cc: Roger Quadros, Bajjuri Praneeth, Thomas Petazzoni, u-boot,
	Kory Maincent (TI.com)

Migrate sandbox extension board detection from legacy implementation to
the new UCLASS-based extension board framework.

Signed-off-by: Kory Maincent (TI.com) <kory.maincent@bootlin.com>
---
 arch/Kconfig            |  2 +-
 board/sandbox/sandbox.c | 24 ++++++++++++------------
 2 files changed, 13 insertions(+), 13 deletions(-)

diff --git a/arch/Kconfig b/arch/Kconfig
index 7e05e0c2263..5bb65a29f8d 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -215,7 +215,7 @@ config SANDBOX
 	select SYSRESET_CMD_POWEROFF if CMD_POWEROFF
 	select SYS_CACHE_SHIFT_4
 	select IRQ
-	select SUPPORT_EXTENSION_SCAN if CMDLINE
+	select SUPPORT_DM_EXTENSION_SCAN if CMDLINE
 	select SUPPORT_ACPI
 	imply BITREVERSE
 	select BLOBLIST
diff --git a/board/sandbox/sandbox.c b/board/sandbox/sandbox.c
index c5d7b9651a9..0e83173f531 100644
--- a/board/sandbox/sandbox.c
+++ b/board/sandbox/sandbox.c
@@ -111,27 +111,27 @@ int ft_board_setup(void *fdt, struct bd_info *bd)
 }
 
 #ifdef CONFIG_CMD_EXTENSION
-int extension_board_scan(struct list_head *extension_list)
+static int sandbox_extension_board_scan(struct alist *extension_list)
 {
 	int i;
 
 	for (i = 0; i < 2; i++) {
-		struct extension *extension;
-
-		extension = calloc(1, sizeof(struct extension));
-		if (!extension)
+		struct extension extension = {0}, *_extension;
+
+		snprintf(extension.overlay, sizeof(extension.overlay), "overlay%d.dtbo", i);
+		snprintf(extension.name, sizeof(extension.name), "extension board %d", i);
+		snprintf(extension.owner, sizeof(extension.owner), "sandbox");
+		snprintf(extension.version, sizeof(extension.version), "1.1");
+		snprintf(extension.other, sizeof(extension.other), "Fictional extension board");
+		_extension = alist_add(extension_list, extension);
+		if (!_extension)
 			return -ENOMEM;
-
-		snprintf(extension->overlay, sizeof(extension->overlay), "overlay%d.dtbo", i);
-		snprintf(extension->name, sizeof(extension->name), "extension board %d", i);
-		snprintf(extension->owner, sizeof(extension->owner), "sandbox");
-		snprintf(extension->version, sizeof(extension->version), "1.1");
-		snprintf(extension->other, sizeof(extension->other), "Fictional extension board");
-		list_add_tail(&extension->list, extension_list);
 	}
 
 	return i;
 }
+
+U_BOOT_EXTENSION(sandbox_extension, sandbox_extension_board_scan);
 #endif
 
 #ifdef CONFIG_BOARD_LATE_INIT

-- 
2.43.0


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v2 12/18] board: compulab: Exclude compulab extension board detection from XPL builds
  2025-10-09 14:50 [PATCH v2 00/18] Convert extension support to UCLASS and adds its support to boot flows Kory Maincent (TI.com)
                   ` (10 preceding siblings ...)
  2025-10-09 14:50 ` [PATCH v2 11/18] board: sandbox: Convert extension support to UCLASS framework Kory Maincent (TI.com)
@ 2025-10-09 14:50 ` Kory Maincent (TI.com)
  2025-10-09 14:50 ` [PATCH v2 13/18] board: compulab: Convert imx8mm-cl-iot-gate to UCLASS extension framework Kory Maincent (TI.com)
                   ` (5 subsequent siblings)
  17 siblings, 0 replies; 36+ messages in thread
From: Kory Maincent (TI.com) @ 2025-10-09 14:50 UTC (permalink / raw)
  To: Tom Rini, Simon Glass, Jagan Teki, Andre Przywara, Hans de Goede,
	Mario Six, Stefano Babic, Fabio Estevam, NXP i.MX U-Boot Team,
	Ying-Chun Liu (PaulLiu)
  Cc: Roger Quadros, Bajjuri Praneeth, Thomas Petazzoni, u-boot,
	Kory Maincent (TI.com)

Disable compulab extension board detection functionality in XPL (eXtended
Program Loader) images to reduce size and complexity in the early boot
stage.

Signed-off-by: Kory Maincent (TI.com) <kory.maincent@bootlin.com>
---

Change in v2:
- New patch.
---
 board/compulab/imx8mm-cl-iot-gate/imx8mm-cl-iot-gate.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/board/compulab/imx8mm-cl-iot-gate/imx8mm-cl-iot-gate.c b/board/compulab/imx8mm-cl-iot-gate/imx8mm-cl-iot-gate.c
index bda7aac5be4..be4f293bd4a 100644
--- a/board/compulab/imx8mm-cl-iot-gate/imx8mm-cl-iot-gate.c
+++ b/board/compulab/imx8mm-cl-iot-gate/imx8mm-cl-iot-gate.c
@@ -249,6 +249,8 @@ int board_mmc_get_env_dev(int devno)
 #define IOT_GATE_IMX8_EXT_I2C_ADDR_GPIO 0x22 /* I2C address of the GPIO
 						extender */
 
+#if !IS_ENABLED(CONFIG_XPL_BUILD)
+
 static int iot_gate_imx8_ext_id = IOT_GATE_EXT_EMPTY; /* Extension board ID */
 static int iot_gate_imx8_ext_ied_id [3] = {
 	IOT_GATE_IMX8_CARD_ID_EMPTY,
@@ -541,6 +543,7 @@ int extension_board_scan(struct list_head *extension_list)
 
         return ret;
 }
+#endif
 
 static int setup_mac_address(void)
 {

-- 
2.43.0


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v2 13/18] board: compulab: Convert imx8mm-cl-iot-gate to UCLASS extension framework
  2025-10-09 14:50 [PATCH v2 00/18] Convert extension support to UCLASS and adds its support to boot flows Kory Maincent (TI.com)
                   ` (11 preceding siblings ...)
  2025-10-09 14:50 ` [PATCH v2 12/18] board: compulab: Exclude compulab extension board detection from XPL builds Kory Maincent (TI.com)
@ 2025-10-09 14:50 ` Kory Maincent (TI.com)
  2025-10-09 14:50 ` [PATCH v2 14/18] boot: Remove legacy extension board support Kory Maincent (TI.com)
                   ` (4 subsequent siblings)
  17 siblings, 0 replies; 36+ messages in thread
From: Kory Maincent (TI.com) @ 2025-10-09 14:50 UTC (permalink / raw)
  To: Tom Rini, Simon Glass, Jagan Teki, Andre Przywara, Hans de Goede,
	Mario Six, Stefano Babic, Fabio Estevam, NXP i.MX U-Boot Team,
	Ying-Chun Liu (PaulLiu)
  Cc: Roger Quadros, Bajjuri Praneeth, Thomas Petazzoni, u-boot,
	Kory Maincent (TI.com)

Migrate CompuLab imx8mm-cl-iot-gate board extension detection from legacy
implementation to the new UCLASS-based extension board framework.

Signed-off-by: Kory Maincent (TI.com) <kory.maincent@bootlin.com>
---

Change in v2:
- Fix build errors.
---
 arch/arm/mach-imx/imx8m/Kconfig                    |  4 +-
 .../imx8mm-cl-iot-gate/imx8mm-cl-iot-gate.c        | 64 ++++++++++------------
 2 files changed, 32 insertions(+), 36 deletions(-)

diff --git a/arch/arm/mach-imx/imx8m/Kconfig b/arch/arm/mach-imx/imx8m/Kconfig
index e7bc154b805..5324eff3084 100644
--- a/arch/arm/mach-imx/imx8m/Kconfig
+++ b/arch/arm/mach-imx/imx8m/Kconfig
@@ -359,14 +359,14 @@ config TARGET_IMX8MM_CL_IOT_GATE
 	select IMX8MM
 	select SUPPORT_SPL
 	select IMX8M_LPDDR4
-	select SUPPORT_EXTENSION_SCAN
+	select SUPPORT_DM_EXTENSION_SCAN
 
 config TARGET_IMX8MM_CL_IOT_GATE_OPTEE
 	bool "CompuLab iot-gate-imx8 with optee support"
 	select IMX8MM
 	select SUPPORT_SPL
 	select IMX8M_LPDDR4
-	select SUPPORT_EXTENSION_SCAN
+	select SUPPORT_DM_EXTENSION_SCAN
 
 config TARGET_IMX8MP_RSB3720A1_4G
 	bool "Support i.MX8MP RSB3720A1 4G"
diff --git a/board/compulab/imx8mm-cl-iot-gate/imx8mm-cl-iot-gate.c b/board/compulab/imx8mm-cl-iot-gate/imx8mm-cl-iot-gate.c
index be4f293bd4a..e6f0c374067 100644
--- a/board/compulab/imx8mm-cl-iot-gate/imx8mm-cl-iot-gate.c
+++ b/board/compulab/imx8mm-cl-iot-gate/imx8mm-cl-iot-gate.c
@@ -436,9 +436,9 @@ static int iot_gate_imx8_update_ext_ied(void)
 	return 0;
 }
 
-int extension_board_scan(struct list_head *extension_list)
+static int iot_gate_imx8_extension_board_scan(struct alist *extension_list)
 {
-	struct extension *extension = NULL;
+	struct extension extension = {0}, *_extension = NULL;
 	int i;
 	int ret = 0;
 
@@ -448,25 +448,21 @@ int extension_board_scan(struct list_head *extension_list)
 	case IOT_GATE_EXT_EMPTY:
 		break;
 	case IOT_GATE_EXT_CAN:
-		extension = calloc(1, sizeof(struct extension));
-		snprintf(extension->name, sizeof(extension->name),
+		snprintf(extension.name, sizeof(extension.name),
 			 "IOT_GATE_EXT_CAN");
 		break;
 	case IOT_GATE_EXT_IED:
-		extension = calloc(1, sizeof(struct extension));
-		snprintf(extension->name, sizeof(extension->name),
+		snprintf(extension.name, sizeof(extension.name),
 			 "IOT_GATE_EXT_IED");
-		snprintf(extension->overlay, sizeof(extension->overlay),
+		snprintf(extension.overlay, sizeof(extension.overlay),
 			 "imx8mm-cl-iot-gate-ied.dtbo");
 		break;
 	case IOT_GATE_EXT_POE:
-		extension = calloc(1, sizeof(struct extension));
-		snprintf(extension->name, sizeof(extension->name),
+		snprintf(extension.name, sizeof(extension.name),
 			 "IOT_GATE_EXT_POE");
 		break;
 	case IOT_GATE_EXT_POEV2:
-		extension = calloc(1, sizeof(struct extension));
-		snprintf(extension->name, sizeof(extension->name),
+		snprintf(extension.name, sizeof(extension.name),
 			 "IOT_GATE_EXT_POEV2");
 		break;
 	default:
@@ -474,10 +470,12 @@ int extension_board_scan(struct list_head *extension_list)
 		break;
 	}
 
-	if (extension) {
-		snprintf(extension->owner, sizeof(extension->owner),
+	if (extension.name[0]) {
+		snprintf(extension.owner, sizeof(extension.owner),
 			 "Compulab");
-		list_add_tail(&extension->list, extension_list);
+		_extension = alist_add(extension_list, extension);
+		if (!_extension)
+			return -ENOMEM;
 		ret = 1;
 	} else
 		return ret;
@@ -486,44 +484,38 @@ int extension_board_scan(struct list_head *extension_list)
 
 	iot_gate_imx8_update_ext_ied();
 	for (i=0; i<ARRAY_SIZE(iot_gate_imx8_ext_ied_id); i++) {
-		extension = NULL;
+		memset(&extension, 0, sizeof(extension));
 		switch (iot_gate_imx8_ext_ied_id[i]) {
 		case IOT_GATE_IMX8_CARD_ID_EMPTY:
 			break;
 		case IOT_GATE_IMX8_CARD_ID_RS_485:
-			extension = calloc(1, sizeof(struct extension));
-			snprintf(extension->name, sizeof(extension->name),
+			snprintf(extension.name, sizeof(extension.name),
 				 "IOT_GATE_IMX8_CARD_ID_RS_485");
 			break;
 		case IOT_GATE_IMX8_CARD_ID_RS_232:
-			extension = calloc(1, sizeof(struct extension));
-			snprintf(extension->name, sizeof(extension->name),
+			snprintf(extension.name, sizeof(extension.name),
 				 "IOT_GATE_IMX8_CARD_ID_RS_232");
 			break;
 		case IOT_GATE_IMX8_CARD_ID_CAN:
-			extension = calloc(1, sizeof(struct extension));
-			snprintf(extension->name, sizeof(extension->name),
+			snprintf(extension.name, sizeof(extension.name),
 				 "IOT_GATE_IMX8_CARD_ID_CAN");
-			snprintf(extension->overlay, sizeof(extension->overlay),
+			snprintf(extension.overlay, sizeof(extension.overlay),
 				 "imx8mm-cl-iot-gate-ied-can%d.dtbo", i);
 			break;
 		case IOT_GATE_IMX8_CARD_ID_TPM:
-			extension = calloc(1, sizeof(struct extension));
-			snprintf(extension->name, sizeof(extension->name),
+			snprintf(extension.name, sizeof(extension.name),
 				 "IOT_GATE_IMX8_CARD_ID_TPM");
-			snprintf(extension->overlay, sizeof(extension->overlay),
+			snprintf(extension.overlay, sizeof(extension.overlay),
 				 "imx8mm-cl-iot-gate-ied-tpm%d.dtbo", i);
 			break;
 		case IOT_GATE_IMX8_CARD_ID_CL420:
-			extension = calloc(1, sizeof(struct extension));
-			snprintf(extension->name, sizeof(extension->name),
+			snprintf(extension.name, sizeof(extension.name),
 				 "IOT_GATE_IMX8_CARD_ID_CL420");
-			snprintf(extension->overlay, sizeof(extension->overlay),
+			snprintf(extension.overlay, sizeof(extension.overlay),
 				 "imx8mm-cl-iot-gate-ied-can%d.dtbo", i);
 			break;
 		case IOT_GATE_IMX8_CARD_ID_DI4O4:
-			extension = calloc(1, sizeof(struct extension));
-			snprintf(extension->name, sizeof(extension->name),
+			snprintf(extension.name, sizeof(extension.name),
 				 "IOT_GATE_IMX8_CARD_ID_DI4O4");
 			break;
 		default:
@@ -531,18 +523,22 @@ int extension_board_scan(struct list_head *extension_list)
 			       __func__, i, iot_gate_imx8_ext_ied_id[i]);
 			break;
 		}
-		if (extension) {
-			snprintf(extension->owner, sizeof(extension->owner),
+		if (extension.name[0]) {
+			snprintf(extension.owner, sizeof(extension.owner),
 				 "Compulab");
-			snprintf(extension->other, sizeof(extension->other),
+			snprintf(extension.other, sizeof(extension.other),
 				 "On slot %d", i);
-			list_add_tail(&extension->list, extension_list);
+			_extension = alist_add(extension_list, extension);
+			if (!_extension)
+				return -ENOMEM;
 			ret = ret + 1;
 		}
 	}
 
         return ret;
 }
+
+U_BOOT_EXTENSION(iot_gate_imx8_extension, iot_gate_imx8_extension_board_scan);
 #endif
 
 static int setup_mac_address(void)

-- 
2.43.0


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v2 14/18] boot: Remove legacy extension board support
  2025-10-09 14:50 [PATCH v2 00/18] Convert extension support to UCLASS and adds its support to boot flows Kory Maincent (TI.com)
                   ` (12 preceding siblings ...)
  2025-10-09 14:50 ` [PATCH v2 13/18] board: compulab: Convert imx8mm-cl-iot-gate to UCLASS extension framework Kory Maincent (TI.com)
@ 2025-10-09 14:50 ` Kory Maincent (TI.com)
  2025-10-10 11:13   ` Simon Glass
  2025-10-09 14:50 ` [PATCH v2 15/18] boot: extension: Move overlay apply custom logic to command level Kory Maincent (TI.com)
                   ` (3 subsequent siblings)
  17 siblings, 1 reply; 36+ messages in thread
From: Kory Maincent (TI.com) @ 2025-10-09 14:50 UTC (permalink / raw)
  To: Tom Rini, Simon Glass, Jagan Teki, Andre Przywara, Hans de Goede,
	Mario Six, Stefano Babic, Fabio Estevam, NXP i.MX U-Boot Team,
	Ying-Chun Liu (PaulLiu)
  Cc: Roger Quadros, Bajjuri Praneeth, Thomas Petazzoni, u-boot,
	Kory Maincent (TI.com)

Remove the legacy extension board implementation now that all boards
have been converted to use the new UCLASS-based framework. This
eliminates 223 lines of legacy code while preserving functionality
through the modern driver model approach.

Signed-off-by: Kory Maincent (TI.com) <kory.maincent@bootlin.com>
---

Changes in v2:
- Remove a missing DM_EXTENSION_SCAN in cmd/Kconfig
---
 MAINTAINERS                        |  1 -
 arch/Kconfig                       |  2 +-
 arch/arm/mach-imx/imx8m/Kconfig    |  4 +-
 arch/arm/mach-omap2/am33xx/Kconfig |  2 +-
 arch/arm/mach-omap2/omap5/Kconfig  |  2 +-
 arch/arm/mach-sunxi/Kconfig        |  2 +-
 board/ti/common/Makefile           |  2 +-
 boot/Kconfig                       |  3 --
 boot/Makefile                      |  3 +-
 boot/extension-uclass.c            | 18 +++----
 boot/extension.c                   | 97 --------------------------------------
 cmd/Kconfig                        |  2 +-
 cmd/extension_board.c              | 74 ++++-------------------------
 include/extension_board.h          | 55 ++++++---------------
 14 files changed, 40 insertions(+), 227 deletions(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index a63ffa14ef5..a75e59453d7 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1188,7 +1188,6 @@ S:	Maintained
 F:	board/sunxi/chip.c
 F:	board/ti/common/cape_detect.c
 F:	boot/extension-uclass.c
-F:	boot/extension.c
 F:	cmd/extension_board.c
 F:	include/extension_board.h
 
diff --git a/arch/Kconfig b/arch/Kconfig
index 5bb65a29f8d..7e05e0c2263 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -215,7 +215,7 @@ config SANDBOX
 	select SYSRESET_CMD_POWEROFF if CMD_POWEROFF
 	select SYS_CACHE_SHIFT_4
 	select IRQ
-	select SUPPORT_DM_EXTENSION_SCAN if CMDLINE
+	select SUPPORT_EXTENSION_SCAN if CMDLINE
 	select SUPPORT_ACPI
 	imply BITREVERSE
 	select BLOBLIST
diff --git a/arch/arm/mach-imx/imx8m/Kconfig b/arch/arm/mach-imx/imx8m/Kconfig
index 5324eff3084..e7bc154b805 100644
--- a/arch/arm/mach-imx/imx8m/Kconfig
+++ b/arch/arm/mach-imx/imx8m/Kconfig
@@ -359,14 +359,14 @@ config TARGET_IMX8MM_CL_IOT_GATE
 	select IMX8MM
 	select SUPPORT_SPL
 	select IMX8M_LPDDR4
-	select SUPPORT_DM_EXTENSION_SCAN
+	select SUPPORT_EXTENSION_SCAN
 
 config TARGET_IMX8MM_CL_IOT_GATE_OPTEE
 	bool "CompuLab iot-gate-imx8 with optee support"
 	select IMX8MM
 	select SUPPORT_SPL
 	select IMX8M_LPDDR4
-	select SUPPORT_DM_EXTENSION_SCAN
+	select SUPPORT_EXTENSION_SCAN
 
 config TARGET_IMX8MP_RSB3720A1_4G
 	bool "Support i.MX8MP RSB3720A1 4G"
diff --git a/arch/arm/mach-omap2/am33xx/Kconfig b/arch/arm/mach-omap2/am33xx/Kconfig
index 77f7938305b..dff4f1cf202 100644
--- a/arch/arm/mach-omap2/am33xx/Kconfig
+++ b/arch/arm/mach-omap2/am33xx/Kconfig
@@ -15,7 +15,7 @@ config TARGET_AM335X_EVM
 	select DM_GPIO
 	select DM_SERIAL
 	select TI_I2C_BOARD_DETECT
-	select SUPPORT_DM_EXTENSION_SCAN
+	select SUPPORT_EXTENSION_SCAN
 	imply CMD_DM
 	imply SPL_DM
 	imply SPL_DM_SEQ_ALIAS
diff --git a/arch/arm/mach-omap2/omap5/Kconfig b/arch/arm/mach-omap2/omap5/Kconfig
index 819490a8cf8..5394529658b 100644
--- a/arch/arm/mach-omap2/omap5/Kconfig
+++ b/arch/arm/mach-omap2/omap5/Kconfig
@@ -38,7 +38,7 @@ config TARGET_AM57XX_EVM
 	select CMD_DDR3
 	select DRA7XX
 	select TI_I2C_BOARD_DETECT
-	select SUPPORT_DM_EXTENSION_SCAN
+	select SUPPORT_EXTENSION_SCAN
 	imply DM_THERMAL
 	imply SCSI
 	imply SPL_THERMAL
diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
index f5696199516..b04ec671696 100644
--- a/arch/arm/mach-sunxi/Kconfig
+++ b/arch/arm/mach-sunxi/Kconfig
@@ -1223,7 +1223,7 @@ config BLUETOOTH_DT_DEVICE_FIXUP
 
 config CHIP_DIP_SCAN
 	bool "Enable DIPs detection for CHIP board"
-	select SUPPORT_DM_EXTENSION_SCAN
+	select SUPPORT_EXTENSION_SCAN
 	select W1
 	select W1_GPIO
 	select W1_EEPROM
diff --git a/board/ti/common/Makefile b/board/ti/common/Makefile
index b42273d3a5a..f58935b4103 100644
--- a/board/ti/common/Makefile
+++ b/board/ti/common/Makefile
@@ -2,6 +2,6 @@
 # Copyright (C) 2015-2016 Texas Instruments Incorporated - https://www.ti.com/
 
 obj-${CONFIG_TI_I2C_BOARD_DETECT} += board_detect.o
-obj-${CONFIG_$(PHASE_)SUPPORT_DM_EXTENSION_SCAN} += cape_detect.o
+obj-${CONFIG_$(PHASE_)SUPPORT_EXTENSION_SCAN} += cape_detect.o
 obj-${CONFIG_OF_LIBFDT} += fdt_ops.o
 obj-${CONFIG_ARCH_K3} += k3-ddr.o
diff --git a/boot/Kconfig b/boot/Kconfig
index 159da81bec5..62aa301f18f 100644
--- a/boot/Kconfig
+++ b/boot/Kconfig
@@ -1909,9 +1909,6 @@ endif # OF_LIBFDT
 config SUPPORT_EXTENSION_SCAN
         bool
 
-config SUPPORT_DM_EXTENSION_SCAN
-        bool
-
 config USE_BOOTARGS
 	bool "Enable boot arguments"
 	help
diff --git a/boot/Makefile b/boot/Makefile
index aa26070fbb8..7fb56e7ef37 100644
--- a/boot/Makefile
+++ b/boot/Makefile
@@ -9,8 +9,7 @@ obj-$(CONFIG_BOOT_RETRY) += bootretry.o
 obj-$(CONFIG_CMD_BOOTM) += bootm.o bootm_os.o
 obj-$(CONFIG_CMD_BOOTZ) += bootm.o bootm_os.o
 obj-$(CONFIG_CMD_BOOTI) += bootm.o bootm_os.o
-obj-$(CONFIG_SUPPORT_EXTENSION_SCAN) += extension.o
-obj-$(CONFIG_SUPPORT_DM_EXTENSION_SCAN) += extension-uclass.o
+obj-$(CONFIG_SUPPORT_EXTENSION_SCAN) += extension-uclass.o
 
 obj-$(CONFIG_PXE_UTILS) += pxe_utils.o
 
diff --git a/boot/extension-uclass.c b/boot/extension-uclass.c
index 9dfbeb60d20..1b21aa08944 100644
--- a/boot/extension-uclass.c
+++ b/boot/extension-uclass.c
@@ -61,7 +61,7 @@ static struct udevice *extension_get_dev(void)
 	return NULL;
 }
 
-struct alist *dm_extension_get_list(void)
+struct alist *extension_get_list(void)
 {
 	struct udevice *dev = extension_get_dev();
 
@@ -71,7 +71,7 @@ struct alist *dm_extension_get_list(void)
 	return dev_get_priv(dev);
 }
 
-int dm_extension_probe(struct udevice *dev)
+int extension_probe(struct udevice *dev)
 {
 	struct alist *extension_list = dev_get_priv(dev);
 
@@ -79,7 +79,7 @@ int dm_extension_probe(struct udevice *dev)
 	return 0;
 }
 
-int dm_extension_remove(struct udevice *dev)
+int extension_remove(struct udevice *dev)
 {
 	struct alist *extension_list = dev_get_priv(dev);
 
@@ -87,9 +87,9 @@ int dm_extension_remove(struct udevice *dev)
 	return 0;
 }
 
-int dm_extension_scan(void)
+int extension_scan(void)
 {
-	struct alist *extension_list = dm_extension_get_list();
+	struct alist *extension_list = extension_get_list();
 	struct udevice *dev = extension_get_dev();
 	const struct extension_ops *ops;
 
@@ -154,9 +154,9 @@ static int _extension_apply(const struct extension *extension)
 	return ret;
 }
 
-int dm_extension_apply(int extension_num)
+int extension_apply(int extension_num)
 {
-	struct alist *extension_list = dm_extension_get_list();
+	struct alist *extension_list = extension_get_list();
 	const struct extension *extension;
 
 	if (!extension_list)
@@ -172,9 +172,9 @@ int dm_extension_apply(int extension_num)
 	return _extension_apply(extension);
 }
 
-int dm_extension_apply_all(void)
+int extension_apply_all(void)
 {
-	struct alist *extension_list = dm_extension_get_list();
+	struct alist *extension_list = extension_get_list();
 	const struct extension *extension;
 	int ret;
 
diff --git a/boot/extension.c b/boot/extension.c
deleted file mode 100644
index fc9e1d398f4..00000000000
--- a/boot/extension.c
+++ /dev/null
@@ -1,97 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * (C) Copyright 2025 Köry Maincent <kory.maincent@bootlin.com>
- */
-
-#include <bootdev.h>
-#include <command.h>
-#include <env.h>
-#include <extension_board.h>
-#include <fdt_support.h>
-#include <malloc.h>
-#include <mapmem.h>
-
-int extension_apply(struct extension *extension)
-{
-	ulong extrasize, overlay_addr;
-	struct fdt_header *blob;
-	char *overlay_cmd;
-
-	if (!working_fdt) {
-		printf("No FDT memory address configured. Please configure\n"
-		       "the FDT address via \"fdt addr <address>\" command.\n");
-		return CMD_RET_FAILURE;
-	}
-
-	overlay_cmd = env_get("extension_overlay_cmd");
-	if (!overlay_cmd) {
-		printf("Environment extension_overlay_cmd is missing\n");
-		return CMD_RET_FAILURE;
-	}
-
-	overlay_addr = env_get_hex("extension_overlay_addr", 0);
-	if (!overlay_addr) {
-		printf("Environment extension_overlay_addr is missing\n");
-		return CMD_RET_FAILURE;
-	}
-
-	env_set("extension_overlay_name", extension->overlay);
-	if (run_command(overlay_cmd, 0) != 0)
-		return CMD_RET_FAILURE;
-
-	extrasize = env_get_hex("filesize", 0);
-	if (!extrasize)
-		return CMD_RET_FAILURE;
-
-	fdt_shrink_to_minimum(working_fdt, extrasize);
-
-	blob = map_sysmem(overlay_addr, 0);
-	if (!fdt_valid(&blob))
-		return CMD_RET_FAILURE;
-
-	/* apply method prints messages on error */
-	if (fdt_overlay_apply_verbose(working_fdt, blob))
-		return CMD_RET_FAILURE;
-
-	return CMD_RET_SUCCESS;
-}
-
-int extension_scan(bool show)
-{
-	struct extension *extension, *next;
-	int extension_num;
-
-	list_for_each_entry_safe(extension, next, &extension_list, list) {
-		list_del(&extension->list);
-		free(extension);
-	}
-	extension_num = extension_board_scan(&extension_list);
-	if (show && extension_num >= 0)
-		printf("Found %d extension board(s).\n", extension_num);
-
-	/* either the number of extensions, or -ve for error */
-	return extension_num;
-}
-
-static int extension_bootdev_hunt(struct bootdev_hunter *info, bool show)
-{
-	int ret;
-
-	ret = env_set_hex("extension_overlay_addr",
-			  env_get_hex("fdtoverlay_addr_r", 0));
-	if (ret)
-		return log_msg_ret("env", ret);
-
-	ret = extension_scan(show);
-	if (ret < 0)
-		return log_msg_ret("ext", ret);
-
-	return 0;
-}
-
-/* extensions should have a uclass - for now we use UCLASS_SIMPLE_BUS uclass */
-BOOTDEV_HUNTER(extension_bootdev_hunter) = {
-	.prio		= BOOTDEVP_1_PRE_SCAN,
-	.uclass		= UCLASS_SIMPLE_BUS,
-	.hunt		= extension_bootdev_hunt,
-};
diff --git a/cmd/Kconfig b/cmd/Kconfig
index 721bdb87c8a..986eeeba807 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -548,7 +548,7 @@ config CMD_FDT
 config CMD_EXTENSION
 	bool "Extension board management command"
 	select CMD_FDT
-	depends on SUPPORT_EXTENSION_SCAN || SUPPORT_DM_EXTENSION_SCAN
+	depends on SUPPORT_EXTENSION_SCAN
 	help
 	  Enables the "extension" command, which allows to detect
 	  extension boards connected to the system, and apply
diff --git a/cmd/extension_board.c b/cmd/extension_board.c
index d70394f36c7..c373397e0fb 100644
--- a/cmd/extension_board.c
+++ b/cmd/extension_board.c
@@ -9,46 +9,26 @@
 #include <command.h>
 #include <extension_board.h>
 
-LIST_HEAD(extension_list);
-
 static int do_extension_list(struct cmd_tbl *cmdtp, int flag,
 			     int argc, char *const argv[])
 {
-#if CONFIG_IS_ENABLED(SUPPORT_DM_EXTENSION_SCAN)
-	struct alist *dm_extension_list;
-#endif
+	struct alist *extension_list;
 	struct extension *extension;
 	int i = 0;
 
-#if CONFIG_IS_ENABLED(SUPPORT_DM_EXTENSION_SCAN)
-	dm_extension_list = dm_extension_get_list();
-
-	if (!alist_get_ptr(dm_extension_list, 0)) {
+	extension_list = extension_get_list();
+	if (!alist_get_ptr(extension_list, 0)) {
 		printf("No extension registered - Please run \"extension scan\"\n");
 		return CMD_RET_SUCCESS;
 	}
 
-	alist_for_each(extension, dm_extension_list) {
+	alist_for_each(extension, extension_list) {
 		printf("Extension %d: %s\n", i++, extension->name);
 		printf("\tManufacturer: \t\t%s\n", extension->owner);
 		printf("\tVersion: \t\t%s\n", extension->version);
 		printf("\tDevicetree overlay: \t%s\n", extension->overlay);
 		printf("\tOther information: \t%s\n", extension->other);
 	}
-#else
-	if (list_empty(&extension_list)) {
-		printf("No extension registered - Please run \"extension scan\"\n");
-		return CMD_RET_SUCCESS;
-	}
-
-	list_for_each_entry(extension, &extension_list, list) {
-		printf("Extension %d: %s\n", i++, extension->name);
-		printf("\tManufacturer: \t\t%s\n", extension->owner);
-		printf("\tVersion: \t\t%s\n", extension->version);
-		printf("\tDevicetree overlay: \t%s\n", extension->overlay);
-		printf("\tOther information: \t%s\n", extension->other);
-	}
-#endif
 	return CMD_RET_SUCCESS;
 }
 
@@ -57,69 +37,31 @@ static int do_extension_scan(struct cmd_tbl *cmdtp, int flag,
 {
 	int extension_num;
 
-#if CONFIG_IS_ENABLED(SUPPORT_DM_EXTENSION_SCAN)
-	extension_num = dm_extension_scan();
+	extension_num = extension_scan();
 	if (extension_num == -ENODEV)
 		extension_num = 0;
 	else if (extension_num < 0)
 		return CMD_RET_FAILURE;
 
 	printf("Found %d extension board(s).\n", extension_num);
-#else
-	extension_num = extension_scan(true);
-	if (extension_num < 0 && extension_num != -ENODEV)
-		return CMD_RET_FAILURE;
-#endif
-
 	return CMD_RET_SUCCESS;
 }
 
 static int do_extension_apply(struct cmd_tbl *cmdtp, int flag,
 			      int argc, char *const argv[])
 {
-#if !CONFIG_IS_ENABLED(SUPPORT_DM_EXTENSION_SCAN)
-	struct extension *extension = NULL;
-	struct list_head *entry;
-	int i = 0;
-#endif
-	int extension_id, ret;
+	int extension_id;
 
 	if (argc < 2)
 		return CMD_RET_USAGE;
 
 	if (strcmp(argv[1], "all") == 0) {
-		ret = CMD_RET_FAILURE;
-#if CONFIG_IS_ENABLED(SUPPORT_DM_EXTENSION_SCAN)
-		if (dm_extension_apply_all())
+		if (extension_apply_all())
 			return CMD_RET_FAILURE;
-#else
-		list_for_each_entry(extension, &extension_list, list) {
-			ret = extension_apply(extension);
-			if (ret != CMD_RET_SUCCESS)
-				break;
-		}
-#endif
 	} else {
 		extension_id = simple_strtol(argv[1], NULL, 10);
-#if CONFIG_IS_ENABLED(SUPPORT_DM_EXTENSION_SCAN)
-		if (dm_extension_apply(extension_id))
+		if (extension_apply(extension_id))
 			return CMD_RET_FAILURE;
-#else
-		list_for_each(entry, &extension_list) {
-			if (i == extension_id) {
-				extension = list_entry(entry, struct extension,  list);
-				break;
-			}
-			i++;
-		}
-
-		if (!extension) {
-			printf("Wrong extension number\n");
-			return CMD_RET_FAILURE;
-		}
-
-		ret = extension_apply(extension);
-#endif
 	}
 
 	return CMD_RET_SUCCESS;
diff --git a/include/extension_board.h b/include/extension_board.h
index 78139cd7489..fc9c33ed354 100644
--- a/include/extension_board.h
+++ b/include/extension_board.h
@@ -14,47 +14,46 @@
 extern struct list_head extension_list;
 
 /**
- * dm_extension_get_list - Get the extension list
+ * extension_get_list - Get the extension list
  * Return: The extension alist pointer, or NULL if no such list exists.
  */
-struct alist *dm_extension_get_list(void);
+struct alist *extension_get_list(void);
 
 /**
- * dm_extension_probe - Probe extension device
+ * extension_probe - Probe extension device
  * @dev: Extension device that needs to be probed
  * Return: Zero on success, negative on failure.
  */
-int dm_extension_probe(struct udevice *dev);
+int extension_probe(struct udevice *dev);
 
 /**
- * dm_extension_remove - Remove extension device
+ * extension_remove - Remove extension device
  * @dev: Extension device that needs to be removed
  * Return: Zero on success, negative on failure.
  */
-int dm_extension_remove(struct udevice *dev);
+int extension_remove(struct udevice *dev);
 
 /**
- * dm_extension_scan - Scan extension boards available.
+ * extension_scan - Scan extension boards available.
  * Return: Zero on success, negative on failure.
  */
-int dm_extension_scan(void);
+int extension_scan(void);
 
 /**
- * dm_extension_apply - Apply extension board overlay to the devicetree
+ * extension_apply - Apply extension board overlay to the devicetree
  * @extension_num: Extension number to be applied
  * Return: Zero on success, negative on failure.
  */
-int dm_extension_apply(int extension_num);
+int extension_apply(int extension_num);
 
 /**
- * dm_extension_apply_all - Apply all extension board overlays to the
+ * extension_apply_all - Apply all extension board overlays to the
  *			    devicetree
  * Return: Zero on success, negative on failure.
  */
-int dm_extension_apply_all(void);
+int extension_apply_all(void);
 
 struct extension {
-	struct list_head list;
 	char name[32];
 	char owner[32];
 	char version[32];
@@ -76,38 +75,12 @@ struct extension_ops {
 	U_BOOT_DRIVER(_name) = { \
 		.name = #_name, \
 		.id = UCLASS_EXTENSION, \
-		.probe = dm_extension_probe, \
-		.remove = dm_extension_remove, \
+		.probe = extension_probe, \
+		.remove = extension_remove, \
 		.ops = &(struct extension_ops) { \
 		       .scan = _scan_func, \
 		       }, \
 		.priv_auto = sizeof(struct alist), \
 	}
 
-/**
- * extension_board_scan - Add system-specific function to scan extension board.
- * @param extension_list	List of extension board information to update.
- * Return: the number of extension.
- *
- * This function is called if CONFIG_CMD_EXTENSION is defined.
- * Needs to fill the list extension_list with elements.
- * Each element need to be allocated to an extension structure.
- *
- */
-int extension_board_scan(struct list_head *extension_list);
-
-/**
- * extension_apply - Apply extension board overlay to the devicetree
- * @extension: Extension to be applied
- * Return: Zero on success, negative on failure.
- */
-int extension_apply(struct extension *extension);
-
-/**
- * extension_scan - Scan extension boards available.
- * @show: Flag to enable verbose log
- * Return: Zero on success, negative on failure.
- */
-int extension_scan(bool show);
-
 #endif /* __EXTENSION_SUPPORT_H */

-- 
2.43.0


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v2 15/18] boot: extension: Move overlay apply custom logic to command level
  2025-10-09 14:50 [PATCH v2 00/18] Convert extension support to UCLASS and adds its support to boot flows Kory Maincent (TI.com)
                   ` (13 preceding siblings ...)
  2025-10-09 14:50 ` [PATCH v2 14/18] boot: Remove legacy extension board support Kory Maincent (TI.com)
@ 2025-10-09 14:50 ` Kory Maincent (TI.com)
  2025-10-10 11:13   ` Simon Glass
  2025-10-09 14:50 ` [PATCH v2 16/18] boot: pxe_utils: Add extension board devicetree overlay support Kory Maincent (TI.com)
                   ` (2 subsequent siblings)
  17 siblings, 1 reply; 36+ messages in thread
From: Kory Maincent (TI.com) @ 2025-10-09 14:50 UTC (permalink / raw)
  To: Tom Rini, Simon Glass, Jagan Teki, Andre Przywara, Hans de Goede,
	Mario Six, Stefano Babic, Fabio Estevam, NXP i.MX U-Boot Team,
	Ying-Chun Liu (PaulLiu)
  Cc: Roger Quadros, Bajjuri Praneeth, Thomas Petazzoni, u-boot,
	Kory Maincent (TI.com)

The extension_overlay_cmd environment variable approach is specific to
the U-Boot extension_board command, while other boot flows (pxe_utils,
bootstd) handle overlay loading differently.

Move the extension_overlay_cmd execution out of the core extension
framework to the command level. This decouples the framework from
command-specific behavior and prepares for future extension support
in other boot flows.

Signed-off-by: Kory Maincent (TI.com) <kory.maincent@bootlin.com>
---
 boot/extension-uclass.c   | 68 +++--------------------------------
 cmd/extension_board.c     | 92 +++++++++++++++++++++++++++++++++++++++++++++--
 include/extension_board.h | 12 ++-----
 3 files changed, 98 insertions(+), 74 deletions(-)

diff --git a/boot/extension-uclass.c b/boot/extension-uclass.c
index 1b21aa08944..840023fa84e 100644
--- a/boot/extension-uclass.c
+++ b/boot/extension-uclass.c
@@ -104,92 +104,34 @@ int extension_scan(void)
 	return ops->scan(extension_list);
 }
 
-static int _extension_apply(const struct extension *extension)
+int extension_apply(struct fdt_header *working_fdt, ulong size)
 {
-	ulong extrasize, overlay_addr;
 	struct fdt_header *blob;
-	char *overlay_cmd;
+	ulong overlay_addr;
 	int ret;
 
-	if (!working_fdt) {
-		printf("No FDT memory address configured. Please configure\n"
-		       "the FDT address via \"fdt addr <address>\" command.\n");
-		return -EINVAL;
-	}
-
-	overlay_cmd = env_get("extension_overlay_cmd");
-	if (!overlay_cmd) {
-		printf("Environment extension_overlay_cmd is missing\n");
-		return -EINVAL;
-	}
-
 	overlay_addr = env_get_hex("extension_overlay_addr", 0);
 	if (!overlay_addr) {
 		printf("Environment extension_overlay_addr is missing\n");
 		return -EINVAL;
 	}
 
-	env_set("extension_overlay_name", extension->overlay);
-	ret = run_command(overlay_cmd, 0);
-	if (ret)
-		return ret;
-
-	extrasize = env_get_hex("filesize", 0);
-	if (!extrasize)
-		return -EINVAL;
-
-	fdt_shrink_to_minimum(working_fdt, extrasize);
+	fdt_shrink_to_minimum(working_fdt, size);
 
 	blob = map_sysmem(overlay_addr, 0);
 	if (!fdt_valid(&blob)) {
-		printf("Invalid overlay devicetree %s\n", extension->overlay);
+		printf("Invalid overlay devicetree\n");
 		return -EINVAL;
 	}
 
 	/* Apply method prints messages on error */
 	ret = fdt_overlay_apply_verbose(working_fdt, blob);
 	if (ret)
-		printf("Failed to apply overlay %s\n", extension->overlay);
+		printf("Failed to apply overlay\n");
 
 	return ret;
 }
 
-int extension_apply(int extension_num)
-{
-	struct alist *extension_list = extension_get_list();
-	const struct extension *extension;
-
-	if (!extension_list)
-		return -ENODEV;
-
-	extension = alist_get(extension_list, extension_num,
-			      struct extension);
-	if (!extension) {
-		printf("Wrong extension number\n");
-		return -ENODEV;
-	}
-
-	return _extension_apply(extension);
-}
-
-int extension_apply_all(void)
-{
-	struct alist *extension_list = extension_get_list();
-	const struct extension *extension;
-	int ret;
-
-	if (!extension_list)
-		return -ENODEV;
-
-	alist_for_each(extension, extension_list) {
-		ret = _extension_apply(extension);
-		if (ret)
-			return ret;
-	}
-
-	return 0;
-}
-
 UCLASS_DRIVER(extension) = {
 	.name	= "extension",
 	.id	= UCLASS_EXTENSION,
diff --git a/cmd/extension_board.c b/cmd/extension_board.c
index c373397e0fb..86e4795ba8a 100644
--- a/cmd/extension_board.c
+++ b/cmd/extension_board.c
@@ -7,8 +7,90 @@
 #include <alist.h>
 #include <exports.h>
 #include <command.h>
+#include <env.h>
 #include <extension_board.h>
 
+static int
+cmd_extension_load_overlay_from_env(const struct extension *extension,
+				    ulong *filesize)
+{
+	ulong size, overlay_addr;
+	char *overlay_cmd;
+	int ret;
+
+	overlay_cmd = env_get("extension_overlay_cmd");
+	if (!overlay_cmd) {
+		printf("Environment extension_overlay_cmd is missing\n");
+		return -EINVAL;
+	}
+
+	overlay_addr = env_get_hex("extension_overlay_addr", 0);
+	if (!overlay_addr) {
+		printf("Environment extension_overlay_addr is missing\n");
+		return -EINVAL;
+	}
+
+	env_set("extension_overlay_name", extension->overlay);
+	ret = run_command(overlay_cmd, 0);
+	if (ret)
+		return ret;
+
+	size = env_get_hex("filesize", 0);
+	if (!size)
+		return -EINVAL;
+
+	*filesize = size;
+	return 0;
+}
+
+static int cmd_extension_apply(int extension_num)
+{
+	struct alist *extension_list = extension_get_list();
+	const struct extension *extension;
+	ulong size;
+	int ret;
+
+	if (!extension_list)
+		return -ENODEV;
+
+	extension = alist_get(extension_list, extension_num,
+			      struct extension);
+	if (!extension) {
+		printf("Wrong extension number\n");
+		return -ENODEV;
+	}
+
+	ret = cmd_extension_load_overlay_from_env(extension, &size);
+	if (ret)
+		return ret;
+
+	return extension_apply(working_fdt, size);
+}
+
+static int cmd_extension_apply_all(void)
+{
+	struct alist *extension_list = extension_get_list();
+	const struct extension *extension;
+	int ret;
+
+	if (!extension_list)
+		return -ENODEV;
+
+	alist_for_each(extension, extension_list) {
+		ulong size;
+
+		ret = cmd_extension_load_overlay_from_env(extension, &size);
+		if (ret)
+			return ret;
+
+		ret = extension_apply(working_fdt, size);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
 static int do_extension_list(struct cmd_tbl *cmdtp, int flag,
 			     int argc, char *const argv[])
 {
@@ -55,12 +137,18 @@ static int do_extension_apply(struct cmd_tbl *cmdtp, int flag,
 	if (argc < 2)
 		return CMD_RET_USAGE;
 
+	if (!working_fdt) {
+		printf("No FDT memory address configured. Please configure\n"
+		       "the FDT address via \"fdt addr <address>\" command.\n");
+		return -EINVAL;
+	}
+
 	if (strcmp(argv[1], "all") == 0) {
-		if (extension_apply_all())
+		if (cmd_extension_apply_all())
 			return CMD_RET_FAILURE;
 	} else {
 		extension_id = simple_strtol(argv[1], NULL, 10);
-		if (extension_apply(extension_id))
+		if (cmd_extension_apply(extension_id))
 			return CMD_RET_FAILURE;
 	}
 
diff --git a/include/extension_board.h b/include/extension_board.h
index fc9c33ed354..e12c91abb4c 100644
--- a/include/extension_board.h
+++ b/include/extension_board.h
@@ -41,17 +41,11 @@ int extension_scan(void);
 
 /**
  * extension_apply - Apply extension board overlay to the devicetree
- * @extension_num: Extension number to be applied
+ * @working_fdt: Pointer to working flattened device tree
+ * @size: Size of the devicetree overlay
  * Return: Zero on success, negative on failure.
  */
-int extension_apply(int extension_num);
-
-/**
- * extension_apply_all - Apply all extension board overlays to the
- *			    devicetree
- * Return: Zero on success, negative on failure.
- */
-int extension_apply_all(void);
+int extension_apply(struct fdt_header *working_fdt, ulong size);
 
 struct extension {
 	char name[32];

-- 
2.43.0


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v2 16/18] boot: pxe_utils: Add extension board devicetree overlay support
  2025-10-09 14:50 [PATCH v2 00/18] Convert extension support to UCLASS and adds its support to boot flows Kory Maincent (TI.com)
                   ` (14 preceding siblings ...)
  2025-10-09 14:50 ` [PATCH v2 15/18] boot: extension: Move overlay apply custom logic to command level Kory Maincent (TI.com)
@ 2025-10-09 14:50 ` Kory Maincent (TI.com)
  2025-10-09 16:37   ` Kory Maincent
  2025-10-10 11:13   ` Simon Glass
  2025-10-09 14:50 ` [PATCH v2 17/18] boot: bootmeth_efi: Refactor distro_efi_try_bootflow_files return logic Kory Maincent (TI.com)
  2025-10-09 14:50 ` [PATCH v2 18/18] boot: bootmeth_efi: Add extension board devicetree overlay support Kory Maincent (TI.com)
  17 siblings, 2 replies; 36+ messages in thread
From: Kory Maincent (TI.com) @ 2025-10-09 14:50 UTC (permalink / raw)
  To: Tom Rini, Simon Glass, Jagan Teki, Andre Przywara, Hans de Goede,
	Mario Six, Stefano Babic, Fabio Estevam, NXP i.MX U-Boot Team,
	Ying-Chun Liu (PaulLiu)
  Cc: Roger Quadros, Bajjuri Praneeth, Thomas Petazzoni, u-boot,
	Kory Maincent (TI.com)

Add support for scanning and applying extension board devicetree
overlays during PXE boot. After loading the main board devicetree,
the system now scans for available extension boards and applies their
overlays automatically.

This enables dynamic hardware configuration for systems with extension
boards during boot scenarios which are using pxe_utils.

Signed-off-by: Kory Maincent (TI.com) <kory.maincent@bootlin.com>
---
 boot/pxe_utils.c | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 90 insertions(+)

diff --git a/boot/pxe_utils.c b/boot/pxe_utils.c
index eb4d7723481..f28fddfd8b3 100644
--- a/boot/pxe_utils.c
+++ b/boot/pxe_utils.c
@@ -10,6 +10,7 @@
 #include <command.h>
 #include <dm.h>
 #include <env.h>
+#include <extension_board.h>
 #include <image.h>
 #include <log.h>
 #include <malloc.h>
@@ -432,6 +433,93 @@ skip_overlay:
 }
 #endif
 
+/*
+ * label_boot_extension - scan extension boards and load overlay associated
+ */
+
+static void label_boot_extension(struct pxe_context *ctx,
+				 struct pxe_label *label)
+{
+#if CONFIG_IS_ENABLED(SUPPORT_EXTENSION_SCAN)
+	const struct extension *extension;
+	struct fdt_header *working_fdt;
+	struct alist *extension_list;
+	int ret, dir_len, len;
+	char *overlay_dir;
+	const char *slash;
+	ulong fdt_addr;
+
+	ret = extension_scan();
+	if (ret < 0)
+		return;
+
+	extension_list = extension_get_list();
+	if (!extension_list)
+		return;
+
+	/* Get the main fdt and map it */
+	fdt_addr = env_get_hex("fdt_addr_r", 0);
+	working_fdt = map_sysmem(fdt_addr, 0);
+	if (fdt_check_header(working_fdt))
+		return;
+
+	/* Use fdtdir for now as the overlay devicetree directory */
+	if (label->fdtdir) {
+		len = strlen(label->fdtdir);
+		if (!len)
+			slash = "./";
+		else if (label->fdtdir[len - 1] != '/')
+			slash = "/";
+		else
+			slash = "";
+
+		dir_len = strlen(label->fdtdir) + strlen(slash) + 1;
+		overlay_dir = calloc(1, len);
+		if (!overlay_dir)
+			return;
+
+		snprintf(overlay_dir, dir_len, "%s%s", label->fdtdir,
+			 slash);
+	} else {
+		dir_len = 2;
+		snprintf(overlay_dir, dir_len, "/");
+	}
+
+	alist_for_each(extension, extension_list) {
+		char *overlay_file;
+		ulong size;
+
+		len = dir_len + strlen(extension->overlay);
+		overlay_file = calloc(1, len);
+		if (!overlay_file)
+			goto cleanup;
+
+		snprintf(overlay_file, len, "%s%s", overlay_dir,
+			 extension->overlay);
+
+		/* Load extension overlay file */
+		ret = get_relfile_envaddr(ctx, overlay_file,
+					  "extension_overlay_addr",
+					  (enum bootflow_img_t)IH_TYPE_FLATDT,
+					  &size);
+		if (ret < 0) {
+			free(overlay_file);
+			continue;
+		}
+
+		ret = extension_apply(working_fdt, size);
+		if (ret) {
+			free(overlay_file);
+			continue;
+		}
+		free(overlay_file);
+	}
+
+cleanup:
+	free(overlay_dir);
+#endif
+}
+
 /**
  * label_boot() - Boot according to the contents of a pxe_label
  *
@@ -685,6 +773,8 @@ static int label_boot(struct pxe_context *ctx, struct pxe_label *label)
 			if (label->fdtoverlays)
 				label_boot_fdtoverlay(ctx, label);
 #endif
+			label_boot_extension(ctx, label);
+
 		} else {
 			bootm_argv[3] = NULL;
 		}

-- 
2.43.0


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v2 17/18] boot: bootmeth_efi: Refactor distro_efi_try_bootflow_files return logic
  2025-10-09 14:50 [PATCH v2 00/18] Convert extension support to UCLASS and adds its support to boot flows Kory Maincent (TI.com)
                   ` (15 preceding siblings ...)
  2025-10-09 14:50 ` [PATCH v2 16/18] boot: pxe_utils: Add extension board devicetree overlay support Kory Maincent (TI.com)
@ 2025-10-09 14:50 ` Kory Maincent (TI.com)
  2025-10-10 11:13   ` Simon Glass
  2025-10-09 14:50 ` [PATCH v2 18/18] boot: bootmeth_efi: Add extension board devicetree overlay support Kory Maincent (TI.com)
  17 siblings, 1 reply; 36+ messages in thread
From: Kory Maincent (TI.com) @ 2025-10-09 14:50 UTC (permalink / raw)
  To: Tom Rini, Simon Glass, Jagan Teki, Andre Przywara, Hans de Goede,
	Mario Six, Stefano Babic, Fabio Estevam, NXP i.MX U-Boot Team,
	Ying-Chun Liu (PaulLiu)
  Cc: Roger Quadros, Bajjuri Praneeth, Thomas Petazzoni, u-boot,
	Kory Maincent (TI.com)

Simplify the return path in distro_efi_try_bootflow_files() to prepare
for adding extension board support in a subsequent commit.

Signed-off-by: Kory Maincent (TI.com) <kory.maincent@bootlin.com>
---
 boot/bootmeth_efi.c | 31 ++++++++++++++++---------------
 1 file changed, 16 insertions(+), 15 deletions(-)

diff --git a/boot/bootmeth_efi.c b/boot/bootmeth_efi.c
index 0af23df3a4a..64de5c08b7b 100644
--- a/boot/bootmeth_efi.c
+++ b/boot/bootmeth_efi.c
@@ -148,25 +148,26 @@ static int distro_efi_try_bootflow_files(struct udevice *dev,
 			return log_msg_ret("fil", -ENOMEM);
 	}
 
-	if (!ret) {
-		bflow->fdt_size = size;
-		bflow->fdt_addr = fdt_addr;
-
-		/*
-		 * TODO: Apply extension overlay
-		 *
-		 * Here we need to load and apply the extension overlay. This is
-		 * not implemented. See do_extension_apply(). The extension
-		 * stuff needs an implementation in boot/extension.c so it is
-		 * separate from the command code. Really the extension stuff
-		 * should use the device tree and a uclass / driver interface
-		 * rather than implementing its own list
-		 */
-	} else {
+	if (ret) {
 		log_debug("No device tree available\n");
 		bflow->flags |= BOOTFLOWF_USE_BUILTIN_FDT;
+		return 0;
 	}
 
+	bflow->fdt_size = size;
+	bflow->fdt_addr = fdt_addr;
+
+	/*
+	 * TODO: Apply extension overlay
+	 *
+	 * Here we need to load and apply the extension overlay. This is
+	 * not implemented. See do_extension_apply(). The extension
+	 * stuff needs an implementation in boot/extension.c so it is
+	 * separate from the command code. Really the extension stuff
+	 * should use the device tree and a uclass / driver interface
+	 * rather than implementing its own list
+	 */
+
 	return 0;
 }
 

-- 
2.43.0


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v2 18/18] boot: bootmeth_efi: Add extension board devicetree overlay support
  2025-10-09 14:50 [PATCH v2 00/18] Convert extension support to UCLASS and adds its support to boot flows Kory Maincent (TI.com)
                   ` (16 preceding siblings ...)
  2025-10-09 14:50 ` [PATCH v2 17/18] boot: bootmeth_efi: Refactor distro_efi_try_bootflow_files return logic Kory Maincent (TI.com)
@ 2025-10-09 14:50 ` Kory Maincent (TI.com)
  2025-10-10 11:13   ` Simon Glass
  17 siblings, 1 reply; 36+ messages in thread
From: Kory Maincent (TI.com) @ 2025-10-09 14:50 UTC (permalink / raw)
  To: Tom Rini, Simon Glass, Jagan Teki, Andre Przywara, Hans de Goede,
	Mario Six, Stefano Babic, Fabio Estevam, NXP i.MX U-Boot Team,
	Ying-Chun Liu (PaulLiu)
  Cc: Roger Quadros, Bajjuri Praneeth, Thomas Petazzoni, u-boot,
	Kory Maincent (TI.com)

Add support for scanning and applying extension board devicetree
overlays during EFI boot. After loading the main board devicetree,
the system now scans for available extension boards and applies their
overlays automatically.

Signed-off-by: Kory Maincent (TI.com) <kory.maincent@bootlin.com>
---

Not yet tested, need to find a board with extension boards and supporting
EFI boot. Roger Quadros could you test it on your side?
---
 boot/bootmeth_efi.c | 67 ++++++++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 56 insertions(+), 11 deletions(-)

diff --git a/boot/bootmeth_efi.c b/boot/bootmeth_efi.c
index 64de5c08b7b..13726a13e07 100644
--- a/boot/bootmeth_efi.c
+++ b/boot/bootmeth_efi.c
@@ -16,6 +16,7 @@
 #include <efi.h>
 #include <efi_loader.h>
 #include <env.h>
+#include <extension_board.h>
 #include <fs.h>
 #include <malloc.h>
 #include <mapmem.h>
@@ -99,8 +100,11 @@ static int distro_efi_check(struct udevice *dev, struct bootflow_iter *iter)
 static int distro_efi_try_bootflow_files(struct udevice *dev,
 					 struct bootflow *bflow)
 {
+	ulong fdt_addr, size, overlay_addr;
+	const struct extension *extension;
+	struct fdt_header *working_fdt;
 	struct blk_desc *desc = NULL;
-	ulong fdt_addr, size;
+	struct alist *extension_list;
 	char fname[256];
 	int ret, seq;
 
@@ -157,16 +161,57 @@ static int distro_efi_try_bootflow_files(struct udevice *dev,
 	bflow->fdt_size = size;
 	bflow->fdt_addr = fdt_addr;
 
-	/*
-	 * TODO: Apply extension overlay
-	 *
-	 * Here we need to load and apply the extension overlay. This is
-	 * not implemented. See do_extension_apply(). The extension
-	 * stuff needs an implementation in boot/extension.c so it is
-	 * separate from the command code. Really the extension stuff
-	 * should use the device tree and a uclass / driver interface
-	 * rather than implementing its own list
-	 */
+	if (!CONFIG_IS_ENABLED(SUPPORT_EXTENSION_SCAN))
+		return 0;
+
+	ret = extension_scan();
+	if (ret < 0)
+		return 0;
+
+	extension_list = extension_get_list();
+	if (!extension_list)
+		return 0;
+
+	working_fdt = map_sysmem(fdt_addr, 0);
+	if (fdt_check_header(working_fdt))
+		return 0;
+
+	overlay_addr = env_get_hex("extension_overlay_addr", 0);
+	if (!overlay_addr) {
+		log_debug("Environment extension_overlay_addr is missing\n");
+		return 0;
+	}
+
+	alist_for_each(extension, extension_list) {
+		char *overlay_file;
+		int len;
+
+		len = sizeof(EFI_DIRNAME) + strlen(extension->overlay);
+		overlay_file = calloc(1, len);
+		if (!overlay_file)
+			return -ENOMEM;
+
+		snprintf(overlay_file, len, "%s%s", EFI_DIRNAME,
+			 extension->overlay);
+
+		ret = bootmeth_common_read_file(dev, bflow, overlay_file,
+						overlay_addr,
+						(enum bootflow_img_t)IH_TYPE_FLATDT,
+						&size);
+		if (ret) {
+			log_debug("No device tree overlay\n");
+			free(overlay_file);
+			continue;
+		}
+
+		ret = extension_apply(working_fdt, size);
+		if (ret) {
+			free(overlay_file);
+			continue;
+		}
+		bflow->fdt_size += size;
+		free(overlay_file);
+	}
 
 	return 0;
 }

-- 
2.43.0


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* Re: [PATCH v2 16/18] boot: pxe_utils: Add extension board devicetree overlay support
  2025-10-09 14:50 ` [PATCH v2 16/18] boot: pxe_utils: Add extension board devicetree overlay support Kory Maincent (TI.com)
@ 2025-10-09 16:37   ` Kory Maincent
  2025-10-10 11:13   ` Simon Glass
  1 sibling, 0 replies; 36+ messages in thread
From: Kory Maincent @ 2025-10-09 16:37 UTC (permalink / raw)
  To: Tom Rini, Simon Glass, Jagan Teki, Andre Przywara, Hans de Goede,
	Mario Six, Stefano Babic, Fabio Estevam, NXP i.MX U-Boot Team,
	Ying-Chun Liu (PaulLiu)
  Cc: Roger Quadros, Bajjuri Praneeth, Thomas Petazzoni, u-boot

On Thu, 09 Oct 2025 16:50:52 +0200
"Kory Maincent (TI.com)" <kory.maincent@bootlin.com> wrote:

> Add support for scanning and applying extension board devicetree
> overlays during PXE boot. After loading the main board devicetree,
> the system now scans for available extension boards and applies their
> overlays automatically.
> 
> This enables dynamic hardware configuration for systems with extension
> boards during boot scenarios which are using pxe_utils.
> 
> Signed-off-by: Kory Maincent (TI.com) <kory.maincent@bootlin.com>

...

> +
> +	alist_for_each(extension, extension_list) {
> +		char *overlay_file;
> +		ulong size;
> +
> +		len = dir_len + strlen(extension->overlay);
> +		overlay_file = calloc(1, len);
> +		if (!overlay_file)
> +			goto cleanup;
> +
> +		snprintf(overlay_file, len, "%s%s", overlay_dir,
> +			 extension->overlay);
> +
> +		/* Load extension overlay file */
> +		ret = get_relfile_envaddr(ctx, overlay_file,
> +					  "extension_overlay_addr",
> +					  (enum
> bootflow_img_t)IH_TYPE_FLATDT,
> +					  &size);
> +		if (ret < 0) {

Just figured out that it would be nice to have a warning here if the file is
not loaded or found:
printf("Failed loading overlay %s\n", overlay_file);

> +			free(overlay_file);
> +			continue;
> +		}
> +
> +		ret = extension_apply(working_fdt, size);
> +		if (ret) {
> +			free(overlay_file);
> +			continue;
> +		}
> +		free(overlay_file);
> +	}
-- 
Köry Maincent, Bootlin
Embedded Linux and kernel engineering
https://bootlin.com

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH v2 01/18] MAINTAINERS: Add maintainer for extension board support
  2025-10-09 14:50 ` [PATCH v2 01/18] MAINTAINERS: Add maintainer for extension board support Kory Maincent (TI.com)
@ 2025-10-10 11:13   ` Simon Glass
  2025-10-10 14:13   ` Mattijs Korpershoek
  1 sibling, 0 replies; 36+ messages in thread
From: Simon Glass @ 2025-10-10 11:13 UTC (permalink / raw)
  To: Kory Maincent (TI.com)
  Cc: Tom Rini, Jagan Teki, Andre Przywara, Hans de Goede, Mario Six,
	Stefano Babic, Fabio Estevam, NXP i.MX U-Boot Team,
	Ying-Chun Liu (PaulLiu), Roger Quadros, Bajjuri Praneeth,
	Thomas Petazzoni, u-boot

On Thu, 9 Oct 2025 at 15:50, Kory Maincent (TI.com)
<kory.maincent@bootlin.com> wrote:
>
> Add myself as maintainer for the extension board support that was
> originally added to track ongoing development and maintenance.
>
> Signed-off-by: Kory Maincent (TI.com) <kory.maincent@bootlin.com>
> ---
>  MAINTAINERS | 8 ++++++++
>  1 file changed, 8 insertions(+)
>

Reviewed-by: Simon Glass <sjg@chromium.org>

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH v2 02/18] boot: Move extension board support from cmd/ to boot/
  2025-10-09 14:50 ` [PATCH v2 02/18] boot: Move extension board support from cmd/ to boot/ Kory Maincent (TI.com)
@ 2025-10-10 11:13   ` Simon Glass
  2025-10-10 12:33     ` Kory Maincent
  0 siblings, 1 reply; 36+ messages in thread
From: Simon Glass @ 2025-10-10 11:13 UTC (permalink / raw)
  To: Kory Maincent (TI.com)
  Cc: Tom Rini, Jagan Teki, Andre Przywara, Hans de Goede, Mario Six,
	Stefano Babic, Fabio Estevam, NXP i.MX U-Boot Team,
	Ying-Chun Liu (PaulLiu), Roger Quadros, Bajjuri Praneeth,
	Thomas Petazzoni, u-boot

Hi Kory,

On Thu, 9 Oct 2025 at 15:50, Kory Maincent (TI.com)
<kory.maincent@bootlin.com> wrote:
>
> Relocate extension board support from cmd/ to boot/ directory in
> preparation for converting the extension framework to use UCLASS.
> Also improve code style by applying reverse Christmas tree ordering.
>
> Signed-off-by: Kory Maincent (TI.com) <kory.maincent@bootlin.com>
> ---
>  MAINTAINERS               |  1 +
>  boot/Kconfig              |  3 ++
>  boot/Makefile             |  1 +
>  boot/extension.c          | 97 ++++++++++++++++++++++++++++++++++++++++++++++
>  cmd/Kconfig               |  3 --
>  cmd/extension_board.c     | 99 ++---------------------------------------------
>  include/extension_board.h | 16 ++++++++
>  7 files changed, 122 insertions(+), 98 deletions(-)

Reviewed-by: Simon Glass <sjg@chromium.org>

I didn't know the name for this, but I like this style too. Just in
time for Christmas!

Regards,
Simon

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH v2 03/18] boot: Add UCLASS support for extension boards
  2025-10-09 14:50 ` [PATCH v2 03/18] boot: Add UCLASS support for extension boards Kory Maincent (TI.com)
@ 2025-10-10 11:13   ` Simon Glass
  2025-10-10 13:35     ` Kory Maincent
  0 siblings, 1 reply; 36+ messages in thread
From: Simon Glass @ 2025-10-10 11:13 UTC (permalink / raw)
  To: Kory Maincent (TI.com)
  Cc: Tom Rini, Jagan Teki, Andre Przywara, Hans de Goede, Mario Six,
	Stefano Babic, Fabio Estevam, NXP i.MX U-Boot Team,
	Ying-Chun Liu (PaulLiu), Roger Quadros, Bajjuri Praneeth,
	Thomas Petazzoni, u-boot

Hi Kory,

On Thu, 9 Oct 2025 at 15:51, Kory Maincent (TI.com)
<kory.maincent@bootlin.com> wrote:
>
> Introduce UCLASS-based extension board support to enable more
> standardized and automatic loading of extension board device tree
> overlays in preparation for integration with bootstd and pxe_utils.
>
> Signed-off-by: Kory Maincent (TI.com) <kory.maincent@bootlin.com>
> ---
>  MAINTAINERS                 |   1 +
>  boot/Kconfig                |   3 +
>  boot/Makefile               |   1 +
>  boot/extension-uclass.c     | 196 ++++++++++++++++++++++++++++++++++++++++++++
>  cmd/Kconfig                 |   2 +-
>  cmd/extension_board.c       |  50 ++++++++++-
>  doc/usage/cmd/extension.rst |  24 +++---
>  include/dm/uclass-id.h      |   1 +
>  include/extension_board.h   |  64 +++++++++++++++
>  9 files changed, 326 insertions(+), 16 deletions(-)
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index c67d5ae9d6b..a63ffa14ef5 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -1187,6 +1187,7 @@ M:        Kory Maincent <kory.maincent@bootlin.com>
>  S:     Maintained
>  F:     board/sunxi/chip.c
>  F:     board/ti/common/cape_detect.c
> +F:     boot/extension-uclass.c
>  F:     boot/extension.c
>  F:     cmd/extension_board.c
>  F:     include/extension_board.h
> diff --git a/boot/Kconfig b/boot/Kconfig
> index 62aa301f18f..159da81bec5 100644
> --- a/boot/Kconfig
> +++ b/boot/Kconfig
> @@ -1909,6 +1909,9 @@ endif # OF_LIBFDT
>  config SUPPORT_EXTENSION_SCAN
>          bool
>
> +config SUPPORT_DM_EXTENSION_SCAN
> +        bool
> +
>  config USE_BOOTARGS
>         bool "Enable boot arguments"
>         help
> diff --git a/boot/Makefile b/boot/Makefile
> index f60d13130b1..aa26070fbb8 100644
> --- a/boot/Makefile
> +++ b/boot/Makefile
> @@ -10,6 +10,7 @@ obj-$(CONFIG_CMD_BOOTM) += bootm.o bootm_os.o
>  obj-$(CONFIG_CMD_BOOTZ) += bootm.o bootm_os.o
>  obj-$(CONFIG_CMD_BOOTI) += bootm.o bootm_os.o
>  obj-$(CONFIG_SUPPORT_EXTENSION_SCAN) += extension.o
> +obj-$(CONFIG_SUPPORT_DM_EXTENSION_SCAN) += extension-uclass.o
>
>  obj-$(CONFIG_PXE_UTILS) += pxe_utils.o
>
> diff --git a/boot/extension-uclass.c b/boot/extension-uclass.c
> new file mode 100644
> index 00000000000..9dfbeb60d20
> --- /dev/null
> +++ b/boot/extension-uclass.c
> @@ -0,0 +1,196 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * (C) Copyright 2025 Köry Maincent <kory.maincent@bootlin.com>
> + */
> +
> +#include <alist.h>
> +#include <command.h>
> +#include <dm/device-internal.h>
> +#include <dm/lists.h>
> +#include <dm/uclass.h>
> +#include <env.h>
> +#include <extension_board.h>
> +#include <fdt_support.h>
> +#include <malloc.h>
> +#include <mapmem.h>

nit: Please correct the ordering

https://docs.u-boot.org/en/latest/develop/codingstyle.html#include-files

> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +/* For now, bind the extension device manually if none are found */
> +static struct udevice *extension_get_dev(void)

This should really return the error rather than gobbling it. Normally
we use 'int' as the return value, so:

static int extension_get_dev(struct udevice *devp)

> +{
> +       struct driver *drv = ll_entry_start(struct driver, driver);
> +       const int n_ents = ll_entry_count(struct driver, driver);
> +       struct udevice *dev;
> +       int i, ret;
> +
> +       /* These are not needed before relocation */
> +       if (!(gd->flags & GD_FLG_RELOC))
> +               return NULL;
> +
> +       uclass_first_device(UCLASS_EXTENSION, &dev);
> +       if (dev)
> +               return dev;
> +
> +       /* Create the extension device if not already bound */
> +       for (i = 0; i < n_ents; i++, drv++) {
> +               if (drv->id == UCLASS_EXTENSION) {

If this is really what you want, you might as well just put a
U_BOOT_DRVINFO() declaration in the source. Then driver model does it
for you. We are supposed to use the devicetree, but it seems that that
idea is WIP at best.

> +                       char name[32];
> +
> +                       snprintf(name, sizeof(name), "%s_dev", drv->name);
> +                       ret = device_bind_driver(gd->dm_root, drv->name,
> +                                                name, &dev);
> +                       if (ret) {
> +                               printf("Bind extension driver %s error=%d\n",
> +                                      drv->name, ret);
> +                               return NULL;
> +                       }
> +
> +                       ret = device_probe(dev);
> +                       if (ret) {
> +                               printf("Probe extension driver %s error=%d\n",
> +                                      drv->name, ret);
> +                               return NULL;
> +                       }
> +
> +                       /* We manage only one extension driver for now */
> +                       return dev;
> +               }
> +       }
> +
> +       return NULL;
> +}
> +
> +struct alist *dm_extension_get_list(void)
> +{
> +       struct udevice *dev = extension_get_dev();
> +
> +       if (!dev)
> +               return NULL;
> +
> +       return dev_get_priv(dev);
> +}
> +
> +int dm_extension_probe(struct udevice *dev)
> +{
> +       struct alist *extension_list = dev_get_priv(dev);
> +
> +       alist_init_struct(extension_list, struct extension);
> +       return 0;
> +}
> +
> +int dm_extension_remove(struct udevice *dev)
> +{
> +       struct alist *extension_list = dev_get_priv(dev);
> +
> +       alist_uninit(extension_list);
> +       return 0;
> +}
> +
> +int dm_extension_scan(void)
> +{
> +       struct alist *extension_list = dm_extension_get_list();
> +       struct udevice *dev = extension_get_dev();
> +       const struct extension_ops *ops;
> +
> +       if (!dev || !extension_list)
> +               return -ENODEV;
> +
> +       ops = device_get_ops(dev);

extension_get_ops()

> +       if (!ops->scan)
> +               return -ENODEV;

That is normally -ENOSYS - at this point we have a device, it's just
that it doesn't have the require method.

But it seem strange to me to allow a device that has no means to scan.

> +
> +       alist_empty(extension_list);
> +       return ops->scan(extension_list);
> +}
> +
> +static int _extension_apply(const struct extension *extension)
> +{
> +       ulong extrasize, overlay_addr;
> +       struct fdt_header *blob;
> +       char *overlay_cmd;
> +       int ret;
> +
> +       if (!working_fdt) {
> +               printf("No FDT memory address configured. Please configure\n"
> +                      "the FDT address via \"fdt addr <address>\" command.\n");
> +               return -EINVAL;
> +       }
> +
> +       overlay_cmd = env_get("extension_overlay_cmd");
> +       if (!overlay_cmd) {
> +               printf("Environment extension_overlay_cmd is missing\n");
> +               return -EINVAL;
> +       }
> +
> +       overlay_addr = env_get_hex("extension_overlay_addr", 0);
> +       if (!overlay_addr) {
> +               printf("Environment extension_overlay_addr is missing\n");
> +               return -EINVAL;
> +       }
> +
> +       env_set("extension_overlay_name", extension->overlay);
> +       ret = run_command(overlay_cmd, 0);
> +       if (ret)
> +               return ret;
> +
> +       extrasize = env_get_hex("filesize", 0);
> +       if (!extrasize)
> +               return -EINVAL;
> +
> +       fdt_shrink_to_minimum(working_fdt, extrasize);
> +
> +       blob = map_sysmem(overlay_addr, 0);
> +       if (!fdt_valid(&blob)) {
> +               printf("Invalid overlay devicetree %s\n", extension->overlay);
> +               return -EINVAL;
> +       }
> +
> +       /* Apply method prints messages on error */
> +       ret = fdt_overlay_apply_verbose(working_fdt, blob);
> +       if (ret)
> +               printf("Failed to apply overlay %s\n", extension->overlay);
> +
> +       return ret;
> +}
> +
> +int dm_extension_apply(int extension_num)
> +{
> +       struct alist *extension_list = dm_extension_get_list();
> +       const struct extension *extension;
> +
> +       if (!extension_list)
> +               return -ENODEV;

-ENODEV has a special meaning with driver model, which is that there
is no device. I think -ENOENT would be better.

> +
> +       extension = alist_get(extension_list, extension_num,
> +                             struct extension);
> +       if (!extension) {
> +               printf("Wrong extension number\n");
> +               return -ENODEV;

-EINVAL ?

> +       }
> +
> +       return _extension_apply(extension);
> +}
> +
> +int dm_extension_apply_all(void)
> +{
> +       struct alist *extension_list = dm_extension_get_list();
> +       const struct extension *extension;
> +       int ret;
> +
> +       if (!extension_list)
> +               return -ENODEV;

-ENOENT

> +
> +       alist_for_each(extension, extension_list) {
> +               ret = _extension_apply(extension);
> +               if (ret)
> +                       return ret;
> +       }
> +
> +       return 0;
> +}
> +
> +UCLASS_DRIVER(extension) = {
> +       .name   = "extension",
> +       .id     = UCLASS_EXTENSION,
> +};
> diff --git a/cmd/Kconfig b/cmd/Kconfig
> index 986eeeba807..721bdb87c8a 100644
> --- a/cmd/Kconfig
> +++ b/cmd/Kconfig
> @@ -548,7 +548,7 @@ config CMD_FDT
>  config CMD_EXTENSION
>         bool "Extension board management command"
>         select CMD_FDT
> -       depends on SUPPORT_EXTENSION_SCAN
> +       depends on SUPPORT_EXTENSION_SCAN || SUPPORT_DM_EXTENSION_SCAN
>         help
>           Enables the "extension" command, which allows to detect
>           extension boards connected to the system, and apply
> diff --git a/cmd/extension_board.c b/cmd/extension_board.c
> index 78d937ee6b6..d70394f36c7 100644
> --- a/cmd/extension_board.c
> +++ b/cmd/extension_board.c
> @@ -4,6 +4,7 @@
>   * Köry Maincent, Bootlin, <kory.maincent@bootlin.com>
>   */
>
> +#include <alist.h>
>  #include <exports.h>
>  #include <command.h>
>  #include <extension_board.h>
> @@ -13,9 +14,28 @@ LIST_HEAD(extension_list);
>  static int do_extension_list(struct cmd_tbl *cmdtp, int flag,
>                              int argc, char *const argv[])
>  {
> +#if CONFIG_IS_ENABLED(SUPPORT_DM_EXTENSION_SCAN)
> +       struct alist *dm_extension_list;
> +#endif
>         struct extension *extension;
>         int i = 0;
>
> +#if CONFIG_IS_ENABLED(SUPPORT_DM_EXTENSION_SCAN)

Is it possible to use if() ? Perhaps at the end of your series, when
all the conversions are done and you can delete the old code?

> +       dm_extension_list = dm_extension_get_list();
> +
> +       if (!alist_get_ptr(dm_extension_list, 0)) {
> +               printf("No extension registered - Please run \"extension scan\"\n");
> +               return CMD_RET_SUCCESS;
> +       }
> +
> +       alist_for_each(extension, dm_extension_list) {
> +               printf("Extension %d: %s\n", i++, extension->name);
> +               printf("\tManufacturer: \t\t%s\n", extension->owner);
> +               printf("\tVersion: \t\t%s\n", extension->version);
> +               printf("\tDevicetree overlay: \t%s\n", extension->overlay);
> +               printf("\tOther information: \t%s\n", extension->other);
> +       }
> +#else
>         if (list_empty(&extension_list)) {
>                 printf("No extension registered - Please run \"extension scan\"\n");
>                 return CMD_RET_SUCCESS;
> @@ -28,6 +48,7 @@ static int do_extension_list(struct cmd_tbl *cmdtp, int flag,
>                 printf("\tDevicetree overlay: \t%s\n", extension->overlay);
>                 printf("\tOther information: \t%s\n", extension->other);
>         }
> +#endif
>         return CMD_RET_SUCCESS;
>  }
>
> @@ -36,9 +57,19 @@ static int do_extension_scan(struct cmd_tbl *cmdtp, int flag,
>  {
>         int extension_num;
>
> +#if CONFIG_IS_ENABLED(SUPPORT_DM_EXTENSION_SCAN)

I'm hoping you can use if() instead of #if for all of these?

> +       extension_num = dm_extension_scan();
> +       if (extension_num == -ENODEV)
> +               extension_num = 0;
> +       else if (extension_num < 0)
> +               return CMD_RET_FAILURE;
> +
> +       printf("Found %d extension board(s).\n", extension_num);
> +#else
>         extension_num = extension_scan(true);
> -       if (extension_num < 0)
> +       if (extension_num < 0 && extension_num != -ENODEV)
>                 return CMD_RET_FAILURE;
> +#endif
>
>         return CMD_RET_SUCCESS;
>  }
> @@ -46,22 +77,34 @@ static int do_extension_scan(struct cmd_tbl *cmdtp, int flag,
>  static int do_extension_apply(struct cmd_tbl *cmdtp, int flag,
>                               int argc, char *const argv[])
>  {
> +#if !CONFIG_IS_ENABLED(SUPPORT_DM_EXTENSION_SCAN)
>         struct extension *extension = NULL;
> -       int i = 0, extension_id, ret;
>         struct list_head *entry;
> +       int i = 0;
> +#endif
> +       int extension_id, ret;
>
>         if (argc < 2)
>                 return CMD_RET_USAGE;
>
>         if (strcmp(argv[1], "all") == 0) {
>                 ret = CMD_RET_FAILURE;
> +#if CONFIG_IS_ENABLED(SUPPORT_DM_EXTENSION_SCAN)
> +               if (dm_extension_apply_all())
> +                       return CMD_RET_FAILURE;
> +#else
>                 list_for_each_entry(extension, &extension_list, list) {
>                         ret = extension_apply(extension);
>                         if (ret != CMD_RET_SUCCESS)
>                                 break;
>                 }
> +#endif
>         } else {
>                 extension_id = simple_strtol(argv[1], NULL, 10);
> +#if CONFIG_IS_ENABLED(SUPPORT_DM_EXTENSION_SCAN)
> +               if (dm_extension_apply(extension_id))
> +                       return CMD_RET_FAILURE;
> +#else
>                 list_for_each(entry, &extension_list) {
>                         if (i == extension_id) {
>                                 extension = list_entry(entry, struct extension,  list);
> @@ -76,9 +119,10 @@ static int do_extension_apply(struct cmd_tbl *cmdtp, int flag,
>                 }
>
>                 ret = extension_apply(extension);
> +#endif
>         }
>
> -       return ret;
> +       return CMD_RET_SUCCESS;

or just 0

>  }
>
>  static struct cmd_tbl cmd_extension[] = {
> diff --git a/doc/usage/cmd/extension.rst b/doc/usage/cmd/extension.rst
> index 4c261e74951..d82c3fbef0a 100644
> --- a/doc/usage/cmd/extension.rst
> +++ b/doc/usage/cmd/extension.rst
> @@ -25,9 +25,8 @@ Device Tree overlays depending on the detected extension boards.
>
>  The "extension" command comes with three sub-commands:
>
> - - "extension scan" makes the generic code call the board-specific
> -   extension_board_scan() function to retrieve the list of detected
> -   extension boards.
> + - "extension scan" makes the generic code call a board-specific extension
> +   function to retrieve the list of detected extension boards.
>
>   - "extension list" allows to list the detected extension boards.
>
> @@ -98,17 +97,18 @@ Simple extension_board_scan function example
>
>  .. code-block:: c
>
> -    int extension_board_scan(struct list_head *extension_list)
> +    static int foo_extension_board_scan(struct alist *extension_list)
>      {
> -        struct extension *extension;
> +        struct extension extension = {0};
>
> -        extension = calloc(1, sizeof(struct extension));
> -        snprintf(extension->overlay, sizeof(extension->overlay), "overlay.dtbo");
> -        snprintf(extension->name, sizeof(extension->name), "extension board");
> -        snprintf(extension->owner, sizeof(extension->owner), "sandbox");
> -        snprintf(extension->version, sizeof(extension->version), "1.1");
> -        snprintf(extension->other, sizeof(extension->other), "Extension board information");
> -        list_add_tail(&extension->list, extension_list);
> +        snprintf(extension.overlay, sizeof(extension.overlay), "overlay.dtbo");
> +        snprintf(extension.name, sizeof(extension.name), "extension board");
> +        snprintf(extension.owner, sizeof(extension.owner), "sandbox");
> +        snprintf(extension.version, sizeof(extension.version), "1.1");
> +        snprintf(extension.other, sizeof(extension.other), "Extension board information");
> +        alist_add(extension_list, extension);

This can fail, so:

if (!alist_add(...))
   return -ENOMEM

>
>          return 1;
>      }
> +
> +    U_BOOT_EXTENSION(foo_extension_name, foo_extension_board_scan);
> diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
> index 6be59093160..eb6416b5917 100644
> --- a/include/dm/uclass-id.h
> +++ b/include/dm/uclass-id.h
> @@ -63,6 +63,7 @@ enum uclass_id {
>         UCLASS_ETH,             /* Ethernet device */
>         UCLASS_ETH_PHY,         /* Ethernet PHY device */
>         UCLASS_EXTCON,          /* External Connector Class */
> +       UCLASS_EXTENSION,       /* Extension board */
>         UCLASS_FFA,             /* Arm Firmware Framework for Armv8-A */
>         UCLASS_FFA_EMUL,                /* sandbox FF-A device emulator */
>         UCLASS_FIRMWARE,        /* Firmware */
> diff --git a/include/extension_board.h b/include/extension_board.h
> index 3f70416f005..78139cd7489 100644
> --- a/include/extension_board.h
> +++ b/include/extension_board.h
> @@ -8,9 +8,51 @@
>  #define __EXTENSION_SUPPORT_H
>
>  #include <linux/list.h>
> +#include <alist.h>
> +#include <dm/device.h>
>
>  extern struct list_head extension_list;
>
> +/**
> + * dm_extension_get_list - Get the extension list
> + * Return: The extension alist pointer, or NULL if no such list exists.

caller must free the list?

> + */
> +struct alist *dm_extension_get_list(void);

Is this the list of all extensions from all extension devices?

> +
> +/**
> + * dm_extension_probe - Probe extension device
> + * @dev: Extension device that needs to be probed
> + * Return: Zero on success, negative on failure.
> + */
> +int dm_extension_probe(struct udevice *dev);
> +
> +/**
> + * dm_extension_remove - Remove extension device
> + * @dev: Extension device that needs to be removed
> + * Return: Zero on success, negative on failure.
> + */
> +int dm_extension_remove(struct udevice *dev);
> +
> +/**
> + * dm_extension_scan - Scan extension boards available.
> + * Return: Zero on success, negative on failure.
> + */
> +int dm_extension_scan(void);
> +
> +/**
> + * dm_extension_apply - Apply extension board overlay to the devicetree
> + * @extension_num: Extension number to be applied
> + * Return: Zero on success, negative on failure.
> + */
> +int dm_extension_apply(int extension_num);

The uclass should have a method like apply(struct uclass *dev, int
extension_num). Is the numbering global across all devices?

> +
> +/**
> + * dm_extension_apply_all - Apply all extension board overlays to the
> + *                         devicetree
> + * Return: Zero on success, negative on failure.
> + */
> +int dm_extension_apply_all(void);
> +
>  struct extension {
>         struct list_head list;
>         char name[32];
> @@ -20,6 +62,28 @@ struct extension {
>         char other[32];
>  };

At some point in this series, please comment this struct

>
> +struct extension_ops {
> +       /**
> +        * scan - Add system-specific function to scan extension boards.
> +        * @dev: extension device to use

need to document extension_list here - I believe it is a list of
struct extension? Or is it struct extension * ?

> +        * Return: The number of extension or a negative value in case of
> +        *         error.
> +        */
> +       int (*scan)(struct alist *extension_list);

This is a bit of a strange uclass function! Since you are probing
drivers in this uclass, you can iterate through them using
uclass_foreach...() etc.

I am guessing that you just need to add a struct udevice * as the first arg.

> +};

We should have an extension_get_ops() and extension_scan() stub as
well, for calling this. See how other uclasses do this.

> +
> +#define U_BOOT_EXTENSION(_name, _scan_func) \
> +       U_BOOT_DRIVER(_name) = { \
> +               .name = #_name, \
> +               .id = UCLASS_EXTENSION, \
> +               .probe = dm_extension_probe, \
> +               .remove = dm_extension_remove, \
> +               .ops = &(struct extension_ops) { \
> +                      .scan = _scan_func, \
> +                      }, \
> +               .priv_auto = sizeof(struct alist), \
> +       }
> +
>  /**
>   * extension_board_scan - Add system-specific function to scan extension board.
>   * @param extension_list       List of extension board information to update.
>
> --
> 2.43.0
>

Regards,
Simon

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH v2 10/18] board: sandbox: Improve extension board scan implementation
  2025-10-09 14:50 ` [PATCH v2 10/18] board: sandbox: Improve extension board scan implementation Kory Maincent (TI.com)
@ 2025-10-10 11:13   ` Simon Glass
  0 siblings, 0 replies; 36+ messages in thread
From: Simon Glass @ 2025-10-10 11:13 UTC (permalink / raw)
  To: Kory Maincent (TI.com)
  Cc: Tom Rini, Jagan Teki, Andre Przywara, Hans de Goede, Mario Six,
	Stefano Babic, Fabio Estevam, NXP i.MX U-Boot Team,
	Ying-Chun Liu (PaulLiu), Roger Quadros, Bajjuri Praneeth,
	Thomas Petazzoni, u-boot

On Thu, 9 Oct 2025 at 15:51, Kory Maincent (TI.com)
<kory.maincent@bootlin.com> wrote:
>
> Enhance the extension board scanning code in sandbox with better error
> handling and code organization.
>
> Signed-off-by: Kory Maincent (TI.com) <kory.maincent@bootlin.com>
> ---
>  board/sandbox/sandbox.c | 6 +++++-
>  1 file changed, 5 insertions(+), 1 deletion(-)
>

Reviewed-by: Simon Glass <sjg@chromium.org>

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH v2 11/18] board: sandbox: Convert extension support to UCLASS framework
  2025-10-09 14:50 ` [PATCH v2 11/18] board: sandbox: Convert extension support to UCLASS framework Kory Maincent (TI.com)
@ 2025-10-10 11:13   ` Simon Glass
  0 siblings, 0 replies; 36+ messages in thread
From: Simon Glass @ 2025-10-10 11:13 UTC (permalink / raw)
  To: Kory Maincent (TI.com)
  Cc: Tom Rini, Jagan Teki, Andre Przywara, Hans de Goede, Mario Six,
	Stefano Babic, Fabio Estevam, NXP i.MX U-Boot Team,
	Ying-Chun Liu (PaulLiu), Roger Quadros, Bajjuri Praneeth,
	Thomas Petazzoni, u-boot

On Thu, 9 Oct 2025 at 15:51, Kory Maincent (TI.com)
<kory.maincent@bootlin.com> wrote:
>
> Migrate sandbox extension board detection from legacy implementation to
> the new UCLASS-based extension board framework.
>
> Signed-off-by: Kory Maincent (TI.com) <kory.maincent@bootlin.com>
> ---
>  arch/Kconfig            |  2 +-
>  board/sandbox/sandbox.c | 24 ++++++++++++------------
>  2 files changed, 13 insertions(+), 13 deletions(-)

Reviewed-by: Simon Glass <sjg@chromium.org>

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH v2 14/18] boot: Remove legacy extension board support
  2025-10-09 14:50 ` [PATCH v2 14/18] boot: Remove legacy extension board support Kory Maincent (TI.com)
@ 2025-10-10 11:13   ` Simon Glass
  0 siblings, 0 replies; 36+ messages in thread
From: Simon Glass @ 2025-10-10 11:13 UTC (permalink / raw)
  To: Kory Maincent (TI.com)
  Cc: Tom Rini, Jagan Teki, Andre Przywara, Hans de Goede, Mario Six,
	Stefano Babic, Fabio Estevam, NXP i.MX U-Boot Team,
	Ying-Chun Liu (PaulLiu), Roger Quadros, Bajjuri Praneeth,
	Thomas Petazzoni, u-boot

On Thu, 9 Oct 2025 at 15:51, Kory Maincent (TI.com)
<kory.maincent@bootlin.com> wrote:
>
> Remove the legacy extension board implementation now that all boards
> have been converted to use the new UCLASS-based framework. This
> eliminates 223 lines of legacy code while preserving functionality
> through the modern driver model approach.
>
> Signed-off-by: Kory Maincent (TI.com) <kory.maincent@bootlin.com>
> ---
>
> Changes in v2:
> - Remove a missing DM_EXTENSION_SCAN in cmd/Kconfig
> ---
>  MAINTAINERS                        |  1 -
>  arch/Kconfig                       |  2 +-
>  arch/arm/mach-imx/imx8m/Kconfig    |  4 +-
>  arch/arm/mach-omap2/am33xx/Kconfig |  2 +-
>  arch/arm/mach-omap2/omap5/Kconfig  |  2 +-
>  arch/arm/mach-sunxi/Kconfig        |  2 +-
>  board/ti/common/Makefile           |  2 +-
>  boot/Kconfig                       |  3 --
>  boot/Makefile                      |  3 +-
>  boot/extension-uclass.c            | 18 +++----
>  boot/extension.c                   | 97 --------------------------------------
>  cmd/Kconfig                        |  2 +-
>  cmd/extension_board.c              | 74 ++++-------------------------
>  include/extension_board.h          | 55 ++++++---------------
>  14 files changed, 40 insertions(+), 227 deletions(-)

Reviewed-by: Simon Glass <sjg@chromium.org>

This is a really nice way of doing it, doing the conversion and then
removing at the end.

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH v2 15/18] boot: extension: Move overlay apply custom logic to command level
  2025-10-09 14:50 ` [PATCH v2 15/18] boot: extension: Move overlay apply custom logic to command level Kory Maincent (TI.com)
@ 2025-10-10 11:13   ` Simon Glass
  0 siblings, 0 replies; 36+ messages in thread
From: Simon Glass @ 2025-10-10 11:13 UTC (permalink / raw)
  To: Kory Maincent (TI.com)
  Cc: Tom Rini, Jagan Teki, Andre Przywara, Hans de Goede, Mario Six,
	Stefano Babic, Fabio Estevam, NXP i.MX U-Boot Team,
	Ying-Chun Liu (PaulLiu), Roger Quadros, Bajjuri Praneeth,
	Thomas Petazzoni, u-boot

On Thu, 9 Oct 2025 at 15:51, Kory Maincent (TI.com)
<kory.maincent@bootlin.com> wrote:
>
> The extension_overlay_cmd environment variable approach is specific to
> the U-Boot extension_board command, while other boot flows (pxe_utils,
> bootstd) handle overlay loading differently.
>
> Move the extension_overlay_cmd execution out of the core extension
> framework to the command level. This decouples the framework from
> command-specific behavior and prepares for future extension support
> in other boot flows.
>
> Signed-off-by: Kory Maincent (TI.com) <kory.maincent@bootlin.com>
> ---
>  boot/extension-uclass.c   | 68 +++--------------------------------
>  cmd/extension_board.c     | 92 +++++++++++++++++++++++++++++++++++++++++++++--
>  include/extension_board.h | 12 ++-----
>  3 files changed, 98 insertions(+), 74 deletions(-)

Reviewed-by: Simon Glass <sjg@chromium.org>

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH v2 16/18] boot: pxe_utils: Add extension board devicetree overlay support
  2025-10-09 14:50 ` [PATCH v2 16/18] boot: pxe_utils: Add extension board devicetree overlay support Kory Maincent (TI.com)
  2025-10-09 16:37   ` Kory Maincent
@ 2025-10-10 11:13   ` Simon Glass
  1 sibling, 0 replies; 36+ messages in thread
From: Simon Glass @ 2025-10-10 11:13 UTC (permalink / raw)
  To: Kory Maincent (TI.com)
  Cc: Tom Rini, Jagan Teki, Andre Przywara, Hans de Goede, Mario Six,
	Stefano Babic, Fabio Estevam, NXP i.MX U-Boot Team,
	Ying-Chun Liu (PaulLiu), Roger Quadros, Bajjuri Praneeth,
	Thomas Petazzoni, u-boot

On Thu, 9 Oct 2025 at 15:51, Kory Maincent (TI.com)
<kory.maincent@bootlin.com> wrote:
>
> Add support for scanning and applying extension board devicetree
> overlays during PXE boot. After loading the main board devicetree,
> the system now scans for available extension boards and applies their
> overlays automatically.
>
> This enables dynamic hardware configuration for systems with extension
> boards during boot scenarios which are using pxe_utils.
>
> Signed-off-by: Kory Maincent (TI.com) <kory.maincent@bootlin.com>
> ---
>  boot/pxe_utils.c | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 90 insertions(+)
>

Reviewed-by: Simon Glass <sjg@chromium.org>

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH v2 17/18] boot: bootmeth_efi: Refactor distro_efi_try_bootflow_files return logic
  2025-10-09 14:50 ` [PATCH v2 17/18] boot: bootmeth_efi: Refactor distro_efi_try_bootflow_files return logic Kory Maincent (TI.com)
@ 2025-10-10 11:13   ` Simon Glass
  0 siblings, 0 replies; 36+ messages in thread
From: Simon Glass @ 2025-10-10 11:13 UTC (permalink / raw)
  To: Kory Maincent (TI.com)
  Cc: Tom Rini, Jagan Teki, Andre Przywara, Hans de Goede, Mario Six,
	Stefano Babic, Fabio Estevam, NXP i.MX U-Boot Team,
	Ying-Chun Liu (PaulLiu), Roger Quadros, Bajjuri Praneeth,
	Thomas Petazzoni, u-boot

On Thu, 9 Oct 2025 at 15:51, Kory Maincent (TI.com)
<kory.maincent@bootlin.com> wrote:
>
> Simplify the return path in distro_efi_try_bootflow_files() to prepare
> for adding extension board support in a subsequent commit.
>
> Signed-off-by: Kory Maincent (TI.com) <kory.maincent@bootlin.com>
> ---
>  boot/bootmeth_efi.c | 31 ++++++++++++++++---------------
>  1 file changed, 16 insertions(+), 15 deletions(-)

Reviewed-by: Simon Glass <sjg@chromium.org>

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH v2 18/18] boot: bootmeth_efi: Add extension board devicetree overlay support
  2025-10-09 14:50 ` [PATCH v2 18/18] boot: bootmeth_efi: Add extension board devicetree overlay support Kory Maincent (TI.com)
@ 2025-10-10 11:13   ` Simon Glass
  0 siblings, 0 replies; 36+ messages in thread
From: Simon Glass @ 2025-10-10 11:13 UTC (permalink / raw)
  To: Kory Maincent (TI.com)
  Cc: Tom Rini, Jagan Teki, Andre Przywara, Hans de Goede, Mario Six,
	Stefano Babic, Fabio Estevam, NXP i.MX U-Boot Team,
	Ying-Chun Liu (PaulLiu), Roger Quadros, Bajjuri Praneeth,
	Thomas Petazzoni, u-boot

On Thu, 9 Oct 2025 at 15:51, Kory Maincent (TI.com)
<kory.maincent@bootlin.com> wrote:
>
> Add support for scanning and applying extension board devicetree
> overlays during EFI boot. After loading the main board devicetree,
> the system now scans for available extension boards and applies their
> overlays automatically.
>
> Signed-off-by: Kory Maincent (TI.com) <kory.maincent@bootlin.com>
> ---
>
> Not yet tested, need to find a board with extension boards and supporting
> EFI boot. Roger Quadros could you test it on your side?
> ---
>  boot/bootmeth_efi.c | 67 ++++++++++++++++++++++++++++++++++++++++++++---------
>  1 file changed, 56 insertions(+), 11 deletions(-)

Very nice!

Reviewed-by: Simon Glass <sjg@chromium.org>

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH v2 02/18] boot: Move extension board support from cmd/ to boot/
  2025-10-10 11:13   ` Simon Glass
@ 2025-10-10 12:33     ` Kory Maincent
  0 siblings, 0 replies; 36+ messages in thread
From: Kory Maincent @ 2025-10-10 12:33 UTC (permalink / raw)
  To: Simon Glass
  Cc: Tom Rini, Jagan Teki, Andre Przywara, Hans de Goede, Mario Six,
	Stefano Babic, Fabio Estevam, NXP i.MX U-Boot Team,
	Ying-Chun Liu (PaulLiu), Roger Quadros, Bajjuri Praneeth,
	Thomas Petazzoni, u-boot

On Fri, 10 Oct 2025 12:13:05 +0100
Simon Glass <sjg@chromium.org> wrote:

> Hi Kory,
> 
> On Thu, 9 Oct 2025 at 15:50, Kory Maincent (TI.com)
> <kory.maincent@bootlin.com> wrote:
> >
> > Relocate extension board support from cmd/ to boot/ directory in
> > preparation for converting the extension framework to use UCLASS.
> > Also improve code style by applying reverse Christmas tree ordering.
> >
> > Signed-off-by: Kory Maincent (TI.com) <kory.maincent@bootlin.com>
> > ---
> >  MAINTAINERS               |  1 +
> >  boot/Kconfig              |  3 ++
> >  boot/Makefile             |  1 +
> >  boot/extension.c          | 97
> > ++++++++++++++++++++++++++++++++++++++++++++++ cmd/Kconfig               |
> > 3 -- cmd/extension_board.c     | 99
> > ++--------------------------------------------- include/extension_board.h |
> > 16 ++++++++ 7 files changed, 122 insertions(+), 98 deletions(-)  
> 
> Reviewed-by: Simon Glass <sjg@chromium.org>
> 
> I didn't know the name for this, but I like this style too. Just in
> time for Christmas!

Ahah I usually write it xmas tree but it seems my brain has written it
differently.

Regards,
-- 
Köry Maincent, Bootlin
Embedded Linux and kernel engineering
https://bootlin.com

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH v2 03/18] boot: Add UCLASS support for extension boards
  2025-10-10 11:13   ` Simon Glass
@ 2025-10-10 13:35     ` Kory Maincent
  2025-10-11  7:20       ` Simon Glass
  0 siblings, 1 reply; 36+ messages in thread
From: Kory Maincent @ 2025-10-10 13:35 UTC (permalink / raw)
  To: Simon Glass
  Cc: Tom Rini, Jagan Teki, Andre Przywara, Hans de Goede, Mario Six,
	Stefano Babic, Fabio Estevam, NXP i.MX U-Boot Team,
	Ying-Chun Liu (PaulLiu), Roger Quadros, Bajjuri Praneeth,
	Thomas Petazzoni, u-boot

On Fri, 10 Oct 2025 12:13:11 +0100
Simon Glass <sjg@chromium.org> wrote:

> Hi Kory,
> 
> On Thu, 9 Oct 2025 at 15:51, Kory Maincent (TI.com)
> <kory.maincent@bootlin.com> wrote:
> >
> > Introduce UCLASS-based extension board support to enable more
> > standardized and automatic loading of extension board device tree
> > overlays in preparation for integration with bootstd and pxe_utils.
> >
> > Signed-off-by: Kory Maincent (TI.com) <kory.maincent@bootlin.com>

...

> > +
> > +#include <alist.h>
> > +#include <command.h>
> > +#include <dm/device-internal.h>
> > +#include <dm/lists.h>
> > +#include <dm/uclass.h>
> > +#include <env.h>
> > +#include <extension_board.h>
> > +#include <fdt_support.h>
> > +#include <malloc.h>
> > +#include <mapmem.h>  
> 
> nit: Please correct the ordering
> 
> https://docs.u-boot.org/en/latest/develop/codingstyle.html#include-files

Oh didn't know this rule.

> > +
> > +DECLARE_GLOBAL_DATA_PTR;
> > +
> > +/* For now, bind the extension device manually if none are found */
> > +static struct udevice *extension_get_dev(void)  
> 
> This should really return the error rather than gobbling it. Normally
> we use 'int' as the return value, so:
> 
> static int extension_get_dev(struct udevice *devp)

You mean rather this then:
static int extension_get_dev(struct udevice **devp)

> 
> > +{
> > +       struct driver *drv = ll_entry_start(struct driver, driver);
> > +       const int n_ents = ll_entry_count(struct driver, driver);
> > +       struct udevice *dev;
> > +       int i, ret;
> > +
> > +       /* These are not needed before relocation */
> > +       if (!(gd->flags & GD_FLG_RELOC))
> > +               return NULL;
> > +
> > +       uclass_first_device(UCLASS_EXTENSION, &dev);
> > +       if (dev)
> > +               return dev;
> > +
> > +       /* Create the extension device if not already bound */
> > +       for (i = 0; i < n_ents; i++, drv++) {
> > +               if (drv->id == UCLASS_EXTENSION) {  
> 
> If this is really what you want, you might as well just put a
> U_BOOT_DRVINFO() declaration in the source. Then driver model does it
> for you. We are supposed to use the devicetree, but it seems that that
> idea is WIP at best.

Oh I will use this MACRO instead.
 
> > +int dm_extension_scan(void)
> > +{
> > +       struct alist *extension_list = dm_extension_get_list();
> > +       struct udevice *dev = extension_get_dev();
> > +       const struct extension_ops *ops;
> > +
> > +       if (!dev || !extension_list)
> > +               return -ENODEV;
> > +
> > +       ops = device_get_ops(dev);  
> 
> extension_get_ops()

Is it really needed as it is used only once.

> 
> > +       if (!ops->scan)
> > +               return -ENODEV;  
> 
> That is normally -ENOSYS - at this point we have a device, it's just
> that it doesn't have the require method.
> 
> But it seem strange to me to allow a device that has no means to scan.

Yes, maybe this check is useless indeed, as it is the only action done by the
board code.

...

> > @@ -13,9 +14,28 @@ LIST_HEAD(extension_list);
> >  static int do_extension_list(struct cmd_tbl *cmdtp, int flag,
> >                              int argc, char *const argv[])
> >  {
> > +#if CONFIG_IS_ENABLED(SUPPORT_DM_EXTENSION_SCAN)
> > +       struct alist *dm_extension_list;
> > +#endif
> >         struct extension *extension;
> >         int i = 0;
> >
> > +#if CONFIG_IS_ENABLED(SUPPORT_DM_EXTENSION_SCAN)  
> 
> Is it possible to use if() ? Perhaps at the end of your series, when
> all the conversions are done and you can delete the old code?

As all these macro check are removed when the conversion is done I didn't
bother to use if() because I would have to take care of define but not used
warnings.

...

> > +/**
> > + * dm_extension_get_list - Get the extension list
> > + * Return: The extension alist pointer, or NULL if no such list exists.  
> 
> caller must free the list?

No.
 
> > + */
> > +struct alist *dm_extension_get_list(void);  
> 
> Is this the list of all extensions from all extension devices?

yes.

> > +/**
> > + * dm_extension_apply - Apply extension board overlay to the devicetree
> > + * @extension_num: Extension number to be applied
> > + * Return: Zero on success, negative on failure.
> > + */
> > +int dm_extension_apply(int extension_num);  
> 
> The uclass should have a method like apply(struct uclass *dev, int
> extension_num). Is the numbering global across all devices?

We currently support only one extension driver loaded at a time, therefore we
don't currently need this uclass parameter.
We will change the API when we will have several scan method possible at the
same time but I can't test it for now. I don't think we will have such cases
soon and maybe the devicetree WIP support will be ok at that time.

> > +
> > +/**
> > + * dm_extension_apply_all - Apply all extension board overlays to the
> > + *                         devicetree
> > + * Return: Zero on success, negative on failure.
> > + */
> > +int dm_extension_apply_all(void);
> > +
> >  struct extension {
> >         struct list_head list;
> >         char name[32];
> > @@ -20,6 +62,28 @@ struct extension {
> >         char other[32];
> >  };  
> 
> At some point in this series, please comment this struct

Ok I will add a patch to add comment on this.

> 
> >
> > +struct extension_ops {
> > +       /**
> > +        * scan - Add system-specific function to scan extension boards.
> > +        * @dev: extension device to use  
> 
> need to document extension_list here - I believe it is a list of
> struct extension? Or is it struct extension * ?

Oop some code leftover here.

> 
> > +        * Return: The number of extension or a negative value in case of
> > +        *         error.
> > +        */
> > +       int (*scan)(struct alist *extension_list);  
> 
> This is a bit of a strange uclass function! Since you are probing
> drivers in this uclass, you can iterate through them using
> uclass_foreach...() etc.
> 
> I am guessing that you just need to add a struct udevice * as the first arg.

As I said there is only one drivers loaded at a time supported for now.  

Regards,
-- 
Köry Maincent, Bootlin
Embedded Linux and kernel engineering
https://bootlin.com

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH v2 01/18] MAINTAINERS: Add maintainer for extension board support
  2025-10-09 14:50 ` [PATCH v2 01/18] MAINTAINERS: Add maintainer for extension board support Kory Maincent (TI.com)
  2025-10-10 11:13   ` Simon Glass
@ 2025-10-10 14:13   ` Mattijs Korpershoek
  1 sibling, 0 replies; 36+ messages in thread
From: Mattijs Korpershoek @ 2025-10-10 14:13 UTC (permalink / raw)
  To: Kory Maincent (TI.com), Tom Rini, Simon Glass, Jagan Teki,
	Andre Przywara, Hans de Goede, Mario Six, Stefano Babic,
	Fabio Estevam, NXP i.MX U-Boot Team, Ying-Chun Liu (PaulLiu)
  Cc: Roger Quadros, Bajjuri Praneeth, Thomas Petazzoni, u-boot,
	Kory Maincent (TI.com)

Hi Kory,

Welcome to the MAINTAINERS file.

On Thu, Oct 09, 2025 at 16:50, "Kory Maincent (TI.com)" <kory.maincent@bootlin.com> wrote:

> Add myself as maintainer for the extension board support that was
> originally added to track ongoing development and maintenance.
>
> Signed-off-by: Kory Maincent (TI.com) <kory.maincent@bootlin.com>

Reviewed-by: Mattijs Korpershoek <mkorpershoek@kernel.org>

> ---
>  MAINTAINERS | 8 ++++++++
>  1 file changed, 8 insertions(+)
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 12043a1f82e..e411e266c94 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -1182,6 +1182,14 @@ F:	scripts/event_dump.py
>  F:	test/common/event.c
>  F:	test/py/tests/test_event_dump.py
>  
> +EXTENSION
> +M:	Kory Maincent <kory.maincent@bootlin.com>
> +S:	Maintained
> +F:	board/sunxi/chip.c
> +F:	board/ti/common/cape_detect.c
> +F:	cmd/extension_board.c
> +F:	include/extension_board.h
> +
>  FASTBOOT
>  M:	Mattijs Korpershoek <mkorpershoek@kernel.org>
>  S:	Maintained
>
> -- 
> 2.43.0

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH v2 03/18] boot: Add UCLASS support for extension boards
  2025-10-10 13:35     ` Kory Maincent
@ 2025-10-11  7:20       ` Simon Glass
  2025-10-13 12:45         ` Kory Maincent
  0 siblings, 1 reply; 36+ messages in thread
From: Simon Glass @ 2025-10-11  7:20 UTC (permalink / raw)
  To: Kory Maincent
  Cc: Tom Rini, Jagan Teki, Andre Przywara, Hans de Goede, Mario Six,
	Stefano Babic, Fabio Estevam, NXP i.MX U-Boot Team,
	Ying-Chun Liu (PaulLiu), Roger Quadros, Bajjuri Praneeth,
	Thomas Petazzoni, u-boot

Hi Kory,

On Fri, 10 Oct 2025 at 14:35, Kory Maincent <kory.maincent@bootlin.com> wrote:
>
> On Fri, 10 Oct 2025 12:13:11 +0100
> Simon Glass <sjg@chromium.org> wrote:
>
> > Hi Kory,
> >
> > On Thu, 9 Oct 2025 at 15:51, Kory Maincent (TI.com)
> > <kory.maincent@bootlin.com> wrote:
> > >
> > > Introduce UCLASS-based extension board support to enable more
> > > standardized and automatic loading of extension board device tree
> > > overlays in preparation for integration with bootstd and pxe_utils.
> > >
> > > Signed-off-by: Kory Maincent (TI.com) <kory.maincent@bootlin.com>
>
> ...
>
> > > +
> > > +#include <alist.h>
> > > +#include <command.h>
> > > +#include <dm/device-internal.h>
> > > +#include <dm/lists.h>
> > > +#include <dm/uclass.h>
> > > +#include <env.h>
> > > +#include <extension_board.h>
> > > +#include <fdt_support.h>
> > > +#include <malloc.h>
> > > +#include <mapmem.h>
> >
> > nit: Please correct the ordering
> >
> > https://docs.u-boot.org/en/latest/develop/codingstyle.html#include-files
>
> Oh didn't know this rule.
>
> > > +
> > > +DECLARE_GLOBAL_DATA_PTR;
> > > +
> > > +/* For now, bind the extension device manually if none are found */
> > > +static struct udevice *extension_get_dev(void)
> >
> > This should really return the error rather than gobbling it. Normally
> > we use 'int' as the return value, so:
> >
> > static int extension_get_dev(struct udevice *devp)
>
> You mean rather this then:
> static int extension_get_dev(struct udevice **devp)

Yes that's right. In fact you can probably drop this function and use
'uclass_first_device_err(UCLASS_EXTENSION, &dev)' ? The pre-relocation
check shouldn't be needed.

>
> >
> > > +{
> > > +       struct driver *drv = ll_entry_start(struct driver, driver);
> > > +       const int n_ents = ll_entry_count(struct driver, driver);
> > > +       struct udevice *dev;
> > > +       int i, ret;
> > > +
> > > +       /* These are not needed before relocation */
> > > +       if (!(gd->flags & GD_FLG_RELOC))
> > > +               return NULL;
> > > +
> > > +       uclass_first_device(UCLASS_EXTENSION, &dev);
> > > +       if (dev)
> > > +               return dev;
> > > +
> > > +       /* Create the extension device if not already bound */
> > > +       for (i = 0; i < n_ents; i++, drv++) {
> > > +               if (drv->id == UCLASS_EXTENSION) {
> >
> > If this is really what you want, you might as well just put a
> > U_BOOT_DRVINFO() declaration in the source. Then driver model does it
> > for you. We are supposed to use the devicetree, but it seems that that
> > idea is WIP at best.
>
> Oh I will use this MACRO instead.
>
> > > +int dm_extension_scan(void)
> > > +{
> > > +       struct alist *extension_list = dm_extension_get_list();
> > > +       struct udevice *dev = extension_get_dev();
> > > +       const struct extension_ops *ops;
> > > +
> > > +       if (!dev || !extension_list)
> > > +               return -ENODEV;
> > > +
> > > +       ops = device_get_ops(dev);
> >
> > extension_get_ops()
>
> Is it really needed as it is used only once.

Not needed, just a convention, which I'd like to keep if we can.

>
> >
> > > +       if (!ops->scan)
> > > +               return -ENODEV;
> >
> > That is normally -ENOSYS - at this point we have a device, it's just
> > that it doesn't have the require method.
> >
> > But it seem strange to me to allow a device that has no means to scan.
>
> Yes, maybe this check is useless indeed, as it is the only action done by the
> board code.
>
> ...
>
> > > @@ -13,9 +14,28 @@ LIST_HEAD(extension_list);
> > >  static int do_extension_list(struct cmd_tbl *cmdtp, int flag,
> > >                              int argc, char *const argv[])
> > >  {
> > > +#if CONFIG_IS_ENABLED(SUPPORT_DM_EXTENSION_SCAN)
> > > +       struct alist *dm_extension_list;
> > > +#endif
> > >         struct extension *extension;
> > >         int i = 0;
> > >
> > > +#if CONFIG_IS_ENABLED(SUPPORT_DM_EXTENSION_SCAN)
> >
> > Is it possible to use if() ? Perhaps at the end of your series, when
> > all the conversions are done and you can delete the old code?
>
> As all these macro check are removed when the conversion is done I didn't
> bother to use if() because I would have to take care of define but not used
> warnings.

Ah OK, then it doesn't matter. I had forgotten that.

>
> ...
>
> > > +/**
> > > + * dm_extension_get_list - Get the extension list
> > > + * Return: The extension alist pointer, or NULL if no such list exists.
> >
> > caller must free the list?
>
> No.

OK, then perhaps just note that the caller must not free it

>
> > > + */
> > > +struct alist *dm_extension_get_list(void);
> >
> > Is this the list of all extensions from all extension devices?
>
> yes.
>
> > > +/**
> > > + * dm_extension_apply - Apply extension board overlay to the devicetree
> > > + * @extension_num: Extension number to be applied
> > > + * Return: Zero on success, negative on failure.
> > > + */
> > > +int dm_extension_apply(int extension_num);
> >
> > The uclass should have a method like apply(struct uclass *dev, int
> > extension_num). Is the numbering global across all devices?
>
> We currently support only one extension driver loaded at a time, therefore we
> don't currently need this uclass parameter.
> We will change the API when we will have several scan method possible at the
> same time but I can't test it for now. I don't think we will have such cases
> soon and maybe the devicetree WIP support will be ok at that time.

OK, I hadn't picked that up but it makes sense. We can always change
it later, as you say. But I would like to see an apply() method in
extension_ops, so that it actually looks like a driver.

>
> > > +
> > > +/**
> > > + * dm_extension_apply_all - Apply all extension board overlays to the
> > > + *                         devicetree
> > > + * Return: Zero on success, negative on failure.
> > > + */
> > > +int dm_extension_apply_all(void);
> > > +
> > >  struct extension {
> > >         struct list_head list;
> > >         char name[32];
> > > @@ -20,6 +62,28 @@ struct extension {
> > >         char other[32];
> > >  };
> >
> > At some point in this series, please comment this struct
>
> Ok I will add a patch to add comment on this.
>
> >
> > >
> > > +struct extension_ops {
> > > +       /**
> > > +        * scan - Add system-specific function to scan extension boards.
> > > +        * @dev: extension device to use
> >
> > need to document extension_list here - I believe it is a list of
> > struct extension? Or is it struct extension * ?
>
> Oop some code leftover here.
>
> >
> > > +        * Return: The number of extension or a negative value in case of
> > > +        *         error.
> > > +        */
> > > +       int (*scan)(struct alist *extension_list);
> >
> > This is a bit of a strange uclass function! Since you are probing
> > drivers in this uclass, you can iterate through them using
> > uclass_foreach...() etc.
> >
> > I am guessing that you just need to add a struct udevice * as the first arg.
>
> As I said there is only one drivers loaded at a time supported for now.

There are a lot of things with only one device / driver, but passing
the device in is how these work. If you don't want to do this, we can
always worry about it later, if needed.

Regards,
Simon

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH v2 03/18] boot: Add UCLASS support for extension boards
  2025-10-11  7:20       ` Simon Glass
@ 2025-10-13 12:45         ` Kory Maincent
  2025-10-13 13:41           ` Simon Glass
  0 siblings, 1 reply; 36+ messages in thread
From: Kory Maincent @ 2025-10-13 12:45 UTC (permalink / raw)
  To: Simon Glass
  Cc: Tom Rini, Jagan Teki, Andre Przywara, Hans de Goede, Mario Six,
	Stefano Babic, Fabio Estevam, NXP i.MX U-Boot Team,
	Ying-Chun Liu (PaulLiu), Roger Quadros, Bajjuri Praneeth,
	Thomas Petazzoni, u-boot

On Sat, 11 Oct 2025 08:20:58 +0100
Simon Glass <sjg@chromium.org> wrote:

> Hi Kory,
> 
> On Fri, 10 Oct 2025 at 14:35, Kory Maincent <kory.maincent@bootlin.com> wrote:
> >
> > On Fri, 10 Oct 2025 12:13:11 +0100
> > Simon Glass <sjg@chromium.org> wrote:

...

> > > > +/**
> > > > + * dm_extension_apply - Apply extension board overlay to the devicetree
> > > > + * @extension_num: Extension number to be applied
> > > > + * Return: Zero on success, negative on failure.
> > > > + */
> > > > +int dm_extension_apply(int extension_num);  
> > >
> > > The uclass should have a method like apply(struct uclass *dev, int
> > > extension_num). Is the numbering global across all devices?  
> >
> > We currently support only one extension driver loaded at a time, therefore
> > we don't currently need this uclass parameter.
> > We will change the API when we will have several scan method possible at the
> > same time but I can't test it for now. I don't think we will have such cases
> > soon and maybe the devicetree WIP support will be ok at that time.  
> 
> OK, I hadn't picked that up but it makes sense. We can always change
> it later, as you say. But I would like to see an apply() method in
> extension_ops, so that it actually looks like a driver.

Are you sure adding an apply ops method make sense? It is not something driver
or board specific. Do you want to have an apply driver ops set to the same
generic apply function for all drivers? 

Ok for the rest.

Regards,
-- 
Köry Maincent, Bootlin
Embedded Linux and kernel engineering
https://bootlin.com

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH v2 03/18] boot: Add UCLASS support for extension boards
  2025-10-13 12:45         ` Kory Maincent
@ 2025-10-13 13:41           ` Simon Glass
  0 siblings, 0 replies; 36+ messages in thread
From: Simon Glass @ 2025-10-13 13:41 UTC (permalink / raw)
  To: Kory Maincent
  Cc: Tom Rini, Jagan Teki, Andre Przywara, Hans de Goede, Mario Six,
	Stefano Babic, Fabio Estevam, NXP i.MX U-Boot Team,
	Ying-Chun Liu (PaulLiu), Roger Quadros, Bajjuri Praneeth,
	Thomas Petazzoni, u-boot

Hi Kory,

On Mon, 13 Oct 2025 at 13:45, Kory Maincent <kory.maincent@bootlin.com> wrote:
>
> On Sat, 11 Oct 2025 08:20:58 +0100
> Simon Glass <sjg@chromium.org> wrote:
>
> > Hi Kory,
> >
> > On Fri, 10 Oct 2025 at 14:35, Kory Maincent <kory.maincent@bootlin.com> wrote:
> > >
> > > On Fri, 10 Oct 2025 12:13:11 +0100
> > > Simon Glass <sjg@chromium.org> wrote:
>
> ...
>
> > > > > +/**
> > > > > + * dm_extension_apply - Apply extension board overlay to the devicetree
> > > > > + * @extension_num: Extension number to be applied
> > > > > + * Return: Zero on success, negative on failure.
> > > > > + */
> > > > > +int dm_extension_apply(int extension_num);
> > > >
> > > > The uclass should have a method like apply(struct uclass *dev, int
> > > > extension_num). Is the numbering global across all devices?
> > >
> > > We currently support only one extension driver loaded at a time, therefore
> > > we don't currently need this uclass parameter.
> > > We will change the API when we will have several scan method possible at the
> > > same time but I can't test it for now. I don't think we will have such cases
> > > soon and maybe the devicetree WIP support will be ok at that time.
> >
> > OK, I hadn't picked that up but it makes sense. We can always change
> > it later, as you say. But I would like to see an apply() method in
> > extension_ops, so that it actually looks like a driver.
>
> Are you sure adding an apply ops method make sense? It is not something driver
> or board specific. Do you want to have an apply driver ops set to the same
> generic apply function for all drivers?

I don't mind. I'll leave it to you.

Regards,
Simon

^ permalink raw reply	[flat|nested] 36+ messages in thread

end of thread, other threads:[~2025-10-13 13:41 UTC | newest]

Thread overview: 36+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-10-09 14:50 [PATCH v2 00/18] Convert extension support to UCLASS and adds its support to boot flows Kory Maincent (TI.com)
2025-10-09 14:50 ` [PATCH v2 01/18] MAINTAINERS: Add maintainer for extension board support Kory Maincent (TI.com)
2025-10-10 11:13   ` Simon Glass
2025-10-10 14:13   ` Mattijs Korpershoek
2025-10-09 14:50 ` [PATCH v2 02/18] boot: Move extension board support from cmd/ to boot/ Kory Maincent (TI.com)
2025-10-10 11:13   ` Simon Glass
2025-10-10 12:33     ` Kory Maincent
2025-10-09 14:50 ` [PATCH v2 03/18] boot: Add UCLASS support for extension boards Kory Maincent (TI.com)
2025-10-10 11:13   ` Simon Glass
2025-10-10 13:35     ` Kory Maincent
2025-10-11  7:20       ` Simon Glass
2025-10-13 12:45         ` Kory Maincent
2025-10-13 13:41           ` Simon Glass
2025-10-09 14:50 ` [PATCH v2 04/18] board: ti: Exclude cape detection from XPL builds Kory Maincent (TI.com)
2025-10-09 14:50 ` [PATCH v2 05/18] board: ti: Refactor cape detection code for readability Kory Maincent (TI.com)
2025-10-09 14:50 ` [PATCH v2 06/18] board: ti: Convert cape detection to use UCLASS framework Kory Maincent (TI.com)
2025-10-09 14:50 ` [PATCH v2 07/18] board: sunxi: Exclude DIP detection from XPL builds Kory Maincent (TI.com)
2025-10-09 14:50 ` [PATCH v2 08/18] board: sunxi: Refactor CHIP board extension code Kory Maincent (TI.com)
2025-10-09 14:50 ` [PATCH v2 09/18] board: sunxi: Convert extension support to UCLASS framework Kory Maincent (TI.com)
2025-10-09 14:50 ` [PATCH v2 10/18] board: sandbox: Improve extension board scan implementation Kory Maincent (TI.com)
2025-10-10 11:13   ` Simon Glass
2025-10-09 14:50 ` [PATCH v2 11/18] board: sandbox: Convert extension support to UCLASS framework Kory Maincent (TI.com)
2025-10-10 11:13   ` Simon Glass
2025-10-09 14:50 ` [PATCH v2 12/18] board: compulab: Exclude compulab extension board detection from XPL builds Kory Maincent (TI.com)
2025-10-09 14:50 ` [PATCH v2 13/18] board: compulab: Convert imx8mm-cl-iot-gate to UCLASS extension framework Kory Maincent (TI.com)
2025-10-09 14:50 ` [PATCH v2 14/18] boot: Remove legacy extension board support Kory Maincent (TI.com)
2025-10-10 11:13   ` Simon Glass
2025-10-09 14:50 ` [PATCH v2 15/18] boot: extension: Move overlay apply custom logic to command level Kory Maincent (TI.com)
2025-10-10 11:13   ` Simon Glass
2025-10-09 14:50 ` [PATCH v2 16/18] boot: pxe_utils: Add extension board devicetree overlay support Kory Maincent (TI.com)
2025-10-09 16:37   ` Kory Maincent
2025-10-10 11:13   ` Simon Glass
2025-10-09 14:50 ` [PATCH v2 17/18] boot: bootmeth_efi: Refactor distro_efi_try_bootflow_files return logic Kory Maincent (TI.com)
2025-10-10 11:13   ` Simon Glass
2025-10-09 14:50 ` [PATCH v2 18/18] boot: bootmeth_efi: Add extension board devicetree overlay support Kory Maincent (TI.com)
2025-10-10 11:13   ` Simon Glass

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.