diff --git a/com32/include/syslinux/movebits.h b/com32/include/syslinux/movebits.h
index f35ef22..66ff494 100644
--- a/com32/include/syslinux/movebits.h
+++ b/com32/include/syslinux/movebits.h
@@ -74,6 +74,7 @@ int syslinux_memmap_largest(struct syslinux_memmap *list,
 			    addr_t *start, addr_t *len);
 void syslinux_free_memmap(struct syslinux_memmap *list);
 struct syslinux_memmap *syslinux_dup_memmap(struct syslinux_memmap *list);
+void syslinux_add_malloc_memory(const struct syslinux_memmap *map);
 
 /* Debugging functions */
 void syslinux_dump_movelist(FILE *file, struct syslinux_movelist *ml);
diff --git a/com32/lib/Makefile b/com32/lib/Makefile
index 0279904..63393dd 100644
--- a/com32/lib/Makefile
+++ b/com32/lib/Makefile
@@ -76,6 +76,7 @@ LIBOBJS = \
 	syslinux/ipappend.o syslinux/dsinfo.o syslinux/version.o	\
 	\
 	syslinux/addlist.o syslinux/freelist.o syslinux/memmap.o	\
+	syslinux/addmem.o						\
 	syslinux/movebits.o syslinux/shuffle.o syslinux/shuffle_pm.o	\
 	syslinux/shuffle_rm.o syslinux/zonelist.o			\
 	syslinux/dump_mmap.o syslinux/dump_movelist.o			\
diff --git a/com32/lib/free.c b/com32/lib/free.c
index aa17080..8980a50 100644
--- a/com32/lib/free.c
+++ b/com32/lib/free.c
@@ -7,8 +7,7 @@
 #include <stdlib.h>
 #include "malloc.h"
 
-static struct free_arena_header *
-__free_block(struct free_arena_header *ah)
+struct free_arena_header *__free_block(struct free_arena_header *ah)
 {
   struct free_arena_header *pah, *nah;
 
diff --git a/com32/lib/malloc.h b/com32/lib/malloc.h
index 830377d..a13acf6 100644
--- a/com32/lib/malloc.h
+++ b/com32/lib/malloc.h
@@ -22,7 +22,7 @@ struct free_arena_header;
 
 struct arena_header {
   size_t type;
-  size_t size;			/* Also gives the location of the next entry */
+  size_t size;
   struct free_arena_header *next, *prev;
 };
 
@@ -52,3 +52,4 @@ struct free_arena_header {
 };
 
 extern struct free_arena_header __malloc_head;
+struct free_arena_header *__free_block(struct free_arena_header *);
diff --git a/com32/lib/syslinux/addmem.c b/com32/lib/syslinux/addmem.c
new file mode 100644
index 0000000..ae9b108
--- /dev/null
+++ b/com32/lib/syslinux/addmem.c
@@ -0,0 +1,101 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   Copyright 2008 H. Peter Anvin - All Rights Reserved
+ *
+ *   Permission is hereby granted, free of charge, to any person
+ *   obtaining a copy of this software and associated documentation
+ *   files (the "Software"), to deal in the Software without
+ *   restriction, including without limitation the rights to use,
+ *   copy, modify, merge, publish, distribute, sublicense, and/or
+ *   sell copies of the Software, and to permit persons to whom
+ *   the Software is furnished to do so, subject to the following
+ *   conditions:
+ *
+ *   The above copyright notice and this permission notice shall
+ *   be included in all copies or substantial portions of the Software.
+ *
+ *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *   OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *   OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * addmem.c
+ *
+ * After probing the memory map, add previously unknown region to the
+ * malloc() arena allocator.  This is primarily intended to deal with
+ * machines with a memory hole in low extended memory (like at 15 MB);
+ * this makes the rest of the memory available so we can, say, load an
+ * initrd.  Those machines are still f*cked, but this is easy enough to
+ * do.
+ */
+
+#include <assert.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <inttypes.h>
+#include <string.h>
+
+#include <syslinux/movebits.h>
+#include "malloc.h"
+
+void syslinux_add_malloc_memory(const struct syslinux_memmap *map)
+{
+  addr_t start, end, len;
+  struct free_arena_header *ah, *fah;
+
+  ah = __malloc_head.a.next;	/* First (lowest address) block */
+
+  for (; map->type != SMT_END; map = map->next) {
+    if (map->type != SMT_FREE)
+      continue;
+    
+    start = map->start;
+    end = map->next->start - 1;
+
+    /* Truncate to the general memory region we care about */
+    if (start < 0x100000)
+      start = 0x100000;
+    if (end > 0xffffffff-(1 << 20))
+      end = 0xffffffff-(1 << 20);
+
+    if (end <= start)
+      continue;
+
+    len = end-start+1;
+    
+    while (ah != &__malloc_head && (uintptr_t)ah + ah->a.size < start)
+      ah = ah->a.next;
+      
+    /* Now ah is the lowest arena block inside or after this memory
+       region (which may be the head node in the latter case.) */
+
+    if (ah != &__malloc_head && (uintptr_t)ah <= end)
+      continue;			/* Already arena structures in this block */
+
+    /* No arena structures present, but this is usable memory.  ah points
+       to the *successor* of the new block we're about to create. */
+    if (len < 2*sizeof(struct arena_header))
+      continue;			/* Block unusably small */
+
+    /* Create the new block and add it to the block chain */
+    fah = (struct free_arena_header *)start;
+    fah->a.type = ARENA_TYPE_USED;
+    fah->a.size = len & ARENA_SIZE_MASK;
+    fah->a.prev = ah->a.prev;
+    fah->a.next = ah;
+    ah->a.prev->a.next = fah;
+    ah->a.prev = fah;
+    
+    /* Now add it to the free list */
+    __free_block(fah);
+  }
+}
+
diff --git a/com32/lib/syslinux/memmap.c b/com32/lib/syslinux/memmap.c
index 105c947..8285afd 100644
--- a/com32/lib/syslinux/memmap.c
+++ b/com32/lib/syslinux/memmap.c
@@ -36,7 +36,6 @@
 #include <errno.h>
 #include <stdlib.h>
 #include <inttypes.h>
-#include <setjmp.h>
 #include <string.h>
 
 #include <com32.h>
diff --git a/com32/modules/linux.c b/com32/modules/linux.c
index a2edd10..57b7049 100644
--- a/com32/modules/linux.c
+++ b/com32/modules/linux.c
@@ -44,6 +44,7 @@
 #include <syslinux/loadfile.h>
 #include <syslinux/linux.h>
 #include <syslinux/pxe.h>
+#include <syslinux/movebits.h>
 
 const char *progname = "linux.c32";
 
@@ -135,6 +136,19 @@ static char *make_cmdline(char **argv)
   return cmdline;
 }
 
+/* XXX: this function should be librarized */
+static void add_malloc_memory(void)
+{
+  struct syslinux_memmap *map;
+  
+  map = syslinux_memory_map();
+  if (!map)
+    return;
+
+  syslinux_add_malloc_memory(map);
+  syslinux_free_memmap(map);
+}
+
 int main(int argc, char *argv[])
 {
   uint32_t mem_limit = 0;
@@ -151,6 +165,7 @@ int main(int argc, char *argv[])
   char **argp, *arg, *p;
 
   openconsole(&dev_null_r, &dev_stdcon_w);
+  add_malloc_memory();
 
   (void)argc;
   argp = argv+1;
