1 /* *********************************************************************
2 * Broadcom Common Firmware Environment (CFE)
4 * Memory dump commands File: ui_examcmds.c
6 * UI functions for examining data in various ways
8 * Author: Mitch Lichtenberg (mpl@broadcom.com)
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"
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
[]);
72 #define XTOI(x) xtoq(x)
74 #define XTOI(x) xtoi(x)
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
)
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
;
137 x
= cmd_getarg(cmd
,0);
139 if (strcmp(x
,".") == 0) newaddr
= *addr
;
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
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 */
160 x
= cmd_getarg(cmd
,1);
162 newlen
= (long) xtoi(x
);
171 static int stuffmem(long addr
,int wlen
,char *tail
)
183 while ((tok
= gettoken(&tail
))) {
187 b
= (uint8_t) xtoq(tok
);
188 if ((res
= mem_poke(addr
, b
, MEM_BYTE
))) {
194 h
= (uint16_t) xtoq(tok
);
195 if ((res
= mem_poke(addr
, h
, MEM_HALFWORD
))) {
201 w
= (uint32_t) xtoq(tok
);
202 if ((res
= mem_poke(addr
, w
, MEM_WORD
))) {
208 q
= (uint64_t) xtoq(tok
);
209 if ((res
= mem_poke(addr
, q
, MEM_QUADWORD
))) {
223 static int dumpmem(long addr
,long dispaddr
,int length
,int wlen
)
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
248 for (idx
= 0; idx
< length
; idx
+= 16) {
249 xprintf("%P%c ",dispaddr
+idx
,(dispaddr
!= addr
) ? '%' : ':');
253 for (x
= 0; x
< 16; x
++) {
254 if (idx
+x
< length
) {
255 if ((res
= mem_peek(&b
, (addr
+idx
+x
), MEM_BYTE
))) {
267 for (x
= 0; x
< 16; x
+=2) {
268 if (idx
+x
< length
) {
269 if ((res
= mem_peek(&h
, (addr
+idx
+x
), MEM_HALFWORD
))) {
272 line
.halves
[x
/2] = h
;
281 for (x
= 0; x
< 16; x
+=4) {
282 if (idx
+x
< length
) {
284 if ((res
= mem_peek(&w
, (addr
+idx
+x
), MEM_WORD
))) {
296 for (x
= 0; x
< 16; x
+=8) {
297 if (idx
+x
< length
) {
298 if ((res
= mem_peek(&q
, (addr
+idx
+x
), MEM_QUADWORD
))) {
302 xprintf("%016llX ",q
);
312 for (x
= 0; x
< 16; x
++) {
313 if (idx
+x
< length
) {
315 if ((b
< 32) || (b
> 127)) xprintf(".");
316 else xprintf("%c",b
);
328 static int ui_cmd_memedit(ui_cmdline_t
*cmd
,int argc
,char *argv
[])
343 getaddrargs(cmd
,&prev_wtype
,&prev_addr
,NULL
);
345 wlen
= prev_wtype
& ATYPE_SIZE_MASK
;
347 vtext
= cmd_getarg(cmd
,idx
++);
352 count
= stuffmem(addr
,wlen
,vtext
);
354 ui_showerror(count
,"Could not modify memory");
355 return count
; /* error */
358 prev_addr
+= count
*wlen
;
360 vtext
= cmd_getarg(cmd
,idx
++);
367 xprintf("Type '.' to exit, '-' to back up, '=' to dump memory.\n");
371 if ((prev_wtype
& ATYPE_TYPE_MASK
) == ATYPE_TYPE_PHYS
) {
372 addr
= UNCADDR(addr
);
375 xprintf("%P%c ",prev_addr
,(addr
!= prev_addr
) ? '%' : ':');
380 if ((res
= mem_peek(&b
, addr
, MEM_BYTE
))) {
383 xsprintf(prompt
,"[%02X]: ", b
);
386 if ((res
= mem_peek(&h
, addr
, MEM_HALFWORD
))) {
389 xsprintf(prompt
,"[%04X]: ",h
);
392 if ((res
= mem_peek(&w
, addr
, MEM_WORD
))) {
395 xsprintf(prompt
,"[%08X]: ",w
);
398 if ((res
= mem_peek(&q
, addr
, MEM_QUADWORD
))) {
401 xsprintf(prompt
,"[%016llX]: ",q
);
405 console_readline(prompt
,line
,sizeof(line
));
406 if (line
[0] == '-') {
410 if (line
[0] == '=') {
411 dumpmem(prev_addr
,prev_addr
,16,wlen
);
414 if (line
[0] == '.') {
417 if (line
[0] == '\0') {
421 count
= stuffmem(addr
,wlen
,line
);
422 if (count
< 0) return count
;
423 if (count
== 0) break;
424 prev_addr
+= count
*wlen
;
431 static int ui_cmd_memfill(ui_cmdline_t
*cmd
,int argc
,char *argv
[])
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
);
453 if ((prev_wtype
& ATYPE_TYPE_MASK
) == ATYPE_TYPE_PHYS
) {
454 addr
= UNCADDR(addr
);
457 wlen
= prev_wtype
& ATYPE_SIZE_MASK
;
461 b_ptr
= (uint8_t *) addr
;
463 if ((res
= mem_poke( ((long)(b_ptr
)), pattern
, MEM_BYTE
))) {
472 h_ptr
= (uint16_t *) addr
;
474 if ((res
= mem_poke( ((long)(h_ptr
)), pattern
, MEM_HALFWORD
))) {
482 w_ptr
= (uint32_t *) addr
;
484 if ((res
= mem_poke( ((long)(w_ptr
)), pattern
, MEM_WORD
))) {
492 q_ptr
= (uint64_t *) addr
;
494 if ((res
= mem_poke( ((long)(q_ptr
)), pattern
, MEM_QUADWORD
))) {
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
[])
529 getaddrargs(cmd
,&wtype
,&addr
,&len
);
534 if ((prev_wtype
& ATYPE_TYPE_MASK
) == ATYPE_TYPE_PHYS
) {
535 addr
= UNCADDR(addr
);
538 if (cmd_sw_isset(cmd
,"-loop")) {
544 ptr
= (uint64_t *) addr
;
548 printf("Pass %d\n",pass
);
549 if (console_status()) break;
551 MEMTEST(ptr
,len
,(idx
*8));
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;
565 static int ui_cmd_memdump(ui_cmdline_t
*cmd
,int argc
,char *argv
[])
570 getaddrargs(cmd
,&prev_wtype
,&prev_addr
,&prev_length
);
573 if ((prev_wtype
& ATYPE_TYPE_MASK
) == ATYPE_TYPE_PHYS
) {
574 addr
= UNCADDR(addr
);
580 prev_wtype
& ATYPE_SIZE_MASK
);
583 ui_showerror(res
,"Could not display memory");
586 prev_addr
+= prev_length
;
592 static int ui_cmd_disasm(ui_cmdline_t
*cmd
,int argc
,char *argv
[])
600 getaddrargs(cmd
,&prev_wtype
,&prev_addr
,&prev_dlength
);
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");
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
);
623 int ui_init_examcmds(void)
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");
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");
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");
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",
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);