xref: /OK3568_Linux_fs/yocto/meta-rockchip/recipes-devtools/io/files/io.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /*
2  * Simple app. to do memory accesses via /dev/mem.
3  *
4  * $Id: io.c,v 1.5 2000/08/21 09:01:57 richard Exp $
5  *
6  * Copyright (c) Richard Hirst <rhirst@linuxcare.com>
7  */
8 
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <unistd.h>
13 #include <sys/mman.h>
14 #include <sys/types.h>
15 #include <stdint.h>
16 #include <sys/stat.h>
17 #include <fcntl.h>
18 #include <errno.h>
19 
20 #ifndef FALSE
21 #define FALSE	0
22 #define TRUE	(!FALSE)
23 #endif
24 
25 #ifdef MMAP64
26 #define mmap mmap64
27 #endif
28 
29 static char *argv0;
30 
31 static void
usage(void)32 usage (void)
33 {
34 	fprintf(stderr,
35 "Raw memory i/o utility - $Revision: 1.5 $\n\n"
36 "%s -v -1|2|4 -r|w [-l <len>] [-f <file>] <addr> [<value>]\n\n"
37 "    -v         Verbose, asks for confirmation\n"
38 "    -1|2|4     Sets memory access size in bytes (default byte)\n"
39 "    -l <len>   Length in bytes of area to access (defaults to\n"
40 "               one access, or whole file length)\n"
41 "    -r|w       Read from or Write to memory (default read)\n"
42 "    -f <file>  File to write on memory read, or\n"
43 "               to read on memory write\n"
44 "    <addr>     The memory address to access\n"
45 "    <val>      The value to write (implies -w)\n\n"
46 "Examples:\n"
47 "    %s 0x1000                  Reads one byte from 0x1000\n"
48 "    %s 0x1000 0x12             Writes 0x12 to location 0x1000\n"
49 "    %s -2 -l 8 0x1000          Reads 8 words from 0x1000\n"
50 "    %s -r -f dmp -l 100 200    Reads 100 bytes from addr 200 to file\n"
51 "    %s -w -f img 0x10000       Writes the whole of file to memory\n"
52 "\n"
53 "Note access size (-1|2|4) does not apply to file based accesses.\n\n",
54 		argv0, argv0, argv0, argv0, argv0, argv0);
55 	exit(1);
56 }
57 
58 
59 static void
memread_memory(unsigned long phys_addr,uint8_t * addr,int len,int iosize)60 memread_memory(unsigned long phys_addr, uint8_t *addr, int len, int iosize)
61 {
62 	int i;
63 
64 	while (len) {
65 		printf("%08lx: ", phys_addr);
66 		i = 0;
67 		while (i < 16 && len) {
68 			switch(iosize) {
69 			case 1:
70 				printf(" %02x", *(uint8_t *)addr);
71 				break;
72 			case 2:
73 				printf(" %04x", *(uint16_t *)addr);
74 				break;
75 			case 4:
76 				printf(" %08x", *(uint32_t *)addr);
77 				break;
78 			}
79 			i += iosize;
80 			addr += iosize;
81 			len -= iosize;
82 		}
83 		phys_addr += 16;
84 		printf("\n");
85 	}
86 }
87 
88 
89 static void
write_memory(uint8_t * addr,int len,int iosize,unsigned long value)90 write_memory(uint8_t *addr, int len, int iosize, unsigned long value)
91 {
92 	switch(iosize) {
93 	case 1:
94 		while (len) {
95 			*(uint8_t *)addr = value;
96 			len -= iosize;
97 			addr += iosize;
98 		}
99 		break;
100 	case 2:
101 		while (len) {
102 			*(uint16_t *)addr = value;
103 			len -= iosize;
104 			addr += iosize;
105 		}
106 		break;
107 	case 4:
108 		while (len) {
109 			*(uint32_t *)addr = value;
110 			len -= iosize;
111 			addr += iosize;
112 		}
113 		break;
114 	}
115 }
116 
117 
118 int
main(int argc,char ** argv)119 main (int argc, char **argv)
120 {
121 	int mfd, ffd = 0, req_len = 0, opt;
122 	uint8_t *real_io;
123 	unsigned long real_len, real_addr, req_addr, req_value = 0, offset;
124 	char *endptr;
125 	int memread = TRUE;
126 	int iosize = 1;
127 	char *filename = NULL;
128 	int verbose = 0;
129 
130 	argv0 = argv[0];
131 	opterr = 0;
132 	if (argc == 1)
133 		usage();
134 
135 	while ((opt = getopt(argc, argv, "hv124rwl:f:")) > 0) {
136 		switch (opt) {
137 		case 'h':
138 			usage();
139 		case 'v':
140 			verbose = 1;
141 			break;
142 		case '1':
143 		case '2':
144 		case '4':
145 			iosize = opt - '0';
146 			break;
147 		case 'r':
148 			memread = TRUE;
149 			break;
150 		case 'w':
151 			memread = FALSE;
152 			break;
153 		case 'l':
154 			req_len = strtoul(optarg, &endptr, 0);
155 			if (*endptr) {
156 				fprintf(stderr, "Bad <size> value '%s'\n", optarg);
157 				exit(1);
158 			}
159 			break;
160 		case 'f':
161 			filename = strdup(optarg);
162 			break;
163 		default:
164 			fprintf(stderr, "Unknown option: %c\n", opt);
165 			usage();
166 		}
167 	}
168 
169 	if (optind == argc) {
170 		fprintf(stderr, "No address given\n");
171 		exit(1);
172 	}
173 	req_addr = strtoul(argv[optind], &endptr, 0);
174 	if (*endptr) {
175 		fprintf(stderr, "Bad <addr> value '%s'\n", argv[optind]);
176 		exit(1);
177 	}
178 	optind++;
179 	if (!filename && optind < argc)
180 		memread = FALSE;
181 	if (filename && optind > argc) {
182 		fprintf(stderr, "Filename AND value given\n");
183 		exit(1);
184 	}
185 	if (!filename && !memread && optind == argc) {
186 		fprintf(stderr, "No value given for WRITE\n");
187 		exit(1);
188 	}
189 	if (!filename && !memread) {
190 		req_value = strtoul(argv[optind], &endptr, 0);
191 		if (*endptr) {
192 			fprintf(stderr, "Bad <value> value '%s'\n", argv[optind]);
193 			exit(1);
194 		}
195 		if ((iosize == 1 && (req_value & 0xffffff00)) ||
196 				(iosize == 2 && (req_value & 0xffff0000))) {
197 			fprintf(stderr, "<value> too large\n");
198 			exit(1);
199 		}
200 		optind++;
201 	}
202 	if (filename && memread && !req_len) {
203 		fprintf(stderr, "No size given for file memread\n");
204 		exit(1);
205 	}
206 	if (optind < argc) {
207 		fprintf(stderr, "Too many arguments '%s'...\n", argv[optind]);
208 		exit(1);
209 	}
210 	if (filename && memread) {
211 		ffd = open(filename, O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
212 		if (ffd < 0) {
213 			fprintf(stderr, "Failed to open destination file '%s': %s\n", filename, strerror(errno));
214 			exit(1);
215 		}
216 	}
217 	if (filename && !memread) {
218 		ffd = open(filename, O_RDONLY);
219 		if (ffd < 0) {
220 			fprintf(stderr, "Failed to open source file '%s': %s\n", filename, strerror(errno));
221 			exit(1);
222 		}
223 	}
224 
225 	if (filename && !req_len) {
226 		req_len = lseek(ffd, 0, SEEK_END);
227 		if (req_len < 0) {
228 			fprintf(stderr, "Failed to seek on '%s': %s\n",
229 					filename, strerror(errno));
230 			exit(1);
231 		}
232 		if (lseek(ffd, 0, SEEK_SET)) {
233 			fprintf(stderr, "Failed to seek on '%s': %s\n",
234 					filename, strerror(errno));
235 			exit(1);
236 		}
237 	}
238 	if (!req_len)
239 		req_len = iosize;
240 
241 	if ((iosize == 2 && (req_addr & 1)) ||
242 			(iosize == 4 && (req_addr & 3))) {
243 		fprintf(stderr, "Badly aligned <addr> for access size\n");
244 		exit(1);
245 	}
246 	if ((iosize == 2 && (req_len & 1)) ||
247 			(iosize == 4 && (req_len & 3))) {
248 		fprintf(stderr, "Badly aligned <size> for access size\n");
249 		exit(1);
250 	}
251 
252 	if (!verbose)
253 		/* Nothing */;
254 	else if (filename && memread)
255 		printf("Request to memread 0x%x bytes from address 0x%08lx\n"
256 			"\tto file %s, using %d byte accesses\n",
257 			req_len, req_addr, filename, iosize);
258 	else if (filename)
259 		printf("Request to write 0x%x bytes to address 0x%08lx\n"
260 			"\tfrom file %s, using %d byte accesses\n",
261 			req_len, req_addr, filename, iosize);
262 	else if (memread)
263 		printf("Request to memread 0x%x bytes from address 0x%08lx\n"
264 			"\tusing %d byte accesses\n",
265 			req_len, req_addr, iosize);
266 	else
267 		printf("Request to write 0x%x bytes to address 0x%08lx\n"
268 			"\tusing %d byte accesses of value 0x%0*lx\n",
269 			req_len, req_addr, iosize, iosize*2, req_value);
270 
271 	real_addr = req_addr & ~4095;
272 	if (real_addr == 0xfffff000) {
273 		fprintf(stderr, "Sorry, cannot map the top 4K page\n");
274 		exit(1);
275 	}
276 	offset = req_addr - real_addr;
277 	real_len = req_len + offset;
278 	real_len = (real_len + 4095) & ~ 4095;
279 	if (real_addr + real_len < real_addr) {
280 		fprintf(stderr, "Aligned addr+len exceeds top of address space\n");
281 		exit(1);
282 	}
283 	if (verbose)
284 		printf("Attempting to map 0x%lx bytes at address 0x%08lx\n",
285 			real_len, real_addr);
286 
287 	mfd = open("/dev/mem", (memread ? O_RDONLY : O_RDWR) | O_SYNC);
288 	if (mfd == -1) {
289 		perror("open /dev/mem");
290 		exit(1);
291 	}
292 	if (verbose)
293 		printf("open(/dev/mem) ok\n");
294 	real_io = mmap(NULL, real_len,
295 			memread ? PROT_READ:PROT_WRITE,
296 			MAP_SHARED, mfd, real_addr);
297 	if (real_io == (void *)(-1)) {
298 		fprintf(stderr, "mmap() failed: %s\n", strerror(errno));
299 		exit(1);
300 	}
301 	if (verbose)
302 		printf("mmap() ok\n");
303 
304 	if (verbose) {
305 		int c;
306 
307 		printf("OK? ");
308 		fflush(stdout);
309 		c = getchar();
310 		if (c != 'y' && c != 'Y') {
311 			printf("Aborted\n");
312 			exit(1);
313 		}
314 	}
315 
316 	if (filename && memread) {
317 		int n = write(ffd, real_io + offset, req_len);
318 
319 		if (n < 0) {
320 			fprintf(stderr, "File write failed: %s\n", strerror(errno));
321 			exit(1);
322 		}
323 		else if (n != req_len) {
324 			fprintf(stderr, "Only wrote %d of %d bytes to file\n",
325 					n, req_len);
326 			exit(1);
327 		}
328 	}
329 	else if (filename) {
330 		int n = read(ffd, real_io + offset, req_len);
331 
332 		if (n < 0) {
333 			fprintf(stderr, "File read failed: %s\n", strerror(errno));
334 			exit(1);
335 		}
336 		else if (n != req_len) {
337 			fprintf(stderr, "Only read %d of %d bytes from file\n",
338 					n, req_len);
339 			exit(1);
340 		}
341 	}
342 	else if (memread)
343 		memread_memory(req_addr, real_io + offset, req_len, iosize);
344 	else
345 		write_memory(real_io + offset, req_len, iosize, req_value);
346 
347 	if (filename)
348 		close(ffd);
349 	close (mfd);
350 
351 	return 0;
352 }
353 
354