blob: afb2443434148b5419cbf66dd6a3e713bf8c4463 [file] [log] [blame]
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -07001/*
2 * Copyright (c) 2008 Travis Geiselbrecht
3 *
Maria Yue2e80352014-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 Yue2e80352014-05-28 15:57:51 +080037#include <rand.h>
Unnati Gandhieef3dbf2014-07-17 14:45:43 +053038#if ARCH_ARM
39#include <arch/arm.h>
40#endif
Maria Yue2e80352014-05-28 15:57:51 +080041
42void __attribute__ ((noreturn))
43__stack_chk_fail (void)
44{
45 panic("stack smashing detected.");
Unnati Gandhieef3dbf2014-07-17 14:45:43 +053046 for(;;);
Maria Yue2e80352014-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
63void _panic(void *caller, const char *fmt, ...)
64{
Travis Geiselbrechteb946052008-09-07 22:32:49 -070065 dprintf(ALWAYS, "panic (caller %p): ", caller);
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -070066
67 va_list ap;
68 va_start(ap, fmt);
Travis Geiselbrechteb946052008-09-07 22:32:49 -070069 _dvprintf(fmt, ap);
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -070070 va_end(ap);
71
72 halt();
73}
74
Travis Geiselbrechteb946052008-09-07 22:32:49 -070075int _dputs(const char *str)
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -070076{
77 while(*str != 0) {
Travis Geiselbrechteb946052008-09-07 22:32:49 -070078 _dputc(*str++);
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -070079 }
80
81 return 0;
82}
83
Travis Geiselbrechteb946052008-09-07 22:32:49 -070084int _dprintf(const char *fmt, ...)
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -070085{
86 char buf[256];
Ajay Dudani81f9a782010-12-16 19:44:06 -080087 char ts_buf[13];
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -070088 int err;
89
Unnati Gandhieef3dbf2014-07-17 14:45:43 +053090 snprintf(ts_buf, sizeof(ts_buf), "[%u] ",(unsigned int)current_time());
Ajay Dudani81f9a782010-12-16 19:44:06 -080091 dputs(ALWAYS, ts_buf);
92
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -070093 va_list ap;
94 va_start(ap, fmt);
Travis Geiselbrecht6c5fa8a2008-12-30 23:39:26 -080095 err = vsnprintf(buf, sizeof(buf), fmt, ap);
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -070096 va_end(ap);
97
Travis Geiselbrechteb946052008-09-07 22:32:49 -070098 dputs(ALWAYS, buf);
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -070099
100 return err;
101}
102
Travis Geiselbrechteb946052008-09-07 22:32:49 -0700103int _dvprintf(const char *fmt, va_list ap)
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -0700104{
105 char buf[256];
106 int err;
107
Travis Geiselbrecht6c5fa8a2008-12-30 23:39:26 -0800108 err = vsnprintf(buf, sizeof(buf), fmt, ap);
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -0700109
Travis Geiselbrechteb946052008-09-07 22:32:49 -0700110 dputs(ALWAYS, buf);
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -0700111
112 return err;
113}
114
115void hexdump(const void *ptr, size_t len)
116{
117 addr_t address = (addr_t)ptr;
118 size_t count;
119 int i;
120
121 for (count = 0 ; count < len; count += 16) {
122 printf("0x%08lx: ", address);
123 printf("%08x %08x %08x %08x |", *(const uint32_t *)address, *(const uint32_t *)(address + 4), *(const uint32_t *)(address + 8), *(const uint32_t *)(address + 12));
124 for (i=0; i < 16; i++) {
125 char c = *(const char *)(address + i);
126 if (isalpha(c)) {
127 printf("%c", c);
128 } else {
129 printf(".");
130 }
131 }
132 printf("|\n");
133 address += 16;
134 }
135}
136
137void hexdump8(const void *ptr, size_t len)
138{
139 addr_t address = (addr_t)ptr;
140 size_t count;
141 int i;
142
143 for (count = 0 ; count < len; count += 16) {
144 printf("0x%08lx: ", address);
145 for (i=0; i < 16; i++) {
146 printf("0x%02hhx ", *(const uint8_t *)(address + i));
147 }
148 printf("\n");
149 address += 16;
150 }
151}
152
Travis Geiselbrecht39deded2009-01-24 20:12:27 -0800153#ifdef WITH_LIB_CONSOLE
154#include <lib/console.h>
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -0700155
156static int cmd_display_mem(int argc, const cmd_args *argv);
157static int cmd_modify_mem(int argc, const cmd_args *argv);
158static int cmd_fill_mem(int argc, const cmd_args *argv);
159static int cmd_reset(int argc, const cmd_args *argv);
160static int cmd_memtest(int argc, const cmd_args *argv);
161static int cmd_copy_mem(int argc, const cmd_args *argv);
162
163STATIC_COMMAND_START
164#if DEBUGLEVEL > 0
165 { "dw", "display memory in words", &cmd_display_mem },
166 { "dh", "display memory in halfwords", &cmd_display_mem },
167 { "db", "display memory in bytes", &cmd_display_mem },
168 { "mw", "modify word of memory", &cmd_modify_mem },
169 { "mh", "modify halfword of memory", &cmd_modify_mem },
170 { "mb", "modify byte of memory", &cmd_modify_mem },
171 { "fw", "fill range of memory by word", &cmd_fill_mem },
172 { "fh", "fill range of memory by halfword", &cmd_fill_mem },
173 { "fb", "fill range of memory by byte", &cmd_fill_mem },
174 { "mc", "copy a range of memory", &cmd_copy_mem },
175#endif
176#if DEBUGLEVEL > 1
177 { "mtest", "simple memory test", &cmd_memtest },
178#endif
179STATIC_COMMAND_END(mem);
180
181static int cmd_display_mem(int argc, const cmd_args *argv)
182{
183 int size;
184
185 if (argc < 3) {
186 printf("not enough arguments\n");
187 printf("%s <address> <length>\n", argv[0].str);
188 return -1;
189 }
190
191 if (strcmp(argv[0].str, "dw") == 0) {
192 size = 4;
193 } else if (strcmp(argv[0].str, "dh") == 0) {
194 size = 2;
195 } else {
196 size = 1;
197 }
198
199 unsigned long address = argv[1].u;
200 size_t len = argv[2].u;
201 unsigned long stop = address + len;
202 int count = 0;
203
204 if ((address & (size - 1)) != 0) {
205 printf("unaligned address, cannot display\n");
206 return -1;
207 }
208
209 for ( ; address < stop; address += size) {
210 if (count == 0)
211 printf("0x%08lx: ", address);
212 switch (size) {
213 case 4:
214 printf("%08x ", *(uint32_t *)address);
215 break;
216 case 2:
217 printf("%04hx ", *(uint16_t *)address);
218 break;
219 case 1:
220 printf("%02hhx ", *(uint8_t *)address);
221 break;
222 }
223 count += size;
224 if (count == 16) {
225 printf("\n");
226 count = 0;
227 }
228 }
229
230 if (count != 0)
231 printf("\n");
232
233 return 0;
234}
235
236static int cmd_modify_mem(int argc, const cmd_args *argv)
237{
238 int size;
239
240 if (argc < 3) {
241 printf("not enough arguments\n");
242 printf("%s <address> <val>\n", argv[0].str);
243 return -1;
244 }
245
246 if (strcmp(argv[0].str, "mw") == 0) {
247 size = 4;
248 } else if (strcmp(argv[0].str, "mh") == 0) {
249 size = 2;
250 } else {
251 size = 1;
252 }
253
254 unsigned long address = argv[1].u;
255 unsigned int val = argv[2].u;
256
257 if ((address & (size - 1)) != 0) {
258 printf("unaligned address, cannot modify\n");
259 return -1;
260 }
261
262 switch (size) {
263 case 4:
264 *(uint32_t *)address = (uint32_t)val;
265 break;
266 case 2:
267 *(uint16_t *)address = (uint16_t)val;
268 break;
269 case 1:
270 *(uint8_t *)address = (uint8_t)val;
271 break;
272 }
273
274 return 0;
275}
276
277static int cmd_fill_mem(int argc, const cmd_args *argv)
278{
279 int size;
280
281 if (argc < 4) {
282 printf("not enough arguments\n");
283 printf("%s <address> <len> <val>\n", argv[0].str);
284 return -1;
285 }
286
287 if (strcmp(argv[0].str, "fw") == 0) {
288 size = 4;
289 } else if (strcmp(argv[0].str, "fh") == 0) {
290 size = 2;
291 } else {
292 size = 1;
293 }
294
295 unsigned long address = argv[1].u;
296 unsigned long len = argv[2].u;
297 unsigned long stop = address + len;
298 unsigned int val = argv[3].u;
299
300 if ((address & (size - 1)) != 0) {
301 printf("unaligned address, cannot modify\n");
302 return -1;
303 }
304
305 for ( ; address < stop; address += size) {
306 switch (size) {
307 case 4:
308 *(uint32_t *)address = (uint32_t)val;
309 break;
310 case 2:
311 *(uint16_t *)address = (uint16_t)val;
312 break;
313 case 1:
314 *(uint8_t *)address = (uint8_t)val;
315 break;
316 }
317 }
318
319 return 0;
320}
321
322static int cmd_copy_mem(int argc, const cmd_args *argv)
323{
324 if (argc < 4) {
325 printf("not enough arguments\n");
326 printf("%s <source address> <target address> <len>\n", argv[0].str);
327 return -1;
328 }
329
330 addr_t source = argv[1].u;
331 addr_t target = argv[2].u;
332 size_t len = argv[3].u;
333
334 memcpy((void *)target, (const void *)source, len);
335
336 return 0;
337}
338
339static int cmd_memtest(int argc, const cmd_args *argv)
340{
341 if (argc < 3) {
342 printf("not enough arguments\n");
343 printf("%s <base> <len>\n", argv[0].str);
344 return -1;
345 }
346
347 uint32_t *ptr;
348 size_t len;
349
350 ptr = (uint32_t *)argv[1].u;
351 len = (size_t)argv[2].u;
352
353 size_t i;
354 // write out
355 printf("writing first pass...");
356 for (i = 0; i < len / 4; i++) {
357 ptr[i] = i;
358 }
359 printf("done\n");
360
361 // verify
362 printf("verifying...");
363 for (i = 0; i < len / 4; i++) {
364 if (ptr[i] != i)
365 printf("error at %p\n", &ptr[i]);
366 }
367 printf("done\n");
368
369 return 0;
370}
371
372#endif
373