// SPDX-License-Identifier: GPL-2.0+ #include #include #include #include #include "pxe_utils.h" static char *fs_argv[5]; static int do_get_ext2(struct pxe_context *ctx, const char *file_path, char *file_addr) { #ifdef CONFIG_CMD_EXT2 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; #endif return -ENOENT; } static int do_get_fat(struct pxe_context *ctx, const char *file_path, char *file_addr) { #ifdef CONFIG_CMD_FAT 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; #endif return -ENOENT; } static int do_get_any(struct pxe_context *ctx, const char *file_path, char *file_addr) { #ifdef CONFIG_CMD_FS_GENERIC 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; #endif return -ENOENT; } /* * Boots a system using a local disk syslinux/extlinux file * * Returns 0 on success, 1 on error. */ 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; int prompt = 0; if (argc > 1 && 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 = env_get("bootfile"); } else { filename = argv[5]; env_set("bootfile", filename); } pxe_setup_ctx(&ctx, cmdtp, NULL, NULL, true); if (strstr(argv[3], "ext2")) { ctx.getfile = do_get_ext2; } else if (strstr(argv[3], "fat")) { ctx.getfile = do_get_fat; } else if (strstr(argv[3], "any")) { ctx.getfile = do_get_any; } 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(&ctx, filename, pxefile_addr_r) < 0) { printf("Error reading config file\n"); 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); 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, fat\n" " or any filesystem on 'dev' on 'interface' to address 'addr'" );