1 /*
2 * Copyright (c) 2008-2012 Travis Geiselbrecht
3 *
4 * Use of this source code is governed by a MIT-style
5 * license that can be found in the LICENSE file or at
6 * https://opensource.org/licenses/MIT
7 */
8
9 #include <ctype.h>
10 #include <lk/debug.h>
11 #include <stdlib.h>
12 #include <stdio.h>
13 #include <lk/list.h>
14 #include <string.h>
15 #include <arch/ops.h>
16 #include <platform.h>
17 #include <platform/debug.h>
18 #include <kernel/thread.h>
19 #include <arch.h>
20
21 #include <lk/console_cmd.h>
22
23 #if WITH_KERNEL_VM
24 #include <kernel/vm.h>
25 #endif
26
27 static int cmd_display_mem(int argc, const console_cmd_args *argv);
28 static int cmd_modify_mem(int argc, const console_cmd_args *argv);
29 static int cmd_fill_mem(int argc, const console_cmd_args *argv);
30 static int cmd_reset(int argc, const console_cmd_args *argv);
31 static int cmd_memtest(int argc, const console_cmd_args *argv);
32 static int cmd_copy_mem(int argc, const console_cmd_args *argv);
33 static int cmd_chain(int argc, const console_cmd_args *argv);
34 static int cmd_sleep(int argc, const console_cmd_args *argv);
35 static int cmd_crash(int argc, const console_cmd_args *argv);
36 static int cmd_stackstomp(int argc, const console_cmd_args *argv);
37
38 STATIC_COMMAND_START
39 #if LK_DEBUGLEVEL > 0
40 STATIC_COMMAND_MASKED("dw", "display memory in words", &cmd_display_mem, CMD_AVAIL_ALWAYS)
41 STATIC_COMMAND_MASKED("dh", "display memory in halfwords", &cmd_display_mem, CMD_AVAIL_ALWAYS)
42 STATIC_COMMAND_MASKED("db", "display memory in bytes", &cmd_display_mem, CMD_AVAIL_ALWAYS)
43 STATIC_COMMAND_MASKED("mw", "modify word of memory", &cmd_modify_mem, CMD_AVAIL_ALWAYS)
44 STATIC_COMMAND_MASKED("mh", "modify halfword of memory", &cmd_modify_mem, CMD_AVAIL_ALWAYS)
45 STATIC_COMMAND_MASKED("mb", "modify byte of memory", &cmd_modify_mem, CMD_AVAIL_ALWAYS)
46 STATIC_COMMAND_MASKED("fw", "fill range of memory by word", &cmd_fill_mem, CMD_AVAIL_ALWAYS)
47 STATIC_COMMAND_MASKED("fh", "fill range of memory by halfword", &cmd_fill_mem, CMD_AVAIL_ALWAYS)
48 STATIC_COMMAND_MASKED("fb", "fill range of memory by byte", &cmd_fill_mem, CMD_AVAIL_ALWAYS)
49 STATIC_COMMAND_MASKED("mc", "copy a range of memory", &cmd_copy_mem, CMD_AVAIL_ALWAYS)
50 STATIC_COMMAND("crash", "intentionally crash", &cmd_crash)
51 STATIC_COMMAND("stackstomp", "intentionally overrun the stack", &cmd_stackstomp)
52 #endif
53 #if LK_DEBUGLEVEL > 1
54 STATIC_COMMAND("mtest", "simple memory test", &cmd_memtest)
55 #endif
56 STATIC_COMMAND("chain", "chain load another binary", &cmd_chain)
57 STATIC_COMMAND("sleep", "sleep number of seconds", &cmd_sleep)
58 STATIC_COMMAND("sleepm", "sleep number of milliseconds", &cmd_sleep)
59 STATIC_COMMAND_END(mem);
60
cmd_display_mem(int argc,const console_cmd_args * argv)61 static int cmd_display_mem(int argc, const console_cmd_args *argv) {
62 /* save the last address and len so we can continue where we left off */
63 static unsigned long address;
64 static size_t len;
65
66 if (argc < 3 && len == 0) {
67 printf("not enough arguments\n");
68 printf("%s [-l] [-b] [address] [length]\n", argv[0].str);
69 return -1;
70 }
71
72 int size;
73 if (strcmp(argv[0].str, "dw") == 0) {
74 size = 4;
75 } else if (strcmp(argv[0].str, "dh") == 0) {
76 size = 2;
77 } else {
78 size = 1;
79 }
80
81 uint byte_order = BYTE_ORDER;
82 int argindex = 1;
83 bool read_address = false;
84 while (argc > argindex) {
85 if (!strcmp(argv[argindex].str, "-l")) {
86 byte_order = LITTLE_ENDIAN;
87 } else if (!strcmp(argv[argindex].str, "-b")) {
88 byte_order = BIG_ENDIAN;
89 } else if (!read_address) {
90 address = argv[argindex].u;
91 read_address = true;
92 } else {
93 len = argv[argindex].u;
94 }
95
96 argindex++;
97 }
98
99 unsigned long stop = address + len;
100 int count = 0;
101
102 if ((address & (size - 1)) != 0) {
103 printf("unaligned address, cannot display\n");
104 return -1;
105 }
106
107 #if WITH_KERNEL_VM
108 /* preflight the start address to see if it's mapped */
109 if (vaddr_to_paddr((void *)address) == 0) {
110 printf("ERROR: address 0x%lx is unmapped\n", address);
111 return -1;
112 }
113 #endif
114
115 for ( ; address < stop; address += size) {
116 if (count == 0)
117 printf("0x%08lx: ", address);
118 switch (size) {
119 case 4: {
120 uint32_t val = (byte_order != BYTE_ORDER) ?
121 SWAP_32(*(uint32_t *)address) :
122 *(uint32_t *)address;
123 printf("%08x ", val);
124 break;
125 }
126 case 2: {
127 uint16_t val = (byte_order != BYTE_ORDER) ?
128 SWAP_16(*(uint16_t *)address) :
129 *(uint16_t *)address;
130 printf("%04hx ", val);
131 break;
132 }
133 case 1:
134 printf("%02hhx ", *(uint8_t *)address);
135 break;
136 }
137 count += size;
138 if (count == 16) {
139 printf("\n");
140 count = 0;
141 }
142 }
143
144 if (count != 0)
145 printf("\n");
146
147 return 0;
148 }
149
cmd_modify_mem(int argc,const console_cmd_args * argv)150 static int cmd_modify_mem(int argc, const console_cmd_args *argv) {
151 int size;
152
153 if (argc < 3) {
154 printf("not enough arguments\n");
155 printf("%s <address> <val>\n", argv[0].str);
156 return -1;
157 }
158
159 if (strcmp(argv[0].str, "mw") == 0) {
160 size = 4;
161 } else if (strcmp(argv[0].str, "mh") == 0) {
162 size = 2;
163 } else {
164 size = 1;
165 }
166
167 unsigned long address = argv[1].u;
168 unsigned int val = argv[2].u;
169
170 if ((address & (size - 1)) != 0) {
171 printf("unaligned address, cannot modify\n");
172 return -1;
173 }
174
175 switch (size) {
176 case 4:
177 *(uint32_t *)address = (uint32_t)val;
178 break;
179 case 2:
180 *(uint16_t *)address = (uint16_t)val;
181 break;
182 case 1:
183 *(uint8_t *)address = (uint8_t)val;
184 break;
185 }
186
187 return 0;
188 }
189
cmd_fill_mem(int argc,const console_cmd_args * argv)190 static int cmd_fill_mem(int argc, const console_cmd_args *argv) {
191 int size;
192
193 if (argc < 4) {
194 printf("not enough arguments\n");
195 printf("%s <address> <len> <val>\n", argv[0].str);
196 return -1;
197 }
198
199 if (strcmp(argv[0].str, "fw") == 0) {
200 size = 4;
201 } else if (strcmp(argv[0].str, "fh") == 0) {
202 size = 2;
203 } else {
204 size = 1;
205 }
206
207 unsigned long address = argv[1].u;
208 unsigned long len = argv[2].u;
209 unsigned long stop = address + len;
210 unsigned int val = argv[3].u;
211
212 if ((address & (size - 1)) != 0) {
213 printf("unaligned address, cannot modify\n");
214 return -1;
215 }
216
217 for ( ; address < stop; address += size) {
218 switch (size) {
219 case 4:
220 *(uint32_t *)address = (uint32_t)val;
221 break;
222 case 2:
223 *(uint16_t *)address = (uint16_t)val;
224 break;
225 case 1:
226 *(uint8_t *)address = (uint8_t)val;
227 break;
228 }
229 }
230
231 return 0;
232 }
233
cmd_copy_mem(int argc,const console_cmd_args * argv)234 static int cmd_copy_mem(int argc, const console_cmd_args *argv) {
235 if (argc < 4) {
236 printf("not enough arguments\n");
237 printf("%s <source address> <target address> <len>\n", argv[0].str);
238 return -1;
239 }
240
241 addr_t source = argv[1].u;
242 addr_t target = argv[2].u;
243 size_t len = argv[3].u;
244
245 memcpy((void *)target, (const void *)source, len);
246
247 return 0;
248 }
249
cmd_memtest(int argc,const console_cmd_args * argv)250 static int cmd_memtest(int argc, const console_cmd_args *argv) {
251 if (argc < 3) {
252 printf("not enough arguments\n");
253 printf("%s <base> <len>\n", argv[0].str);
254 return -1;
255 }
256
257 uint32_t *ptr;
258 size_t len;
259
260 ptr = (uint32_t *)argv[1].u;
261 len = (size_t)argv[2].u;
262
263 size_t i;
264 // write out
265 printf("writing first pass...");
266 for (i = 0; i < len / 4; i++) {
267 ptr[i] = i;
268 }
269 printf("done\n");
270
271 // verify
272 printf("verifying...");
273 for (i = 0; i < len / 4; i++) {
274 if (ptr[i] != i)
275 printf("error at %p\n", &ptr[i]);
276 }
277 printf("done\n");
278
279 return 0;
280 }
281
cmd_chain(int argc,const console_cmd_args * argv)282 static int cmd_chain(int argc, const console_cmd_args *argv) {
283 if (argc < 2) {
284 printf("not enough arguments\n");
285 printf("%s <address>\n", argv[0].str);
286 return -1;
287 }
288
289 arch_chain_load(argv[1].p, 0, 0, 0, 0);
290
291 return 0;
292 }
293
cmd_sleep(int argc,const console_cmd_args * argv)294 static int cmd_sleep(int argc, const console_cmd_args *argv) {
295 lk_time_t t = 1000; /* default to 1 second */
296
297 if (argc >= 2) {
298 t = argv[1].u;
299 if (!strcmp(argv[0].str, "sleep"))
300 t *= 1000;
301 }
302
303 thread_sleep(t);
304
305 return 0;
306 }
307
cmd_crash(int argc,const console_cmd_args * argv)308 static int cmd_crash(int argc, const console_cmd_args *argv) {
309 /* should crash */
310 volatile uint32_t *ptr = (void *)1;
311 *ptr = 1;
312
313 /* if it didn't, panic the system */
314 panic("crash");
315
316 return 0;
317 }
318
cmd_stackstomp(int argc,const console_cmd_args * argv)319 static int cmd_stackstomp(int argc, const console_cmd_args *argv) {
320 for (size_t i = 0; i < DEFAULT_STACK_SIZE * 2; i++) {
321 uint8_t death[i];
322
323 memset(death, 0xaa, i);
324 thread_sleep(1);
325 }
326
327 printf("survived.\n");
328
329 return 0;
330 }
331
332
333