Add devmem
Change-Id: I024cbb49796f324a798596ad39c9a9691a0676a7
diff --git a/Makefile b/Makefile
index 417e298..8151fd1 100644
--- a/Makefile
+++ b/Makefile
@@ -44,7 +44,8 @@
id \
vmstat \
lsof \
- daemon
+ daemon \
+ devmem
LOCAL_SRC_FILES:= \
toolbox.c \
diff --git a/devmem.c b/devmem.c
new file mode 100644
index 0000000..0771912
--- /dev/null
+++ b/devmem.c
@@ -0,0 +1,121 @@
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+typedef unsigned int uint32;
+typedef unsigned short uint16;
+typedef unsigned char uint8;
+
+int devmem_main(int argc, char *argv[]) {
+
+ if (argc < 2 || argc > 4) {
+ fprintf(stderr, "usage: devmem <addr> [default:32|16|8] [data]\n");
+ return 1;
+ }
+
+ off_t addr;
+ uint32 data = 0;
+ int wordsize = 32;
+
+ addr = strtoul(argv[1], NULL, 0);
+ if (errno) {
+ perror("Invalid address specified");
+ return 1;
+ }
+
+ if (argc > 2) {
+ wordsize = strtol(argv[2], NULL, 0);
+
+ if (errno || (wordsize != 32 && wordsize != 16 && wordsize != 8)) {
+ fprintf(stderr, "Invalid wordsize specified\n");
+ return 1;
+ }
+ }
+
+ if (argc == 4) {
+ data = strtoul(argv[3], NULL, 0);
+ if (errno) {
+ perror("Invalid data specified");
+ return 1;
+ }
+ }
+
+
+ int mem_fd;
+ void *base, *offset;
+ long pagesize;
+
+ pagesize = sysconf(_SC_PAGE_SIZE);
+
+ if (pagesize <= 0) {
+ return 1;
+ }
+
+ mem_fd = open("/dev/mem", O_SYNC | O_RDWR);
+ if (mem_fd < 0) {
+ perror("open /dev/mem failed");
+ return 1;
+ }
+
+ base = mmap(NULL, 2*pagesize, PROT_READ | PROT_WRITE,
+ MAP_SHARED | MAP_FIXED, mem_fd, addr & ~(pagesize-1));
+
+ if (base == MAP_FAILED) {
+ perror("mmap failed");
+ return 1;
+ }
+
+ offset = base + (addr & (pagesize-1));
+
+ switch(wordsize) {
+ case 32:
+ fprintf(stdout, "0x%08x\n", *(uint32*)offset);
+ break;
+
+ case 16:
+ fprintf(stdout, "0x%04x\n", *(uint16*)offset);
+ break;
+
+ case 8:
+ fprintf(stdout, "0x%02x\n", *(uint8*)offset);
+ break;
+ }
+
+ if (argc == 4) {
+ switch(wordsize) {
+ case 32:
+ *(uint32*)offset = (uint32)data;
+ fprintf(stdout, "0x%08x\n", *(uint32*)offset);
+ break;
+
+ case 16:
+ *(uint16*)offset = (uint16)data;
+ fprintf(stdout, "0x%04x\n", *(uint16*)offset);
+ break;
+
+ case 8:
+ *(uint8*)offset = (uint8)data;
+ fprintf(stdout, "0x%02x\n", *(uint8*)offset);
+ break;
+ }
+ }
+
+
+ if (munmap(base, 2*pagesize)) {
+ perror("munmap failed");
+ return 1;
+ }
+
+ if (close(mem_fd)) {
+ perror("cannot close /dev/mem");
+ return 1;
+ }
+
+ return 0;
+}