summaryrefslogtreecommitdiff
path: root/com32/lib/syslinux/zonelist.c
diff options
context:
space:
mode:
Diffstat (limited to 'com32/lib/syslinux/zonelist.c')
-rw-r--r--com32/lib/syslinux/zonelist.c63
1 files changed, 63 insertions, 0 deletions
diff --git a/com32/lib/syslinux/zonelist.c b/com32/lib/syslinux/zonelist.c
index d1510d2f..7cd83642 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;
+}