[U-Boot] [PATCH 0/2] Add support for the 32 bit boot protocol to the x86 zboot command.

These two patches add support for the 32 bit Linux boot protocol to the zboot command.
Gabe Black (2): x86: Clean up the x86 zimage code in preparation to extend it x86: Add support for booting Linux using the 32 bit boot protocol
arch/x86/include/asm/zimage.h | 25 +-------- arch/x86/lib/bootm.c | 6 +- arch/x86/lib/zimage.c | 125 ++++++++++++++++++++++++++--------------- 3 files changed, 86 insertions(+), 70 deletions(-)

This change cleans up some formatting issues in the zimage handling code, and converts it from using offsets added to a base pointer to using the available structure definitions which were already being included.
Signed-off-by: Gabe Black gabeblack@chromium.org --- arch/x86/include/asm/zimage.h | 21 ---------- arch/x86/lib/zimage.c | 82 ++++++++++++++++++++++------------------ 2 files changed, 45 insertions(+), 58 deletions(-)
diff --git a/arch/x86/include/asm/zimage.h b/arch/x86/include/asm/zimage.h index a02637f..1a77e00 100644 --- a/arch/x86/include/asm/zimage.h +++ b/arch/x86/include/asm/zimage.h @@ -27,27 +27,6 @@ /* linux i386 zImage/bzImage header. Offsets relative to * the start of the image */
-#define CMD_LINE_MAGIC_OFF 0x020 /* Magic 0xa33f if the offset below is valid */ -#define CMD_LINE_OFFSET_OFF 0x022 /* Offset to comandline */ -#define SETUP_SECTS_OFF 0x1F1 /* The size of the setup in sectors */ -#define ROOT_FLAGS_OFF 0x1F2 /* If set, the root is mounted readonly */ -#define VID_MODE_OFF 0x1FA /* Video mode control */ -#define ROOT_DEV_OFF 0x1FC /* Default root device number */ -#define BOOT_FLAG_OFF 0x1FE /* 0xAA55 magic number */ -#define HEADER_OFF 0x202 /* Magic signature "HdrS" */ -#define VERSION_OFF 0x206 /* Boot protocol version supported */ -#define REALMODE_SWTCH_OFF 0x208 /* Boot loader hook (see below) */ -#define START_SYS_OFF 0x20C /* Points to kernel version string */ -#define TYPE_OF_LOADER_OFF 0x210 /* Boot loader identifier */ -#define LOADFLAGS_OFF 0x211 /* Boot protocol option flags */ -#define SETUP_MOVE_SIZE_OFF 0x212 /* Move to high memory size (used with hooks) */ -#define CODE32_START_OFF 0x214 /* Boot loader hook (see below) */ -#define RAMDISK_IMAGE_OFF 0x218 /* initrd load address (set by boot loader) */ -#define RAMDISK_SIZE_OFF 0x21C /* initrd size (set by boot loader) */ -#define HEAP_END_PTR_OFF 0x224 /* Free memory after setup end */ -#define CMD_LINE_PTR_OFF 0x228 /* 32-bit pointer to the kernel command line */ - - #define HEAP_FLAG 0x80 #define BIG_KERNEL_FLAG 0x01
diff --git a/arch/x86/lib/zimage.c b/arch/x86/lib/zimage.c index 6843ff6..3b33486 100644 --- a/arch/x86/lib/zimage.c +++ b/arch/x86/lib/zimage.c @@ -1,4 +1,5 @@ /* + * Copyright (c) 2011 The Chromium OS Authors. * (C) Copyright 2002 * Daniel Engström, Omicron Ceti AB, daniel@omicron.se * @@ -84,21 +85,22 @@ void *load_zimage(char *image, unsigned long kernel_size, unsigned long initrd_addr, unsigned long initrd_size, int auto_boot) { - void *setup_base; + struct boot_params *setup_base; int setup_size; int bootproto; int big_image; void *load_address; - struct setup_header *hdr;
- hdr = (struct setup_header *)(image + SETUP_SECTS_OFF); + struct boot_params *params = (struct boot_params *)image; + struct setup_header *hdr = ¶ms->hdr;
/* base address for real-mode segment */ - setup_base = (void *)DEFAULT_SETUP_BASE; + setup_base = (struct boot_params *)DEFAULT_SETUP_BASE;
if (KERNEL_MAGIC != hdr->boot_flag) { - printf("Error: Invalid Boot Flag (found 0x%04x, expected 0x%04x)\n", - hdr->boot_flag, KERNEL_MAGIC); + printf("Error: Invalid Boot Flag " + "(found 0x%04x, expected 0x%04x)\n", + hdr->boot_flag, KERNEL_MAGIC); return 0; } else { printf("Valid Boot Flag\n"); @@ -133,9 +135,10 @@ void *load_zimage(char *image, unsigned long kernel_size, (hdr->loadflags & BIG_KERNEL_FLAG);
/* Determine load address */ - load_address = (void *)(big_image ? - BZIMAGE_LOAD_ADDR : - ZIMAGE_LOAD_ADDR); + if (big_image) + load_address = (void *)BZIMAGE_LOAD_ADDR; + else + load_address = (void *)ZIMAGE_LOAD_ADDR;
/* load setup */ printf("Moving Real-Mode Code to 0x%8.8lx (%d bytes)\n", @@ -146,8 +149,8 @@ void *load_zimage(char *image, unsigned long kernel_size, (bootproto & 0xff00) >> 8, bootproto & 0xff);
if (bootproto == 0x0100) { - *(u16 *)(setup_base + CMD_LINE_MAGIC_OFF) = COMMAND_LINE_MAGIC; - *(u16 *)(setup_base + CMD_LINE_OFFSET_OFF) = COMMAND_LINE_OFFSET; + setup_base->screen_info.cl_magic = COMMAND_LINE_MAGIC; + setup_base->screen_info.cl_offset = COMMAND_LINE_OFFSET;
/* * A very old kernel MUST have its real-mode code @@ -159,33 +162,36 @@ void *load_zimage(char *image, unsigned long kernel_size,
/* Copy the command line */ memmove((void *)0x99000, - setup_base + COMMAND_LINE_OFFSET, + (u8 *)setup_base + COMMAND_LINE_OFFSET, COMMAND_LINE_SIZE);
/* Relocated */ - setup_base = (void *)0x90000; + setup_base = (struct boot_params *)0x90000; }
/* It is recommended to clear memory up to the 32K mark */ - memset((void *)0x90000 + setup_size, 0, - SETUP_MAX_SIZE-setup_size); + memset((u8 *)0x90000 + setup_size, 0, + SETUP_MAX_SIZE - setup_size); }
/* We are now setting up the real-mode version of the header */ - hdr = (struct setup_header *)(setup_base + SETUP_SECTS_OFF); + hdr = &setup_base->hdr;
if (bootproto >= 0x0200) { hdr->type_of_loader = 8;
- if (hdr->setup_sects >= 15) + if (hdr->setup_sects >= 15) { printf("Linux kernel version %s\n", - (char *)(setup_base + - (hdr->kernel_version + 0x200))); - else - printf("Setup Sectors < 15 - Cannot print kernel version.\n"); + (char *)setup_base + + hdr->kernel_version + 0x200); + } else { + printf("Setup Sectors < 15 - " + "Cannot print kernel version.\n"); + }
if (initrd_addr) { - printf("Initial RAM disk at linear address 0x%08lx, size %ld bytes\n", + printf("Initial RAM disk at linear address " + "0x%08lx, size %ld bytes\n", initrd_addr, initrd_size);
hdr->ramdisk_image = initrd_addr; @@ -199,11 +205,11 @@ void *load_zimage(char *image, unsigned long kernel_size, }
if (bootproto >= 0x0202) { - hdr->cmd_line_ptr = (u32)setup_base + COMMAND_LINE_OFFSET; + hdr->cmd_line_ptr = + (uintptr_t)setup_base + COMMAND_LINE_OFFSET; } else if (bootproto >= 0x0200) { - - *(u16 *)(setup_base + CMD_LINE_MAGIC_OFF) = COMMAND_LINE_MAGIC; - *(u16 *)(setup_base + CMD_LINE_OFFSET_OFF) = COMMAND_LINE_OFFSET; + setup_base->screen_info.cl_magic = COMMAND_LINE_MAGIC; + setup_base->screen_info.cl_offset = COMMAND_LINE_OFFSET;
hdr->setup_move_size = 0x9100; } @@ -216,11 +222,11 @@ void *load_zimage(char *image, unsigned long kernel_size,
if (big_image) { if ((kernel_size) > BZIMAGE_MAX_SIZE) { - printf("Error: bzImage kernel too big! (size: %ld, max: %d)\n", - kernel_size, BZIMAGE_MAX_SIZE); + printf("Error: bzImage kernel too big! " + "(size: %ld, max: %d)\n", + kernel_size, BZIMAGE_MAX_SIZE); return 0; } - } else if ((kernel_size) > ZIMAGE_MAX_SIZE) { printf("Error: zImage kernel too big! (size: %ld, max: %d)\n", kernel_size, ZIMAGE_MAX_SIZE); @@ -228,7 +234,7 @@ void *load_zimage(char *image, unsigned long kernel_size, }
/* build command line at COMMAND_LINE_OFFSET */ - build_command_line(setup_base + COMMAND_LINE_OFFSET, auto_boot); + 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); @@ -250,8 +256,8 @@ void boot_zimage(void *setup_base) regs.xss = regs.xds; regs.esp = 0x9000; regs.eflags = 0; - enter_realmode(((u32)setup_base+SETUP_START_OFFSET)>>4, 0, ®s, - ®s); + enter_realmode(((u32)setup_base + SETUP_START_OFFSET) >> 4, 0, + ®s, ®s); }
int do_zboot(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) @@ -266,11 +272,12 @@ int do_zboot(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) /* Setup board for maximum PC/AT Compatibility */ setup_pcat_compatibility();
- if (argc >= 2) + if (argc >= 2) { /* argv[1] holds the address of the bzImage */ s = argv[1]; - else + } else { s = getenv("fileaddr"); + }
if (s) bzImage_addr = (void *)simple_strtoul(s, NULL, 16); @@ -279,14 +286,15 @@ int do_zboot(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) /* argv[2] holds the size of the bzImage */ bzImage_size = simple_strtoul(argv[2], NULL, 16);
- /* Lets look for*/ + /* Lets look for */ base_ptr = load_zimage(bzImage_addr, bzImage_size, 0, 0, 0);
if (!base_ptr) { printf("## Kernel loading failed ...\n"); } else { - printf("## Transferring control to Linux (at address %08x) ...\n", - (u32)base_ptr); + printf("## Transferring control to Linux " + "(at address %08x) ...\n", + (u32)base_ptr);
/* we assume that the kernel is in place */ printf("\nStarting kernel ...\n\n");

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@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); +#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 */ }

Hi Gabe,
Thanks, I've been itching for this :)
On Wed, Nov 30, 2011 at 2:11 PM, Gabe Black gabeblack@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@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

Hmm, that's in an intervening patch. I didn't think that one was necessary but apparently it is. I'll add that to the series and send this out again.
Gabe
On Tue, Nov 29, 2011 at 7:23 PM, Graeme Russ graeme.russ@gmail.com wrote:
Hi Gabe,
Thanks, I've been itching for this :)
On Wed, Nov 30, 2011 at 2:11 PM, Gabe Black gabeblack@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@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

Hi Gabe,
On Wed, Nov 30, 2011 at 2:29 PM, Gabe Black gabeblack@chromium.org wrote:
Hmm, that's in an intervening patch. I didn't think that one was necessary but apparently it is. I'll add that to the series and send this out again.
That would be nice ;)
P.S. Please stop top-quoting...
Regards,
Graeme

On Tue, Nov 29, 2011 at 7:39 PM, Graeme Russ graeme.russ@gmail.com wrote:
Hi Gabe,
On Wed, Nov 30, 2011 at 2:29 PM, Gabe Black gabeblack@chromium.org wrote:
Hmm, that's in an intervening patch. I didn't think that one was
necessary
but apparently it is. I'll add that to the series and send this out
again.
That would be nice ;)
P.S. Please stop top-quoting...
Regards,
Graeme
Actually that patch depends on another one too. Since those don't really go with these, I'll just send them out separately and they'll need to be applied first.
Gabe

Hi Gabe,
On Wed, Nov 30, 2011 at 2:50 PM, Gabe Black gabeblack@google.com wrote:
On Tue, Nov 29, 2011 at 7:39 PM, Graeme Russ graeme.russ@gmail.com wrote:
Hi Gabe,
On Wed, Nov 30, 2011 at 2:29 PM, Gabe Black gabeblack@chromium.org wrote:
Hmm, that's in an intervening patch. I didn't think that one was necessary but apparently it is. I'll add that to the series and send this out again.
That would be nice ;)
P.S. Please stop top-quoting...
Regards,
Graeme
Actually that patch depends on another one too. Since those don't really go with these, I'll just send them out separately and they'll need to be applied first.
Sounds good me
Regards,
Graeme

On Tue, Nov 29, 2011 at 7:52 PM, Graeme Russ graeme.russ@gmail.com wrote:
Hi Gabe,
On Wed, Nov 30, 2011 at 2:50 PM, Gabe Black gabeblack@google.com wrote:
On Tue, Nov 29, 2011 at 7:39 PM, Graeme Russ graeme.russ@gmail.com
wrote:
Hi Gabe,
On Wed, Nov 30, 2011 at 2:29 PM, Gabe Black gabeblack@chromium.org wrote:
Hmm, that's in an intervening patch. I didn't think that one was necessary but apparently it is. I'll add that to the series and send this out again.
That would be nice ;)
P.S. Please stop top-quoting...
Regards,
Graeme
Actually that patch depends on another one too. Since those don't really
go
with these, I'll just send them out separately and they'll need to be applied first.
Sounds good me
Regards,
Graeme
Since this series has to be applied after the other anyway, I think I will send it out again with another patch or two I was holding back.
Gabe

