[U-Boot] [PATCH V2 2/2] pxe: implement fdtdir extlinux.conf tag

Stephen Warren swarren at wwwdotorg.org
Tue Jan 28 22:50:10 CET 2014


From: Stephen Warren <swarren at nvidia.com>

People who write (or scripts that auto-generate) extlinux.conf don't
want to know about HW-specific information such as FDT filenames. Create
a new extlinux.conf tag "fdtdir" that specifies only the directory where
FDT files are located, and defer all knowledge of the filename to U-Boot.
The algorithm implemented is:

==========
if $fdt_addr_r is set:
  if "fdt" tag was specified in extlinux.conf:
    load the FDT from the filename in the tag
  else if "fdtdir" tag was specified in extlinux.conf:
    if "fdtfile" is set in the environment:
      load the FDT from filename in "$fdtfile"
    else:
      load the FDT from some automatically generated filename

if no FDT file was loaded, and $fdtaddr is set:
  # This indicates an FDT packaged with firmware
  use the FDT at $fdtaddr
==========

A small part of an example /boot/extlinux.conf might be:

==========
LABEL primary
        LINUX zImage
        FDTDIR ./

LABEL failsafe
        LINUX bkp/zImage
        FDTDIR bkp/
==========

... with /boot/tegra20-seaboard.dtb or /boot/bkp/tegra20-seaboard.dtb
being loaded by the sysboot/pxe code.

Signed-off-by: Stephen Warren <swarren at nvidia.com>
---
v2: Added support for "devicetreedir" config file tag, per the spec.
v1 (relative to RFC): no change; just reposting as non-RFC.

This patch is related to, but actually doesn't depend on the following
from Dennis Gilmore:
- cmd_pxe.c add any option for filesystem with sysboot uses generic load
- config: add config_distro_defaults.h
---
 common/cmd_pxe.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 72 insertions(+), 6 deletions(-)

diff --git a/common/cmd_pxe.c b/common/cmd_pxe.c
index 4f00b1a607d4..2bd572d64691 100644
--- a/common/cmd_pxe.c
+++ b/common/cmd_pxe.c
@@ -445,6 +445,7 @@ struct pxe_label {
 	char *append;
 	char *initrd;
 	char *fdt;
+	char *fdtdir;
 	int ipappend;
 	int attempted;
 	int localboot;
@@ -517,6 +518,9 @@ static void label_destroy(struct pxe_label *label)
 	if (label->fdt)
 		free(label->fdt);
 
+	if (label->fdtdir)
+		free(label->fdtdir);
+
 	free(label);
 }
 
@@ -675,13 +679,67 @@ static int label_boot(cmd_tbl_t *cmdtp, struct pxe_label *label)
 	bootm_argv[3] = getenv("fdt_addr_r");
 
 	/* if fdt label is defined then get fdt from server */
-	if (bootm_argv[3] && label->fdt) {
-		if (get_relfile_envaddr(cmdtp, label->fdt, "fdt_addr_r") < 0) {
-			printf("Skipping %s for failure retrieving fdt\n",
-					label->name);
-			return 1;
+	if (bootm_argv[3]) {
+		char *fdtfile = NULL;
+		char *fdtfilefree = NULL;
+
+		if (label->fdt) {
+			fdtfile = label->fdt;
+		} else if (label->fdtdir) {
+			fdtfile = getenv("fdtfile");
+			/*
+			 * For complex cases, it might be worth calling a
+			 * board- or SoC-provided function here to provide a
+			 * better default:
+			 *
+			 * if (!fdtfile)
+			 *     fdtfile = gen_fdtfile();
+			 *
+			 * If this is added, be sure to keep the default below,
+			 * or move it to the default weak implementation of
+			 * gen_fdtfile().
+			 */
+			if (!fdtfile) {
+				char *soc = getenv("soc");
+				char *board = getenv("board");
+				char *slash;
+
+				len = strlen(label->fdtdir);
+				if (!len)
+					slash = "./";
+				else if (label->fdtdir[len - 1] != '/')
+					slash = "/";
+				else
+					slash = "";
+
+				len = strlen(label->fdtdir) + strlen(slash) +
+					strlen(soc) + 1 + strlen(board) + 5;
+				fdtfilefree = malloc(len);
+				if (!fdtfilefree) {
+					printf("malloc fail (FDT filename)\n");
+					return 1;
+				}
+
+				snprintf(fdtfilefree, len, "%s%s%s-%s.dtb",
+					label->fdtdir, slash, soc, board);
+				fdtfile = fdtfilefree;
+			}
 		}
-	} else
+
+		if (fdtfile) {
+			int err = get_relfile_envaddr(cmdtp, fdtfile, "fdt_addr_r");
+			free(fdtfilefree);
+			if (err < 0) {
+				printf("Skipping %s for failure retrieving fdt\n",
+						label->name);
+				return 1;
+			}
+		} else {
+			bootm_argv[3] = NULL;
+		}
+	}
+
+	if (!bootm_argv[3])
 		bootm_argv[3] = getenv("fdt_addr");
 
 	if (bootm_argv[3])
@@ -716,6 +774,7 @@ enum token_type {
 	T_PROMPT,
 	T_INCLUDE,
 	T_FDT,
+	T_FDTDIR,
 	T_ONTIMEOUT,
 	T_IPAPPEND,
 	T_INVALID
@@ -747,6 +806,8 @@ static const struct token keywords[] = {
 	{"include", T_INCLUDE},
 	{"devicetree", T_FDT},
 	{"fdt", T_FDT},
+	{"devicetreedir", T_FDTDIR},
+	{"fdtdir", T_FDTDIR},
 	{"ontimeout", T_ONTIMEOUT,},
 	{"ipappend", T_IPAPPEND,},
 	{NULL, T_INVALID}
@@ -1135,6 +1196,11 @@ static int parse_label(char **c, struct pxe_menu *cfg)
 				err = parse_sliteral(c, &label->fdt);
 			break;
 
+		case T_FDTDIR:
+			if (!label->fdtdir)
+				err = parse_sliteral(c, &label->fdtdir);
+			break;
+
 		case T_LOCALBOOT:
 			label->localboot = 1;
 			err = parse_integer(c, &label->localboot_val);
-- 
1.8.1.5



More information about the U-Boot mailing list