Skip to content

Commit bb273d3

Browse files
committed
cmd: pxe: add support for FDT overlays
This adds support for specifying FDT overlays in an extlinux/pxelinux configuration file. Without this, there is no simple way to apply overlays when the kernel and fdt 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 specified in the 'fdt' or 'devicetree' keyword. Example: label linux kernel /Image fdt /soc-board.dtb fdtoverlays /soc-board-function.dtbo append console=ttyS0,115200 root=/dev/mmcblk0p2 rootwait This code makes usage of a new variable called fdtoverlay_addr_r used to load the overlay files without overwritting anything important. Cc: Tom Rini <[email protected]> Cc: Andre Heider <[email protected]> Cc: Jernej Škrabec <[email protected]> Cc: Jonas Karlman <[email protected]> Tested-by: Jernej Škrabec <[email protected]> Reviewed-by: Jernej Škrabec <[email protected]> Signed-off-by: Neil Armstrong <[email protected]> The original commit is u-boot/u-boot@69076df Signed-off-by: Stephen Chen <[email protected]>
1 parent 9b25465 commit bb273d3

File tree

2 files changed

+113
-0
lines changed

2 files changed

+113
-0
lines changed

cmd/pxe.c

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
#include <command.h>
1010
#include <malloc.h>
1111
#include <mapmem.h>
12+
#include <fdt_support.h>
13+
#include <linux/libfdt.h>
1214
#include <linux/string.h>
1315
#include <linux/ctype.h>
1416
#include <errno.h>
@@ -476,6 +478,7 @@ struct pxe_label {
476478
char *initrd;
477479
char *fdt;
478480
char *fdtdir;
481+
char *fdtoverlays;
479482
int ipappend;
480483
int attempted;
481484
int localboot;
@@ -551,6 +554,9 @@ static void label_destroy(struct pxe_label *label)
551554
if (label->fdtdir)
552555
free(label->fdtdir);
553556

557+
if (label->fdtoverlays)
558+
free(label->fdtoverlays);
559+
554560
free(label);
555561
}
556562

@@ -598,6 +604,92 @@ static int label_localboot(struct pxe_label *label)
598604
return run_command_list(localcmd, strlen(localcmd), 0);
599605
}
600606

