Add memtest support.
[syslinux-debian/hramrach.git] / utils / memdiskfind.c
blob815f8bc1c1b1aad6cdb52ef1dd400983fe2a8ee0
1 /* ----------------------------------------------------------------------- *
3 * Copyright 2010 Intel Corporation; author: H. Peter Anvin
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
8 * Boston MA 02110-1301, USA; either version 2 of the License, or
9 * (at your option) any later version; incorporated herein by reference.
11 * ----------------------------------------------------------------------- */
14 * memdiskfind.c
16 * Simple utility to search for a MEMDISK instance and output the parameters
17 * needed to use the "phram" driver in Linux to map it.
20 #include <errno.h>
21 #include <fcntl.h>
22 #include <inttypes.h>
23 #include <stdbool.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <unistd.h>
28 #include <sys/mman.h>
29 #include <sys/stat.h>
30 #include "../memdisk/mstructs.h"
32 #define MBFT_MIN_LENGTH (36+4+26)
34 static bool valid_mbft(const struct mBFT *mbft, size_t space)
36 uint8_t csum;
37 size_t i;
39 if (memcmp(mbft->acpi.signature, "mBFT", 4))
40 return false;
42 if (mbft->acpi.length < MBFT_MIN_LENGTH)
43 return false;
45 if (mbft->acpi.length > space)
46 return false;
48 if ((size_t)mbft->acpi.length != (size_t)mbft->mdi.bytes + 36+4)
49 return false;
51 csum = 0;
52 for (i = 0; i < mbft->acpi.length; i++)
53 csum += ((const uint8_t *)mbft)[i];
55 if (csum)
56 return false;
58 return true;
61 static void output_params(const struct mBFT *mbft)
63 int sector_shift = mbft->mdi.sector_shift;
65 if (!sector_shift)
66 sector_shift = 9;
68 printf("%#x,%#x\n",
69 mbft->mdi.diskbuf, mbft->mdi.disksize << sector_shift);
72 static size_t memlimit(void)
74 char txtline[256], user[256];
75 size_t maxram = 0;
76 unsigned long long start, end;
77 FILE *iomem;
79 iomem = fopen("/proc/iomem", "r");
80 if (!iomem)
81 return 0;
83 while (fgets(txtline, sizeof txtline, iomem) != NULL) {
84 if (sscanf(txtline, "%llx-%llx : %[^\n]", &start, &end, user) != 3)
85 continue;
86 if (strcmp(user, "System RAM"))
87 continue;
88 if (start >= 0xa0000)
89 continue;
90 maxram = (end >= 0xa0000) ? 0xa0000 : end+1;
92 fclose(iomem);
94 return maxram;
97 static inline size_t get_page_size(void)
99 #ifdef _SC_PAGESIZE
100 return sysconf(_SC_PAGESIZE);
101 #else
102 /* klibc, for one, doesn't have sysconf() due to excessive multiplex */
103 return getpagesize();
104 #endif
107 int main(int argc, char *argv[])
109 const char *map;
110 int memfd;
111 size_t fbm;
112 const char *ptr, *end;
113 size_t page = get_page_size();
114 size_t mapbase, maplen;
115 int err = 1;
117 (void)argc;
119 mapbase = memlimit() & ~(page - 1);
120 if (!mapbase)
121 return 2;
123 memfd = open("/dev/mem", O_RDONLY);
124 if (memfd < 0) {
125 fprintf(stderr, "%s: cannot open /dev/mem: %s\n",
126 argv[0], strerror(errno));
127 return 2;
130 map = mmap(NULL, page, PROT_READ, MAP_SHARED, memfd, 0);
131 if (map == MAP_FAILED) {
132 fprintf(stderr, "%s: cannot map page 0: %s\n",
133 argv[0], strerror(errno));
134 return 2;
137 fbm = *(uint16_t *)(map + 0x413) << 10;
138 if (fbm < mapbase)
139 fbm = mapbase;
141 munmap((void *)map, page);
143 if (fbm < 64*1024 || fbm >= 640*1024)
144 return 1;
146 maplen = 0xa0000 - mapbase;
147 map = mmap(NULL, maplen, PROT_READ, MAP_SHARED, memfd, mapbase);
148 if (map == MAP_FAILED) {
149 fprintf(stderr, "%s: cannot map base memory: %s\n",
150 argv[0], strerror(errno));
151 return 2;
154 ptr = map + (fbm - mapbase);
155 end = map + (0xa0000 - mapbase);
156 while (ptr < end) {
157 if (valid_mbft((const struct mBFT *)ptr, end-ptr)) {
158 output_params((const struct mBFT *)ptr);
159 err = 0;
160 break;
162 ptr += 16;
165 munmap((void *)map, maplen);
167 return err;