Blame view

cmd/bedbug.c 11.7 KB
47d1a6e1e   wdenk   Initial revision
1
2
3
4
5
  /*
   * BedBug Functions
   */
  
  #include <common.h>
18d66533a   Simon Glass   move CLI prototyp...
6
  #include <cli.h>
47d1a6e1e   wdenk   Initial revision
7
  #include <command.h>
24b852a7a   Simon Glass   Move console defi...
8
  #include <console.h>
47d1a6e1e   wdenk   Initial revision
9
10
  #include <linux/ctype.h>
  #include <net.h>
8bde7f776   wdenk   * Code cleanup:
11
  #include <bedbug/type.h>
47d1a6e1e   wdenk   Initial revision
12
13
14
  #include <bedbug/bedbug.h>
  #include <bedbug/regs.h>
  #include <bedbug/ppc.h>
47d1a6e1e   wdenk   Initial revision
15

d87080b72   Wolfgang Denk   GCC-4.x fixes: cl...
16
  DECLARE_GLOBAL_DATA_PTR;
d87080b72   Wolfgang Denk   GCC-4.x fixes: cl...
17
18
  extern void show_regs __P ((struct pt_regs *));
  extern int run_command __P ((const char *, int));
47d1a6e1e   wdenk   Initial revision
19

d87080b72   Wolfgang Denk   GCC-4.x fixes: cl...
20
21
22
  ulong dis_last_addr = 0;	/* Last address disassembled   */
  ulong dis_last_len = 20;	/* Default disassembler length */
  CPU_DEBUG_CTX bug_ctx;		/* Bedbug context structure    */
e1bf824df   Simon Glass   Add cli_ prefix t...
23

d87080b72   Wolfgang Denk   GCC-4.x fixes: cl...
24

47d1a6e1e   wdenk   Initial revision
25
26
27
28
  /* ======================================================================
   * U-Boot's puts function does not append a newline, so the bedbug stuff
   * will use this for the output of the dis/assembler.
   * ====================================================================== */
d87080b72   Wolfgang Denk   GCC-4.x fixes: cl...
29
  int bedbug_puts (const char *str)
