diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2008-10-26 17:26:55 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2008-10-26 17:26:55 +0000 |
commit | 043246560fcd5bb7bfb2caa2db270c3c0e8e06f4 (patch) | |
tree | 709f6baf5b3859310c3208fea502bcc10ca3e083 | |
parent | e1ef89abada09b96fb79b167c5d60db718f9429e (diff) | |
download | busybox-w32-043246560fcd5bb7bfb2caa2db270c3c0e8e06f4.tar.gz busybox-w32-043246560fcd5bb7bfb2caa2db270c3c0e8e06f4.tar.bz2 busybox-w32-043246560fcd5bb7bfb2caa2db270c3c0e8e06f4.zip |
devmem: make it more script-friendly; don't do any reads
and output nothing if writing was requested. -100 bytes
-rw-r--r-- | miscutils/devmem.c | 79 |
1 files changed, 42 insertions, 37 deletions
diff --git a/miscutils/devmem.c b/miscutils/devmem.c index 8b8edbe7c..4903b5dcb 100644 --- a/miscutils/devmem.c +++ b/miscutils/devmem.c | |||
@@ -6,9 +6,6 @@ | |||
6 | 6 | ||
7 | #include "libbb.h" | 7 | #include "libbb.h" |
8 | 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; | 9 | int devmem_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
13 | int devmem_main(int argc UNUSED_PARAM, char **argv) | 10 | int devmem_main(int argc UNUSED_PARAM, char **argv) |
14 | { | 11 | { |
@@ -16,10 +13,16 @@ int devmem_main(int argc UNUSED_PARAM, char **argv) | |||
16 | uint64_t read_result; | 13 | uint64_t read_result; |
17 | uint64_t writeval = writeval; /* for compiler */ | 14 | uint64_t writeval = writeval; /* for compiler */ |
18 | off_t target; | 15 | off_t target; |
16 | unsigned page_size = getpagesize(); | ||
19 | int fd; | 17 | int fd; |
20 | int width = 8 * sizeof(int); | 18 | int width = 8 * sizeof(int); |
21 | 19 | ||
22 | /* devmem ADDRESS [WIDTH [VALUE]] */ | 20 | /* devmem ADDRESS [WIDTH [VALUE]] */ |
21 | // TODO: options? | ||
22 | // -r: read and output only the value in hex, with 0x prefix | ||
23 | // -w: write only, no reads before or after, and no output | ||
24 | // or make this behavior default? | ||
25 | // Let's try this and see how users react. | ||
23 | 26 | ||
24 | /* ADDRESS */ | 27 | /* ADDRESS */ |
25 | if (!argv[1]) | 28 | if (!argv[1]) |
@@ -54,67 +57,69 @@ int devmem_main(int argc UNUSED_PARAM, char **argv) | |||
54 | bb_show_usage(); /* bb_strtouXX failed */ | 57 | bb_show_usage(); /* bb_strtouXX failed */ |
55 | 58 | ||
56 | fd = xopen("/dev/mem", argv[3] ? (O_RDWR | O_SYNC) : (O_RDONLY | O_SYNC)); | 59 | fd = xopen("/dev/mem", argv[3] ? (O_RDWR | O_SYNC) : (O_RDONLY | O_SYNC)); |
57 | |||
58 | map_base = mmap(NULL, | 60 | map_base = mmap(NULL, |
59 | DEVMEM_MAP_SIZE * 2 /* in case value spans page */, | 61 | page_size * 2 /* in case value spans page */, |
60 | argv[3] ? (PROT_READ | PROT_WRITE) : PROT_READ, | 62 | argv[3] ? (PROT_READ | PROT_WRITE) : PROT_READ, |
61 | MAP_SHARED, | 63 | MAP_SHARED, |
62 | fd, | 64 | fd, |
63 | target & ~DEVMEM_MAP_MASK); | 65 | target & ~(off_t)(page_size - 1)); |
64 | if (map_base == MAP_FAILED) | 66 | if (map_base == MAP_FAILED) |
65 | bb_perror_msg_and_die("mmap"); | 67 | bb_perror_msg_and_die("mmap"); |
66 | 68 | ||
67 | // printf("Memory mapped at address %p.\n", map_base); | 69 | // printf("Memory mapped at address %p.\n", map_base); |
68 | 70 | ||
69 | virt_addr = (char*)map_base + (target & DEVMEM_MAP_MASK); | 71 | virt_addr = (char*)map_base + (target & (page_size - 1)); |
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 | 72 | ||
92 | if (argv[3]) { | 73 | if (!argv[3]) { |
93 | switch (width) { | 74 | switch (width) { |
94 | case 8: | 75 | case 8: |
95 | *(volatile uint8_t*)virt_addr = writeval; | ||
96 | read_result = *(volatile uint8_t*)virt_addr; | 76 | read_result = *(volatile uint8_t*)virt_addr; |
97 | break; | 77 | break; |
98 | case 16: | 78 | case 16: |
99 | *(volatile uint16_t*)virt_addr = writeval; | ||
100 | read_result = *(volatile uint16_t*)virt_addr; | 79 | read_result = *(volatile uint16_t*)virt_addr; |
101 | break; | 80 | break; |
102 | case 32: | 81 | case 32: |
103 | *(volatile uint32_t*)virt_addr = writeval; | ||
104 | read_result = *(volatile uint32_t*)virt_addr; | 82 | read_result = *(volatile uint32_t*)virt_addr; |
105 | break; | 83 | break; |
106 | case 64: | 84 | case 64: |
107 | *(volatile uint64_t*)virt_addr = writeval; | ||
108 | read_result = *(volatile uint64_t*)virt_addr; | 85 | read_result = *(volatile uint64_t*)virt_addr; |
109 | break; | 86 | break; |
87 | default: | ||
88 | bb_error_msg_and_die("bad width"); | ||
89 | } | ||
90 | // printf("Value at address 0x%"OFF_FMT"X (%p): 0x%llX\n", | ||
91 | // target, virt_addr, | ||
92 | // (unsigned long long)read_result); | ||
93 | /* Zero-padded output shows the width of access just done */ | ||
94 | printf("0x%0*llX\n", (width >> 2), (unsigned long long)read_result); | ||
95 | } else { | ||
96 | switch (width) { | ||
97 | case 8: | ||
98 | *(volatile uint8_t*)virt_addr = writeval; | ||
99 | // read_result = *(volatile uint8_t*)virt_addr; | ||
100 | break; | ||
101 | case 16: | ||
102 | *(volatile uint16_t*)virt_addr = writeval; | ||
103 | // read_result = *(volatile uint16_t*)virt_addr; | ||
104 | break; | ||
105 | case 32: | ||
106 | *(volatile uint32_t*)virt_addr = writeval; | ||
107 | // read_result = *(volatile uint32_t*)virt_addr; | ||
108 | break; | ||
109 | case 64: | ||
110 | *(volatile uint64_t*)virt_addr = writeval; | ||
111 | // read_result = *(volatile uint64_t*)virt_addr; | ||
112 | break; | ||
113 | default: | ||
114 | bb_error_msg_and_die("bad width"); | ||
110 | } | 115 | } |
111 | printf("Written 0x%llX; readback 0x%llX\n", | 116 | // printf("Written 0x%llX; readback 0x%llX\n", |
112 | (unsigned long long)writeval, | 117 | // (unsigned long long)writeval, |
113 | (unsigned long long)read_result); | 118 | // (unsigned long long)read_result); |
114 | } | 119 | } |
115 | 120 | ||
116 | if (ENABLE_FEATURE_CLEAN_UP) { | 121 | if (ENABLE_FEATURE_CLEAN_UP) { |
117 | if (munmap(map_base, DEVMEM_MAP_SIZE) == -1) | 122 | if (munmap(map_base, page_size) == -1) |
118 | bb_perror_msg_and_die("munmap"); | 123 | bb_perror_msg_and_die("munmap"); |
119 | close(fd); | 124 | close(fd); |
120 | } | 125 | } |