From: Stephen Warren <swar...@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 <swar...@nvidia.com>
---
 common/cmd_pxe.c | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 71 insertions(+), 6 deletions(-)

diff --git a/common/cmd_pxe.c b/common/cmd_pxe.c
index 20569bb04201..5d356295e48e 100644
--- a/common/cmd_pxe.c
+++ b/common/cmd_pxe.c
@@ -459,6 +459,7 @@ struct pxe_label {
        char *append;
        char *initrd;
        char *fdt;
+       char *fdtdir;
        int ipappend;
        int attempted;
        int localboot;
@@ -531,6 +532,9 @@ static void label_destroy(struct pxe_label *label)
        if (label->fdt)
                free(label->fdt);
 
+       if (label->fdtdir)
+               free(label->fdtdir);
+
        free(label);
 }
 
@@ -689,13 +693,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])
@@ -730,6 +788,7 @@ enum token_type {
        T_PROMPT,
        T_INCLUDE,
        T_FDT,
+       T_FDTDIR,
        T_ONTIMEOUT,
        T_IPAPPEND,
        T_INVALID
@@ -760,6 +819,7 @@ static const struct token keywords[] = {
        {"initrd", T_INITRD},
        {"include", T_INCLUDE},
        {"fdt", T_FDT},
+       {"fdtdir", T_FDTDIR},
        {"ontimeout", T_ONTIMEOUT,},
        {"ipappend", T_IPAPPEND,},
        {NULL, T_INVALID}
@@ -1148,6 +1208,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

_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot

Reply via email to