Access physical memory from Linux user space

If you want to find a way for access physical memory in Linux there are only two solutions. The first is to develop a module running in kernel space with the correct privileges to access physical memory and the second is to use a special devices called "/dev/mem". If your purpose is only to read or write some small parts of physical memory from user space this device is the right solution for you. Basically you can manage it as a file with additional use of some special functions required for get a pointer to the memory address your are interested to work in.

The first operation is to get handle of this special device, Please, note that in Linux system the access of this device is usually guarantee only to root user. If you want to get handle from a different user you need to change device access permission. Anyway the command for get the handle is the following:

int mem_dev = open("/dev/mem", O_RDWR | O_SYNC);

if(mem_dev == -1)
{
   // Error
}

and once finished obviously:

close(mem_dev);

Now the most important part. On Linux the physical memory pointer you want must be page aligned. This mean we need to change, in case, the original memory address you need to something the system can accept. The operation is quite simple and all you need are the following lines of code:

const uint32_t mem_address = 0x10001234
const uint32_t mem_size = 0x100;

uint32_t alloc_mem_size, page_mask, page_size;
void *mem_pointer, *virt_addr;

page_size = sysconf(_SC_PAGESIZE);
alloc_mem_size = (((mem_size / page_size) + 1) * page_size);
page_mask = (page_size - 1);

mem_pointer = mmap(NULL,
                   alloc_mem_size,
                   PROT_READ | PROT_WRITE,
                   MAP_SHARED,
                   mem_dev,
                   (mem_address & ~page_mask)
                   );

if(mem_pointer == MAP_FAILED)
{  
      // Error
}

virt_addr = (mem_pointer + (mem_address & page_mask)); 

At the end of this code, if no errors occurred, you have a pointer virt_addr to the physical memory space from address 0x10001234 to 0x10001334. You can use this pointer in read/write mode but be very carefully since an incorrect modify to some critical memory section will crash the system. Once finished to use the pointer you must free it as follow:

munmap(mem_pointer, alloc_mem_size);

Finish! Very short code and quite easy.

Comments

Popular posts from this blog

Access GPIO from Linux user space

Android: adb push and read-only file system error

Tree in SQL database: The Nested Set Model