*
* Returns 1 on success or < 0 on error.
*/
-static int pxe_uuid_path(struct cmd_tbl *cmdtp, unsigned long pxefile_addr_r)
+static int pxe_uuid_path(struct pxe_context *ctx, unsigned long pxefile_addr_r)
{
char *uuid_str;
if (!uuid_str)
return -ENOENT;
- return get_pxelinux_path(cmdtp, uuid_str, pxefile_addr_r);
+ return get_pxelinux_path(ctx, uuid_str, pxefile_addr_r);
}
/*
*
* Returns 1 on success or < 0 on error.
*/
-static int pxe_mac_path(struct cmd_tbl *cmdtp, unsigned long pxefile_addr_r)
+static int pxe_mac_path(struct pxe_context *ctx, unsigned long pxefile_addr_r)
{
char mac_str[21];
int err;
if (err < 0)
return err;
- return get_pxelinux_path(cmdtp, mac_str, pxefile_addr_r);
+ return get_pxelinux_path(ctx, mac_str, pxefile_addr_r);
}
/*
*
* Returns 1 on success or < 0 on error.
*/
-static int pxe_ipaddr_paths(struct cmd_tbl *cmdtp, unsigned long pxefile_addr_r)
+static int pxe_ipaddr_paths(struct pxe_context *ctx, unsigned long pxefile_addr_r)
{
char ip_addr[9];
int mask_pos, err;
sprintf(ip_addr, "%08X", ntohl(net_ip.s_addr));
for (mask_pos = 7; mask_pos >= 0; mask_pos--) {
- err = get_pxelinux_path(cmdtp, ip_addr, pxefile_addr_r);
+ err = get_pxelinux_path(ctx, ip_addr, pxefile_addr_r);
if (err > 0)
return err;
{
char *pxefile_addr_str;
unsigned long pxefile_addr_r;
+ struct pxe_context ctx;
int err, i = 0;
+ pxe_setup_ctx(&ctx, cmdtp);
do_getfile = do_get_tftp;
if (argc != 1)
* Keep trying paths until we successfully get a file we're looking
* for.
*/
- if (pxe_uuid_path(cmdtp, pxefile_addr_r) > 0 ||
- pxe_mac_path(cmdtp, pxefile_addr_r) > 0 ||
- pxe_ipaddr_paths(cmdtp, pxefile_addr_r) > 0) {
+ if (pxe_uuid_path(&ctx, pxefile_addr_r) > 0 ||
+ pxe_mac_path(&ctx, pxefile_addr_r) > 0 ||
+ pxe_ipaddr_paths(&ctx, pxefile_addr_r) > 0) {
printf("Config file found\n");
return 0;
}
while (pxe_default_paths[i]) {
- if (get_pxelinux_path(cmdtp, pxe_default_paths[i],
+ if (get_pxelinux_path(&ctx, pxe_default_paths[i],
pxefile_addr_r) > 0) {
printf("Config file found\n");
return 0;
unsigned long pxefile_addr_r;
struct pxe_menu *cfg;
char *pxefile_addr_str;
+ struct pxe_context ctx;
+ pxe_setup_ctx(&ctx, cmdtp);
do_getfile = do_get_tftp;
if (argc == 1) {
return 1;
}
- cfg = parse_pxefile(cmdtp, pxefile_addr_r);
+ cfg = parse_pxefile(&ctx, pxefile_addr_r);
if (!cfg) {
printf("Error parsing config file\n");
return 1;
}
- handle_pxe_menu(cmdtp, cfg);
+ handle_pxe_menu(&ctx, cfg);
destroy_pxe_menu(cfg);
*
* Returns 1 for success, or < 0 on error.
*/
-static int get_relfile(struct cmd_tbl *cmdtp, const char *file_path,
+static int get_relfile(struct pxe_context *ctx, const char *file_path,
unsigned long file_addr)
{
size_t path_len;
sprintf(addr_buf, "%lx", file_addr);
- return do_getfile(cmdtp, relfile, addr_buf);
+ return do_getfile(ctx->cmdtp, relfile, addr_buf);
}
-int get_pxe_file(struct cmd_tbl *cmdtp, const char *file_path,
+int get_pxe_file(struct pxe_context *ctx, const char *file_path,
unsigned long file_addr)
{
unsigned long config_file_size;
int err;
char *buf;
- err = get_relfile(cmdtp, file_path, file_addr);
+ err = get_relfile(ctx, file_path, file_addr);
if (err < 0)
return err;
#define PXELINUX_DIR "pxelinux.cfg/"
-int get_pxelinux_path(struct cmd_tbl *cmdtp, const char *file,
+int get_pxelinux_path(struct pxe_context *ctx, const char *file,
unsigned long pxefile_addr_r)
{
size_t base_len = strlen(PXELINUX_DIR);
sprintf(path, PXELINUX_DIR "%s", file);
- return get_pxe_file(cmdtp, path, pxefile_addr_r);
+ return get_pxe_file(ctx, path, pxefile_addr_r);
}
/*
*
* Returns 1 on success or < 0 on error.
*/
-static int get_relfile_envaddr(struct cmd_tbl *cmdtp, const char *file_path,
+static int get_relfile_envaddr(struct pxe_context *ctx, const char *file_path,
const char *envaddr_name)
{
unsigned long file_addr;
if (strict_strtoul(envaddr, 16, &file_addr) < 0)
return -EINVAL;
- return get_relfile(cmdtp, file_path, file_addr);
+ return get_relfile(ctx, file_path, file_addr);
}
/*
* Loads fdt overlays specified in 'fdtoverlays'.
*/
#ifdef CONFIG_OF_LIBFDT_OVERLAY
-static void label_boot_fdtoverlay(struct cmd_tbl *cmdtp, struct pxe_label *label)
+static void label_boot_fdtoverlay(struct pxe_context *ctx,
+ struct pxe_label *label)
{
char *fdtoverlay = label->fdtoverlays;
struct fdt_header *working_fdt;
goto skip_overlay;
/* Load overlay file */
- err = get_relfile_envaddr(cmdtp, overlayfile,
+ err = get_relfile_envaddr(ctx, overlayfile,
"fdtoverlay_addr_r");
if (err < 0) {
printf("Failed loading overlay %s\n", overlayfile);
* If the label specifies an 'append' line, its contents will overwrite that
* of the 'bootargs' environment variable.
*/
-static int label_boot(struct cmd_tbl *cmdtp, struct pxe_label *label)
+static int label_boot(struct pxe_context *ctx, struct pxe_label *label)
{
char *bootm_argv[] = { "bootm", NULL, NULL, NULL, NULL };
char *zboot_argv[] = { "zboot", NULL, "0", NULL, NULL };
}
if (label->initrd) {
- if (get_relfile_envaddr(cmdtp, label->initrd, "ramdisk_addr_r") < 0) {
+ if (get_relfile_envaddr(ctx, label->initrd, "ramdisk_addr_r") < 0) {
printf("Skipping %s for failure retrieving initrd\n",
label->name);
return 1;
strncat(initrd_str, initrd_filesize, 9);
}
- if (get_relfile_envaddr(cmdtp, label->kernel, "kernel_addr_r") < 0) {
+ if (get_relfile_envaddr(ctx, label->kernel, "kernel_addr_r") < 0) {
printf("Skipping %s for failure retrieving kernel\n",
label->name);
return 1;
}
if (fdtfile) {
- int err = get_relfile_envaddr(cmdtp, fdtfile,
+ int err = get_relfile_envaddr(ctx, fdtfile,
"fdt_addr_r");
free(fdtfilefree);
#ifdef CONFIG_OF_LIBFDT_OVERLAY
if (label->fdtoverlays)
- label_boot_fdtoverlay(cmdtp, label);
+ label_boot_fdtoverlay(ctx, label);
#endif
} else {
bootm_argv[3] = NULL;
buf = map_sysmem(kernel_addr_r, 0);
/* Try bootm for legacy and FIT format image */
if (genimg_get_format(buf) != IMAGE_FORMAT_INVALID)
- do_bootm(cmdtp, 0, bootm_argc, bootm_argv);
+ do_bootm(ctx->cmdtp, 0, bootm_argc, bootm_argv);
/* Try booting an AArch64 Linux kernel image */
else if (IS_ENABLED(CONFIG_CMD_BOOTI))
- do_booti(cmdtp, 0, bootm_argc, bootm_argv);
+ do_booti(ctx->cmdtp, 0, bootm_argc, bootm_argv);
/* Try booting a Image */
else if (IS_ENABLED(CONFIG_CMD_BOOTZ))
- do_bootz(cmdtp, 0, bootm_argc, bootm_argv);
+ do_bootz(ctx->cmdtp, 0, bootm_argc, bootm_argv);
/* Try booting an x86_64 Linux kernel image */
else if (IS_ENABLED(CONFIG_CMD_ZBOOT))
- do_zboot_parent(cmdtp, 0, zboot_argc, zboot_argv, NULL);
+ do_zboot_parent(ctx->cmdtp, 0, zboot_argc, zboot_argv, NULL);
unmap_sysmem(buf);
return 1;
}
-static int parse_pxefile_top(struct cmd_tbl *cmdtp, char *p, unsigned long base,
+static int parse_pxefile_top(struct pxe_context *ctx, char *p, ulong base,
struct pxe_menu *cfg, int nest_level);
/*
* include, nest_level has already been incremented and doesn't need to be
* incremented here.
*/
-static int handle_include(struct cmd_tbl *cmdtp, char **c, unsigned long base,
+static int handle_include(struct pxe_context *ctx, char **c, unsigned long base,
struct pxe_menu *cfg, int nest_level)
{
char *include_path;
return err;
}
- err = get_pxe_file(cmdtp, include_path, base);
+ err = get_pxe_file(ctx, include_path, base);
if (err < 0) {
printf("Couldn't retrieve %s\n", include_path);
}
buf = map_sysmem(base, 0);
- ret = parse_pxefile_top(cmdtp, buf, base, cfg, nest_level);
+ ret = parse_pxefile_top(ctx, buf, base, cfg, nest_level);
unmap_sysmem(buf);
return ret;
* nest_level should be 1 when parsing the top level pxe file, 2 when parsing
* a file it includes, 3 when parsing a file included by that file, and so on.
*/
-static int parse_menu(struct cmd_tbl *cmdtp, char **c, struct pxe_menu *cfg,
+static int parse_menu(struct pxe_context *ctx, char **c, struct pxe_menu *cfg,
unsigned long base, int nest_level)
{
struct token t;
break;
case T_INCLUDE:
- err = handle_include(cmdtp, c, base, cfg, nest_level + 1);
+ err = handle_include(ctx, c, base, cfg, nest_level + 1);
break;
case T_BACKGROUND:
*
* Returns 1 on success, < 0 on error.
*/
-static int parse_pxefile_top(struct cmd_tbl *cmdtp, char *p, unsigned long base,
+static int parse_pxefile_top(struct pxe_context *ctx, char *p, unsigned long base,
struct pxe_menu *cfg, int nest_level)
{
struct token t;
switch (t.type) {
case T_MENU:
cfg->prompt = 1;
- err = parse_menu(cmdtp, &p, cfg,
+ err = parse_menu(ctx, &p, cfg,
base + ALIGN(strlen(b) + 1, 4),
nest_level);
break;
break;
case T_INCLUDE:
- err = handle_include(cmdtp, &p,
+ err = handle_include(ctx, &p,
base + ALIGN(strlen(b), 4), cfg,
nest_level + 1);
break;
}
/*
- * Free the memory used by a pxe_menu and its labels.
*/
void destroy_pxe_menu(struct pxe_menu *cfg)
{
free(cfg);
}
-struct pxe_menu *parse_pxefile(struct cmd_tbl *cmdtp, unsigned long menucfg)
+struct pxe_menu *parse_pxefile(struct pxe_context *ctx, unsigned long menucfg)
{
struct pxe_menu *cfg;
char *buf;
INIT_LIST_HEAD(&cfg->labels);
buf = map_sysmem(menucfg, 0);
- r = parse_pxefile_top(cmdtp, buf, menucfg, cfg, 1);
+ r = parse_pxefile_top(ctx, buf, menucfg, cfg, 1);
unmap_sysmem(buf);
if (r < 0) {
/*
* Try to boot any labels we have yet to attempt to boot.
*/
-static void boot_unattempted_labels(struct cmd_tbl *cmdtp, struct pxe_menu *cfg)
+static void boot_unattempted_labels(struct pxe_context *ctx,
+ struct pxe_menu *cfg)
{
struct list_head *pos;
struct pxe_label *label;
label = list_entry(pos, struct pxe_label, list);
if (!label->attempted)
- label_boot(cmdtp, label);
+ label_boot(ctx, label);
}
}
-void handle_pxe_menu(struct cmd_tbl *cmdtp, struct pxe_menu *cfg)
+void handle_pxe_menu(struct pxe_context *ctx, struct pxe_menu *cfg)
{
void *choice;
struct menu *m;
if (IS_ENABLED(CONFIG_CMD_BMP)) {
/* display BMP if available */
if (cfg->bmp) {
- if (get_relfile(cmdtp, cfg->bmp, image_load_addr)) {
+ if (get_relfile(ctx, cfg->bmp, image_load_addr)) {
if (CONFIG_IS_ENABLED(CMD_CLS))
run_command("cls", 0);
bmp_display(image_load_addr,
*/
if (err == 1) {
- err = label_boot(cmdtp, choice);
+ err = label_boot(ctx, choice);
if (!err)
return;
} else if (err != -ENOENT) {
return;
}
- boot_unattempted_labels(cmdtp, cfg);
+ boot_unattempted_labels(ctx, cfg);
+}
+
+void pxe_setup_ctx(struct pxe_context *ctx, struct cmd_tbl *cmdtp)
+{
+ ctx->cmdtp = cmdtp;
}
extern int (*do_getfile)(struct cmd_tbl *cmdtp, const char *file_path,
char *file_addr);
+
+/**
+ * struct pxe_context - context information for PXE parsing
+ *
+ * @cmdtp: Pointer to command table to use when calling other commands
+ */
+struct pxe_context {
+ struct cmd_tbl *cmdtp;
+};
+
+/**
+ * destroy_pxe_menu() - Destroy an allocated pxe structure
+ *
+ * Free the memory used by a pxe_menu and its labels
+ *
+ * @cfg: Config to destroy, previous returned from parse_pxefile()
+ */
void destroy_pxe_menu(struct pxe_menu *cfg);
/**
* 'bootfile' was specified in the environment, the path to bootfile will be
* prepended to 'file_path' and the resulting path will be used.
*
- * @cmdtp: Pointer to command-table entry for the initiating command
+ * @ctx: PXE context
* @file_path: Path to file
* @file_addr: Address to place file
* Returns 1 on success, or < 0 for error
*/
-int get_pxe_file(struct cmd_tbl *cmdtp, const char *file_path,
+int get_pxe_file(struct pxe_context *ctx, const char *file_path,
ulong file_addr);
/**
* to do the hard work, the location of the 'pxelinux.cfg' folder is generated
* from the bootfile path, as described in get_pxe_file().
*
- * @cmdtp: Pointer to command-table entry for the initiating command
+ * @ctx: PXE context
* @file: Relative path to file
* @pxefile_addr_r: Address to load file
* Returns 1 on success or < 0 on error.
*/
-int get_pxelinux_path(struct cmd_tbl *cmdtp, const char *file,
+int get_pxelinux_path(struct pxe_context *ctx, const char *file,
ulong pxefile_addr_r);
/**
* If this function returns, there weren't any labels that successfully
* booted, or the user interrupted the menu selection via ctrl+c.
*
- * @cmdtp: Pointer to command-table entry for the initiating command
+ * @ctx: PXE context
* @cfg: PXE menu
*/
-void handle_pxe_menu(struct cmd_tbl *cmdtp, struct pxe_menu *cfg);
+void handle_pxe_menu(struct pxe_context *ctx, struct pxe_menu *cfg);
/**
* parse_pxefile() - Parsing a pxe file
*
* This is only used for the top-level file.
*
- * @cmdtp: Pointer to command-table entry for the initiating command
- * @menucfg: Address of PXE file
- *
+ * @ctx: PXE context (provided by the caller)
* Returns NULL if there is an error, otherwise, returns a pointer to a
* pxe_menu struct populated with the results of parsing the pxe file (and any
* files it includes). The resulting pxe_menu struct can be free()'d by using
* the destroy_pxe_menu() function.
*/
-struct pxe_menu *parse_pxefile(struct cmd_tbl *cmdtp, ulong menucfg);
+struct pxe_menu *parse_pxefile(struct pxe_context *ctx, ulong menucfg);
/**
* format_mac_pxe() - Convert a MAC address to PXE format
*/
int format_mac_pxe(char *outbuf, size_t outbuf_len);
+/**
+ * pxe_setup_ctx() - Setup a new PXE context
+ *
+ * @ctx: Context to set up
+ * @cmdtp: Command table entry which started this action
+ */
+void pxe_setup_ctx(struct pxe_context *ctx, struct cmd_tbl *cmdtp);
+
#endif /* __PXE_UTILS_H */