diff --git a/com32/include/com32.h b/com32/include/com32.h
index 8be8721..5c031ff 100644
--- a/com32/include/com32.h
+++ b/com32/include/com32.h
@@ -75,6 +75,7 @@ extern struct com32_sys_args {
   uint32_t cs_bounce_size;
   void __cdecl (*cs_farcall)(uint32_t, const com32sys_t *, com32sys_t *);
   int __cdecl (*cs_cfarcall)(uint32_t, const void *, uint32_t);
+  uint32_t cs_memsize;
 } __com32;
 
 /*
diff --git a/com32/lib/free.c b/com32/lib/free.c
index aa17080..2004407 100644
--- a/com32/lib/free.c
+++ b/com32/lib/free.c
@@ -58,6 +58,42 @@ __free_block(struct free_arena_header *ah)
   return ah;
 }
 
+/*
+ * This is used to insert a block which is not previously on the
+ * free list.  Only the a.size field of the arena header is assumed
+ * to be valid.
+ */
+void __inject_free_block(struct free_arena_header *ah)
+{
+  struct free_arena_header *nah;
+  size_t a_end = (size_t)ah + ah->a.size;
+  size_t n_end;
+
+  for (nah = __malloc_head.a.next; nah->a.type != ARENA_TYPE_HEAD;
+       nah = nah->a.next) {
+    n_end = (size_t)nah + nah->a.size;
+
+    /* Is nah entirely beyond this block? */
+    if ((size_t)nah >= a_end)
+      break;
+
+    /* Is this block entirely beyond nah? */
+    if ((size_t)ah >= n_end)
+      continue;
+
+    /* Otherwise we have some sort of overlap - reject this block */
+    return;
+  }
+
+  /* Now, nah should point to the successor block */
+  ah->a.next = nah;
+  ah->a.prev = nah->a.prev;
+  nah->a.prev = ah;
+  ah->a.prev->a.next = ah;
+
+  __free_block(ah);
+}
+
 void free(void *ptr)
 {
   struct free_arena_header *ah;
diff --git a/com32/lib/malloc.c b/com32/lib/malloc.c
index 2f8362b..fbab9f4 100644
--- a/com32/lib/malloc.c
+++ b/com32/lib/malloc.c
@@ -5,6 +5,8 @@
  */
 
 #include <stdlib.h>
+#include <string.h>
+#include <com32.h>
 #include "init.h"
 #include "malloc.h"
 
@@ -31,10 +33,20 @@ static inline size_t sp(void)
   return sp;
 }
 
+struct e820_entry {
+  uint64_t start;
+  uint64_t len;
+  uint32_t type;
+  uint32_t extattr;
+};
+
 static void __constructor init_memory_arena(void)
 {
-  struct free_arena_header *fp;
+  struct free_arena_header *fp, *fx;
   size_t start, total_space;
+  static com32sys_t ireg;
+  com32sys_t oreg;
+  struct e820_entry *e820buf;
 
   start = (size_t)ARENA_ALIGN_UP(__mem_end);
   total_space = sp() - start;
@@ -46,14 +58,62 @@ static void __constructor init_memory_arena(void)
     __stack_size = total_space - 4*sizeof(struct arena_header);
 
   fp = (struct free_arena_header *)start;
-  fp->a.type = ARENA_TYPE_FREE;
   fp->a.size = total_space - __stack_size;
 
-  /* Insert into chains */
-  fp->a.next = fp->a.prev = &__malloc_head;
-  fp->next_free = fp->prev_free = &__malloc_head;
-  __malloc_head.a.next = __malloc_head.a.prev = fp;
-  __malloc_head.next_free = __malloc_head.prev_free = fp;
+  __inject_free_block(fp);
+
+  /* Scan E820 to see if there are any other suitable blocks */
+  if (!__com32.cs_memsize)
+    return;			/* Old Syslinux core, can't do this... */
+
+  e820buf = __com32.cs_bounce;
+  ireg.eax.l    = 0xe820;
+  ireg.edx.l    = 0x534d4150;
+  ireg.ebx.l    = 0;
+  ireg.ecx.l    = sizeof(*e820buf);
+  ireg.es       = SEG(e820buf);
+  ireg.edi.w[0] = OFFS(e820buf);
+  memset(e820buf, 0, sizeof *e820buf);
+  e820buf->extattr = 1;
+
+  do {
+    uint64_t start, end, len;
+
+    __intcall(0x15, &ireg, &oreg);
+
+    if ((oreg.eflags.l & EFLAGS_CF) ||
+	(oreg.eax.l != 0x534d4150) ||
+	(oreg.ecx.l < 20))
+      break;
+
+    if (oreg.ecx.l > 20 && !(e820buf->extattr & 1))
+      continue;
+    if (e820buf->type != 1)
+      continue;
+
+    start = e820buf->start;
+    len = e820buf->len;
+
+    if (start >= (1ULL << 32))
+      continue;			/* Ignore 64-bit memory */
+    if (len > (1ULL << 32)-start)
+      len = (1ULL << 32)-start;
+
+    end = start + len;
+
+    if (end <= __com32.cs_memsize)
+      continue;
+    if (start <= __com32.cs_memsize) {
+      start = __com32.cs_memsize;
+      len = end - start;
+    }
+
+    if (len >= 2*sizeof(struct arena_header)) {
+      fp = (struct free_arena_header *)start;
+      fp->a.size = len;
+      __inject_free_block(fp);
+    }
+  } while ((ireg.ebx.l = oreg.ebx.l));
 }
 
 static void *__malloc_from_block(struct free_arena_header *fp, size_t size)
