Posted: aprile 22nd, 2012 | Author: Francesco Apollonio | Filed under: ARM, C/C++, English, Linux, Programmazione | Tags: code tips, linux, mmap, program, qemu, syscall | No Comments »
Ok, this is another trick I learned working on my project.
I’ve a QEMU arm machine and a simulation outside them. QEMU shares his RAM (in the future I’ll write about this) with the simulator so I want to unlock the simulation (that is waiting for a 1 at the address 0x0FF8000) writing the specified value on that address using an application in user space inside the VM.
Ok I’ve found here a source code that do exactly this operation.
It uses the device /dev/mem. It is a special file that provides access to the physical memory of the computer.
if((fd = open("/dev/mem", O_RDWR | O_SYNC)) == -1) FATAL;
It opens /dev/mem in RW.
map_base = mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, target & ~MAP_MASK);
This is the key line of the program. The function mmap maps something in the virtual address space of the process who call them. To map the content of a file, mmap starts to read from the offset parameter (the last one) to the length parameter (the second one). MAP_SIZE is 4096 (the size of a memory page), the offset must be multiple of the page size, so target & ~MAP_MASK calculates what is the nearest multiple for our address.
virt_addr = map_base + (target & MAP_MASK);
Now we can add, to the map_base address returned by mmap, the offset deleted before when calculating the multiple of the page size, now we have a physical address that is mapped in a virtual address, and we can write or read directly from it.