Home | History | Annotate | Download | only in other
      1 /* devmem.c - Access physical addresses
      2  *
      3  * Copyright 2019 The Android Open Source Project
      4 
      5 USE_DEVMEM(NEWTOY(devmem, "<1>3", TOYFLAG_USR|TOYFLAG_BIN))
      6 
      7 config DEVMEM
      8   bool "devmem"
      9   default y
     10   help
     11     usage: devmem ADDR [WIDTH [DATA]]
     12 
     13     Read/write physical address via /dev/mem.
     14 
     15     WIDTH is 1, 2, 4, or 8 bytes (default 4).
     16 */
     17 
     18 #define FOR_devmem
     19 #include "toys.h"
     20 
     21 void devmem_main(void)
     22 {
     23   int writing = toys.optc == 3, page_size = getpagesize(), bytes = 4, fd;
     24   unsigned long long addr = atolx(toys.optargs[0]), data = 0, map_off, map_len;
     25   void *map, *p;
     26 
     27   // WIDTH?
     28   if (toys.optc>1) {
     29     int i;
     30 
     31     if (strlen(toys.optargs[1])!=1 || (i=stridx("1248", *toys.optargs[1]))==-1)
     32       error_exit("bad width: %s", toys.optargs[1]);
     33     bytes = 1<<i;
     34   }
     35 
     36   // DATA? Report out of range values as errors rather than truncating.
     37   if (writing) data = atolx_range(toys.optargs[2], 0, (1ULL<<(8*bytes))-1);
     38 
     39   // Map in just enough.
     40   fd = xopen("/dev/mem", (writing ? O_RDWR : O_RDONLY) | O_SYNC);
     41   map_off = addr & ~(page_size - 1);
     42   map_len = (addr+bytes-map_off);
     43   map = xmmap(NULL, map_len, writing ? PROT_WRITE : PROT_READ, MAP_SHARED, fd,
     44       map_off);
     45   p = map + (addr & (page_size - 1));
     46   close(fd);
     47 
     48   // Not using peek()/poke() because registers care about size of read/write
     49   if (writing) {
     50     if (bytes == 1) *(char *)p = data;
     51     else if (bytes == 2) *(short *)p = data;
     52     else if (bytes == 4) *(int *)p = data;
     53     else if (bytes == 8) *(long long *)p = data;
     54   } else {
     55     if (bytes == 1) data = *(char *)p;
     56     else if (bytes == 2) data = *(short *)p;
     57     else if (bytes == 4) data = *(int *)p;
     58     else if (bytes == 8) data = *(long long *)p;
     59     printf("%#0*llx\n", bytes*2, data);
     60   }
     61 
     62   munmap(map, map_len);
     63 }
     64