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 /* ======================================================================
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 
bedbug_init(void)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  * ====================================================================== */
do_bedbug_dis(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])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 = simple_strtoul (argv[1], NULL, 16);
79 
80 		/* If an extra param is given then it is the length */
81 		if (argc > 2)
82 			len = simple_strtoul (argv[2], NULL, 16);
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  * ====================================================================== */
do_bedbug_asm(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])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 = simple_strtoul (argv[1], NULL, 16);
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 
do_bedbug_break(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])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 
do_bedbug_breakpoint(struct pt_regs * regs)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 
bedbug_main_loop(unsigned long addr,struct pt_regs * regs)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  * ====================================================================== */
do_bedbug_continue(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])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  * ====================================================================== */
do_bedbug_step(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])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  * ====================================================================== */
do_bedbug_next(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])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  * ====================================================================== */
do_bedbug_stack(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])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  * ====================================================================== */
do_bedbug_rdump(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])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  */
415