blob: 84d0678b1f122a392a6a82a3c07fbab17fcd98f7 [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>
38
39void __attribute__ ((noreturn))
40__stack_chk_fail (void)
41{
42 panic("stack smashing detected.");
43}
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -070044
45void spin(uint32_t usecs)
46{
47 bigtime_t start = current_time_hires();
48
49 while ((current_time_hires() - start) < usecs)
50 ;
51}
52
53void halt(void)
54{
55 enter_critical_section(); // disable ints
Travis Geiselbrechteb946052008-09-07 22:32:49 -070056 platform_halt();
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -070057}
58
59void _panic(void *caller, const char *fmt, ...)
60{
Travis Geiselbrechteb946052008-09-07 22:32:49 -070061 dprintf(ALWAYS, "panic (caller %p): ", caller);
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -070062
63 va_list ap;
64 va_start(ap, fmt);
Travis Geiselbrechteb946052008-09-07 22:32:49 -070065 _dvprintf(fmt, ap);
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -070066 va_end(ap);
67
68 halt();
69}
70
Travis Geiselbrechteb946052008-09-07 22:32:49 -070071int _dputs(const char *str)
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -070072{
73 while(*str != 0) {
Travis Geiselbrechteb946052008-09-07 22:32:49 -070074 _dputc(*str++);
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -070075 }
76
77 return 0;
78}
79
Travis Geiselbrechteb946052008-09-07 22:32:49 -070080int _dprintf(const char *fmt, ...)
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -070081{
82 char buf[256];
Ajay Dudani81f9a782010-12-16 19:44:06 -080083 char ts_buf[13];
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -070084 int err;
85
Ajay Dudani81f9a782010-12-16 19:44:06 -080086 snprintf(ts_buf, sizeof(ts_buf), "[%u] ", current_time());
87 dputs(ALWAYS, ts_buf);
88
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -070089 va_list ap;
90 va_start(ap, fmt);
Travis Geiselbrecht6c5fa8a2008-12-30 23:39:26 -080091 err = vsnprintf(buf, sizeof(buf), fmt, ap);
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -070092 va_end(ap);
93
Travis Geiselbrechteb946052008-09-07 22:32:49 -070094 dputs(ALWAYS, buf);
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -070095
96 return err;
97}
98
Travis Geiselbrechteb946052008-09-07 22:32:49 -070099int _dvprintf(const char *fmt, va_list ap)
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -0700100{
101 char buf[256];
102 int err;
103
Travis Geiselbrecht6c5fa8a2008-12-30 23:39:26 -0800104 err = vsnprintf(buf, sizeof(buf), fmt, ap);
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -0700105
Travis Geiselbrechteb946052008-09-07 22:32:49 -0700106 dputs(ALWAYS, buf);
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -0700107
108 return err;
109}
110
111void hexdump(const void *ptr, size_t len)
112{
113 addr_t address = (addr_t)ptr;
114 size_t count;
115 int i;
116
117 for (count = 0 ; count < len; count += 16) {
118 printf("0x%08lx: ", address);
119 printf("%08x %08x %08x %08x |", *(const uint32_t *)address, *(const uint32_t *)(address + 4), *(const uint32_t *)(address + 8), *(const uint32_t *)(address + 12));
120 for (i=0; i < 16; i++) {
121 char c = *(const char *)(address + i);
122 if (isalpha(c)) {
123 printf("%c", c);
124 } else {
125 printf(".");
126 }
127 }
128 printf("|\n");
129 address += 16;
130 }
131}
132
133void hexdump8(const void *ptr, size_t len)
134{
135 addr_t address = (addr_t)ptr;
136 size_t count;
137 int i;
138
139 for (count = 0 ; count < len; count += 16) {
140 printf("0x%08lx: ", address);
141 for (i=0; i < 16; i++) {
142 printf("0x%02hhx ", *(const uint8_t *)(address + i));
143 }
144 printf("\n");
145 address += 16;
146 }
147}
148
Travis Geiselbrecht39deded2009-01-24 20:12:27 -0800149#ifdef WITH_LIB_CONSOLE
150#include <lib/console.h>
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -0700151
152static int cmd_display_mem(int argc, const cmd_args *argv);
153static int cmd_modify_mem(int argc, const cmd_args *argv);
154static int cmd_fill_mem(int argc, const cmd_args *argv);
155static int cmd_reset(int argc, const cmd_args *argv);
156static int cmd_memtest(int argc, const cmd_args *argv);
157static int cmd_copy_mem(int argc, const cmd_args *argv);
158
159STATIC_COMMAND_START
160#if DEBUGLEVEL > 0
161 { "dw", "display memory in words", &cmd_display_mem },
162 { "dh", "display memory in halfwords", &cmd_display_mem },
163 { "db", "display memory in bytes", &cmd_display_mem },
164 { "mw", "modify word of memory", &cmd_modify_mem },
165 { "mh", "modify halfword of memory", &cmd_modify_mem },
166 { "mb", "modify byte of memory", &cmd_modify_mem },
167 { "fw", "fill range of memory by word", &cmd_fill_mem },
168 { "fh", "fill range of memory by halfword", &cmd_fill_mem },
169 { "fb", "fill range of memory by byte", &cmd_fill_mem },
170 { "mc", "copy a range of memory", &cmd_copy_mem },
171#endif
172#if DEBUGLEVEL > 1
173 { "mtest", "simple memory test", &cmd_memtest },
174#endif
175STATIC_COMMAND_END(mem);
176
177static int cmd_display_mem(int argc, const cmd_args *argv)
178{
179 int size;
180
181 if (argc < 3) {
182 printf("not enough arguments\n");
183 printf("%s <address> <length>\n", argv[0].str);
184 return -1;
185 }
186
187 if (strcmp(argv[0].str, "dw") == 0) {
188 size = 4;
189 } else if (strcmp(argv[0].str, "dh") == 0) {
190 size = 2;
191 } else {
192 size = 1;
193 }
194
195 unsigned long address = argv[1].u;
196 size_t len = argv[2].u;
197 unsigned long stop = address + len;
198 int count = 0;
199
200 if ((address & (size - 1)) != 0) {
201 printf("unaligned address, cannot display\n");
202 return -1;
203 }
204
205 for ( ; address < stop; address += size) {
206 if (count == 0)
207 printf("0x%08lx: ", address);
208 switch (size) {
209 case 4:
210 printf("%08x ", *(uint32_t *)address);
211 break;
212 case 2:
213 printf("%04hx ", *(uint16_t *)address);
214 break;
215 case 1:
216 printf("%02hhx ", *(uint8_t *)address);
217 break;
218 }
219 count += size;
220 if (count == 16) {
221 printf("\n");
222 count = 0;
223 }
224 }
225
226 if (count != 0)
227 printf("\n");
228
229 return 0;
230}
231
232static int cmd_modify_mem(int argc, const cmd_args *argv)
233{
234 int size;
235
236 if (argc < 3) {
237 printf("not enough arguments\n");
238 printf("%s <address> <val>\n", argv[0].str);
239 return -1;
240 }
241
242 if (strcmp(argv[0].str, "mw") == 0) {
243 size = 4;
244 } else if (strcmp(argv[0].str, "mh") == 0) {
245 size = 2;
246 } else {
247 size = 1;
248 }
249
250 unsigned long address = argv[1].u;
251 unsigned int val = argv[2].u;
252
253 if ((address & (size - 1)) != 0) {
254 printf("unaligned address, cannot modify\n");
255 return -1;
256 }
257
258 switch (size) {
259 case 4:
260 *(uint32_t *)address = (uint32_t)val;
261 break;
262 case 2:
263 *(uint16_t *)address = (uint16_t)val;
264 break;
265 case 1:
266 *(uint8_t *)address = (uint8_t)val;
267 break;
268 }
269
270 return 0;
271}
272
273static int cmd_fill_mem(int argc, const cmd_args *argv)
274{
275 int size;
276
277 if (argc < 4) {
278 printf("not enough arguments\n");
279 printf("%s <address> <len> <val>\n", argv[0].str);
280 return -1;
281 }
282
283 if (strcmp(argv[0].str, "fw") == 0) {
284 size = 4;
285 } else if (strcmp(argv[0].str, "fh") == 0) {
286 size = 2;
287 } else {
288 size = 1;
289 }
290
291 unsigned long address = argv[1].u;
292 unsigned long len = argv[2].u;
293 unsigned long stop = address + len;
294 unsigned int val = argv[3].u;
295
296 if ((address & (size - 1)) != 0) {
297 printf("unaligned address, cannot modify\n");
298 return -1;
299 }
300
301 for ( ; address < stop; address += size) {
302 switch (size) {
303 case 4:
304 *(uint32_t *)address = (uint32_t)val;
305 break;
306 case 2:
307 *(uint16_t *)address = (uint16_t)val;
308 break;
309 case 1:
310 *(uint8_t *)address = (uint8_t)val;
311 break;
312 }
313 }
314
315 return 0;
316}
317
318static int cmd_copy_mem(int argc, const cmd_args *argv)
319{
320 if (argc < 4) {
321 printf("not enough arguments\n");
322 printf("%s <source address> <target address> <len>\n", argv[0].str);
323 return -1;
324 }
325
326 addr_t source = argv[1].u;
327 addr_t target = argv[2].u;
328 size_t len = argv[3].u;
329
330 memcpy((void *)target, (const void *)source, len);
331
332 return 0;
333}
334
335static int cmd_memtest(int argc, const cmd_args *argv)
336{
337 if (argc < 3) {
338 printf("not enough arguments\n");
339 printf("%s <base> <len>\n", argv[0].str);
340 return -1;
341 }
342
343 uint32_t *ptr;
344 size_t len;
345
346 ptr = (uint32_t *)argv[1].u;
347 len = (size_t)argv[2].u;
348
349 size_t i;
350 // write out
351 printf("writing first pass...");
352 for (i = 0; i < len / 4; i++) {
353 ptr[i] = i;
354 }
355 printf("done\n");
356
357 // verify
358 printf("verifying...");
359 for (i = 0; i < len / 4; i++) {
360 if (ptr[i] != i)
361 printf("error at %p\n", &ptr[i]);
362 }
363 printf("done\n");
364
365 return 0;
366}
367
368#endif
369