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