1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
|
/* ----------------------------------------------------------------------- *
*
* Copyright 2010 Intel Corporation; author: H. Peter Anvin
*
* 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., 51 Franklin St, Fifth Floor,
* Boston MA 02110-1301, USA; either version 2 of the License, or
* (at your option) any later version; incorporated herein by reference.
*
* ----------------------------------------------------------------------- */
/*
* memdiskfind.c
*
* Simple utility to search for a MEMDISK instance and output the parameters
* needed to use the "phram" driver in Linux to map it.
*/
#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include "../memdisk/mstructs.h"
#define MBFT_MIN_LENGTH (36+4+26)
static bool valid_mbft(const struct mBFT *mbft, size_t space)
{
uint8_t csum;
size_t i;
if (memcmp(mbft->acpi.signature, "mBFT", 4))
return false;
if (mbft->acpi.length < MBFT_MIN_LENGTH)
return false;
if (mbft->acpi.length > space)
return false;
if ((size_t)mbft->acpi.length != (size_t)mbft->mdi.bytes + 36+4)
return false;
csum = 0;
for (i = 0; i < mbft->acpi.length; i++)
csum += ((const uint8_t *)mbft)[i];
if (csum)
return false;
return true;
}
static void output_params(const struct mBFT *mbft)
{
printf("%u,%u\n", mbft->mdi.diskbuf, mbft->mdi.disksize);
}
int main(int argc, char *argv[])
{
const char *map;
int memfd;
uint16_t fbm;
const char *ptr, *end;
size_t page = sysconf(_SC_PAGESIZE);
size_t mapbase, maplen;
int err = 1;
(void)argc;
memfd = open("/dev/mem", O_RDONLY);
if (memfd < 0) {
fprintf(stderr, "%s: cannot open /dev/mem: %s\n",
argv[0], strerror(errno));
return 2;
}
map = mmap(NULL, page, PROT_READ, MAP_SHARED, memfd, 0);
if (map == MAP_FAILED) {
fprintf(stderr, "%s: cannot map page 0: %s\n",
argv[0], strerror(errno));
return 2;
}
fbm = *(uint16_t *)(map + 0x413);
munmap((void *)map, 4096);
if (fbm < 64 || fbm >= 640)
return 1;
mapbase = (fbm << 10) & ~(page - 1);
maplen = 0xa0000 - mapbase;
map = mmap(NULL, maplen, PROT_READ, MAP_SHARED, memfd, mapbase);
if (map == MAP_FAILED) {
fprintf(stderr, "%s: cannot map base memory: %s\n",
argv[0], strerror(errno));
return 2;
}
ptr = map + ((fbm << 10) & (page - 1));
end = map + (0xa0000 - mapbase);
while (ptr < end) {
if (valid_mbft((const struct mBFT *)ptr, end-ptr)) {
output_params((const struct mBFT *)ptr);
err = 0;
break;
}
ptr += 16;
}
munmap((void *)map, maplen);
return err;
}
|