[syslinux:firmware] movebits: Add syslinux_memmap_find()

syslinux-bot for Matt Fleming matt.fleming at intel.com
Thu Jul 18 05:00:07 PDT 2013


Commit-ID:  8f470e7bfe75f6401f6c5432988c620b863ad274
Gitweb:     http://www.syslinux.org/commit/8f470e7bfe75f6401f6c5432988c620b863ad274
Author:     Matt Fleming <matt.fleming at intel.com>
AuthorDate: Tue, 16 Jul 2013 15:15:54 +0100
Committer:  Matt Fleming <matt.fleming at intel.com>
CommitDate: Wed, 17 Jul 2013 18:29:16 +0100

movebits: Add syslinux_memmap_find()

Refactor the code for finding a suitable location for kernel
protected-mode and real-mode data. It's complicated enough that it
deserves to be separated into its own function.

Signed-off-by: Matt Fleming <matt.fleming at intel.com>

---
 com32/include/syslinux/movebits.h |  6 +++
 com32/lib/syslinux/load_linux.c   | 89 +++++++--------------------------------
 com32/lib/syslinux/zonelist.c     | 63 +++++++++++++++++++++++++++
 3 files changed, 84 insertions(+), 74 deletions(-)

diff --git a/com32/include/syslinux/movebits.h b/com32/include/syslinux/movebits.h
index 5023acc..feeab3a 100644
--- a/com32/include/syslinux/movebits.h
+++ b/com32/include/syslinux/movebits.h
@@ -3,6 +3,7 @@
 
 #include <inttypes.h>
 #include <stdio.h>
+#include <stdbool.h>
 
 typedef uint32_t addr_t;
 
@@ -81,6 +82,11 @@ struct syslinux_memmap *syslinux_dup_memmap(struct syslinux_memmap *list);
 int syslinux_memmap_find_type(struct syslinux_memmap *list,
 			      enum syslinux_memmap_types type,
 			      addr_t * start, addr_t * len, addr_t align);
+int syslinux_memmap_find(struct syslinux_memmap *mmap,
+			 addr_t *base, size_t size,
+			 bool relocate, size_t align,
+			 addr_t start_min, addr_t start_max,
+			 addr_t end_min, addr_t end_max);
 
 /* Debugging functions */
 #ifdef DEBUG
