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