[syslinux] Com32/PXELINUX issues when booting on certain hardware

Salman Qazi sqazi at google.com
Mon Jun 16 11:16:00 PDT 2008


Hi,

It is possible for some BIOSes to return non-page-aligned values for
the start and length of regions in the BIOS memory map (through int
15h, e820h).  As a result, the initrd is loaded by linux.c32 (a
provided com32 module) in a manner such that the last page contains
both a portion of initrd and some BIOS data.  The linux kernel treats
this page as part of the ramdisk file system and ends up corrupting
the BIOS data.  Here is a patch (against syslinux-3.63) to fix this:

--- /a/syslinux/com32/lib/syslinux/memmap.c#2        2008-06-12
18:08:46.000000000 -0700
+++ /b/syslinux/com32/lib/syslinux/memmap.c#3        2008-06-16
11:09:01.000000000 -0700
@@ -42,6 +42,9 @@
 #include <com32.h>
 #include <syslinux/movebits.h>

+#define PAGE_SIZE     4096
+#define PAGE_MASK     (PAGE_SIZE - 1)
+
 struct e820_entry {
   uint64_t start;
   uint64_t len;
@@ -87,8 +90,22 @@
       break;

     type = e820buf->type == 1 ? SMT_FREE : SMT_RESERVED;
-    start = e820buf->start;
-    len = e820buf->len;
+
+    /*
+     * If the start and length of a usable region in the BIOS
+     * memory map are not page-aligned, we may end up passing
+     * an initrd to the kernel that shares a page with a reserved
+     * region of memory.  This results in the kernel accidentally
+     * overwriting data in such reserved regions.
+     */
+    /* Align the start to the next page boundary */
+    start = ((e820buf->start + PAGE_SIZE - 1) & ~PAGE_MASK);
+
+    /* Adjust length so that the end doesn't drift forward */
+    len = e820buf->len - (start - e820buf->start);
+
+    /* Page align the length */
+    len = (len & ~PAGE_MASK);

     if (start < 0x100000000ULL) {
       /* Don't rely on E820 being valid for low memory.  Doing so




Kindest Regards,

Salman Qazi




More information about the Syslinux mailing list