diff --git a/com32/lib/malloc.h b/com32/lib/malloc.h
index 830377d..983a3c5 100644
--- a/com32/lib/malloc.h
+++ b/com32/lib/malloc.h
@@ -52,3 +52,5 @@ struct free_arena_header {
 };
 
 extern struct free_arena_header __malloc_head;
+void __inject_free_block(struct free_arena_header *ah);
+
diff --git a/com32/lib/sys/entry.S b/com32/lib/sys/entry.S
index ed5da95..53bf2ec 100644
--- a/com32/lib/sys/entry.S
+++ b/com32/lib/sys/entry.S
@@ -30,7 +30,7 @@
  */
 
 /* Number of arguments in our version of the entry structure */
-#define COM32_ARGS 6
+#define COM32_ARGS 7
 
 		.section ".init","ax"
 		.globl _start
diff --git a/core/com32.inc b/core/com32.inc
index bd6d727..477d657 100644
--- a/core/com32.inc
+++ b/core/com32.inc
@@ -178,7 +178,8 @@ com32_call_start:
 		push dword (comboot_seg << 4)	; Bounce buffer address
 		push dword com32_intcall	; Intcall entry point
 		push dword command_line		; Command line pointer
-		push dword 6			; Argument count
+		push dword [HighMemSize]	; Memory managed by Syslinux
+		push dword 7			; Argument count
 		sti				; Interrupts OK now
 		call pm_entry			; Run the program...
 		; ... on return, fall through to com32_exit ...
diff --git a/doc/comboot.txt b/doc/comboot.txt
index 5f57da7..d7890d4 100644
--- a/doc/comboot.txt
+++ b/doc/comboot.txt
@@ -79,13 +79,14 @@ The following arguments are passed to the program on the stack:
 
  Address  Size	Meaning
  [ESP]    dword Return (termination) address
- [ESP+4]  dword	Number of additional arguments (currently 5)
+ [ESP+4]  dword	Number of additional arguments (currently 7)
  [ESP+8]  dword	Pointer to the command line arguments (null-terminated string)
  [ESP+12] dword Pointer to INT call helper function
  [ESP+16] dword Pointer to low memory bounce buffer
  [ESP+20] dword Size of low memory bounce buffer
  [ESP+24] dword Pointer to FAR call helper function (new in 2.05)
  [ESP+28] dword Pointer to CDECL helper function (new in 3.54)
+ [ESP+32] dword Amount of memory controlled by the Syslinux core (new in 3.74)
 
 This corresponds to the following C prototype, available in the file
 com32/include/com32.h:
