[syslinux] PATCH: Handle virtual entry point in mboot.c32

Matthew Iselin matthew at theiselins.net
Thu Apr 2 17:09:42 PDT 2009


Hi,

This patch ensures that mboot.c32 will always jump to a physical address
when loading a Multiboot kernel.

Some kernels are linked with a virtual entry point and without this patch
these kernels are unbootable.

Hope this helps,

Matthew

--- a/com32/modules/mboot.c	2009-04-03 09:48:08.000000000 +1000
+++ b/com32/modules/mboot.c	2009-04-03 09:48:16.000000000 +1000
@@ -650,6 +650,13 @@ static size_t load_kernel(struct multibo
                 exit(1);
             }
 
+            /* The real entry point is the actual physical location of the
code to jump to.
+             * This allows kernels with a virtual entry point address to
successfully run (if
+             * their startup code is position-independent). For instance, a
kernel whose
+             * entry point is at 0xFF400000 virtual, but 0x100000 physical
will be able to
+             * be booted because of this special handling.  */
+            Elf32_Addr realEntry = ehdr->e_entry;
+
 #ifdef DEBUG
             printf("Using ELF header.\n");
 #endif
@@ -682,6 +689,17 @@ static size_t load_kernel(struct multibo
                 /* Skip segments that don't take up any memory */
                 if (run_size == 0) continue;
 
+                /* If the entry point is within this program header, set
the real
+                 * entry point to the correct physical address. See GRUB's
stage2
+                 * (line 620) for a similar calculation. */
+                if(
+                    (ehdr->e_entry >= phdr[i].p_vaddr)
+                    &&
+                    (ehdr->e_entry < (phdr[i].p_vaddr + run_size))
+                   ) {
+                    realEntry = (ehdr->e_entry + phdr[i].p_paddr) -
phdr[i].p_vaddr;
+                }
+
                 /* Place the segment where it wants to be */
                 run_addr = phdr[i].p_paddr;
                 place_kernel_section(run_addr, run_size);
@@ -753,7 +771,7 @@ static size_t load_kernel(struct multibo
             }
 
             /* Done! */
-            return ehdr->e_entry;
+            return realEntry;
         }
     }





More information about the Syslinux mailing list