mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-12-22 12:21:18 +00:00
Merge pull request #209 from Resaec/new_print
Silenced boot from stage 2
This commit is contained in:
commit
2e6983d214
24 changed files with 460 additions and 215 deletions
|
@ -17,9 +17,8 @@
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
|
||||||
#include "exception_handlers.h"
|
#include "exception_handlers.h"
|
||||||
#include "lib/driver_utils.h"
|
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "display/video_fb.h"
|
#include "lib/log.h"
|
||||||
|
|
||||||
#define CODE_DUMP_SIZE 0x30
|
#define CODE_DUMP_SIZE 0x30
|
||||||
#define STACK_DUMP_SIZE 0x60
|
#define STACK_DUMP_SIZE 0x60
|
||||||
|
@ -55,26 +54,28 @@ 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 | SCREEN_LOG_LEVEL_NO_PREFIX, "\nException type: %s\n",
|
||||||
printk("\nRegisters:\n\n");
|
exception_names[exception_type]);
|
||||||
|
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "\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 | SCREEN_LOG_LEVEL_NO_PREFIX, "%-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 | SCREEN_LOG_LEVEL_NO_PREFIX, "%-7s%08"PRIX32"\n", register_names[16], registers[16]);
|
||||||
|
|
||||||
printk("\nCode dump:\n");
|
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "\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 | SCREEN_LOG_LEVEL_NO_PREFIX, "\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 | SCREEN_LOG_LEVEL_NO_PREFIX, "\n");
|
||||||
fatal_error("An exception occured!\n");
|
fatal_error("An exception occured!\n");
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,11 +13,11 @@
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "fs_utils.h"
|
#include "fs_utils.h"
|
||||||
#include "mc.h"
|
#include "mc.h"
|
||||||
#include "lib/printk.h"
|
|
||||||
#include "lib/fatfs/ff.h"
|
#include "lib/fatfs/ff.h"
|
||||||
|
#include "lib/log.h"
|
||||||
|
|
||||||
FATFS sd_fs;
|
FATFS sd_fs;
|
||||||
static bool g_sd_mounted = false;
|
static bool g_sd_mounted = false;
|
||||||
|
@ -44,7 +44,7 @@ bool mount_sd(void)
|
||||||
|
|
||||||
/* Mount SD. */
|
/* Mount SD. */
|
||||||
if (f_mount(&sd_fs, "", 1) == FR_OK) {
|
if (f_mount(&sd_fs, "", 1) == FR_OK) {
|
||||||
printk("Mounted SD card!\n");
|
print(SCREEN_LOG_LEVEL_INFO, "Mounted SD card!\n");
|
||||||
g_sd_mounted = true;
|
g_sd_mounted = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,23 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2018 Atmosphère-NX
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms and conditions of the GNU General Public License,
|
|
||||||
* version 2, as published by the Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
||||||
* more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef FUSEE_DRIVER_UTILS_H
|
|
||||||
#define FUSEE_DRIVER_UTILS_H
|
|
||||||
|
|
||||||
#include "vsprintf.h"
|
|
||||||
#include "printk.h"
|
|
||||||
|
|
||||||
#endif
|
|
123
fusee/fusee-primary/src/lib/log.c
Normal file
123
fusee/fusee-primary/src/lib/log.c
Normal file
|
@ -0,0 +1,123 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018 Atmosphère-NX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
|
#include "../display/video_fb.h"
|
||||||
|
#include "vsprintf.h"
|
||||||
|
|
||||||
|
/* default log level for screen output */
|
||||||
|
ScreenLogLevel g_screen_log_level = SCREEN_LOG_LEVEL_MANDATORY;
|
||||||
|
|
||||||
|
void log_set_log_level(ScreenLogLevel log_level) {
|
||||||
|
g_screen_log_level = log_level;
|
||||||
|
}
|
||||||
|
|
||||||
|
void log_to_uart(const char *message) {
|
||||||
|
/* TODO: add UART logging */
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_to_screen(ScreenLogLevel screen_log_level, char *message) {
|
||||||
|
/* don't print to screen if below log level */
|
||||||
|
if(screen_log_level > g_screen_log_level) return;
|
||||||
|
|
||||||
|
video_puts(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* vprintk - logs a message and prints it to screen based on its screen_log_level
|
||||||
|
*
|
||||||
|
* If the level is below g_screen_log_level it will not be shown but logged to UART
|
||||||
|
* This text will not be colored or prefixed
|
||||||
|
* UART is TODO
|
||||||
|
*/
|
||||||
|
void vprint(ScreenLogLevel screen_log_level, const char *fmt, va_list args)
|
||||||
|
{
|
||||||
|
char buf[PRINT_MESSAGE_MAX_LENGTH];
|
||||||
|
vsnprintf(buf, PRINT_MESSAGE_MAX_LENGTH, fmt, args);
|
||||||
|
|
||||||
|
/* we don't need that flag here, but if it gets used, strip it so we print correctly */
|
||||||
|
screen_log_level &= ~SCREEN_LOG_LEVEL_NO_PREFIX;
|
||||||
|
|
||||||
|
/* log to UART */
|
||||||
|
log_to_uart(buf);
|
||||||
|
|
||||||
|
print_to_screen(screen_log_level, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
void add_prefix(ScreenLogLevel screen_log_level, const char *fmt, char *buf) {
|
||||||
|
char typebuf[] = "[%s] %s";
|
||||||
|
|
||||||
|
/* apply prefix and append message format */
|
||||||
|
/* TODO: add coloring to the output */
|
||||||
|
switch(screen_log_level)
|
||||||
|
{
|
||||||
|
case SCREEN_LOG_LEVEL_ERROR:
|
||||||
|
snprintf(buf, PRINT_MESSAGE_MAX_LENGTH, typebuf, "ERROR", fmt);
|
||||||
|
break;
|
||||||
|
case SCREEN_LOG_LEVEL_WARNING:
|
||||||
|
snprintf(buf, PRINT_MESSAGE_MAX_LENGTH, typebuf, "WARNING", fmt);
|
||||||
|
break;
|
||||||
|
case SCREEN_LOG_LEVEL_MANDATORY:
|
||||||
|
snprintf(buf, PRINT_MESSAGE_MAX_LENGTH, "%s", fmt);
|
||||||
|
break;
|
||||||
|
case SCREEN_LOG_LEVEL_INFO:
|
||||||
|
snprintf(buf, PRINT_MESSAGE_MAX_LENGTH, typebuf, "INFO", fmt);
|
||||||
|
break;
|
||||||
|
case SCREEN_LOG_LEVEL_DEBUG:
|
||||||
|
snprintf(buf, PRINT_MESSAGE_MAX_LENGTH, typebuf, "DEBUG", fmt);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* print - logs a message and prints it to screen based on its screen_log_level
|
||||||
|
*
|
||||||
|
* If the level is below g_screen_log_level it will not be shown but logged to UART
|
||||||
|
* Use SCREEN_LOG_LEVEL_NO_PREFIX if you don't want a prefix to be added
|
||||||
|
* UART is TODO
|
||||||
|
*/
|
||||||
|
void print(ScreenLogLevel screen_log_level, const char * fmt, ...)
|
||||||
|
{
|
||||||
|
char buf[PRINT_MESSAGE_MAX_LENGTH] = {};
|
||||||
|
char message[PRINT_MESSAGE_MAX_LENGTH] = {};
|
||||||
|
|
||||||
|
/* TODO: make splash disappear if level > MANDATORY */
|
||||||
|
|
||||||
|
/* make prefix free messages with log_level possible */
|
||||||
|
if(screen_log_level & SCREEN_LOG_LEVEL_NO_PREFIX) {
|
||||||
|
/* remove the NO_PREFIX flag so the enum can be recognized later on */
|
||||||
|
screen_log_level &= ~SCREEN_LOG_LEVEL_NO_PREFIX;
|
||||||
|
|
||||||
|
snprintf(buf, PRINT_MESSAGE_MAX_LENGTH, "%s", fmt);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
add_prefix(screen_log_level, fmt, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* input arguments */
|
||||||
|
va_list args;
|
||||||
|
va_start(args, fmt);
|
||||||
|
vsnprintf(message, PRINT_MESSAGE_MAX_LENGTH, buf, args);
|
||||||
|
va_end(args);
|
||||||
|
|
||||||
|
/* log to UART */
|
||||||
|
log_to_uart(message);
|
||||||
|
|
||||||
|
print_to_screen(screen_log_level, message);
|
||||||
|
}
|
43
fusee/fusee-primary/src/lib/log.h
Normal file
43
fusee/fusee-primary/src/lib/log.h
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018 Atmosphère-NX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef FUSEE_PRIMARY_PRINT_H
|
||||||
|
#define FUSEE_PRIMARY_PRINT_H
|
||||||
|
|
||||||
|
#define PRINT_MESSAGE_MAX_LENGTH 512
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
SCREEN_LOG_LEVEL_NONE = 0,
|
||||||
|
SCREEN_LOG_LEVEL_ERROR = 1,
|
||||||
|
SCREEN_LOG_LEVEL_WARNING = 2,
|
||||||
|
SCREEN_LOG_LEVEL_MANDATORY = 3, /* no log prefix */
|
||||||
|
SCREEN_LOG_LEVEL_INFO = 4,
|
||||||
|
SCREEN_LOG_LEVEL_DEBUG = 5,
|
||||||
|
|
||||||
|
SCREEN_LOG_LEVEL_NO_PREFIX = 0x100 /* OR this to your LOG_LEVEL to prevent prefix creation */
|
||||||
|
} ScreenLogLevel;
|
||||||
|
|
||||||
|
/* TODO: make this configurable by BCT.ini */
|
||||||
|
extern ScreenLogLevel g_screen_log_level;
|
||||||
|
|
||||||
|
void log_set_log_level(ScreenLogLevel screen_log_level);
|
||||||
|
void log_to_uart(const char *message);
|
||||||
|
void vprint(ScreenLogLevel screen_log_level, const char *fmt, va_list args);
|
||||||
|
void print(ScreenLogLevel screen_log_level, const char* fmt, ...);
|
||||||
|
|
||||||
|
#endif
|
|
@ -1,42 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2018 Atmosphère-NX
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms and conditions of the GNU General Public License,
|
|
||||||
* version 2, as published by the Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
||||||
* more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "printk.h"
|
|
||||||
|
|
||||||
#include "vsprintf.h"
|
|
||||||
#include "../display/video_fb.h"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Temporary stand-in main printk.
|
|
||||||
*
|
|
||||||
* TODO: This should print via UART, console framebuffer, and to a ring for
|
|
||||||
* consumption by Horizon
|
|
||||||
*/
|
|
||||||
void printk(const char *fmt, ...)
|
|
||||||
{
|
|
||||||
va_list list;
|
|
||||||
va_start(list, fmt);
|
|
||||||
vprintk(fmt, list);
|
|
||||||
va_end(list);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void vprintk(const char *fmt, va_list args)
|
|
||||||
{
|
|
||||||
char buf[512];
|
|
||||||
vsnprintf(buf, sizeof(buf), fmt, args);
|
|
||||||
video_puts(buf);
|
|
||||||
}
|
|
|
@ -1,25 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2018 Atmosphère-NX
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms and conditions of the GNU General Public License,
|
|
||||||
* version 2, as published by the Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
||||||
* more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __PRINTK_H__
|
|
||||||
#define __PRINTK_H__
|
|
||||||
|
|
||||||
#include <stdarg.h>
|
|
||||||
|
|
||||||
void printk(const char *fmt, ...);
|
|
||||||
void vprintk(const char *fmt, va_list args);
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -25,7 +25,7 @@
|
||||||
#include "chainloader.h"
|
#include "chainloader.h"
|
||||||
#include "sdmmc/sdmmc.h"
|
#include "sdmmc/sdmmc.h"
|
||||||
#include "lib/fatfs/ff.h"
|
#include "lib/fatfs/ff.h"
|
||||||
#include "lib/printk.h"
|
#include "lib/log.h"
|
||||||
#include "display/video_fb.h"
|
#include "display/video_fb.h"
|
||||||
|
|
||||||
extern void (*__program_exit_callback)(int rc);
|
extern void (*__program_exit_callback)(int rc);
|
||||||
|
@ -42,8 +42,8 @@ static char g_bct0_buffer[BCTO_MAX_SIZE];
|
||||||
|
|
||||||
static const char *load_config(void) {
|
static const char *load_config(void) {
|
||||||
if (!read_from_file(g_bct0_buffer, BCTO_MAX_SIZE, "BCT.ini")) {
|
if (!read_from_file(g_bct0_buffer, BCTO_MAX_SIZE, "BCT.ini")) {
|
||||||
printk("Failed to read BCT0 from SD!\n");
|
print(SCREEN_LOG_LEVEL_DEBUG, "Failed to read BCT0 from SD!\n");
|
||||||
printk("[DEBUG] Using default BCT0!\n");
|
print(SCREEN_LOG_LEVEL_DEBUG, "Using default BCT0!\n");
|
||||||
memcpy(g_bct0_buffer, DEFAULT_BCT0_FOR_DEBUG, sizeof(DEFAULT_BCT0_FOR_DEBUG));
|
memcpy(g_bct0_buffer, DEFAULT_BCT0_FOR_DEBUG, sizeof(DEFAULT_BCT0_FOR_DEBUG));
|
||||||
/* TODO: Stop using default. */
|
/* TODO: Stop using default. */
|
||||||
/* printk("Error: Failed to load BCT.ini!\n");
|
/* printk("Error: Failed to load BCT.ini!\n");
|
||||||
|
@ -119,8 +119,8 @@ int main(void) {
|
||||||
setup_env();
|
setup_env();
|
||||||
|
|
||||||
/* Say hello. */
|
/* Say hello. */
|
||||||
printk("Welcome to Atmosph\xe8re Fus\xe9" "e!\n");
|
print(SCREEN_LOG_LEVEL_MANDATORY, "Welcome to Atmosph\xe8re Fus\xe9" "e!\n");
|
||||||
printk("Using color linear framebuffer at 0x%p!\n", g_framebuffer);
|
print(SCREEN_LOG_LEVEL_DEBUG, "Using color linear framebuffer at 0x%p!\n", g_framebuffer);
|
||||||
|
|
||||||
/* Load the BCT0 configuration ini off of the SD. */
|
/* Load the BCT0 configuration ini off of the SD. */
|
||||||
bct0 = load_config();
|
bct0 = load_config();
|
||||||
|
|
|
@ -26,7 +26,6 @@
|
||||||
#include "mmc.h"
|
#include "mmc.h"
|
||||||
#include "sd.h"
|
#include "sd.h"
|
||||||
#include "../timers.h"
|
#include "../timers.h"
|
||||||
#include "../lib/driver_utils.h"
|
|
||||||
|
|
||||||
#define UNSTUFF_BITS(resp,start,size) \
|
#define UNSTUFF_BITS(resp,start,size) \
|
||||||
({ \
|
({ \
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
#include "../gpio.h"
|
#include "../gpio.h"
|
||||||
#include "../pmc.h"
|
#include "../pmc.h"
|
||||||
#include "../max7762x.h"
|
#include "../max7762x.h"
|
||||||
#include "../lib/driver_utils.h"
|
#include "../lib/log.h"
|
||||||
|
|
||||||
static SdmmcLogLevel g_sdmmc_log_level = SDMMC_LOG_NONE;
|
static SdmmcLogLevel g_sdmmc_log_level = SDMMC_LOG_NONE;
|
||||||
|
|
||||||
|
@ -43,26 +43,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:
|
||||||
printk("%s [ERROR]: ", sdmmc->name);
|
screen_log_level = SCREEN_LOG_LEVEL_ERROR;
|
||||||
break;
|
break;
|
||||||
case SDMMC_LOG_WARN:
|
case SDMMC_LOG_WARN:
|
||||||
printk("%s [WARN]: ", sdmmc->name);
|
screen_log_level = SCREEN_LOG_LEVEL_WARNING;
|
||||||
break;
|
break;
|
||||||
case SDMMC_LOG_INFO:
|
case SDMMC_LOG_INFO:
|
||||||
printk("%s [INFO]: ", sdmmc->name);
|
screen_log_level = SCREEN_LOG_LEVEL_DEBUG;
|
||||||
break;
|
break;
|
||||||
case SDMMC_LOG_DEBUG:
|
case SDMMC_LOG_DEBUG:
|
||||||
printk("%s [DEBUG]: ", 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 | SCREEN_LOG_LEVEL_NO_PREFIX, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void sdmmc_error(sdmmc_t *sdmmc, char *fmt, ...)
|
void sdmmc_error(sdmmc_t *sdmmc, char *fmt, ...)
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
#include "fs_utils.h"
|
#include "fs_utils.h"
|
||||||
#include "stage2.h"
|
#include "stage2.h"
|
||||||
#include "chainloader.h"
|
#include "chainloader.h"
|
||||||
#include "lib/printk.h"
|
#include "lib/log.h"
|
||||||
#include "lib/vsprintf.h"
|
#include "lib/vsprintf.h"
|
||||||
#include "lib/ini.h"
|
#include "lib/ini.h"
|
||||||
#include "lib/fatfs/ff.h"
|
#include "lib/fatfs/ff.h"
|
||||||
|
@ -74,7 +74,7 @@ void load_stage2(const char *bct0) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strlen(config.path) + 1 + sizeof(stage2_args_t) > CHAINLOADER_ARG_DATA_MAX_SIZE) {
|
if (strlen(config.path) + 1 + sizeof(stage2_args_t) > CHAINLOADER_ARG_DATA_MAX_SIZE) {
|
||||||
printk("Error: Stage2's path name is too big!\n");
|
print(SCREEN_LOG_LEVEL_ERROR, "Stage2's path name is too big!\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!check_32bit_address_loadable(config.entrypoint)) {
|
if (!check_32bit_address_loadable(config.entrypoint)) {
|
||||||
|
@ -85,10 +85,10 @@ void load_stage2(const char *bct0) {
|
||||||
fatal_error("Stage2's load address is invalid!\n");
|
fatal_error("Stage2's load address is invalid!\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
printk("[DEBUG] Stage 2 Config:\n");
|
print(SCREEN_LOG_LEVEL_DEBUG, "Stage 2 Config:\n");
|
||||||
printk(" File Path: %s\n", config.path);
|
print(SCREEN_LOG_LEVEL_DEBUG | SCREEN_LOG_LEVEL_NO_PREFIX, " File Path: %s\n", config.path);
|
||||||
printk(" Load Address: 0x%08x\n", config.load_address);
|
print(SCREEN_LOG_LEVEL_DEBUG | SCREEN_LOG_LEVEL_NO_PREFIX, " Load Address: 0x%08x\n", config.load_address);
|
||||||
printk(" Entrypoint: 0x%p\n", config.entrypoint);
|
print(SCREEN_LOG_LEVEL_DEBUG | SCREEN_LOG_LEVEL_NO_PREFIX, " Entrypoint: 0x%p\n", config.entrypoint);
|
||||||
|
|
||||||
if (f_stat(config.path, &info) != FR_OK) {
|
if (f_stat(config.path, &info) != FR_OK) {
|
||||||
fatal_error("Failed to stat stage2 (%s)!\n", config.path);
|
fatal_error("Failed to stat stage2 (%s)!\n", config.path);
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
#include "car.h"
|
#include "car.h"
|
||||||
#include "btn.h"
|
#include "btn.h"
|
||||||
|
|
||||||
#include "lib/printk.h"
|
#include "lib/log.h"
|
||||||
|
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
|
||||||
|
@ -84,11 +84,11 @@ __attribute__ ((noreturn)) void generic_panic(void) {
|
||||||
|
|
||||||
__attribute__((noreturn)) void fatal_error(const char *fmt, ...) {
|
__attribute__((noreturn)) void fatal_error(const char *fmt, ...) {
|
||||||
va_list args;
|
va_list args;
|
||||||
printk("Fatal error: ");
|
print(SCREEN_LOG_LEVEL_ERROR, "Fatal error: ");
|
||||||
va_start(args, fmt);
|
va_start(args, fmt);
|
||||||
vprintk(fmt, args);
|
vprint(SCREEN_LOG_LEVEL_ERROR, fmt, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
printk("\nPress POWER to reboot\n");
|
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX,"\nPress POWER to reboot\n");
|
||||||
wait_for_button_and_reboot();
|
wait_for_button_and_reboot();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,27 +109,27 @@ void hexdump(const void* data, size_t size, uintptr_t addrbase) {
|
||||||
|
|
||||||
for (size_t i = 0; i < size; i++) {
|
for (size_t i = 0; i < size; i++) {
|
||||||
if (i % 16 == 0) {
|
if (i % 16 == 0) {
|
||||||
printk("%0*" PRIXPTR ": | ", 2 * sizeof(addrbase), addrbase + i);
|
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "%0*" PRIXPTR ": | ", 2 * sizeof(addrbase), addrbase + i);
|
||||||
}
|
}
|
||||||
printk("%02X ", d[i]);
|
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "%02X ", d[i]);
|
||||||
if (d[i] >= ' ' && d[i] <= '~') {
|
if (d[i] >= ' ' && d[i] <= '~') {
|
||||||
ascii[i % 16] = d[i];
|
ascii[i % 16] = d[i];
|
||||||
} else {
|
} else {
|
||||||
ascii[i % 16] = '.';
|
ascii[i % 16] = '.';
|
||||||
}
|
}
|
||||||
if ((i+1) % 8 == 0 || i+1 == size) {
|
if ((i+1) % 8 == 0 || i+1 == size) {
|
||||||
printk(" ");
|
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, " ");
|
||||||
if ((i+1) % 16 == 0) {
|
if ((i+1) % 16 == 0) {
|
||||||
printk("| %s \n", ascii);
|
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "| %s \n", ascii);
|
||||||
} else if (i+1 == size) {
|
} else if (i+1 == size) {
|
||||||
ascii[(i+1) % 16] = '\0';
|
ascii[(i+1) % 16] = '\0';
|
||||||
if ((i+1) % 16 <= 8) {
|
if ((i+1) % 16 <= 8) {
|
||||||
printk(" ");
|
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, " ");
|
||||||
}
|
}
|
||||||
for (size_t j = (i+1) % 16; j < 16; j++) {
|
for (size_t j = (i+1) % 16; j < 16; j++) {
|
||||||
printk(" ");
|
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, " ");
|
||||||
}
|
}
|
||||||
printk("| %s \n", ascii);
|
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "| %s \n", ascii);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,9 +17,9 @@
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
|
||||||
#include "exception_handlers.h"
|
#include "exception_handlers.h"
|
||||||
#include "lib/driver_utils.h"
|
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "display/video_fb.h"
|
#include "display/video_fb.h"
|
||||||
|
#include "lib/log.h"
|
||||||
|
|
||||||
#define CODE_DUMP_SIZE 0x30
|
#define CODE_DUMP_SIZE 0x30
|
||||||
#define STACK_DUMP_SIZE 0x60
|
#define STACK_DUMP_SIZE 0x60
|
||||||
|
@ -55,26 +55,28 @@ 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 | SCREEN_LOG_LEVEL_NO_PREFIX, "\nException type: %s\n",
|
||||||
printk("\nRegisters:\n\n");
|
exception_names[exception_type]);
|
||||||
|
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "\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 | SCREEN_LOG_LEVEL_NO_PREFIX, "%-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 | SCREEN_LOG_LEVEL_NO_PREFIX, "%-7s%08"PRIX32"\n", register_names[16], registers[16]);
|
||||||
|
|
||||||
printk("\nCode dump:\n");
|
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "\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 | SCREEN_LOG_LEVEL_NO_PREFIX, "\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 | SCREEN_LOG_LEVEL_NO_PREFIX, "\n");
|
||||||
fatal_error("An exception occured!\n");
|
fatal_error("An exception occurred!\n");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,26 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2018 Atmosphère-NX
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms and conditions of the GNU General Public License,
|
|
||||||
* version 2, as published by the Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
||||||
* more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef FUSEE_DRIVER_UTILS_H
|
|
||||||
#define FUSEE_DRIVER_UTILS_H
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
|
|
||||||
#define vprintk vprintf
|
|
||||||
#define printk printf
|
|
||||||
|
|
||||||
#endif
|
|
122
fusee/fusee-secondary/src/lib/log.c
Normal file
122
fusee/fusee-secondary/src/lib/log.c
Normal file
|
@ -0,0 +1,122 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018 Atmosphère-NX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
/* default log level for screen output */
|
||||||
|
ScreenLogLevel g_screen_log_level = SCREEN_LOG_LEVEL_MANDATORY;
|
||||||
|
|
||||||
|
void log_set_log_level(ScreenLogLevel log_level) {
|
||||||
|
g_screen_log_level = log_level;
|
||||||
|
}
|
||||||
|
|
||||||
|
void log_to_uart(const char *message) {
|
||||||
|
/* TODO: add UART logging */
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_to_screen(ScreenLogLevel screen_log_level, char *message) {
|
||||||
|
/* don't print to screen if below log level */
|
||||||
|
if(screen_log_level > g_screen_log_level) return;
|
||||||
|
|
||||||
|
printf(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* vprintk - logs a message and prints it to screen based on its screen_log_level
|
||||||
|
*
|
||||||
|
* If the level is below g_screen_log_level it will not be shown but logged to UART
|
||||||
|
* This text will not be colored or prefixed
|
||||||
|
* UART is TODO
|
||||||
|
*/
|
||||||
|
void vprint(ScreenLogLevel screen_log_level, const char *fmt, va_list args)
|
||||||
|
{
|
||||||
|
char buf[PRINT_MESSAGE_MAX_LENGTH];
|
||||||
|
vsnprintf(buf, PRINT_MESSAGE_MAX_LENGTH, fmt, args);
|
||||||
|
|
||||||
|
/* we don't need that flag here, but if it gets used, strip it so we print correctly */
|
||||||
|
screen_log_level &= ~SCREEN_LOG_LEVEL_NO_PREFIX;
|
||||||
|
|
||||||
|
/* log to UART */
|
||||||
|
log_to_uart(buf);
|
||||||
|
|
||||||
|
print_to_screen(screen_log_level, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
void add_prefix(ScreenLogLevel screen_log_level, const char *fmt, char *buf) {
|
||||||
|
char typebuf[] = "[%s] %s";
|
||||||
|
|
||||||
|
/* apply prefix and append message format */
|
||||||
|
/* TODO: add coloring to the output */
|
||||||
|
switch(screen_log_level)
|
||||||
|
{
|
||||||
|
case SCREEN_LOG_LEVEL_ERROR:
|
||||||
|
snprintf(buf, PRINT_MESSAGE_MAX_LENGTH, typebuf, "ERROR", fmt);
|
||||||
|
break;
|
||||||
|
case SCREEN_LOG_LEVEL_WARNING:
|
||||||
|
snprintf(buf, PRINT_MESSAGE_MAX_LENGTH, typebuf, "WARNING", fmt);
|
||||||
|
break;
|
||||||
|
case SCREEN_LOG_LEVEL_MANDATORY:
|
||||||
|
snprintf(buf, PRINT_MESSAGE_MAX_LENGTH, "%s", fmt);
|
||||||
|
break;
|
||||||
|
case SCREEN_LOG_LEVEL_INFO:
|
||||||
|
snprintf(buf, PRINT_MESSAGE_MAX_LENGTH, typebuf, "INFO", fmt);
|
||||||
|
break;
|
||||||
|
case SCREEN_LOG_LEVEL_DEBUG:
|
||||||
|
snprintf(buf, PRINT_MESSAGE_MAX_LENGTH, typebuf, "DEBUG", fmt);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* print - logs a message and prints it to screen based on its screen_log_level
|
||||||
|
*
|
||||||
|
* If the level is below g_screen_log_level it will not be shown but logged to UART
|
||||||
|
* Use SCREEN_LOG_LEVEL_NO_PREFIX if you don't want a prefix to be added
|
||||||
|
* UART is TODO
|
||||||
|
*/
|
||||||
|
void print(ScreenLogLevel screen_log_level, const char * fmt, ...)
|
||||||
|
{
|
||||||
|
char buf[PRINT_MESSAGE_MAX_LENGTH] = {};
|
||||||
|
char message[PRINT_MESSAGE_MAX_LENGTH] = {};
|
||||||
|
|
||||||
|
/* TODO: make splash disappear if level > MANDATORY */
|
||||||
|
|
||||||
|
/* make prefix free messages with log_level possible */
|
||||||
|
if(screen_log_level & SCREEN_LOG_LEVEL_NO_PREFIX) {
|
||||||
|
/* remove the NO_PREFIX flag so the enum can be recognized later on */
|
||||||
|
screen_log_level &= ~SCREEN_LOG_LEVEL_NO_PREFIX;
|
||||||
|
|
||||||
|
snprintf(buf, PRINT_MESSAGE_MAX_LENGTH, "%s", fmt);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
add_prefix(screen_log_level, fmt, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* input arguments */
|
||||||
|
va_list args;
|
||||||
|
va_start(args, fmt);
|
||||||
|
vsnprintf(message, PRINT_MESSAGE_MAX_LENGTH, buf, args);
|
||||||
|
va_end(args);
|
||||||
|
|
||||||
|
/* log to UART */
|
||||||
|
log_to_uart(message);
|
||||||
|
|
||||||
|
print_to_screen(screen_log_level, message);
|
||||||
|
}
|
43
fusee/fusee-secondary/src/lib/log.h
Normal file
43
fusee/fusee-secondary/src/lib/log.h
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018 Atmosphère-NX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef FUSEE_SECONDARY_PRINT_H
|
||||||
|
#define FUSEE_SECONDARY_PRINT_H
|
||||||
|
|
||||||
|
#define PRINT_MESSAGE_MAX_LENGTH 512
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
SCREEN_LOG_LEVEL_NONE = 0,
|
||||||
|
SCREEN_LOG_LEVEL_ERROR = 1,
|
||||||
|
SCREEN_LOG_LEVEL_WARNING = 2,
|
||||||
|
SCREEN_LOG_LEVEL_MANDATORY = 3, /* no log prefix */
|
||||||
|
SCREEN_LOG_LEVEL_INFO = 4,
|
||||||
|
SCREEN_LOG_LEVEL_DEBUG = 5,
|
||||||
|
|
||||||
|
SCREEN_LOG_LEVEL_NO_PREFIX = 0x100 /* OR this to your LOG_LEVEL to prevent prefix creation */
|
||||||
|
} ScreenLogLevel;
|
||||||
|
|
||||||
|
/* TODO: make this configurable by BCT.ini */
|
||||||
|
extern ScreenLogLevel g_screen_log_level;
|
||||||
|
|
||||||
|
void log_set_log_level(ScreenLogLevel screen_log_level);
|
||||||
|
void log_to_uart(const char *message);
|
||||||
|
void vprint(ScreenLogLevel screen_log_level, const char *fmt, va_list args);
|
||||||
|
void print(ScreenLogLevel screen_log_level, const char* fmt, ...);
|
||||||
|
|
||||||
|
#endif
|
|
@ -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 "lib/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);
|
||||||
|
|
|
@ -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,6 +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 "lib/log.h"
|
||||||
|
|
||||||
extern void (*__program_exit_callback)(int rc);
|
extern void (*__program_exit_callback)(int rc);
|
||||||
|
|
||||||
|
@ -91,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();
|
||||||
|
|
||||||
printf(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");
|
||||||
printf("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);
|
||||||
|
|
||||||
printf("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) {
|
||||||
printf("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];
|
||||||
printf("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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 "lib/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);
|
||||||
|
|
|
@ -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 "lib/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);
|
||||||
|
|
|
@ -26,7 +26,6 @@
|
||||||
#include "mmc.h"
|
#include "mmc.h"
|
||||||
#include "sd.h"
|
#include "sd.h"
|
||||||
#include "../timers.h"
|
#include "../timers.h"
|
||||||
#include "../lib/driver_utils.h"
|
|
||||||
|
|
||||||
#define UNSTUFF_BITS(resp,start,size) \
|
#define UNSTUFF_BITS(resp,start,size) \
|
||||||
({ \
|
({ \
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
#include "../gpio.h"
|
#include "../gpio.h"
|
||||||
#include "../pmc.h"
|
#include "../pmc.h"
|
||||||
#include "../max7762x.h"
|
#include "../max7762x.h"
|
||||||
#include "../lib/driver_utils.h"
|
#include "../lib/log.h"
|
||||||
|
|
||||||
static SdmmcLogLevel g_sdmmc_log_level = SDMMC_LOG_NONE;
|
static SdmmcLogLevel g_sdmmc_log_level = SDMMC_LOG_NONE;
|
||||||
|
|
||||||
|
@ -43,26 +43,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:
|
||||||
printk("%s [ERROR]: ", sdmmc->name);
|
screen_log_level = SCREEN_LOG_LEVEL_ERROR;
|
||||||
break;
|
break;
|
||||||
case SDMMC_LOG_WARN:
|
case SDMMC_LOG_WARN:
|
||||||
printk("%s [WARN]: ", sdmmc->name);
|
screen_log_level = SCREEN_LOG_LEVEL_WARNING;
|
||||||
break;
|
break;
|
||||||
case SDMMC_LOG_INFO:
|
case SDMMC_LOG_INFO:
|
||||||
printk("%s [INFO]: ", sdmmc->name);
|
screen_log_level = SCREEN_LOG_LEVEL_DEBUG;
|
||||||
break;
|
break;
|
||||||
case SDMMC_LOG_DEBUG:
|
case SDMMC_LOG_DEBUG:
|
||||||
printk("%s [DEBUG]: ", 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 | SCREEN_LOG_LEVEL_NO_PREFIX, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void sdmmc_error(sdmmc_t *sdmmc, char *fmt, ...)
|
void sdmmc_error(sdmmc_t *sdmmc, char *fmt, ...)
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include "timers.h"
|
#include "timers.h"
|
||||||
#include "btn.h"
|
#include "btn.h"
|
||||||
#include "panic.h"
|
#include "panic.h"
|
||||||
|
#include "lib/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 | SCREEN_LOG_LEVEL_NO_PREFIX, "\n Press POWER to reboot.\n");
|
||||||
wait_for_button_and_reboot();
|
wait_for_button_and_reboot();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue