blob: e62f8068c573db269b2f997767759c14aef45d64 [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.");
Unnati Gandhia7e1fe02014-07-17 14:45:43 +053046 for(;;);
Maria Yud3200512014-05-28 15:57:51 +080047}
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -070048
49void spin(uint32_t usecs)
50{
51 bigtime_t start = current_time_hires();
52
53 while ((current_time_hires() - start) < usecs)
54 ;
55}
56
57void halt(void)
58{
59 enter_critical_section(); // disable ints
Travis Geiselbrechteb946052008-09-07 22:32:49 -070060 platform_halt();
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -070061}
62
Maria Yu639951a2014-05-29 14:15:54 +080063void dump_frame(void *frame)
64{
65 enter_critical_section(); // disable ints
66#if ARCH_ARM
67 dump_fault_frame((struct arm_fault_frame *)frame);
68#endif
69 exit_critical_section(); // disable ints
70}
71
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -070072void _panic(void *caller, const char *fmt, ...)
73{
Maria Yu639951a2014-05-29 14:15:54 +080074 dprintf(ALWAYS, "panic (frame %p): \n", __GET_FRAME());
75 dump_frame(__GET_FRAME());
Travis Geiselbrechteb946052008-09-07 22:32:49 -070076 dprintf(ALWAYS, "panic (caller %p): ", caller);
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -070077
78 va_list ap;
79 va_start(ap, fmt);
Travis Geiselbrechteb946052008-09-07 22:32:49 -070080 _dvprintf(fmt, ap);
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -070081 va_end(ap);
82
83 halt();
84}
85
Travis Geiselbrechteb946052008-09-07 22:32:49 -070086int _dputs(const char *str)
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -070087{
88 while(*str != 0) {
Travis Geiselbrechteb946052008-09-07 22:32:49 -070089 _dputc(*str++);
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -070090 }
91
92 return 0;
93}
94
Travis Geiselbrechteb946052008-09-07 22:32:49 -070095int _dprintf(const char *fmt, ...)
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -070096{
97 char buf[256];
Ajay Dudani81f9a782010-12-16 19:44:06 -080098 char ts_buf[13];
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -070099 int err;
100
Unnati Gandhia7e1fe02014-07-17 14:45:43 +0530101 snprintf(ts_buf, sizeof(ts_buf), "[%u] ",(unsigned int)current_time());
Ajay Dudani81f9a782010-12-16 19:44:06 -0800102 dputs(ALWAYS, ts_buf);
103
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -0700104 va_list ap;
105 va_start(ap, fmt);
Travis Geiselbrecht6c5fa8a2008-12-30 23:39:26 -0800106 err = vsnprintf(buf, sizeof(buf), fmt, ap);
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -0700107 va_end(ap);
108
Travis Geiselbrechteb946052008-09-07 22:32:49 -0700109 dputs(ALWAYS, buf);
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -0700110
111 return err;
112}
113
Travis Geiselbrechteb946052008-09-07 22:32:49 -0700114int _dvprintf(const char *fmt, va_list ap)
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -0700115{
116 char buf[256];
117 int err;
118
Travis Geiselbrecht6c5fa8a2008-12-30 23:39:26 -0800119 err = vsnprintf(buf, sizeof(buf), fmt, ap);
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -0700120
Travis Geiselbrechteb946052008-09-07 22:32:49 -0700121 dputs(ALWAYS, buf);
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -0700122
123 return err;
124}
125
126void hexdump(const void *ptr, size_t len)
127{
128 addr_t address = (addr_t)ptr;
129 size_t count;
130 int i;
131
132 for (count = 0 ; count < len; count += 16) {
133 printf("0x%08lx: ", address);
134 printf("%08x %08x %08x %08x |", *(const uint32_t *)address, *(const uint32_t *)(address + 4), *(const uint32_t *)(address + 8), *(const uint32_t *)(address + 12));
135 for (i=0; i < 16; i++) {
136 char c = *(const char *)(address + i);
137 if (isalpha(c)) {
138 printf("%c", c);
139 } else {
140 printf(".");
141 }
142 }
143 printf("|\n");
144 address += 16;
145 }
146}
147
148void hexdump8(const void *ptr, size_t len)
149{
150 addr_t address = (addr_t)ptr;
151 size_t count;
152 int i;
153
154 for (count = 0 ; count < len; count += 16) {
155 printf("0x%08lx: ", address);
156 for (i=0; i < 16; i++) {
157 printf("0x%02hhx ", *(const uint8_t *)(address + i));
158 }
159 printf("\n");
160 address += 16;
161 }
162}
163
Travis Geiselbrecht39deded2009-01-24 20:12:27 -0800164#ifdef WITH_LIB_CONSOLE
165#include <lib/console.h>
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -0700166
167static int cmd_display_mem(int argc, const cmd_args *argv);
168static int cmd_modify_mem(int argc, const cmd_args *argv);
169static int cmd_fill_mem(int argc, const cmd_args *argv);
170static int cmd_reset(int argc, const cmd_args *argv);
171static int cmd_memtest(int argc, const cmd_args *argv);
172static int cmd_copy_mem(int argc, const cmd_args *argv);
173
174STATIC_COMMAND_START
175#if DEBUGLEVEL > 0
176 { "dw", "display memory in words", &cmd_display_mem },
177 { "dh", "display memory in halfwords", &cmd_display_mem },
178 { "db", "display memory in bytes", &cmd_display_mem },
179 { "mw", "modify word of memory", &cmd_modify_mem },
180 { "mh", "modify halfword of memory", &cmd_modify_mem },
181 { "mb", "modify byte of memory", &cmd_modify_mem },
182 { "fw", "fill range of memory by word", &cmd_fill_mem },
183 { "fh", "fill range of memory by halfword", &cmd_fill_mem },
184 { "fb", "fill range of memory by byte", &cmd_fill_mem },
185 { "mc", "copy a range of memory", &cmd_copy_mem },
186#endif
187#if DEBUGLEVEL > 1
188 { "mtest", "simple memory test", &cmd_memtest },
189#endif
190STATIC_COMMAND_END(mem);
191
192static int cmd_display_mem(int argc, const cmd_args *argv)
193{
194 int size;
195
196 if (argc < 3) {
197 printf("not enough arguments\n");
198 printf("%s <address> <length>\n", argv[0].str);
199 return -1;
200 }
201
202 if (strcmp(argv[0].str, "dw") == 0) {
203 size = 4;
204 } else if (strcmp(argv[0].str, "dh") == 0) {
205 size = 2;
206 } else {
207 size = 1;
208 }
209
210 unsigned long address = argv[1].u;
211 size_t len = argv[2].u;
212 unsigned long stop = address + len;
213 int count = 0;
214
215 if ((address & (size - 1)) != 0) {
216 printf("unaligned address, cannot display\n");
217 return -1;
218 }
219
220 for ( ; address < stop; address += size) {
221 if (count == 0)
222 printf("0x%08lx: ", address);
223 switch (size) {
224 case 4:
225 printf("%08x ", *(uint32_t *)address);
226 break;
227 case 2:
228 printf("%04hx ", *(uint16_t *)address);
229 break;
230 case 1:
231 printf("%02hhx ", *(uint8_t *)address);
232 break;
233 }
234 count += size;
235 if (count == 16) {
236 printf("\n");
237 count = 0;
238 }
239 }
240
241 if (count != 0)
242 printf("\n");
243
244 return 0;
245}
246
247static int cmd_modify_mem(int argc, const cmd_args *argv)
248{
249 int size;
250
251 if (argc < 3) {
252 printf("not enough arguments\n");
253 printf("%s <address> <val>\n", argv[0].str);
254 return -1;
255 }
256
257 if (strcmp(argv[0].str, "mw") == 0) {
258 size = 4;
259 } else if (strcmp(argv[0].str, "mh") == 0) {
260 size = 2;
261 } else {
262 size = 1;
263 }
264
265 unsigned long address = argv[1].u;
266 unsigned int val = argv[2].u;
267
268 if ((address & (size - 1)) != 0) {
269 printf("unaligned address, cannot modify\n");
270 return -1;
271 }
272
273 switch (size) {
274 case 4:
275 *(uint32_t *)address = (uint32_t)val;
276 break;
277 case 2:
278 *(uint16_t *)address = (uint16_t)val;
279 break;
280 case 1:
281 *(uint8_t *)address = (uint8_t)val;
282 break;
283 }
284
285 return 0;
286}
287
288static int cmd_fill_mem(int argc, const cmd_args *argv)
289{
290 int size;
291
292 if (argc < 4) {
293 printf("not enough arguments\n");
294 printf("%s <address> <len> <val>\n", argv[0].str);
295 return -1;
296 }
297
298 if (strcmp(argv[0].str, "fw") == 0) {
299 size = 4;
300 } else if (strcmp(argv[0].str, "fh") == 0) {
301 size = 2;
302 } else {
303 size = 1;
304 }
305
306 unsigned long address = argv[1].u;
307 unsigned long len = argv[2].u;
308 unsigned long stop = address + len;
309 unsigned int val = argv[3].u;
310
311 if ((address & (size - 1)) != 0) {
312 printf("unaligned address, cannot modify\n");
313 return -1;
314 }
315
316 for ( ; address < stop; address += size) {
317 switch (size) {
318 case 4:
319 *(uint32_t *)address = (uint32_t)val;
320 break;
321 case 2:
322 *(uint16_t *)address = (uint16_t)val;
323 break;
324 case 1:
325 *(uint8_t *)address = (uint8_t)val;
326 break;
327 }
328 }
329
330 return 0;
331}
332
333static int cmd_copy_mem(int argc, const cmd_args *argv)
334{
335 if (argc < 4) {
336 printf("not enough arguments\n");
337 printf("%s <source address> <target address> <len>\n", argv[0].str);
338 return -1;
339 }
340
341 addr_t source = argv[1].u;
342 addr_t target = argv[2].u;
343 size_t len = argv[3].u;
344
345 memcpy((void *)target, (const void *)source, len);
346
347 return 0;
348}
349
350static int cmd_memtest(int argc, const cmd_args *argv)
351{
352 if (argc < 3) {
353 printf("not enough arguments\n");
354 printf("%s <base> <len>\n", argv[0].str);
355 return -1;
356 }
357
358 uint32_t *ptr;
359 size_t len;
360
361 ptr = (uint32_t *)argv[1].u;
362 len = (size_t)argv[2].u;
363
364 size_t i;
365 // write out
366 printf("writing first pass...");
367 for (i = 0; i < len / 4; i++) {
368 ptr[i] = i;
369 }
370 printf("done\n");
371
372 // verify
373 printf("verifying...");
374 for (i = 0; i < len / 4; i++) {
375 if (ptr[i] != i)
376 printf("error at %p\n", &ptr[i]);
377 }
378 printf("done\n");
379
380 return 0;
381}
382
383#endif
384