1 /* taken from arch/ppc/kernel/ppc-stub.c */ 2 3 /**************************************************************************** 4 5 THIS SOFTWARE IS NOT COPYRIGHTED 6 7 HP offers the following for use in the public domain. HP makes no 8 warranty with regard to the software or its performance and the 9 user accepts the software "AS IS" with all faults. 10 11 HP DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD 12 TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES 13 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 14 15 ****************************************************************************/ 16 17 /**************************************************************************** 18 * Header: remcom.c,v 1.34 91/03/09 12:29:49 glenne Exp $ 19 * 20 * Module name: remcom.c $ 21 * Revision: 1.34 $ 22 * Date: 91/03/09 12:29:49 $ 23 * Contributor: Lake Stevens Instrument Division$ 24 * 25 * Description: low level support for gdb debugger. $ 26 * 27 * Considerations: only works on target hardware $ 28 * 29 * Written by: Glenn Engel $ 30 * ModuleState: Experimental $ 31 * 32 * NOTES: See Below $ 33 * 34 * Modified for SPARC by Stu Grossman, Cygnus Support. 35 * 36 * This code has been extensively tested on the Fujitsu SPARClite demo board. 37 * 38 * To enable debugger support, two things need to happen. One, a 39 * call to set_debug_traps() is necessary in order to allow any breakpoints 40 * or error conditions to be properly intercepted and reported to gdb. 41 * Two, a breakpoint needs to be generated to begin communication. This 42 * is most easily accomplished by a call to breakpoint(). Breakpoint() 43 * simulates a breakpoint by executing a trap #1. 44 * 45 ************* 46 * 47 * The following gdb commands are supported: 48 * 49 * command function Return value 50 * 51 * g return the value of the CPU registers hex data or ENN 52 * G set the value of the CPU registers OK or ENN 53 * qOffsets Get section offsets. Reply is Text=xxx;Data=yyy;Bss=zzz 54 * 55 * mAA..AA,LLLL Read LLLL bytes at address AA..AA hex data or ENN 56 * MAA..AA,LLLL: Write LLLL bytes at address AA.AA OK or ENN 57 * 58 * c Resume at current address SNN ( signal NN) 59 * cAA..AA Continue at address AA..AA SNN 60 * 61 * s Step one instruction SNN 62 * sAA..AA Step one instruction from AA..AA SNN 63 * 64 * k kill 65 * 66 * ? What was the last sigval ? SNN (signal NN) 67 * 68 * bBB..BB Set baud rate to BB..BB OK or BNN, then sets 69 * baud rate 70 * 71 * All commands and responses are sent with a packet which includes a 72 * checksum. A packet consists of 73 * 74 * $<packet info>#<checksum>. 75 * 76 * where 77 * <packet info> :: <characters representing the command or response> 78 * <checksum> :: <two hex digits computed as modulo 256 sum of <packetinfo>> 79 * 80 * When a packet is received, it is first acknowledged with either '+' or '-'. 81 * '+' indicates a successful transfer. '-' indicates a failed transfer. 82 * 83 * Example: 84 * 85 * Host: Reply: 86 * $m0,10#2a +$00010203040506070809101112131415#42 87 * 88 ****************************************************************************/ 89 90 #include <common.h> 91 92 #include <kgdb.h> 93 #include <command.h> 94 95 #undef KGDB_DEBUG 96 97 /* 98 * BUFMAX defines the maximum number of characters in inbound/outbound buffers 99 */ 100 #define BUFMAX 1024 101 static char remcomInBuffer[BUFMAX]; 102 static char remcomOutBuffer[BUFMAX]; 103 static char remcomRegBuffer[BUFMAX]; 104 105 static int initialized = 0; 106 static int kgdb_active = 0, first_entry = 1; 107 static struct pt_regs entry_regs; 108 static long error_jmp_buf[BUFMAX/2]; 109 static int longjmp_on_fault = 0; 110 #ifdef KGDB_DEBUG 111 static int kdebug = 1; 112 #endif 113 114 static const char hexchars[]="0123456789abcdef"; 115 116 /* Convert ch from a hex digit to an int */ 117 static int 118 hex(unsigned char ch) 119 { 120 if (ch >= 'a' && ch <= 'f') 121 return ch-'a'+10; 122 if (ch >= '0' && ch <= '9') 123 return ch-'0'; 124 if (ch >= 'A' && ch <= 'F') 125 return ch-'A'+10; 126 return -1; 127 } 128 129 /* Convert the memory pointed to by mem into hex, placing result in buf. 130 * Return a pointer to the last char put in buf (null). 131 */ 132 static unsigned char * 133 mem2hex(char *mem, char *buf, int count) 134 { 135 unsigned char ch; 136 137 longjmp_on_fault = 1; 138 while (count-- > 0) { 139 ch = *mem++; 140 *buf++ = hexchars[ch >> 4]; 141 *buf++ = hexchars[ch & 0xf]; 142 } 143 *buf = 0; 144 longjmp_on_fault = 0; 145 return (unsigned char *)buf; 146 } 147 148 /* convert the hex array pointed to by buf into binary to be placed in mem 149 * return a pointer to the character AFTER the last byte fetched from buf. 150 */ 151 static char * 152 hex2mem(char *buf, char *mem, int count) 153 { 154 int i, hexValue; 155 unsigned char ch; 156 char *mem_start = mem; 157 158 longjmp_on_fault = 1; 159 for (i=0; i<count; i++) { 160 if ((hexValue = hex(*buf++)) < 0) 161 kgdb_error(KGDBERR_NOTHEXDIG); 162 ch = hexValue << 4; 163 if ((hexValue = hex(*buf++)) < 0) 164 kgdb_error(KGDBERR_NOTHEXDIG); 165 ch |= hexValue; 166 *mem++ = ch; 167 } 168 kgdb_flush_cache_range((void *)mem_start, (void *)(mem - 1)); 169 longjmp_on_fault = 0; 170 171 return buf; 172 } 173 174 /* 175 * While we find nice hex chars, build an int. 176 * Return number of chars processed. 177 */ 178 static int 179 hexToInt(char **ptr, int *intValue) 180 { 181 int numChars = 0; 182 int hexValue; 183 184 *intValue = 0; 185 186 longjmp_on_fault = 1; 187 while (**ptr) { 188 hexValue = hex(**ptr); 189 if (hexValue < 0) 190 break; 191 192 *intValue = (*intValue << 4) | hexValue; 193 numChars ++; 194 195 (*ptr)++; 196 } 197 longjmp_on_fault = 0; 198 199 return (numChars); 200 } 201 202 /* scan for the sequence $<data>#<checksum> */ 203 static void 204 getpacket(char *buffer) 205 { 206 unsigned char checksum; 207 unsigned char xmitcsum; 208 int i; 209 int count; 210 unsigned char ch; 211 212 do { 213 /* wait around for the start character, ignore all other 214 * characters */ 215 while ((ch = (getDebugChar() & 0x7f)) != '$') { 216 #ifdef KGDB_DEBUG 217 if (kdebug) 218 putc(ch); 219 #endif 220 ; 221 } 222 223 checksum = 0; 224 xmitcsum = -1; 225 226 count = 0; 227 228 /* now, read until a # or end of buffer is found */ 229 while (count < BUFMAX) { 230 ch = getDebugChar() & 0x7f; 231 if (ch == '#') 232 break; 233 checksum = checksum + ch; 234 buffer[count] = ch; 235 count = count + 1; 236 } 237 238 if (count >= BUFMAX) 239 continue; 240 241 buffer[count] = 0; 242 243 if (ch == '#') { 244 xmitcsum = hex(getDebugChar() & 0x7f) << 4; 245 xmitcsum |= hex(getDebugChar() & 0x7f); 246 if (checksum != xmitcsum) 247 putDebugChar('-'); /* failed checksum */ 248 else { 249 putDebugChar('+'); /* successful transfer */ 250 /* if a sequence char is present, reply the ID */ 251 if (buffer[2] == ':') { 252 putDebugChar(buffer[0]); 253 putDebugChar(buffer[1]); 254 /* remove sequence chars from buffer */ 255 count = strlen(buffer); 256 for (i=3; i <= count; i++) 257 buffer[i-3] = buffer[i]; 258 } 259 } 260 } 261 } while (checksum != xmitcsum); 262 } 263 264 /* send the packet in buffer. */ 265 static void 266 putpacket(unsigned char *buffer) 267 { 268 unsigned char checksum; 269 int count; 270 unsigned char ch, recv; 271 272 /* $<packet info>#<checksum>. */ 273 do { 274 putDebugChar('$'); 275 checksum = 0; 276 count = 0; 277 278 while ((ch = buffer[count])) { 279 putDebugChar(ch); 280 checksum += ch; 281 count += 1; 282 } 283 284 putDebugChar('#'); 285 putDebugChar(hexchars[checksum >> 4]); 286 putDebugChar(hexchars[checksum & 0xf]); 287 recv = getDebugChar(); 288 } while ((recv & 0x7f) != '+'); 289 } 290 291 /* 292 * This function does all command processing for interfacing to gdb. 293 */ 294 static int 295 handle_exception (struct pt_regs *regs) 296 { 297 int addr; 298 int length; 299 char *ptr; 300 kgdb_data kd; 301 int i; 302 303 if (!initialized) { 304 printf("kgdb: exception before kgdb is initialized! huh?\n"); 305 return (0); 306 } 307 308 /* probably should check which exception occured as well */ 309 if (longjmp_on_fault) { 310 longjmp_on_fault = 0; 311 kgdb_longjmp(error_jmp_buf, KGDBERR_MEMFAULT); 312 panic("kgdb longjump failed!\n"); 313 } 314 315 if (kgdb_active) { 316 printf("kgdb: unexpected exception from within kgdb\n"); 317 return (0); 318 } 319 kgdb_active = 1; 320 321 kgdb_interruptible(0); 322 323 printf("kgdb: handle_exception; trap [0x%x]\n", kgdb_trap(regs)); 324 325 if (kgdb_setjmp(error_jmp_buf) != 0) 326 panic("kgdb: error or fault in entry init!\n"); 327 328 kgdb_enter(regs, &kd); 329 330 if (first_entry) { 331 /* 332 * the first time we enter kgdb, we save the processor 333 * state so that we can return to the monitor if the 334 * remote end quits gdb (or at least, tells us to quit 335 * with the 'k' packet) 336 */ 337 entry_regs = *regs; 338 first_entry = 0; 339 } 340 341 ptr = remcomOutBuffer; 342 343 *ptr++ = 'T'; 344 345 *ptr++ = hexchars[kd.sigval >> 4]; 346 *ptr++ = hexchars[kd.sigval & 0xf]; 347 348 for (i = 0; i < kd.nregs; i++) { 349 kgdb_reg *rp = &kd.regs[i]; 350 351 *ptr++ = hexchars[rp->num >> 4]; 352 *ptr++ = hexchars[rp->num & 0xf]; 353 *ptr++ = ':'; 354 ptr = (char *)mem2hex((char *)&rp->val, ptr, 4); 355 *ptr++ = ';'; 356 } 357 358 *ptr = 0; 359 360 #ifdef KGDB_DEBUG 361 if (kdebug) 362 printf("kgdb: remcomOutBuffer: %s\n", remcomOutBuffer); 363 #endif 364 365 putpacket((unsigned char *)&remcomOutBuffer); 366 367 while (1) { 368 volatile int errnum; 369 370 remcomOutBuffer[0] = 0; 371 372 getpacket(remcomInBuffer); 373 ptr = &remcomInBuffer[1]; 374 375 #ifdef KGDB_DEBUG 376 if (kdebug) 377 printf("kgdb: remcomInBuffer: %s\n", remcomInBuffer); 378 #endif 379 380 errnum = kgdb_setjmp(error_jmp_buf); 381 382 if (errnum == 0) switch (remcomInBuffer[0]) { 383 384 case '?': /* report most recent signal */ 385 remcomOutBuffer[0] = 'S'; 386 remcomOutBuffer[1] = hexchars[kd.sigval >> 4]; 387 remcomOutBuffer[2] = hexchars[kd.sigval & 0xf]; 388 remcomOutBuffer[3] = 0; 389 break; 390 391 #ifdef KGDB_DEBUG 392 case 'd': 393 /* toggle debug flag */ 394 kdebug ^= 1; 395 break; 396 #endif 397 398 case 'g': /* return the value of the CPU registers. */ 399 length = kgdb_getregs(regs, remcomRegBuffer, BUFMAX); 400 mem2hex(remcomRegBuffer, remcomOutBuffer, length); 401 break; 402 403 case 'G': /* set the value of the CPU registers */ 404 length = strlen(ptr); 405 if ((length & 1) != 0) kgdb_error(KGDBERR_BADPARAMS); 406 hex2mem(ptr, remcomRegBuffer, length/2); 407 kgdb_putregs(regs, remcomRegBuffer, length/2); 408 strcpy(remcomOutBuffer,"OK"); 409 break; 410 411 case 'm': /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */ 412 /* Try to read %x,%x. */ 413 414 if (hexToInt(&ptr, &addr) 415 && *ptr++ == ',' 416 && hexToInt(&ptr, &length)) { 417 mem2hex((char *)addr, remcomOutBuffer, length); 418 } else { 419 kgdb_error(KGDBERR_BADPARAMS); 420 } 421 break; 422 423 case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */ 424 /* Try to read '%x,%x:'. */ 425 426 if (hexToInt(&ptr, &addr) 427 && *ptr++ == ',' 428 && hexToInt(&ptr, &length) 429 && *ptr++ == ':') { 430 hex2mem(ptr, (char *)addr, length); 431 strcpy(remcomOutBuffer, "OK"); 432 } else { 433 kgdb_error(KGDBERR_BADPARAMS); 434 } 435 break; 436 437 438 case 'k': /* kill the program, actually return to monitor */ 439 kd.extype = KGDBEXIT_KILL; 440 *regs = entry_regs; 441 first_entry = 1; 442 goto doexit; 443 444 case 'C': /* CSS continue with signal SS */ 445 *ptr = '\0'; /* ignore the signal number for now */ 446 /* fall through */ 447 448 case 'c': /* cAA..AA Continue; address AA..AA optional */ 449 /* try to read optional parameter, pc unchanged if no parm */ 450 kd.extype = KGDBEXIT_CONTINUE; 451 452 if (hexToInt(&ptr, &addr)) { 453 kd.exaddr = addr; 454 kd.extype |= KGDBEXIT_WITHADDR; 455 } 456 457 goto doexit; 458 459 case 'S': /* SSS single step with signal SS */ 460 *ptr = '\0'; /* ignore the signal number for now */ 461 /* fall through */ 462 463 case 's': 464 kd.extype = KGDBEXIT_SINGLE; 465 466 if (hexToInt(&ptr, &addr)) { 467 kd.exaddr = addr; 468 kd.extype |= KGDBEXIT_WITHADDR; 469 } 470 471 doexit: 472 /* Need to flush the instruction cache here, as we may have deposited a 473 * breakpoint, and the icache probably has no way of knowing that a data ref to 474 * some location may have changed something that is in the instruction cache. 475 */ 476 kgdb_flush_cache_all(); 477 kgdb_exit(regs, &kd); 478 kgdb_active = 0; 479 kgdb_interruptible(1); 480 return (1); 481 482 case 'r': /* Reset (if user process..exit ???)*/ 483 panic("kgdb reset."); 484 break; 485 486 case 'P': /* Pr=v set reg r to value v (r and v are hex) */ 487 if (hexToInt(&ptr, &addr) 488 && *ptr++ == '=' 489 && ((length = strlen(ptr)) & 1) == 0) { 490 hex2mem(ptr, remcomRegBuffer, length/2); 491 kgdb_putreg(regs, addr, 492 remcomRegBuffer, length/2); 493 strcpy(remcomOutBuffer,"OK"); 494 } else { 495 kgdb_error(KGDBERR_BADPARAMS); 496 } 497 break; 498 } /* switch */ 499 500 if (errnum != 0) 501 sprintf(remcomOutBuffer, "E%02d", errnum); 502 503 #ifdef KGDB_DEBUG 504 if (kdebug) 505 printf("kgdb: remcomOutBuffer: %s\n", remcomOutBuffer); 506 #endif 507 508 /* reply to the request */ 509 putpacket((unsigned char *)&remcomOutBuffer); 510 511 } /* while(1) */ 512 } 513 514 /* 515 * kgdb_init must be called *after* the 516 * monitor is relocated into ram 517 */ 518 void 519 kgdb_init(void) 520 { 521 kgdb_serial_init(); 522 debugger_exception_handler = handle_exception; 523 initialized = 1; 524 525 putDebugStr("kgdb ready\n"); 526 puts("ready\n"); 527 } 528 529 void 530 kgdb_error(int errnum) 531 { 532 longjmp_on_fault = 0; 533 kgdb_longjmp(error_jmp_buf, errnum); 534 panic("kgdb_error: longjmp failed!\n"); 535 } 536 537 /* Output string in GDB O-packet format if GDB has connected. If nothing 538 output, returns 0 (caller must then handle output). */ 539 int 540 kgdb_output_string (const char* s, unsigned int count) 541 { 542 char buffer[512]; 543 544 count = (count <= (sizeof(buffer) / 2 - 2)) 545 ? count : (sizeof(buffer) / 2 - 2); 546 547 buffer[0] = 'O'; 548 mem2hex ((char *)s, &buffer[1], count); 549 putpacket((unsigned char *)&buffer); 550 551 return 1; 552 } 553 554 void 555 breakpoint(void) 556 { 557 if (!initialized) { 558 printf("breakpoint() called b4 kgdb init\n"); 559 return; 560 } 561 562 kgdb_breakpoint(0, 0); 563 } 564 565 int 566 do_kgdb(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) 567 { 568 printf("Entering KGDB mode via exception handler...\n\n"); 569 kgdb_breakpoint(argc - 1, argv + 1); 570 printf("\nReturned from KGDB mode\n"); 571 return 0; 572 } 573 574 U_BOOT_CMD( 575 kgdb, CONFIG_SYS_MAXARGS, 1, do_kgdb, 576 "enter gdb remote debug mode", 577 "[arg0 arg1 .. argN]\n" 578 " - executes a breakpoint so that kgdb mode is\n" 579 " entered via the exception handler. To return\n" 580 " to the monitor, the remote gdb debugger must\n" 581 " execute a \"continue\" or \"quit\" command.\n" 582 "\n" 583 " if a program is loaded by the remote gdb, any args\n" 584 " passed to the kgdb command are given to the loaded\n" 585 " program if it is executed (see the \"hello_world\"\n" 586 " example program in the U-Boot examples directory)." 587 ); 588