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