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