xref: /openbmc/u-boot/common/kgdb.c (revision c0dcece7)
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 
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 	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 *
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
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
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
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
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 occured 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 	if (first_entry) {
352 		/*
353 		 * the first time we enter kgdb, we save the processor
354 		 * state so that we can return to the monitor if the
355 		 * remote end quits gdb (or at least, tells us to quit
356 		 * with the 'k' packet)
357 		 */
358 		entry_regs = *regs;
359 		first_entry = 0;
360 	}
361 
362 	ptr = remcomOutBuffer;
363 
364 	*ptr++ = 'T';
365 
366 	*ptr++ = hexchars[kd.sigval >> 4];
367 	*ptr++ = hexchars[kd.sigval & 0xf];
368 
369 	for (i = 0; i < kd.nregs; i++) {
370 		kgdb_reg *rp = &kd.regs[i];
371 
372 		*ptr++ = hexchars[rp->num >> 4];
373 		*ptr++ = hexchars[rp->num & 0xf];
374 		*ptr++ = ':';
375 		ptr = (char *)mem2hex((char *)&rp->val, ptr, 4);
376 		*ptr++ = ';';
377 	}
378 
379 	*ptr = 0;
380 
381 #ifdef KGDB_DEBUG
382 	if (kdebug)
383 		printf("kgdb: remcomOutBuffer: %s\n", remcomOutBuffer);
384 #endif
385 
386 	putpacket((unsigned char *)&remcomOutBuffer);
387 
388 	while (1) {
389 		volatile int errnum;
390 
391 		remcomOutBuffer[0] = 0;
392 
393 		getpacket(remcomInBuffer);
394 		ptr = &remcomInBuffer[1];
395 
396 #ifdef KGDB_DEBUG
397 		if (kdebug)
398 			printf("kgdb:  remcomInBuffer: %s\n", remcomInBuffer);
399 #endif
400 
401 		errnum = kgdb_setjmp(error_jmp_buf);
402 
403 		if (errnum == 0) switch (remcomInBuffer[0]) {
404 
405 		case '?':               /* report most recent signal */
406 			remcomOutBuffer[0] = 'S';
407 			remcomOutBuffer[1] = hexchars[kd.sigval >> 4];
408 			remcomOutBuffer[2] = hexchars[kd.sigval & 0xf];
409 			remcomOutBuffer[3] = 0;
410 			break;
411 
412 #ifdef KGDB_DEBUG
413 		case 'd':
414 			/* toggle debug flag */
415 			kdebug ^= 1;
416 			break;
417 #endif
418 
419 		case 'g':	/* return the value of the CPU registers. */
420 			length = kgdb_getregs(regs, remcomRegBuffer, BUFMAX);
421 			mem2hex(remcomRegBuffer, remcomOutBuffer, length);
422 			break;
423 
424 		case 'G':   /* set the value of the CPU registers */
425 			length = strlen(ptr);
426 			if ((length & 1) != 0) kgdb_error(KGDBERR_BADPARAMS);
427 			hex2mem(ptr, remcomRegBuffer, length/2);
428 			kgdb_putregs(regs, remcomRegBuffer, length/2);
429 			strcpy(remcomOutBuffer,"OK");
430 			break;
431 
432 		case 'm':	/* mAA..AA,LLLL  Read LLLL bytes at address AA..AA */
433 				/* Try to read %x,%x.  */
434 
435 			if (hexToInt(&ptr, &addr)
436 			    && *ptr++ == ','
437 			    && hexToInt(&ptr, &length))	{
438 				mem2hex((char *)addr, remcomOutBuffer, length);
439 			} else {
440 				kgdb_error(KGDBERR_BADPARAMS);
441 			}
442 			break;
443 
444 		case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
445 			/* Try to read '%x,%x:'.  */
446 
447 			if (hexToInt(&ptr, &addr)
448 			    && *ptr++ == ','
449 			    && hexToInt(&ptr, &length)
450 			    && *ptr++ == ':') {
451 				hex2mem(ptr, (char *)addr, length);
452 				strcpy(remcomOutBuffer, "OK");
453 			} else {
454 				kgdb_error(KGDBERR_BADPARAMS);
455 			}
456 			break;
457 
458 
459 		case 'k':    /* kill the program, actually return to monitor */
460 			kd.extype = KGDBEXIT_KILL;
461 			*regs = entry_regs;
462 			first_entry = 1;
463 			goto doexit;
464 
465 		case 'C':    /* CSS  continue with signal SS */
466 			*ptr = '\0';	/* ignore the signal number for now */
467 			/* fall through */
468 
469 		case 'c':    /* cAA..AA  Continue; address AA..AA optional */
470 			/* try to read optional parameter, pc unchanged if no parm */
471 			kd.extype = KGDBEXIT_CONTINUE;
472 
473 			if (hexToInt(&ptr, &addr)) {
474 				kd.exaddr = addr;
475 				kd.extype |= KGDBEXIT_WITHADDR;
476 			}
477 
478 			goto doexit;
479 
480 		case 'S':    /* SSS  single step with signal SS */
481 			*ptr = '\0';	/* ignore the signal number for now */
482 			/* fall through */
483 
484 		case 's':
485 			kd.extype = KGDBEXIT_SINGLE;
486 
487 			if (hexToInt(&ptr, &addr)) {
488 				kd.exaddr = addr;
489 				kd.extype |= KGDBEXIT_WITHADDR;
490 			}
491 
492 		doexit:
493 /* Need to flush the instruction cache here, as we may have deposited a
494  * breakpoint, and the icache probably has no way of knowing that a data ref to
495  * some location may have changed something that is in the instruction cache.
496  */
497 			kgdb_flush_cache_all();
498 			kgdb_exit(regs, &kd);
499 			kgdb_active = 0;
500 			kgdb_interruptible(1);
501 			return (1);
502 
503 		case 'r':		/* Reset (if user process..exit ???)*/
504 			panic("kgdb reset.");
505 			break;
506 
507 		case 'P':    /* Pr=v  set reg r to value v (r and v are hex) */
508 			if (hexToInt(&ptr, &addr)
509 			    && *ptr++ == '='
510 			    && ((length = strlen(ptr)) & 1) == 0) {
511 				hex2mem(ptr, remcomRegBuffer, length/2);
512 				kgdb_putreg(regs, addr,
513 					remcomRegBuffer, length/2);
514 				strcpy(remcomOutBuffer,"OK");
515 			} else {
516 				kgdb_error(KGDBERR_BADPARAMS);
517 			}
518 			break;
519 		}			/* switch */
520 
521 		if (errnum != 0)
522 			sprintf(remcomOutBuffer, "E%02d", errnum);
523 
524 #ifdef KGDB_DEBUG
525 		if (kdebug)
526 			printf("kgdb: remcomOutBuffer: %s\n", remcomOutBuffer);
527 #endif
528 
529 		/* reply to the request */
530 		putpacket((unsigned char *)&remcomOutBuffer);
531 
532 	} /* while(1) */
533 }
534 
535 /*
536  * kgdb_init must be called *after* the
537  * monitor is relocated into ram
538  */
539 void
540 kgdb_init(void)
541 {
542 	kgdb_serial_init();
543 	debugger_exception_handler = handle_exception;
544 	initialized = 1;
545 
546 	putDebugStr("kgdb ready\n");
547 	puts("ready\n");
548 }
549 
550 void
551 kgdb_error(int errnum)
552 {
553 	longjmp_on_fault = 0;
554 	kgdb_longjmp(error_jmp_buf, errnum);
555 	panic("kgdb_error: longjmp failed!\n");
556 }
557 
558 /* Output string in GDB O-packet format if GDB has connected. If nothing
559    output, returns 0 (caller must then handle output). */
560 int
561 kgdb_output_string (const char* s, unsigned int count)
562 {
563 	char buffer[512];
564 
565 	count = (count <= (sizeof(buffer) / 2 - 2))
566 		? count : (sizeof(buffer) / 2 - 2);
567 
568 	buffer[0] = 'O';
569 	mem2hex ((char *)s, &buffer[1], count);
570 	putpacket((unsigned char *)&buffer);
571 
572 	return 1;
573 }
574 
575 void
576 breakpoint(void)
577 {
578 	if (!initialized) {
579 		printf("breakpoint() called b4 kgdb init\n");
580 		return;
581 	}
582 
583 	kgdb_breakpoint(0, 0);
584 }
585 
586 int
587 do_kgdb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
588 {
589     printf("Entering KGDB mode via exception handler...\n\n");
590     kgdb_breakpoint(argc - 1, argv + 1);
591     printf("\nReturned from KGDB mode\n");
592     return 0;
593 }
594 
595 U_BOOT_CMD(
596 	kgdb, CONFIG_SYS_MAXARGS, 1,	do_kgdb,
597 	"enter gdb remote debug mode",
598 	"[arg0 arg1 .. argN]\n"
599 	"    - executes a breakpoint so that kgdb mode is\n"
600 	"      entered via the exception handler. To return\n"
601 	"      to the monitor, the remote gdb debugger must\n"
602 	"      execute a \"continue\" or \"quit\" command.\n"
603 	"\n"
604 	"      if a program is loaded by the remote gdb, any args\n"
605 	"      passed to the kgdb command are given to the loaded\n"
606 	"      program if it is executed (see the \"hello_world\"\n"
607 	"      example program in the U-Boot examples directory)."
608 );
609