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