Hi Gabe,
On Wed, Nov 30, 2011 at 2:11 PM, Gabe Black gabeblack@chromium.org wrote:
These two patches add support for the 32 bit Linux boot protocol to the zboot command.
Going by our previous offline correspondence, I assume this approach still uses the bzImage's decompression stub?
Also, as I discussion offline previously, I'm going through the boot_params with a fine-tooth comb to get a complete picture of what the Linux kernel actually requires to be filled out in the boot_params structure - I expect this will result in a 'built_boot_params()' function which is called by zboot and bootm - possibly with some weak stubs to helper functions
Regards,
Graeme

On Tue, Nov 29, 2011 at 7:48 PM, Graeme Russ graeme.russ@gmail.com wrote:
Hi Gabe,
On Wed, Nov 30, 2011 at 2:11 PM, Gabe Black gabeblack@chromium.org wrote:
These two patches add support for the 32 bit Linux boot protocol to the zboot command.
Going by our previous offline correspondence, I assume this approach still uses the bzImage's decompression stub?
Also, as I discussion offline previously, I'm going through the boot_params with a fine-tooth comb to get a complete picture of what the Linux kernel actually requires to be filled out in the boot_params structure - I expect this will result in a 'built_boot_params()' function which is called by zboot and bootm - possibly with some weak stubs to helper functions
Regards,
Graeme
Yes, this supports the 32 bit protocol which includes the decompression stub. I don't think a build_boot_params function which actually builds the bootstub would work for a number of reasons. First, that's not how the boot protocol works. The kernel provides information there that u-boot needs to read, and u-boot shouldn't just make it up. An example of this is what boot protocol is expected. Second, you might find all the things a particular version of the kernel wants right now, but that could easy change at any time and break booting. Third, the boot_params structure isn't compressed (because otherwise the bootloader couldn't fill it out) and building our own wouldn't serve any purpose.
If you mean consolidating the existing boot_params code so that both zboot and bootm can use it, that seems reasonable. I'd point out, though, that filling out the table takes a trivial amount of time, so trying to cut corners and not fill it out completely would not only be dangerous, it would very likely not be worth the effort.
Gabe

On Wed, Nov 30, 2011 at 5:25 PM, Gabe Black gabeblack@google.com wrote:
On Tue, Nov 29, 2011 at 7:48 PM, Graeme Russ graeme.russ@gmail.com wrote:
Hi Gabe,
On Wed, Nov 30, 2011 at 2:11 PM, Gabe Black gabeblack@chromium.org wrote:
These two patches add support for the 32 bit Linux boot protocol to the zboot command.
Going by our previous offline correspondence, I assume this approach still uses the bzImage's decompression stub?
Also, as I discussion offline previously, I'm going through the boot_params with a fine-tooth comb to get a complete picture of what the Linux kernel actually requires to be filled out in the boot_params structure - I expect this will result in a 'built_boot_params()' function which is called by zboot and bootm - possibly with some weak stubs to helper functions
Regards,
Graeme
Yes, this supports the 32 bit protocol which includes the decompression stub. I don't think a build_boot_params function which actually builds the bootstub would work for a number of reasons. First, that's not how the boot protocol works. The kernel provides information there that u-boot needs to
Well actually, the kernel does not provide that information - That information is generated during the compilation of the kernel
read, and u-boot shouldn't just make it up. An example of this is what boot protocol is expected. Second, you might find all the things a particular
Correct - The kernel build process files in a few important pieces of information for the bootloader - Particularly, this information lets the bootloader know where it can physically place the kernel, if the kernel is relocatable, what the minimum and optimum alignments of a relocatable kernel are, where the command line arguments can be stored, how big the command line can be, etc, etc,
version of the kernel wants right now, but that could easy change at any time and break booting. Third, the boot_params structure isn't compressed
But once a location in the boot_params structure has been given a defined purpose, it is never re-allocated (only deprecated) so using the latest version of boot_params guarantees that we will have all the fields for all kernels. The 'Protocol Version' field tells us what fields are required
(because otherwise the bootloader couldn't fill it out) and building our own wouldn't serve any purpose.
Correct. What I'm suggesting is that we take the boot_params structure created during the kernel build process and include it in the uImage so we would have a uImage containing (vmlinux + boot_params + initrd). We extract the boot_params, use the info contained within to load the kernel into the correct location in memory, fill out the bits of boot_params that the kernel needs from us (command line and e820 map mostly, but I think there may be one or two others) and jump into the kernel.
If you mean consolidating the existing boot_params code so that both zboot and bootm can use it, that seems reasonable. I'd point out, though, that filling out the table takes a trivial amount of time, so trying to cut corners and not fill it out completely would not only be dangerous, it would very likely not be worth the effort.
I'm not suggesting cutting corners - If we have a centralised function which gets passed a boot_params and it fills out all the required info, then we only have one code location that needs updating for any new Linux kernel. This is essentially all that the 16-bit 'setup.bin' which sits at the start of bzImage does.
Regards,
Graeme

Hi Gabe,
On 30/11/11 17:25, Gabe Black wrote:
On Tue, Nov 29, 2011 at 7:48 PM, Graeme Russ <graeme.russ@gmail.com mailto:graeme.russ@gmail.com> wrote:
Hi Gabe, On Wed, Nov 30, 2011 at 2:11 PM, Gabe Black <gabeblack@chromium.org <mailto:gabeblack@chromium.org>> wrote: > These two patches add support for the 32 bit Linux boot protocol to the > zboot command. Going by our previous offline correspondence, I assume this approach still uses the bzImage's decompression stub? Also, as I discussion offline previously, I'm going through the boot_params with a fine-tooth comb to get a complete picture of what the Linux kernel actually requires to be filled out in the boot_params structure - I expect this will result in a 'built_boot_params()' function which is called by zboot and bootm - possibly with some weak stubs to helper functions Regards, Graeme
Yes, this supports the 32 bit protocol which includes the decompression stub. I don't think a build_boot_params function which actually builds the bootstub would work for a number of reasons. First, that's not how the boot protocol works. The kernel provides information there that u-boot needs to read, and u-boot shouldn't just make it up. An example of this is what boot protocol is expected. Second, you might find all the things a particular version of the kernel wants right now, but that could easy change at any time and break booting. Third, the boot_params structure isn't compressed (because otherwise the bootloader couldn't fill it out) and building our own wouldn't serve any purpose.
If you mean consolidating the existing boot_params code so that both zboot and bootm can use it, that seems reasonable. I'd point out, though, that filling out the table takes a trivial amount of time, so trying to cut corners and not fill it out completely would not only be dangerous, it would very likely not be worth the effort.
I've been playing around tonight and have managed to embed a gzip'd vmlinux and raw header (stripped from the associated bzImage) into my U-Boot image but I end up getting the same results - No RAM :(
So proof of concept is good
Regards
Graeme

On Thu, Dec 1, 2011 at 7:47 AM, Graeme Russ graeme.russ@gmail.com wrote:
Hi Gabe,
On 30/11/11 17:25, Gabe Black wrote:
On Tue, Nov 29, 2011 at 7:48 PM, Graeme Russ <graeme.russ@gmail.com mailto:graeme.russ@gmail.com> wrote:
Hi Gabe, On Wed, Nov 30, 2011 at 2:11 PM, Gabe Black <gabeblack@chromium.org <mailto:gabeblack@chromium.org>> wrote: > These two patches add support for the 32 bit Linux boot protocol
to the
> zboot command. Going by our previous offline correspondence, I assume this approach
still
uses the bzImage's decompression stub? Also, as I discussion offline previously, I'm going through the
boot_params
with a fine-tooth comb to get a complete picture of what the Linux
kernel
actually requires to be filled out in the boot_params structure - I
expect
this will result in a 'built_boot_params()' function which is called
by
zboot and bootm - possibly with some weak stubs to helper functions Regards, Graeme
Yes, this supports the 32 bit protocol which includes the decompression stub. I don't think a build_boot_params function which actually builds
the
bootstub would work for a number of reasons. First, that's not how the
boot
protocol works. The kernel provides information there that u-boot needs
to
read, and u-boot shouldn't just make it up. An example of this is what
boot
protocol is expected. Second, you might find all the things a particular version of the kernel wants right now, but that could easy change at any time and break booting. Third, the boot_params structure isn't compressed (because otherwise the bootloader couldn't fill it out) and building our own wouldn't serve any purpose.
If you mean consolidating the existing boot_params code so that both
zboot
and bootm can use it, that seems reasonable. I'd point out, though, that filling out the table takes a trivial amount of time, so trying to cut corners and not fill it out completely would not only be dangerous, it would very likely not be worth the effort.
I've been playing around tonight and have managed to embed a gzip'd vmlinux and raw header (stripped from the associated bzImage) into my U-Boot image but I end up getting the same results - No RAM :(
So proof of concept is good
Regards
Graeme
You have to make sure you're using the 32 bit protocol. The 16 bit protocol should still work and is the default, but then the kernel tries to use other means to figure out what memory looks like. To use the 32 bit protocol, you need to define CONFIG_ZBOOT_32.
Gabe

Hi Gabe,
On Fri, Dec 2, 2011 at 8:26 AM, Gabe Black gabeblack@google.com wrote:
On Thu, Dec 1, 2011 at 7:47 AM, Graeme Russ graeme.russ@gmail.com wrote:
Hi Gabe,
On 30/11/11 17:25, Gabe Black wrote:
On Tue, Nov 29, 2011 at 7:48 PM, Graeme Russ <graeme.russ@gmail.com mailto:graeme.russ@gmail.com> wrote:
Hi Gabe,
On Wed, Nov 30, 2011 at 2:11 PM, Gabe Black <gabeblack@chromium.org mailto:gabeblack@chromium.org> wrote: > These two patches add support for the 32 bit Linux boot protocol to the > zboot command.
Going by our previous offline correspondence, I assume this approach still uses the bzImage's decompression stub?
Also, as I discussion offline previously, I'm going through the boot_params with a fine-tooth comb to get a complete picture of what the Linux kernel actually requires to be filled out in the boot_params structure - I expect this will result in a 'built_boot_params()' function which is called by zboot and bootm - possibly with some weak stubs to helper functions
Regards,
Graeme
Yes, this supports the 32 bit protocol which includes the decompression stub. I don't think a build_boot_params function which actually builds the bootstub would work for a number of reasons. First, that's not how the boot protocol works. The kernel provides information there that u-boot needs to read, and u-boot shouldn't just make it up. An example of this is what boot protocol is expected. Second, you might find all the things a particular version of the kernel wants right now, but that could easy change at any time and break booting. Third, the boot_params structure isn't compressed (because otherwise the bootloader couldn't fill it out) and building our own wouldn't serve any purpose.
If you mean consolidating the existing boot_params code so that both zboot and bootm can use it, that seems reasonable. I'd point out, though, that filling out the table takes a trivial amount of time, so trying to cut corners and not fill it out completely would not only be dangerous, it would very likely not be worth the effort.
I've been playing around tonight and have managed to embed a gzip'd vmlinux and raw header (stripped from the associated bzImage) into my U-Boot image but I end up getting the same results - No RAM :(
So proof of concept is good
Regards
Graeme
You have to make sure you're using the 32 bit protocol. The 16 bit protocol should still work and is the default, but then the kernel tries to use other means to figure out what memory looks like. To use the 32 bit protocol, you need to define CONFIG_ZBOOT_32.
Yep, done that - And when you boot a raw vmlinux, there is no 16-bit protocol as there is no 'setup.bin' stub
There is something else going on with the e820 - Any chance you could provide a dump of a typical e820 array passed into the kernel by your coreboot patches?
Regards,
Graeme
participants (3)
-
Gabe Black
-
Gabe Black
-
Graeme Russ