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 
bedbug_puts(const char * str)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 
bedbug_init(void)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  * ====================================================================== */
do_bedbug_dis(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])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  * ====================================================================== */
do_bedbug_asm(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])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 
do_bedbug_break(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])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 
do_bedbug_breakpoint(struct pt_regs * regs)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 
bedbug_main_loop(unsigned long addr,struct pt_regs * regs)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  * ====================================================================== */
do_bedbug_continue(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])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  * ====================================================================== */
do_bedbug_step(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])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  * ====================================================================== */
do_bedbug_next(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])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  * ====================================================================== */
do_bedbug_stack(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])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  * ====================================================================== */
do_bedbug_rdump(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])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  */
411