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
102 static char remcomInBuffer[BUFMAX];
103 static char remcomOutBuffer[BUFMAX];
104 static char remcomRegBuffer[BUFMAX];
105
106 static int initialized = 0;
107 static int kgdb_active;
108 static struct pt_regs entry_regs;
109 static long error_jmp_buf[BUFMAX/2];
110 static int longjmp_on_fault = 0;
111 #ifdef KGDB_DEBUG
112 static int kdebug = 1;
113 #endif
114
115 static const char hexchars[]="0123456789abcdef";
116
117 /* Convert ch from a hex digit to an int */
118 static int
hex(unsigned char ch)119 hex(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 */
133 static unsigned char *
mem2hex(char * mem,char * buf,int count)134 mem2hex(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 */
161 static char *
hex2mem(char * buf,char * mem,int count)162 hex2mem(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 */
200 static int
hexToInt(char ** ptr,int * intValue)201 hexToInt(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> */
225 static void
getpacket(char * buffer)226 getpacket(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. */
287 static void
putpacket(unsigned char * buffer)288 putpacket(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 */
316 static int
handle_exception(struct pt_regs * regs)317 handle_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 */
530 void
kgdb_init(void)531 kgdb_init(void)
532 {
533 kgdb_serial_init();
534 debugger_exception_handler = handle_exception;
535 initialized = 1;
536
537 putDebugStr("kgdb ready\n");
538 puts("ready\n");
539 }
540
541 void
kgdb_error(int errnum)542 kgdb_error(int errnum)
543 {
544 longjmp_on_fault = 0;
545 kgdb_longjmp(error_jmp_buf, errnum);
546 panic("kgdb_error: longjmp failed!\n");
547 }
548
549 /* Output string in GDB O-packet format if GDB has connected. If nothing
550 output, returns 0 (caller must then handle output). */
551 int
kgdb_output_string(const char * s,unsigned int count)552 kgdb_output_string (const char* s, unsigned int count)
553 {
554 char buffer[512];
555
556 count = (count <= (sizeof(buffer) / 2 - 2))
557 ? count : (sizeof(buffer) / 2 - 2);
558
559 buffer[0] = 'O';
560 mem2hex ((char *)s, &buffer[1], count);
561 putpacket((unsigned char *)&buffer);
562
563 return 1;
564 }
565
566 void
breakpoint(void)567 breakpoint(void)
568 {
569 if (!initialized) {
570 printf("breakpoint() called b4 kgdb init\n");
571 return;
572 }
573
574 kgdb_breakpoint(0, 0);
575 }
576
577 int
do_kgdb(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])578 do_kgdb(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
579 {
580 printf("Entering KGDB mode via exception handler...\n\n");
581 kgdb_breakpoint(argc - 1, argv + 1);
582 printf("\nReturned from KGDB mode\n");
583 return 0;
584 }
585
586 U_BOOT_CMD(
587 kgdb, CONFIG_SYS_MAXARGS, 1, do_kgdb,
588 "enter gdb remote debug mode",
589 "[arg0 arg1 .. argN]\n"
590 " - executes a breakpoint so that kgdb mode is\n"
591 " entered via the exception handler. To return\n"
592 " to the monitor, the remote gdb debugger must\n"
593 " execute a \"continue\" or \"quit\" command.\n"
594 "\n"
595 " if a program is loaded by the remote gdb, any args\n"
596 " passed to the kgdb command are given to the loaded\n"
597 " program if it is executed (see the \"hello_world\"\n"
598 " example program in the U-Boot examples directory)."
599 );
600