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
102static char remcomInBuffer[BUFMAX];
103static char remcomOutBuffer[BUFMAX];
104static char remcomRegBuffer[BUFMAX];
105
106static int initialized = 0;
107static int kgdb_active;
108static struct pt_regs entry_regs;
109static long error_jmp_buf[BUFMAX/2];
110static int longjmp_on_fault = 0;
111#ifdef KGDB_DEBUG
112static int kdebug = 1;
113#endif
114
115static const char hexchars[]="0123456789abcdef";
116
117/* Convert ch from a hex digit to an int */
118static int
119hex(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 */
133static unsigned char *
134mem2hex(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*/
161static char *
162hex2mem(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 */
200static int
201hexToInt(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>     */
225static void
226getpacket(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.  */
287static void
288putpacket(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 */
316static int
317handle_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 */
530int kgdb_init(void)
531{
532	puts("KGDB:  ");
533
534	kgdb_serial_init();
535	debugger_exception_handler = handle_exception;
536	initialized = 1;
537
538	putDebugStr("kgdb ready\n");
539	puts("ready\n");
540
541	return 0;
542}
543
544void
545kgdb_error(int errnum)
546{
547	longjmp_on_fault = 0;
548	kgdb_longjmp(error_jmp_buf, errnum);
549	panic("kgdb_error: longjmp failed!\n");
550}
551
552/* Output string in GDB O-packet format if GDB has connected. If nothing
553   output, returns 0 (caller must then handle output). */
554int
555kgdb_output_string (const char* s, unsigned int count)
556{
557	char buffer[512];
558
559	count = (count <= (sizeof(buffer) / 2 - 2))
560		? count : (sizeof(buffer) / 2 - 2);
561
562	buffer[0] = 'O';
563	mem2hex ((char *)s, &buffer[1], count);
564	putpacket((unsigned char *)&buffer);
565
566	return 1;
567}
568
569void
570breakpoint(void)
571{
572	if (!initialized) {
573		printf("breakpoint() called b4 kgdb init\n");
574		return;
575	}
576
577	kgdb_breakpoint(0, 0);
578}
579
580int
581do_kgdb(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
582{
583    printf("Entering KGDB mode via exception handler...\n\n");
584    kgdb_breakpoint(argc - 1, argv + 1);
585    printf("\nReturned from KGDB mode\n");
586    return 0;
587}
588
589U_BOOT_CMD(
590	kgdb, CONFIG_SYS_MAXARGS, 1,	do_kgdb,
591	"enter gdb remote debug mode",
592	"[arg0 arg1 .. argN]\n"
593	"    - executes a breakpoint so that kgdb mode is\n"
594	"      entered via the exception handler. To return\n"
595	"      to the monitor, the remote gdb debugger must\n"
596	"      execute a \"continue\" or \"quit\" command.\n"
597	"\n"
598	"      if a program is loaded by the remote gdb, any args\n"
599	"      passed to the kgdb command are given to the loaded\n"
600	"      program if it is executed (see the \"hello_world\"\n"
601	"      example program in the U-Boot examples directory)."
602);
603