1/* taken from arch/powerpc/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#include <asm/ptrace.h> 92 93#include <kgdb.h> 94#include <command.h> 95 96#undef KGDB_DEBUG 97 98/* 99 * BUFMAX defines the maximum number of characters in inbound/outbound buffers 100 */ 101#define BUFMAX 1024 102static char remcomInBuffer[BUFMAX]; 103static char remcomOutBuffer[BUFMAX]; 104static char remcomRegBuffer[BUFMAX]; 105 106static int initialized = 0; 107static int kgdb_active; 108static struct pt_regs entry_regs; 109static long error_jmp_buf[BUFMAX/2]; 110static int longjmp_on_fault = 0; 111#ifdef KGDB_DEBUG 112static int kdebug = 1; 113#endif 114 115static const char hexchars[]="0123456789abcdef"; 116 117/* Convert ch from a hex digit to an int */ 118static int 119hex(unsigned char ch) 120{ 121 if (ch >= 'a' && ch <= 'f') 122 return ch-'a'+10; 123 if (ch >= '0' && ch <= '9') 124 return ch-'0'; 125 if (ch >= 'A' && ch <= 'F') 126 return ch-'A'+10; 127 return -1; 128} 129 130/* Convert the memory pointed to by mem into hex, placing result in buf. 131 * Return a pointer to the last char put in buf (null). 132 */ 133static unsigned char * 134mem2hex(char *mem, char *buf, int count) 135{ 136 char *tmp; 137 unsigned char ch; 138 139 /* 140 * We use the upper half of buf as an intermediate buffer for the 141 * raw memory copy. Hex conversion will work against this one. 142 */ 143 tmp = buf + count; 144 longjmp_on_fault = 1; 145 146 memcpy(tmp, mem, count); 147 148 while (count-- > 0) { 149 ch = *tmp++; 150 *buf++ = hexchars[ch >> 4]; 151 *buf++ = hexchars[ch & 0xf]; 152 } 153 *buf = 0; 154 longjmp_on_fault = 0; 155 return (unsigned char *)buf; 156} 157 158/* convert the hex array pointed to by buf into binary to be placed in mem 159 * return a pointer to the character AFTER the last byte fetched from buf. 160*/ 161static char * 162hex2mem(char *buf, char *mem, int count) 163{ 164 int hexValue; 165 char *tmp_raw, *tmp_hex; 166 167 /* 168 * We use the upper half of buf as an intermediate buffer for the 169 * raw memory that is converted from hex. 170 */ 171 tmp_raw = buf + count * 2; 172 tmp_hex = tmp_raw - 1; 173 174 longjmp_on_fault = 1; 175 while (tmp_hex >= buf) { 176 tmp_raw--; 177 hexValue = hex(*tmp_hex--); 178 if (hexValue < 0) 179 kgdb_error(KGDBERR_NOTHEXDIG); 180 *tmp_raw = hexValue; 181 hexValue = hex(*tmp_hex--); 182 if (hexValue < 0) 183 kgdb_error(KGDBERR_NOTHEXDIG); 184 *tmp_raw |= hexValue << 4; 185 186 } 187 188 memcpy(mem, tmp_raw, count); 189 190 kgdb_flush_cache_range((void *)mem, (void *)(mem+count)); 191 longjmp_on_fault = 0; 192 193 return buf; 194} 195 196/* 197 * While we find nice hex chars, build an int. 198 * Return number of chars processed. 199 */ 200static int 201hexToInt(char **ptr, int *intValue) 202{ 203 int numChars = 0; 204 int hexValue; 205 206 *intValue = 0; 207 208 longjmp_on_fault = 1; 209 while (**ptr) { 210 hexValue = hex(**ptr); 211 if (hexValue < 0) 212 break; 213 214 *intValue = (*intValue << 4) | hexValue; 215 numChars ++; 216 217 (*ptr)++; 218 } 219 longjmp_on_fault = 0; 220 221 return (numChars); 222} 223 224/* scan for the sequence $<data>#<checksum> */ 225static void 226getpacket(char *buffer) 227{ 228 unsigned char checksum; 229 unsigned char xmitcsum; 230 int i; 231 int count; 232 unsigned char ch; 233 234 do { 235 /* wait around for the start character, ignore all other 236 * characters */ 237 while ((ch = (getDebugChar() & 0x7f)) != '$') { 238#ifdef KGDB_DEBUG 239 if (kdebug) 240 putc(ch); 241#endif 242 ; 243 } 244 245 checksum = 0; 246 xmitcsum = -1; 247 248 count = 0; 249 250 /* now, read until a # or end of buffer is found */ 251 while (count < BUFMAX) { 252 ch = getDebugChar() & 0x7f; 253 if (ch == '#') 254 break; 255 checksum = checksum + ch; 256 buffer[count] = ch; 257 count = count + 1; 258 } 259 260 if (count >= BUFMAX) 261 continue; 262 263 buffer[count] = 0; 264 265 if (ch == '#') { 266 xmitcsum = hex(getDebugChar() & 0x7f) << 4; 267 xmitcsum |= hex(getDebugChar() & 0x7f); 268 if (checksum != xmitcsum) 269 putDebugChar('-'); /* failed checksum */ 270 else { 271 putDebugChar('+'); /* successful transfer */ 272 /* if a sequence char is present, reply the ID */ 273 if (buffer[2] == ':') { 274 putDebugChar(buffer[0]); 275 putDebugChar(buffer[1]); 276 /* remove sequence chars from buffer */ 277 count = strlen(buffer); 278 for (i=3; i <= count; i++) 279 buffer[i-3] = buffer[i]; 280 } 281 } 282 } 283 } while (checksum != xmitcsum); 284} 285 286/* send the packet in buffer. */ 287static void 288putpacket(unsigned char *buffer) 289{ 290 unsigned char checksum; 291 int count; 292 unsigned char ch, recv; 293 294 /* $<packet info>#<checksum>. */ 295 do { 296 putDebugChar('$'); 297 checksum = 0; 298 count = 0; 299 300 while ((ch = buffer[count])) { 301 putDebugChar(ch); 302 checksum += ch; 303 count += 1; 304 } 305 306 putDebugChar('#'); 307 putDebugChar(hexchars[checksum >> 4]); 308 putDebugChar(hexchars[checksum & 0xf]); 309 recv = getDebugChar(); 310 } while ((recv & 0x7f) != '+'); 311} 312 313/* 314 * This function does all command processing for interfacing to gdb. 315 */ 316static int 317handle_exception (struct pt_regs *regs) 318{ 319 int addr; 320 int length; 321 char *ptr; 322 kgdb_data kd; 323 int i; 324 325 if (!initialized) { 326 printf("kgdb: exception before kgdb is initialized! huh?\n"); 327 return (0); 328 } 329 330 /* probably should check which exception occurred as well */ 331 if (longjmp_on_fault) { 332 longjmp_on_fault = 0; 333 kgdb_longjmp(error_jmp_buf, KGDBERR_MEMFAULT); 334 panic("kgdb longjump failed!\n"); 335 } 336 337 if (kgdb_active) { 338 printf("kgdb: unexpected exception from within kgdb\n"); 339 return (0); 340 } 341 kgdb_active = 1; 342 343 kgdb_interruptible(0); 344 345 printf("kgdb: handle_exception; trap [0x%x]\n", kgdb_trap(regs)); 346 347 if (kgdb_setjmp(error_jmp_buf) != 0) 348 panic("kgdb: error or fault in entry init!\n"); 349 350 kgdb_enter(regs, &kd); 351 352 entry_regs = *regs; 353 354 ptr = remcomOutBuffer; 355 356 *ptr++ = 'T'; 357 358 *ptr++ = hexchars[kd.sigval >> 4]; 359 *ptr++ = hexchars[kd.sigval & 0xf]; 360 361 for (i = 0; i < kd.nregs; i++) { 362 kgdb_reg *rp = &kd.regs[i]; 363 364 *ptr++ = hexchars[rp->num >> 4]; 365 *ptr++ = hexchars[rp->num & 0xf]; 366 *ptr++ = ':'; 367 ptr = (char *)mem2hex((char *)&rp->val, ptr, 4); 368 *ptr++ = ';'; 369 } 370 371 *ptr = 0; 372 373#ifdef KGDB_DEBUG 374 if (kdebug) 375 printf("kgdb: remcomOutBuffer: %s\n", remcomOutBuffer); 376#endif 377 378 putpacket((unsigned char *)&remcomOutBuffer); 379 380 while (1) { 381 volatile int errnum; 382 383 remcomOutBuffer[0] = 0; 384 385 getpacket(remcomInBuffer); 386 ptr = &remcomInBuffer[1]; 387 388#ifdef KGDB_DEBUG 389 if (kdebug) 390 printf("kgdb: remcomInBuffer: %s\n", remcomInBuffer); 391#endif 392 393 errnum = kgdb_setjmp(error_jmp_buf); 394 395 if (errnum == 0) switch (remcomInBuffer[0]) { 396 397 case '?': /* report most recent signal */ 398 remcomOutBuffer[0] = 'S'; 399 remcomOutBuffer[1] = hexchars[kd.sigval >> 4]; 400 remcomOutBuffer[2] = hexchars[kd.sigval & 0xf]; 401 remcomOutBuffer[3] = 0; 402 break; 403 404#ifdef KGDB_DEBUG 405 case 'd': 406 /* toggle debug flag */ 407 kdebug ^= 1; 408 break; 409#endif 410 411 case 'g': /* return the value of the CPU registers. */ 412 length = kgdb_getregs(regs, remcomRegBuffer, BUFMAX); 413 mem2hex(remcomRegBuffer, remcomOutBuffer, length); 414 break; 415 416 case 'G': /* set the value of the CPU registers */ 417 length = strlen(ptr); 418 if ((length & 1) != 0) kgdb_error(KGDBERR_BADPARAMS); 419 hex2mem(ptr, remcomRegBuffer, length/2); 420 kgdb_putregs(regs, remcomRegBuffer, length/2); 421 strcpy(remcomOutBuffer,"OK"); 422 break; 423 424 case 'm': /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */ 425 /* Try to read %x,%x. */ 426 427 if (hexToInt(&ptr, &addr) 428 && *ptr++ == ',' 429 && hexToInt(&ptr, &length)) { 430 mem2hex((char *)addr, remcomOutBuffer, length); 431 } else { 432 kgdb_error(KGDBERR_BADPARAMS); 433 } 434 break; 435 436 case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */ 437 /* Try to read '%x,%x:'. */ 438 439 if (hexToInt(&ptr, &addr) 440 && *ptr++ == ',' 441 && hexToInt(&ptr, &length) 442 && *ptr++ == ':') { 443 hex2mem(ptr, (char *)addr, length); 444 strcpy(remcomOutBuffer, "OK"); 445 } else { 446 kgdb_error(KGDBERR_BADPARAMS); 447 } 448 break; 449 450 451 case 'k': /* kill the program, actually return to monitor */ 452 kd.extype = KGDBEXIT_KILL; 453 *regs = entry_regs; 454 goto doexit; 455 456 case 'C': /* CSS continue with signal SS */ 457 *ptr = '\0'; /* ignore the signal number for now */ 458 /* fall through */ 459 460 case 'c': /* cAA..AA Continue; address AA..AA optional */ 461 /* try to read optional parameter, pc unchanged if no parm */ 462 kd.extype = KGDBEXIT_CONTINUE; 463 464 if (hexToInt(&ptr, &addr)) { 465 kd.exaddr = addr; 466 kd.extype |= KGDBEXIT_WITHADDR; 467 } 468 469 goto doexit; 470 471 case 'S': /* SSS single step with signal SS */ 472 *ptr = '\0'; /* ignore the signal number for now */ 473 /* fall through */ 474 475 case 's': 476 kd.extype = KGDBEXIT_SINGLE; 477 478 if (hexToInt(&ptr, &addr)) { 479 kd.exaddr = addr; 480 kd.extype |= KGDBEXIT_WITHADDR; 481 } 482 483 doexit: 484/* Need to flush the instruction cache here, as we may have deposited a 485 * breakpoint, and the icache probably has no way of knowing that a data ref to 486 * some location may have changed something that is in the instruction cache. 487 */ 488 kgdb_flush_cache_all(); 489 kgdb_exit(regs, &kd); 490 kgdb_active = 0; 491 kgdb_interruptible(1); 492 return (1); 493 494 case 'r': /* Reset (if user process..exit ???)*/ 495 panic("kgdb reset."); 496 break; 497 498 case 'P': /* Pr=v set reg r to value v (r and v are hex) */ 499 if (hexToInt(&ptr, &addr) 500 && *ptr++ == '=' 501 && ((length = strlen(ptr)) & 1) == 0) { 502 hex2mem(ptr, remcomRegBuffer, length/2); 503 kgdb_putreg(regs, addr, 504 remcomRegBuffer, length/2); 505 strcpy(remcomOutBuffer,"OK"); 506 } else { 507 kgdb_error(KGDBERR_BADPARAMS); 508 } 509 break; 510 } /* switch */ 511 512 if (errnum != 0) 513 sprintf(remcomOutBuffer, "E%02d", errnum); 514 515#ifdef KGDB_DEBUG 516 if (kdebug) 517 printf("kgdb: remcomOutBuffer: %s\n", remcomOutBuffer); 518#endif 519 520 /* reply to the request */ 521 putpacket((unsigned char *)&remcomOutBuffer); 522 523 } /* while(1) */ 524} 525 526/* 527 * kgdb_init must be called *after* the 528 * monitor is relocated into ram 529 */ 530int kgdb_init(void) 531{ 532 puts("KGDB: "); 533 534 kgdb_serial_init(); 535 debugger_exception_handler = handle_exception; 536 initialized = 1; 537 538 putDebugStr("kgdb ready\n"); 539 puts("ready\n"); 540 541 return 0; 542} 543 544void 545kgdb_error(int errnum) 546{ 547 longjmp_on_fault = 0; 548 kgdb_longjmp(error_jmp_buf, errnum); 549 panic("kgdb_error: longjmp failed!\n"); 550} 551 552/* Output string in GDB O-packet format if GDB has connected. If nothing 553 output, returns 0 (caller must then handle output). */ 554int 555kgdb_output_string (const char* s, unsigned int count) 556{ 557 char buffer[512]; 558 559 count = (count <= (sizeof(buffer) / 2 - 2)) 560 ? count : (sizeof(buffer) / 2 - 2); 561 562 buffer[0] = 'O'; 563 mem2hex ((char *)s, &buffer[1], count); 564 putpacket((unsigned char *)&buffer); 565 566 return 1; 567} 568 569void 570breakpoint(void) 571{ 572 if (!initialized) { 573 printf("breakpoint() called b4 kgdb init\n"); 574 return; 575 } 576 577 kgdb_breakpoint(0, 0); 578} 579 580int 581do_kgdb(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) 582{ 583 printf("Entering KGDB mode via exception handler...\n\n"); 584 kgdb_breakpoint(argc - 1, argv + 1); 585 printf("\nReturned from KGDB mode\n"); 586 return 0; 587} 588 589U_BOOT_CMD( 590 kgdb, CONFIG_SYS_MAXARGS, 1, do_kgdb, 591 "enter gdb remote debug mode", 592 "[arg0 arg1 .. argN]\n" 593 " - executes a breakpoint so that kgdb mode is\n" 594 " entered via the exception handler. To return\n" 595 " to the monitor, the remote gdb debugger must\n" 596 " execute a \"continue\" or \"quit\" command.\n" 597 "\n" 598 " if a program is loaded by the remote gdb, any args\n" 599 " passed to the kgdb command are given to the loaded\n" 600 " program if it is executed (see the \"hello_world\"\n" 601 " example program in the U-Boot examples directory)." 602); 603