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