change all print* calls to use the new print with a log_level

This commit is contained in:
Resaec 2018-09-23 23:22:25 +02:00
parent 7548c8ecfa
commit 8cc266174d
No known key found for this signature in database
GPG key ID: 5E890BD898EA9064
9 changed files with 79 additions and 54 deletions

View file

@ -20,6 +20,7 @@
#include "lib/driver_utils.h" #include "lib/driver_utils.h"
#include "utils.h" #include "utils.h"
#include "display/video_fb.h" #include "display/video_fb.h"
#include "log.h"
#define CODE_DUMP_SIZE 0x30 #define CODE_DUMP_SIZE 0x30
#define STACK_DUMP_SIZE 0x60 #define STACK_DUMP_SIZE 0x60
@ -55,26 +56,26 @@ void exception_handler_main(uint32_t *registers, unsigned int exception_type) {
uint32_t instr_addr = pc + ((cpsr & 0x20) ? 2 : 4) - CODE_DUMP_SIZE; uint32_t instr_addr = pc + ((cpsr & 0x20) ? 2 : 4) - CODE_DUMP_SIZE;
printk("\nSomething went wrong...\n"); print(SCREEN_LOG_LEVEL_ERROR, "\nSomething went wrong...\n");
code_dump_size = safecpy(code_dump, (const void *)instr_addr, CODE_DUMP_SIZE); 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); stack_dump_size = safecpy(stack_dump, (const void *)registers[13], STACK_DUMP_SIZE);
printk("\nException type: %s\n", exception_names[exception_type]); print(SCREEN_LOG_LEVEL_ERROR, "\nException type: %s\n", exception_names[exception_type]);
printk("\nRegisters:\n\n"); print(SCREEN_LOG_LEVEL_ERROR, "\nRegisters:\n\n");
/* Print r0 to pc. */ /* Print r0 to pc. */
for (int i = 0; i < 16; i += 2) { for (int i = 0; i < 16; i += 2) {
printk("%-7s%08"PRIX32" %-7s%08"PRIX32"\n", register_names[i], registers[i], register_names[i+1], registers[i+1]); print(SCREEN_LOG_LEVEL_ERROR, "%-7s%08"PRIX32" %-7s%08"PRIX32"\n", register_names[i], registers[i], register_names[i+1], registers[i+1]);
} }
/* Print cpsr. */ /* Print cpsr. */
printk("%-7s%08"PRIX32"\n", register_names[16], registers[16]); print(SCREEN_LOG_LEVEL_ERROR, "%-7s%08"PRIX32"\n", register_names[16], registers[16]);
printk("\nCode dump:\n"); print(SCREEN_LOG_LEVEL_ERROR, "\nCode dump:\n");
hexdump(code_dump, code_dump_size, instr_addr); hexdump(code_dump, code_dump_size, instr_addr);
printk("\nStack dump:\n"); print(SCREEN_LOG_LEVEL_ERROR, "\nStack dump:\n");
hexdump(stack_dump, stack_dump_size, registers[13]); hexdump(stack_dump, stack_dump_size, registers[13]);
printk("\n"); print(SCREEN_LOG_LEVEL_ERROR, "\n");
fatal_error("An exception occured!\n"); fatal_error("An exception occurred!\n");
} }

View file

@ -20,7 +20,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdarg.h> #include <stdarg.h>
#define vprintk vprintf //#define vprint vprintf
#define printk printf //#define print printf
#endif #endif

View file

