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