47d1a6e1e   wdenk   Initial revision
30
  {
d87080b72   Wolfgang Denk   GCC-4.x fixes: cl...
31
  	/* -------------------------------------------------- */
47d1a6e1e   wdenk   Initial revision
32

d87080b72   Wolfgang Denk   GCC-4.x fixes: cl...
33
34
35
36
  	printf ("%s\r
  ", str);
  	return 0;
  }				/* bedbug_puts */
e1bf824df   Simon Glass   Add cli_ prefix t...
37

47d1a6e1e   wdenk   Initial revision
38

47d1a6e1e   wdenk   Initial revision
39
40
41
42
43
  /* ======================================================================
   * Initialize the bug_ctx structure used by the bedbug debugger.  This is
   * specific to the CPU since each has different debug registers and
   * settings.
   * ====================================================================== */
d87080b72   Wolfgang Denk   GCC-4.x fixes: cl...
44
  void bedbug_init (void)
47d1a6e1e   wdenk   Initial revision
45
  {
d87080b72   Wolfgang Denk   GCC-4.x fixes: cl...
46
  	/* -------------------------------------------------- */
d87080b72   Wolfgang Denk   GCC-4.x fixes: cl...
47
48
  	return;
  }				/* bedbug_init */
e1bf824df   Simon Glass   Add cli_ prefix t...
49

47d1a6e1e   wdenk   Initial revision
50

47d1a6e1e   wdenk   Initial revision
51
52
53
54
  /* ======================================================================
   * Entry point from the interpreter to the disassembler.  Repeated calls
   * will resume from the last disassembled address.
   * ====================================================================== */
54841ab50   Wolfgang Denk   Make sure that ar...
55
  int do_bedbug_dis (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
47d1a6e1e   wdenk   Initial revision
56
  {
d87080b72   Wolfgang Denk   GCC-4.x fixes: cl...
57
58
59
60
61
62
63
64
  	ulong addr;		/* Address to start disassembly from    */
  	ulong len;		/* # of instructions to disassemble     */
  
  	/* -------------------------------------------------- */
  
  	/* Setup to go from the last address if none is given */
  	addr = dis_last_addr;
  	len = dis_last_len;
47e26b1bf   Wolfgang Denk   cmd_usage(): simp...
65
  	if (argc < 2)
4c12eeb8b   Simon Glass   Convert cmd_usage...
66
  		return CMD_RET_USAGE;
d87080b72   Wolfgang Denk   GCC-4.x fixes: cl...
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
  
  	if ((flag & CMD_FLAG_REPEAT) == 0) {
  		/* New command */
  		addr = simple_strtoul (argv[1], NULL, 16);
  
  		/* If an extra param is given then it is the length */
  		if (argc > 2)
  			len = simple_strtoul (argv[2], NULL, 16);
  	}
  
  	/* Run the disassembler */
  	disppc ((unsigned char *) addr, 0, len, bedbug_puts, F_RADHEX);
  
  	dis_last_addr = addr + (len * 4);
  	dis_last_len = len;
  	return 0;
  }				/* do_bedbug_dis */
  
  U_BOOT_CMD (ds, 3, 1, do_bedbug_dis,
2fb2604d5   Peter Tyser   Command usage cle...
86
  	    "disassemble memory",
a89c33db9   Wolfgang Denk   General help mess...
87
  	    "ds <address> [# instructions]");
e1bf824df   Simon Glass   Add cli_ prefix t...
88

47d1a6e1e   wdenk   Initial revision
89
90
91
92
93
  /* ======================================================================
   * Entry point from the interpreter to the assembler.  Assembles
   * instructions in consecutive memory locations until a '.' (period) is
   * entered on a line by itself.
   * ====================================================================== */
54841ab50   Wolfgang Denk   Make sure that ar...
94
  int do_bedbug_asm (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
47d1a6e1e   wdenk   Initial revision
95
  {
d87080b72   Wolfgang Denk   GCC-4.x fixes: cl...
96
97
98
99
100
101
102
  	long mem_addr;		/* Address to assemble into     */
  	unsigned long instr;	/* Machine code for text        */
  	char prompt[15];	/* Prompt string for user input */
  	int asm_err;		/* Error code from the assembler */
  
  	/* -------------------------------------------------- */
  	int rcode = 0;
47e26b1bf   Wolfgang Denk   cmd_usage(): simp...
103
  	if (argc < 2)
4c12eeb8b   Simon Glass   Convert cmd_usage...
104
  		return CMD_RET_USAGE;
d87080b72   Wolfgang Denk   GCC-4.x fixes: cl...
105
106
107
108
109
110
111
112
113
114
115
116
117
  
  	printf ("
  Enter '.' when done
  ");
  	mem_addr = simple_strtoul (argv[1], NULL, 16);
  
  	while (1) {
  		putc ('
  ');
  		disppc ((unsigned char *) mem_addr, 0, 1, bedbug_puts,
  			F_RADHEX);
  
  		sprintf (prompt, "%08lx:    ", mem_addr);
e1bf824df   Simon Glass   Add cli_ prefix t...
118
  		cli_readline(prompt);
d87080b72   Wolfgang Denk   GCC-4.x fixes: cl...
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
  
  		if (console_buffer[0] && strcmp (console_buffer, ".")) {
  			if ((instr =
  			     asmppc (mem_addr, console_buffer,
  				     &asm_err)) != 0) {
  				*(unsigned long *) mem_addr = instr;
  				mem_addr += 4;
  			} else {
  				printf ("*** Error: %s ***
  ",
  					asm_error_str (asm_err));
  				rcode = 1;
  			}
  		} else {
  			break;
  		}
  	}
  	return rcode;
  }				/* do_bedbug_asm */
  
  U_BOOT_CMD (as, 2, 0, do_bedbug_asm,
a89c33db9   Wolfgang Denk   General help mess...
140
  	    "assemble memory", "as <address>");
e1bf824df   Simon Glass   Add cli_ prefix t...
141

47d1a6e1e   wdenk   Initial revision
142
143
144
145
  /* ======================================================================
   * Used to set a break point from the interpreter.  Simply calls into the
   * CPU-specific break point set routine.
   * ====================================================================== */
54841ab50   Wolfgang Denk   Make sure that ar...
146
  int do_bedbug_break (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
47d1a6e1e   wdenk   Initial revision
147
  {
d87080b72   Wolfgang Denk   GCC-4.x fixes: cl...
148
149
150
151
152
153
154
155
  	/* -------------------------------------------------- */
  	if (bug_ctx.do_break)
  		(*bug_ctx.do_break) (cmdtp, flag, argc, argv);
  	return 0;
  
  }				/* do_bedbug_break */
  
  U_BOOT_CMD (break, 3, 0, do_bedbug_break,
2fb2604d5   Peter Tyser   Command usage cle...
156
  	    "set or clear a breakpoint",
d87080b72   Wolfgang Denk   GCC-4.x fixes: cl...
157
158
159
160
161
162
  	    " - Set or clear a breakpoint
  "
  	    "break <address> - Break at an address
  "
  	    "break off <bp#> - Disable breakpoint.
  "
a89c33db9   Wolfgang Denk   General help mess...
163
  	    "break show      - List breakpoints.");
e1bf824df   Simon Glass   Add cli_ prefix t...
164

47d1a6e1e   wdenk   Initial revision
165
166
167
168
169
170
171
  /* ======================================================================
   * Called from the debug interrupt routine.  Simply calls the CPU-specific
   * breakpoint handling routine.
   * ====================================================================== */
  
  void do_bedbug_breakpoint (struct pt_regs *regs)
  {
d87080b72   Wolfgang Denk   GCC-4.x fixes: cl...
172
  	/* -------------------------------------------------- */
47d1a6e1e   wdenk   Initial revision
173

d87080b72   Wolfgang Denk   GCC-4.x fixes: cl...
174
175
  	if (bug_ctx.break_isr)
  		(*bug_ctx.break_isr) (regs);
47d1a6e1e   wdenk   Initial revision
176

d87080b72   Wolfgang Denk   GCC-4.x fixes: cl...
177
178
  	return;
  }				/* do_bedbug_breakpoint */
e1bf824df   Simon Glass   Add cli_ prefix t...
179

47d1a6e1e   wdenk   Initial revision
180

47d1a6e1e   wdenk   Initial revision
181
182
183
184
185
186
187
  /* ======================================================================
   * Called from the CPU-specific breakpoint handling routine.  Enter a
   * mini main loop until the stopped flag is cleared from the breakpoint
   * context.
   *
   * This handles the parts of the debugger that are common to all CPU's.
   * ====================================================================== */
d87080b72   Wolfgang Denk   GCC-4.x fixes: cl...
188
  void bedbug_main_loop (unsigned long addr, struct pt_regs *regs)
47d1a6e1e   wdenk   Initial revision
189
  {
d87080b72   Wolfgang Denk   GCC-4.x fixes: cl...
190
191
192
193
  	int len;		/* Length of command line */
  	int flag;		/* Command flags          */
  	int rc = 0;		/* Result from run_command */
  	char prompt_str[20];	/* Prompt string          */
6d0f6bcf3   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ macro...
194
  	static char lastcommand[CONFIG_SYS_CBSIZE] = { 0 };	/* previous command */
d87080b72   Wolfgang Denk   GCC-4.x fixes: cl...
195
  	/* -------------------------------------------------- */
47d1a6e1e   wdenk   Initial revision
196

d87080b72   Wolfgang Denk   GCC-4.x fixes: cl...
197
198
  	if (bug_ctx.clear)
  		(*bug_ctx.clear) (bug_ctx.current_bp);
47d1a6e1e   wdenk   Initial revision
199

d87080b72   Wolfgang Denk   GCC-4.x fixes: cl...
200
201
  	printf ("Breakpoint %d: ", bug_ctx.current_bp);
  	disppc ((unsigned char *) addr, 0, 1, bedbug_puts, F_RADHEX);
47d1a6e1e   wdenk   Initial revision
202

d87080b72   Wolfgang Denk   GCC-4.x fixes: cl...
203
204
  	bug_ctx.stopped = 1;
  	bug_ctx.regs = regs;
47d1a6e1e   wdenk   Initial revision
205

d87080b72   Wolfgang Denk   GCC-4.x fixes: cl...
206
  	sprintf (prompt_str, "BEDBUG.%d =>", bug_ctx.current_bp);
47d1a6e1e   wdenk   Initial revision
207

d87080b72   Wolfgang Denk   GCC-4.x fixes: cl...
208
209
  	/* A miniature main loop */
  	while (bug_ctx.stopped) {
e1bf824df   Simon Glass   Add cli_ prefix t...
210
  		len = cli_readline(prompt_str);
47d1a6e1e   wdenk   Initial revision
211

d87080b72   Wolfgang Denk   GCC-4.x fixes: cl...
212
  		flag = 0;	/* assume no special flags for now */
47d1a6e1e   wdenk   Initial revision
213

d87080b72   Wolfgang Denk   GCC-4.x fixes: cl...
214
215
216
217
  		if (len > 0)
  			strcpy (lastcommand, console_buffer);
  		else if (len == 0)
  			flag |= CMD_FLAG_REPEAT;
47d1a6e1e   wdenk   Initial revision
218

d87080b72   Wolfgang Denk   GCC-4.x fixes: cl...
219
220
221
222
  		if (len == -1)
  			printf ("<INTERRUPT>
  ");
  		else
52715f893   Thomas Betker   Use run_command_r...
223
  			rc = run_command_repeatable(lastcommand, flag);
47d1a6e1e   wdenk   Initial revision
224

d87080b72   Wolfgang Denk   GCC-4.x fixes: cl...
225
226
227
228
229
  		if (rc <= 0) {
  			/* invalid command or not repeatable, forget it */
  			lastcommand[0] = 0;
  		}
  	}
47d1a6e1e   wdenk   Initial revision
230

d87080b72   Wolfgang Denk   GCC-4.x fixes: cl...
231
232
  	bug_ctx.regs = NULL;
  	bug_ctx.current_bp = 0;
47d1a6e1e   wdenk   Initial revision
233

d87080b72   Wolfgang Denk   GCC-4.x fixes: cl...
234
235
  	return;
  }				/* bedbug_main_loop */
e1bf824df   Simon Glass   Add cli_ prefix t...
236

47d1a6e1e   wdenk   Initial revision
237

47d1a6e1e   wdenk   Initial revision
238
239
240
241
242
  /* ======================================================================
   * Interpreter command to continue from a breakpoint.  Just clears the
   * stopped flag in the context so that the breakpoint routine will
   * return.
   * ====================================================================== */
54841ab50   Wolfgang Denk   Make sure that ar...
243
  int do_bedbug_continue (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
47d1a6e1e   wdenk   Initial revision
244
  {
d87080b72   Wolfgang Denk   GCC-4.x fixes: cl...
245
246
247
248
249
250
251
252
253
254
255
256
257
  	/* -------------------------------------------------- */
  
  	if (!bug_ctx.stopped) {
  		printf ("Not at a breakpoint
  ");
  		return 1;
  	}
  
  	bug_ctx.stopped = 0;
  	return 0;
  }				/* do_bedbug_continue */
  
  U_BOOT_CMD (continue, 1, 0, do_bedbug_continue,
2fb2604d5   Peter Tyser   Command usage cle...
258
  	    "continue from a breakpoint",
a89c33db9   Wolfgang Denk   General help mess...
259
  	    "");
e1bf824df   Simon Glass   Add cli_ prefix t...
260

47d1a6e1e   wdenk   Initial revision
261
262
263
264
265
266
  /* ======================================================================
   * Interpreter command to continue to the next instruction, stepping into
   * subroutines.  Works by calling the find_next_addr() routine to compute
   * the address passes control to the CPU-specific set breakpoint routine
   * for the current breakpoint number.
   * ====================================================================== */
54841ab50   Wolfgang Denk   Make sure that ar...
267
  int do_bedbug_step (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
47d1a6e1e   wdenk   Initial revision
268
  {
d87080b72   Wolfgang Denk   GCC-4.x fixes: cl...
269
270
271
272
273
274
275
276
277
  	unsigned long addr;	/* Address to stop at */
  
  	/* -------------------------------------------------- */
  
  	if (!bug_ctx.stopped) {
  		printf ("Not at a breakpoint
  ");
  		return 1;
  	}
472d54605   York Sun   Consolidate bool ...
278
  	if (!find_next_address((unsigned char *) &addr, false, bug_ctx.regs))
d87080b72   Wolfgang Denk   GCC-4.x fixes: cl...
279
280
281
282
283
284
285
286
287
288
  		return 1;
  
  	if (bug_ctx.set)
  		(*bug_ctx.set) (bug_ctx.current_bp, addr);
  
  	bug_ctx.stopped = 0;
  	return 0;
  }				/* do_bedbug_step */
  
  U_BOOT_CMD (step, 1, 1, do_bedbug_step,
2fb2604d5   Peter Tyser   Command usage cle...
289
  	    "single step execution.",
a89c33db9   Wolfgang Denk   General help mess...
290
  	    "");
e1bf824df   Simon Glass   Add cli_ prefix t...
291

47d1a6e1e   wdenk   Initial revision
292
293
294
295
296
297
  /* ======================================================================
   * Interpreter command to continue to the next instruction, stepping over
   * subroutines.  Works by calling the find_next_addr() routine to compute
   * the address passes control to the CPU-specific set breakpoint routine
   * for the current breakpoint number.
   * ====================================================================== */
54841ab50   Wolfgang Denk   Make sure that ar...
298
  int do_bedbug_next (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
47d1a6e1e   wdenk   Initial revision
299
  {
d87080b72   Wolfgang Denk   GCC-4.x fixes: cl...
300
301
302
303
304
305
306
307
308
  	unsigned long addr;	/* Address to stop at */
  
  	/* -------------------------------------------------- */
  
  	if (!bug_ctx.stopped) {
  		printf ("Not at a breakpoint
  ");
  		return 1;
  	}
472d54605   York Sun   Consolidate bool ...
309
  	if (!find_next_address((unsigned char *) &addr, true, bug_ctx.regs))
d87080b72   Wolfgang Denk   GCC-4.x fixes: cl...
310
311
312
313
314
315
316
317
318
319
  		return 1;
  
  	if (bug_ctx.set)
  		(*bug_ctx.set) (bug_ctx.current_bp, addr);
  
  	bug_ctx.stopped = 0;
  	return 0;
  }				/* do_bedbug_next */
  
  U_BOOT_CMD (next, 1, 1, do_bedbug_next,
2fb2604d5   Peter Tyser   Command usage cle...
320
  	    "single step execution, stepping over subroutines.",
a89c33db9   Wolfgang Denk   General help mess...
321
  	    "");
e1bf824df   Simon Glass   Add cli_ prefix t...
322

47d1a6e1e   wdenk   Initial revision
323
324
325
326
  /* ======================================================================
   * Interpreter command to print the current stack.  This assumes an EABI
   * architecture, so it starts with GPR R1 and works back up the stack.
   * ====================================================================== */
54841ab50   Wolfgang Denk   Make sure that ar...
327
  int do_bedbug_stack (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
47d1a6e1e   wdenk   Initial revision
328
  {
d87080b72   Wolfgang Denk   GCC-4.x fixes: cl...
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
  	unsigned long sp;	/* Stack pointer                */
  	unsigned long func;	/* LR from stack                */
  	int depth;		/* Stack iteration level        */
  	int skip = 1;		/* Flag to skip the first entry */
  	unsigned long top;	/* Top of memory address        */
  
  	/* -------------------------------------------------- */
  
  	if (!bug_ctx.stopped) {
  		printf ("Not at a breakpoint
  ");
  		return 1;
  	}
  
  	top = gd->bd->bi_memstart + gd->bd->bi_memsize;
  	depth = 0;
  
  	printf ("Depth     PC
  ");
  	printf ("-----  --------
  ");
  	printf ("%5d  %08lx
  ", depth++, bug_ctx.regs->nip);
  
  	sp = bug_ctx.regs->gpr[1];
  	func = *(unsigned long *) (sp + 4);
  
  	while ((func < top) && (sp < top)) {
  		if (!skip)
  			printf ("%5d  %08lx
  ", depth++, func);
  		else
  			--skip;
  
  		sp = *(unsigned long *) sp;
  		func = *(unsigned long *) (sp + 4);
  	}
  	return 0;
  }				/* do_bedbug_stack */
  
  U_BOOT_CMD (where, 1, 1, do_bedbug_stack,
2fb2604d5   Peter Tyser   Command usage cle...
370
  	    "Print the running stack.",
a89c33db9   Wolfgang Denk   General help mess...
371
  	    "");
e1bf824df   Simon Glass   Add cli_ prefix t...
372

47d1a6e1e   wdenk   Initial revision
373
374
375
376
  /* ======================================================================
   * Interpreter command to dump the registers.  Calls the CPU-specific
   * show registers routine.
   * ====================================================================== */
54841ab50   Wolfgang Denk   Make sure that ar...
377
  int do_bedbug_rdump (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
47d1a6e1e   wdenk   Initial revision
378
  {
d87080b72   Wolfgang Denk   GCC-4.x fixes: cl...
379
380
381
382
383
384
385
386
387
388
389
390
391
  	/* -------------------------------------------------- */
  
  	if (!bug_ctx.stopped) {
  		printf ("Not at a breakpoint
  ");
  		return 1;
  	}
  
  	show_regs (bug_ctx.regs);
  	return 0;
  }				/* do_bedbug_rdump */
  
  U_BOOT_CMD (rdump, 1, 1, do_bedbug_rdump,
a89c33db9   Wolfgang Denk   General help mess...
392
  	    "Show registers.", "");
47d1a6e1e   wdenk   Initial revision
393
  /* ====================================================================== */
47d1a6e1e   wdenk   Initial revision
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
  
  
  /*
   * Copyright (c) 2001 William L. Pitts
   * All rights reserved.
   *
   * Redistribution and use in source and binary forms are freely
   * permitted provided that the above copyright notice and this
   * paragraph and the following disclaimer are duplicated in all
   * such forms.
   *
   * This software is provided "AS IS" and without any express or
   * implied warranties, including, without limitation, the implied
   * warranties of merchantability and fitness for a particular
   * purpose.
   */