diff options
author | H. Peter Anvin <hpa@linux.intel.com> | 2010-06-21 17:29:51 -0700 |
---|---|---|
committer | H. Peter Anvin <hpa@linux.intel.com> | 2010-06-21 17:29:51 -0700 |
commit | 1d0c49827da98d852d42fadd56b073ad3d3f1faa (patch) | |
tree | f2509cf058e9d7bc3fed323283b16349cc29a162 /utils | |
parent | 7556a891b2f28617f6c95aa271aeaf29883d0981 (diff) | |
download | syslinux-1d0c49827da98d852d42fadd56b073ad3d3f1faa.tar.gz syslinux-1d0c49827da98d852d42fadd56b073ad3d3f1faa.tar.xz syslinux-1d0c49827da98d852d42fadd56b073ad3d3f1faa.zip |
memdiskfind: utility to find an mBFT and output phram parameters
A trivial Linux utility to search for mBFT and output its parameters
in a form which can be used as input to the phram Linux kernel module.
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
Diffstat (limited to 'utils')
-rw-r--r-- | utils/Makefile | 5 | ||||
-rw-r--r-- | utils/memdiskfind.c | 119 |
2 files changed, 123 insertions, 1 deletions
diff --git a/utils/Makefile b/utils/Makefile index 43552d88..455eb828 100644 --- a/utils/Makefile +++ b/utils/Makefile @@ -20,7 +20,7 @@ include $(topdir)/MCONFIG CFLAGS = $(GCCWARN) -Os -fomit-frame-pointer -D_FILE_OFFSET_BITS=64 LDFLAGS = -O2 -s -TARGETS = mkdiskimage isohybrid gethostip +TARGETS = mkdiskimage isohybrid gethostip memdiskfind TARGETS += isohybrid.pl # about to be obsoleted ASIS = keytab-lilo lss16toppm md5pass ppmtolss16 sha1pass syslinux2ansi \ pxelinux-options @@ -52,6 +52,9 @@ isohybrid: isohybrid.o isohdpfx.o gethostip: gethostip.o $(CC) $(LDFLAGS) -o $@ $^ +memdiskfind: memdiskfind.o + $(CC) $(LDFLAGS) -o $@ $^ + tidy dist: rm -f *.o .*.d isohdpfx.c diff --git a/utils/memdiskfind.c b/utils/memdiskfind.c new file mode 100644 index 00000000..331bfb35 --- /dev/null +++ b/utils/memdiskfind.c @@ -0,0 +1,119 @@ +/* ----------------------------------------------------------------------- * + * + * 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); + + 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)); + exit(1); + } + + 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; +} |