Created
June 11, 2012 13:48
-
-
Save mike0/2910170 to your computer and use it in GitHub Desktop.
memtool
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Copyright 2006 Freescale Semiconductor, Inc. All Rights Reserved. | |
*/ | |
/* | |
* The code contained herein is licensed under the GNU General Public | |
* License. You may obtain a copy of the GNU General Public License | |
* Version 2 or later at the following locations: | |
* | |
* http://www.opensource.org/licenses/gpl-license.html | |
* http://www.gnu.org/copyleft/gpl.html | |
*/ | |
#include <stddef.h> | |
#include <stdio.h> | |
#include <sys/types.h> | |
#include <stdint.h> | |
#include <sys/stat.h> | |
#include <fcntl.h> | |
#include <sys/mman.h> | |
#include <string.h> /* strcmp() */ | |
#include <stdlib.h> /* strtoul() */ | |
#include <unistd.h> /* close() */ | |
int g_size = 4; | |
unsigned long int g_paddr; | |
int g_is_write; | |
uint32_t g_value = 0; | |
uint32_t g_count = 1; | |
int parse_cmdline(int argc, char ** argv) | |
{ | |
int cur_arg = 0; | |
char * str; | |
if (argc < 2) | |
return -1; | |
cur_arg++; | |
if (strcmp(argv[cur_arg], "-8") == 0) { | |
cur_arg++; | |
g_size = 1; | |
} | |
else if (strcmp(argv[cur_arg], "-16") == 0) { | |
cur_arg++; | |
g_size = 2; | |
} | |
else if (strcmp(argv[cur_arg], "-32") == 0) { | |
cur_arg++; | |
g_size = 4; | |
} | |
if (cur_arg >= argc) | |
return -1; | |
g_paddr = strtoul(argv[cur_arg], NULL, 16); | |
if (!g_paddr) | |
return -1; | |
if ( ( str = strchr(argv[cur_arg], '=') ) ) { | |
g_is_write = 1; | |
if (strlen(str) > 1) { | |
str++; | |
g_value = strtoul(str, NULL, 16); | |
return 0; | |
} | |
} | |
if (++cur_arg >= argc) | |
return -1; | |
if ((argv[cur_arg])[0] == '=' ) { | |
g_is_write = 1; | |
if (strlen(argv[cur_arg]) > 1) { | |
(argv[cur_arg])++; | |
} else { | |
if (++cur_arg >= argc) | |
return -1; | |
} | |
g_value = strtoul(argv[cur_arg], NULL, 16); | |
} | |
else { | |
if (g_is_write) | |
g_value = strtoul(argv[cur_arg], NULL, 16); | |
else | |
g_count = strtoul(argv[cur_arg], NULL, 16); | |
} | |
return 0; | |
} | |
void read_mem(void * addr, uint32_t count, uint32_t size) | |
{ | |
int i; | |
uint8_t * addr8 = addr; | |
uint16_t * addr16 = addr; | |
uint32_t * addr32 = addr; | |
switch (size) | |
{ | |
case 1: | |
for (i = 0; i < count; i++) { | |
if ( (i % 16) == 0 ) | |
printf("\n0x%08X: ", (uint)g_paddr); | |
printf(" %02X", addr8[i]); | |
g_paddr++; | |
} | |
break; | |
case 2: | |
for (i = 0; i < count; i++) { | |
if ( (i % 8) == 0 ) | |
printf("\n0x%08X: ", (uint)g_paddr); | |
printf(" %04X", addr16[i]); | |
g_paddr += 2; | |
} | |
break; | |
case 4: | |
for (i = 0; i < count; i++) { | |
if ( (i % 4) == 0 ) | |
printf("\n0x%08X: ", (uint)g_paddr); | |
printf(" %08X", addr32[i]); | |
g_paddr += 4; | |
} | |
break; | |
} | |
printf("\n\n"); | |
} | |
void write_mem(void * addr, uint32_t value, uint32_t size) | |
{ | |
uint8_t * addr8 = addr; | |
uint16_t * addr16 = addr; | |
uint32_t * addr32 = addr; | |
switch (size) | |
{ | |
case 1: | |
*addr8 = value; | |
break; | |
case 2: | |
*addr16 = value; | |
break; | |
case 4: | |
*addr32 = value; | |
break; | |
} | |
} | |
int main(int argc, char **argv) | |
{ | |
int fd; | |
void * mem; | |
void * aligned_vaddr; | |
unsigned long aligned_paddr; | |
uint32_t aligned_size; | |
if (parse_cmdline(argc, argv)) { | |
printf("Usage:\n\n" \ | |
"Read memory: memtool [-8 | -16 | -32] <phys addr> <count>\n" \ | |
"Write memory: memtool [-8 | -16 | -32] <phys addr>=<value>\n\n" \ | |
"Default access size is 32-bit.\n\nAddress, count and value are all in hex.\n"); | |
return 1; | |
} | |
/* Align address to access size */ | |
g_paddr &= ~(g_size - 1); | |
aligned_paddr = g_paddr & ~(4096 - 1); | |
aligned_size = g_paddr - aligned_paddr + (g_count * g_size); | |
aligned_size = (aligned_size + 4096 - 1) & ~(4096 - 1); | |
if (g_is_write) | |
printf("Writing %d-bit value 0x%X to address 0x%08X\n", | |
g_size*8, g_value, (uint)g_paddr); | |
else | |
printf("Reading 0x%X count starting at address 0x%08X\n", | |
g_count, (uint)g_paddr); | |
if ((fd = open("/dev/mem", O_RDWR, 0)) < 0) { | |
printf("Open /dev/mem error, maybe check permission.\n"); | |
return 1; | |
} | |
aligned_vaddr = mmap(NULL, aligned_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, aligned_paddr); | |
if (aligned_vaddr == NULL) { | |
printf("Error mapping address\n"); | |
close(fd); | |
return 1; | |
} | |
mem = (void *)((uint32_t)aligned_vaddr + (g_paddr - aligned_paddr)); | |
if (g_is_write) { | |
write_mem(mem, g_value, g_size); | |
} | |
else { | |
read_mem(mem, g_count, g_size); | |
} | |
munmap(aligned_vaddr, aligned_size); | |
close(fd); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment