pico-imx7d: Add NYMPH baseboard support
[oweals/u-boot.git] / cmd / pxe.c
index c5a770a26995fabc5a1b3b0b7450997d29e110db..205997544623836b0976599046d9609d15351f2e 100644 (file)
--- a/cmd/pxe.c
+++ b/cmd/pxe.c
@@ -1,19 +1,21 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright 2010-2011 Calxeda, Inc.
  * Copyright (c) 2014, NVIDIA CORPORATION.  All rights reserved.
- *
- * SPDX-License-Identifier:    GPL-2.0+
  */
 
 #include <common.h>
 #include <command.h>
+#include <env.h>
 #include <malloc.h>
 #include <mapmem.h>
+#include <lcd.h>
 #include <linux/string.h>
 #include <linux/ctype.h>
 #include <errno.h>
 #include <linux/list.h>
 #include <fs.h>
+#include <splash.h>
 #include <asm/io.h>
 
 #include "menu.h"
@@ -23,6 +25,9 @@
 
 const char *pxe_default_paths[] = {
 #ifdef CONFIG_SYS_SOC
+#ifdef CONFIG_SYS_BOARD
+       "default-" CONFIG_SYS_ARCH "-" CONFIG_SYS_SOC "-" CONFIG_SYS_BOARD,
+#endif
        "default-" CONFIG_SYS_ARCH "-" CONFIG_SYS_SOC,
 #endif
        "default-" CONFIG_SYS_ARCH,
@@ -472,6 +477,7 @@ struct pxe_label {
        char *name;
        char *menu;
        char *kernel;
+       char *config;
        char *append;
        char *initrd;
        char *fdt;
@@ -488,6 +494,7 @@ struct pxe_label {
  *
  * title - the name of the menu as given by a 'menu title' line.
  * default_label - the name of the default label, if any.
+ * bmp - the bmp file name which is displayed in background
  * timeout - time in tenths of a second to wait for a user key-press before
  *           booting the default label.
  * prompt - if 0, don't prompt for a choice unless the timeout period is
@@ -498,6 +505,7 @@ struct pxe_label {
 struct pxe_menu {
        char *title;
        char *default_label;
+       char *bmp;
        int timeout;
        int prompt;
        struct list_head labels;
@@ -539,6 +547,9 @@ static void label_destroy(struct pxe_label *label)
        if (label->kernel)
                free(label->kernel);
 
+       if (label->config)
+               free(label->config);
+
        if (label->append)
                free(label->append);
 
@@ -616,9 +627,10 @@ static int label_localboot(struct pxe_label *label)
 static int label_boot(cmd_tbl_t *cmdtp, struct pxe_label *label)
 {
        char *bootm_argv[] = { "bootm", NULL, NULL, NULL, NULL };
-       char initrd_str[22];
+       char initrd_str[28];
        char mac_str[29] = "";
        char ip_str[68] = "";
+       char *fit_addr = NULL;
        int bootm_argc = 2;
        int len = 0;
        ulong kernel_addr;
@@ -648,9 +660,9 @@ static int label_boot(cmd_tbl_t *cmdtp, struct pxe_label *label)
                }
 
                bootm_argv[2] = initrd_str;
-               strcpy(bootm_argv[2], env_get("ramdisk_addr_r"));
+               strncpy(bootm_argv[2], env_get("ramdisk_addr_r"), 18);
                strcat(bootm_argv[2], ":");
-               strcat(bootm_argv[2], env_get("filesize"));
+               strncat(bootm_argv[2], env_get("filesize"), 9);
        }
 
        if (get_relfile_envaddr(cmdtp, label->kernel, "kernel_addr_r") < 0) {
@@ -686,19 +698,32 @@ static int label_boot(cmd_tbl_t *cmdtp, struct pxe_label *label)
                               strlen(ip_str), strlen(mac_str),
                               sizeof(bootargs));
                        return 1;
+               } else {
+                       if (label->append)
+                               strncpy(bootargs, label->append,
+                                       sizeof(bootargs));
+                       strcat(bootargs, ip_str);
+                       strcat(bootargs, mac_str);
+
+                       cli_simple_process_macros(bootargs, finalbootargs);
+                       env_set("bootargs", finalbootargs);
+                       printf("append: %s\n", finalbootargs);
                }
-
-               if (label->append)
-                       strcpy(bootargs, label->append);
-               strcat(bootargs, ip_str);
-               strcat(bootargs, mac_str);
-
-               cli_simple_process_macros(bootargs, finalbootargs);
-               env_set("bootargs", finalbootargs);
-               printf("append: %s\n", finalbootargs);
        }
 
        bootm_argv[1] = env_get("kernel_addr_r");
+       /* for FIT, append the configuration identifier */
+       if (label->config) {
+               int len = strlen(bootm_argv[1]) + strlen(label->config) + 1;
+
+               fit_addr = malloc(len);
+               if (!fit_addr) {
+                       printf("malloc fail (FIT address)\n");
+                       return 1;
+               }
+               snprintf(fit_addr, len, "%s%s", bootm_argv[1], label->config);
+               bootm_argv[1] = fit_addr;
+       }
 
        /*
         * fdt usage is optional:
@@ -758,7 +783,7 @@ static int label_boot(cmd_tbl_t *cmdtp, struct pxe_label *label)
                        fdtfilefree = malloc(len);
                        if (!fdtfilefree) {
                                printf("malloc fail (FDT filename)\n");
-                               return 1;
+                               goto cleanup;
                        }
 
                        snprintf(fdtfilefree, len, "%s%s%s%s%s%s",
@@ -772,7 +797,7 @@ static int label_boot(cmd_tbl_t *cmdtp, struct pxe_label *label)
                        if (err < 0) {
                                printf("Skipping %s for failure retrieving fdt\n",
                                                label->name);
-                               return 1;
+                               goto cleanup;
                        }
                } else {
                        bootm_argv[3] = NULL;
@@ -803,6 +828,10 @@ static int label_boot(cmd_tbl_t *cmdtp, struct pxe_label *label)
                do_bootz(cmdtp, 0, bootm_argc, bootm_argv);
 #endif
        unmap_sysmem(buf);
+
+cleanup:
+       if (fit_addr)
+               free(fit_addr);
        return 1;
 }
 
@@ -829,6 +858,7 @@ enum token_type {
        T_FDTDIR,
        T_ONTIMEOUT,
        T_IPAPPEND,
+       T_BACKGROUND,
        T_INVALID
 };
 
@@ -862,6 +892,7 @@ static const struct token keywords[] = {
        {"fdtdir", T_FDTDIR},
        {"ontimeout", T_ONTIMEOUT,},
        {"ipappend", T_IPAPPEND,},
+       {"background", T_BACKGROUND,},
        {NULL, T_INVALID}
 };
 
@@ -1139,6 +1170,10 @@ static int parse_menu(cmd_tbl_t *cmdtp, char **c, struct pxe_menu *cfg,
                                                nest_level + 1);
                break;
 
+       case T_BACKGROUND:
+               err = parse_sliteral(c, &cfg->bmp);
+               break;
+
        default:
                printf("Ignoring malformed menu command: %.*s\n",
                                (int)(*c - s), s);
@@ -1187,6 +1222,33 @@ static int parse_label_menu(char **c, struct pxe_menu *cfg,
        return 0;
 }
 
+/*
+ * Handles parsing a 'kernel' label.
+ * expecting "filename" or "<fit_filename>#cfg"
+ */
+static int parse_label_kernel(char **c, struct pxe_label *label)
+{
+       char *s;
+       int err;
+
+       err = parse_sliteral(c, &label->kernel);
+       if (err < 0)
+               return err;
+
+       s = strstr(label->kernel, "#");
+       if (!s)
+               return 1;
+
+       label->config = malloc(strlen(s) + 1);
+       if (!label->config)
+               return -ENOMEM;
+
+       strcpy(label->config, s);
+       *s = 0;
+
+       return 1;
+}
+
 /*
  * Parses a label and adds it to the list of labels for a menu.
  *
@@ -1228,7 +1290,7 @@ static int parse_label(char **c, struct pxe_menu *cfg)
 
                case T_KERNEL:
                case T_LINUX:
-                       err = parse_sliteral(c, &label->kernel);
+                       err = parse_label_kernel(c, label);
                        break;
 
                case T_APPEND:
@@ -1453,8 +1515,8 @@ static struct menu *pxe_menu_to_menu(struct pxe_menu *cfg)
        /*
         * Create a menu and add items for all the labels.
         */
-       m = menu_create(cfg->title, cfg->timeout, cfg->prompt, label_print,
-                       NULL, NULL);
+       m = menu_create(cfg->title, DIV_ROUND_UP(cfg->timeout, 10),
+                       cfg->prompt, label_print, NULL, NULL);
 
        if (!m)
                return NULL;
@@ -1526,6 +1588,20 @@ static void handle_pxe_menu(cmd_tbl_t *cmdtp, struct pxe_menu *cfg)
        struct menu *m;
        int err;
 
+#ifdef CONFIG_CMD_BMP
+       /* display BMP if available */
+       if (cfg->bmp) {
+               if (get_relfile(cmdtp, cfg->bmp, load_addr)) {
+                       run_command("cls", 0);
+                       bmp_display(load_addr,
+                                   BMP_ALIGN_CENTER, BMP_ALIGN_CENTER);
+               } else {
+                       printf("Skipping background bmp %s for failure\n",
+                              cfg->bmp);
+               }
+       }
+#endif
+
        m = pxe_menu_to_menu(cfg);
        if (!m)
                return;