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 * ----------------------------------------------------------------------- */
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.
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
)
39 if (memcmp(mbft
->acpi
.signature
, "mBFT", 4))
42 if (mbft
->acpi
.length
< MBFT_MIN_LENGTH
)
45 if (mbft
->acpi
.length
> space
)
48 if ((size_t)mbft
->acpi
.length
!= (size_t)mbft
->mdi
.bytes
+ 36+4)
52 for (i
= 0; i
< mbft
->acpi
.length
; i
++)
53 csum
+= ((const uint8_t *)mbft
)[i
];
61 static void output_params(const struct mBFT
*mbft
)
63 int sector_shift
= mbft
->mdi
.sector_shift
;
69 mbft
->mdi
.diskbuf
, mbft
->mdi
.disksize
<< sector_shift
);
72 static size_t memlimit(void)
74 char txtline
[256], user
[256];
76 unsigned long long start
, end
;
79 iomem
= fopen("/proc/iomem", "r");
83 while (fgets(txtline
, sizeof txtline
, iomem
) != NULL
) {
84 if (sscanf(txtline
, "%llx-%llx : %[^\n]", &start
, &end
, user
) != 3)
86 if (strcmp(user
, "System RAM"))
90 maxram
= (end
>= 0xa0000) ? 0xa0000 : end
+1;
97 static inline size_t get_page_size(void)
100 return sysconf(_SC_PAGESIZE
);
102 /* klibc, for one, doesn't have sysconf() due to excessive multiplex */
103 return getpagesize();
107 int main(int argc
, char *argv
[])
112 const char *ptr
, *end
;
113 size_t page
= get_page_size();
114 size_t mapbase
, maplen
;
119 mapbase
= memlimit() & ~(page
- 1);
123 memfd
= open("/dev/mem", O_RDONLY
);
125 fprintf(stderr
, "%s: cannot open /dev/mem: %s\n",
126 argv
[0], strerror(errno
));
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
));
137 fbm
= *(uint16_t *)(map
+ 0x413) << 10;
141 munmap((void *)map
, page
);
143 if (fbm
< 64*1024 || fbm
>= 640*1024)
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
));
154 ptr
= map
+ (fbm
- mapbase
);
155 end
= map
+ (0xa0000 - mapbase
);
157 if (valid_mbft((const struct mBFT
*)ptr
, end
-ptr
)) {
158 output_params((const struct mBFT
*)ptr
);
165 munmap((void *)map
, maplen
);