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