o Modify bzImage loader to be able to recognize a relocatable bzImage and 
  load it. Now bzImage loader can identify that bzImage is relocatable and
  can load the protected mode kernel code at a non 1MB addr.

Signed-off-by: Vivek Goyal <[EMAIL PROTECTED]>
---

 include/x86/x86-linux.h           |   10 ++++++-
 kexec/arch/i386/kexec-bzImage.c   |   48 +++++++++++++++++++++++++++++++++-----
 kexec/arch/i386/x86-linux-setup.c |    3 ++
 3 files changed, 53 insertions(+), 8 deletions(-)

diff -puN 
include/x86/x86-linux.h~kexec-tools-i386-support-loading-relocatable-bzImage 
include/x86/x86-linux.h
--- 
horms-kexec-tools/include/x86/x86-linux.h~kexec-tools-i386-support-loading-relocatable-bzImage
      2006-10-16 13:34:14.000000000 -0400
+++ horms-kexec-tools-root/include/x86/x86-linux.h      2006-10-16 
13:34:14.000000000 -0400
@@ -141,7 +141,10 @@ struct x86_linux_param_header {
        uint32_t high_filesz;                   /* 0x254 */
        uint8_t  reserved15[0x2d0 - 0x258];     /* 0x258 */
 #else
-       uint8_t  reserved15[0x2d0 - 0x230];     /* 0x230 */
+       /* 2.04+ */
+       uint32_t kernel_alignment;              /* 0x230 */
+       uint8_t  relocatable_kernel;            /* 0x234 */
+       uint8_t  reserved15[0x2d0 - 0x235];     /* 0x230 */
 #endif
        struct e820entry e820_map[E820MAX];     /* 0x2d0 */
                                                /* 0x550 */
@@ -201,12 +204,15 @@ struct x86_linux_header {
        uint32_t high_filesz;                   /* 0x254 */
        uint32_t tail[32*1024 - 0x258];         /* 0x258 */
 #else
-       uint8_t  tail[32*1024 - 0x230];         /* 0x230 */
+       uint32_t kernel_alignment;              /* 0x230 */
+       uint8_t  relocatable_kernel;            /* 0x234 */
+       uint8_t  tail[32*1024 - 0x235];         /* 0x230 */
 #endif
 } PACKED;
 
 #endif /* ASSEMBLY */
 
 #define DEFAULT_INITRD_ADDR_MAX 0x37FFFFFF
+#define DEFAULT_BZIMAGE_ADDR_MAX 0x37FFFFFF
 
 #endif /* X86_LINUX_H */
diff -puN 
kexec/arch/i386/kexec-bzImage.c~kexec-tools-i386-support-loading-relocatable-bzImage
 kexec/arch/i386/kexec-bzImage.c
--- 
horms-kexec-tools/kexec/arch/i386/kexec-bzImage.c~kexec-tools-i386-support-loading-relocatable-bzImage
      2006-10-16 13:34:14.000000000 -0400
+++ horms-kexec-tools-root/kexec/arch/i386/kexec-bzImage.c      2006-10-16 
13:34:38.000000000 -0400
@@ -109,6 +109,8 @@ int do_bzImage_load(struct kexec_info *i
        unsigned long setup_base, setup_size;
        struct entry32_regs regs32;
        struct entry16_regs regs16;
+       unsigned int relocatable_kernel = 0;
+       unsigned long kernel32_load_addr;
 
        /*
         * Find out about the file I am about to load.
@@ -121,6 +123,7 @@ int do_bzImage_load(struct kexec_info *i
        if (setup_sects == 0) {
                setup_sects = 4;
        }
+
        kern16_size = (setup_sects +1) *512;
        kernel_version = ((unsigned char *)&setup_header) + 512 + 
setup_header.kver_addr;
        if (kernel_len < kern16_size) {
@@ -128,13 +131,23 @@ int do_bzImage_load(struct kexec_info *i
                return -1;
        }
 
+       if (setup_header.protocol_version >= 0x0205) {
+               relocatable_kernel = setup_header.relocatable_kernel;
+               dfprintf(stdout, "bzImage is relocatable\n");
+       }
+
        /* Load the trampoline.  This must load at a higher address
         * the the argument/parameter segment or the kernel will stomp
         * it's gdt.
         */
-       elf_rel_build_load(info, &info->rhdr, purgatory, purgatory_size,
-               0x3000, 640*1024, -1, 0);
-
+       if (!real_mode_entry && relocatable_kernel)
+               elf_rel_build_load(info, &info->rhdr, purgatory, purgatory_size,
+                                       0x3000, -1, -1, 0);
+       else
+               elf_rel_build_load(info, &info->rhdr, purgatory, purgatory_size,
+                                       0x3000, 640*1024, -1, 0);
+       dfprintf(stdout, "Loaded purgatory at addr 0x%lx\n",
+                               info->rhdr.rel_addr);
        /* The argument/parameter segment */
        setup_size = kern16_size + command_line_len;
        real_mode = xmalloc(setup_size);
@@ -142,11 +155,13 @@ int do_bzImage_load(struct kexec_info *i
        if (real_mode->protocol_version >= 0x0200) {
                /* Careful setup_base must be greater than 8K */
                setup_base = add_buffer(info, real_mode, setup_size, setup_size,
-                       16, 0x3000, 640*1024, -1);
+                       16, 0x3000, 640*1024, 1);
        } else {
                add_segment(info, real_mode, setup_size, SETUP_BASE, 
setup_size);
                setup_base = SETUP_BASE;
        }
+       dfprintf(stdout, "Loaded real-mode code and command line at 0x%lx\n",
+                       setup_base);
        /* Verify purgatory loads higher than the parameters */
        if (info->rhdr.rel_addr < setup_base) {
                die("Could not put setup code above the kernel parameters\n");
@@ -154,9 +169,30 @@ int do_bzImage_load(struct kexec_info *i
        
        /* The main kernel segment */
        size = kernel_len - kern16_size;
-       add_segment(info, kernel + kern16_size, size, KERN32_BASE,  size);
 
+       if (real_mode->protocol_version >=0x0205 && relocatable_kernel) {
+               /* Relocatable bzImage */
+               unsigned long kern_align = real_mode->kernel_alignment;
+               unsigned long kernel32_max_addr = DEFAULT_BZIMAGE_ADDR_MAX;
+
+               if (real_mode->protocol_version >= 0x0203) {
+                       if (kernel32_max_addr > real_mode->initrd_addr_max)
+                               kernel32_max_addr = real_mode->initrd_addr_max;
+               }
+
+               kernel32_load_addr = add_buffer(info, kernel + kern16_size,
+                                               size, size, kern_align,
+                                               0x100000, kernel32_max_addr,
+                                               1);
+       }
+       else {
+               kernel32_load_addr = KERN32_BASE;
+               add_segment(info, kernel + kern16_size, size,
+                               kernel32_load_addr, size);
+       }
                
+       dfprintf(stdout, "Loaded 32bit kernel at 0x%lx\n", kernel32_load_addr);
+
        /* Tell the kernel what is going on */
        setup_linux_bootloader_parameters(info, real_mode, setup_base,
                kern16_size, command_line, command_line_len,
@@ -177,7 +213,7 @@ int do_bzImage_load(struct kexec_info *i
        regs32.edi = 0; /* unused */
        regs32.esp = elf_rel_get_addr(&info->rhdr, "stack_end"); /* stack, 
unused */
        regs32.ebp = 0; /* unused */
-       regs32.eip = KERN32_BASE; /* kernel entry point */
+       regs32.eip = kernel32_load_addr; /* kernel entry point */
 
        /*
         * Initialize the 16bit start information.
diff -puN 
kexec/arch/i386/x86-linux-setup.c~kexec-tools-i386-support-loading-relocatable-bzImage
 kexec/arch/i386/x86-linux-setup.c
--- 
horms-kexec-tools/kexec/arch/i386/x86-linux-setup.c~kexec-tools-i386-support-loading-relocatable-bzImage
    2006-10-16 13:34:14.000000000 -0400
+++ horms-kexec-tools-root/kexec/arch/i386/x86-linux-setup.c    2006-10-16 
13:34:14.000000000 -0400
@@ -61,6 +61,7 @@ void setup_linux_bootloader_parameters(
        initrd_addr_max = DEFAULT_INITRD_ADDR_MAX;
        if (real_mode->protocol_version >= 0x0203) {
                initrd_addr_max = real_mode->initrd_addr_max;
+               dfprintf(stdout, "initrd_addr_max is 0x%lx\n", initrd_addr_max);
        }
 
        /* Load the initrd if we have one */
@@ -68,6 +69,8 @@ void setup_linux_bootloader_parameters(
                initrd_base = add_buffer(info,
                        initrd_buf, initrd_size, initrd_size,
                        4096, INITRD_BASE, initrd_addr_max, -1);
+               dfprintf(stdout, "Loaded initrd at 0x%lx size 0x%lx\n",
+                                       initrd_base, initrd_size);
        } else {
                initrd_base = 0;
                initrd_size = 0;
_
_______________________________________________
fastboot mailing list
[email protected]
https://lists.osdl.org/mailman/listinfo/fastboot

Reply via email to