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