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 | |
parent | f3dcd3c30aa704a542b50357094d037f976be3ce (diff) | |
download | busybox-w32-c94fa5651a6c4f6b526de261e7480ce2c4e34aba.tar.gz busybox-w32-c94fa5651a6c4f6b526de261e7480ce2c4e34aba.tar.bz2 busybox-w32-c94fa5651a6c4f6b526de261e7480ce2c4e34aba.zip |
devmem: new applet
-rw-r--r-- | include/applets.h | 1 | ||||
-rw-r--r-- | include/usage.h | 9 | ||||
-rw-r--r-- | miscutils/Config.in | 7 | ||||
-rw-r--r-- | miscutils/Kbuild | 1 | ||||
-rw-r--r-- | miscutils/devmem.c | 123 |
5 files changed, 141 insertions, 0 deletions
diff --git a/include/applets.h b/include/applets.h index e3f929440..d52f9f034 100644 --- a/include/applets.h +++ b/include/applets.h | |||
@@ -119,6 +119,7 @@ USE_DELUSER(APPLET(deluser, _BB_DIR_BIN, _BB_SUID_NEVER)) | |||
119 | USE_DEPMOD(APPLET(depmod, _BB_DIR_SBIN, _BB_SUID_NEVER)) | 119 | USE_DEPMOD(APPLET(depmod, _BB_DIR_SBIN, _BB_SUID_NEVER)) |
120 | USE_MODPROBE_SMALL(APPLET_ODDNAME(depmod, modprobe, _BB_DIR_SBIN, _BB_SUID_NEVER, modprobe)) | 120 | USE_MODPROBE_SMALL(APPLET_ODDNAME(depmod, modprobe, _BB_DIR_SBIN, _BB_SUID_NEVER, modprobe)) |
121 | USE_DEVFSD(APPLET(devfsd, _BB_DIR_SBIN, _BB_SUID_NEVER)) | 121 | USE_DEVFSD(APPLET(devfsd, _BB_DIR_SBIN, _BB_SUID_NEVER)) |
122 | USE_DEVMEM(APPLET(devmem, _BB_DIR_SBIN, _BB_SUID_NEVER)) | ||
122 | USE_DF(APPLET(df, _BB_DIR_BIN, _BB_SUID_NEVER)) | 123 | USE_DF(APPLET(df, _BB_DIR_BIN, _BB_SUID_NEVER)) |
123 | USE_APP_DHCPRELAY(APPLET(dhcprelay, _BB_DIR_USR_SBIN, _BB_SUID_NEVER)) | 124 | USE_APP_DHCPRELAY(APPLET(dhcprelay, _BB_DIR_USR_SBIN, _BB_SUID_NEVER)) |
124 | USE_DIFF(APPLET(diff, _BB_DIR_USR_BIN, _BB_SUID_NEVER)) | 125 | USE_DIFF(APPLET(diff, _BB_DIR_USR_BIN, _BB_SUID_NEVER)) |
diff --git a/include/usage.h b/include/usage.h index 3c110132e..dbef9f6f5 100644 --- a/include/usage.h +++ b/include/usage.h | |||
@@ -690,6 +690,15 @@ | |||
690 | #define depmod_trivial_usage NOUSAGE_STR | 690 | #define depmod_trivial_usage NOUSAGE_STR |
691 | #define depmod_full_usage "" | 691 | #define depmod_full_usage "" |
692 | 692 | ||
693 | #define devmem_trivial_usage \ | ||
694 | "ADDRESS [WIDTH [VALUE]]" | ||
695 | |||
696 | #define devmem_full_usage "\n\n" \ | ||
697 | "Read/write from physical address\n" \ | ||
698 | "\n ADDRESS Address to act upon" \ | ||
699 | "\n WIDTH Width (8/16/...)" \ | ||
700 | "\n VALUE Data to be written" \ | ||
701 | |||
693 | #define devfsd_trivial_usage \ | 702 | #define devfsd_trivial_usage \ |
694 | "mntpnt [-v]" USE_DEVFSD_FG_NP("[-fg][-np]") | 703 | "mntpnt [-v]" USE_DEVFSD_FG_NP("[-fg][-np]") |
695 | #define devfsd_full_usage "\n\n" \ | 704 | #define devfsd_full_usage "\n\n" \ |
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 | } | ||