diff --git a/arch/x86/include/asm/zimage.h b/arch/x86/include/asm/zimage.h index 1a77e00995a030b2df886bf7ce8b5df97c3d1a01..3a68bb0bb3037aef5f10d75cbfa060574b7abefd 100644 --- a/arch/x86/include/asm/zimage.h +++ b/arch/x86/include/asm/zimage.h @@ -24,6 +24,8 @@ #ifndef _ASM_ZIMAGE_H_ #define _ASM_ZIMAGE_H_ +#include + /* linux i386 zImage/bzImage header. Offsets relative to * the start of the image */ @@ -44,10 +46,13 @@ #define BZIMAGE_LOAD_ADDR 0x100000 #define ZIMAGE_LOAD_ADDR 0x10000 +/* Implementation defined function to install an e820 map. */ +unsigned install_e820_map(unsigned max_entries, struct e820entry *); + void *load_zimage(char *image, unsigned long kernel_size, unsigned long initrd_addr, unsigned long initrd_size, - int auto_boot); + int auto_boot, void **load_address); -void boot_zimage(void *setup_base); +void boot_zimage(void *setup_base, void *load_address); #endif diff --git a/arch/x86/lib/bootm.c b/arch/x86/lib/bootm.c index bac7b4f0cfb8a3b629e11010073509a2b463191b..ba3875b1bc7e1d362947790809ab4796631146ad 100644 --- a/arch/x86/lib/bootm.c +++ b/arch/x86/lib/bootm.c @@ -38,6 +38,7 @@ int do_bootm_linux(int flag, int argc, char * const argv[], void *base_ptr = NULL; ulong os_data, os_len; image_header_t *hdr; + void *load_address; #if defined(CONFIG_FIT) const void *data; @@ -75,7 +76,8 @@ int do_bootm_linux(int flag, int argc, char * const argv[], #ifdef CONFIG_CMD_ZBOOT base_ptr = load_zimage((void *)os_data, os_len, - images->rd_start, images->rd_end - images->rd_start, 0); + images->rd_start, images->rd_end - images->rd_start, + 0, &load_address); #endif if (NULL == base_ptr) { @@ -92,7 +94,7 @@ int do_bootm_linux(int flag, int argc, char * const argv[], /* we assume that the kernel is in place */ printf("\nStarting kernel ...\n\n"); - boot_zimage(base_ptr); + boot_zimage(base_ptr, load_address); /* does not return */ error: diff --git a/arch/x86/lib/zimage.c b/arch/x86/lib/zimage.c index 98e7507058f9ada01407ce49b75a15567e51a084..b5597ecd7497642ca46676ed51ff1add79682ecb 100644 --- a/arch/x86/lib/zimage.c +++ b/arch/x86/lib/zimage.c @@ -52,6 +52,16 @@ #define COMMAND_LINE_SIZE 2048 +unsigned generic_install_e820_map(unsigned max_entries, + struct e820entry *entries) +{ + return 0; +} + +unsigned install_e820_map(unsigned max_entries, + struct e820entry *entries) + __attribute__((weak, alias("generic_install_e820_map"))); + static void build_command_line(char *command_line, int auto_boot) { char *env_command_line; @@ -81,13 +91,12 @@ static void build_command_line(char *command_line, int auto_boot) void *load_zimage(char *image, unsigned long kernel_size, unsigned long initrd_addr, unsigned long initrd_size, - int auto_boot) + int auto_boot, void **load_address) { struct boot_params *setup_base; int setup_size; int bootproto; int big_image; - void *load_address; struct boot_params *params = (struct boot_params *)image; struct setup_header *hdr = ¶ms->hdr; @@ -134,14 +143,23 @@ void *load_zimage(char *image, unsigned long kernel_size, /* Determine load address */ if (big_image) - load_address = (void *)BZIMAGE_LOAD_ADDR; + *load_address = (void *)BZIMAGE_LOAD_ADDR; else - load_address = (void *)ZIMAGE_LOAD_ADDR; + *load_address = (void *)ZIMAGE_LOAD_ADDR; +#if defined CONFIG_ZBOOT_32 + printf("Building boot_params at 0x%8.8lx\n", (ulong)setup_base); + memset(setup_base, 0, sizeof(*setup_base)); + setup_base->hdr = params->hdr; + + setup_base->e820_entries = install_e820_map( + ARRAY_SIZE(setup_base->e820_map), setup_base->e820_map); +#else /* load setup */ printf("Moving Real-Mode Code to 0x%8.8lx (%d bytes)\n", (ulong)setup_base, setup_size); memmove(setup_base, image, setup_size); +#endif printf("Using boot protocol version %x.%02x\n", (bootproto & 0xff00) >> 8, bootproto & 0xff); @@ -180,7 +198,7 @@ void *load_zimage(char *image, unsigned long kernel_size, if (hdr->setup_sects >= 15) { printf("Linux kernel version %s\n", - (char *)setup_base + + (char *)params + hdr->kernel_version + 0x200); } else { printf("Setup Sectors < 15 - " @@ -235,17 +253,36 @@ void *load_zimage(char *image, unsigned long kernel_size, build_command_line((char *)setup_base + COMMAND_LINE_OFFSET, auto_boot); printf("Loading %czImage at address 0x%08x (%ld bytes)\n", - big_image ? 'b' : ' ', (u32)load_address, kernel_size); - + big_image ? 'b' : ' ', (u32)*load_address, kernel_size); - memmove(load_address, image + setup_size, kernel_size); + memmove(*load_address, image + setup_size, kernel_size); /* ready for booting */ return setup_base; } -void boot_zimage(void *setup_base) +void boot_zimage(void *setup_base, void *load_address) { + printf("\nStarting kernel ...\n\n"); + +#if defined CONFIG_ZBOOT_32 + /* + * Set %ebx, %ebp, and %edi to 0, %esi to point to the boot_params + * structure, and then jump to the kernel. We assume that %cs is + * 0x10, 4GB flat, and read/execute, and the data segments are 0x18, + * 4GB flat, and read/write. U-boot is setting them up that way for + * itself in arch/i386/cpu/cpu.c. + */ + __asm__ __volatile__ ( + "movl $0, %%ebp \n" + "cli \n" + "jmp %[kernel_entry] \n" + :: [kernel_entry]"a"(load_address), + [boot_params] "S"(setup_base), + "b"(0), "D"(0) + : "%ebp" + ); +#else struct pt_regs regs; memset(®s, 0, sizeof(struct pt_regs)); @@ -256,12 +293,14 @@ void boot_zimage(void *setup_base) regs.eflags = 0; enter_realmode(((u32)setup_base + SETUP_START_OFFSET) >> 4, 0, ®s, ®s); +#endif } int do_zboot(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) { void *base_ptr; void *bzImage_addr = NULL; + void *load_address; char *s; ulong bzImage_size = 0; @@ -285,7 +324,8 @@ int do_zboot(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) bzImage_size = simple_strtoul(argv[2], NULL, 16); /* Lets look for */ - base_ptr = load_zimage(bzImage_addr, bzImage_size, 0, 0, 0); + base_ptr = load_zimage(bzImage_addr, bzImage_size, 0, 0, 0, + &load_address); if (!base_ptr) { printf("## Kernel loading failed ...\n"); @@ -295,9 +335,7 @@ int do_zboot(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) (u32)base_ptr); /* we assume that the kernel is in place */ - printf("\nStarting kernel ...\n\n"); - - boot_zimage(base_ptr); + boot_zimage(base_ptr, load_address); /* does not return */ }