devmem: map two pages only if it is necessary
No binary (build failed)
—
(log yok)
| @@ -13,9 +13,9 @@ int devmem_main(int argc UNUSED_PARAM, char **argv) | |
| uint64_t read_result; | |
| uint64_t writeval = writeval; /* for compiler */ | |
| off_t target; | |
| - | unsigned page_size = getpagesize(); |
| + | unsigned page_size, mapped_size, offset_in_page; |
| int fd; | |
| - | int width = 8 * sizeof(int); |
| + | unsigned width = 8 * sizeof(int); |
| /* devmem ADDRESS [WIDTH [VALUE]] */ | |
| // TODO: options? | |
| @@ -50,15 +50,22 @@ int devmem_main(int argc UNUSED_PARAM, char **argv) | |
| if (argv[3]) | |
| writeval = bb_strtoull(argv[3], NULL, 0); | |
| } else { /* argv[2] == NULL */ | |
| - | /* make argv[3] to be a valid thing to use */ |
| + | /* make argv[3] to be a valid thing to fetch */ |
| argv--; | |
| } | |
| if (errno) | |
| - | bb_show_usage(); /* bb_strtouXX failed */ |
| + | bb_show_usage(); /* one of bb_strtouXX failed */ |
| fd = xopen("/dev/mem", argv[3] ? (O_RDWR | O_SYNC) : (O_RDONLY | O_SYNC)); | |
| + | mapped_size = page_size = getpagesize(); |
| + | offset_in_page = (unsigned)target & (page_size - 1); |
| + | if (offset_in_page + width > page_size) { |
| + | /* This access spans pages. |
| + | * Must map two pages to make it possible: */ |
| + | mapped_size *= 2; |
| + | } |
| map_base = mmap(NULL, | |
| - | page_size * 2 /* in case value spans page */, |
| + | mapped_size, |
| argv[3] ? (PROT_READ | PROT_WRITE) : PROT_READ, | |
| MAP_SHARED, | |
| fd, | |
| @@ -68,7 +75,7 @@ int devmem_main(int argc UNUSED_PARAM, char **argv) | |
| // printf("Memory mapped at address %p.\n", map_base); | |
| - | virt_addr = (char*)map_base + (target & (page_size - 1)); |
| + | virt_addr = (char*)map_base + offset_in_page; |
| if (!argv[3]) { | |
| switch (width) { | |
| @@ -119,7 +126,7 @@ int devmem_main(int argc UNUSED_PARAM, char **argv) | |
| } | |
| if (ENABLE_FEATURE_CLEAN_UP) { | |
| - | if (munmap(map_base, page_size * 2) == -1) |
| + | if (munmap(map_base, mapped_size) == -1) |
| bb_perror_msg_and_die("munmap"); | |
| close(fd); | |
| } | |