aboutsummaryrefslogtreecommitdiffstats
path: root/utils
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2010-06-22 23:19:40 -0700
committerH. Peter Anvin <hpa@zytor.com>2010-06-22 23:19:40 -0700
commit21444299d4086ade6c6bb33c0ce96edf441c2c6e (patch)
treec8a11bc18c790b73f3dd7972032c45404d054f61 /utils
parent134e5f60f81f3372407a771898c381afe394abbf (diff)
downloadsyslinux-21444299d4086ade6c6bb33c0ce96edf441c2c6e.tar.gz
syslinux-21444299d4086ade6c6bb33c0ce96edf441c2c6e.tar.xz
syslinux-21444299d4086ade6c6bb33c0ce96edf441c2c6e.zip
memdiskfind: make sure we don't map unavailable RAM
Sometimes FBM is below the reserved memory limit, which means memory that is available to protected-mode operating systems only and which will be claimed by the kernel and therefore be unmappable. Read /proc/iomem to make sure the memory range is safe to map. Signed-off-by: H. Peter Anvin <hpa@zytor.com>
Diffstat (limited to 'utils')
-rw-r--r--utils/memdiskfind.c44
1 files changed, 38 insertions, 6 deletions
diff --git a/utils/memdiskfind.c b/utils/memdiskfind.c
index f2086b23..25285714 100644
--- a/utils/memdiskfind.c
+++ b/utils/memdiskfind.c
@@ -69,11 +69,36 @@ static void output_params(const struct mBFT *mbft)
mbft->mdi.diskbuf, mbft->mdi.disksize << sector_shift);
}
+static size_t memlimit(void)
+{
+ char txtline[256], user[256];
+ size_t maxram = 0;
+ unsigned long long start, end;
+ FILE *iomem;
+
+ iomem = fopen("/proc/iomem", "r");
+ if (!iomem)
+ return 0;
+
+ while (fgets(txtline, sizeof txtline, iomem) != NULL) {
+ if (sscanf(txtline, "%llx-%llx : %[^\n]", &start, &end, user) != 3)
+ continue;
+ if (strcmp(user, "System RAM"))
+ continue;
+ if (start >= 0xa0000)
+ continue;
+ maxram = (end >= 0xa0000) ? 0xa0000 : end+1;
+ }
+ fclose(iomem);
+
+ return maxram;
+}
+
int main(int argc, char *argv[])
{
const char *map;
int memfd;
- uint16_t fbm;
+ size_t fbm;
const char *ptr, *end;
size_t page = sysconf(_SC_PAGESIZE);
size_t mapbase, maplen;
@@ -81,6 +106,12 @@ int main(int argc, char *argv[])
(void)argc;
+ mapbase = memlimit() & ~(page - 1);
+ if (!mapbase)
+ return 2;
+
+ printf("mapbase = %#zx\n", mapbase);
+
memfd = open("/dev/mem", O_RDONLY);
if (memfd < 0) {
fprintf(stderr, "%s: cannot open /dev/mem: %s\n",
@@ -95,14 +126,15 @@ int main(int argc, char *argv[])
return 2;
}
- fbm = *(uint16_t *)(map + 0x413);
+ fbm = *(uint16_t *)(map + 0x413) << 10;
+ if (fbm < mapbase)
+ fbm = mapbase;
- munmap((void *)map, 4096);
+ munmap((void *)map, page);
- if (fbm < 64 || fbm >= 640)
+ if (fbm < 64*1024 || fbm >= 640*1024)
return 1;
- mapbase = (fbm << 10) & ~(page - 1);
maplen = 0xa0000 - mapbase;
map = mmap(NULL, maplen, PROT_READ, MAP_SHARED, memfd, mapbase);
if (map == MAP_FAILED) {
@@ -111,7 +143,7 @@ int main(int argc, char *argv[])
return 2;
}
- ptr = map + ((fbm << 10) & (page - 1));
+ ptr = map + (fbm - mapbase);
end = map + (0xa0000 - mapbase);
while (ptr < end) {
if (valid_mbft((const struct mBFT *)ptr, end-ptr)) {