lede-packages-rs

git clone git://archive.git.mtrnord.blog/MTRNord/lede-packages-rs.git
Log | Files | Refs | README | LICENSE

io.c (9728B)


      1 /*
      2  * Simple app. to do memory accesses via /dev/mem.
      3  *
      4  *
      5  * Copyright (c) Richard Hirst <rhirst@linuxcare.com>
      6  * Copyright (c) Thomas Langer <thomas.langer@infineon.com>
      7  *
      8  */
      9 
     10 #include <stdio.h>
     11 #include <stdlib.h>
     12 #include <string.h>
     13 #include <unistd.h>
     14 #include <sys/mman.h>
     15 #include <sys/types.h>
     16 #include <sys/stat.h>
     17 #include <fcntl.h>
     18 #include <errno.h>
     19 
     20 #define MEM_READ  0
     21 #define MEM_WRITE 1
     22 #define MEM_AND   2
     23 #define MEM_OR    3
     24 
     25 static void
     26 usage (char *argv0)
     27 {
     28 	fprintf(stderr,
     29 "Raw memory i/o utility - $Revision: 2.0 $\n\n"
     30 "%s -v -1|2|4 -r|w|a|o [-l <len>] [-f <file>] <addr> [<value>]\n\n"
     31 "    -v         Verbose, asks for confirmation\n"
     32 "    -1|2|4     Sets memory access size in bytes (default byte)\n"
     33 "    -l <len>   Length in bytes of area to access (defaults to\n"
     34 "               one access, or whole file length)\n"
     35 "    -r|w|a|o   Read from or Write to memory (default read)\n"
     36 "               optional write with modify (and/or)\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"
     41 "Examples:\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"
     47 "\n"
     48 "Note access size (-1|2|4) does not apply to file based accesses.\n\n",
     49 		argv0, argv0, argv0, argv0, argv0, argv0);
     50 	exit(1);
     51 }
     52 
     53 
     54 static void
     55 memread_memory(unsigned long phys_addr, void *addr, int len, int iosize)
     56 {
     57 	int i;
     58 
     59 	while (len) {
     60 		printf("%08lx: ", phys_addr);
     61 		i = 0;
     62 		while (i < 16 && len) {
     63 			switch(iosize) {
     64 			case 1:
     65 				printf(" %02x", *(unsigned char *)addr);
     66 				break;
     67 			case 2:
     68 				printf(" %04x", *(unsigned short *)addr);
     69 				break;
     70 			case 4:
     71 				printf(" %08lx", *(unsigned long *)addr);
     72 				break;
     73 			}
     74 			i += iosize;
     75 			addr += iosize;
     76 			len -= iosize;
     77 		}
     78 		phys_addr += 16;
     79 		printf("\n");
     80 	}
     81 }
     82 
     83 
     84 static void
     85 write_memory(unsigned long phys_addr, void *addr, int len, int iosize, unsigned long value)
     86 {
     87 	switch(iosize) {
     88 	case 1:
     89 		while (len) {
     90 			*(unsigned char *)addr = value;
     91 			len -= iosize;
     92 			addr += iosize;
     93 		}
     94 		break;
     95 	case 2:
     96 		while (len) {
     97 			*(unsigned short *)addr = value;
     98 			len -= iosize;
     99 			addr += iosize;
    100 		}
    101 		break;
    102 	case 4:
    103 		while (len) {
    104 			*(unsigned long *)addr = value;
    105 			len -= iosize;
    106 			addr += iosize;
    107 		}
    108 		break;
    109 	}
    110 }
    111 
    112 
    113 static void
    114 and_write_memory(unsigned long phys_addr, void *addr, int len, int iosize, unsigned long value)
    115 {
    116 	switch(iosize) {
    117 	case 1:
    118 		while (len) {
    119 			*(unsigned char *)addr &= value;
    120 			len -= iosize;
    121 			addr += iosize;
    122 		}
    123 		break;
    124 	case 2:
    125 		while (len) {
    126 			*(unsigned short *)addr &= value;
    127 			len -= iosize;
    128 			addr += iosize;
    129 		}
    130 		break;
    131 	case 4:
    132 		while (len) {
    133 			*(unsigned long *)addr &= value;
    134 			len -= iosize;
    135 			addr += iosize;
    136 		}
    137 		break;
    138 	}
    139 }
    140 
    141 
    142 static void
    143 or_write_memory(unsigned long phys_addr, void *addr, int len, int iosize, unsigned long value)
    144 {
    145 	switch(iosize) {
    146 	case 1:
    147 		while (len) {
    148 			*(unsigned char *)addr |= value;
    149 			len -= iosize;
    150 			addr += iosize;
    151 		}
    152 		break;
    153 	case 2:
    154 		while (len) {
    155 			*(unsigned short *)addr |= value;
    156 			len -= iosize;
    157 			addr += iosize;
    158 		}
    159 		break;
    160 	case 4:
    161 		while (len) {
    162 			*(unsigned long *)addr |= value;
    163 			len -= iosize;
    164 			addr += iosize;
    165 		}
    166 		break;
    167 	}
    168 }
    169 
    170 
    171 int
    172 main (int argc, char **argv)
    173 {
    174 	int mfd, ffd = 0, req_len = 0, opt;
    175 	void *real_io;
    176 	unsigned long real_len, real_addr, req_addr, req_value = 0, offset;
    177 	char *endptr;
    178 	int memfunc = MEM_READ;
    179 	int iosize = 1;
    180 	char *filename = NULL;
    181 	int verbose = 0;
    182 
    183 	opterr = 0;
    184 	if (argc == 1)
    185 		usage(argv[0]);
    186 
    187 	while ((opt = getopt(argc, argv, "hv124rwaol:f:")) > 0) {
    188 		switch (opt) {
    189 		case 'h':
    190 			usage(argv[0]);
    191 		case 'v':
    192 			verbose = 1;
    193 			break;
    194 		case '1':
    195 		case '2':
    196 		case '4':
    197 			iosize = opt - '0';
    198 			break;
    199 		case 'r':
    200 			memfunc = MEM_READ;
    201 			break;
    202 		case 'a':
    203 			memfunc = MEM_AND;
    204 			break;
    205 		case 'o':
    206 			memfunc = MEM_OR;
    207 			break;
    208 		case 'w':
    209 			memfunc = MEM_WRITE;
    210 			break;
    211 		case 'l':
    212 			req_len = strtoul(optarg, &endptr, 0);
    213 			if (*endptr) {
    214 				fprintf(stderr, "Bad <size> value '%s'\n", optarg);
    215 				exit(1);
    216 			}
    217 			break;
    218 		case 'f':
    219 			filename = strdup(optarg);
    220 			break;
    221 		default:
    222 			fprintf(stderr, "Unknown option: %c\n", opt);
    223 			usage(argv[0]);
    224 		}
    225 	}
    226 
    227 	if (optind == argc) {
    228 		fprintf(stderr, "No address given\n");
    229 		exit(1);
    230 	}
    231 	req_addr = strtoul(argv[optind], &endptr, 0);
    232 	if (*endptr) {
    233 		fprintf(stderr, "Bad <addr> value '%s'\n", argv[optind]);
    234 		exit(1);
    235 	}
    236 	optind++;
    237 	if (!filename && (memfunc == MEM_READ) && optind < argc) {
    238 		memfunc = MEM_WRITE;
    239 	}
    240 	if (filename && optind > argc) {
    241 		fprintf(stderr, "Filename AND value given\n");
    242 		exit(1);
    243 	}
    244 	if (!filename && (memfunc != MEM_READ) && optind == argc) {
    245 		fprintf(stderr, "No value given for WRITE\n");
    246 		exit(1);
    247 	}
    248 	if (!filename && (memfunc != MEM_READ)) {
    249 		req_value = strtoul(argv[optind], &endptr, 0);
    250 		if (*endptr) {
    251 			fprintf(stderr, "Bad <value> value '%s'\n", argv[optind]);
    252 			exit(1);
    253 		}
    254 		if ((iosize == 1 && (req_value & 0xffffff00)) ||
    255 				(iosize == 2 && (req_value & 0xffff0000))) {
    256 			fprintf(stderr, "<value> too large\n");
    257 			exit(1);
    258 		}
    259 		optind++;
    260 	}
    261 	if (filename && (memfunc == MEM_READ) && !req_len) {
    262 		fprintf(stderr, "No size given for file memread\n");
    263 		exit(1);
    264 	}
    265 	if (optind < argc) {
    266 		fprintf(stderr, "Too many arguments '%s'...\n", argv[optind]);
    267 		exit(1);
    268 	}
    269 	if (filename && (memfunc == MEM_READ)) {
    270 		ffd = open(filename, O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
    271 		if (ffd < 0) {
    272 			fprintf(stderr, "Failed to open destination file '%s': %s\n", filename, strerror(errno));
    273 			exit(1);
    274 		}
    275 	}
    276 	if (filename && (memfunc != MEM_READ)) {
    277 		ffd = open(filename, O_RDONLY);
    278 		if (ffd < 0) {
    279 			fprintf(stderr, "Failed to open source file '%s': %s\n", filename, strerror(errno));
    280 			exit(1);
    281 		}
    282 	}
    283 
    284 	if (filename && !req_len) {
    285 		req_len = lseek(ffd, 0, SEEK_END);
    286 		if (req_len < 0) {
    287 			fprintf(stderr, "Failed to seek on '%s': %s\n",
    288 					filename, strerror(errno));
    289 			exit(1);
    290 		}
    291 		if (lseek(ffd, 0, SEEK_SET)) {
    292 			fprintf(stderr, "Failed to seek on '%s': %s\n",
    293 					filename, strerror(errno));
    294 			exit(1);
    295 		}
    296 	}
    297 	if (!req_len)
    298 		req_len = iosize;
    299 
    300 	if ((iosize == 2 && (req_addr & 1)) ||
    301 			(iosize == 4 && (req_addr & 3))) {
    302 		fprintf(stderr, "Badly aligned <addr> for access size\n");
    303 		exit(1);
    304 	}
    305 	if ((iosize == 2 && (req_len & 1)) ||
    306 			(iosize == 4 && (req_len & 3))) {
    307 		fprintf(stderr, "Badly aligned <size> for access size\n");
    308 		exit(1);
    309 	}
    310 
    311 	if (!verbose)
    312 		/* Nothing */;
    313 	else if (filename && (memfunc == MEM_READ))
    314 		printf("Request to read 0x%x bytes from address 0x%08lx\n"
    315 			"\tto file %s, using %d byte accesses\n",
    316 			req_len, req_addr, filename, iosize);
    317 	else if (filename)
    318 		printf("Request to write 0x%x bytes to address 0x%08lx\n"
    319 			"\tfrom file %s, using %d byte accesses\n",
    320 			req_len, req_addr, filename, iosize);
    321 	else if (memfunc == MEM_READ)
    322 		printf("Request to read 0x%x bytes from address 0x%08lx\n"
    323 			"\tusing %d byte accesses\n",
    324 			req_len, req_addr, iosize);
    325 	else
    326 		printf("Request to write 0x%x bytes to address 0x%08lx\n"
    327 			"\tusing %d byte accesses of value 0x%0*lx\n",
    328 			req_len, req_addr, iosize, iosize*2, req_value);
    329 
    330 	real_addr = req_addr & ~4095;
    331 	if (real_addr == 0xfffff000) {
    332 		fprintf(stderr, "Sorry, cannot map the top 4K page\n");
    333 		exit(1);
    334 	}
    335 	offset = req_addr - real_addr;
    336 	real_len = req_len + offset;
    337 	real_len = (real_len + 4095) & ~ 4095;
    338 	if (real_addr + real_len < real_addr) {
    339 		fprintf(stderr, "Aligned addr+len exceeds top of address space\n");
    340 		exit(1);
    341 	}
    342 	if (verbose)
    343 		printf("Attempting to map 0x%lx bytes at address 0x%08lx\n",
    344 			real_len, real_addr);
    345 
    346 	mfd = open("/dev/mem", (memfunc == MEM_READ) ? O_RDONLY : O_RDWR);
    347 	if (mfd == -1) {
    348 		perror("open /dev/mem");
    349 		fprintf(stderr, "Is CONFIG_DEVMEM activated?\n");
    350 		exit(1);
    351 	}
    352 	if (verbose)
    353 		printf("open(/dev/mem) ok\n");
    354 	real_io = mmap(NULL, real_len,
    355 			(memfunc == MEM_READ) ? PROT_READ:PROT_READ|PROT_WRITE,
    356 			MAP_SHARED, mfd, real_addr);
    357 	if (real_io == (void *)(-1)) {
    358 		fprintf(stderr, "mmap() failed: %s\n", strerror(errno));
    359 		exit(1);
    360 	}
    361 	if (verbose)
    362 		printf("mmap() ok\n");
    363 
    364 	if (verbose) {
    365 		int c;
    366 
    367 		printf("OK? ");
    368 		fflush(stdout);
    369 		c = getchar();
    370 		if (c != 'y' && c != 'Y') {
    371 			printf("Aborted\n");
    372 			exit(1);
    373 		}
    374 	}
    375 
    376 	if (filename && (memfunc == MEM_READ)) {
    377 		int n = write(ffd, real_io + offset, req_len);
    378 
    379 		if (n < 0) {
    380 			fprintf(stderr, "File write failed: %s\n", strerror(errno));
    381 			exit(1);
    382 		}
    383 		else if (n != req_len) {
    384 			fprintf(stderr, "Only wrote %d of %d bytes to file\n",
    385 					n, req_len);
    386 			exit(1);
    387 		}
    388 	}
    389 	else if (filename) {
    390 		int n = read(ffd, real_io + offset, req_len);
    391 
    392 		if (n < 0) {
    393 			fprintf(stderr, "File read failed: %s\n", strerror(errno));
    394 			exit(1);
    395 		}
    396 		else if (n != req_len) {
    397 			fprintf(stderr, "Only read %d of %d bytes from file\n",
    398 					n, req_len);
    399 			exit(1);
    400 		}
    401 	}
    402 	else {
    403 		switch (memfunc)
    404 		{
    405 		case MEM_READ:
    406 			memread_memory(req_addr, real_io + offset, req_len, iosize);
    407 			break;
    408 		case MEM_WRITE:
    409 			write_memory(req_addr, real_io + offset, req_len, iosize, req_value);
    410 			break;
    411 		case MEM_AND:
    412 			and_write_memory(req_addr, real_io + offset, req_len, iosize, req_value);
    413 			break;
    414 		case MEM_OR:
    415 			or_write_memory(req_addr, real_io + offset, req_len, iosize, req_value);
    416 			break;
    417 		}
    418 	}
    419 
    420 	munmap(real_io, real_len);
    421 
    422 	if (filename)
    423 		close(ffd);
    424 	close (mfd);
    425 
    426 	return 0;
    427 }
    428