From 72afe34cf9c832ccbdf45048533f7d8269a7abe0 Mon Sep 17 00:00:00 2001 From: hexkyz Date: Tue, 14 Jul 2020 18:12:31 +0100 Subject: [PATCH] fusee/sept: fix error printing --- fusee/fusee-mtc/src/lib/log.h | 2 +- fusee/fusee-mtc/src/utils.c | 13 +++- fusee/fusee-primary/src/exception_handlers.c | 73 ++++++++++++++----- fusee/fusee-primary/src/lib/log.h | 2 +- fusee/fusee-primary/src/stage2.c | 2 +- fusee/fusee-primary/src/utils.c | 41 +---------- fusee/fusee-primary/src/utils.h | 3 - .../fusee-secondary/src/exception_handlers.c | 73 ++++++++++++++----- fusee/fusee-secondary/src/lib/log.h | 2 +- fusee/fusee-secondary/src/utils.c | 40 ++-------- fusee/fusee-secondary/src/utils.h | 4 - sept/sept-secondary/src/exception_handlers.c | 72 +++++++++++++----- sept/sept-secondary/src/lib/log.h | 2 +- sept/sept-secondary/src/utils.c | 42 ++--------- sept/sept-secondary/src/utils.h | 3 - 15 files changed, 197 insertions(+), 177 deletions(-) diff --git a/fusee/fusee-mtc/src/lib/log.h b/fusee/fusee-mtc/src/lib/log.h index 8a28b0835..d1c5777f3 100644 --- a/fusee/fusee-mtc/src/lib/log.h +++ b/fusee/fusee-mtc/src/lib/log.h @@ -17,7 +17,7 @@ #ifndef FUSEE_LOG_H #define FUSEE_LOG_H -#define PRINT_MESSAGE_MAX_LENGTH 512 +#define PRINT_MESSAGE_MAX_LENGTH 1024 #include diff --git a/fusee/fusee-mtc/src/utils.c b/fusee/fusee-mtc/src/utils.c index d06fe6e91..95577462e 100644 --- a/fusee/fusee-mtc/src/utils.c +++ b/fusee/fusee-mtc/src/utils.c @@ -17,17 +17,26 @@ #include #include #include "utils.h" +#include "display/video_fb.h" #include "lib/log.h" __attribute__ ((noreturn)) void generic_panic(void) { - print(SCREEN_LOG_LEVEL_ERROR, "Panic raised!"); - while (true) { /* Lock. */ } } __attribute__((noreturn)) void fatal_error(const char *fmt, ...) { + /* Forcefully initialize the screen if logging is disabled. */ + if (log_get_log_level() == SCREEN_LOG_LEVEL_NONE) { + /* Zero-fill the framebuffer and register it as printk provider. */ + video_init((void *)0xC0000000); + + /* Override the global logging level. */ + log_set_log_level(SCREEN_LOG_LEVEL_ERROR); + } + + /* Display fatal error. */ va_list args; print(SCREEN_LOG_LEVEL_ERROR, "Fatal error: "); va_start(args, fmt); diff --git a/fusee/fusee-primary/src/exception_handlers.c b/fusee/fusee-primary/src/exception_handlers.c index 821f8cb2d..6a005293a 100644 --- a/fusee/fusee-primary/src/exception_handlers.c +++ b/fusee/fusee-primary/src/exception_handlers.c @@ -19,9 +19,10 @@ #include "exception_handlers.h" #include "utils.h" #include "lib/log.h" +#include "lib/vsprintf.h" #define CODE_DUMP_SIZE 0x30 -#define STACK_DUMP_SIZE 0x60 +#define STACK_DUMP_SIZE 0x30 extern const uint32_t exception_handler_table[]; @@ -34,6 +35,40 @@ static const char *register_names[] = { "SP", "LR", "PC", "CPSR", }; +/* Adapted from https://gist.github.com/ccbrown/9722406 */ +static void hexdump(const void* data, size_t size, uintptr_t addrbase, char* strbuf) { + const uint8_t *d = (const uint8_t *)data; + char ascii[17]; + ascii[16] = '\0'; + + for (size_t i = 0; i < size; i++) { + if (i % 16 == 0) { + strbuf += sprintf(strbuf, "%0*" PRIXPTR ": | ", 2 * sizeof(addrbase), addrbase + i); + } + strbuf += sprintf(strbuf, "%02X ", d[i]); + if (d[i] >= ' ' && d[i] <= '~') { + ascii[i % 16] = d[i]; + } else { + ascii[i % 16] = '.'; + } + if ((i+1) % 8 == 0 || i+1 == size) { + strbuf += sprintf(strbuf, " "); + if ((i+1) % 16 == 0) { + strbuf += sprintf(strbuf, "| %s \n", ascii); + } else if (i+1 == size) { + ascii[(i+1) % 16] = '\0'; + if ((i+1) % 16 <= 8) { + strbuf += sprintf(strbuf, " "); + } + for (size_t j = (i+1) % 16; j < 16; j++) { + strbuf += sprintf(strbuf, " "); + } + strbuf += sprintf(strbuf, "| %s \n", ascii); + } + } + } +} + void setup_exception_handlers(void) { volatile uint32_t *bpmp_exception_handler_table = (volatile uint32_t *)0x6000F200; for (int i = 0; i < 8; i++) { @@ -44,38 +79,40 @@ void setup_exception_handlers(void) { } void exception_handler_main(uint32_t *registers, unsigned int exception_type) { + char exception_log[0x400]; uint8_t code_dump[CODE_DUMP_SIZE]; uint8_t stack_dump[STACK_DUMP_SIZE]; - size_t code_dump_size; - size_t stack_dump_size; + size_t code_dump_size; + size_t stack_dump_size; uint32_t pc = registers[15]; uint32_t cpsr = registers[16]; - uint32_t instr_addr = pc + ((cpsr & 0x20) ? 2 : 4) - CODE_DUMP_SIZE; - print(SCREEN_LOG_LEVEL_ERROR, "\nSomething went wrong...\n"); - + sprintf(exception_log + strlen(exception_log), "An exception occured!\n"); + code_dump_size = safecpy(code_dump, (const void *)instr_addr, CODE_DUMP_SIZE); stack_dump_size = safecpy(stack_dump, (const void *)registers[13], STACK_DUMP_SIZE); - print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "\nException type: %s\n", - exception_names[exception_type]); - print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "\nRegisters:\n\n"); + sprintf(exception_log + strlen(exception_log), "\nException type: %s\n", exception_names[exception_type]); + sprintf(exception_log + strlen(exception_log), "\nRegisters:\n"); /* Print r0 to pc. */ for (int i = 0; i < 16; i += 2) { - print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "%-7s%08"PRIX32" %-7s%08"PRIX32"\n", + sprintf(exception_log + strlen(exception_log), "%-7s%08"PRIX32" %-7s%08"PRIX32"\n", register_names[i], registers[i], register_names[i+1], registers[i+1]); } /* Print cpsr. */ - print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "%-7s%08"PRIX32"\n", register_names[16], registers[16]); - - print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "\nCode dump:\n"); - hexdump(code_dump, code_dump_size, instr_addr); - print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "\nStack dump:\n"); - hexdump(stack_dump, stack_dump_size, registers[13]); - print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "\n"); - fatal_error("An exception occured!\n"); + sprintf(exception_log + strlen(exception_log), "%-7s%08"PRIX32"\n", register_names[16], registers[16]); + + /* Print code and stack regions. */ + sprintf(exception_log + strlen(exception_log), "\nCode dump:\n"); + hexdump(code_dump, code_dump_size, instr_addr, exception_log + strlen(exception_log)); + sprintf(exception_log + strlen(exception_log), "\nStack dump:\n"); + hexdump(stack_dump, stack_dump_size, registers[13], exception_log + strlen(exception_log)); + sprintf(exception_log + strlen(exception_log), "\n"); + + /* Throw fatal error with the full exception log. */ + fatal_error(exception_log); } diff --git a/fusee/fusee-primary/src/lib/log.h b/fusee/fusee-primary/src/lib/log.h index 8a28b0835..d1c5777f3 100644 --- a/fusee/fusee-primary/src/lib/log.h +++ b/fusee/fusee-primary/src/lib/log.h @@ -17,7 +17,7 @@ #ifndef FUSEE_LOG_H #define FUSEE_LOG_H -#define PRINT_MESSAGE_MAX_LENGTH 512 +#define PRINT_MESSAGE_MAX_LENGTH 1024 #include diff --git a/fusee/fusee-primary/src/stage2.c b/fusee/fusee-primary/src/stage2.c index b267f1217..150fcb310 100644 --- a/fusee/fusee-primary/src/stage2.c +++ b/fusee/fusee-primary/src/stage2.c @@ -106,7 +106,7 @@ void load_stage2(const char *bct0) { } if (strlen(config.path) + 1 + sizeof(stage2_args_t) > CHAINLOADER_ARG_DATA_MAX_SIZE) { - print(SCREEN_LOG_LEVEL_ERROR, "Stage2's path name is too big!\n"); + fatal_error("Stage2's path name is too big!\n"); } if (!check_32bit_address_loadable(config.entrypoint)) { diff --git a/fusee/fusee-primary/src/utils.c b/fusee/fusee-primary/src/utils.c index 910e36c4e..51033eed7 100644 --- a/fusee/fusee-primary/src/utils.c +++ b/fusee/fusee-primary/src/utils.c @@ -26,6 +26,7 @@ #include "car.h" #include "btn.h" #include "lib/log.h" +#include "lib/vsprintf.h" #include "display/video_fb.h" #include @@ -112,11 +113,11 @@ __attribute__((noreturn)) void fatal_error(const char *fmt, ...) { /* Turn on the backlight after initializing the lfb */ /* to avoid flickering. */ display_backlight(true); - - /* Override the global logging level. */ - log_set_log_level(SCREEN_LOG_LEVEL_ERROR); } + /* Override the global logging level. */ + log_set_log_level(SCREEN_LOG_LEVEL_ERROR); + /* Display fatal error. */ va_list args; print(SCREEN_LOG_LEVEL_ERROR, "Fatal error: "); @@ -137,37 +138,3 @@ __attribute__((noinline)) bool overlaps(uint64_t as, uint64_t ae, uint64_t bs, u return true; return false; } - -/* Adapted from https://gist.github.com/ccbrown/9722406 */ -void hexdump(const void* data, size_t size, uintptr_t addrbase) { - const uint8_t *d = (const uint8_t *)data; - char ascii[17]; - ascii[16] = '\0'; - - for (size_t i = 0; i < size; i++) { - if (i % 16 == 0) { - print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "%0*" PRIXPTR ": | ", 2 * sizeof(addrbase), addrbase + i); - } - print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "%02X ", d[i]); - if (d[i] >= ' ' && d[i] <= '~') { - ascii[i % 16] = d[i]; - } else { - ascii[i % 16] = '.'; - } - if ((i+1) % 8 == 0 || i+1 == size) { - print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, " "); - if ((i+1) % 16 == 0) { - print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "| %s \n", ascii); - } else if (i+1 == size) { - ascii[(i+1) % 16] = '\0'; - if ((i+1) % 16 <= 8) { - print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, " "); - } - for (size_t j = (i+1) % 16; j < 16; j++) { - print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, " "); - } - print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "| %s \n", ascii); - } - } - } -} diff --git a/fusee/fusee-primary/src/utils.h b/fusee/fusee-primary/src/utils.h index 0b16ff6dc..d3eaea88e 100644 --- a/fusee/fusee-primary/src/utils.h +++ b/fusee/fusee-primary/src/utils.h @@ -117,15 +117,12 @@ static inline bool check_32bit_address_range_in_program(uintptr_t addr, size_t s overlaps_a(start, end, __start__, __end__); } -void hexdump(const void* data, size_t size, uintptr_t addrbase); - __attribute__((noreturn)) void watchdog_reboot(void); __attribute__((noreturn)) void pmc_reboot(uint32_t scratch0); __attribute__((noreturn)) void reboot_to_self(void); __attribute__((noreturn)) void wait_for_button_and_reboot(void); __attribute__((noreturn)) void generic_panic(void); - __attribute__((noreturn)) void fatal_error(const char *fmt, ...); #endif diff --git a/fusee/fusee-secondary/src/exception_handlers.c b/fusee/fusee-secondary/src/exception_handlers.c index 698129ee4..b09f5507c 100644 --- a/fusee/fusee-secondary/src/exception_handlers.c +++ b/fusee/fusee-secondary/src/exception_handlers.c @@ -14,6 +14,7 @@ * along with this program. If not, see . */ +#include #include #include "exception_handlers.h" @@ -22,7 +23,7 @@ #include "lib/log.h" #define CODE_DUMP_SIZE 0x30 -#define STACK_DUMP_SIZE 0x60 +#define STACK_DUMP_SIZE 0x30 extern const uint32_t exception_handler_table[]; @@ -35,6 +36,40 @@ static const char *register_names[] = { "SP", "LR", "PC", "CPSR", }; +/* Adapted from https://gist.github.com/ccbrown/9722406 */ +static void hexdump(const void* data, size_t size, uintptr_t addrbase, char* strbuf) { + const uint8_t *d = (const uint8_t *)data; + char ascii[17]; + ascii[16] = '\0'; + + for (size_t i = 0; i < size; i++) { + if (i % 16 == 0) { + strbuf += sprintf(strbuf, "%0*" PRIXPTR ": | ", 2 * sizeof(addrbase), addrbase + i); + } + strbuf += sprintf(strbuf, "%02X ", d[i]); + if (d[i] >= ' ' && d[i] <= '~') { + ascii[i % 16] = d[i]; + } else { + ascii[i % 16] = '.'; + } + if ((i+1) % 8 == 0 || i+1 == size) { + strbuf += sprintf(strbuf, " "); + if ((i+1) % 16 == 0) { + strbuf += sprintf(strbuf, "| %s \n", ascii); + } else if (i+1 == size) { + ascii[(i+1) % 16] = '\0'; + if ((i+1) % 16 <= 8) { + strbuf += sprintf(strbuf, " "); + } + for (size_t j = (i+1) % 16; j < 16; j++) { + strbuf += sprintf(strbuf, " "); + } + strbuf += sprintf(strbuf, "| %s \n", ascii); + } + } + } +} + void setup_exception_handlers(void) { volatile uint32_t *bpmp_exception_handler_table = (volatile uint32_t *)0x6000F200; for (int i = 0; i < 8; i++) { @@ -45,38 +80,40 @@ void setup_exception_handlers(void) { } void exception_handler_main(uint32_t *registers, unsigned int exception_type) { + char exception_log[0x400]; uint8_t code_dump[CODE_DUMP_SIZE]; uint8_t stack_dump[STACK_DUMP_SIZE]; - size_t code_dump_size; - size_t stack_dump_size; + size_t code_dump_size; + size_t stack_dump_size; uint32_t pc = registers[15]; uint32_t cpsr = registers[16]; - uint32_t instr_addr = pc + ((cpsr & 0x20) ? 2 : 4) - CODE_DUMP_SIZE; - print(SCREEN_LOG_LEVEL_ERROR, "\nSomething went wrong...\n"); - + sprintf(exception_log + strlen(exception_log), "An exception occured!\n"); + code_dump_size = safecpy(code_dump, (const void *)instr_addr, CODE_DUMP_SIZE); stack_dump_size = safecpy(stack_dump, (const void *)registers[13], STACK_DUMP_SIZE); - print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "\nException type: %s\n", - exception_names[exception_type]); - print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "\nRegisters:\n\n"); + sprintf(exception_log + strlen(exception_log), "\nException type: %s\n", exception_names[exception_type]); + sprintf(exception_log + strlen(exception_log), "\nRegisters:\n"); /* Print r0 to pc. */ for (int i = 0; i < 16; i += 2) { - print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "%-7s%08"PRIX32" %-7s%08"PRIX32"\n", + sprintf(exception_log + strlen(exception_log), "%-7s%08"PRIX32" %-7s%08"PRIX32"\n", register_names[i], registers[i], register_names[i+1], registers[i+1]); } /* Print cpsr. */ - print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "%-7s%08"PRIX32"\n", register_names[16], registers[16]); - - print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "\nCode dump:\n"); - hexdump(code_dump, code_dump_size, instr_addr); - print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "\nStack dump:\n"); - hexdump(stack_dump, stack_dump_size, registers[13]); - print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "\n"); - fatal_error("An exception occurred!\n"); + sprintf(exception_log + strlen(exception_log), "%-7s%08"PRIX32"\n", register_names[16], registers[16]); + + /* Print code and stack regions. */ + sprintf(exception_log + strlen(exception_log), "\nCode dump:\n"); + hexdump(code_dump, code_dump_size, instr_addr, exception_log + strlen(exception_log)); + sprintf(exception_log + strlen(exception_log), "\nStack dump:\n"); + hexdump(stack_dump, stack_dump_size, registers[13], exception_log + strlen(exception_log)); + sprintf(exception_log + strlen(exception_log), "\n"); + + /* Throw fatal error with the full exception log. */ + fatal_error(exception_log); } diff --git a/fusee/fusee-secondary/src/lib/log.h b/fusee/fusee-secondary/src/lib/log.h index 8a28b0835..d1c5777f3 100644 --- a/fusee/fusee-secondary/src/lib/log.h +++ b/fusee/fusee-secondary/src/lib/log.h @@ -17,7 +17,7 @@ #ifndef FUSEE_LOG_H #define FUSEE_LOG_H -#define PRINT_MESSAGE_MAX_LENGTH 512 +#define PRINT_MESSAGE_MAX_LENGTH 1024 #include diff --git a/fusee/fusee-secondary/src/utils.c b/fusee/fusee-secondary/src/utils.c index 2ea2aafd4..0e8f0abd5 100644 --- a/fusee/fusee-secondary/src/utils.c +++ b/fusee/fusee-secondary/src/utils.c @@ -157,12 +157,18 @@ __attribute__ ((noreturn)) void generic_panic(void) { } __attribute__((noreturn)) void fatal_error(const char *fmt, ...) { + /* Override the global logging level. */ + log_set_log_level(SCREEN_LOG_LEVEL_ERROR); + + /* Display fatal error. */ va_list args; print(SCREEN_LOG_LEVEL_ERROR, "Fatal error: "); va_start(args, fmt); vprint(SCREEN_LOG_LEVEL_ERROR, fmt, args); va_end(args); print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "\n Press POWER to reboot.\n"); + + /* Wait for button and reboot. */ wait_for_button_and_reboot(); } @@ -174,37 +180,3 @@ __attribute__((noinline)) bool overlaps(uint64_t as, uint64_t ae, uint64_t bs, u return true; return false; } - -/* Adapted from https://gist.github.com/ccbrown/9722406 */ -void hexdump(const void* data, size_t size, uintptr_t addrbase) { - const uint8_t *d = (const uint8_t *)data; - char ascii[17]; - ascii[16] = '\0'; - - for (size_t i = 0; i < size; i++) { - if (i % 16 == 0) { - printf("%0*" PRIXPTR ": | ", 2 * sizeof(addrbase), addrbase + i); - } - printf("%02X ", d[i]); - if (d[i] >= ' ' && d[i] <= '~') { - ascii[i % 16] = d[i]; - } else { - ascii[i % 16] = '.'; - } - if ((i+1) % 8 == 0 || i+1 == size) { - printf(" "); - if ((i+1) % 16 == 0) { - printf("| %s \n", ascii); - } else if (i+1 == size) { - ascii[(i+1) % 16] = '\0'; - if ((i+1) % 16 <= 8) { - printf(" "); - } - for (size_t j = (i+1) % 16; j < 16; j++) { - printf(" "); - } - printf("| %s \n", ascii); - } - } - } -} diff --git a/fusee/fusee-secondary/src/utils.h b/fusee/fusee-secondary/src/utils.h index d90b9cd99..846d7da9c 100644 --- a/fusee/fusee-secondary/src/utils.h +++ b/fusee/fusee-secondary/src/utils.h @@ -118,8 +118,6 @@ static inline bool check_32bit_address_range_in_program(uintptr_t addr, size_t s overlaps_a(start, end, __start__, __end__); } -void hexdump(const void* data, size_t size, uintptr_t addrbase); - __attribute__((noreturn)) void watchdog_reboot(void); __attribute__((noreturn)) void pmc_reboot(uint32_t scratch0); __attribute__((noreturn)) void reboot_to_fusee_primary(void); @@ -129,8 +127,6 @@ __attribute__((noreturn)) void wait_for_button_and_reboot(void); void wait_for_button(void); __attribute__((noreturn)) void generic_panic(void); - __attribute__((noreturn)) void fatal_error(const char *fmt, ...); - #endif diff --git a/sept/sept-secondary/src/exception_handlers.c b/sept/sept-secondary/src/exception_handlers.c index 821f8cb2d..7879dd622 100644 --- a/sept/sept-secondary/src/exception_handlers.c +++ b/sept/sept-secondary/src/exception_handlers.c @@ -21,7 +21,7 @@ #include "lib/log.h" #define CODE_DUMP_SIZE 0x30 -#define STACK_DUMP_SIZE 0x60 +#define STACK_DUMP_SIZE 0x30 extern const uint32_t exception_handler_table[]; @@ -34,6 +34,40 @@ static const char *register_names[] = { "SP", "LR", "PC", "CPSR", }; +/* Adapted from https://gist.github.com/ccbrown/9722406 */ +static void hexdump(const void* data, size_t size, uintptr_t addrbase, char* strbuf) { + const uint8_t *d = (const uint8_t *)data; + char ascii[17]; + ascii[16] = '\0'; + + for (size_t i = 0; i < size; i++) { + if (i % 16 == 0) { + strbuf += sprintf(strbuf, "%0*" PRIXPTR ": | ", 2 * sizeof(addrbase), addrbase + i); + } + strbuf += sprintf(strbuf, "%02X ", d[i]); + if (d[i] >= ' ' && d[i] <= '~') { + ascii[i % 16] = d[i]; + } else { + ascii[i % 16] = '.'; + } + if ((i+1) % 8 == 0 || i+1 == size) { + strbuf += sprintf(strbuf, " "); + if ((i+1) % 16 == 0) { + strbuf += sprintf(strbuf, "| %s \n", ascii); + } else if (i+1 == size) { + ascii[(i+1) % 16] = '\0'; + if ((i+1) % 16 <= 8) { + strbuf += sprintf(strbuf, " "); + } + for (size_t j = (i+1) % 16; j < 16; j++) { + strbuf += sprintf(strbuf, " "); + } + strbuf += sprintf(strbuf, "| %s \n", ascii); + } + } + } +} + void setup_exception_handlers(void) { volatile uint32_t *bpmp_exception_handler_table = (volatile uint32_t *)0x6000F200; for (int i = 0; i < 8; i++) { @@ -44,38 +78,40 @@ void setup_exception_handlers(void) { } void exception_handler_main(uint32_t *registers, unsigned int exception_type) { + char exception_log[0x400]; uint8_t code_dump[CODE_DUMP_SIZE]; uint8_t stack_dump[STACK_DUMP_SIZE]; - size_t code_dump_size; - size_t stack_dump_size; + size_t code_dump_size; + size_t stack_dump_size; uint32_t pc = registers[15]; uint32_t cpsr = registers[16]; - uint32_t instr_addr = pc + ((cpsr & 0x20) ? 2 : 4) - CODE_DUMP_SIZE; - print(SCREEN_LOG_LEVEL_ERROR, "\nSomething went wrong...\n"); - + sprintf(exception_log + strlen(exception_log), "An exception occured!\n"); + code_dump_size = safecpy(code_dump, (const void *)instr_addr, CODE_DUMP_SIZE); stack_dump_size = safecpy(stack_dump, (const void *)registers[13], STACK_DUMP_SIZE); - print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "\nException type: %s\n", - exception_names[exception_type]); - print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "\nRegisters:\n\n"); + sprintf(exception_log + strlen(exception_log), "\nException type: %s\n", exception_names[exception_type]); + sprintf(exception_log + strlen(exception_log), "\nRegisters:\n"); /* Print r0 to pc. */ for (int i = 0; i < 16; i += 2) { - print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "%-7s%08"PRIX32" %-7s%08"PRIX32"\n", + sprintf(exception_log + strlen(exception_log), "%-7s%08"PRIX32" %-7s%08"PRIX32"\n", register_names[i], registers[i], register_names[i+1], registers[i+1]); } /* Print cpsr. */ - print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "%-7s%08"PRIX32"\n", register_names[16], registers[16]); - - print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "\nCode dump:\n"); - hexdump(code_dump, code_dump_size, instr_addr); - print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "\nStack dump:\n"); - hexdump(stack_dump, stack_dump_size, registers[13]); - print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "\n"); - fatal_error("An exception occured!\n"); + sprintf(exception_log + strlen(exception_log), "%-7s%08"PRIX32"\n", register_names[16], registers[16]); + + /* Print code and stack regions. */ + sprintf(exception_log + strlen(exception_log), "\nCode dump:\n"); + hexdump(code_dump, code_dump_size, instr_addr, exception_log + strlen(exception_log)); + sprintf(exception_log + strlen(exception_log), "\nStack dump:\n"); + hexdump(stack_dump, stack_dump_size, registers[13], exception_log + strlen(exception_log)); + sprintf(exception_log + strlen(exception_log), "\n"); + + /* Throw fatal error with the full exception log. */ + fatal_error(exception_log); } diff --git a/sept/sept-secondary/src/lib/log.h b/sept/sept-secondary/src/lib/log.h index 8a28b0835..d1c5777f3 100644 --- a/sept/sept-secondary/src/lib/log.h +++ b/sept/sept-secondary/src/lib/log.h @@ -17,7 +17,7 @@ #ifndef FUSEE_LOG_H #define FUSEE_LOG_H -#define PRINT_MESSAGE_MAX_LENGTH 512 +#define PRINT_MESSAGE_MAX_LENGTH 1024 #include diff --git a/sept/sept-secondary/src/utils.c b/sept/sept-secondary/src/utils.c index 6ccf4cdd9..3a180c247 100644 --- a/sept/sept-secondary/src/utils.c +++ b/sept/sept-secondary/src/utils.c @@ -105,12 +105,18 @@ __attribute__ ((noreturn)) void generic_panic(void) { } __attribute__((noreturn)) void fatal_error(const char *fmt, ...) { + /* Override the global logging level. */ + log_set_log_level(SCREEN_LOG_LEVEL_ERROR); + + /* Display fatal error. */ va_list args; print(SCREEN_LOG_LEVEL_ERROR, "Fatal error: "); va_start(args, fmt); vprint(SCREEN_LOG_LEVEL_ERROR, fmt, args); va_end(args); - print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX,"\nPress POWER to reboot\n"); + print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "\n Press POWER to reboot.\n"); + + /* Wait for button and reboot. */ wait_for_button_and_reboot(); } @@ -122,37 +128,3 @@ __attribute__((noinline)) bool overlaps(uint64_t as, uint64_t ae, uint64_t bs, u return true; return false; } - -/* Adapted from https://gist.github.com/ccbrown/9722406 */ -void hexdump(const void* data, size_t size, uintptr_t addrbase) { - const uint8_t *d = (const uint8_t *)data; - char ascii[17]; - ascii[16] = '\0'; - - for (size_t i = 0; i < size; i++) { - if (i % 16 == 0) { - print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "%0*" PRIXPTR ": | ", 2 * sizeof(addrbase), addrbase + i); - } - print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "%02X ", d[i]); - if (d[i] >= ' ' && d[i] <= '~') { - ascii[i % 16] = d[i]; - } else { - ascii[i % 16] = '.'; - } - if ((i+1) % 8 == 0 || i+1 == size) { - print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, " "); - if ((i+1) % 16 == 0) { - print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "| %s \n", ascii); - } else if (i+1 == size) { - ascii[(i+1) % 16] = '\0'; - if ((i+1) % 16 <= 8) { - print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, " "); - } - for (size_t j = (i+1) % 16; j < 16; j++) { - print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, " "); - } - print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "| %s \n", ascii); - } - } - } -} diff --git a/sept/sept-secondary/src/utils.h b/sept/sept-secondary/src/utils.h index d4f0d8e6b..457df7602 100644 --- a/sept/sept-secondary/src/utils.h +++ b/sept/sept-secondary/src/utils.h @@ -117,8 +117,6 @@ static inline bool check_32bit_address_range_in_program(uintptr_t addr, size_t s overlaps_a(start, end, __start__, __end__); } -void hexdump(const void* data, size_t size, uintptr_t addrbase); - __attribute__((noreturn)) void watchdog_reboot(void); __attribute__((noreturn)) void pmc_reboot(uint32_t scratch0); void prepare_for_reboot_to_self(void); @@ -126,7 +124,6 @@ __attribute__((noreturn)) void reboot_to_self(void); __attribute__((noreturn)) void wait_for_button_and_reboot(void); __attribute__((noreturn)) void generic_panic(void); - __attribute__((noreturn)) void fatal_error(const char *fmt, ...); #endif