[U-Boot] [PATCH 2/2] x86: Add support for booting Linux using the 32 bit boot protocol
Graeme Russ
graeme.russ at gmail.com
Wed Nov 30 04:23:06 CET 2011
Hi Gabe,
Thanks, I've been itching for this :)
On Wed, Nov 30, 2011 at 2:11 PM, Gabe Black <gabeblack at chromium.org> wrote:
> This change conditionally modifies the zboot command so that it can use the
> 32 bit boot protocol. This is necessary because the 16 bit realmode entry
> point assumes that it can call BIOS services which neither coreboot nor
> u-boot provide.
>
> Signed-off-by: Gabe Black <gabeblack at chromium.org>
> ---
> arch/x86/include/asm/zimage.h | 4 +-
> arch/x86/lib/bootm.c | 6 +++-
> arch/x86/lib/zimage.c | 49 +++++++++++++++++++++++++++++++---------
> 3 files changed, 44 insertions(+), 15 deletions(-)
>
> diff --git a/arch/x86/include/asm/zimage.h b/arch/x86/include/asm/zimage.h
> index 1a77e00..8ee6a74 100644
> --- a/arch/x86/include/asm/zimage.h
> +++ b/arch/x86/include/asm/zimage.h
> @@ -46,8 +46,8 @@
>
> 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 bac7b4f..0905809 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 3b33486..1003929 100644
> --- a/arch/x86/lib/zimage.c
> +++ b/arch/x86/lib/zimage.c
> @@ -83,13 +83,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;
> @@ -136,14 +135,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);
Where is install_e820_map() defined?
> +#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);
> @@ -182,7 +190,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 - "
> @@ -237,17 +245,33 @@ 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)
> {
> +#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]"r"(load_address),
> + [boot_params] "S"(setup_base),
> + "b"(0), "D"(0)
> + );
> +#else
> struct pt_regs regs;
>
> memset(®s, 0, sizeof(struct pt_regs));
> @@ -258,12 +282,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;
>
> @@ -287,7 +313,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");
> @@ -299,7 +326,7 @@ int do_zboot(cmd_tbl_t *cmdtp, 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 */
> }
>
> --
> 1.7.3.1
>
Regards,
Graeme
More information about the U-Boot
mailing list