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