607+
/*
608+
* Loads fdt overlays specified in 'fdtoverlays'.
609+
*/
610+
#ifdef CONFIG_OF_LIBFDT_OVERLAY
611+
static void label_boot_fdtoverlay(cmd_tbl_t *cmdtp, struct pxe_label *label)
612+
{
613+
char *fdtoverlay = label->fdtoverlays;
614+
struct fdt_header *working_fdt;
615+
char *fdtoverlay_addr_env;
616+
ulong fdtoverlay_addr;
617+
ulong fdt_addr;
618+
int err;
619+
620+
/* Get the main fdt and map it */
621+
fdt_addr = simple_strtoul(env_get("fdt_addr_r"), NULL, 16);
622+
working_fdt = map_sysmem(fdt_addr, 0);
623+
err = fdt_check_header(working_fdt);
624+
if (err)
625+
return;
626+
627+
/* Get the specific overlay loading address */
628+
fdtoverlay_addr_env = env_get("fdtoverlay_addr_r");
629+
if (!fdtoverlay_addr_env) {
630+
printf("Invalid fdtoverlay_addr_r for loading overlays\n");
631+
return;
632+
}
633+
634+
fdtoverlay_addr = simple_strtoul(fdtoverlay_addr_env, NULL, 16);
635+
636+
/* Cycle over the overlay files and apply them in order */
637+
do {
638+
struct fdt_header *blob;
639+
char *overlayfile;
640+
char *end;
641+
int len;
642+
643+
/* Drop leading spaces */
644+
while (*fdtoverlay == ' ')
645+
++fdtoverlay;
646+
647+
/* Copy a single filename if multiple provided */
648+
end = strstr(fdtoverlay, " ");
649+
if (end) {
650+
len = (int)(end - fdtoverlay);
651+
overlayfile = malloc(len + 1);
652+
strncpy(overlayfile, fdtoverlay, len);
653+
overlayfile[len] = '\0';
654+
} else
655+
overlayfile = fdtoverlay;
656+
657+
if (!strlen(overlayfile))
658+
goto skip_overlay;
659+
660+
/* Load overlay file */
661+
err = get_relfile_envaddr(cmdtp, overlayfile,
662+
"fdtoverlay_addr_r");
663+
if (err < 0) {
664+
printf("Failed loading overlay %s\n", overlayfile);
665+
goto skip_overlay;
666+
}
667+
668+
/* Resize main fdt */
669+
fdt_shrink_to_minimum(working_fdt, 8192);
670+
671+
blob = map_sysmem(fdtoverlay_addr, 0);
672+
err = fdt_check_header(blob);
673+
if (err) {
674+
printf("Invalid overlay %s, skipping\n",
675+
overlayfile);
676+
goto skip_overlay;
677+
}
678+
679+
err = fdt_overlay_apply_verbose(working_fdt, blob);
680+
if (err) {
681+
printf("Failed to apply overlay %s, skipping\n",
682+
overlayfile);
683+
goto skip_overlay;
684+
}
685+
686+
skip_overlay:
687+
if (end)
688+
free(overlayfile);
689+
} while ((fdtoverlay = strstr(fdtoverlay, " ")));
690+
}
691+
#endif
692+
601693
/*
602694
* Boot according to the contents of a pxe_label.
603695
*
@@ -775,6 +867,11 @@ static int label_boot(cmd_tbl_t *cmdtp, struct pxe_label *label)
775867
label->name);
776868
return 1;
777869
}
870+
871+
#ifdef CONFIG_OF_LIBFDT_OVERLAY
872+
if (label->fdtoverlays)
873+
label_boot_fdtoverlay(cmdtp, label);
874+
#endif
778875
} else {
779876
bootm_argv[3] = NULL;
780877
}
@@ -828,6 +925,7 @@ enum token_type {
828925
T_INCLUDE,
829926
T_FDT,
830927
T_FDTDIR,
928+
T_FDTOVERLAYS,
831929
T_ONTIMEOUT,
832930
T_IPAPPEND,
833931
T_INVALID
@@ -861,6 +959,7 @@ static const struct token keywords[] = {
861959
{"fdt", T_FDT},
862960
{"devicetreedir", T_FDTDIR},
863961
{"fdtdir", T_FDTDIR},
962+
{"fdtoverlays", T_FDTOVERLAYS},
864963
{"ontimeout", T_ONTIMEOUT,},
865964
{"ipappend", T_IPAPPEND,},
866965
{NULL, T_INVALID}
@@ -1262,6 +1361,11 @@ static int parse_label(char **c, struct pxe_menu *cfg)
12621361
err = parse_sliteral(c, &label->fdtdir);
12631362
break;
12641363

1364+
case T_FDTOVERLAYS:
1365+
if (!label->fdtoverlays)
1366+
err = parse_sliteral(c, &label->fdtoverlays);
1367+
break;
1368+
12651369
case T_LOCALBOOT:
12661370
label->localboot = 1;
12671371
err = parse_integer(c, &label->localboot_val);

doc/README.pxe

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,9 @@ pxe boot
9090
fdt_addr - the location of a fdt blob. 'fdt_addr' will be passed to bootm
9191
command if it is set and 'fdt_addr_r' is not passed to bootm command.
9292

93+
fdtoverlay_addr_r - location in RAM at which 'pxe boot' will temporarily store
94+
fdt overlay(s) before applying them to the fdt blob stored at 'fdt_addr_r'.
95+
9396
pxe file format
9497
===============
9598
The pxe file format is nearly a subset of the PXELINUX file format; see
@@ -142,6 +145,12 @@ kernel <path> - if this label is chosen, use tftp to retrieve the kernel
142145
indicated in the kernel_addr_r environment variable, and
143146
that address will be passed to bootm to boot this kernel.
144147

148+
fdtoverlays <path> [...] - if this label is chosen, use tftp to retrieve the DT
149+
overlay(s) at <path>. it will be temporarily stored at the
150+
address indicated in the fdtoverlay_addr_r environment variable,
151+
and then applied in the load order to the fdt blob stored at the
152+
address indicated in the fdt_addr_r environment variable.
153+
145154
append <string> - use <string> as the kernel command line when booting this
146155
label.
147156

0 commit comments

Comments
 (0)