[PATCH v3 02/10] cmd: add support for a new "extension" command

Maxime Ripard maxime at cerno.tech
Wed Mar 24 15:18:42 CET 2021


Hi,

On Wed, Mar 24, 2021 at 11:04:12AM +0100, Kory Maincent wrote:
> This patch adds a new "extension" command, which aims at detecting
> extension boards connected to the hardware platform, and apply the
> Device Tree overlays that describe the hardware present on those
> extension boards.
> 
> In order to enable this mechanism, board-specific code must implement
> the extension_board_scan() function that fills in a linked list of
> "struct extension", each describing one extension board. In addition,
> the board-specific code must select the SUPPORT_EXTENSION_SCAN Kconfig
> boolean.
> 
> Based on this:
> 
>  - "extension scan" makes the generic code call the board-specific
>    extension_board_scan() function to retrieve the list of detected
>    extension boards.
> 
>  - "extension list" allows to list the detected extension boards.
> 
>  - "extension apply <number>|all" allows to apply the Device Tree
>    overlay(s) corresponding to one, or all, extension boards
> 
> The latter requires two environment variables to exist:
> 
>  - extension_overlay_addr: the RAM address where to load the Device
>    Tree overlays
> 
>  - extension_overlay_cmd: the U-Boot command to load one overlay.
>    Indeed, the location and mechanism to load DT overlays is very setup
>    specific.
> 
> When calling the command described in the extension_overlay_cmd
> variable, the variable extension_overlay_name will be defined. So a
> typical extension_overlay_cmd will look like this:
> 
>   extension_overlay_cmd=load mmc 0:1 $extension_overlay_addr /boot/$extension_overlay_name
> 
> Here is an example on how to use it:
> => run loadfdt
> => fdt addr $fdtaddr
> => setenv extension_overlay_addr 0x1000
> => setenv extension_overlay_cmd 'load mmc 0:1 ${extension_overlay_addr} /boot/${extension_overlay_name}'
> => extension scan
> Found 1 extension board(s).
> => extension apply 0
> 519 bytes read in 3 ms (168.9 KiB/s)
> 
> Signed-off-by: Kory Maincent <kory.maincent at bootlin.com>
> ---
> 
> Change since v1:
>  - add list_for_each_entry loop bracket
>  - move doc location and update it to rST
> 
>  cmd/Kconfig               |  12 +++
>  cmd/Makefile              |   1 +
>  cmd/extension_board.c     | 167 ++++++++++++++++++++++++++++++++++++++
>  doc/usage/extension.rst   | 111 +++++++++++++++++++++++++
>  include/extension_board.h |  31 +++++++
>  5 files changed, 322 insertions(+)
>  create mode 100644 cmd/extension_board.c
>  create mode 100644 doc/usage/extension.rst
>  create mode 100644 include/extension_board.h
> 
> diff --git a/cmd/Kconfig b/cmd/Kconfig
> index 1595de999b..90be5c260a 100644
> --- a/cmd/Kconfig
> +++ b/cmd/Kconfig
> @@ -314,6 +314,18 @@ 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
> +	depends on SUPPORT_EXTENSION_SCAN
> +	help
> +	  Enables the "extension" command, which allows to detect
> +	  extension boards connected to the system, and apply
> +	  corresponding Device Tree overlays.
> +
>  config CMD_GO
>  	bool "go"
>  	default y
> diff --git a/cmd/Makefile b/cmd/Makefile
> index dd86675bf2..87da67d27d 100644
> --- a/cmd/Makefile
> +++ b/cmd/Makefile
> @@ -53,6 +53,7 @@ obj-$(CONFIG_CMD_DIAG) += diag.o
>  endif
>  obj-$(CONFIG_CMD_ADTIMG) += adtimg.o
>  obj-$(CONFIG_CMD_ABOOTIMG) += abootimg.o
> +obj-$(CONFIG_CMD_EXTENSION) += extension_board.o
>  obj-$(CONFIG_CMD_ECHO) += echo.o
>  obj-$(CONFIG_ENV_IS_IN_EEPROM) += eeprom.o
>  obj-$(CONFIG_CMD_EEPROM) += eeprom.o
> diff --git a/cmd/extension_board.c b/cmd/extension_board.c
> new file mode 100644
> index 0000000000..6ad9765d84
> --- /dev/null
> +++ b/cmd/extension_board.c
> @@ -0,0 +1,167 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * (C) Copyright 2021
> + * Köry Maincent, Bootlin, <kory.maincent at bootlin.com>
> + */
> +
> +#include <common.h>
> +#include <command.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;
> +}
> +
> +static int do_extension_list(struct cmd_tbl *cmdtp, int flag,
> +			     int argc, char *const argv[])
> +{
> +	int i;
> +	struct extension *extension;
> +
> +	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);
> +	}
> +	return CMD_RET_SUCCESS;
> +}
> +
> +static int do_extension_scan(struct cmd_tbl *cmdtp, int flag,
> +			     int argc, char *const argv[])
> +{
> +	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 (extension_num < 0)
> +		return CMD_RET_FAILURE;
> +
> +	printf("Found %d extension board(s).\n", extension_num);
> +
> +	return CMD_RET_SUCCESS;
> +}
> +
> +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;
> +
> +	if (argc < 2)
> +		return CMD_RET_USAGE;
> +
> +	if (strcmp(argv[1], "all") == 0) {
> +		list_for_each_entry(extension, &extension_list, list) {
> +			ret = extension_apply(extension);
> +			if (ret != CMD_RET_SUCCESS)
> +				break;
> +		}
> +	} else {
> +		extension_id = simple_strtol(argv[1], NULL, 10);
> +		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);
> +	}
> +
> +	return ret;
> +}
> +
> +static struct cmd_tbl cmd_extension[] = {
> +	U_BOOT_CMD_MKENT(scan, 1, 1, do_extension_scan, "", ""),
> +	U_BOOT_CMD_MKENT(list, 1, 0, do_extension_list, "", ""),
> +	U_BOOT_CMD_MKENT(apply, 2, 0, do_extension_apply, "", ""),
> +};
> +
> +static int do_extensionops(struct cmd_tbl *cmdtp, int flag, int argc,
> +			   char *const argv[])
> +{
> +	struct cmd_tbl *cp;
> +
> +	/* Drop the extension command */
> +	argc--;
> +	argv++;
> +
> +	cp = find_cmd_tbl(argv[0], cmd_extension, ARRAY_SIZE(cmd_extension));
> +	if (cp)
> +		return cp->cmd(cmdtp, flag, argc, argv);
> +
> +	return CMD_RET_USAGE;
> +}
> +
> +U_BOOT_CMD(extension, 3, 1, do_extensionops,
> +	"Extension board management sub system",
> +	"scan - scan plugged extension(s) board(s)\n"
> +	"extension list - lists available extension(s) board(s)\n"
> +	"extension apply <extension number|all> - applies DT overlays corresponding to extension boards\n"
> +);
> diff --git a/doc/usage/extension.rst b/doc/usage/extension.rst
> new file mode 100644
> index 0000000000..2b88398b18
> --- /dev/null
> +++ b/doc/usage/extension.rst
> @@ -0,0 +1,111 @@
> +.. SPDX-License-Identifier: GPL-2.0+
> +.. Copyright 2021, Kory Maincent <kory.maincent at bootlin.com>
> +
> +U-Boot extension board usage (CONFIG_EXTENSION)
> +===============================================
> +
> +Synopsis
> +--------
> +
> +::
> +
> +    extension scan
> +    extension list
> +    extension apply <extension number|all>
> +
> +Description
> +-----------
> +
> +The "extension" command proposes a generic U-Boot mechanism to detect
> +extension boards connected to the HW platform, and apply the appropriate
> +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 list" allows to list the detected extension boards.
> +
> + - "extension apply <number>|all" allows to apply the Device Tree
> +   overlay(s) corresponding to one, or all, extension boards
> +
> +The latter requires two environment variables to exist:
> +
> + - extension_overlay_addr: the RAM address where to load the Device
> +   Tree overlays
> +
> + - extension_overlay_cmd: the U-Boot command to load one overlay.
> +   Indeed, the location and mechanism to load DT overlays is very setup
> +   specific.

I guess we should make it explicit that the extension_overlay_name
variable will be set and usable by that command

With that fixed,
Reviewed-by: Maxime Ripard <maxime at cerno.tech>

Maxime
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 228 bytes
Desc: not available
URL: <https://lists.denx.de/pipermail/u-boot/attachments/20210324/9a6c25e6/attachment.sig>


More information about the U-Boot mailing list