summaryrefslogtreecommitdiff
path: root/common/memory_commands.c
blob: a568435d10d074baad7d6c68e6e5f6666b5f1d6e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
/* 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"

static int command_mem_dump(int argc, char **argv)
{
	volatile uint32_t *address;
	uint32_t value, num = 1, i;
	char *e;

	if (argc < 2)
		return EC_ERROR_PARAM_COUNT;

	address = (uint32_t *)(uintptr_t)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++) {
		value = address[i];
		if (0 == (i%4))
			ccprintf("\n%08X: %08x", address+i, value);
		else
			ccprintf(" %08x", value);
		cflush();

		/* 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,
			"addr [num]",
			"dump num of words (4B) in memory",
			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 's':
				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,
	 "addr [.{b|s}] [value]",
	 "Read or write a word in memory optionally specifying the size",
	 NULL);