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