GUI: Fix Tomato RAF theme for all builds. Compilation typo.
[tomato.git] / release / src-rt-6.x.4708 / cfe / cfe / ui / ui_examcmds.c
blobd80904260ad905bf7ff83c001920f3867a7b3c9c
1 /* *********************************************************************
2 * Broadcom Common Firmware Environment (CFE)
3 *
4 * Memory dump commands File: ui_examcmds.c
5 *
6 * UI functions for examining data in various ways
7 *
8 * Author: Mitch Lichtenberg (mpl@broadcom.com)
9 *
10 *********************************************************************
12 * Copyright 2000,2001,2002,2003
13 * Broadcom Corporation. All rights reserved.
15 * This software is furnished under license and may be used and
16 * copied only in accordance with the following terms and
17 * conditions. Subject to these conditions, you may download,
18 * copy, install, use, modify and distribute modified or unmodified
19 * copies of this software in source and/or binary form. No title
20 * or ownership is transferred hereby.
22 * 1) Any source code used, modified or distributed must reproduce
23 * and retain this copyright notice and list of conditions
24 * as they appear in the source file.
26 * 2) No right is granted to use any trade name, trademark, or
27 * logo of Broadcom Corporation. The "Broadcom Corporation"
28 * name may not be used to endorse or promote products derived
29 * from this software without the prior written permission of
30 * Broadcom Corporation.
32 * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
33 * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
34 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
35 * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
36 * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
37 * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
38 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
39 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
40 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
41 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
42 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
43 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
44 * THE POSSIBILITY OF SUCH DAMAGE.
45 ********************************************************************* */
49 #include "lib_types.h"
50 #include "lib_string.h"
51 #include "lib_queue.h"
52 #include "lib_malloc.h"
53 #include "lib_printf.h"
55 #include "cfe_error.h"
56 #include "cfe_console.h"
58 #include "ui_command.h"
59 #include "cfe.h"
60 #include "disasm.h"
62 #include "addrspace.h"
63 #include "exchandler.h"
66 static int ui_cmd_memdump(ui_cmdline_t *cmd,int argc,char *argv[]);
67 static int ui_cmd_memedit(ui_cmdline_t *cmd,int argc,char *argv[]);
68 static int ui_cmd_memfill(ui_cmdline_t *cmd,int argc,char *argv[]);
69 static int ui_cmd_disasm(ui_cmdline_t *cmd,int argc,char *argv[]);
71 #ifdef __long64
72 #define XTOI(x) xtoq(x)
73 #else
74 #define XTOI(x) xtoi(x)
75 #endif
77 int ui_init_examcmds(void);
80 #define ATYPE_SIZE_NONE 0
81 #define ATYPE_SIZE_BYTE 1
82 #define ATYPE_SIZE_HALF 2
83 #define ATYPE_SIZE_WORD 4
84 #define ATYPE_SIZE_QUAD 8
85 #define ATYPE_SIZE_MASK 0x0F
87 #define ATYPE_TYPE_NONE 0
88 #define ATYPE_TYPE_PHYS 0x10
89 #define ATYPE_TYPE_KERN 0x20
90 #define ATYPE_TYPE_MASK 0xF0
92 static long prev_addr = 0; /* initialized below in ui_init_examcmds */
93 static int prev_length = 256;
94 static int prev_dlength = 16;
95 static int prev_wtype = ATYPE_SIZE_WORD | ATYPE_TYPE_KERN;
97 static int getaddrargs(ui_cmdline_t *cmd,int *curtype,long *addr,int *length)
99 int atype = *curtype;
100 long newaddr;
101 int newlen;
102 char *x;
103 long wlen;
105 if (cmd_sw_isset(cmd,"-b")) {
106 atype &= ~ATYPE_SIZE_MASK;
107 atype |= ATYPE_SIZE_BYTE;
109 else if (cmd_sw_isset(cmd,"-h")) {
110 atype &= ~ATYPE_SIZE_MASK;
111 atype |= ATYPE_SIZE_HALF;
113 else if (cmd_sw_isset(cmd,"-w")) {
114 atype &= ~ATYPE_SIZE_MASK;
115 atype |= ATYPE_SIZE_WORD;
117 else if (cmd_sw_isset(cmd,"-q")) {
118 atype &= ~ATYPE_SIZE_MASK;
119 atype |= ATYPE_SIZE_QUAD;
122 wlen = atype & ATYPE_SIZE_MASK;
123 if (wlen == 0) wlen = 1; /* bytes are the default */
125 if (cmd_sw_isset(cmd,"-p")) {
126 atype &= ~ATYPE_TYPE_MASK;
127 atype |= ATYPE_TYPE_PHYS;
129 else if (cmd_sw_isset(cmd,"-v")) {
130 atype &= ~ATYPE_TYPE_MASK;
131 atype |= ATYPE_TYPE_KERN;
134 *curtype = atype;
136 if (addr) {
137 x = cmd_getarg(cmd,0);
138 if (x) {
139 if (strcmp(x,".") == 0) newaddr = *addr;
140 else {
142 * hold on to your lunch, this is really, really bad!
143 * Make 64-bit addresses expressed as 8-digit numbers
144 * sign extend automagically. Saves typing, but is very
145 * gross.
147 int longaddr = 0;
148 longaddr = strlen(x);
149 if (memcmp(x,"0x",2) == 0) longaddr -= 2;
150 longaddr = (longaddr > 8) ? 1 : 0;
152 if (longaddr) newaddr = (long) xtoq(x);
153 else newaddr = (long) xtoi(x);
155 *addr = newaddr & ~(wlen - 1); /* align to natural boundary */
159 if (length) {
160 x = cmd_getarg(cmd,1);
161 if (x) {
162 newlen = (long) xtoi(x);
163 *length = newlen;
167 return 0;
171 static int stuffmem(long addr,int wlen,char *tail)
173 char *tok;
174 int count = 0;
175 uint8_t b;
176 uint16_t h;
177 uint32_t w;
178 uint64_t q;
179 int res = 0;
181 addr &= ~(wlen-1);
183 while ((tok = gettoken(&tail))) {
184 switch (wlen) {
185 default:
186 case 1:
187 b = (uint8_t) xtoq(tok);
188 if ((res = mem_poke(addr, b, MEM_BYTE))) {
189 /*Did not edit*/
190 return res;
192 break;
193 case 2:
194 h = (uint16_t) xtoq(tok);
195 if ((res = mem_poke(addr, h, MEM_HALFWORD))) {
196 /*Did not edit*/
197 return res;
199 break;
200 case 4:
201 w = (uint32_t) xtoq(tok);
202 if ((res = mem_poke(addr, w, MEM_WORD))) {
203 /*Did not edit*/
204 return res;
206 break;
207 case 8:
208 q = (uint64_t) xtoq(tok);
209 if ((res = mem_poke(addr, q, MEM_QUADWORD))) {
210 /*Did not edit*/
211 return res;
213 break;
216 addr += wlen;
217 count++;
220 return count;
223 static int dumpmem(long addr,long dispaddr,int length,int wlen)
225 int idx,x;
226 uint8_t b;
227 uint16_t h;
228 uint32_t w;
229 uint64_t q;
230 int res = 0;
233 * The reason we save the line in this union is to provide the
234 * property that the dump command will only touch the
235 * memory once. This might be useful when looking at
236 * device registers.
239 union {
240 uint8_t bytes[16];
241 uint16_t halves[8];
242 uint32_t words[4];
243 uint64_t quads[2];
244 } line;
246 addr &= ~(wlen-1);
248 for (idx = 0; idx < length; idx += 16) {
249 xprintf("%P%c ",dispaddr+idx,(dispaddr != addr) ? '%' : ':');
250 switch (wlen) {
251 default:
252 case 1:
253 for (x = 0; x < 16; x++) {
254 if (idx+x < length) {
255 if ((res = mem_peek(&b, (addr+idx+x), MEM_BYTE))) {
256 return res;
258 line.bytes[x] = b;
259 xprintf("%02X ",b);
261 else {
262 xprintf(" ");
265 break;
266 case 2:
267 for (x = 0; x < 16; x+=2) {
268 if (idx+x < length) {
269 if ((res = mem_peek(&h, (addr+idx+x), MEM_HALFWORD))) {
270 return res;
272 line.halves[x/2] = h;
273 xprintf("%04X ",h);
275 else {
276 xprintf(" ");
279 break;
280 case 4:
281 for (x = 0; x < 16; x+=4) {
282 if (idx+x < length) {
284 if ((res = mem_peek(&w , (addr+idx+x), MEM_WORD))) {
285 return res;
287 line.words[x/4] = w;
288 xprintf("%08X ",w);
290 else {
291 xprintf(" ");
294 break;
295 case 8:
296 for (x = 0; x < 16; x+=8) {
297 if (idx+x < length) {
298 if ((res = mem_peek(&q, (addr+idx+x), MEM_QUADWORD))) {
299 return res;
301 line.quads[x/8] = q;
302 xprintf("%016llX ",q);
304 else {
305 xprintf(" ");
308 break;
311 xprintf(" ");
312 for (x = 0; x < 16; x++) {
313 if (idx+x < length) {
314 b = line.bytes[x];
315 if ((b < 32) || (b > 127)) xprintf(".");
316 else xprintf("%c",b);
318 else {
319 xprintf(" ");
322 xprintf("\n");
325 return 0;
328 static int ui_cmd_memedit(ui_cmdline_t *cmd,int argc,char *argv[])
330 uint8_t b;
331 uint16_t h;
332 uint32_t w;
333 uint64_t q;
335 long addr;
336 char *vtext;
337 int wlen;
338 int count;
339 int idx = 1;
340 int stuffed = 0;
341 int res = 0;
343 getaddrargs(cmd,&prev_wtype,&prev_addr,NULL);
345 wlen = prev_wtype & ATYPE_SIZE_MASK;
347 vtext = cmd_getarg(cmd,idx++);
349 addr = prev_addr;
351 while (vtext) {
352 count = stuffmem(addr,wlen,vtext);
353 if (count < 0) {
354 ui_showerror(count,"Could not modify memory");
355 return count; /* error */
357 addr += count*wlen;
358 prev_addr += count*wlen;
359 stuffed += count;
360 vtext = cmd_getarg(cmd,idx++);
363 if (stuffed == 0) {
364 char line[256];
365 char prompt[32];
367 xprintf("Type '.' to exit, '-' to back up, '=' to dump memory.\n");
368 for (;;) {
370 addr = prev_addr;
371 if ((prev_wtype & ATYPE_TYPE_MASK) == ATYPE_TYPE_PHYS) {
372 addr = UNCADDR(addr);
375 xprintf("%P%c ",prev_addr,(addr != prev_addr) ? '%' : ':');
377 switch (wlen) {
378 default:
379 case 1:
380 if ((res = mem_peek(&b, addr, MEM_BYTE))) {
381 return res;
383 xsprintf(prompt,"[%02X]: ", b);
384 break;
385 case 2:
386 if ((res = mem_peek(&h, addr, MEM_HALFWORD))) {
387 return res;
389 xsprintf(prompt,"[%04X]: ",h);
390 break;
391 case 4:
392 if ((res = mem_peek(&w, addr, MEM_WORD))) {
393 return res;
395 xsprintf(prompt,"[%08X]: ",w);
396 break;
397 case 8:
398 if ((res = mem_peek(&q, addr, MEM_QUADWORD))) {
399 return res;
401 xsprintf(prompt,"[%016llX]: ",q);
402 break;
405 console_readline(prompt,line,sizeof(line));
406 if (line[0] == '-') {
407 prev_addr -= wlen;
408 continue;
410 if (line[0] == '=') {
411 dumpmem(prev_addr,prev_addr,16,wlen);
412 continue;
414 if (line[0] == '.') {
415 break;
417 if (line[0] == '\0') {
418 prev_addr += wlen;
419 continue;
421 count = stuffmem(addr,wlen,line);
422 if (count < 0) return count;
423 if (count == 0) break;
424 prev_addr += count*wlen;
428 return 0;
431 static int ui_cmd_memfill(ui_cmdline_t *cmd,int argc,char *argv[])
433 long addr;
434 char *atext;
435 int wlen;
436 int idx = 2;
437 int len;
438 uint64_t pattern;
439 uint8_t *b_ptr;
440 uint16_t *h_ptr;
441 uint32_t *w_ptr;
442 uint64_t *q_ptr;
443 int res;
445 getaddrargs(cmd,&prev_wtype,&prev_addr,&len);
447 atext = cmd_getarg(cmd,idx++);
448 if (!atext) return ui_showusage(cmd);
449 pattern = xtoq(atext);
451 addr = prev_addr;
453 if ((prev_wtype & ATYPE_TYPE_MASK) == ATYPE_TYPE_PHYS) {
454 addr = UNCADDR(addr);
457 wlen = prev_wtype & ATYPE_SIZE_MASK;
459 switch (wlen) {
460 case 1:
461 b_ptr = (uint8_t *) addr;
462 while (len > 0) {
463 if ((res = mem_poke( ((long)(b_ptr)), pattern, MEM_BYTE))) {
464 /*Did not edit*/
465 return 0;
467 b_ptr++;
468 len--;
470 break;
471 case 2:
472 h_ptr = (uint16_t *) addr;
473 while (len > 0) {
474 if ((res = mem_poke( ((long)(h_ptr)), pattern, MEM_HALFWORD))) {
475 return 0;
477 h_ptr++;
478 len--;
480 break;
481 case 4:
482 w_ptr = (uint32_t *) addr;
483 while (len > 0) {
484 if ((res = mem_poke( ((long)(w_ptr)), pattern, MEM_WORD))) {
485 return -1;
487 w_ptr++;
488 len--;
490 break;
491 case 8:
492 q_ptr = (uint64_t *) addr;
493 while (len > 0) {
494 if ((res = mem_poke( ((long)(q_ptr)), pattern, MEM_QUADWORD))) {
495 return 0;
497 q_ptr++;
498 len--;
500 break;
503 return 0;
507 #define FILL(ptr,len,pattern) printf("Pattern: %016llX\n",pattern); \
508 for (idx = 0; idx < len; idx++) ptr[idx] = pattern
509 #define CHECK(ptr,len,pattern) for (idx = 0; idx < len; idx++) { \
510 if (ptr[idx]!=pattern) {printf("Mismatch at %016llX: Expected %016llX got %016llX", \
511 (uint64_t) (uintptr_t) &(ptr[idx]),pattern,ptr[idx]); \
512 error = 1; loopmode = 0;break;} \
515 #define MEMTEST(ptr,len,pattern) if (!error) { FILL(ptr,len,pattern) ; CHECK(ptr,len,pattern); }
517 static int ui_cmd_memtest(ui_cmdline_t *cmd,int argc,char *argv[])
519 long addr = 0;
520 int len = 0;
521 int wtype = 0;
522 int wlen;
523 int idx = 0;
524 uint64_t *ptr;
525 int error = 0;
526 int loopmode = 0;
527 int pass =0;
529 getaddrargs(cmd,&wtype,&addr,&len);
531 wlen = 8;
532 addr &= ~(wlen-1);
534 if ((prev_wtype & ATYPE_TYPE_MASK) == ATYPE_TYPE_PHYS) {
535 addr = UNCADDR(addr);
538 if (cmd_sw_isset(cmd,"-loop")) {
539 loopmode = 1;
542 len /= wlen;
544 ptr = (uint64_t *) addr;
545 pass = 0;
546 for (;;) {
547 if (loopmode) {
548 printf("Pass %d\n",pass);
549 if (console_status()) break;
551 MEMTEST(ptr,len,(idx*8));
552 MEMTEST(ptr,len, 0);
553 MEMTEST(ptr,len,0xFFFFFFFFFFFFFFFFLL);
554 MEMTEST(ptr,len,0x5555555555555555LL);
555 MEMTEST(ptr,len,0xAAAAAAAAAAAAAAAALL);
556 MEMTEST(ptr,len,0xFF00FF00FF00FF00LL);
557 MEMTEST(ptr,len,0x00FF00FF00FF00FFLL);
558 if (!loopmode) break;
559 pass++;
562 return 0;
565 static int ui_cmd_memdump(ui_cmdline_t *cmd,int argc,char *argv[])
567 long addr;
568 int res;
570 getaddrargs(cmd,&prev_wtype,&prev_addr,&prev_length);
572 addr = prev_addr;
573 if ((prev_wtype & ATYPE_TYPE_MASK) == ATYPE_TYPE_PHYS) {
574 addr = UNCADDR(addr);
577 res = dumpmem(addr,
578 prev_addr,
579 prev_length,
580 prev_wtype & ATYPE_SIZE_MASK);
582 if (res < 0) {
583 ui_showerror(res,"Could not display memory");
585 else {
586 prev_addr += prev_length;
589 return res;
592 static int ui_cmd_disasm(ui_cmdline_t *cmd,int argc,char *argv[])
594 long addr;
595 char buf[512];
596 int idx;
597 uint32_t inst;
598 int res;
600 getaddrargs(cmd,&prev_wtype,&prev_addr,&prev_dlength);
602 prev_addr &= ~3;
604 addr = prev_addr;
605 if ((prev_wtype & ATYPE_TYPE_MASK) == ATYPE_TYPE_PHYS) {
606 addr = UNCADDR(addr);
609 for (idx = 0; idx < prev_dlength; idx++) {
610 if ((res = mem_peek(&inst, addr, MEM_WORD))) {
611 ui_showerror(res,"Could not disassemble memory");
612 return res;
614 disasm_inst(buf,sizeof(buf),inst,(uint64_t) prev_addr);
615 xprintf("%P%c %08x %s\n",prev_addr,(addr != prev_addr) ? '%' : ':',inst,buf);
616 addr += 4;
617 prev_addr += 4;
620 return 0;
623 int ui_init_examcmds(void)
625 cmd_addcmd("u",
626 ui_cmd_disasm,
627 NULL,
628 "Disassemble instructions.",
629 "u [addr [length]]\n\n"
630 "This command disassembles instructions at the specified address.\n"
631 "CFE will display standard register names and symbolic names for\n"
632 "certain CP0 registers. The 'u' command remembers the last address\n"
633 "that was disassembled so you can enter 'u' again with no parameters\n"
634 "to continue a previous request.\n",
635 "-p;Address is an uncached physical address|"
636 "-v;Address is a kernel virtual address");
639 cmd_addcmd("d",
640 ui_cmd_memdump,
641 NULL,
642 "Dump memory.",
643 "d [-b|-h|-w|-q] [addr [length]]\n\n"
644 "This command displays data from memory as bytes, halfwords, words,\n"
645 "or quadwords. ASCII text, if present, will appear to the right of\n"
646 "the hex data. The dump command remembers the previous word size,\n"
647 "dump length and last displayed address, so you can enter 'd' again\n"
648 "to continue a previous dump request.",
649 "-b;Dump memory as bytes|"
650 "-h;Dump memory as halfwords (16-bits)|"
651 "-w;Dump memory as words (32-bits)|"
652 "-q;Dump memory as quadwords (64-bits)|"
653 "-p;Address is an uncached physical address|"
654 "-v;Address is a kernel virtual address");
657 cmd_addcmd("e",
658 ui_cmd_memedit,
659 NULL,
660 "Modify contents of memory.",
661 "e [-b|-h|-w|-q] [addr [data...]]\n\n"
662 "This command modifies the contents of memory. If you do not specify\n"
663 "data on the command line, CFE will prompt for it. When prompting for\n"
664 "data you may enter '-' to back up, '=' to dump memory at the current\n"
665 "location, or '.' to exit edit mode.",
666 "-b;Edit memory as bytes|"
667 "-h;Edit memory as halfwords (16-bits)|"
668 "-w;Edit memory as words (32-bits)|"
669 "-q;Edit memory as quadwords (64-bits)|"
670 "-p;Address is an uncached physical address|"
671 "-v;Address is a kernel virtual address");
673 cmd_addcmd("f",
674 ui_cmd_memfill,
675 NULL,
676 "Fill contents of memory.",
677 "f [-b|-h|-w|-q] addr length pattern\n\n"
678 "This command modifies the contents of memory. You can specify the\n"
679 "starting address, length, and pattern of data to fill (in hex)\n",
680 "-b;Edit memory as bytes|"
681 "-h;Edit memory as halfwords (16-bits)|"
682 "-w;Edit memory as words (32-bits)|"
683 "-q;Edit memory as quadwords (64-bits)|"
684 "-p;Address is an uncached physical address|"
685 "-v;Address is a kernel virtual address");
687 cmd_addcmd("memtest",
688 ui_cmd_memtest,
689 NULL,
690 "Test memory.",
691 "memtest [options] addr length\n\n"
692 "This command tests memory. It is a very crude test, so don't\n"
693 "rely on it for anything really important. Addr and length are in hex\n",
694 "-p;Address is an uncached physical address|"
695 "-v;Address is a kernel virtual address|"
696 "-loop;Loop till keypress");
699 prev_addr = KERNADDR(0);
701 return 0;