blob: f239bbeeaa8e9d0d78eee2344e4b68db665d5dd8 [file] [log] [blame]
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -07001/*
2 * Copyright (c) 2008 Travis Geiselbrecht
3 *
Maria Yud3200512014-05-28 15:57:51 +08004 * Copyright (c) 2014, The Linux Foundation. All rights reserved.
5 *
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -07006 * Permission is hereby granted, free of charge, to any person obtaining
7 * a copy of this software and associated documentation files
8 * (the "Software"), to deal in the Software without restriction,
9 * including without limitation the rights to use, copy, modify, merge,
10 * publish, distribute, sublicense, and/or sell copies of the Software,
11 * and to permit persons to whom the Software is furnished to do so,
12 * subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be
15 * included in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
21 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 */
25
26#include <ctype.h>
27#include <debug.h>
28#include <stdlib.h>
29#include <printf.h>
30#include <list.h>
31#include <string.h>
32#include <arch/ops.h>
33#include <platform.h>
Travis Geiselbrechteb946052008-09-07 22:32:49 -070034#include <platform/debug.h>
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -070035#include <kernel/thread.h>
Ajay Dudani81f9a782010-12-16 19:44:06 -080036#include <kernel/timer.h>
Maria Yud3200512014-05-28 15:57:51 +080037#include <rand.h>
Maria Yu639951a2014-05-29 14:15:54 +080038#if ARCH_ARM
39#include <arch/arm.h>
40#endif
Maria Yud3200512014-05-28 15:57:51 +080041
42void __attribute__ ((noreturn))
43__stack_chk_fail (void)
44{
45 panic("stack smashing detected.");
46}
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -070047
48void spin(uint32_t usecs)
49{
50 bigtime_t start = current_time_hires();
51
52 while ((current_time_hires() - start) < usecs)
53 ;
54}
55
56void halt(void)
57{
58 enter_critical_section(); // disable ints
Travis Geiselbrechteb946052008-09-07 22:32:49 -070059 platform_halt();
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -070060}
61
Maria Yu639951a2014-05-29 14:15:54 +080062void dump_frame(void *frame)
63{
64 enter_critical_section(); // disable ints
65#if ARCH_ARM
66 dump_fault_frame((struct arm_fault_frame *)frame);
67#endif
68 exit_critical_section(); // disable ints
69}
70
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -070071void _panic(void *caller, const char *fmt, ...)
72{
Maria Yu639951a2014-05-29 14:15:54 +080073 dprintf(ALWAYS, "panic (frame %p): \n", __GET_FRAME());
74 dump_frame(__GET_FRAME());
Travis Geiselbrechteb946052008-09-07 22:32:49 -070075 dprintf(ALWAYS, "panic (caller %p): ", caller);
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -070076
77 va_list ap;
78 va_start(ap, fmt);
Travis Geiselbrechteb946052008-09-07 22:32:49 -070079 _dvprintf(fmt, ap);
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -070080 va_end(ap);
81
82 halt();
83}
84
Travis Geiselbrechteb946052008-09-07 22:32:49 -070085int _dputs(const char *str)
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -070086{
87 while(*str != 0) {
Travis Geiselbrechteb946052008-09-07 22:32:49 -070088 _dputc(*str++);
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -070089 }
90
91 return 0;
92}
93
Travis Geiselbrechteb946052008-09-07 22:32:49 -070094int _dprintf(const char *fmt, ...)
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -070095{
96 char buf[256];
Ajay Dudani81f9a782010-12-16 19:44:06 -080097 char ts_buf[13];
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -070098 int err;
99
Ajay Dudani81f9a782010-12-16 19:44:06 -0800100 snprintf(ts_buf, sizeof(ts_buf), "[%u] ", current_time());
101 dputs(ALWAYS, ts_buf);
102
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -0700103 va_list ap;
104 va_start(ap, fmt);
Travis Geiselbrecht6c5fa8a2008-12-30 23:39:26 -0800105 err = vsnprintf(buf, sizeof(buf), fmt, ap);
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -0700106 va_end(ap);
107
Travis Geiselbrechteb946052008-09-07 22:32:49 -0700108 dputs(ALWAYS, buf);
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -0700109
110 return err;
111}
112
Travis Geiselbrechteb946052008-09-07 22:32:49 -0700113int _dvprintf(const char *fmt, va_list ap)
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -0700114{
115 char buf[256];
116 int err;
117
Travis Geiselbrecht6c5fa8a2008-12-30 23:39:26 -0800118 err = vsnprintf(buf, sizeof(buf), fmt, ap);
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -0700119
Travis Geiselbrechteb946052008-09-07 22:32:49 -0700120 dputs(ALWAYS, buf);
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -0700121
122 return err;
123}
124
125void hexdump(const void *ptr, size_t len)
126{
127 addr_t address = (addr_t)ptr;
128 size_t count;
129 int i;
130
131 for (count = 0 ; count < len; count += 16) {
132 printf("0x%08lx: ", address);
133 printf("%08x %08x %08x %08x |", *(const uint32_t *)address, *(const uint32_t *)(address + 4), *(const uint32_t *)(address + 8), *(const uint32_t *)(address + 12));
134 for (i=0; i < 16; i++) {
135 char c = *(const char *)(address + i);
136 if (isalpha(c)) {
137 printf("%c", c);
138 } else {
139 printf(".");
140 }
141 }
142 printf("|\n");
143 address += 16;
144 }
145}
146
147void hexdump8(const void *ptr, size_t len)
148{
149 addr_t address = (addr_t)ptr;
150 size_t count;
151 int i;
152
153 for (count = 0 ; count < len; count += 16) {
154 printf("0x%08lx: ", address);
155 for (i=0; i < 16; i++) {
156 printf("0x%02hhx ", *(const uint8_t *)(address + i));
157 }
158 printf("\n");
159 address += 16;
160 }
161}
162
Travis Geiselbrecht39deded2009-01-24 20:12:27 -0800163#ifdef WITH_LIB_CONSOLE
164#include <lib/console.h>
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -0700165
166static int cmd_display_mem(int argc, const cmd_args *argv);
167static int cmd_modify_mem(int argc, const cmd_args *argv);
168static int cmd_fill_mem(int argc, const cmd_args *argv);
169static int cmd_reset(int argc, const cmd_args *argv);
170static int cmd_memtest(int argc, const cmd_args *argv);
171static int cmd_copy_mem(int argc, const cmd_args *argv);
172
173STATIC_COMMAND_START
174#if DEBUGLEVEL > 0
175 { "dw", "display memory in words", &cmd_display_mem },
176 { "dh", "display memory in halfwords", &cmd_display_mem },
177 { "db", "display memory in bytes", &cmd_display_mem },
178 { "mw", "modify word of memory", &cmd_modify_mem },
179 { "mh", "modify halfword of memory", &cmd_modify_mem },
180 { "mb", "modify byte of memory", &cmd_modify_mem },
181 { "fw", "fill range of memory by word", &cmd_fill_mem },
182 { "fh", "fill range of memory by halfword", &cmd_fill_mem },
183 { "fb", "fill range of memory by byte", &cmd_fill_mem },
184 { "mc", "copy a range of memory", &cmd_copy_mem },
185#endif
186#if DEBUGLEVEL > 1
187 { "mtest", "simple memory test", &cmd_memtest },
188#endif
189STATIC_COMMAND_END(mem);
190
191static int cmd_display_mem(int argc, const cmd_args *argv)
192{
193 int size;
194
195 if (argc < 3) {
196 printf("not enough arguments\n");
197 printf("%s <address> <length>\n", argv[0].str);
198 return -1;
199 }
200
201 if (strcmp(argv[0].str, "dw") == 0) {
202 size = 4;
203 } else if (strcmp(argv[0].str, "dh") == 0) {
204 size = 2;
205 } else {
206 size = 1;
207 }
208
209 unsigned long address = argv[1].u;
210 size_t len = argv[2].u;
211 unsigned long stop = address + len;
212 int count = 0;
213
214 if ((address & (size - 1)) != 0) {
215 printf("unaligned address, cannot display\n");
216 return -1;
217 }
218
219 for ( ; address < stop; address += size) {
220 if (count == 0)
221 printf("0x%08lx: ", address);
222 switch (size) {
223 case 4:
224 printf("%08x ", *(uint32_t *)address);
225 break;
226 case 2:
227 printf("%04hx ", *(uint16_t *)address);
228 break;
229 case 1:
230 printf("%02hhx ", *(uint8_t *)address);
231 break;
232 }
233 count += size;
234 if (count == 16) {
235 printf("\n");
236 count = 0;
237 }
238 }
239
240 if (count != 0)
241 printf("\n");
242
243 return 0;
244}
245
246static int cmd_modify_mem(int argc, const cmd_args *argv)
247{
248 int size;
249
250 if (argc < 3) {
251 printf("not enough arguments\n");
252 printf("%s <address> <val>\n", argv[0].str);
253 return -1;
254 }
255
256 if (strcmp(argv[0].str, "mw") == 0) {
257 size = 4;
258 } else if (strcmp(argv[0].str, "mh") == 0) {
259 size = 2;
260 } else {
261 size = 1;
262 }
263
264 unsigned long address = argv[1].u;
265 unsigned int val = argv[2].u;
266
267 if ((address & (size - 1)) != 0) {
268 printf("unaligned address, cannot modify\n");
269 return -1;
270 }
271
272 switch (size) {
273 case 4:
274 *(uint32_t *)address = (uint32_t)val;
275 break;
276 case 2:
277 *(uint16_t *)address = (uint16_t)val;
278 break;
279 case 1:
280 *(uint8_t *)address = (uint8_t)val;
281 break;
282 }
283
284 return 0;
285}
286
287static int cmd_fill_mem(int argc, const cmd_args *argv)
288{
289 int size;
290
291 if (argc < 4) {
292 printf("not enough arguments\n");
293 printf("%s <address> <len> <val>\n", argv[0].str);
294 return -1;
295 }
296
297 if (strcmp(argv[0].str, "fw") == 0) {
298 size = 4;
299 } else if (strcmp(argv[0].str, "fh") == 0) {
300 size = 2;
301 } else {
302 size = 1;
303 }
304
305 unsigned long address = argv[1].u;
306 unsigned long len = argv[2].u;
307 unsigned long stop = address + len;
308 unsigned int val = argv[3].u;
309
310 if ((address & (size - 1)) != 0) {
311 printf("unaligned address, cannot modify\n");
312 return -1;
313 }
314
315 for ( ; address < stop; address += size) {
316 switch (size) {
317 case 4:
318 *(uint32_t *)address = (uint32_t)val;
319 break;
320 case 2:
321 *(uint16_t *)address = (uint16_t)val;
322 break;
323 case 1:
324 *(uint8_t *)address = (uint8_t)val;
325 break;
326 }
327 }
328
329 return 0;
330}
331
332static int cmd_copy_mem(int argc, const cmd_args *argv)
333{
334 if (argc < 4) {
335 printf("not enough arguments\n");
336 printf("%s <source address> <target address> <len>\n", argv[0].str);
337 return -1;
338 }
339
340 addr_t source = argv[1].u;
341 addr_t target = argv[2].u;
342 size_t len = argv[3].u;
343
344 memcpy((void *)target, (const void *)source, len);
345
346 return 0;
347}
348
349static int cmd_memtest(int argc, const cmd_args *argv)
350{
351 if (argc < 3) {
352 printf("not enough arguments\n");
353 printf("%s <base> <len>\n", argv[0].str);
354 return -1;
355 }
356
357 uint32_t *ptr;
358 size_t len;
359
360 ptr = (uint32_t *)argv[1].u;
361 len = (size_t)argv[2].u;
362
363 size_t i;
364 // write out
365 printf("writing first pass...");
366 for (i = 0; i < len / 4; i++) {
367 ptr[i] = i;
368 }
369 printf("done\n");
370
371 // verify
372 printf("verifying...");
373 for (i = 0; i < len / 4; i++) {
374 if (ptr[i] != i)
375 printf("error at %p\n", &ptr[i]);
376 }
377 printf("done\n");
378
379 return 0;
380}
381
382#endif
383