diff options
Diffstat (limited to 'contrib/syslinux-4.02/memdisk/e820func.c')
-rw-r--r-- | contrib/syslinux-4.02/memdisk/e820func.c | 107 |
1 files changed, 107 insertions, 0 deletions
diff --git a/contrib/syslinux-4.02/memdisk/e820func.c b/contrib/syslinux-4.02/memdisk/e820func.c new file mode 100644 index 0000000..13c0a6f --- /dev/null +++ b/contrib/syslinux-4.02/memdisk/e820func.c @@ -0,0 +1,107 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2001-2008 H. Peter Anvin - All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, Inc., 53 Temple Place Ste 330, + * Boston MA 02111-1307, USA; either version 2 of the License, or + * (at your option) any later version; incorporated herein by reference. + * + * ----------------------------------------------------------------------- */ + +/* + * e820func.c + * + * E820 range database manager + */ + +#include <stdint.h> +#ifdef TEST +#include <string.h> +#else +#include "memdisk.h" /* For memset() */ +#endif +#include "e820.h" + +#define MAXRANGES 1024 +/* All of memory starts out as one range of "indeterminate" type */ +struct e820range ranges[MAXRANGES]; +int nranges; + +void e820map_init(void) +{ + memset(ranges, 0, sizeof(ranges)); + nranges = 1; + ranges[1].type = -1U; +} + +static void insertrange_at(int where, uint64_t start, uint32_t type) +{ + int i; + + for (i = nranges; i > where; i--) + ranges[i] = ranges[i - 1]; + + ranges[where].start = start; + ranges[where].type = type; + + nranges++; + ranges[nranges].start = 0ULL; + ranges[nranges].type = -1U; +} + +void insertrange(uint64_t start, uint64_t len, uint32_t type) +{ + uint64_t last; + uint32_t oldtype; + int i, j; + + /* Remove this to make len == 0 mean all of memory */ + if (len == 0) + return; /* Nothing to insert */ + + last = start + len - 1; /* May roll over */ + + i = 0; + oldtype = -2U; + while (start > ranges[i].start && ranges[i].type != -1U) { + oldtype = ranges[i].type; + i++; + } + + /* Consider the replacement policy. This current one is "overwrite." */ + + if (start < ranges[i].start || ranges[i].type == -1U) + insertrange_at(i++, start, type); + + while (i == 0 || last > ranges[i].start - 1) { + oldtype = ranges[i].type; + ranges[i].type = type; + i++; + } + + if (last < ranges[i].start - 1) + insertrange_at(i, last + 1, oldtype); + + /* Now the map is correct, but quite possibly not optimal. Scan the + map for ranges which are redundant and remove them. */ + i = j = 1; + oldtype = ranges[0].type; + while (i < nranges) { + if (ranges[i].type == oldtype) { + i++; + } else { + oldtype = ranges[i].type; + if (i != j) + ranges[j] = ranges[i]; + i++; + j++; + } + } + + if (i != j) { + ranges[j] = ranges[i]; /* Termination sentinel copy */ + nranges -= (i - j); + } +} |