2 * Simple app. to do memory accesses via /dev/mem.
4 * $Id: io.c,v 1.5 2000/08/21 09:01:57 richard Exp $
6 * Copyright (c) Richard Hirst <rhirst@linuxcare.com>
14 #include <sys/types.h>
30 "Raw memory i/o utility - $Revision: 1.5 $\n\n"
31 "%s -v -1|2|4 -r|w [-l <len>] [-f <file>] <addr> [<value>]\n\n"
32 " -v Verbose, asks for confirmation\n"
33 " -1|2|4 Sets memory access size in bytes (default byte)\n"
34 " -l <len> Length in bytes of area to access (defaults to\n"
35 " one access, or whole file length)\n"
36 " -r|w Read from or Write to memory (default read)\n"
37 " -f <file> File to write on memory read, or\n"
38 " to read on memory write\n"
39 " <addr> The memory address to access\n"
40 " <val> The value to write (implies -w)\n\n"
42 " %s 0x1000 Reads one byte from 0x1000\n"
43 " %s 0x1000 0x12 Writes 0x12 to location 0x1000\n"
44 " %s -2 -l 8 0x1000 Reads 8 words from 0x1000\n"
45 " %s -r -f dmp -l 100 200 Reads 100 bytes from addr 200 to file\n"
46 " %s -w -f img 0x10000 Writes the whole of file to memory\n"
48 "Note access size (-1|2|4) does not apply to file based accesses.\n\n",
49 argv0
, argv0
, argv0
, argv0
, argv0
, argv0
);
55 memread_memory(unsigned long phys_addr
, void *addr
, int len
, int iosize
)
60 printf("%08lx: ", phys_addr
);
62 while (i
< 16 && len
) {
65 printf(" %02x", *(unsigned char *)addr
);
68 printf(" %04x", *(unsigned short *)addr
);
71 printf(" %08lx", *(unsigned long *)addr
);
85 write_memory(unsigned long phys_addr
, void *addr
, int len
, int iosize
, unsigned long value
)
90 *(unsigned char *)addr
= value
;
97 *(unsigned short *)addr
= value
;
104 *(unsigned long *)addr
= value
;
114 main (int argc
, char **argv
)
116 int mfd
, ffd
= 0, req_len
= 0, opt
;
118 unsigned long real_len
, real_addr
, req_addr
, req_value
= 0, offset
;
122 char *filename
= NULL
;
130 while ((opt
= getopt(argc
, argv
, "hv124rwl:f:")) > 0) {
149 req_len
= strtoul(optarg
, &endptr
, 0);
151 fprintf(stderr
, "Bad <size> value '%s'\n", optarg
);
156 filename
= strdup(optarg
);
159 fprintf(stderr
, "Unknown option: %c\n", opt
);
164 if (optind
== argc
) {
165 fprintf(stderr
, "No address given\n");
168 req_addr
= strtoul(argv
[optind
], &endptr
, 0);
170 fprintf(stderr
, "Bad <addr> value '%s'\n", argv
[optind
]);
174 if (!filename
&& optind
< argc
)
176 if (filename
&& optind
> argc
) {
177 fprintf(stderr
, "Filename AND value given\n");
180 if (!filename
&& !memread
&& optind
== argc
) {
181 fprintf(stderr
, "No value given for WRITE\n");
184 if (!filename
&& !memread
) {
185 req_value
= strtoul(argv
[optind
], &endptr
, 0);
187 fprintf(stderr
, "Bad <value> value '%s'\n", argv
[optind
]);
190 if ((iosize
== 1 && (req_value
& 0xffffff00)) ||
191 (iosize
== 2 && (req_value
& 0xffff0000))) {
192 fprintf(stderr
, "<value> too large\n");
197 if (filename
&& memread
&& !req_len
) {
198 fprintf(stderr
, "No size given for file memread\n");
202 fprintf(stderr
, "Too many arguments '%s'...\n", argv
[optind
]);
205 if (filename
&& memread
) {
206 ffd
= open(filename
, O_WRONLY
|O_CREAT
|O_TRUNC
, S_IRUSR
|S_IWUSR
|S_IRGRP
|S_IROTH
);
208 fprintf(stderr
, "Failed to open destination file '%s': %s\n", filename
, strerror(errno
));
212 if (filename
&& !memread
) {
213 ffd
= open(filename
, O_RDONLY
);
215 fprintf(stderr
, "Failed to open source file '%s': %s\n", filename
, strerror(errno
));
220 if (filename
&& !req_len
) {
221 req_len
= lseek(ffd
, 0, SEEK_END
);
223 fprintf(stderr
, "Failed to seek on '%s': %s\n",
224 filename
, strerror(errno
));
227 if (lseek(ffd
, 0, SEEK_SET
)) {
228 fprintf(stderr
, "Failed to seek on '%s': %s\n",
229 filename
, strerror(errno
));
236 if ((iosize
== 2 && (req_addr
& 1)) ||
237 (iosize
== 4 && (req_addr
& 3))) {
238 fprintf(stderr
, "Badly aligned <addr> for access size\n");
241 if ((iosize
== 2 && (req_len
& 1)) ||
242 (iosize
== 4 && (req_len
& 3))) {
243 fprintf(stderr
, "Badly aligned <size> for access size\n");
249 else if (filename
&& memread
)
250 printf("Request to memread 0x%x bytes from address 0x%08lx\n"
251 "\tto file %s, using %d byte accesses\n",
252 req_len
, req_addr
, filename
, iosize
);
254 printf("Request to write 0x%x bytes to address 0x%08lx\n"
255 "\tfrom file %s, using %d byte accesses\n",
256 req_len
, req_addr
, filename
, iosize
);
258 printf("Request to memread 0x%x bytes from address 0x%08lx\n"
259 "\tusing %d byte accesses\n",
260 req_len
, req_addr
, iosize
);
262 printf("Request to write 0x%x bytes to address 0x%08lx\n"
263 "\tusing %d byte accesses of value 0x%0*lx\n",
264 req_len
, req_addr
, iosize
, iosize
*2, req_value
);
266 real_addr
= req_addr
& ~4095;
267 if (real_addr
== 0xfffff000) {
268 fprintf(stderr
, "Sorry, cannot map the top 4K page\n");
271 offset
= req_addr
- real_addr
;
272 real_len
= req_len
+ offset
;
273 real_len
= (real_len
+ 4095) & ~ 4095;
274 if (real_addr
+ real_len
< real_addr
) {
275 fprintf(stderr
, "Aligned addr+len exceeds top of address space\n");
279 printf("Attempting to map 0x%lx bytes at address 0x%08lx\n",
280 real_len
, real_addr
);
282 mfd
= open("/dev/mem", memread
? O_RDONLY
: O_RDWR
);
284 perror("open /dev/mem");
288 printf("open(/dev/mem) ok\n");
289 real_io
= mmap(NULL
, real_len
,
290 memread
? PROT_READ
:PROT_WRITE
,
291 MAP_SHARED
, mfd
, real_addr
);
292 if (real_io
== (void *)(-1)) {
293 fprintf(stderr
, "mmap() failed: %s\n", strerror(errno
));
297 printf("mmap() ok\n");
305 if (c
!= 'y' && c
!= 'Y') {
311 if (filename
&& memread
) {
312 int n
= write(ffd
, real_io
+ offset
, req_len
);
315 fprintf(stderr
, "File write failed: %s\n", strerror(errno
));
318 else if (n
!= req_len
) {
319 fprintf(stderr
, "Only wrote %d of %d bytes to file\n",
325 int n
= read(ffd
, real_io
+ offset
, req_len
);
328 fprintf(stderr
, "File read failed: %s\n", strerror(errno
));
331 else if (n
!= req_len
) {
332 fprintf(stderr
, "Only read %d of %d bytes from file\n",
338 memread_memory(req_addr
, real_io
+ offset
, req_len
, iosize
);
340 write_memory(req_addr
, real_io
+ offset
, req_len
, iosize
, req_value
);