diff options
-rw-r--r-- | common/cmd_pxe.c | 141 | ||||
-rw-r--r-- | include/common.h | 6 |
2 files changed, 139 insertions, 8 deletions
diff --git a/common/cmd_pxe.c b/common/cmd_pxe.c index 0fc863b..2b1115d 100644 --- a/common/cmd_pxe.c +++ b/common/cmd_pxe.c @@ -132,6 +132,51 @@ 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_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 @@ -145,7 +190,6 @@ 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(file_path, relfile, sizeof(relfile)); @@ -170,13 +214,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); } /* @@ -322,6 +360,8 @@ do_pxe_get(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) unsigned long pxefile_addr_r; int err; + do_getfile = do_get_tftp; + if (argc != 1) return CMD_RET_USAGE; @@ -1331,6 +1371,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) @@ -1391,3 +1433,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] <interface> <dev[:part]> <ext2|fat> [addr] [filename]\n" + " - load and parse syslinux menu file 'filename' from ext2 or fat\n" + " filesystem on 'dev' on 'interface' to address 'addr'" +); diff --git a/include/common.h b/include/common.h index ecfa6c4..7cf15c5 100644 --- a/include/common.h +++ b/include/common.h @@ -325,6 +325,12 @@ void doc_probe(unsigned long physadr); /* common/cmd_net.c */ int do_tftpb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]); +/* common/cmd_fat.c */ +int do_fat_fsload(cmd_tbl_t *, int, int, char * const []); + +/* common/cmd_ext2.c */ +int do_ext2load(cmd_tbl_t *, int, int, char * const []); + /* common/cmd_nvedit.c */ int env_init (void); void env_relocate (void); |