aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRob Herring <rob.herring@calxeda.com>2012-05-25 10:47:39 +0000
committerJohn Rigby <john.rigby@linaro.org>2012-07-20 20:33:37 -0600
commitcfb48a3a75a8860f4d004a3a3e384732b3593b99 (patch)
tree07c46c8d2560635d7dbe3932f49d1ddb2f57aab3
parent36f306c3239b195fadb2ee4e66ca4ab0f15a0b52 (diff)
pxe: add support for parsing local syslinux files2012.05.52012.05-5
Add a new command "sysboot" which parses syslinux menu files and boots using kernel and initrd specified by menu files. The operation is similar to "pxe boot" except local files on ext2 or fat filesystem are parsed. Signed-off-by: Rob Herring <rob.herring@calxeda.com>
-rw-r--r--common/cmd_pxe.c141
-rw-r--r--include/common.h6
2 files changed, 139 insertions, 8 deletions
diff --git a/common/cmd_pxe.c b/common/cmd_pxe.c
index 9e929717b..050874d81 100644
--- a/common/cmd_pxe.c
+++ b/common/cmd_pxe.c
@@ -135,6 +135,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
@@ -148,7 +193,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));
@@ -173,13 +217,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);
}
/*
@@ -325,6 +363,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;
@@ -1334,6 +1374,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)
@@ -1394,3 +1436,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 4b5841ef4..5667b4580 100644
--- a/include/common.h
+++ b/include/common.h
@@ -300,6 +300,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);