@ -24,6 +24,7 @@
#include "fs_utils.h" #include "fs_utils.h"
#include "stage2.h" #include "stage2.h"
#include "lib/ini.h" #include "lib/ini.h"
#include "log.h"
static loader_ctx_t g_loader_ctx = {0}; static loader_ctx_t g_loader_ctx = {0};
@ -103,7 +104,7 @@ static void load_list_entry(const char *key) {
} }
static void parse_loadlist(const char *ll) { static void parse_loadlist(const char *ll) {
printf("Parsing load list: %s\n", ll); print(SCREEN_LOG_LEVEL_DEBUG, "Parsing load list: %s\n", ll);
char load_list[0x200] = {0}; char load_list[0x200] = {0};
strncpy(load_list, ll, 0x200 - 1); strncpy(load_list, ll, 0x200 - 1);

View file

@ -19,6 +19,7 @@
#include <string.h> #include <string.h>
#include <errno.h> #include <errno.h>
#include <malloc.h> #include <malloc.h>
#include "utils.h" #include "utils.h"
#include "panic.h" #include "panic.h"
#include "exception_handlers.h" #include "exception_handlers.h"
@ -32,7 +33,7 @@
#include "gpt.h" #include "gpt.h"
#include "display/video_fb.h" #include "display/video_fb.h"
#include "sdmmc/sdmmc.h" #include "sdmmc/sdmmc.h"
#include "print.h" #include "log.h"
extern void (*__program_exit_callback)(int rc); extern void (*__program_exit_callback)(int rc);
@ -92,23 +93,23 @@ int main(int argc, void **argv) {
/* Initialize the display, console, FS, etc. */ /* Initialize the display, console, FS, etc. */
setup_env(); setup_env();
print(PRINT_LOG_MANDATORY, u8"Welcome to Atmosphère Fusée Stage 2!\n"); print(SCREEN_LOG_LEVEL_MANDATORY, u8"Welcome to Atmosphère Fusée Stage 2!\n");
print(PRINT_LOG_DEBUG, "Stage 2 executing from: %s\n", (const char *)argv[STAGE2_ARGV_PROGRAM_PATH]); print(SCREEN_LOG_LEVEL_DEBUG, "Stage 2 executing from: %s\n", (const char *)argv[STAGE2_ARGV_PROGRAM_PATH]);
/* This will load all remaining binaries off of the SD. */ /* This will load all remaining binaries off of the SD. */
load_payload(g_stage2_args->bct0); load_payload(g_stage2_args->bct0);
print(PRINT_LOG_INFO, "Loaded payloads!\n"); print(SCREEN_LOG_LEVEL_INFO, "Loaded payloads!\n");
g_do_nxboot = loader_ctx->chainload_entrypoint == 0; g_do_nxboot = loader_ctx->chainload_entrypoint == 0;
if (g_do_nxboot) { if (g_do_nxboot) {
print(PRINT_LOG_INFO, "Now performing nxboot.\n"); print(SCREEN_LOG_LEVEL_INFO, "Now performing nxboot.\n");
uint32_t boot_memaddr = nxboot_main(); uint32_t boot_memaddr = nxboot_main();
nxboot_finish(boot_memaddr); nxboot_finish(boot_memaddr);
} else { } else {
/* TODO: What else do we want to do in terms of argc/argv? */ /* TODO: What else do we want to do in terms of argc/argv? */
const char *path = get_loader_ctx()->file_paths_to_load[get_loader_ctx()->file_id_of_entrypoint]; const char *path = get_loader_ctx()->file_paths_to_load[get_loader_ctx()->file_id_of_entrypoint];
print(PRINT_LOG_INFO, "Now chainloading.\n"); print(SCREEN_LOG_LEVEL_INFO, "Now chainloading.\n");
g_chainloader_argc = 1; g_chainloader_argc = 1;
strcpy(g_chainloader_arg_data, path); strcpy(g_chainloader_arg_data, path);
} }

View file

@ -45,6 +45,7 @@
#define u8 uint8_t #define u8 uint8_t
#define u32 uint32_t #define u32 uint32_t
#include "exosphere_bin.h" #include "exosphere_bin.h"
#include "log.h"
#undef u8 #undef u8
#undef u32 #undef u32
@ -175,6 +176,7 @@ static void nxboot_move_bootconfig() {
fatal_error("[NXBOOT]: Failed to open BootConfig from eMMC!\n"); fatal_error("[NXBOOT]: Failed to open BootConfig from eMMC!\n");
} }
if (fread(bootconfig, 0x4000, 1, bcfile) < 1) { if (fread(bootconfig, 0x4000, 1, bcfile) < 1) {
fclose(bcfile);
fatal_error("[NXBOOT]: Failed to read BootConfig!\n"); fatal_error("[NXBOOT]: Failed to read BootConfig!\n");
} }
fclose(bcfile); fclose(bcfile);
@ -218,7 +220,7 @@ uint32_t nxboot_main(void) {
} }
/* Read Package2 from a file, otherwise from its partition(s). */ /* Read Package2 from a file, otherwise from its partition(s). */
printf("[NXBOOT]: Reading package2...\n"); print(SCREEN_LOG_LEVEL_INFO, "[NXBOOT]: Reading package2...\n");
if (loader_ctx->package2_path[0] != '\0') { if (loader_ctx->package2_path[0] != '\0') {
pk2file = fopen(loader_ctx->package2_path, "rb"); pk2file = fopen(loader_ctx->package2_path, "rb");
if (pk2file == NULL) { if (pk2file == NULL) {
@ -230,26 +232,29 @@ uint32_t nxboot_main(void) {
fatal_error("[NXBOOT]: Failed to open Package2 from eMMC: %s!\n", strerror(errno)); fatal_error("[NXBOOT]: Failed to open Package2 from eMMC: %s!\n", strerror(errno));
} }
if (fseek(pk2file, 0x4000, SEEK_SET) != 0) { if (fseek(pk2file, 0x4000, SEEK_SET) != 0) {
fatal_error("[NXBOOT]: Failed to seek Package2 in eMMC: %s!\n", strerror(errno));
fclose(pk2file); fclose(pk2file);
fatal_error("[NXBOOT]: Failed to seek Package2 in eMMC: %s!\n", strerror(errno));
} }
} }
setvbuf(pk2file, NULL, _IONBF, 0); /* Workaround. */ setvbuf(pk2file, NULL, _IONBF, 0); /* Workaround. */
if (fread(package2, sizeof(package2_header_t), 1, pk2file) < 1) { if (fread(package2, sizeof(package2_header_t), 1, pk2file) < 1) {
fclose(pk2file);
fatal_error("[NXBOOT]: Failed to read Package2!\n"); fatal_error("[NXBOOT]: Failed to read Package2!\n");
} }
package2_size = package2_meta_get_size(&package2->metadata); package2_size = package2_meta_get_size(&package2->metadata);
if ((package2_size > PACKAGE2_SIZE_MAX) || (package2_size <= sizeof(package2_header_t))) { if ((package2_size > PACKAGE2_SIZE_MAX) || (package2_size <= sizeof(package2_header_t))) {
fclose(pk2file);
fatal_error("[NXBOOT]: Package2 is too big or too small!\n"); fatal_error("[NXBOOT]: Package2 is too big or too small!\n");
} }
if (fread(package2->data, package2_size - sizeof(package2_header_t), 1, pk2file) < 1) { if (fread(package2->data, package2_size - sizeof(package2_header_t), 1, pk2file) < 1) {
fclose(pk2file);
fatal_error("[NXBOOT]: Failed to read Package2!\n"); fatal_error("[NXBOOT]: Failed to read Package2!\n");
} }
fclose(pk2file); fclose(pk2file);
/* Read and parse boot0. */ /* Read and parse boot0. */
printf("[NXBOOT]: Reading boot0...\n"); print(SCREEN_LOG_LEVEL_INFO, "[NXBOOT]: Reading boot0...\n");
boot0 = fopen("boot0:/", "rb"); boot0 = fopen("boot0:/", "rb");
if ((boot0 == NULL) || (package1_read_and_parse_boot0(&package1loader, &package1loader_size, g_keyblobs, &available_revision, boot0) == -1)) { if ((boot0 == NULL) || (package1_read_and_parse_boot0(&package1loader, &package1loader_size, g_keyblobs, &available_revision, boot0) == -1)) {
fatal_error("[NXBOOT]: Couldn't parse boot0: %s!\n", strerror(errno)); fatal_error("[NXBOOT]: Couldn't parse boot0: %s!\n", strerror(errno));
@ -286,17 +291,17 @@ uint32_t nxboot_main(void) {
if (!target_firmware) if (!target_firmware)
fatal_error("[NXBOOT]: Failed to detect target firmware!\n"); fatal_error("[NXBOOT]: Failed to detect target firmware!\n");
else else
printf("[NXBOOT]: Detected target firmware %ld!\n", target_firmware); print(SCREEN_LOG_LEVEL_INFO, "[NXBOOT]: Detected target firmware %ld!\n", target_firmware);
/* Setup boot configuration for Exosphère. */ /* Setup boot configuration for Exosphère. */
nxboot_configure_exosphere(target_firmware); nxboot_configure_exosphere(target_firmware);
/* Initialize Boot Reason on older firmware versions. */ /* Initialize Boot Reason on older firmware versions. */
if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < EXOSPHERE_TARGET_FIRMWARE_400) { if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < EXOSPHERE_TARGET_FIRMWARE_400) {
printf("[NXBOOT]: Initializing Boot Reason...\n"); print(SCREEN_LOG_LEVEL_INFO, "[NXBOOT]: Initializing Boot Reason...\n");
nxboot_set_bootreason(); nxboot_set_bootreason();
} }
/* Derive keydata. */ /* Derive keydata. */
if (derive_nx_keydata(MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware, g_keyblobs, available_revision, tsec_fw, tsec_fw_size) != 0) { if (derive_nx_keydata(MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware, g_keyblobs, available_revision, tsec_fw, tsec_fw_size) != 0) {
fatal_error("[NXBOOT]: Key derivation failed!\n"); fatal_error("[NXBOOT]: Key derivation failed!\n");
@ -311,7 +316,7 @@ uint32_t nxboot_main(void) {
/* Allocate memory for the warmboot firmware. */ /* Allocate memory for the warmboot firmware. */
warmboot_fw = malloc(warmboot_fw_size); warmboot_fw = malloc(warmboot_fw_size);
if (warmboot_fw == NULL) { if (warmboot_fw == NULL) {
fatal_error("[NXBOOT]: Out of memory!\n"); fatal_error("[NXBOOT]: Out of memory!\n");
} }
@ -333,7 +338,7 @@ uint32_t nxboot_main(void) {
fatal_error("[NXBOOT]: Could not read the warmboot firmware from Package1!\n"); fatal_error("[NXBOOT]: Could not read the warmboot firmware from Package1!\n");
} }
} }
/* Select the right address for the warmboot firmware. */ /* Select the right address for the warmboot firmware. */
if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < EXOSPHERE_TARGET_FIRMWARE_400) { if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < EXOSPHERE_TARGET_FIRMWARE_400) {
warmboot_memaddr = (void *)0x8000D000; warmboot_memaddr = (void *)0x8000D000;
@ -342,23 +347,23 @@ uint32_t nxboot_main(void) {
} else { } else {
warmboot_memaddr = (void *)0x4003D800; warmboot_memaddr = (void *)0x4003D800;
} }
printf("[NXBOOT]: Copying warmboot firmware...\n"); print(SCREEN_LOG_LEVEL_INFO, "[NXBOOT]: Copying warmboot firmware...\n");
/* Copy the warmboot firmware and set the address in PMC if necessary. */ /* Copy the warmboot firmware and set the address in PMC if necessary. */
if (warmboot_fw && (warmboot_fw_size > 0)) { if (warmboot_fw && (warmboot_fw_size > 0)) {
memcpy(warmboot_memaddr, warmboot_fw, warmboot_fw_size); memcpy(warmboot_memaddr, warmboot_fw, warmboot_fw_size);
if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < EXOSPHERE_TARGET_FIRMWARE_400) if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < EXOSPHERE_TARGET_FIRMWARE_400)
pmc->scratch1 = (uint32_t)warmboot_memaddr; pmc->scratch1 = (uint32_t)warmboot_memaddr;
} }
printf("[NXBOOT]: Rebuilding package2...\n"); print(SCREEN_LOG_LEVEL_INFO, "[NXBOOT]: Rebuilding package2...\n");
/* Patch package2, adding Thermosphère + custom KIPs. */ /* Patch package2, adding Thermosphère + custom KIPs. */
package2_rebuild_and_copy(package2, MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware); package2_rebuild_and_copy(package2, MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware);
printf(u8"[NXBOOT]: Reading Exosphère...\n"); print(SCREEN_LOG_LEVEL_INFO, u8"[NXBOOT]: Reading Exosphère...\n");
/* Select the right address for Exosphère. */ /* Select the right address for Exosphère. */
if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < EXOSPHERE_TARGET_FIRMWARE_400) { if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < EXOSPHERE_TARGET_FIRMWARE_400) {
exosphere_memaddr = (void *)0x4002D000; exosphere_memaddr = (void *)0x4002D000;
@ -382,11 +387,11 @@ uint32_t nxboot_main(void) {
} else { } else {
memcpy(exosphere_memaddr, exosphere_bin, exosphere_bin_size); memcpy(exosphere_memaddr, exosphere_bin, exosphere_bin_size);
} }
/* Move BootConfig. */ /* Move BootConfig. */
printf("[NXBOOT]: Moving BootConfig...\n"); print(SCREEN_LOG_LEVEL_INFO, "[NXBOOT]: Moving BootConfig...\n");
nxboot_move_bootconfig(); nxboot_move_bootconfig();
/* Set 3.0.0/3.0.1/3.0.2 warmboot security check. */ /* Set 3.0.0/3.0.1/3.0.2 warmboot security check. */
if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware == EXOSPHERE_TARGET_FIRMWARE_300) { if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware == EXOSPHERE_TARGET_FIRMWARE_300) {
const package1loader_header_t *package1loader_header = (const package1loader_header_t *)package1loader; const package1loader_header_t *package1loader_header = (const package1loader_header_t *)package1loader;
@ -395,7 +400,7 @@ uint32_t nxboot_main(void) {
else if (!strcmp(package1loader_header->build_timestamp, "20170710161758")) else if (!strcmp(package1loader_header->build_timestamp, "20170710161758"))
pmc->secure_scratch32 = 0x104; /* Warmboot 3.0.1/3.0.2 security check. */ pmc->secure_scratch32 = 0x104; /* Warmboot 3.0.1/3.0.2 security check. */
} }
/* Clean up. */ /* Clean up. */
free(package1loader); free(package1loader);
if (loader_ctx->tsecfw_path[0] != '\0') { if (loader_ctx->tsecfw_path[0] != '\0') {
@ -405,8 +410,8 @@ uint32_t nxboot_main(void) {
free(warmboot_fw); free(warmboot_fw);
} }
free(package2); free(package2);
printf("[NXBOOT]: Powering on the CCPLEX...\n"); print(SCREEN_LOG_LEVEL_INFO, "[NXBOOT]: Powering on the CCPLEX...\n");
/* Display splash screen. */ /* Display splash screen. */
display_splash_screen_bmp(loader_ctx->custom_splash_path, (void *)0xC0000000); display_splash_screen_bmp(loader_ctx->custom_splash_path, (void *)0xC0000000);

View file

@ -27,6 +27,7 @@
#define u8 uint8_t #define u8 uint8_t
#define u32 uint32_t #define u32 uint32_t
#include "thermosphere_bin.h" #include "thermosphere_bin.h"
#include "log.h"
#undef u8 #undef u8
#undef u32 #undef u32
@ -52,7 +53,7 @@ void package2_rebuild_and_copy(package2_header_t *package2, uint32_t target_firm
/* First things first: Decrypt Package2 in place. */ /* First things first: Decrypt Package2 in place. */
package2_decrypt(package2); package2_decrypt(package2);
printf("Decrypted package2!\n"); print(SCREEN_LOG_LEVEL_DEBUG, "Decrypted package2!\n");
kernel_size = package2_get_src_section(&kernel, package2, PACKAGE2_SECTION_KERNEL); kernel_size = package2_get_src_section(&kernel, package2, PACKAGE2_SECTION_KERNEL);
@ -66,11 +67,11 @@ void package2_rebuild_and_copy(package2_header_t *package2, uint32_t target_firm
/* Perform any patches we want to the NX kernel. */ /* Perform any patches we want to the NX kernel. */
package2_patch_kernel(kernel, kernel_size); package2_patch_kernel(kernel, kernel_size);
printf("Rebuilding the INI1 section...\n"); print(SCREEN_LOG_LEVEL_DEBUG, "Rebuilding the INI1 section...\n");
package2_get_src_section((void *)&orig_ini1, package2, PACKAGE2_SECTION_INI1); package2_get_src_section((void *)&orig_ini1, package2, PACKAGE2_SECTION_INI1);
/* Perform any patches to the INI1, rebuilding it (This is where our built-in sysmodules will be added.) */ /* Perform any patches to the INI1, rebuilding it (This is where our built-in sysmodules will be added.) */
rebuilt_ini1 = package2_rebuild_ini1(orig_ini1, target_firmware); rebuilt_ini1 = package2_rebuild_ini1(orig_ini1, target_firmware);
printf("Rebuilt INI1...\n"); print(SCREEN_LOG_LEVEL_DEBUG, "Rebuilt INI1...\n");
/* Allocate the rebuilt package2. */ /* Allocate the rebuilt package2. */
rebuilt_package2_size = sizeof(package2_header_t) + kernel_size + align_to_4(thermosphere_size) + align_to_4(rebuilt_ini1->size); rebuilt_package2_size = sizeof(package2_header_t) + kernel_size + align_to_4(thermosphere_size) + align_to_4(rebuilt_ini1->size);

View file

@ -31,7 +31,7 @@
#include "../pmc.h" #include "../pmc.h"
#include "../max7762x.h" #include "../max7762x.h"
#include "../lib/driver_utils.h" #include "../lib/driver_utils.h"
#include "../print.h" #include "../log.h"
static SdmmcLogLevel g_sdmmc_log_level = SDMMC_LOG_NONE; static SdmmcLogLevel g_sdmmc_log_level = SDMMC_LOG_NONE;
@ -44,26 +44,30 @@ static void sdmmc_print(sdmmc_t *sdmmc, SdmmcLogLevel log_level, char *fmt, va_l
{ {
if (log_level > g_sdmmc_log_level) if (log_level > g_sdmmc_log_level)
return; return;
char sdmmc_fmt[] = "%s: ";
ScreenLogLevel screen_log_level = SCREEN_LOG_LEVEL_ERROR;
switch (log_level) { switch (log_level) {
case SDMMC_LOG_ERROR: case SDMMC_LOG_ERROR:
print(PRINT_LOG_ERROR, "%s", sdmmc->name); screen_log_level = SCREEN_LOG_LEVEL_ERROR;
break; break;
case SDMMC_LOG_WARN: case SDMMC_LOG_WARN:
print(PRINT_LOG_WARNING, "%s", sdmmc->name); screen_log_level = SCREEN_LOG_LEVEL_WARNING;
break; break;
case SDMMC_LOG_INFO: case SDMMC_LOG_INFO:
print(PRINT_LOG_INFO, "%s", sdmmc->name); screen_log_level = SCREEN_LOG_LEVEL_DEBUG;
break; break;
case SDMMC_LOG_DEBUG: case SDMMC_LOG_DEBUG:
print(PRINT_LOG_DEBUG, "%s", sdmmc->name); screen_log_level = SCREEN_LOG_LEVEL_DEBUG;
break; break;
default: default:
break; break;
} }
vprintk(fmt, list); print(screen_log_level, sdmmc_fmt, sdmmc->name);
printk("\n"); vprint(screen_log_level, fmt, list);
print(screen_log_level, "\n");
} }
void sdmmc_error(sdmmc_t *sdmmc, char *fmt, ...) void sdmmc_error(sdmmc_t *sdmmc, char *fmt, ...)

View file

@ -24,6 +24,7 @@
#include "timers.h" #include "timers.h"
#include "btn.h" #include "btn.h"
#include "panic.h" #include "panic.h"
#include "log.h"
#include <stdio.h> #include <stdio.h>
#include <inttypes.h> #include <inttypes.h>
@ -76,17 +77,27 @@ __attribute__((noreturn)) void wait_for_button_and_reboot(void) {
} }
} }
void wait_for_button(void) {
uint32_t button;
while (true) {
button = btn_read();
if (button) {
return;
}
}
}
__attribute__ ((noreturn)) void generic_panic(void) { __attribute__ ((noreturn)) void generic_panic(void) {
panic(0xFF000006); panic(0xFF000006);
} }
__attribute__((noreturn)) void fatal_error(const char *fmt, ...) { __attribute__((noreturn)) void fatal_error(const char *fmt, ...) {
va_list args; va_list args;
printf("Fatal error: "); print(SCREEN_LOG_LEVEL_ERROR, "Fatal error: ");
va_start(args, fmt); va_start(args, fmt);
vprintf(fmt, args); vprint(SCREEN_LOG_LEVEL_ERROR, fmt, args);
va_end(args); va_end(args);
printf("\n Press POWER to reboot.\n"); print(SCREEN_LOG_LEVEL_ERROR, "\n Press POWER to reboot.\n");
wait_for_button_and_reboot(); wait_for_button_and_reboot();
} }

View file

@ -124,6 +124,7 @@ __attribute__((noreturn)) void watchdog_reboot(void);
__attribute__((noreturn)) void pmc_reboot(uint32_t scratch0); __attribute__((noreturn)) void pmc_reboot(uint32_t scratch0);
__attribute__((noreturn)) void car_reboot(void); __attribute__((noreturn)) void car_reboot(void);
__attribute__((noreturn)) void wait_for_button_and_reboot(void); __attribute__((noreturn)) void wait_for_button_and_reboot(void);
void wait_for_button(void);
__attribute__((noreturn)) void generic_panic(void); __attribute__((noreturn)) void generic_panic(void);