[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