diff options
author | Tom Rini <trini@ti.com> | 2013-06-24 22:27:44 -0400 |
---|---|---|
committer | Tom Rini <trini@ti.com> | 2013-06-24 22:27:44 -0400 |
commit | ca85eb8c4271509aaac1ccb26ae3eb1a7827b4e6 (patch) | |
tree | 1532b13194c3d7daa8f1f10f3263fb806911cd67 /common/cmd_pxe.c | |
parent | 4e78e0317d3aab42c381b01033a0cd869ea28979 (diff) | |
parent | 433a2c5325b982b49b099e526d373d07d0cc5e97 (diff) |
Merge branch 'master' of git://git.denx.de/u-boot-net
Diffstat (limited to 'common/cmd_pxe.c')
-rw-r--r-- | common/cmd_pxe.c | 221 |
1 files changed, 136 insertions, 85 deletions
diff --git a/common/cmd_pxe.c b/common/cmd_pxe.c index 2dbd49cbd6..1fb75d8ae9 100644 --- a/common/cmd_pxe.c +++ b/common/cmd_pxe.c @@ -26,12 +26,21 @@ #define MAX_TFTP_PATH_LEN 127 +const char *pxe_default_paths[] = { +#ifdef CONFIG_SYS_SOC + "default-" CONFIG_SYS_ARCH "-" CONFIG_SYS_SOC, +#endif + "default-" CONFIG_SYS_ARCH, + "default", + NULL +}; + /* * Like getenv, but prints an error if envvar isn't defined in the * environment. It always returns what getenv does, so it can be used in * place of getenv without changing error handling otherwise. */ -static char *from_env(char *envvar) +static char *from_env(const char *envvar) { char *ret; @@ -55,37 +64,21 @@ static char *from_env(char *envvar) */ static int format_mac_pxe(char *outbuf, size_t outbuf_len) { - size_t ethaddr_len; - char *p, *ethaddr; - - ethaddr = from_env("ethaddr"); + uchar ethaddr[6]; - if (!ethaddr) - return -ENOENT; - - ethaddr_len = strlen(ethaddr); - - /* - * ethaddr_len + 4 gives room for "01-", ethaddr, and a NUL byte at - * the end. - */ - if (outbuf_len < ethaddr_len + 4) { - printf("outbuf is too small (%d < %d)\n", - outbuf_len, ethaddr_len + 4); + if (outbuf_len < 21) { + printf("outbuf is too small (%d < 21)\n", outbuf_len); return -EINVAL; } - strcpy(outbuf, "01-"); - - for (p = outbuf + 3; *ethaddr; ethaddr++, p++) { - if (*ethaddr == ':') - *p = '-'; - else - *p = tolower(*ethaddr); - } + if (!eth_getenv_enetaddr_by_index("eth", eth_get_dev_index(), + ethaddr)) + return -ENOENT; - *p = '\0'; + sprintf(outbuf, "01-%02x-%02x-%02x-%02x-%02x-%02x", + ethaddr[0], ethaddr[1], ethaddr[2], + ethaddr[3], ethaddr[4], ethaddr[5]); return 1; } @@ -131,14 +124,14 @@ static int get_bootfile_path(const char *file_path, char *bootfile_path, return 1; } -static int (*do_getfile)(char *file_path, char *file_addr); +static int (*do_getfile)(const char *file_path, char *file_addr); -static int do_get_tftp(char *file_path, char *file_addr) +static int do_get_tftp(const char *file_path, char *file_addr) { char *tftp_argv[] = {"tftp", NULL, NULL, NULL}; tftp_argv[1] = file_addr; - tftp_argv[2] = file_path; + tftp_argv[2] = (void *)file_path; if (do_tftpb(NULL, 0, 3, tftp_argv)) return -ENOENT; @@ -148,12 +141,12 @@ static int do_get_tftp(char *file_path, char *file_addr) static char *fs_argv[5]; -static int do_get_ext2(char *file_path, char *file_addr) +static int do_get_ext2(const char *file_path, char *file_addr) { #ifdef CONFIG_CMD_EXT2 fs_argv[0] = "ext2load"; fs_argv[3] = file_addr; - fs_argv[4] = file_path; + fs_argv[4] = (void *)file_path; if (!do_ext2load(NULL, 0, 5, fs_argv)) return 1; @@ -161,12 +154,12 @@ static int do_get_ext2(char *file_path, char *file_addr) return -ENOENT; } -static int do_get_fat(char *file_path, char *file_addr) +static int do_get_fat(const char *file_path, char *file_addr) { #ifdef CONFIG_CMD_FAT fs_argv[0] = "fatload"; fs_argv[3] = file_addr; - fs_argv[4] = file_path; + fs_argv[4] = (void *)file_path; if (!do_fat_fsload(NULL, 0, 5, fs_argv)) return 1; @@ -182,7 +175,7 @@ static int do_get_fat(char *file_path, char *file_addr) * * Returns 1 for success, or < 0 on error. */ -static int get_relfile(char *file_path, void *file_addr) +static int get_relfile(const char *file_path, void *file_addr) { size_t path_len; char relfile[MAX_TFTP_PATH_LEN+1]; @@ -221,7 +214,7 @@ static int get_relfile(char *file_path, void *file_addr) * * Returns 1 on success, or < 0 for error. */ -static int get_pxe_file(char *file_path, void *file_addr) +static int get_pxe_file(const char *file_path, void *file_addr) { unsigned long config_file_size; char *tftp_filesize; @@ -258,7 +251,7 @@ static int get_pxe_file(char *file_path, void *file_addr) * * Returns 1 on success or < 0 on error. */ -static int get_pxelinux_path(char *file, void *pxefile_addr_r) +static int get_pxelinux_path(const char *file, void *pxefile_addr_r) { size_t base_len = strlen(PXELINUX_DIR); char path[MAX_TFTP_PATH_LEN+1]; @@ -355,7 +348,7 @@ do_pxe_get(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { char *pxefile_addr_str; unsigned long pxefile_addr_r; - int err; + int err, i = 0; do_getfile = do_get_tftp; @@ -376,16 +369,23 @@ do_pxe_get(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) * Keep trying paths until we successfully get a file we're looking * for. */ - if (pxe_uuid_path((void *)pxefile_addr_r) > 0 - || pxe_mac_path((void *)pxefile_addr_r) > 0 - || pxe_ipaddr_paths((void *)pxefile_addr_r) > 0 - || get_pxelinux_path("default", (void *)pxefile_addr_r) > 0) { - + if (pxe_uuid_path((void *)pxefile_addr_r) > 0 || + pxe_mac_path((void *)pxefile_addr_r) > 0 || + pxe_ipaddr_paths((void *)pxefile_addr_r) > 0) { printf("Config file found\n"); return 0; } + while (pxe_default_paths[i]) { + if (get_pxelinux_path(pxe_default_paths[i], + (void *)pxefile_addr_r) > 0) { + printf("Config file found\n"); + return 0; + } + i++; + } + printf("Config file not found\n"); return 1; @@ -398,7 +398,7 @@ do_pxe_get(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) * * Returns 1 on success or < 0 on error. */ -static int get_relfile_envaddr(char *file_path, char *envaddr_name) +static int get_relfile_envaddr(const char *file_path, const char *envaddr_name) { unsigned long file_addr; char *envaddr; @@ -445,14 +445,17 @@ static int get_relfile_envaddr(char *file_path, char *envaddr_name) * list - lets these form a list, which a pxe_menu struct will hold. */ struct pxe_label { + char num[4]; char *name; char *menu; char *kernel; char *append; char *initrd; char *fdt; + int ipappend; int attempted; int localboot; + int localboot_val; struct list_head list; }; @@ -533,21 +536,9 @@ static void label_destroy(struct pxe_label *label) static void label_print(void *data) { struct pxe_label *label = data; - const char *c = label->menu ? label->menu : label->kernel; - - printf("%s:\t%s\n", label->name, c); - - if (label->kernel) - printf("\t\tkernel: %s\n", label->kernel); - - if (label->append) - printf("\t\tappend: %s\n", label->append); + const char *c = label->menu ? label->menu : label->name; - if (label->initrd) - printf("\t\tinitrd: %s\n", label->initrd); - - if (label->fdt) - printf("\tfdt: %s\n", label->fdt); + printf("%s:\t%s\n", label->num, c); } /* @@ -591,34 +582,43 @@ static int label_localboot(struct pxe_label *label) * If the label specifies an 'append' line, its contents will overwrite that * of the 'bootargs' environment variable. */ -static void label_boot(struct pxe_label *label) +static int label_boot(struct pxe_label *label) { char *bootm_argv[] = { "bootm", NULL, NULL, NULL, NULL }; + char initrd_str[22]; + char mac_str[29] = ""; + char ip_str[68] = ""; + char *bootargs; int bootm_argc = 3; + int len = 0; label_print(label); label->attempted = 1; if (label->localboot) { - label_localboot(label); - return; + if (label->localboot_val >= 0) + label_localboot(label); + return 0; } if (label->kernel == NULL) { printf("No kernel given, skipping %s\n", label->name); - return; + return 1; } if (label->initrd) { if (get_relfile_envaddr(label->initrd, "ramdisk_addr_r") < 0) { printf("Skipping %s for failure retrieving initrd\n", label->name); - return; + return 1; } - bootm_argv[2] = getenv("ramdisk_addr_r"); + bootm_argv[2] = initrd_str; + strcpy(bootm_argv[2], getenv("ramdisk_addr_r")); + strcat(bootm_argv[2], ":"); + strcat(bootm_argv[2], getenv("filesize")); } else { bootm_argv[2] = "-"; } @@ -626,11 +626,43 @@ static void label_boot(struct pxe_label *label) if (get_relfile_envaddr(label->kernel, "kernel_addr_r") < 0) { printf("Skipping %s for failure retrieving kernel\n", label->name); - return; + return 1; + } + + if (label->ipappend & 0x1) { + sprintf(ip_str, " ip=%s:%s:%s:%s", + getenv("ipaddr"), getenv("serverip"), + getenv("gatewayip"), getenv("netmask")); + len += strlen(ip_str); + } + + if (label->ipappend & 0x2) { + int err; + strcpy(mac_str, " BOOTIF="); + err = format_mac_pxe(mac_str + 8, sizeof(mac_str) - 8); + if (err < 0) + mac_str[0] = '\0'; + len += strlen(mac_str); } if (label->append) - setenv("bootargs", label->append); + len += strlen(label->append); + + if (len) { + bootargs = malloc(len + 1); + if (!bootargs) + return 1; + bootargs[0] = '\0'; + if (label->append) + strcpy(bootargs, label->append); + strcat(bootargs, ip_str); + strcat(bootargs, mac_str); + + setenv("bootargs", bootargs); + printf("append: %s\n", bootargs); + + free(bootargs); + } bootm_argv[1] = getenv("kernel_addr_r"); @@ -654,7 +686,7 @@ static void label_boot(struct pxe_label *label) if (get_relfile_envaddr(label->fdt, "fdt_addr_r") < 0) { printf("Skipping %s for failure retrieving fdt\n", label->name); - return; + return 1; } } else bootm_argv[3] = getenv("fdt_addr"); @@ -663,6 +695,12 @@ static void label_boot(struct pxe_label *label) bootm_argc = 4; do_bootm(NULL, 0, bootm_argc, bootm_argv); + +#ifdef CONFIG_CMD_BOOTZ + /* Try booting a zImage if do_bootm returns */ + do_bootz(NULL, 0, bootm_argc, bootm_argv); +#endif + return 1; } /* @@ -685,6 +723,8 @@ enum token_type { T_PROMPT, T_INCLUDE, T_FDT, + T_ONTIMEOUT, + T_IPAPPEND, T_INVALID }; @@ -713,6 +753,8 @@ static const struct token keywords[] = { {"initrd", T_INITRD}, {"include", T_INCLUDE}, {"fdt", T_FDT}, + {"ontimeout", T_ONTIMEOUT,}, + {"ipappend", T_IPAPPEND,}, {NULL, T_INVALID} }; @@ -903,7 +945,6 @@ static int parse_integer(char **c, int *dst) { struct token t; char *s = *c; - unsigned long temp; get_token(c, &t, L_SLITERAL); @@ -912,12 +953,7 @@ static int parse_integer(char **c, int *dst) return -EINVAL; } - if (strict_strtoul(t.val, 10, &temp) < 0) { - printf("Expected unsigned integer: %s\n", t.val); - return -EINVAL; - } - - *dst = (int)temp; + *dst = simple_strtol(t.val, NULL, 10); free(t.val); @@ -1016,10 +1052,8 @@ static int parse_label_menu(char **c, struct pxe_menu *cfg, switch (t.type) { case T_DEFAULT: - if (cfg->default_label) - free(cfg->default_label); - - cfg->default_label = strdup(label->name); + if (!cfg->default_label) + cfg->default_label = strdup(label->name); if (!cfg->default_label) return -ENOMEM; @@ -1108,7 +1142,12 @@ static int parse_label(char **c, struct pxe_menu *cfg) break; case T_LOCALBOOT: - err = parse_integer(c, &label->localboot); + label->localboot = 1; + err = parse_integer(c, &label->localboot_val); + break; + + case T_IPAPPEND: + err = parse_integer(c, &label->ipappend); break; case T_EOL: @@ -1164,6 +1203,7 @@ static int parse_pxefile_top(char *p, struct pxe_menu *cfg, int nest_level) err = 0; switch (t.type) { case T_MENU: + cfg->prompt = 1; err = parse_menu(&p, cfg, b, nest_level); break; @@ -1176,6 +1216,7 @@ static int parse_pxefile_top(char *p, struct pxe_menu *cfg, int nest_level) break; case T_DEFAULT: + case T_ONTIMEOUT: err = parse_sliteral(&p, &label_name); if (label_name) { @@ -1193,7 +1234,7 @@ static int parse_pxefile_top(char *p, struct pxe_menu *cfg, int nest_level) break; case T_PROMPT: - err = parse_integer(&p, &cfg->prompt); + eol_or_eof(&p); break; case T_EOL: @@ -1276,6 +1317,8 @@ static struct menu *pxe_menu_to_menu(struct pxe_menu *cfg) struct list_head *pos; struct menu *m; int err; + int i = 1; + char *default_num = NULL; /* * Create a menu and add items for all the labels. @@ -1289,18 +1332,23 @@ static struct menu *pxe_menu_to_menu(struct pxe_menu *cfg) list_for_each(pos, &cfg->labels) { label = list_entry(pos, struct pxe_label, list); - if (menu_item_add(m, label->name, label) != 1) { + sprintf(label->num, "%d", i++); + if (menu_item_add(m, label->num, label) != 1) { menu_destroy(m); return NULL; } + if (cfg->default_label && + (strcmp(label->name, cfg->default_label) == 0)) + default_num = label->num; + } /* * After we've created items for each label in the menu, set the * menu's default label if one was specified. */ - if (cfg->default_label) { - err = menu_default_set(m, cfg->default_label); + if (default_num) { + err = menu_default_set(m, default_num); if (err != 1) { if (err != -ENOENT) { menu_destroy(m); @@ -1367,10 +1415,13 @@ static void handle_pxe_menu(struct pxe_menu *cfg) * we give up. */ - if (err == 1) - label_boot(choice); - else if (err != -ENOENT) + if (err == 1) { + err = label_boot(choice); + if (!err) + return; + } else if (err != -ENOENT) { return; + } boot_unattempted_labels(cfg); } |