]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - common/kgdb.c
* Switch LWMON board default config from FRAM to EEPROM;
[karo-tx-uboot.git] / 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 #if (CONFIG_COMMANDS & CFG_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 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 = 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(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(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(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 #else
577
578 int kgdb_not_configured = 1;
579
580 #endif /* CFG_CMD_KGDB */