summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@linux.intel.com>2010-12-08 20:38:21 (GMT)
committerH. Peter Anvin <hpa@linux.intel.com>2010-12-08 20:38:21 (GMT)
commit9526a8dc64dc3e065e01065be0f295b1431b6ea6 (patch)
treec23240e29cf6069c12673d33b7e9c48c919b8efc
parent678414f3bf4733777a57d083a77289677e6ae35f (diff)
downloadmemhack-9526a8dc64dc3e065e01065be0f295b1431b6ea6.zip
memhack-9526a8dc64dc3e065e01065be0f295b1431b6ea6.tar.gz
memhack-9526a8dc64dc3e065e01065be0f295b1431b6ea6.tar.bz2
memhack-9526a8dc64dc3e065e01065be0f295b1431b6ea6.tar.xz
Make it possible to control the access size for getmem
Some I/O devices don't like arbitrary-sized references like memcpy() does.
-rw-r--r--getmem.c135
-rw-r--r--setmem.c6
2 files changed, 126 insertions, 15 deletions
diff --git a/getmem.c b/getmem.c
index f0bd755..22a06cb 100644
--- a/getmem.c
+++ b/getmem.c
@@ -1,27 +1,109 @@
-#include <stdio.h>
-#include <unistd.h>
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 2005-2010 H. Peter Anvin - All Rights Reserved
+ *
+ * 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., 53 Temple Place Ste 330,
+ * Boston MA 02111-1307, USA; either version 2 of the License, or
+ * (at your option) any later version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
#include <fcntl.h>
+#include <getopt.h>
#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
+#include <sysexits.h>
+#include <unistd.h>
#include <sys/stat.h>
#include <sys/mman.h>
-#include <stdlib.h>
+
+#include "version.h"
+
+struct option long_options[] = {
+ { "help", 0, 0, 'h' },
+ { "version", 0, 0, 'V' },
+ { "quad", 0, 0, 'q' },
+ { "long", 0, 0, 'l' },
+ { "dword", 0, 0, 'd' },
+ { "short", 0, 0, 's' },
+ { "word", 0, 0, 'w' },
+ { "byte", 0, 0, 'b' },
+ { "memcpy", 0, 0, 'm' },
+ { 0, 0, 0, 0 }
+};
+
+const char *program;
+
+void usage(void)
+{
+ fprintf(stderr, "Usage: %s [options] address bytes\n"
+ " --help -h Print this help\n"
+ " --version -V Print current version\n"
+ " --quad -q Read quadwords (qword)\n"
+ " --long -l Read longwords (dword)\n"
+ " --dword -d Read longwords (dword)\n"
+ " --short -s Read shortwords (word)\n"
+ " --word -w Read shortwords (word)\n"
+ " --byte -b Read bytes\n"
+ " --memcpy -m Use memcpy (default)\n"
+ , program);
+}
int main(int argc, char *argv[])
{
uintptr_t start, mapstart, len, maplen;
char *mem, *buffer;
+ volatile char *ptr;
int fd;
+ int c;
+ int size = 0;
- if ( argc != 3 ) {
- fprintf(stderr, "Usage: %s start bytes\n", argv[0]);
- exit(1);
+ program = argv[0];
+
+ while ( (c = getopt_long(argc,argv,"hVqldswbm",long_options,NULL)) != - 1 ) {
+ switch( c ) {
+ case 'h':
+ usage();
+ exit(0);
+ case 'V':
+ fprintf(stderr, "%s: version %s\n", program, VERSION_STRING);
+ exit(0);
+ case 'q':
+ size = 8;
+ break;
+ case 'l':
+ case 'd':
+ size = 4;
+ break;
+ case 'w':
+ case 's':
+ size = 2;
+ break;
+ case 'b':
+ size = 1;
+ break;
+ case 'm':
+ size = 0;
+ break;
+ default:
+ usage();
+ exit(EX_USAGE);
+ }
+ }
+
+ if ( argc-optind != 2 ) {
+ usage();
+ exit(EX_USAGE);
}
fd = open("/dev/mem", O_RDONLY);
if ( fd < 0 ) {
perror("/dev/mem");
- exit(1);
+ exit(EX_OSFILE);
}
start = (uintptr_t)strtoumax(argv[1], NULL, 0);
@@ -30,7 +112,7 @@ int main(int argc, char *argv[])
buffer = malloc(len);
if ( !buffer ) {
perror("malloc");
- exit(1);
+ exit(EX_OSERR);
}
mapstart = start & ~0xffff;
@@ -39,14 +121,43 @@ int main(int argc, char *argv[])
mem = mmap(NULL, maplen, PROT_READ, MAP_SHARED, fd, mapstart);
if ( mem == MAP_FAILED ) {
perror("mmap");
- exit(1);
+ exit(EX_OSERR);
}
- memcpy(buffer, mem+(start-mapstart), len);
+ if (size == 0) {
+ memcpy(buffer, mem+(start-mapstart), len);
+ } else {
+ ptr = mem;
+
+ while (len) {
+ static const int next_lower_power_of_2[8] =
+ { 0, 1, 2, 2, 4, 4, 4, 4 };
+
+ if (len < size)
+ size = next_lower_power_of_2[len];
+
+ switch (size) {
+ case 1:
+ *(uint8_t *)buffer = *(volatile uint8_t *)ptr;
+ break;
+ case 2:
+ *(uint16_t *)buffer = *(volatile uint16_t *)ptr;
+ break;
+ case 4:
+ *(uint32_t *)buffer = *(volatile uint32_t *)ptr;
+ break;
+ case 8:
+ *(uint64_t *)buffer = *(volatile uint64_t *)ptr;
+ break;
+ default:
+ abort();
+ }
+ buffer += size;
+ len -= size;
+ }
+ }
fwrite(buffer, len, 1, stdout);
return 0;
}
-
-
diff --git a/setmem.c b/setmem.c
index b44a015..261ba98 100644
--- a/setmem.c
+++ b/setmem.c
@@ -1,4 +1,3 @@
-#ident "$Id$"
/* ----------------------------------------------------------------------- *
*
* Copyright 2005 H. Peter Anvin - All Rights Reserved
@@ -24,6 +23,7 @@
#include <stdlib.h>
#include <getopt.h>
#include <inttypes.h>
+#include <sysexits.h>
#include <sys/types.h>
#include <sys/mman.h>
@@ -107,7 +107,7 @@ int main(int argc, char *argv[])
fd = open("/dev/mem", O_RDWR);
if ( fd < 0 ) {
perror("setmem:/dev/mem");
- exit(1);
+ exit(EX_OSFILE);
}
page_mask = ~((uintptr_t)getpagesize()-1);
@@ -117,7 +117,7 @@ int main(int argc, char *argv[])
map = mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_SHARED, fd, start);
if ( map == MAP_FAILED ) {
perror("setmem:mmap");
- exit(1);
+ exit(EX_OSERR);
}
ptr = (char *)map + (reg & ~page_mask);