2 * Copyright 2014 Google Inc.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of
7 * the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but without any warranty; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
17 #include <libpayload.h>
19 #define OUTPUT_OVERRUN_MSG "GDB output buffer overrun (try increasing reply.size)!\n"
21 /* MMIO word size is not standardized, but *usually* 32 (even on ARM64) */
22 typedef u32 mmio_word_t
;
24 static const int timeout_us
= 100 * 1000;
26 /* Serial-specific glue code... add more transport layers here when desired. */
28 static void gdb_raw_putchar(u8 c
)
33 static int gdb_raw_getchar(void)
35 u64 start
= timer_us(0);
37 while (!serial_havechar())
38 if (timer_us(start
) > timeout_us
)
41 return serial_getchar();
44 void gdb_transport_init(void)
46 console_remove_output_driver(serial_putchar
);
49 void gdb_transport_teardown(void)
51 serial_console_init();
54 /* Hex digit character <-> number conversion (illegal chars undefined!). */
56 static u8
from_hex(unsigned char c
)
58 static const s8 values
[] = {
59 -1, 10, 11, 12, 13, 14, 15, -1,
60 -1, -1, -1, -1, -1, -1, -1, -1,
61 0, 1, 2, 3, 4, 5, 6, 7,
62 8, 9, -1, -1, -1, -1, -1, -1,
65 return values
[c
& 0x1f];
68 static char to_hex(u8 v
)
70 static const char digits
[] = "0123456789abcdef";
72 return digits
[v
& 0xf];
75 /* Message encode/decode functions (must access whole aligned words for MMIO) */
77 void gdb_message_encode_bytes(struct gdb_message
*message
, const void *data
,
80 die_if(message
->used
+ length
* 2 > message
->size
, OUTPUT_OVERRUN_MSG
);
81 const mmio_word_t
*aligned
=
82 (mmio_word_t
*)ALIGN_DOWN((uintptr_t)data
, sizeof(*aligned
));
83 mmio_word_t word
= be32toh(readl(aligned
++));
85 u8 byte
= (word
>> ((((void *)aligned
- data
) - 1) * 8));
86 message
->buf
[message
->used
++] = to_hex(byte
>> 4);
87 message
->buf
[message
->used
++] = to_hex(byte
& 0xf);
88 if (length
&& ++data
== (void *)aligned
)
89 word
= be32toh(readl(aligned
++));
93 void gdb_message_decode_bytes(const struct gdb_message
*message
, int offset
,
94 void *data
, int length
)
96 die_if(offset
+ 2 * length
> message
->used
, "Decode overrun in GDB "
97 "message: %.*s", message
->used
, message
->buf
);
98 mmio_word_t
*aligned
=
99 (mmio_word_t
*)ALIGN_DOWN((uintptr_t)data
, sizeof(*aligned
));
100 int shift
= ((void *)(aligned
+ 1) - data
) * 8;
101 mmio_word_t word
= be32toh(readl(aligned
)) >> shift
;
104 word
|= from_hex(message
->buf
[offset
++]) << 4;
105 word
|= from_hex(message
->buf
[offset
++]);
106 if (++data
- (void *)aligned
== sizeof(*aligned
))
107 writel(htobe32(word
), aligned
++);
109 if (data
!= (void *)aligned
) {
110 shift
= ((void *)(aligned
+ 1) - data
) * 8;
111 clrsetbits_be32(aligned
, ~((1 << shift
) - 1), word
<< shift
);
115 void gdb_message_encode_zero_bytes(struct gdb_message
*message
, int length
)
117 die_if(message
->used
+ length
* 2 > message
->size
, OUTPUT_OVERRUN_MSG
);
118 memset(message
->buf
+ message
->used
, '0', length
* 2);
119 message
->used
+= length
* 2;
122 void gdb_message_add_string(struct gdb_message
*message
, const char *string
)
124 message
->used
+= strlcpy((char *)message
->buf
+ message
->used
,
125 string
, message
->size
- message
->used
);
127 /* Check >= instead of > to account for strlcpy's trailing '\0'. */
128 die_if(message
->used
>= message
->size
, OUTPUT_OVERRUN_MSG
);
131 void gdb_message_encode_int(struct gdb_message
*message
, uintptr_t val
)
133 int length
= sizeof(uintptr_t) * 2 - __builtin_clz(val
) / 4;
134 die_if(message
->used
+ length
> message
->size
, OUTPUT_OVERRUN_MSG
);
136 message
->buf
[message
->used
++] =
137 to_hex((val
>> length
* 4) & 0xf);
140 uintptr_t gdb_message_decode_int(const struct gdb_message
*message
, int offset
,
145 die_if(length
> sizeof(uintptr_t) * 2, "GDB decoding invalid number: "
146 "%.*s", message
->used
, message
->buf
);
150 val
|= from_hex(message
->buf
[offset
++]);
156 /* Like strtok/strsep: writes back offset argument, returns original offset. */
157 int gdb_message_tokenize(const struct gdb_message
*message
, int *offset
)
160 while (!strchr(",;:", message
->buf
[(*offset
)++]))
161 die_if(*offset
>= message
->used
, "Undelimited token in GDB "
162 "message at offset %d: %.*s",
163 token
, message
->used
, message
->buf
);
167 /* High-level send/receive functions. */
169 void gdb_get_command(struct gdb_message
*command
)
179 u8 running_checksum
= 0;
180 enum command_state state
= STATE_WAITING
;
183 int c
= gdb_raw_getchar();
186 * Timeout waiting for a byte. Reset the
189 state
= STATE_WAITING
;
196 running_checksum
= 0;
198 state
= STATE_COMMAND
;
203 state
= STATE_CHECKSUM0
;
206 die_if(command
->used
>= command
->size
, "GDB input buf"
207 "fer overrun (try increasing command.size)!\n");
208 command
->buf
[command
->used
++] = c
;
209 running_checksum
+= c
;
211 case STATE_CHECKSUM0
:
212 checksum
= from_hex(c
) << 4;
213 state
= STATE_CHECKSUM1
;
215 case STATE_CHECKSUM1
:
216 checksum
+= from_hex(c
);
217 if (running_checksum
== checksum
) {
218 gdb_raw_putchar('+');
221 state
= STATE_WAITING
;
222 gdb_raw_putchar('-');
229 void gdb_send_reply(const struct gdb_message
*reply
)
232 int retries
= 1 * 1000 * 1000 / timeout_us
;
235 for (i
= 0; i
< reply
->used
; i
++)
236 checksum
+= reply
->buf
[i
];
239 gdb_raw_putchar('$');
240 for (i
= 0; i
< reply
->used
; i
++)
241 gdb_raw_putchar(reply
->buf
[i
]);
242 gdb_raw_putchar('#');
243 gdb_raw_putchar(to_hex(checksum
>> 4));
244 gdb_raw_putchar(to_hex(checksum
& 0xf));
245 } while (gdb_raw_getchar() != '+' && retries
--);