]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - common/cmd_bedbug.c
* Code cleanup:
[karo-tx-uboot.git] / common / cmd_bedbug.c
1 /*
2  * BedBug Functions
3  */
4
5 #include <common.h>
6 #include <command.h>
7 #include <linux/ctype.h>
8 #include <net.h>
9 #include <bedbug/type.h>
10 #include <bedbug/bedbug.h>
11 #include <bedbug/regs.h>
12 #include <bedbug/ppc.h>
13
14 #if (CONFIG_COMMANDS & CFG_CMD_BEDBUG)
15
16 #ifndef MAX
17 #define MAX(a,b) ((a) > (b) ? (a) : (b))
18 #endif
19
20 extern void show_regs __P((struct pt_regs*));
21 extern int  run_command __P((const char*, int));
22 extern char console_buffer[];
23
24 ulong         dis_last_addr = 0;        /* Last address disassembled   */
25 ulong         dis_last_len = 20;        /* Default disassembler length */
26 CPU_DEBUG_CTX bug_ctx;                  /* Bedbug context structure    */
27
28 \f
29 /* ======================================================================
30  * U-Boot's puts function does not append a newline, so the bedbug stuff
31  * will use this for the output of the dis/assembler.
32  * ====================================================================== */
33
34 int bedbug_puts(const char *str)
35 {
36   /* -------------------------------------------------- */
37
38   printf( "%s\r\n", str );
39   return 0;
40 } /* bedbug_puts */
41
42
43 \f
44 /* ======================================================================
45  * Initialize the bug_ctx structure used by the bedbug debugger.  This is
46  * specific to the CPU since each has different debug registers and
47  * settings.
48  * ====================================================================== */
49
50 void bedbug_init( void )
51 {
52   /* -------------------------------------------------- */
53
54 #if defined(CONFIG_4xx)
55   void bedbug405_init( void );
56   bedbug405_init();
57 #elif defined(CONFIG_8xx)
58   void bedbug860_init( void );
59   bedbug860_init();
60 #endif
61
62 #if defined(CONFIG_MPC824X) || defined(CONFIG_MPC8260)
63   /* Processors that are 603e core based */
64   void bedbug603e_init( void );
65
66   bedbug603e_init();
67 #endif
68
69   return;
70 } /* bedbug_init */
71
72
73 \f
74 /* ======================================================================
75  * Entry point from the interpreter to the disassembler.  Repeated calls
76  * will resume from the last disassembled address.
77  * ====================================================================== */
78 int do_bedbug_dis (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
79 {
80   ulong addr;   /* Address to start disassembly from    */
81   ulong len;    /* # of instructions to disassemble     */
82   /* -------------------------------------------------- */
83
84   /* Setup to go from the last address if none is given */
85   addr = dis_last_addr;
86   len  = dis_last_len;
87
88   if (argc < 2)
89   {
90     printf ("Usage:\n%s\n", cmdtp->usage);
91     return 1;
92   }
93
94   if(( flag & CMD_FLAG_REPEAT ) == 0 )
95   {
96     /* New command */
97     addr = simple_strtoul( argv[1], NULL, 16 );
98
99     /* If an extra param is given then it is the length */
100     if( argc > 2 )
101       len = simple_strtoul( argv[2], NULL, 16 );
102   }
103
104   /* Run the disassembler */
105   disppc( (unsigned char *)addr, 0, len, bedbug_puts, F_RADHEX );
106
107   dis_last_addr = addr + (len * 4);
108   dis_last_len = len;
109   return 0;
110 } /* do_bedbug_dis */
111 cmd_tbl_t U_BOOT_CMD(DIS) = MK_CMD_ENTRY(
112         "ds",      3,      1,      do_bedbug_dis,
113         "ds      - disassemble memory\n",
114         "ds <address> [# instructions]\n"
115 );
116 \f
117 /* ======================================================================
118  * Entry point from the interpreter to the assembler.  Assembles
119  * instructions in consecutive memory locations until a '.' (period) is
120  * entered on a line by itself.
121  * ====================================================================== */
122 int do_bedbug_asm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
123 {
124   long          mem_addr;               /* Address to assemble into     */
125   unsigned long instr;                  /* Machine code for text        */
126   char          prompt[ 15 ];           /* Prompt string for user input */
127   int           asm_err;                /* Error code from the assembler*/
128   /* -------------------------------------------------- */
129    int          rcode = 0;
130
131   if (argc < 2)
132   {
133     printf ("Usage:\n%s\n", cmdtp->usage);
134     return 1;
135   }
136
137   printf( "\nEnter '.' when done\n" );
138   mem_addr = simple_strtoul( argv[ 1 ], NULL, 16 );
139
140   while( 1 )
141   {
142     putc( '\n' );
143     disppc( (unsigned char *)mem_addr, 0, 1, bedbug_puts, F_RADHEX );
144
145     sprintf( prompt, "%08lx:    ", mem_addr );
146     readline( prompt );
147
148     if( console_buffer[ 0 ] && strcmp( console_buffer, "." ))
149     {
150       if(( instr = asmppc( mem_addr, console_buffer, &asm_err )) != 0 )
151       {
152         *(unsigned long *)mem_addr = instr;
153         mem_addr += 4;
154       }
155       else
156       {
157         printf( "*** Error: %s ***\n", asm_error_str( asm_err ));
158         rcode = 1;
159       }
160     }
161     else
162     {
163       break;
164     }
165   }
166   return rcode;
167 } /* do_bedbug_asm */
168 cmd_tbl_t U_BOOT_CMD(ASM) = MK_CMD_ENTRY(
169         "as",      2,      0,      do_bedbug_asm,
170         "as      - assemble memory\n",
171         "as <address>\n"
172 );
173 \f
174 /* ======================================================================
175  * Used to set a break point from the interpreter.  Simply calls into the
176  * CPU-specific break point set routine.
177  * ====================================================================== */
178
179 int do_bedbug_break (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
180 {
181   /* -------------------------------------------------- */
182   if( bug_ctx.do_break )
183     (*bug_ctx.do_break)( cmdtp, flag, argc, argv );
184     return 0;
185
186 } /* do_bedbug_break */
187 cmd_tbl_t U_BOOT_CMD(BREAK) = MK_CMD_ENTRY(
188         "break",      3,      0,      do_bedbug_break,
189         "break   - set or clear a breakpoint\n",
190         " - Set or clear a breakpoint\n"
191         "break <address> - Break at an address\n"
192         "break off <bp#> - Disable breakpoint.\n"
193         "break show      - List breakpoints.\n"
194 );
195 \f
196 /* ======================================================================
197  * Called from the debug interrupt routine.  Simply calls the CPU-specific
198  * breakpoint handling routine.
199  * ====================================================================== */
200
201 void do_bedbug_breakpoint (struct pt_regs *regs)
202 {
203   /* -------------------------------------------------- */
204
205   if( bug_ctx.break_isr )
206     (*bug_ctx.break_isr)( regs );
207
208   return;
209 } /* do_bedbug_breakpoint */
210
211
212 \f
213 /* ======================================================================
214  * Called from the CPU-specific breakpoint handling routine.  Enter a
215  * mini main loop until the stopped flag is cleared from the breakpoint
216  * context.
217  *
218  * This handles the parts of the debugger that are common to all CPU's.
219  * ====================================================================== */
220
221 void bedbug_main_loop( unsigned long addr, struct pt_regs *regs )
222 {
223   int           len;                    /* Length of command line */
224   int           flag;                   /* Command flags          */
225   int           rc = 0;                 /* Result from run_command*/
226   char          prompt_str[ 20 ];       /* Prompt string          */
227   static char   lastcommand[ CFG_CBSIZE ] = {0}; /* previous command */
228   /* -------------------------------------------------- */
229
230   if( bug_ctx.clear )
231     (*bug_ctx.clear)( bug_ctx.current_bp );
232
233   printf( "Breakpoint %d: ", bug_ctx.current_bp );
234   disppc( (unsigned char *)addr, 0, 1, bedbug_puts, F_RADHEX );
235
236   bug_ctx.stopped = 1;
237   bug_ctx.regs = regs;
238
239   sprintf( prompt_str, "BEDBUG.%d =>", bug_ctx.current_bp );
240
241   /* A miniature main loop */
242   while( bug_ctx.stopped )
243   {
244     len = readline( prompt_str );
245
246     flag = 0;   /* assume no special flags for now */
247
248     if (len > 0)
249       strcpy( lastcommand, console_buffer );
250     else if( len == 0 )
251       flag |= CMD_FLAG_REPEAT;
252
253     if (len == -1)
254       printf ("<INTERRUPT>\n");
255     else
256       rc = run_command( lastcommand, flag );
257
258     if (rc <= 0) {
259       /* invalid command or not repeatable, forget it */
260       lastcommand[0] = 0;
261     }
262   }
263
264   bug_ctx.regs = NULL;
265   bug_ctx.current_bp = 0;
266
267   return;
268 } /* bedbug_main_loop */
269
270
271 \f
272 /* ======================================================================
273  * Interpreter command to continue from a breakpoint.  Just clears the
274  * stopped flag in the context so that the breakpoint routine will
275  * return.
276  * ====================================================================== */
277 int do_bedbug_continue (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
278
279 {
280   /* -------------------------------------------------- */
281
282   if( ! bug_ctx.stopped )
283   {
284     printf( "Not at a breakpoint\n" );
285     return 1;
286   }
287
288   bug_ctx.stopped = 0;
289   return 0;
290 } /* do_bedbug_continue */
291 cmd_tbl_t U_BOOT_CMD(CONTINUE) = MK_CMD_ENTRY(
292         "continue",      1,      0,      do_bedbug_continue,
293         "continue- continue from a breakpoint\n",
294         " - continue from a breakpoint.\n"
295 );
296 \f
297 /* ======================================================================
298  * Interpreter command to continue to the next instruction, stepping into
299  * subroutines.  Works by calling the find_next_addr() routine to compute
300  * the address passes control to the CPU-specific set breakpoint routine
301  * for the current breakpoint number.
302  * ====================================================================== */
303 int do_bedbug_step (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
304 {
305   unsigned long addr;   /* Address to stop at */
306   /* -------------------------------------------------- */
307
308   if( ! bug_ctx.stopped )
309   {
310     printf( "Not at a breakpoint\n" );
311     return 1;
312   }
313
314   if( !find_next_address( (unsigned char *)&addr, FALSE, bug_ctx.regs ))
315     return 1;
316
317   if( bug_ctx.set )
318     (*bug_ctx.set)( bug_ctx.current_bp, addr );
319
320   bug_ctx.stopped = 0;
321   return 0;
322 } /* do_bedbug_step */
323 cmd_tbl_t U_BOOT_CMD(STEP) = MK_CMD_ENTRY(
324         "step",      1,      1,      do_bedbug_step,
325         "step    - single step execution.\n",
326         " - single step execution.\n"
327 );
328 \f
329 /* ======================================================================
330  * Interpreter command to continue to the next instruction, stepping over
331  * subroutines.  Works by calling the find_next_addr() routine to compute
332  * the address passes control to the CPU-specific set breakpoint routine
333  * for the current breakpoint number.
334  * ====================================================================== */
335 int do_bedbug_next (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
336 {
337   unsigned long addr;   /* Address to stop at */
338   /* -------------------------------------------------- */
339
340   if( ! bug_ctx.stopped )
341   {
342     printf( "Not at a breakpoint\n" );
343     return 1;
344   }
345
346   if( !find_next_address( (unsigned char *)&addr, TRUE, bug_ctx.regs ))
347     return 1;
348
349   if( bug_ctx.set )
350     (*bug_ctx.set)( bug_ctx.current_bp, addr );
351
352   bug_ctx.stopped = 0;
353   return 0;
354 } /* do_bedbug_next */
355 cmd_tbl_t U_BOOT_CMD(NEXT) = MK_CMD_ENTRY(
356         "next",      1,      1,      do_bedbug_next,
357         "next    - single step execution, stepping over subroutines.\n",
358         " - single step execution, stepping over subroutines.\n"
359 );
360 \f
361 /* ======================================================================
362  * Interpreter command to print the current stack.  This assumes an EABI
363  * architecture, so it starts with GPR R1 and works back up the stack.
364  * ====================================================================== */
365 int do_bedbug_stack (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
366 {
367         DECLARE_GLOBAL_DATA_PTR;
368
369   unsigned long sp;             /* Stack pointer                */
370   unsigned long func;           /* LR from stack                */
371   int           depth;          /* Stack iteration level        */
372   int           skip = 1;       /* Flag to skip the first entry */
373   unsigned long top;            /* Top of memory address        */
374   /* -------------------------------------------------- */
375
376   if( ! bug_ctx.stopped )
377   {
378     printf( "Not at a breakpoint\n" );
379     return 1;
380   }
381
382   top = gd->bd->bi_memstart + gd->bd->bi_memsize;
383   depth = 0;
384
385   printf( "Depth     PC\n" );
386   printf( "-----  --------\n" );
387   printf( "%5d  %08lx\n", depth++, bug_ctx.regs->nip );
388
389   sp = bug_ctx.regs->gpr[ 1 ];
390   func = *(unsigned long *)(sp+4);
391
392   while(( func < top ) && ( sp < top ))
393   {
394     if( !skip )
395       printf( "%5d  %08lx\n", depth++, func );
396     else
397       --skip;
398
399     sp = *(unsigned long *)sp;
400     func = *(unsigned long *)(sp+4);
401   }
402   return 0;
403 } /* do_bedbug_stack */
404 cmd_tbl_t U_BOOT_CMD(STACK) = MK_CMD_ENTRY(
405         "where",     1,      1,      do_bedbug_stack,
406         "where   - Print the running stack.\n",
407         " - Print the running stack.\n"
408 );
409 \f
410 /* ======================================================================
411  * Interpreter command to dump the registers.  Calls the CPU-specific
412  * show registers routine.
413  * ====================================================================== */
414 int do_bedbug_rdump (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
415 {
416   /* -------------------------------------------------- */
417
418   if( ! bug_ctx.stopped )
419   {
420     printf( "Not at a breakpoint\n" );
421     return 1;
422   }
423
424   show_regs( bug_ctx.regs );
425   return 0;
426 } /* do_bedbug_rdump */
427 cmd_tbl_t U_BOOT_CMD(RDUMP) = MK_CMD_ENTRY(
428         "rdump",     1,      1,      do_bedbug_rdump,
429         "rdump   - Show registers.\n",
430         " - Show registers.\n"
431 );
432 /* ====================================================================== */
433 #endif  /* CFG_CMD_BEDBUG */
434
435
436 /*
437  * Copyright (c) 2001 William L. Pitts
438  * All rights reserved.
439  *
440  * Redistribution and use in source and binary forms are freely
441  * permitted provided that the above copyright notice and this
442  * paragraph and the following disclaimer are duplicated in all
443  * such forms.
444  *
445  * This software is provided "AS IS" and without any express or
446  * implied warranties, including, without limitation, the implied
447  * warranties of merchantability and fitness for a particular
448  * purpose.
449  */