]> git.sur5r.net Git - u-boot/blob - common/kgdb.c
fsl_pci_init_port end-point initialization is broken
[u-boot] / common / kgdb.c
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 );