X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=common%2Fcmd_pxe.c;h=77a7dd17ac1d595b4baa77bec92d251050427654;hb=7ee411071f31c856107e6b29fcd8df53ae4d7349;hp=7c0cb666681aa0c2ca8327da7524d28b9ca85066;hpb=43d4a5e687fe530d641227910d5e8f1514228eff;p=u-boot diff --git a/common/cmd_pxe.c b/common/cmd_pxe.c index 7c0cb66668..77a7dd17ac 100644 --- a/common/cmd_pxe.c +++ b/common/cmd_pxe.c @@ -26,7 +26,6 @@ #define MAX_TFTP_PATH_LEN 127 - /* * 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 @@ -96,24 +95,24 @@ static int format_mac_pxe(char *outbuf, size_t outbuf_len) * in. If bootfile isn't defined in the environment, return NULL, which should * be interpreted as "don't prepend anything to paths". */ -static int get_bootfile_path(char *bootfile_path, size_t bootfile_path_size) +static int get_bootfile_path(const char *file_path, char *bootfile_path, + size_t bootfile_path_size) { char *bootfile, *last_slash; - size_t path_len; + size_t path_len = 0; + + if (file_path[0] == '/') + goto ret; bootfile = from_env("bootfile"); - if (!bootfile) { - bootfile_path[0] = '\0'; - return 1; - } + if (!bootfile) + goto ret; last_slash = strrchr(bootfile, '/'); - if (last_slash == NULL) { - bootfile_path[0] = '\0'; - return 1; - } + if (last_slash == NULL) + goto ret; path_len = (last_slash - bootfile) + 1; @@ -126,11 +125,55 @@ static int get_bootfile_path(char *bootfile_path, size_t bootfile_path_size) strncpy(bootfile_path, bootfile, path_len); + ret: bootfile_path[path_len] = '\0'; return 1; } +static int (*do_getfile)(char *file_path, char *file_addr); + +static int do_get_tftp(char *file_path, char *file_addr) +{ + char *tftp_argv[] = {"tftp", NULL, NULL, NULL}; + + tftp_argv[1] = file_addr; + tftp_argv[2] = file_path; + + if (do_tftpb(NULL, 0, 3, tftp_argv)) + return -ENOENT; + + return 1; +} + +static char *fs_argv[5]; + +static int do_get_ext2(char *file_path, char *file_addr) +{ +#ifdef CONFIG_CMD_EXT2 + fs_argv[0] = "ext2load"; + fs_argv[3] = file_addr; + fs_argv[4] = file_path; + + if (!do_ext2load(NULL, 0, 5, fs_argv)) + return 1; +#endif + return -ENOENT; +} + +static int do_get_fat(char *file_path, char *file_addr) +{ +#ifdef CONFIG_CMD_FAT + fs_argv[0] = "fatload"; + fs_argv[3] = file_addr; + fs_argv[4] = file_path; + + if (!do_fat_fsload(NULL, 0, 5, fs_argv)) + return 1; +#endif + return -ENOENT; +} + /* * As in pxelinux, paths to files referenced from files we retrieve are * relative to the location of bootfile. get_relfile takes such a path and @@ -144,10 +187,9 @@ static int get_relfile(char *file_path, void *file_addr) size_t path_len; char relfile[MAX_TFTP_PATH_LEN+1]; char addr_buf[10]; - char *tftp_argv[] = {"tftp", NULL, NULL, NULL}; int err; - err = get_bootfile_path(relfile, sizeof(relfile)); + err = get_bootfile_path(file_path, relfile, sizeof(relfile)); if (err < 0) return err; @@ -169,13 +211,7 @@ static int get_relfile(char *file_path, void *file_addr) sprintf(addr_buf, "%p", file_addr); - tftp_argv[1] = addr_buf; - tftp_argv[2] = relfile; - - if (do_tftpb(NULL, 0, 3, tftp_argv)) - return -ENOENT; - - return 1; + return do_getfile(relfile, addr_buf); } /* @@ -318,12 +354,13 @@ static int do_pxe_get(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { char *pxefile_addr_str; - void *pxefile_addr_r; + unsigned long pxefile_addr_r; int err; - if (argc != 1) - return cmd_usage(cmdtp); + do_getfile = do_get_tftp; + if (argc != 1) + return CMD_RET_USAGE; pxefile_addr_str = from_env("pxefile_addr_r"); @@ -339,10 +376,10 @@ 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(pxefile_addr_r) > 0 - || pxe_mac_path(pxefile_addr_r) > 0 - || pxe_ipaddr_paths(pxefile_addr_r) > 0 - || get_pxelinux_path("default", 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 + || get_pxelinux_path("default", (void *)pxefile_addr_r) > 0) { printf("Config file found\n"); @@ -363,7 +400,7 @@ do_pxe_get(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) */ static int get_relfile_envaddr(char *file_path, char *envaddr_name) { - void *file_addr; + unsigned long file_addr; char *envaddr; envaddr = from_env(envaddr_name); @@ -371,10 +408,10 @@ static int get_relfile_envaddr(char *file_path, char *envaddr_name) if (!envaddr) return -ENOENT; - if (strict_strtoul(envaddr, 16, (unsigned long *)&file_addr) < 0) + if (strict_strtoul(envaddr, 16, &file_addr) < 0) return -EINVAL; - return get_relfile(file_path, file_addr); + return get_relfile(file_path, (void *)file_addr); } /* @@ -409,6 +446,7 @@ static int get_relfile_envaddr(char *file_path, char *envaddr_name) */ struct pxe_label { char *name; + char *menu; char *kernel; char *append; char *initrd; @@ -491,17 +529,18 @@ 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("Label: %s\n", label->name); + printf("%s:\t%s\n", label->name, c); if (label->kernel) - printf("\tkernel: %s\n", label->kernel); + printf("\t\tkernel: %s\n", label->kernel); if (label->append) - printf("\tappend: %s\n", label->append); + printf("\t\tappend: %s\n", label->append); if (label->initrd) - printf("\tinitrd: %s\n", label->initrd); + printf("\t\tinitrd: %s\n", label->initrd); } /* @@ -537,7 +576,7 @@ static int label_localboot(struct pxe_label *label) printf("running: %s\n", dupcmd); - ret = run_command2(dupcmd, 0); + ret = run_command(dupcmd, 0); free(dupcmd); @@ -626,6 +665,7 @@ enum token_type { T_TIMEOUT, T_LABEL, T_KERNEL, + T_LINUX, T_APPEND, T_INITRD, T_LOCALBOOT, @@ -654,6 +694,7 @@ static const struct token keywords[] = { {"prompt", T_PROMPT}, {"label", T_LABEL}, {"kernel", T_KERNEL}, + {"linux", T_LINUX}, {"localboot", T_LOCALBOOT}, {"append", T_APPEND}, {"initrd", T_INITRD}, @@ -969,6 +1010,9 @@ static int parse_label_menu(char **c, struct pxe_menu *cfg, if (!cfg->default_label) return -ENOMEM; + break; + case T_LABEL: + parse_sliteral(c, &label->menu); break; default: printf("Ignoring malformed menu command: %.*s\n", @@ -991,6 +1035,7 @@ static int parse_label_menu(char **c, struct pxe_menu *cfg, static int parse_label(char **c, struct pxe_menu *cfg) { struct token t; + int len; char *s = *c; struct pxe_label *label; int err; @@ -1019,15 +1064,28 @@ static int parse_label(char **c, struct pxe_menu *cfg) break; case T_KERNEL: + case T_LINUX: err = parse_sliteral(c, &label->kernel); break; case T_APPEND: err = parse_sliteral(c, &label->append); + if (label->initrd) + break; + s = strstr(label->append, "initrd="); + if (!s) + break; + s += 7; + len = (int)(strchr(s, ' ') - s); + label->initrd = malloc(len + 1); + strncpy(label->initrd, s, len); + label->initrd[len] = '\0'; + break; case T_INITRD: - err = parse_sliteral(c, &label->initrd); + if (!label->initrd) + err = parse_sliteral(c, &label->initrd); break; case T_LOCALBOOT: @@ -1110,6 +1168,11 @@ static int parse_pxefile_top(char *p, struct pxe_menu *cfg, int nest_level) break; + case T_INCLUDE: + err = handle_include(&p, b + ALIGN(strlen(b), 4), cfg, + nest_level + 1); + break; + case T_PROMPT: err = parse_integer(&p, &cfg->prompt); break; @@ -1304,6 +1367,8 @@ do_pxe_boot(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) struct pxe_menu *cfg; char *pxefile_addr_str; + do_getfile = do_get_tftp; + if (argc == 1) { pxefile_addr_str = from_env("pxefile_addr_r"); if (!pxefile_addr_str) @@ -1312,7 +1377,7 @@ do_pxe_boot(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) } else if (argc == 2) { pxefile_addr_str = argv[1]; } else { - return cmd_usage(cmdtp); + return CMD_RET_USAGE; } if (strict_strtoul(pxefile_addr_str, 16, &pxefile_addr_r) < 0) { @@ -1344,7 +1409,7 @@ int do_pxe(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) cmd_tbl_t *cp; if (argc < 2) - return cmd_usage(cmdtp); + return CMD_RET_USAGE; /* drop initial "pxe" arg */ argc--; @@ -1355,7 +1420,7 @@ int do_pxe(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) if (cp) return cp->cmd(cmdtp, flag, argc, argv); - return cmd_usage(cmdtp); + return CMD_RET_USAGE; } U_BOOT_CMD( @@ -1364,3 +1429,86 @@ U_BOOT_CMD( "get - try to retrieve a pxe file using tftp\npxe " "boot [pxefile_addr_r] - boot from the pxe file at pxefile_addr_r\n" ); + +/* + * Boots a system using a local disk syslinux/extlinux file + * + * Returns 0 on success, 1 on error. + */ +int do_sysboot(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + unsigned long pxefile_addr_r; + struct pxe_menu *cfg; + char *pxefile_addr_str; + char *filename; + int prompt = 0; + + if (strstr(argv[1], "-p")) { + prompt = 1; + argc--; + argv++; + } + + if (argc < 4) + return cmd_usage(cmdtp); + + if (argc < 5) { + pxefile_addr_str = from_env("pxefile_addr_r"); + if (!pxefile_addr_str) + return 1; + } else { + pxefile_addr_str = argv[4]; + } + + if (argc < 6) + filename = getenv("bootfile"); + else { + filename = argv[5]; + setenv("bootfile", filename); + } + + if (strstr(argv[3], "ext2")) + do_getfile = do_get_ext2; + else if (strstr(argv[3], "fat")) + do_getfile = do_get_fat; + else { + printf("Invalid filesystem: %s\n", argv[3]); + return 1; + } + fs_argv[1] = argv[1]; + fs_argv[2] = argv[2]; + + if (strict_strtoul(pxefile_addr_str, 16, &pxefile_addr_r) < 0) { + printf("Invalid pxefile address: %s\n", pxefile_addr_str); + return 1; + } + + if (get_pxe_file(filename, (void *)pxefile_addr_r) < 0) { + printf("Error reading config file\n"); + return 1; + } + + cfg = parse_pxefile((char *)(pxefile_addr_r)); + + if (cfg == NULL) { + printf("Error parsing config file\n"); + return 1; + } + + if (prompt) + cfg->prompt = 1; + + handle_pxe_menu(cfg); + + destroy_pxe_menu(cfg); + + return 0; +} + +U_BOOT_CMD( + sysboot, 7, 1, do_sysboot, + "command to get and boot from syslinux files", + "[-p] [addr] [filename]\n" + " - load and parse syslinux menu file 'filename' from ext2 or fat\n" + " filesystem on 'dev' on 'interface' to address 'addr'" +);