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