1#include <fcntl.h>
2#include <inttypes.h>
3#include <stdbool.h>
4#include <stdio.h>
5#include <stdlib.h>
6#include <string.h>
7#include <sys/mman.h>
8
9#if __LP64__
10#define strtoptr strtoull
11#else
12#define strtoptr strtoul
13#endif
14
15static int usage()
16{
17    fprintf(stderr,"r [-b|-s] <address> [<value>]\n");
18    return -1;
19}
20
21int r_main(int argc, char *argv[])
22{
23    if(argc < 2) return usage();
24
25    int width = 4;
26    if(!strcmp(argv[1], "-b")) {
27        width = 1;
28        argc--;
29        argv++;
30    } else if(!strcmp(argv[1], "-s")) {
31        width = 2;
32        argc--;
33        argv++;
34    }
35
36    if(argc < 2) return usage();
37    uintptr_t addr = strtoptr(argv[1], 0, 16);
38
39    uintptr_t endaddr = 0;
40    char* end = strchr(argv[1], '-');
41    if (end)
42        endaddr = strtoptr(end + 1, 0, 16);
43
44    if (!endaddr)
45        endaddr = addr + width - 1;
46
47    if (endaddr <= addr) {
48        fprintf(stderr, "end address <= start address\n");
49        return -1;
50    }
51
52    bool set = false;
53    uint32_t value = 0;
54    if(argc > 2) {
55        set = true;
56        value = strtoul(argv[2], 0, 16);
57    }
58
59    int fd = open("/dev/mem", O_RDWR | O_SYNC);
60    if(fd < 0) {
61        fprintf(stderr,"cannot open /dev/mem\n");
62        return -1;
63    }
64
65    off64_t mmap_start = addr & ~(PAGE_SIZE - 1);
66    size_t mmap_size = endaddr - mmap_start + 1;
67    mmap_size = (mmap_size + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
68
69    void* page = mmap64(0, mmap_size, PROT_READ | PROT_WRITE,
70                        MAP_SHARED, fd, mmap_start);
71
72    if(page == MAP_FAILED){
73        fprintf(stderr,"cannot mmap region\n");
74        return -1;
75    }
76
77    while (addr <= endaddr) {
78        switch(width){
79        case 4: {
80            uint32_t* x = (uint32_t*) (((uintptr_t) page) + (addr & 4095));
81            if(set) *x = value;
82            fprintf(stderr,"%08"PRIxPTR": %08x\n", addr, *x);
83            break;
84        }
85        case 2: {
86            uint16_t* x = (uint16_t*) (((uintptr_t) page) + (addr & 4095));
87            if(set) *x = value;
88            fprintf(stderr,"%08"PRIxPTR": %04x\n", addr, *x);
89            break;
90        }
91        case 1: {
92            uint8_t* x = (uint8_t*) (((uintptr_t) page) + (addr & 4095));
93            if(set) *x = value;
94            fprintf(stderr,"%08"PRIxPTR": %02x\n", addr, *x);
95            break;
96        }
97        }
98        addr += width;
99    }
100    return 0;
101}
102