[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