[U-Boot] [RFC PATCH] pxe: add support for FDT overlays
Neil Armstrong
narmstrong at baylibre.com
Fri May 31 08:12:10 UTC 2019
Hi Tom.
Is there someone who can review this ? or should I resent without RFC ?
Thanks,
Neil
On 07/05/2019 14:50, Neil Armstrong wrote:
> This adds support for specicyinf FDT overlays in an extlinux/pxelinux
> configuration file.
>
> Without this, there is no simple way to apply overlays when the kernel
> and ftd is loaded by the pxe command.
>
> This change adds the 'fdtoverlays' keyword for a label, supporting multiple
> overlay files to be applied on top of the fdt specific in the 'fdt' or
> 'devicetree' keyword.
>
> Cc: Jernej Škrabec <jernej.skrabec at siol.net>
> Cc: Jonas Karlman <jonas at kwiboo.se>
> Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
> ---
> cmd/pxe.c | 104 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 104 insertions(+)
>
> diff --git a/cmd/pxe.c b/cmd/pxe.c
> index 1dd0a74ea3..8d19e6f99f 100644
> --- a/cmd/pxe.c
> +++ b/cmd/pxe.c
> @@ -13,6 +13,8 @@
> #include <linux/ctype.h>
> #include <errno.h>
> #include <linux/list.h>
> +#include <fdt_support.h>
> +#include <linux/libfdt.h>
> #include <fs.h>
> #include <splash.h>
> #include <asm/io.h>
> @@ -481,6 +483,7 @@ struct pxe_label {
> char *initrd;
> char *fdt;
> char *fdtdir;
> + char *fdtoverlays;
> int ipappend;
> int attempted;
> int localboot;
> @@ -561,6 +564,9 @@ static void label_destroy(struct pxe_label *label)
> if (label->fdtdir)
> free(label->fdtdir);
>
> + if (label->fdtoverlays)
> + free(label->fdtoverlays);
> +
> free(label);
> }
>
> @@ -608,6 +614,92 @@ static int label_localboot(struct pxe_label *label)
> return run_command_list(localcmd, strlen(localcmd), 0);
> }
>
> +/*
> + * Loads fdt overlays specified in 'fdtoverlays'.
> + */
> +#ifdef CONFIG_OF_LIBFDT_OVERLAY
> +static void label_boot_fdtoverlay(cmd_tbl_t *cmdtp, struct pxe_label *label)
> +{
> + char *fdtoverlay = label->fdtoverlays;
> + struct fdt_header *working_fdt;
> + char *fdtoverlay_addr_env;
> + ulong fdtoverlay_addr;
> + ulong fdt_addr;
> + int err;
> +
> + /* Get the main fdt and map it */
> + fdt_addr = simple_strtoul(env_get("fdt_addr_r"), NULL, 16);
> + working_fdt = map_sysmem(fdt_addr, 0);
> + err = fdt_check_header(working_fdt);
> + if (err)
> + return;
> +
> + /* Get the specific overlay loading address */
> + fdtoverlay_addr_env = env_get("fdtoverlay_addr_r");
> + if (!fdtoverlay_addr_env) {
> + printf("Invalid fdtoverlay_addr_r for loading overlays\n");
> + return;
> + }
> +
> + fdtoverlay_addr = simple_strtoul(fdtoverlay_addr_env, NULL, 16);
> +
> + /* Cycle over the overlay files and apply them in order */
> + do {
> + struct fdt_header *blob;
> + char *overlayfile;
> + char *end;
> + int len;
> +
> + /* Drop leading spaces */
> + while (*fdtoverlay == ' ')
> + ++fdtoverlay;
> +
> + /* Copy a single filename if multiple provided */
> + end = strstr(fdtoverlay, " ");
> + if (end) {
> + len = (int)(end - fdtoverlay);
> + overlayfile = malloc(len + 1);
> + strncpy(overlayfile, fdtoverlay, len);
> + overlayfile[len] = '\0';
> + } else
> + overlayfile = fdtoverlay;
> +
> + if (!strlen(overlayfile))
> + goto skip_overlay;
> +
> + /* Load overlay file */
> + err = get_relfile_envaddr(cmdtp, overlayfile,
> + "fdtoverlay_addr_r");
> + if (err < 0) {
> + printf("Failed loading overlay %s\n", overlayfile);
> + goto skip_overlay;
> + }
> +
> + /* Resize main fdt */
> + fdt_shrink_to_minimum(working_fdt, 8192);
> +
> + blob = map_sysmem(fdtoverlay_addr, 0);
> + err = fdt_check_header(blob);
> + if (err) {
> + printf("Invalid overlay %s, skipping\n",
> + overlayfile);
> + goto skip_overlay;
> + }
> +
> + err = fdt_overlay_apply_verbose(working_fdt, blob);
> + if (err) {
> + printf("Failed to apply overlay %s, skipping\n",
> + overlayfile);
> + goto skip_overlay;
> + }
> +
> +skip_overlay:
> + if (end)
> + free(overlayfile);
> + } while ((fdtoverlay = strstr(fdtoverlay, " ")));
> +}
> +#endif
> +
> /*
> * Boot according to the contents of a pxe_label.
> *
> @@ -798,6 +890,11 @@ static int label_boot(cmd_tbl_t *cmdtp, struct pxe_label *label)
> label->name);
> goto cleanup;
> }
> +
> +#ifdef CONFIG_OF_LIBFDT_OVERLAY
> + if (label->fdtoverlays)
> + label_boot_fdtoverlay(cmdtp, label);
> +#endif
> } else {
> bootm_argv[3] = NULL;
> }
> @@ -855,6 +952,7 @@ enum token_type {
> T_INCLUDE,
> T_FDT,
> T_FDTDIR,
> + T_FDTOVERLAYS,
> T_ONTIMEOUT,
> T_IPAPPEND,
> T_BACKGROUND,
> @@ -889,6 +987,7 @@ static const struct token keywords[] = {
> {"fdt", T_FDT},
> {"devicetreedir", T_FDTDIR},
> {"fdtdir", T_FDTDIR},
> + {"fdtoverlays", T_FDTOVERLAYS},
> {"ontimeout", T_ONTIMEOUT,},
> {"ipappend", T_IPAPPEND,},
> {"background", T_BACKGROUND,},
> @@ -1322,6 +1421,11 @@ static int parse_label(char **c, struct pxe_menu *cfg)
> err = parse_sliteral(c, &label->fdtdir);
> break;
>
> + case T_FDTOVERLAYS:
> + if (!label->fdtoverlays)
> + err = parse_sliteral(c, &label->fdtoverlays);
> + break;
> +
> case T_LOCALBOOT:
> label->localboot = 1;
> err = parse_integer(c, &label->localboot_val);
>
More information about the U-Boot
mailing list