Files
OpenCellular/common/memory_commands.c
Bill Richardson 248e1a8a31 md console command can dump memory in more formats
This adds optional format designations to the "md" console
command. By default it dumps memory in 32-bit words, but with
this change it can also display 16-bit words, bytes, and strings.

BUG=none
BRANCH=none
TEST=manual

For example:

> md 0x5c400 32

0005C400: 6d6d6f63 20646e61 75626564 756f2067
0005C410: 74757074 646f6d20 6f6e0065 6c616d72
0005C420: 65766500 70007972 6d617261 41550073
0005C430: 69205452 6974696e 7a696c61 61206465
0005C440: 72657466 73797320 706d756a 2d0a0a00
0005C450: 55202d2d 20545241 74696e69 696c6169
0005C460: 2064657a 65746661 65722072 746f6f62
0005C470: 2d2d2d20 525b000a 74657365 75616320

> md .h 0x5c400 32

0005C400: 6f63 6d6d 6e61 2064 6564 7562 2067 756f
0005C410: 7074 7475 6d20 646f 0065 6f6e 6d72 6c61
0005C420: 6500 6576 7972 7000 7261 6d61 0073 4155
0005C430: 5452 6920 696e 6974 6c61 7a69 6465 6120

> md .b 0x5c400 32

0005C400: 63 6f 6d 6d 61 6e 64 20 64 65 62 75 67 20 6f 75
0005C410: 74 70 75 74 20 6d 6f 64 65 00 6e 6f 72 6d 61 6c

> md .s 0x5c400 32

0005C400: command debug output mode\x00normal
>

Change-Id: Ic0dec9a1a3942acc66c88f46c5b02a80a8110817
Signed-off-by: Bill Richardson <wfrichar@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/300020
Reviewed-by: Randall Spangler <rspangler@chromium.org>
2015-09-16 14:49:59 -07:00

195 lines
3.8 KiB
C

/* Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
/* System module for Chrome EC */
#include "console.h"
#include "timer.h"
#include "util.h"
#include "watchdog.h"
enum format {
FMT_WORD,
FMT_HALF,
FMT_BYTE,
FMT_STRING,
};
static void show_val(uint32_t address, uint32_t index, enum format fmt)
{
uint32_t val;
uintptr_t ptr = address;
switch (fmt) {
case FMT_WORD:
if (0 == (index % 4))
ccprintf("\n%08X:", address + index * 4);
val = *((uint32_t *)ptr + index);
ccprintf(" %08x", val);
break;
case FMT_HALF:
if (0 == (index % 8))
ccprintf("\n%08X:", address + index * 2);
val = *((uint16_t *)ptr + index);
ccprintf(" %04x", val);
break;
case FMT_BYTE:
if (0 == (index % 16))
ccprintf("\n%08X:", address + index);
val = *((uint8_t *)ptr + index);
ccprintf(" %02x", val);
break;
case FMT_STRING:
if (0 == (index % 32))
ccprintf("\n%08X: ", address + index);
val = *((uint8_t *)ptr + index);
if (val >= ' ' && val <= '~')
ccprintf("%c", val);
else
ccprintf("\\x%02x", val);
break;
}
cflush();
}
static int command_mem_dump(int argc, char **argv)
{
uint32_t address, i, num = 1;
char *e;
enum format fmt = FMT_WORD;
if (argc > 1) {
if ((argv[1][0] == '.') && (strlen(argv[1]) == 2)) {
switch (argv[1][1]) {
case 'b':
fmt = FMT_BYTE;
break;
case 'h':
fmt = FMT_HALF;
break;
case 's':
fmt = FMT_STRING;
break;
default:
return EC_ERROR_PARAM1;
}
argc--;
argv++;
}
}
if (argc < 2)
return EC_ERROR_PARAM_COUNT;
address = strtoi(argv[1], &e, 0);
if (*e)
return EC_ERROR_PARAM1;
if (argc >= 3)
num = strtoi(argv[2], &e, 0);
for (i = 0; i < num; i++) {
show_val(address, i, fmt);
/* Lots of output could take a while.
* Let other things happen, too */
if (!(i % 0x100)) {
watchdog_reload();
usleep(10 * MSEC);
}
}
ccprintf("\n");
cflush();
return EC_SUCCESS;
}
DECLARE_CONSOLE_COMMAND(md, command_mem_dump,
"[.b|.h|.s] addr [count]",
"dump memory values, optionally specifying the format",
NULL);
static int command_read_word(int argc, char **argv)
{
volatile uint32_t *address;
uint32_t value;
unsigned access_size = 4;
unsigned argc_offs = 0;
char *e;
if (argc < 2)
return EC_ERROR_PARAM_COUNT;
if (argc > 2) {
if ((argv[1][0] == '.') && (strlen(argv[1]) == 2)) {
argc_offs = 1;
switch (argv[1][1]) {
case 'b':
access_size = 1;
break;
case 'h':
access_size = 2;
break;
default:
return EC_ERROR_PARAM1;
}
}
}
address = (uint32_t *)(uintptr_t)strtoi(argv[1 + argc_offs], &e, 0);
if (*e)
return EC_ERROR_PARAM1 + argc_offs;
/* Just reading? */
if ((argc - argc_offs) < 3) {
switch (access_size) {
case 1:
ccprintf("read 0x%p = 0x%02x\n",
address, *((uint8_t *)address));
break;
case 2:
ccprintf("read 0x%p = 0x%04x\n",
address, *((uint16_t *)address));
break;
default:
ccprintf("read 0x%p = 0x%08x\n", address, *address);
break;
}
return EC_SUCCESS;
}
/* Writing! */
value = strtoi(argv[2 + argc_offs], &e, 0);
if (*e)
return EC_ERROR_PARAM2 + argc_offs;
switch (access_size) {
case 1:
ccprintf("write 0x%p = 0x%02x\n", address, (uint8_t)value);
cflush(); /* Flush before writing in case this crashes */
*((uint8_t *)address) = (uint8_t)value;
break;
case 2:
ccprintf("write 0x%p = 0x%04x\n", address, (uint16_t)value);
cflush();
*((uint16_t *)address) = (uint16_t)value;
break;
default:
ccprintf("write 0x%p = 0x%02x\n", address, value);
cflush();
*address = value;
break;
}
return EC_SUCCESS;
}
DECLARE_CONSOLE_COMMAND
(rw, command_read_word,
"[.b|.h] addr [value]",
"Read or write a word in memory optionally specifying the size",
NULL);