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