diff options
| author | Denis Vlasenko <vda.linux@googlemail.com> | 2008-10-26 11:08:14 +0000 |
|---|---|---|
| committer | Denis Vlasenko <vda.linux@googlemail.com> | 2008-10-26 11:08:14 +0000 |
| commit | c94fa5651a6c4f6b526de261e7480ce2c4e34aba (patch) | |
| tree | f75161b60cffcec4acde0387618de3cd7b5cca52 /miscutils | |
| parent | f3dcd3c30aa704a542b50357094d037f976be3ce (diff) | |
| download | busybox-w32-c94fa5651a6c4f6b526de261e7480ce2c4e34aba.tar.gz busybox-w32-c94fa5651a6c4f6b526de261e7480ce2c4e34aba.tar.bz2 busybox-w32-c94fa5651a6c4f6b526de261e7480ce2c4e34aba.zip | |
devmem: new applet
Diffstat (limited to 'miscutils')
| -rw-r--r-- | miscutils/Config.in | 7 | ||||
| -rw-r--r-- | miscutils/Kbuild | 1 | ||||
| -rw-r--r-- | miscutils/devmem.c | 123 |
3 files changed, 131 insertions, 0 deletions
diff --git a/miscutils/Config.in b/miscutils/Config.in index 074e6c41f..f8b4575e0 100644 --- a/miscutils/Config.in +++ b/miscutils/Config.in | |||
| @@ -196,6 +196,13 @@ config FEATURE_DEVFS | |||
| 196 | /dev/loop0. If your /dev directory has normal names instead of | 196 | /dev/loop0. If your /dev directory has normal names instead of |
| 197 | devfs names, you don't want this. | 197 | devfs names, you don't want this. |
| 198 | 198 | ||
| 199 | config DEVMEM | ||
| 200 | bool "devmem" | ||
| 201 | default n | ||
| 202 | help | ||
| 203 | devmem is a small program that reads and writes from physical | ||
| 204 | memory using /dev/mem. | ||
| 205 | |||
| 199 | config EJECT | 206 | config EJECT |
| 200 | bool "eject" | 207 | bool "eject" |
| 201 | default n | 208 | default n |
diff --git a/miscutils/Kbuild b/miscutils/Kbuild index c12b12d42..13791ef18 100644 --- a/miscutils/Kbuild +++ b/miscutils/Kbuild | |||
| @@ -13,6 +13,7 @@ lib-$(CONFIG_CROND) += crond.o | |||
| 13 | lib-$(CONFIG_CRONTAB) += crontab.o | 13 | lib-$(CONFIG_CRONTAB) += crontab.o |
| 14 | lib-$(CONFIG_DC) += dc.o | 14 | lib-$(CONFIG_DC) += dc.o |
| 15 | lib-$(CONFIG_DEVFSD) += devfsd.o | 15 | lib-$(CONFIG_DEVFSD) += devfsd.o |
| 16 | lib-$(CONFIG_DEVMEM) += devmem.o | ||
| 16 | lib-$(CONFIG_EJECT) += eject.o | 17 | lib-$(CONFIG_EJECT) += eject.o |
| 17 | lib-$(CONFIG_FBSPLASH) += fbsplash.o | 18 | lib-$(CONFIG_FBSPLASH) += fbsplash.o |
| 18 | lib-$(CONFIG_HDPARM) += hdparm.o | 19 | lib-$(CONFIG_HDPARM) += hdparm.o |
diff --git a/miscutils/devmem.c b/miscutils/devmem.c new file mode 100644 index 000000000..8b8edbe7c --- /dev/null +++ b/miscutils/devmem.c | |||
| @@ -0,0 +1,123 @@ | |||
| 1 | /* | ||
| 2 | * Licensed under the GPL v2 or later, see the file LICENSE in this tarball. | ||
| 3 | * Copyright (C) 2000, Jan-Derk Bakker (J.D.Bakker@its.tudelft.nl) | ||
| 4 | * Copyright (C) 2008, BusyBox Team. -solar 4/26/08 | ||
| 5 | */ | ||
| 6 | |||
| 7 | #include "libbb.h" | ||
| 8 | |||
| 9 | #define DEVMEM_MAP_SIZE 4096 | ||
| 10 | #define DEVMEM_MAP_MASK (off_t)(DEVMEM_MAP_SIZE - 1) | ||
| 11 | |||
| 12 | int devmem_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | ||
| 13 | int devmem_main(int argc UNUSED_PARAM, char **argv) | ||
| 14 | { | ||
| 15 | void *map_base, *virt_addr; | ||
| 16 | uint64_t read_result; | ||
| 17 | uint64_t writeval = writeval; /* for compiler */ | ||
| 18 | off_t target; | ||
| 19 | int fd; | ||
| 20 | int width = 8 * sizeof(int); | ||
| 21 | |||
| 22 | /* devmem ADDRESS [WIDTH [VALUE]] */ | ||
| 23 | |||
| 24 | /* ADDRESS */ | ||
| 25 | if (!argv[1]) | ||
| 26 | bb_show_usage(); | ||
| 27 | errno = 0; | ||
| 28 | target = bb_strtoull(argv[1], NULL, 0); /* allows hex, oct etc */ | ||
| 29 | |||
| 30 | /* WIDTH */ | ||
| 31 | if (argv[2]) { | ||
| 32 | if (isdigit(argv[2][0]) || argv[2][1]) | ||
| 33 | width = xatou(argv[2]); | ||
| 34 | else { | ||
| 35 | static const char bhwl[] ALIGN1 = "bhwl"; | ||
| 36 | static const uint8_t sizes[] ALIGN1 = { | ||
| 37 | 8 * sizeof(char), | ||
| 38 | 8 * sizeof(short), | ||
| 39 | 8 * sizeof(int), | ||
| 40 | 8 * sizeof(long), | ||
| 41 | 0 /* bad */ | ||
| 42 | }; | ||
| 43 | width = strchrnul(bhwl, (argv[2][0] | 0x20)) - bhwl; | ||
| 44 | width = sizes[width]; | ||
| 45 | } | ||
| 46 | /* VALUE */ | ||
| 47 | if (argv[3]) | ||
| 48 | writeval = bb_strtoull(argv[3], NULL, 0); | ||
| 49 | } else { /* argv[2] == NULL */ | ||
| 50 | /* make argv[3] to be a valid thing to use */ | ||
| 51 | argv--; | ||
| 52 | } | ||
| 53 | if (errno) | ||
| 54 | bb_show_usage(); /* bb_strtouXX failed */ | ||
| 55 | |||
| 56 | fd = xopen("/dev/mem", argv[3] ? (O_RDWR | O_SYNC) : (O_RDONLY | O_SYNC)); | ||
| 57 | |||
| 58 | map_base = mmap(NULL, | ||
| 59 | DEVMEM_MAP_SIZE * 2 /* in case value spans page */, | ||
| 60 | argv[3] ? (PROT_READ | PROT_WRITE) : PROT_READ, | ||
| 61 | MAP_SHARED, | ||
| 62 | fd, | ||
| 63 | target & ~DEVMEM_MAP_MASK); | ||
| 64 | if (map_base == MAP_FAILED) | ||
| 65 | bb_perror_msg_and_die("mmap"); | ||
| 66 | |||
| 67 | // printf("Memory mapped at address %p.\n", map_base); | ||
| 68 | |||
| 69 | virt_addr = (char*)map_base + (target & DEVMEM_MAP_MASK); | ||
| 70 | |||
| 71 | switch (width) { | ||
| 72 | case 8: | ||
| 73 | read_result = *(volatile uint8_t*)virt_addr; | ||
| 74 | break; | ||
| 75 | case 16: | ||
| 76 | read_result = *(volatile uint16_t*)virt_addr; | ||
| 77 | break; | ||
| 78 | case 32: | ||
| 79 | read_result = *(volatile uint32_t*)virt_addr; | ||
| 80 | break; | ||
| 81 | case 64: | ||
| 82 | read_result = *(volatile uint64_t*)virt_addr; | ||
| 83 | break; | ||
| 84 | default: | ||
| 85 | bb_error_msg_and_die("bad width"); | ||
| 86 | } | ||
| 87 | |||
| 88 | printf("Value at address 0x%"OFF_FMT"X (%p): 0x%llX\n", | ||
| 89 | target, virt_addr, | ||
| 90 | (unsigned long long)read_result); | ||
| 91 | |||
| 92 | if (argv[3]) { | ||
| 93 | switch (width) { | ||
| 94 | case 8: | ||
| 95 | *(volatile uint8_t*)virt_addr = writeval; | ||
| 96 | read_result = *(volatile uint8_t*)virt_addr; | ||
| 97 | break; | ||
| 98 | case 16: | ||
| 99 | *(volatile uint16_t*)virt_addr = writeval; | ||
| 100 | read_result = *(volatile uint16_t*)virt_addr; | ||
| 101 | break; | ||
| 102 | case 32: | ||
| 103 | *(volatile uint32_t*)virt_addr = writeval; | ||
| 104 | read_result = *(volatile uint32_t*)virt_addr; | ||
| 105 | break; | ||
| 106 | case 64: | ||
| 107 | *(volatile uint64_t*)virt_addr = writeval; | ||
| 108 | read_result = *(volatile uint64_t*)virt_addr; | ||
| 109 | break; | ||
| 110 | } | ||
| 111 | printf("Written 0x%llX; readback 0x%llX\n", | ||
| 112 | (unsigned long long)writeval, | ||
| 113 | (unsigned long long)read_result); | ||
| 114 | } | ||
| 115 | |||
| 116 | if (ENABLE_FEATURE_CLEAN_UP) { | ||
| 117 | if (munmap(map_base, DEVMEM_MAP_SIZE) == -1) | ||
| 118 | bb_perror_msg_and_die("munmap"); | ||
| 119 | close(fd); | ||
| 120 | } | ||
| 121 | |||
| 122 | return EXIT_SUCCESS; | ||
| 123 | } | ||
