From fd3fa5c3941d4de0736d066f77d0158cf933e207 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 14 Oct 2021 12:47:56 -0600 Subject: pxe: Use a context pointer At present the PXE functions pass around a pointer to command-table entry which is very strange. It is only needed in a few places and it is odd to pass around a data structure from another module in this way. For bootmethod we will need to provide some context information when reading files. Create a PXE context struct to hold the command-table-entry pointer and pass that around instead. We can then add more things to the context as needed. Signed-off-by: Simon Glass Reviewed-by: Artem Lapkin Tested-by: Artem Lapkin Reviewed-by: Ramon Fried --- cmd/sysboot.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'cmd/sysboot.c') diff --git a/cmd/sysboot.c b/cmd/sysboot.c index af6a2f1b7f1..9ba713c8aae 100644 --- a/cmd/sysboot.c +++ b/cmd/sysboot.c @@ -59,6 +59,7 @@ static int do_sysboot(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { unsigned long pxefile_addr_r; + struct pxe_context ctx; struct pxe_menu *cfg; char *pxefile_addr_str; char *filename; @@ -90,6 +91,7 @@ static int do_sysboot(struct cmd_tbl *cmdtp, int flag, int argc, env_set("bootfile", filename); } + pxe_setup_ctx(&ctx, cmdtp); if (strstr(argv[3], "ext2")) { do_getfile = do_get_ext2; } else if (strstr(argv[3], "fat")) { @@ -108,12 +110,12 @@ static int do_sysboot(struct cmd_tbl *cmdtp, int flag, int argc, return 1; } - if (get_pxe_file(cmdtp, filename, pxefile_addr_r) < 0) { + if (get_pxe_file(&ctx, filename, pxefile_addr_r) < 0) { printf("Error reading config file\n"); return 1; } - cfg = parse_pxefile(cmdtp, pxefile_addr_r); + cfg = parse_pxefile(&ctx, pxefile_addr_r); if (!cfg) { printf("Error parsing config file\n"); @@ -123,7 +125,7 @@ static int do_sysboot(struct cmd_tbl *cmdtp, int flag, int argc, if (prompt) cfg->prompt = 1; - handle_pxe_menu(cmdtp, cfg); + handle_pxe_menu(&ctx, cfg); destroy_pxe_menu(cfg); -- cgit v1.2.3 From b1ead6b9087f1f96cb117d72e3e5cf0d5fb708f5 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 14 Oct 2021 12:47:57 -0600 Subject: pxe: Move do_getfile() into the context Rather than having a global variable, pass the function as part of the context. Signed-off-by: Simon Glass Reviewed-by: Artem Lapkin Tested-by: Artem Lapkin Reviewed-by: Ramon Fried --- cmd/sysboot.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'cmd/sysboot.c') diff --git a/cmd/sysboot.c b/cmd/sysboot.c index 9ba713c8aae..082f23543d1 100644 --- a/cmd/sysboot.c +++ b/cmd/sysboot.c @@ -8,7 +8,7 @@ static char *fs_argv[5]; -static int do_get_ext2(struct cmd_tbl *cmdtp, const char *file_path, +static int do_get_ext2(struct pxe_context *ctx, const char *file_path, char *file_addr) { #ifdef CONFIG_CMD_EXT2 @@ -16,13 +16,13 @@ static int do_get_ext2(struct cmd_tbl *cmdtp, const char *file_path, fs_argv[3] = file_addr; fs_argv[4] = (void *)file_path; - if (!do_ext2load(cmdtp, 0, 5, fs_argv)) + if (!do_ext2load(ctx->cmdtp, 0, 5, fs_argv)) return 1; #endif return -ENOENT; } -static int do_get_fat(struct cmd_tbl *cmdtp, const char *file_path, +static int do_get_fat(struct pxe_context *ctx, const char *file_path, char *file_addr) { #ifdef CONFIG_CMD_FAT @@ -30,13 +30,13 @@ static int do_get_fat(struct cmd_tbl *cmdtp, const char *file_path, fs_argv[3] = file_addr; fs_argv[4] = (void *)file_path; - if (!do_fat_fsload(cmdtp, 0, 5, fs_argv)) + if (!do_fat_fsload(ctx->cmdtp, 0, 5, fs_argv)) return 1; #endif return -ENOENT; } -static int do_get_any(struct cmd_tbl *cmdtp, const char *file_path, +static int do_get_any(struct pxe_context *ctx, const char *file_path, char *file_addr) { #ifdef CONFIG_CMD_FS_GENERIC @@ -44,7 +44,7 @@ static int do_get_any(struct cmd_tbl *cmdtp, const char *file_path, fs_argv[3] = file_addr; fs_argv[4] = (void *)file_path; - if (!do_load(cmdtp, 0, 5, fs_argv, FS_TYPE_ANY)) + if (!do_load(ctx->cmdtp, 0, 5, fs_argv, FS_TYPE_ANY)) return 1; #endif return -ENOENT; @@ -91,13 +91,13 @@ static int do_sysboot(struct cmd_tbl *cmdtp, int flag, int argc, env_set("bootfile", filename); } - pxe_setup_ctx(&ctx, cmdtp); + pxe_setup_ctx(&ctx, cmdtp, NULL); if (strstr(argv[3], "ext2")) { - do_getfile = do_get_ext2; + ctx.getfile = do_get_ext2; } else if (strstr(argv[3], "fat")) { - do_getfile = do_get_fat; + ctx.getfile = do_get_fat; } else if (strstr(argv[3], "any")) { - do_getfile = do_get_any; + ctx.getfile = do_get_any; } else { printf("Invalid filesystem: %s\n", argv[3]); return 1; -- cgit v1.2.3 From 4ad5d51edb6525402b371cc8f8a3bee1b6a42414 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 14 Oct 2021 12:47:58 -0600 Subject: pxe: Add a userdata field to the context Allow the caller to provide some info which is passed back to the readfile() method. Signed-off-by: Simon Glass Reviewed-by: Artem Lapkin Tested-by: Artem Lapkin Reviewed-by: Ramon Fried --- cmd/sysboot.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'cmd/sysboot.c') diff --git a/cmd/sysboot.c b/cmd/sysboot.c index 082f23543d1..5615e81e9ca 100644 --- a/cmd/sysboot.c +++ b/cmd/sysboot.c @@ -91,7 +91,7 @@ static int do_sysboot(struct cmd_tbl *cmdtp, int flag, int argc, env_set("bootfile", filename); } - pxe_setup_ctx(&ctx, cmdtp, NULL); + pxe_setup_ctx(&ctx, cmdtp, NULL, NULL); if (strstr(argv[3], "ext2")) { ctx.getfile = do_get_ext2; } else if (strstr(argv[3], "fat")) { -- cgit v1.2.3 From 8018b9af57b5cd0cfddf48a8d12f04dba8b77a65 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 14 Oct 2021 12:47:59 -0600 Subject: pxe: Tidy up the is_pxe global Move this into the context to avoid a global variable. Also rename it since the current name does not explain what it actually affects. Signed-off-by: Simon Glass Reviewed-by: Artem Lapkin Tested-by: Artem Lapkin Reviewed-by: Ramon Fried --- cmd/sysboot.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'cmd/sysboot.c') diff --git a/cmd/sysboot.c b/cmd/sysboot.c index 5615e81e9ca..85fa5d8aa01 100644 --- a/cmd/sysboot.c +++ b/cmd/sysboot.c @@ -65,8 +65,6 @@ static int do_sysboot(struct cmd_tbl *cmdtp, int flag, int argc, char *filename; int prompt = 0; - is_pxe = false; - if (argc > 1 && strstr(argv[1], "-p")) { prompt = 1; argc--; @@ -91,7 +89,7 @@ static int do_sysboot(struct cmd_tbl *cmdtp, int flag, int argc, env_set("bootfile", filename); } - pxe_setup_ctx(&ctx, cmdtp, NULL, NULL); + pxe_setup_ctx(&ctx, cmdtp, NULL, NULL, true); if (strstr(argv[3], "ext2")) { ctx.getfile = do_get_ext2; } else if (strstr(argv[3], "fat")) { -- cgit v1.2.3 From 262cfb5b15420a1aea465745a821e684b3dfa153 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 14 Oct 2021 12:48:00 -0600 Subject: pxe: Move pxe_utils files Move the header file into the main include/ directory so we can use it from the bootmethod code. Move the C file into boot/ since it relates to booting. Signed-off-by: Simon Glass Reviewed-by: Artem Lapkin Tested-by: Artem Lapkin Reviewed-by: Ramon Fried --- cmd/sysboot.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'cmd/sysboot.c') diff --git a/cmd/sysboot.c b/cmd/sysboot.c index 85fa5d8aa01..b81255e155a 100644 --- a/cmd/sysboot.c +++ b/cmd/sysboot.c @@ -4,7 +4,7 @@ #include #include #include -#include "pxe_utils.h" +#include static char *fs_argv[5]; -- cgit v1.2.3 From 9e62e7ca543ea94a46f30053262f67202e2435f4 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 14 Oct 2021 12:48:03 -0600 Subject: pxe: Move common parsing coding into pxe_util Both the syslinux and pxe commands use essentially the same code to parse and run extlinux.conf files. Move this into a common function. Signed-off-by: Simon Glass Reviewed-by: Artem Lapkin Tested-by: Artem Lapkin Reviewed-by: Ramon Fried --- cmd/sysboot.c | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) (limited to 'cmd/sysboot.c') diff --git a/cmd/sysboot.c b/cmd/sysboot.c index b81255e155a..7ee14df79e5 100644 --- a/cmd/sysboot.c +++ b/cmd/sysboot.c @@ -60,10 +60,10 @@ static int do_sysboot(struct cmd_tbl *cmdtp, int flag, int argc, { unsigned long pxefile_addr_r; struct pxe_context ctx; - struct pxe_menu *cfg; char *pxefile_addr_str; char *filename; int prompt = 0; + int ret; if (argc > 1 && strstr(argv[1], "-p")) { prompt = 1; @@ -113,19 +113,9 @@ static int do_sysboot(struct cmd_tbl *cmdtp, int flag, int argc, return 1; } - cfg = parse_pxefile(&ctx, pxefile_addr_r); - - if (!cfg) { - printf("Error parsing config file\n"); - return 1; - } - - if (prompt) - cfg->prompt = 1; - - handle_pxe_menu(&ctx, cfg); - - destroy_pxe_menu(cfg); + ret = pxe_process(&ctx, pxefile_addr_r, prompt); + if (ret) + return CMD_RET_FAILURE; return 0; } -- cgit v1.2.3 From 12df842ee324a7e188a643bfee6fe08f28127b26 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 14 Oct 2021 12:48:04 -0600 Subject: pxe: Clean up the use of bootfile The 'bootfile' environment variable is read in the bowels of pxe_util to provide a directory to which all loaded files are relative. This is not obvious from the API to PXE and it is strange to make the caller set an environment variable rather than pass this as a parameter. The code is also convoluted, which this feature implemented by get_bootfile_path(). Update the API to improve this. Unfortunately this means that pxe_setup_ctx() can fail, so add error checking. Signed-off-by: Simon Glass Reviewed-by: Artem Lapkin Tested-by: Artem Lapkin Reviewed-by: Ramon Fried --- cmd/sysboot.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) (limited to 'cmd/sysboot.c') diff --git a/cmd/sysboot.c b/cmd/sysboot.c index 7ee14df79e5..c45fed774d6 100644 --- a/cmd/sysboot.c +++ b/cmd/sysboot.c @@ -59,6 +59,7 @@ static int do_sysboot(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { unsigned long pxefile_addr_r; + pxe_getfile_func getfile; struct pxe_context ctx; char *pxefile_addr_str; char *filename; @@ -89,13 +90,12 @@ static int do_sysboot(struct cmd_tbl *cmdtp, int flag, int argc, env_set("bootfile", filename); } - pxe_setup_ctx(&ctx, cmdtp, NULL, NULL, true); if (strstr(argv[3], "ext2")) { - ctx.getfile = do_get_ext2; + getfile = do_get_ext2; } else if (strstr(argv[3], "fat")) { - ctx.getfile = do_get_fat; + getfile = do_get_fat; } else if (strstr(argv[3], "any")) { - ctx.getfile = do_get_any; + getfile = do_get_any; } else { printf("Invalid filesystem: %s\n", argv[3]); return 1; @@ -108,12 +108,19 @@ static int do_sysboot(struct cmd_tbl *cmdtp, int flag, int argc, return 1; } + if (pxe_setup_ctx(&ctx, cmdtp, getfile, NULL, true, filename)) { + printf("Out of memory\n"); + return CMD_RET_FAILURE; + } + if (get_pxe_file(&ctx, filename, pxefile_addr_r) < 0) { printf("Error reading config file\n"); + pxe_destroy_ctx(&ctx); return 1; } ret = pxe_process(&ctx, pxefile_addr_r, prompt); + pxe_destroy_ctx(&ctx); if (ret) return CMD_RET_FAILURE; -- cgit v1.2.3 From 4d79e884adf6842beb94566bf5249c07a84a5b51 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 14 Oct 2021 12:48:08 -0600 Subject: pxe: Return the file size from the getfile() function It is pretty strange that the pxe code uses the 'filesize' environment variable find the size of a file it has just read. Partly this is because it uses the command-line interpreter to parse its request to load the file. As a first step towards unwinding this, return it directly from the getfile() function. This makes the code a bit longer, for now, but will be cleaned up in future patches. Signed-off-by: Simon Glass Reviewed-by: Artem Lapkin Tested-by: Artem Lapkin Reviewed-by: Ramon Fried --- cmd/sysboot.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) (limited to 'cmd/sysboot.c') diff --git a/cmd/sysboot.c b/cmd/sysboot.c index c45fed774d6..6344ecd357b 100644 --- a/cmd/sysboot.c +++ b/cmd/sysboot.c @@ -9,43 +9,58 @@ static char *fs_argv[5]; static int do_get_ext2(struct pxe_context *ctx, const char *file_path, - char *file_addr) + char *file_addr, ulong *sizep) { #ifdef CONFIG_CMD_EXT2 + int ret; + fs_argv[0] = "ext2load"; fs_argv[3] = file_addr; fs_argv[4] = (void *)file_path; if (!do_ext2load(ctx->cmdtp, 0, 5, fs_argv)) return 1; + ret = pxe_get_file_size(sizep); + if (ret) + return log_msg_ret("tftp", ret); #endif return -ENOENT; } static int do_get_fat(struct pxe_context *ctx, const char *file_path, - char *file_addr) + char *file_addr, ulong *sizep) { #ifdef CONFIG_CMD_FAT + int ret; + fs_argv[0] = "fatload"; fs_argv[3] = file_addr; fs_argv[4] = (void *)file_path; if (!do_fat_fsload(ctx->cmdtp, 0, 5, fs_argv)) return 1; + ret = pxe_get_file_size(sizep); + if (ret) + return log_msg_ret("tftp", ret); #endif return -ENOENT; } static int do_get_any(struct pxe_context *ctx, const char *file_path, - char *file_addr) + char *file_addr, ulong *sizep) { #ifdef CONFIG_CMD_FS_GENERIC + int ret; + fs_argv[0] = "load"; fs_argv[3] = file_addr; fs_argv[4] = (void *)file_path; if (!do_load(ctx->cmdtp, 0, 5, fs_argv, FS_TYPE_ANY)) return 1; + ret = pxe_get_file_size(sizep); + if (ret) + return log_msg_ret("tftp", ret); #endif return -ENOENT; } -- cgit v1.2.3 From 81a2f8d34b4ef38f8a4dbb9013ab65476644603a Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 14 Oct 2021 12:48:09 -0600 Subject: pxe: Refactor sysboot to have one helper The only difference between the three helpers is the filesystem type. Factor this out and call the filesystem functions directly, instead of through the command-line interpreter. This allows the file size to be obtained directly, instead of via an environment variable. We cannot do the same thing with PXE's tftpboot since there is no API at present to obtain information about the file that was read. So there is no point in changing pxe_getfile_func to use a ulong for the address, for example. This is as far as the refactoring can go for the present. Signed-off-by: Simon Glass Reviewed-by: Artem Lapkin Tested-by: Artem Lapkin Reviewed-by: Ramon Fried --- cmd/sysboot.c | 94 +++++++++++++++++++++++------------------------------------ 1 file changed, 36 insertions(+), 58 deletions(-) (limited to 'cmd/sysboot.c') diff --git a/cmd/sysboot.c b/cmd/sysboot.c index 6344ecd357b..04c07020269 100644 --- a/cmd/sysboot.c +++ b/cmd/sysboot.c @@ -6,63 +6,40 @@ #include #include -static char *fs_argv[5]; - -static int do_get_ext2(struct pxe_context *ctx, const char *file_path, - char *file_addr, ulong *sizep) +/** + * struct sysboot_info - useful information for sysboot helpers + * + * @fstype: Filesystem type (FS_TYPE_...) + * @ifname: Interface name (e.g. "ide", "scsi") + * @dev_part_str is in the format: + * .: where is the device number, + * is the optional hardware partition number and + * is the partition number + */ +struct sysboot_info { + int fstype; + const char *ifname; + const char *dev_part_str; +}; + +static int sysboot_read_file(struct pxe_context *ctx, const char *file_path, + char *file_addr, ulong *sizep) { -#ifdef CONFIG_CMD_EXT2 + struct sysboot_info *info = ctx->userdata; + loff_t len_read; + ulong addr; int ret; - fs_argv[0] = "ext2load"; - fs_argv[3] = file_addr; - fs_argv[4] = (void *)file_path; - - if (!do_ext2load(ctx->cmdtp, 0, 5, fs_argv)) - return 1; - ret = pxe_get_file_size(sizep); + addr = simple_strtoul(file_addr, NULL, 16); + ret = fs_set_blk_dev(info->ifname, info->dev_part_str, info->fstype); if (ret) - return log_msg_ret("tftp", ret); -#endif - return -ENOENT; -} - -static int do_get_fat(struct pxe_context *ctx, const char *file_path, - char *file_addr, ulong *sizep) -{ -#ifdef CONFIG_CMD_FAT - int ret; - - fs_argv[0] = "fatload"; - fs_argv[3] = file_addr; - fs_argv[4] = (void *)file_path; - - if (!do_fat_fsload(ctx->cmdtp, 0, 5, fs_argv)) - return 1; - ret = pxe_get_file_size(sizep); + return ret; + ret = fs_read(file_path, addr, 0, 0, &len_read); if (ret) - return log_msg_ret("tftp", ret); -#endif - return -ENOENT; -} - -static int do_get_any(struct pxe_context *ctx, const char *file_path, - char *file_addr, ulong *sizep) -{ -#ifdef CONFIG_CMD_FS_GENERIC - int ret; - - fs_argv[0] = "load"; - fs_argv[3] = file_addr; - fs_argv[4] = (void *)file_path; + return ret; + *sizep = len_read; - if (!do_load(ctx->cmdtp, 0, 5, fs_argv, FS_TYPE_ANY)) - return 1; - ret = pxe_get_file_size(sizep); - if (ret) - return log_msg_ret("tftp", ret); -#endif - return -ENOENT; + return 0; } /* @@ -74,9 +51,9 @@ static int do_sysboot(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { unsigned long pxefile_addr_r; - pxe_getfile_func getfile; struct pxe_context ctx; char *pxefile_addr_str; + struct sysboot_info info; char *filename; int prompt = 0; int ret; @@ -106,24 +83,25 @@ static int do_sysboot(struct cmd_tbl *cmdtp, int flag, int argc, } if (strstr(argv[3], "ext2")) { - getfile = do_get_ext2; + info.fstype = FS_TYPE_EXT; } else if (strstr(argv[3], "fat")) { - getfile = do_get_fat; + info.fstype = FS_TYPE_FAT; } else if (strstr(argv[3], "any")) { - getfile = do_get_any; + info.fstype = FS_TYPE_ANY; } else { printf("Invalid filesystem: %s\n", argv[3]); return 1; } - fs_argv[1] = argv[1]; - fs_argv[2] = argv[2]; + info.ifname = argv[1]; + info.dev_part_str = 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 (pxe_setup_ctx(&ctx, cmdtp, getfile, NULL, true, filename)) { + if (pxe_setup_ctx(&ctx, cmdtp, sysboot_read_file, &info, true, + filename)) { printf("Out of memory\n"); return CMD_RET_FAILURE; } -- cgit v1.2.3