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