pxe: Clean up the use of bootfile
[platform/kernel/u-boot.git] / boot / pxe_utils.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright 2010-2011 Calxeda, Inc.
4  * Copyright (c) 2014, NVIDIA CORPORATION.  All rights reserved.
5  */
6
7 #include <common.h>
8 #include <command.h>
9 #include <env.h>
10 #include <image.h>
11 #include <log.h>
12 #include <malloc.h>
13 #include <mapmem.h>
14 #include <lcd.h>
15 #include <net.h>
16 #include <fdt_support.h>
17 #include <linux/libfdt.h>
18 #include <linux/string.h>
19 #include <linux/ctype.h>
20 #include <errno.h>
21 #include <linux/list.h>
22
23 #include <splash.h>
24 #include <asm/io.h>
25
26 #include "menu.h"
27 #include "cli.h"
28
29 #include "pxe_utils.h"
30
31 #define MAX_TFTP_PATH_LEN 512
32
33 /**
34  * format_mac_pxe() - obtain a MAC address in the PXE format
35  *
36  * This produces a MAC-address string in the format for the current ethernet
37  * device:
38  *
39  *   01-aa-bb-cc-dd-ee-ff
40  *
41  * where aa-ff is the MAC address in hex
42  *
43  * @outbuf: Buffer to write string to
44  * @outbuf_len: length of buffer
45  * @return 1 if OK, -ENOSPC if buffer is too small, -ENOENT is there is no
46  *      current ethernet device
47  */
48 int format_mac_pxe(char *outbuf, size_t outbuf_len)
49 {
50         uchar ethaddr[6];
51
52         if (outbuf_len < 21) {
53                 printf("outbuf is too small (%zd < 21)\n", outbuf_len);
54                 return -ENOSPC;
55         }
56
57         if (!eth_env_get_enetaddr_by_index("eth", eth_get_dev_index(), ethaddr))
58                 return -ENOENT;
59
60         sprintf(outbuf, "01-%02x-%02x-%02x-%02x-%02x-%02x",
61                 ethaddr[0], ethaddr[1], ethaddr[2],
62                 ethaddr[3], ethaddr[4], ethaddr[5]);
63
64         return 1;
65 }
66
67 /**
68  * get_bootfile_path() - Figure out the path of a file to read
69  *
70  * Copies the boot directory into the supplied buffer. If there is no boot
71  * directory, set it to ""
72  *
73  * @ctx: PXE context
74  * @file_path: File path to read (relative to the PXE file)
75  * @bootfile_path: Place to put the bootfile path
76  * @bootfile_path_size: Size of @bootfile_path in bytes
77  * @allow_abs_path: true to allow an absolute path (where @file_path starts with
78  *      '/', false to return an empty path (and success) in that case
79  * Returns 1 for success, -ENOSPC if bootfile_path_size is to small to hold the
80  *      resulting path
81  */
82 static int get_bootfile_path(struct pxe_context *ctx, const char *file_path,
83                              char *bootfile_path, size_t bootfile_path_size,
84                              bool allow_abs_path)
85 {
86         size_t path_len = 0;
87
88         /* Only syslinux allows absolute paths */
89         if (file_path[0] == '/' && allow_abs_path)
90                 goto ret;
91
92         path_len = strlen(ctx->bootdir);
93         if (bootfile_path_size < path_len + 1) {
94                 printf("bootfile_path too small. (%zd < %zd)\n",
95                        bootfile_path_size, path_len);
96
97                 return -ENOSPC;
98         }
99
100         strncpy(bootfile_path, ctx->bootdir, path_len);
101
102  ret:
103         bootfile_path[path_len] = '\0';
104
105         return 1;
106 }
107
108 /**
109  * get_relfile() - read a file relative to the PXE file
110  *
111  * As in pxelinux, paths to files referenced from files we retrieve are
112  * relative to the location of bootfile. get_relfile takes such a path and
113  * joins it with the bootfile path to get the full path to the target file. If
114  * the bootfile path is NULL, we use file_path as is.
115  *
116  * @ctx: PXE context
117  * @file_path: File path to read (relative to the PXE file)
118  * @file_addr: Address to load file to
119  * Returns 1 for success, or < 0 on error
120  */
121 static int get_relfile(struct pxe_context *ctx, const char *file_path,
122                        unsigned long file_addr)
123 {
124         size_t path_len;
125         char relfile[MAX_TFTP_PATH_LEN + 1];
126         char addr_buf[18];
127         int err;
128
129         err = get_bootfile_path(ctx, file_path, relfile, sizeof(relfile),
130                                 ctx->allow_abs_path);
131         if (err < 0)
132                 return err;
133
134         path_len = strlen(file_path);
135         path_len += strlen(relfile);
136
137         if (path_len > MAX_TFTP_PATH_LEN) {
138                 printf("Base path too long (%s%s)\n", relfile, file_path);
139
140                 return -ENAMETOOLONG;
141         }
142
143         strcat(relfile, file_path);
144
145         printf("Retrieving file: %s\n", relfile);
146
147         sprintf(addr_buf, "%lx", file_addr);
148
149         return ctx->getfile(ctx, relfile, addr_buf);
150 }
151
152 /**
153  * get_pxe_file() - read a file
154  *
155  * The file is read and nul-terminated
156  *
157  * @ctx: PXE context
158  * @file_path: File path to read (relative to the PXE file)
159  * @file_addr: Address to load file to
160  * Returns 1 for success, or < 0 on error
161  */
162 int get_pxe_file(struct pxe_context *ctx, const char *file_path,
163                  unsigned long file_addr)
164 {
165         unsigned long config_file_size;
166         char *tftp_filesize;
167         int err;
168         char *buf;
169
170         err = get_relfile(ctx, file_path, file_addr);
171         if (err < 0)
172                 return err;
173
174         /*
175          * the file comes without a NUL byte at the end, so find out its size
176          * and add the NUL byte.
177          */
178         tftp_filesize = from_env("filesize");
179         if (!tftp_filesize)
180                 return -ENOENT;
181
182         if (strict_strtoul(tftp_filesize, 16, &config_file_size) < 0)
183                 return -EINVAL;
184
185         buf = map_sysmem(file_addr + config_file_size, 1);
186         *buf = '\0';
187         unmap_sysmem(buf);
188
189         return 1;
190 }
191
192 #define PXELINUX_DIR "pxelinux.cfg/"
193
194 /**
195  * get_pxelinux_path() - Get a file in the pxelinux.cfg/ directory
196  *
197  * @ctx: PXE context
198  * @file: Filename to process (relative to pxelinux.cfg/)
199  * Returns 1 for success, -ENAMETOOLONG if the resulting path is too long.
200  *      or other value < 0 on other error
201  */
202 int get_pxelinux_path(struct pxe_context *ctx, const char *file,
203                       unsigned long pxefile_addr_r)
204 {
205         size_t base_len = strlen(PXELINUX_DIR);
206         char path[MAX_TFTP_PATH_LEN + 1];
207
208         if (base_len + strlen(file) > MAX_TFTP_PATH_LEN) {
209                 printf("path (%s%s) too long, skipping\n",
210                        PXELINUX_DIR, file);
211                 return -ENAMETOOLONG;
212         }
213
214         sprintf(path, PXELINUX_DIR "%s", file);
215
216         return get_pxe_file(ctx, path, pxefile_addr_r);
217 }
218
219 /**
220  * get_relfile_envaddr() - read a file to an address in an env var
221  *
222  * Wrapper to make it easier to store the file at file_path in the location
223  * specified by envaddr_name. file_path will be joined to the bootfile path,
224  * if any is specified.
225  *
226  * @ctx: PXE context
227  * @file_path: File path to read (relative to the PXE file)
228  * @envaddr_name: Name of environment variable which contains the address to
229  *      load to
230  * Returns 1 on success, -ENOENT if @envaddr_name does not exist as an
231  *      environment variable, -EINVAL if its format is not valid hex, or other
232  *      value < 0 on other error
233  */
234 static int get_relfile_envaddr(struct pxe_context *ctx, const char *file_path,
235                                const char *envaddr_name)
236 {
237         unsigned long file_addr;
238         char *envaddr;
239
240         envaddr = from_env(envaddr_name);
241         if (!envaddr)
242                 return -ENOENT;
243
244         if (strict_strtoul(envaddr, 16, &file_addr) < 0)
245                 return -EINVAL;
246
247         return get_relfile(ctx, file_path, file_addr);
248 }
249
250 /**
251  * label_create() - crate a new PXE label
252  *
253  * Allocates memory for and initializes a pxe_label. This uses malloc, so the
254  * result must be free()'d to reclaim the memory.
255  *
256  * Returns a pointer to the label, or NULL if out of memory
257  */
258 static struct pxe_label *label_create(void)
259 {
260         struct pxe_label *label;
261
262         label = malloc(sizeof(struct pxe_label));
263         if (!label)
264                 return NULL;
265
266         memset(label, 0, sizeof(struct pxe_label));
267
268         return label;
269 }
270
271 /**
272  * label_destroy() - free the memory used by a pxe_label
273  *
274  * This frees @label itself as well as memory used by its name,
275  * kernel, config, append, initrd, fdt, fdtdir and fdtoverlay members, if
276  * they're non-NULL.
277  *
278  * So - be sure to only use dynamically allocated memory for the members of
279  * the pxe_label struct, unless you want to clean it up first. These are
280  * currently only created by the pxe file parsing code.
281  *
282  * @label: Label to free
283  */
284 static void label_destroy(struct pxe_label *label)
285 {
286         free(label->name);
287         free(label->kernel);
288         free(label->config);
289         free(label->append);
290         free(label->initrd);
291         free(label->fdt);
292         free(label->fdtdir);
293         free(label->fdtoverlays);
294         free(label);
295 }
296
297 /**
298  * label_print() - Print a label and its string members if they're defined
299  *
300  * This is passed as a callback to the menu code for displaying each
301  * menu entry.
302  *
303  * @data: Label to print (is cast to struct pxe_label *)
304  */
305 static void label_print(void *data)
306 {
307         struct pxe_label *label = data;
308         const char *c = label->menu ? label->menu : label->name;
309
310         printf("%s:\t%s\n", label->num, c);
311 }
312
313 /**
314  * label_localboot() - Boot a label that specified 'localboot'
315  *
316  * This requires that the 'localcmd' environment variable is defined. Its
317  * contents will be executed as U-Boot commands.  If the label specified an
318  * 'append' line, its contents will be used to overwrite the contents of the
319  * 'bootargs' environment variable prior to running 'localcmd'.
320  *
321  * @label: Label to process
322  * Returns 1 on success or < 0 on error
323  */
324 static int label_localboot(struct pxe_label *label)
325 {
326         char *localcmd;
327
328         localcmd = from_env("localcmd");
329         if (!localcmd)
330                 return -ENOENT;
331
332         if (label->append) {
333                 char bootargs[CONFIG_SYS_CBSIZE];
334
335                 cli_simple_process_macros(label->append, bootargs,
336                                           sizeof(bootargs));
337                 env_set("bootargs", bootargs);
338         }
339
340         debug("running: %s\n", localcmd);
341
342         return run_command_list(localcmd, strlen(localcmd), 0);
343 }
344
345 /**
346  * label_boot_fdtoverlay() - Loads fdt overlays specified in 'fdtoverlays'
347  *
348  * @ctx: PXE context
349  * @label: Label to process
350  */
351 #ifdef CONFIG_OF_LIBFDT_OVERLAY
352 static void label_boot_fdtoverlay(struct pxe_context *ctx,
353                                   struct pxe_label *label)
354 {
355         char *fdtoverlay = label->fdtoverlays;
356         struct fdt_header *working_fdt;
357         char *fdtoverlay_addr_env;
358         ulong fdtoverlay_addr;
359         ulong fdt_addr;
360         int err;
361
362         /* Get the main fdt and map it */
363         fdt_addr = hextoul(env_get("fdt_addr_r"), NULL);
364         working_fdt = map_sysmem(fdt_addr, 0);
365         err = fdt_check_header(working_fdt);
366         if (err)
367                 return;
368
369         /* Get the specific overlay loading address */
370         fdtoverlay_addr_env = env_get("fdtoverlay_addr_r");
371         if (!fdtoverlay_addr_env) {
372                 printf("Invalid fdtoverlay_addr_r for loading overlays\n");
373                 return;
374         }
375
376         fdtoverlay_addr = hextoul(fdtoverlay_addr_env, NULL);
377
378         /* Cycle over the overlay files and apply them in order */
379         do {
380                 struct fdt_header *blob;
381                 char *overlayfile;
382                 char *end;
383                 int len;
384
385                 /* Drop leading spaces */
386                 while (*fdtoverlay == ' ')
387                         ++fdtoverlay;
388
389                 /* Copy a single filename if multiple provided */
390                 end = strstr(fdtoverlay, " ");
391                 if (end) {
392                         len = (int)(end - fdtoverlay);
393                         overlayfile = malloc(len + 1);
394                         strncpy(overlayfile, fdtoverlay, len);
395                         overlayfile[len] = '\0';
396                 } else
397                         overlayfile = fdtoverlay;
398
399                 if (!strlen(overlayfile))
400                         goto skip_overlay;
401
402                 /* Load overlay file */
403                 err = get_relfile_envaddr(ctx, overlayfile,
404                                           "fdtoverlay_addr_r");
405                 if (err < 0) {
406                         printf("Failed loading overlay %s\n", overlayfile);
407                         goto skip_overlay;
408                 }
409
410                 /* Resize main fdt */
411                 fdt_shrink_to_minimum(working_fdt, 8192);
412
413                 blob = map_sysmem(fdtoverlay_addr, 0);
414                 err = fdt_check_header(blob);
415                 if (err) {
416                         printf("Invalid overlay %s, skipping\n",
417                                overlayfile);
418                         goto skip_overlay;
419                 }
420
421                 err = fdt_overlay_apply_verbose(working_fdt, blob);
422                 if (err) {
423                         printf("Failed to apply overlay %s, skipping\n",
424                                overlayfile);
425                         goto skip_overlay;
426                 }
427
428 skip_overlay:
429                 if (end)
430                         free(overlayfile);
431         } while ((fdtoverlay = strstr(fdtoverlay, " ")));
432 }
433 #endif
434
435 /**
436  * label_boot() - Boot according to the contents of a pxe_label
437  *
438  * If we can't boot for any reason, we return.  A successful boot never
439  * returns.
440  *
441  * The kernel will be stored in the location given by the 'kernel_addr_r'
442  * environment variable.
443  *
444  * If the label specifies an initrd file, it will be stored in the location
445  * given by the 'ramdisk_addr_r' environment variable.
446  *
447  * If the label specifies an 'append' line, its contents will overwrite that
448  * of the 'bootargs' environment variable.
449  *
450  * @ctx: PXE context
451  * @label: Label to process
452  * Returns does not return on success, otherwise returns 0 if a localboot
453  *      label was processed, or 1 on error
454  */
455 static int label_boot(struct pxe_context *ctx, struct pxe_label *label)
456 {
457         char *bootm_argv[] = { "bootm", NULL, NULL, NULL, NULL };
458         char *zboot_argv[] = { "zboot", NULL, "0", NULL, NULL };
459         char *kernel_addr = NULL;
460         char *initrd_addr_str = NULL;
461         char initrd_filesize[10];
462         char initrd_str[28];
463         char mac_str[29] = "";
464         char ip_str[68] = "";
465         char *fit_addr = NULL;
466         int bootm_argc = 2;
467         int zboot_argc = 3;
468         int len = 0;
469         ulong kernel_addr_r;
470         void *buf;
471
472         label_print(label);
473
474         label->attempted = 1;
475
476         if (label->localboot) {
477                 if (label->localboot_val >= 0)
478                         label_localboot(label);
479                 return 0;
480         }
481
482         if (!label->kernel) {
483                 printf("No kernel given, skipping %s\n",
484                        label->name);
485                 return 1;
486         }
487
488         if (label->initrd) {
489                 if (get_relfile_envaddr(ctx, label->initrd, "ramdisk_addr_r") < 0) {
490                         printf("Skipping %s for failure retrieving initrd\n",
491                                label->name);
492                         return 1;
493                 }
494
495                 initrd_addr_str = env_get("ramdisk_addr_r");
496                 strncpy(initrd_filesize, env_get("filesize"), 9);
497
498                 strncpy(initrd_str, initrd_addr_str, 18);
499                 strcat(initrd_str, ":");
500                 strncat(initrd_str, initrd_filesize, 9);
501         }
502
503         if (get_relfile_envaddr(ctx, label->kernel, "kernel_addr_r") < 0) {
504                 printf("Skipping %s for failure retrieving kernel\n",
505                        label->name);
506                 return 1;
507         }
508
509         if (label->ipappend & 0x1) {
510                 sprintf(ip_str, " ip=%s:%s:%s:%s",
511                         env_get("ipaddr"), env_get("serverip"),
512                         env_get("gatewayip"), env_get("netmask"));
513         }
514
515         if (IS_ENABLED(CONFIG_CMD_NET)) {
516                 if (label->ipappend & 0x2) {
517                         int err;
518
519                         strcpy(mac_str, " BOOTIF=");
520                         err = format_mac_pxe(mac_str + 8, sizeof(mac_str) - 8);
521                         if (err < 0)
522                                 mac_str[0] = '\0';
523                 }
524         }
525
526         if ((label->ipappend & 0x3) || label->append) {
527                 char bootargs[CONFIG_SYS_CBSIZE] = "";
528                 char finalbootargs[CONFIG_SYS_CBSIZE];
529
530                 if (strlen(label->append ?: "") +
531                     strlen(ip_str) + strlen(mac_str) + 1 > sizeof(bootargs)) {
532                         printf("bootarg overflow %zd+%zd+%zd+1 > %zd\n",
533                                strlen(label->append ?: ""),
534                                strlen(ip_str), strlen(mac_str),
535                                sizeof(bootargs));
536                         return 1;
537                 }
538
539                 if (label->append)
540                         strncpy(bootargs, label->append, sizeof(bootargs));
541
542                 strcat(bootargs, ip_str);
543                 strcat(bootargs, mac_str);
544
545                 cli_simple_process_macros(bootargs, finalbootargs,
546                                           sizeof(finalbootargs));
547                 env_set("bootargs", finalbootargs);
548                 printf("append: %s\n", finalbootargs);
549         }
550
551         kernel_addr = env_get("kernel_addr_r");
552
553         /* for FIT, append the configuration identifier */
554         if (label->config) {
555                 int len = strlen(kernel_addr) + strlen(label->config) + 1;
556
557                 fit_addr = malloc(len);
558                 if (!fit_addr) {
559                         printf("malloc fail (FIT address)\n");
560                         return 1;
561                 }
562                 snprintf(fit_addr, len, "%s%s", kernel_addr, label->config);
563                 kernel_addr = fit_addr;
564         }
565
566         /*
567          * fdt usage is optional:
568          * It handles the following scenarios.
569          *
570          * Scenario 1: If fdt_addr_r specified and "fdt" or "fdtdir" label is
571          * defined in pxe file, retrieve fdt blob from server. Pass fdt_addr_r to
572          * bootm, and adjust argc appropriately.
573          *
574          * If retrieve fails and no exact fdt blob is specified in pxe file with
575          * "fdt" label, try Scenario 2.
576          *
577          * Scenario 2: If there is an fdt_addr specified, pass it along to
578          * bootm, and adjust argc appropriately.
579          *
580          * Scenario 3: fdt blob is not available.
581          */
582         bootm_argv[3] = env_get("fdt_addr_r");
583
584         /* if fdt label is defined then get fdt from server */
585         if (bootm_argv[3]) {
586                 char *fdtfile = NULL;
587                 char *fdtfilefree = NULL;
588
589                 if (label->fdt) {
590                         fdtfile = label->fdt;
591                 } else if (label->fdtdir) {
592                         char *f1, *f2, *f3, *f4, *slash;
593
594                         f1 = env_get("fdtfile");
595                         if (f1) {
596                                 f2 = "";
597                                 f3 = "";
598                                 f4 = "";
599                         } else {
600                                 /*
601                                  * For complex cases where this code doesn't
602                                  * generate the correct filename, the board
603                                  * code should set $fdtfile during early boot,
604                                  * or the boot scripts should set $fdtfile
605                                  * before invoking "pxe" or "sysboot".
606                                  */
607                                 f1 = env_get("soc");
608                                 f2 = "-";
609                                 f3 = env_get("board");
610                                 f4 = ".dtb";
611                                 if (!f1) {
612                                         f1 = "";
613                                         f2 = "";
614                                 }
615                                 if (!f3) {
616                                         f2 = "";
617                                         f3 = "";
618                                 }
619                         }
620
621                         len = strlen(label->fdtdir);
622                         if (!len)
623                                 slash = "./";
624                         else if (label->fdtdir[len - 1] != '/')
625                                 slash = "/";
626                         else
627                                 slash = "";
628
629                         len = strlen(label->fdtdir) + strlen(slash) +
630                                 strlen(f1) + strlen(f2) + strlen(f3) +
631                                 strlen(f4) + 1;
632                         fdtfilefree = malloc(len);
633                         if (!fdtfilefree) {
634                                 printf("malloc fail (FDT filename)\n");
635                                 goto cleanup;
636                         }
637
638                         snprintf(fdtfilefree, len, "%s%s%s%s%s%s",
639                                  label->fdtdir, slash, f1, f2, f3, f4);
640                         fdtfile = fdtfilefree;
641                 }
642
643                 if (fdtfile) {
644                         int err = get_relfile_envaddr(ctx, fdtfile,
645                                                       "fdt_addr_r");
646
647                         free(fdtfilefree);
648                         if (err < 0) {
649                                 bootm_argv[3] = NULL;
650
651                                 if (label->fdt) {
652                                         printf("Skipping %s for failure retrieving FDT\n",
653                                                label->name);
654                                         goto cleanup;
655                                 }
656                         }
657
658 #ifdef CONFIG_OF_LIBFDT_OVERLAY
659                         if (label->fdtoverlays)
660                                 label_boot_fdtoverlay(ctx, label);
661 #endif
662                 } else {
663                         bootm_argv[3] = NULL;
664                 }
665         }
666
667         bootm_argv[1] = kernel_addr;
668         zboot_argv[1] = kernel_addr;
669
670         if (initrd_addr_str) {
671                 bootm_argv[2] = initrd_str;
672                 bootm_argc = 3;
673
674                 zboot_argv[3] = initrd_addr_str;
675                 zboot_argv[4] = initrd_filesize;
676                 zboot_argc = 5;
677         }
678
679         if (!bootm_argv[3])
680                 bootm_argv[3] = env_get("fdt_addr");
681
682         if (bootm_argv[3]) {
683                 if (!bootm_argv[2])
684                         bootm_argv[2] = "-";
685                 bootm_argc = 4;
686         }
687
688         kernel_addr_r = genimg_get_kernel_addr(kernel_addr);
689         buf = map_sysmem(kernel_addr_r, 0);
690         /* Try bootm for legacy and FIT format image */
691         if (genimg_get_format(buf) != IMAGE_FORMAT_INVALID)
692                 do_bootm(ctx->cmdtp, 0, bootm_argc, bootm_argv);
693         /* Try booting an AArch64 Linux kernel image */
694         else if (IS_ENABLED(CONFIG_CMD_BOOTI))
695                 do_booti(ctx->cmdtp, 0, bootm_argc, bootm_argv);
696         /* Try booting a Image */
697         else if (IS_ENABLED(CONFIG_CMD_BOOTZ))
698                 do_bootz(ctx->cmdtp, 0, bootm_argc, bootm_argv);
699         /* Try booting an x86_64 Linux kernel image */
700         else if (IS_ENABLED(CONFIG_CMD_ZBOOT))
701                 do_zboot_parent(ctx->cmdtp, 0, zboot_argc, zboot_argv, NULL);
702
703         unmap_sysmem(buf);
704
705 cleanup:
706         free(fit_addr);
707
708         return 1;
709 }
710
711 /** enum token_type - Tokens for the pxe file parser */
712 enum token_type {
713         T_EOL,
714         T_STRING,
715         T_EOF,
716         T_MENU,
717         T_TITLE,
718         T_TIMEOUT,
719         T_LABEL,
720         T_KERNEL,
721         T_LINUX,
722         T_APPEND,
723         T_INITRD,
724         T_LOCALBOOT,
725         T_DEFAULT,
726         T_PROMPT,
727         T_INCLUDE,
728         T_FDT,
729         T_FDTDIR,
730         T_FDTOVERLAYS,
731         T_ONTIMEOUT,
732         T_IPAPPEND,
733         T_BACKGROUND,
734         T_INVALID
735 };
736
737 /** struct token - token - given by a value and a type */
738 struct token {
739         char *val;
740         enum token_type type;
741 };
742
743 /* Keywords recognized */
744 static const struct token keywords[] = {
745         {"menu", T_MENU},
746         {"title", T_TITLE},
747         {"timeout", T_TIMEOUT},
748         {"default", T_DEFAULT},
749         {"prompt", T_PROMPT},
750         {"label", T_LABEL},
751         {"kernel", T_KERNEL},
752         {"linux", T_LINUX},
753         {"localboot", T_LOCALBOOT},
754         {"append", T_APPEND},
755         {"initrd", T_INITRD},
756         {"include", T_INCLUDE},
757         {"devicetree", T_FDT},
758         {"fdt", T_FDT},
759         {"devicetreedir", T_FDTDIR},
760         {"fdtdir", T_FDTDIR},
761         {"fdtoverlays", T_FDTOVERLAYS},
762         {"ontimeout", T_ONTIMEOUT,},
763         {"ipappend", T_IPAPPEND,},
764         {"background", T_BACKGROUND,},
765         {NULL, T_INVALID}
766 };
767
768 /**
769  * enum lex_state - lexer state
770  *
771  * Since pxe(linux) files don't have a token to identify the start of a
772  * literal, we have to keep track of when we're in a state where a literal is
773  * expected vs when we're in a state a keyword is expected.
774  */
775 enum lex_state {
776         L_NORMAL = 0,
777         L_KEYWORD,
778         L_SLITERAL
779 };
780
781 /**
782  * get_string() - retrieves a string from *p and stores it as a token in *t.
783  *
784  * This is used for scanning both string literals and keywords.
785  *
786  * Characters from *p are copied into t-val until a character equal to
787  * delim is found, or a NUL byte is reached. If delim has the special value of
788  * ' ', any whitespace character will be used as a delimiter.
789  *
790  * If lower is unequal to 0, uppercase characters will be converted to
791  * lowercase in the result. This is useful to make keywords case
792  * insensitive.
793  *
794  * The location of *p is updated to point to the first character after the end
795  * of the token - the ending delimiter.
796  *
797  * Memory for t->val is allocated using malloc and must be free()'d to reclaim
798  * it.
799  *
800  * @p: Points to a pointer to the current position in the input being processed.
801  *      Updated to point at the first character after the current token
802  * @t: Pointers to a token to fill in
803  * @delim: Delimiter character to look for, either newline or space
804  * @lower: true to convert the string to lower case when storing
805  * Returns the new value of t->val, on success, NULL if out of memory
806  */
807 static char *get_string(char **p, struct token *t, char delim, int lower)
808 {
809         char *b, *e;
810         size_t len, i;
811
812         /*
813          * b and e both start at the beginning of the input stream.
814          *
815          * e is incremented until we find the ending delimiter, or a NUL byte
816          * is reached. Then, we take e - b to find the length of the token.
817          */
818         b = *p;
819         e = *p;
820         while (*e) {
821                 if ((delim == ' ' && isspace(*e)) || delim == *e)
822                         break;
823                 e++;
824         }
825
826         len = e - b;
827
828         /*
829          * Allocate memory to hold the string, and copy it in, converting
830          * characters to lowercase if lower is != 0.
831          */
832         t->val = malloc(len + 1);
833         if (!t->val)
834                 return NULL;
835
836         for (i = 0; i < len; i++, b++) {
837                 if (lower)
838                         t->val[i] = tolower(*b);
839                 else
840                         t->val[i] = *b;
841         }
842
843         t->val[len] = '\0';
844
845         /* Update *p so the caller knows where to continue scanning */
846         *p = e;
847         t->type = T_STRING;
848
849         return t->val;
850 }
851
852 /**
853  * get_keyword() - Populate a keyword token with a type and value
854  *
855  * Updates the ->type field based on the keyword string in @val
856  * @t: Token to populate
857  */
858 static void get_keyword(struct token *t)
859 {
860         int i;
861
862         for (i = 0; keywords[i].val; i++) {
863                 if (!strcmp(t->val, keywords[i].val)) {
864                         t->type = keywords[i].type;
865                         break;
866                 }
867         }
868 }
869
870 /**
871  * get_token() - Get the next token
872  *
873  * We have to keep track of which state we're in to know if we're looking to get
874  * a string literal or a keyword.
875  *
876  * @p: Points to a pointer to the current position in the input being processed.
877  *      Updated to point at the first character after the current token
878  */
879 static void get_token(char **p, struct token *t, enum lex_state state)
880 {
881         char *c = *p;
882
883         t->type = T_INVALID;
884
885         /* eat non EOL whitespace */
886         while (isblank(*c))
887                 c++;
888
889         /*
890          * eat comments. note that string literals can't begin with #, but
891          * can contain a # after their first character.
892          */
893         if (*c == '#') {
894                 while (*c && *c != '\n')
895                         c++;
896         }
897
898         if (*c == '\n') {
899                 t->type = T_EOL;
900                 c++;
901         } else if (*c == '\0') {
902                 t->type = T_EOF;
903                 c++;
904         } else if (state == L_SLITERAL) {
905                 get_string(&c, t, '\n', 0);
906         } else if (state == L_KEYWORD) {
907                 /*
908                  * when we expect a keyword, we first get the next string
909                  * token delimited by whitespace, and then check if it
910                  * matches a keyword in our keyword list. if it does, it's
911                  * converted to a keyword token of the appropriate type, and
912                  * if not, it remains a string token.
913                  */
914                 get_string(&c, t, ' ', 1);
915                 get_keyword(t);
916         }
917
918         *p = c;
919 }
920
921 /**
922  * eol_or_eof() - Find end of line
923  *
924  * Increment *c until we get to the end of the current line, or EOF
925  *
926  * @c: Points to a pointer to the current position in the input being processed.
927  *      Updated to point at the first character after the current token
928  */
929 static void eol_or_eof(char **c)
930 {
931         while (**c && **c != '\n')
932                 (*c)++;
933 }
934
935 /*
936  * All of these parse_* functions share some common behavior.
937  *
938  * They finish with *c pointing after the token they parse, and return 1 on
939  * success, or < 0 on error.
940  */
941
942 /*
943  * Parse a string literal and store a pointer it at *dst. String literals
944  * terminate at the end of the line.
945  */
946 static int parse_sliteral(char **c, char **dst)
947 {
948         struct token t;
949         char *s = *c;
950
951         get_token(c, &t, L_SLITERAL);
952
953         if (t.type != T_STRING) {
954                 printf("Expected string literal: %.*s\n", (int)(*c - s), s);
955                 return -EINVAL;
956         }
957
958         *dst = t.val;
959
960         return 1;
961 }
962
963 /*
964  * Parse a base 10 (unsigned) integer and store it at *dst.
965  */
966 static int parse_integer(char **c, int *dst)
967 {
968         struct token t;
969         char *s = *c;
970
971         get_token(c, &t, L_SLITERAL);
972         if (t.type != T_STRING) {
973                 printf("Expected string: %.*s\n", (int)(*c - s), s);
974                 return -EINVAL;
975         }
976
977         *dst = simple_strtol(t.val, NULL, 10);
978
979         free(t.val);
980
981         return 1;
982 }
983
984 static int parse_pxefile_top(struct pxe_context *ctx, char *p, ulong base,
985                              struct pxe_menu *cfg, int nest_level);
986
987 /*
988  * Parse an include statement, and retrieve and parse the file it mentions.
989  *
990  * base should point to a location where it's safe to store the file, and
991  * nest_level should indicate how many nested includes have occurred. For this
992  * include, nest_level has already been incremented and doesn't need to be
993  * incremented here.
994  */
995 static int handle_include(struct pxe_context *ctx, char **c, unsigned long base,
996                           struct pxe_menu *cfg, int nest_level)
997 {
998         char *include_path;
999         char *s = *c;
1000         int err;
1001         char *buf;
1002         int ret;
1003
1004         err = parse_sliteral(c, &include_path);
1005         if (err < 0) {
1006                 printf("Expected include path: %.*s\n", (int)(*c - s), s);
1007                 return err;
1008         }
1009
1010         err = get_pxe_file(ctx, include_path, base);
1011         if (err < 0) {
1012                 printf("Couldn't retrieve %s\n", include_path);
1013                 return err;
1014         }
1015
1016         buf = map_sysmem(base, 0);
1017         ret = parse_pxefile_top(ctx, buf, base, cfg, nest_level);
1018         unmap_sysmem(buf);
1019
1020         return ret;
1021 }
1022
1023 /*
1024  * Parse lines that begin with 'menu'.
1025  *
1026  * base and nest are provided to handle the 'menu include' case.
1027  *
1028  * base should point to a location where it's safe to store the included file.
1029  *
1030  * nest_level should be 1 when parsing the top level pxe file, 2 when parsing
1031  * a file it includes, 3 when parsing a file included by that file, and so on.
1032  */
1033 static int parse_menu(struct pxe_context *ctx, char **c, struct pxe_menu *cfg,
1034                       unsigned long base, int nest_level)
1035 {
1036         struct token t;
1037         char *s = *c;
1038         int err = 0;
1039
1040         get_token(c, &t, L_KEYWORD);
1041
1042         switch (t.type) {
1043         case T_TITLE:
1044                 err = parse_sliteral(c, &cfg->title);
1045
1046                 break;
1047
1048         case T_INCLUDE:
1049                 err = handle_include(ctx, c, base, cfg, nest_level + 1);
1050                 break;
1051
1052         case T_BACKGROUND:
1053                 err = parse_sliteral(c, &cfg->bmp);
1054                 break;
1055
1056         default:
1057                 printf("Ignoring malformed menu command: %.*s\n",
1058                        (int)(*c - s), s);
1059         }
1060         if (err < 0)
1061                 return err;
1062
1063         eol_or_eof(c);
1064
1065         return 1;
1066 }
1067
1068 /*
1069  * Handles parsing a 'menu line' when we're parsing a label.
1070  */
1071 static int parse_label_menu(char **c, struct pxe_menu *cfg,
1072                             struct pxe_label *label)
1073 {
1074         struct token t;
1075         char *s;
1076
1077         s = *c;
1078
1079         get_token(c, &t, L_KEYWORD);
1080
1081         switch (t.type) {
1082         case T_DEFAULT:
1083                 if (!cfg->default_label)
1084                         cfg->default_label = strdup(label->name);
1085
1086                 if (!cfg->default_label)
1087                         return -ENOMEM;
1088
1089                 break;
1090         case T_LABEL:
1091                 parse_sliteral(c, &label->menu);
1092                 break;
1093         default:
1094                 printf("Ignoring malformed menu command: %.*s\n",
1095                        (int)(*c - s), s);
1096         }
1097
1098         eol_or_eof(c);
1099
1100         return 0;
1101 }
1102
1103 /*
1104  * Handles parsing a 'kernel' label.
1105  * expecting "filename" or "<fit_filename>#cfg"
1106  */
1107 static int parse_label_kernel(char **c, struct pxe_label *label)
1108 {
1109         char *s;
1110         int err;
1111
1112         err = parse_sliteral(c, &label->kernel);
1113         if (err < 0)
1114                 return err;
1115
1116         s = strstr(label->kernel, "#");
1117         if (!s)
1118                 return 1;
1119
1120         label->config = malloc(strlen(s) + 1);
1121         if (!label->config)
1122                 return -ENOMEM;
1123
1124         strcpy(label->config, s);
1125         *s = 0;
1126
1127         return 1;
1128 }
1129
1130 /*
1131  * Parses a label and adds it to the list of labels for a menu.
1132  *
1133  * A label ends when we either get to the end of a file, or
1134  * get some input we otherwise don't have a handler defined
1135  * for.
1136  *
1137  */
1138 static int parse_label(char **c, struct pxe_menu *cfg)
1139 {
1140         struct token t;
1141         int len;
1142         char *s = *c;
1143         struct pxe_label *label;
1144         int err;
1145
1146         label = label_create();
1147         if (!label)
1148                 return -ENOMEM;
1149
1150         err = parse_sliteral(c, &label->name);
1151         if (err < 0) {
1152                 printf("Expected label name: %.*s\n", (int)(*c - s), s);
1153                 label_destroy(label);
1154                 return -EINVAL;
1155         }
1156
1157         list_add_tail(&label->list, &cfg->labels);
1158
1159         while (1) {
1160                 s = *c;
1161                 get_token(c, &t, L_KEYWORD);
1162
1163                 err = 0;
1164                 switch (t.type) {
1165                 case T_MENU:
1166                         err = parse_label_menu(c, cfg, label);
1167                         break;
1168
1169                 case T_KERNEL:
1170                 case T_LINUX:
1171                         err = parse_label_kernel(c, label);
1172                         break;
1173
1174                 case T_APPEND:
1175                         err = parse_sliteral(c, &label->append);
1176                         if (label->initrd)
1177                                 break;
1178                         s = strstr(label->append, "initrd=");
1179                         if (!s)
1180                                 break;
1181                         s += 7;
1182                         len = (int)(strchr(s, ' ') - s);
1183                         label->initrd = malloc(len + 1);
1184                         strncpy(label->initrd, s, len);
1185                         label->initrd[len] = '\0';
1186
1187                         break;
1188
1189                 case T_INITRD:
1190                         if (!label->initrd)
1191                                 err = parse_sliteral(c, &label->initrd);
1192                         break;
1193
1194                 case T_FDT:
1195                         if (!label->fdt)
1196                                 err = parse_sliteral(c, &label->fdt);
1197                         break;
1198
1199                 case T_FDTDIR:
1200                         if (!label->fdtdir)
1201                                 err = parse_sliteral(c, &label->fdtdir);
1202                         break;
1203
1204                 case T_FDTOVERLAYS:
1205                         if (!label->fdtoverlays)
1206                                 err = parse_sliteral(c, &label->fdtoverlays);
1207                         break;
1208
1209                 case T_LOCALBOOT:
1210                         label->localboot = 1;
1211                         err = parse_integer(c, &label->localboot_val);
1212                         break;
1213
1214                 case T_IPAPPEND:
1215                         err = parse_integer(c, &label->ipappend);
1216                         break;
1217
1218                 case T_EOL:
1219                         break;
1220
1221                 default:
1222                         /*
1223                          * put the token back! we don't want it - it's the end
1224                          * of a label and whatever token this is, it's
1225                          * something for the menu level context to handle.
1226                          */
1227                         *c = s;
1228                         return 1;
1229                 }
1230
1231                 if (err < 0)
1232                         return err;
1233         }
1234 }
1235
1236 /*
1237  * This 16 comes from the limit pxelinux imposes on nested includes.
1238  *
1239  * There is no reason at all we couldn't do more, but some limit helps prevent
1240  * infinite (until crash occurs) recursion if a file tries to include itself.
1241  */
1242 #define MAX_NEST_LEVEL 16
1243
1244 /*
1245  * Entry point for parsing a menu file. nest_level indicates how many times
1246  * we've nested in includes.  It will be 1 for the top level menu file.
1247  *
1248  * Returns 1 on success, < 0 on error.
1249  */
1250 static int parse_pxefile_top(struct pxe_context *ctx, char *p, unsigned long base,
1251                              struct pxe_menu *cfg, int nest_level)
1252 {
1253         struct token t;
1254         char *s, *b, *label_name;
1255         int err;
1256
1257         b = p;
1258
1259         if (nest_level > MAX_NEST_LEVEL) {
1260                 printf("Maximum nesting (%d) exceeded\n", MAX_NEST_LEVEL);
1261                 return -EMLINK;
1262         }
1263
1264         while (1) {
1265                 s = p;
1266
1267                 get_token(&p, &t, L_KEYWORD);
1268
1269                 err = 0;
1270                 switch (t.type) {
1271                 case T_MENU:
1272                         cfg->prompt = 1;
1273                         err = parse_menu(ctx, &p, cfg,
1274                                          base + ALIGN(strlen(b) + 1, 4),
1275                                          nest_level);
1276                         break;
1277
1278                 case T_TIMEOUT:
1279                         err = parse_integer(&p, &cfg->timeout);
1280                         break;
1281
1282                 case T_LABEL:
1283                         err = parse_label(&p, cfg);
1284                         break;
1285
1286                 case T_DEFAULT:
1287                 case T_ONTIMEOUT:
1288                         err = parse_sliteral(&p, &label_name);
1289
1290                         if (label_name) {
1291                                 if (cfg->default_label)
1292                                         free(cfg->default_label);
1293
1294                                 cfg->default_label = label_name;
1295                         }
1296
1297                         break;
1298
1299                 case T_INCLUDE:
1300                         err = handle_include(ctx, &p,
1301                                              base + ALIGN(strlen(b), 4), cfg,
1302                                              nest_level + 1);
1303                         break;
1304
1305                 case T_PROMPT:
1306                         eol_or_eof(&p);
1307                         break;
1308
1309                 case T_EOL:
1310                         break;
1311
1312                 case T_EOF:
1313                         return 1;
1314
1315                 default:
1316                         printf("Ignoring unknown command: %.*s\n",
1317                                (int)(p - s), s);
1318                         eol_or_eof(&p);
1319                 }
1320
1321                 if (err < 0)
1322                         return err;
1323         }
1324 }
1325
1326 /*
1327  */
1328 void destroy_pxe_menu(struct pxe_menu *cfg)
1329 {
1330         struct list_head *pos, *n;
1331         struct pxe_label *label;
1332
1333         free(cfg->title);
1334         free(cfg->default_label);
1335
1336         list_for_each_safe(pos, n, &cfg->labels) {
1337                 label = list_entry(pos, struct pxe_label, list);
1338
1339                 label_destroy(label);
1340         }
1341
1342         free(cfg);
1343 }
1344
1345 struct pxe_menu *parse_pxefile(struct pxe_context *ctx, unsigned long menucfg)
1346 {
1347         struct pxe_menu *cfg;
1348         char *buf;
1349         int r;
1350
1351         cfg = malloc(sizeof(struct pxe_menu));
1352         if (!cfg)
1353                 return NULL;
1354
1355         memset(cfg, 0, sizeof(struct pxe_menu));
1356
1357         INIT_LIST_HEAD(&cfg->labels);
1358
1359         buf = map_sysmem(menucfg, 0);
1360         r = parse_pxefile_top(ctx, buf, menucfg, cfg, 1);
1361         unmap_sysmem(buf);
1362         if (r < 0) {
1363                 destroy_pxe_menu(cfg);
1364                 return NULL;
1365         }
1366
1367         return cfg;
1368 }
1369
1370 /*
1371  * Converts a pxe_menu struct into a menu struct for use with U-Boot's generic
1372  * menu code.
1373  */
1374 static struct menu *pxe_menu_to_menu(struct pxe_menu *cfg)
1375 {
1376         struct pxe_label *label;
1377         struct list_head *pos;
1378         struct menu *m;
1379         int err;
1380         int i = 1;
1381         char *default_num = NULL;
1382
1383         /*
1384          * Create a menu and add items for all the labels.
1385          */
1386         m = menu_create(cfg->title, DIV_ROUND_UP(cfg->timeout, 10),
1387                         cfg->prompt, NULL, label_print, NULL, NULL);
1388         if (!m)
1389                 return NULL;
1390
1391         list_for_each(pos, &cfg->labels) {
1392                 label = list_entry(pos, struct pxe_label, list);
1393
1394                 sprintf(label->num, "%d", i++);
1395                 if (menu_item_add(m, label->num, label) != 1) {
1396                         menu_destroy(m);
1397                         return NULL;
1398                 }
1399                 if (cfg->default_label &&
1400                     (strcmp(label->name, cfg->default_label) == 0))
1401                         default_num = label->num;
1402         }
1403
1404         /*
1405          * After we've created items for each label in the menu, set the
1406          * menu's default label if one was specified.
1407          */
1408         if (default_num) {
1409                 err = menu_default_set(m, default_num);
1410                 if (err != 1) {
1411                         if (err != -ENOENT) {
1412                                 menu_destroy(m);
1413                                 return NULL;
1414                         }
1415
1416                         printf("Missing default: %s\n", cfg->default_label);
1417                 }
1418         }
1419
1420         return m;
1421 }
1422
1423 /*
1424  * Try to boot any labels we have yet to attempt to boot.
1425  */
1426 static void boot_unattempted_labels(struct pxe_context *ctx,
1427                                     struct pxe_menu *cfg)
1428 {
1429         struct list_head *pos;
1430         struct pxe_label *label;
1431
1432         list_for_each(pos, &cfg->labels) {
1433                 label = list_entry(pos, struct pxe_label, list);
1434
1435                 if (!label->attempted)
1436                         label_boot(ctx, label);
1437         }
1438 }
1439
1440 void handle_pxe_menu(struct pxe_context *ctx, struct pxe_menu *cfg)
1441 {
1442         void *choice;
1443         struct menu *m;
1444         int err;
1445
1446         if (IS_ENABLED(CONFIG_CMD_BMP)) {
1447                 /* display BMP if available */
1448                 if (cfg->bmp) {
1449                         if (get_relfile(ctx, cfg->bmp, image_load_addr)) {
1450                                 if (CONFIG_IS_ENABLED(CMD_CLS))
1451                                         run_command("cls", 0);
1452                                 bmp_display(image_load_addr,
1453                                             BMP_ALIGN_CENTER, BMP_ALIGN_CENTER);
1454                         } else {
1455                                 printf("Skipping background bmp %s for failure\n",
1456                                        cfg->bmp);
1457                         }
1458                 }
1459         }
1460
1461         m = pxe_menu_to_menu(cfg);
1462         if (!m)
1463                 return;
1464
1465         err = menu_get_choice(m, &choice);
1466         menu_destroy(m);
1467
1468         /*
1469          * err == 1 means we got a choice back from menu_get_choice.
1470          *
1471          * err == -ENOENT if the menu was setup to select the default but no
1472          * default was set. in that case, we should continue trying to boot
1473          * labels that haven't been attempted yet.
1474          *
1475          * otherwise, the user interrupted or there was some other error and
1476          * we give up.
1477          */
1478
1479         if (err == 1) {
1480                 err = label_boot(ctx, choice);
1481                 if (!err)
1482                         return;
1483         } else if (err != -ENOENT) {
1484                 return;
1485         }
1486
1487         boot_unattempted_labels(ctx, cfg);
1488 }
1489
1490 int pxe_setup_ctx(struct pxe_context *ctx, struct cmd_tbl *cmdtp,
1491                   pxe_getfile_func getfile, void *userdata,
1492                   bool allow_abs_path, const char *bootfile)
1493 {
1494         const char *last_slash;
1495         size_t path_len = 0;
1496
1497         memset(ctx, '\0', sizeof(*ctx));
1498         ctx->cmdtp = cmdtp;
1499         ctx->getfile = getfile;
1500         ctx->userdata = userdata;
1501         ctx->allow_abs_path = allow_abs_path;
1502
1503         /* figure out the boot directory, if there is one */
1504         if (bootfile && strlen(bootfile) >= MAX_TFTP_PATH_LEN)
1505                 return -ENOSPC;
1506         ctx->bootdir = strdup(bootfile ? bootfile : "");
1507         if (!ctx->bootdir)
1508                 return -ENOMEM;
1509
1510         if (bootfile) {
1511                 last_slash = strrchr(bootfile, '/');
1512                 if (last_slash)
1513                         path_len = (last_slash - bootfile) + 1;
1514         }
1515         ctx->bootdir[path_len] = '\0';
1516
1517         return 0;
1518 }
1519
1520 void pxe_destroy_ctx(struct pxe_context *ctx)
1521 {
1522         free(ctx->bootdir);
1523 }
1524
1525 int pxe_process(struct pxe_context *ctx, ulong pxefile_addr_r, bool prompt)
1526 {
1527         struct pxe_menu *cfg;
1528
1529         cfg = parse_pxefile(ctx, pxefile_addr_r);
1530         if (!cfg) {
1531                 printf("Error parsing config file\n");
1532                 return 1;
1533         }
1534
1535         if (prompt)
1536                 cfg->prompt = 1;
1537
1538         handle_pxe_menu(ctx, cfg);
1539
1540         destroy_pxe_menu(cfg);
1541
1542         return 0;
1543 }