diff --git a/com32/lib/syslinux/load_linux.c b/com32/lib/syslinux/load_linux.c
index 6a0afd3..3e659c1 100644
--- a/com32/lib/syslinux/load_linux.c
+++ b/com32/lib/syslinux/load_linux.c
@@ -130,7 +130,7 @@ int bios_boot_linux(void *kernel_buf, size_t kernel_size,
 		    char *cmdline)
 {
     struct linux_header hdr, *whdr;
-    size_t real_mode_size, prot_mode_size;
+    size_t real_mode_size, prot_mode_size, base;
     addr_t real_mode_base, prot_mode_base;
     addr_t irf_size;
     size_t cmdline_size, cmdline_offset;
@@ -139,7 +139,6 @@ int bios_boot_linux(void *kernel_buf, size_t kernel_size,
     struct syslinux_movelist *fraglist = NULL;
     struct syslinux_memmap *mmap = NULL;
     struct syslinux_memmap *amap = NULL;
-    bool ok;
     uint32_t memlimit = 0;
     uint16_t video_mode = 0;
     const char *arg;
@@ -279,82 +278,24 @@ int bios_boot_linux(void *kernel_buf, size_t kernel_size,
     /* Place the kernel in memory */
 
     /* First, find a suitable place for the protected-mode code */
+    base = prot_mode_base;
     if (prot_mode_size &&
-	syslinux_memmap_type(amap, prot_mode_base, prot_mode_size)
-	!= SMT_FREE) {
-	const struct syslinux_memmap *mp;
-	if (!hdr.relocatable_kernel) {
-	    dprintf("Cannot relocate kernel\n");
-	    goto bail;
-	}
-
-	ok = false;
-	for (mp = amap; mp; mp = mp->next) {
-	    addr_t start, end;
-	    start = mp->start;
-	    end = mp->next->start;
-
-	    if (mp->type != SMT_FREE)
-		continue;
-
-	    if (end <= prot_mode_base)
-		continue;	/* Only relocate upwards */
-
-	    if (start <= prot_mode_base)
-		start = prot_mode_base;
-
-	    start = ALIGN_UP(start, hdr.kernel_alignment);
-	    if (start >= end)
-		continue;
-
-	    if (end - start >= hdr.init_size) {
-		whdr->code32_start += start - prot_mode_base;
-		prot_mode_base = start;
-		ok = true;
-		break;
-	    }
-	}
-
-	if (!ok) {
-	    dprintf("Could not find location for protected-mode code\n");
-	    goto bail;
-	}
+	syslinux_memmap_find(amap, &base, hdr.init_size,
+			     hdr.relocatable_kernel, hdr.kernel_alignment,
+			     prot_mode_base, (addr_t)-1,
+			     prot_mode_base, (addr_t)-1)) {
+	dprintf("Could not find location for protected-mode code\n");
+	goto bail;
     }
 
-    /* Real mode code */
-    if (syslinux_memmap_type(amap, real_mode_base,
-			     cmdline_offset + cmdline_size) != SMT_FREE) {
-	const struct syslinux_memmap *mp;
-
-	ok = false;
-	for (mp = amap; mp; mp = mp->next) {
-	    addr_t start, end;
-	    start = mp->start;
-	    end = mp->next->start;
-
-	    if (mp->type != SMT_FREE)
-		continue;
-
-	    if (start < real_mode_base)
-		start = real_mode_base;	/* Lowest address we'll use */
-	    if (end > 640 * 1024)
-		end = 640 * 1024;
-
-	    start = ALIGN_UP(start, 16);
-	    if (start > 0x90000 || start >= end)
-		continue;
+    whdr->code32_start += base - prot_mode_base;
 
-	    if (end - start >= cmdline_offset + cmdline_size) {
-		real_mode_base = start;
-		ok = true;
-		break;
-	    }
-	}
-
-	if (!ok) {
-	    dprintf("Could not find location for real-mode code\n");
-	    goto bail;
-	}
+    /* Real mode code */
+    if (syslinux_memmap_find(amap, &real_mode_base,
+			     cmdline_offset + cmdline_size, true, 16,
+			     real_mode_base, 0x90000, 0, 640*1024)) {
+	dprintf("Could not find location for real-mode code\n");
+	goto bail;
     }
 
     if (syslinux_add_movelist(&fraglist, real_mode_base, (addr_t) kernel_buf,
diff --git a/com32/lib/syslinux/zonelist.c b/com32/lib/syslinux/zonelist.c
index d1510d2..7cd8364 100644
--- a/com32/lib/syslinux/zonelist.c
+++ b/com32/lib/syslinux/zonelist.c
@@ -281,3 +281,66 @@ struct syslinux_memmap *syslinux_dup_memmap(struct syslinux_memmap *list)
 
     return newlist;
 }
+
+/*
+ * Find a memory region, given a set of heuristics and update 'base' if
+ * successful.
+ */
+int syslinux_memmap_find(struct syslinux_memmap *mmap,
+			 addr_t *base, size_t size,
+			 bool relocate, size_t align,
+			 addr_t start_min, addr_t start_max,
+			 addr_t end_min, addr_t end_max)
+{
+    const struct syslinux_memmap *mp;
+    enum syslinux_memmap_types type;
+    bool ok;
+
+    if (!size)
+	return 0;
+
+    type = syslinux_memmap_type(mmap, *base, size);
+    if (type == SMT_FREE)
+	return 0;
+
+    if (!relocate) {
+	dprintf("Cannot relocate\n");
+	return -1;
+    }
+
+    ok = false;
+    for (mp = mmap; mp && mp->type != SMT_END; mp = mp->next) {
+	addr_t start, end;
+	start = mp->start;
+	end = mp->next->start;
+
+	if (mp->type != SMT_FREE)
+	    continue;
+
+	/* min */
+	if (end <= end_min)
+	    continue;	/* Only relocate upwards */
+
+	if (start < start_min)
+	    start = start_min;
+
+	/* max */
+	if (end > end_max)
+	    end = end_max;
+
+	start = ALIGN_UP(start, align);
+	if (start > start_max || start >= end)
+	    continue;
+
+	if (end - start >= size) {
+	    *base = start;
+	    ok = true;
+	    break;
+	}
+    }
+
+    if (!ok)
+	return -1;
+
+    return 0;
+}


More information about the Syslinux-commits mailing list