[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