]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - common/kgdb.c
sandbox: Add a simple sound driver
[karo-tx-uboot.git] / common / kgdb.c
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 );