toybox/toys/other/devmem.c
<<
>>
Prefs
   1/* devmem.c - Access physical addresses
   2 *
   3 * Copyright 2019 The Android Open Source Project
   4
   5USE_DEVMEM(NEWTOY(devmem, "<1>3", TOYFLAG_USR|TOYFLAG_BIN))
   6
   7config DEVMEM
   8  bool "devmem"
   9  default y
  10  help
  11    usage: devmem ADDR [WIDTH [DATA]]
  12
  13    Read/write physical address. WIDTH is 1, 2, 4, or 8 bytes (default 4).
  14    Prefix ADDR with 0x for hexadecimal, output is in same base as address.
  15*/
  16
  17#define FOR_devmem
  18#include "toys.h"
  19
  20void devmem_main(void)
  21{
  22  int writing = toys.optc == 3, page_size = sysconf(_SC_PAGESIZE), bytes = 4,fd;
  23  unsigned long long data = 0, map_off, map_len;
  24  unsigned long addr = atolx(*toys.optargs);
  25  void *map, *p;
  26
  27  // WIDTH?
  28  if (toys.optc>1) {
  29    int i;
  30
  31    if ((i=stridx("1248", *toys.optargs[1]))==-1 || 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  if (CFG_TOYBOX_FORK) {
  41    fd = xopen("/dev/mem", (writing ? O_RDWR : O_RDONLY) | O_SYNC);
  42
  43    map_off = addr & ~(page_size - 1);
  44    map_len = (addr+bytes-map_off);
  45    map = xmmap(0, map_len, writing ? PROT_WRITE : PROT_READ, MAP_SHARED, fd,
  46        map_off);
  47    p = map + (addr & (page_size - 1));
  48    close(fd);
  49  } else p = (void *)addr;
  50
  51  // Not using peek()/poke() because registers care about size of read/write
  52  if (writing) {
  53    if (bytes == 1) *(unsigned char *)p = data;
  54    else if (bytes == 2) *(unsigned short *)p = data;
  55    else if (bytes == 4) *(unsigned int *)p = data;
  56    else if (bytes == 8) *(unsigned long long *)p = data;
  57  } else {
  58    if (bytes == 1) data = *(unsigned char *)p;
  59    else if (bytes == 2) data = *(unsigned short *)p;
  60    else if (bytes == 4) data = *(unsigned int *)p;
  61    else if (bytes == 8) data = *(unsigned long long *)p;
  62    printf((!strchr(*toys.optargs, 'x')) ? "%0*lld\n" : "0x%0*llx\n",
  63      bytes*2, data);
  64  }
  65
  66  if (CFG_TOYBOX_FORK) munmap(map, map_len);
  67}
  68