/* * Copyright (c) 2008 Travis Geiselbrecht * * Copyright (c) 2014, The Linux Foundation. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files * (the "Software"), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, * publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include #include #include #include #include #include #include #include #include #include #include #if ARCH_ARM #include #endif void __attribute__ ((noreturn)) __stack_chk_fail (void) { panic("stack smashing detected."); for(;;); } void spin(uint32_t usecs) { bigtime_t start = current_time_hires(); while ((current_time_hires() - start) < usecs) ; } void halt(void) { enter_critical_section(); // disable ints platform_halt(); } void dump_frame(void *frame) { enter_critical_section(); // disable ints #if ARCH_ARM dump_fault_frame((struct arm_fault_frame *)frame); #endif exit_critical_section(); // disable ints } void _panic(void *caller, const char *fmt, ...) { dprintf(ALWAYS, "panic (frame %p): \n", __GET_FRAME()); dump_frame(__GET_FRAME()); dprintf(ALWAYS, "panic (caller %p): ", caller); va_list ap; va_start(ap, fmt); _dvprintf(fmt, ap); va_end(ap); halt(); } int _dputs(const char *str) { while(*str != 0) { _dputc(*str++); } return 0; } int _dprintf(const char *fmt, ...) { char buf[256]; char ts_buf[13]; int err; snprintf(ts_buf, sizeof(ts_buf), "[%u] ",(unsigned int)current_time()); dputs(ALWAYS, ts_buf); va_list ap; va_start(ap, fmt); err = vsnprintf(buf, sizeof(buf), fmt, ap); va_end(ap); dputs(ALWAYS, buf); return err; } int _dvprintf(const char *fmt, va_list ap) { char buf[256]; int err; err = vsnprintf(buf, sizeof(buf), fmt, ap); dputs(ALWAYS, buf); return err; } void hexdump(const void *ptr, size_t len) { addr_t address = (addr_t)ptr; size_t count; int i; for (count = 0 ; count < len; count += 16) { printf("0x%08lx: ", address); printf("%08x %08x %08x %08x |", *(const uint32_t *)address, *(const uint32_t *)(address + 4), *(const uint32_t *)(address + 8), *(const uint32_t *)(address + 12)); for (i=0; i < 16; i++) { char c = *(const char *)(address + i); if (isalpha(c)) { printf("%c", c); } else { printf("."); } } printf("|\n"); address += 16; } } void hexdump8(const void *ptr, size_t len) { addr_t address = (addr_t)ptr; size_t count; int i; for (count = 0 ; count < len; count += 16) { printf("0x%08lx: ", address); for (i=0; i < 16; i++) { printf("0x%02hhx ", *(const uint8_t *)(address + i)); } printf("\n"); address += 16; } } #ifdef WITH_LIB_CONSOLE #include static int cmd_display_mem(int argc, const cmd_args *argv); static int cmd_modify_mem(int argc, const cmd_args *argv); static int cmd_fill_mem(int argc, const cmd_args *argv); static int cmd_reset(int argc, const cmd_args *argv); static int cmd_memtest(int argc, const cmd_args *argv); static int cmd_copy_mem(int argc, const cmd_args *argv); STATIC_COMMAND_START #if DEBUGLEVEL > 0 { "dw", "display memory in words", &cmd_display_mem }, { "dh", "display memory in halfwords", &cmd_display_mem }, { "db", "display memory in bytes", &cmd_display_mem }, { "mw", "modify word of memory", &cmd_modify_mem }, { "mh", "modify halfword of memory", &cmd_modify_mem }, { "mb", "modify byte of memory", &cmd_modify_mem }, { "fw", "fill range of memory by word", &cmd_fill_mem }, { "fh", "fill range of memory by halfword", &cmd_fill_mem }, { "fb", "fill range of memory by byte", &cmd_fill_mem }, { "mc", "copy a range of memory", &cmd_copy_mem }, #endif #if DEBUGLEVEL > 1 { "mtest", "simple memory test", &cmd_memtest }, #endif STATIC_COMMAND_END(mem); static int cmd_display_mem(int argc, const cmd_args *argv) { int size; if (argc < 3) { printf("not enough arguments\n"); printf("%s
\n", argv[0].str); return -1; } if (strcmp(argv[0].str, "dw") == 0) { size = 4; } else if (strcmp(argv[0].str, "dh") == 0) { size = 2; } else { size = 1; } unsigned long address = argv[1].u; size_t len = argv[2].u; unsigned long stop = address + len; int count = 0; if ((address & (size - 1)) != 0) { printf("unaligned address, cannot display\n"); return -1; } for ( ; address < stop; address += size) { if (count == 0) printf("0x%08lx: ", address); switch (size) { case 4: printf("%08x ", *(uint32_t *)address); break; case 2: printf("%04hx ", *(uint16_t *)address); break; case 1: printf("%02hhx ", *(uint8_t *)address); break; } count += size; if (count == 16) { printf("\n"); count = 0; } } if (count != 0) printf("\n"); return 0; } static int cmd_modify_mem(int argc, const cmd_args *argv) { int size; if (argc < 3) { printf("not enough arguments\n"); printf("%s
\n", argv[0].str); return -1; } if (strcmp(argv[0].str, "mw") == 0) { size = 4; } else if (strcmp(argv[0].str, "mh") == 0) { size = 2; } else { size = 1; } unsigned long address = argv[1].u; unsigned int val = argv[2].u; if ((address & (size - 1)) != 0) { printf("unaligned address, cannot modify\n"); return -1; } switch (size) { case 4: *(uint32_t *)address = (uint32_t)val; break; case 2: *(uint16_t *)address = (uint16_t)val; break; case 1: *(uint8_t *)address = (uint8_t)val; break; } return 0; } static int cmd_fill_mem(int argc, const cmd_args *argv) { int size; if (argc < 4) { printf("not enough arguments\n"); printf("%s
\n", argv[0].str); return -1; } if (strcmp(argv[0].str, "fw") == 0) { size = 4; } else if (strcmp(argv[0].str, "fh") == 0) { size = 2; } else { size = 1; } unsigned long address = argv[1].u; unsigned long len = argv[2].u; unsigned long stop = address + len; unsigned int val = argv[3].u; if ((address & (size - 1)) != 0) { printf("unaligned address, cannot modify\n"); return -1; } for ( ; address < stop; address += size) { switch (size) { case 4: *(uint32_t *)address = (uint32_t)val; break; case 2: *(uint16_t *)address = (uint16_t)val; break; case 1: *(uint8_t *)address = (uint8_t)val; break; } } return 0; } static int cmd_copy_mem(int argc, const cmd_args *argv) { if (argc < 4) { printf("not enough arguments\n"); printf("%s \n", argv[0].str); return -1; } addr_t source = argv[1].u; addr_t target = argv[2].u; size_t len = argv[3].u; memcpy((void *)target, (const void *)source, len); return 0; } static int cmd_memtest(int argc, const cmd_args *argv) { if (argc < 3) { printf("not enough arguments\n"); printf("%s \n", argv[0].str); return -1; } uint32_t *ptr; size_t len; ptr = (uint32_t *)argv[1].u; len = (size_t)argv[2].u; size_t i; // write out printf("writing first pass..."); for (i = 0; i < len / 4; i++) { ptr[i] = i; } printf("done\n"); // verify printf("verifying..."); for (i = 0; i < len / 4; i++) { if (ptr[i] != i) printf("error at %p\n", &ptr[i]); } printf("done\n"); return 0; } #endif