diff options
Diffstat (limited to 'arch/x86/lib/zimage.c')
-rw-r--r-- | arch/x86/lib/zimage.c | 93 |
1 files changed, 79 insertions, 14 deletions
diff --git a/arch/x86/lib/zimage.c b/arch/x86/lib/zimage.c index e5ea5129c1e..062e3d3e315 100644 --- a/arch/x86/lib/zimage.c +++ b/arch/x86/lib/zimage.c @@ -22,6 +22,7 @@ #include <irq_func.h> #include <log.h> #include <malloc.h> +#include <mapmem.h> #include <acpi/acpi_table.h> #include <asm/io.h> #include <asm/ptrace.h> @@ -180,7 +181,7 @@ static int setup_device_tree(struct setup_header *hdr, const void *fdt_blob) return 0; } -static const char *get_kernel_version(struct boot_params *params, +const char *zimage_get_kernel_version(struct boot_params *params, void *kernel_base) { struct setup_header *hdr = ¶ms->hdr; @@ -188,10 +189,14 @@ static const char *get_kernel_version(struct boot_params *params, const char *s, *end; bootproto = get_boot_protocol(hdr, false); + log_debug("bootproto %x, hdr->setup_sects %x\n", bootproto, + hdr->setup_sects); if (bootproto < 0x0200 || hdr->setup_sects < 15) return NULL; /* sanity-check the kernel version in case it is missing */ + log_debug("hdr->kernel_version %x, str at %p\n", hdr->kernel_version, + kernel_base + hdr->kernel_version + 0x200); for (s = kernel_base + hdr->kernel_version + 0x200, end = s + 0x100; *s; s++) { if (!isprint(*s)) @@ -238,7 +243,7 @@ struct boot_params *load_zimage(char *image, unsigned long kernel_size, log_debug("Using boot protocol version %x.%02x\n", (bootproto & 0xff00) >> 8, bootproto & 0xff); - version = get_kernel_version(params, image); + version = zimage_get_kernel_version(params, image); if (version) printf("Linux kernel version %s\n", version); else @@ -442,8 +447,7 @@ static int do_zboot_start(struct cmd_tbl *cmdtp, int flag, int argc, return 0; } -static int do_zboot_load(struct cmd_tbl *cmdtp, int flag, int argc, - char *const argv[]) +static int zboot_load(void) { struct boot_params *base_ptr; @@ -460,31 +464,51 @@ static int do_zboot_load(struct cmd_tbl *cmdtp, int flag, int argc, &state.load_address); if (!base_ptr) { puts("## Kernel loading failed ...\n"); - return CMD_RET_FAILURE; + return -EINVAL; } } state.base_ptr = base_ptr; - if (env_set_hex("zbootbase", (ulong)base_ptr) || + + return 0; +} + +static int do_zboot_load(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + if (zboot_load()) + return CMD_RET_FAILURE; + + if (env_set_hex("zbootbase", map_to_sysmem(state.base_ptr)) || env_set_hex("zbootaddr", state.load_address)) return CMD_RET_FAILURE; return 0; } +static int zboot_setup(void) +{ + struct boot_params *base_ptr = state.base_ptr; + int ret; + + ret = setup_zimage(base_ptr, (char *)base_ptr + COMMAND_LINE_OFFSET, + 0, state.initrd_addr, state.initrd_size, + (ulong)state.cmdline); + if (ret) + return -EINVAL; + + return 0; +} + static int do_zboot_setup(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { struct boot_params *base_ptr = state.base_ptr; - int ret; if (!base_ptr) { printf("base is not set: use 'zboot load' first\n"); return CMD_RET_FAILURE; } - ret = setup_zimage(base_ptr, (char *)base_ptr + COMMAND_LINE_OFFSET, - 0, state.initrd_addr, state.initrd_size, - (ulong)state.cmdline); - if (ret) { + if (zboot_setup()) { puts("Setting up boot parameters failed ...\n"); return CMD_RET_FAILURE; } @@ -501,8 +525,7 @@ static int do_zboot_info(struct cmd_tbl *cmdtp, int flag, int argc, return 0; } -static int do_zboot_go(struct cmd_tbl *cmdtp, int flag, int argc, - char *const argv[]) +static int zboot_go(void) { struct boot_params *params = state.base_ptr; struct setup_header *hdr = ¶ms->hdr; @@ -522,11 +545,52 @@ static int do_zboot_go(struct cmd_tbl *cmdtp, int flag, int argc, /* we assume that the kernel is in place */ ret = boot_linux_kernel((ulong)state.base_ptr, entry, image_64bit); + + return ret; +} + +static int do_zboot_go(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + int ret; + + ret = zboot_go(); printf("Kernel returned! (err=%d)\n", ret); return CMD_RET_FAILURE; } +int zboot_start(ulong addr, ulong size, ulong initrd, ulong initrd_size, + ulong base, char *cmdline) +{ + int ret; + + memset(&state, '\0', sizeof(state)); + + if (base) { + state.base_ptr = map_sysmem(base, 0); + state.load_address = addr; + } else { + state.bzimage_addr = addr; + } + state.bzimage_size = size; + state.initrd_addr = initrd; + state.initrd_size = initrd_size; + state.cmdline = cmdline; + + ret = zboot_load(); + if (ret) + return log_msg_ret("ld", ret); + ret = zboot_setup(); + if (ret) + return log_msg_ret("set", ret); + ret = zboot_go(); + if (ret) + return log_msg_ret("set", ret); + + return -EFAULT; +} + static void print_num(const char *name, ulong value) { printf("%-20s: %lx\n", name, value); @@ -668,7 +732,8 @@ void zimage_dump(struct boot_params *base_ptr) print_num("Real mode switch", hdr->realmode_swtch); print_num("Start sys seg", hdr->start_sys_seg); print_num("Kernel version", hdr->kernel_version); - version = get_kernel_version(base_ptr, (void *)state.bzimage_addr); + version = zimage_get_kernel_version(base_ptr, + (void *)state.bzimage_addr); if (version) printf(" @%p: %s\n", version, version); print_num("Type of loader", hdr->type_of_loader); |