source: bootcd/isolinux/syslinux-6.03/utils/memdiskfind.c @ e16e8f2

Last change on this file since e16e8f2 was e16e8f2, checked in by Edwin Eefting <edwin@datux.nl>, 3 years ago

bootstuff

  • Property mode set to 100644
File size: 3.7 KB
Line 
1/* ----------------------------------------------------------------------- *
2 *
3 *   Copyright 2010 Intel Corporation; author: H. Peter Anvin
4 *
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.
10 *
11 * ----------------------------------------------------------------------- */
12
13/*
14 * memdiskfind.c
15 *
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.
18 */
19
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"
31
32#define MBFT_MIN_LENGTH (36+4+26)
33
34static bool valid_mbft(const struct mBFT *mbft, size_t space)
35{
36    uint8_t csum;
37    size_t i;
38
39    if (memcmp(mbft->acpi.signature, "mBFT", 4))
40        return false;
41
42    if (mbft->acpi.length < MBFT_MIN_LENGTH)
43        return false;
44
45    if (mbft->acpi.length > space)
46        return false;
47
48    if ((size_t)mbft->acpi.length != (size_t)mbft->mdi.bytes + 36+4)
49        return false;
50
51    csum = 0;
52    for (i = 0; i < mbft->acpi.length; i++)
53        csum += ((const uint8_t *)mbft)[i];
54
55    if (csum)
56        return false;
57
58    return true;
59}
60
61static void output_params(const struct mBFT *mbft)
62{
63    int sector_shift = mbft->mdi.sector_shift;
64
65    if (!sector_shift)
66        sector_shift = 9;
67
68    printf("%#x,%#x\n",
69           mbft->mdi.diskbuf, mbft->mdi.disksize << sector_shift);
70}
71
72static size_t memlimit(void)
73{
74    char txtline[256], user[256];
75    size_t maxram = 0;
76    unsigned long long start, end;
77    FILE *iomem;
78
79    iomem = fopen("/proc/iomem", "r");
80    if (!iomem)
81        return 0;
82
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;
91    }
92    fclose(iomem);
93
94    return maxram;
95}
96
97static inline size_t get_page_size(void)
98{
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
105}
106
107int main(int argc, char *argv[])
108{
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;
116
117    (void)argc;
118
119    mapbase = memlimit() & ~(page - 1);
120    if (!mapbase)
121        return 2;
122
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;
128    }
129
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;
135    }
136
137    fbm = *(uint16_t *)(map + 0x413) << 10;
138    if (fbm < mapbase)
139        fbm = mapbase;
140
141    munmap((void *)map, page);
142
143    if (fbm < 64*1024 || fbm >= 640*1024)
144        return 1;
145
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;
152    }
153
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;
161        }
162        ptr += 16;
163    }
164
165    munmap((void *)map, maplen);
166
167    return err;
168}
Note: See TracBrowser for help on using the repository browser.