fusee-primary: reorganize main to give some options when SD mount fails

This commit is contained in:
misson20000 2020-11-20 17:09:28 -08:00
parent 182b45b604
commit 5be26c6c92
5 changed files with 160 additions and 66 deletions

View file

@ -26,16 +26,19 @@ extern "C" {
static ams::fastboot::FastbootGadget fastboot_gadget((uint8_t*) 0xf0000000, 1024 * 1024 * 256); // 256 MiB download buffer reaches end of address space
extern "C" fastboot_return fastboot_enter(const bct0_t *bct0) {
bool should_enter = bct0->fastboot_force_enable;
extern "C" fastboot_return fastboot_enter(const bct0_t *bct0, bool force) {
bool should_enter = force || bct0->fastboot_force_enable;
log_setup_display();
if (!should_enter) {
if(should_enter) {
log_setup_display();
} else {
if (bct0->fastboot_button_timeout > 0) {
log_setup_display();
uint32_t timeout = bct0->fastboot_button_timeout;
uint32_t start_time = get_time_ms();
uint32_t last_message_secs = 0;
while (get_time_ms() - start_time < timeout) {
uint32_t seconds_remaining = (start_time + timeout - get_time_ms() + 999) / 1000;
if (seconds_remaining != last_message_secs) {
@ -48,20 +51,25 @@ extern "C" fastboot_return fastboot_enter(const bct0_t *bct0) {
break;
}
}
print((ScreenLogLevel) (SCREEN_LOG_LEVEL_NONE | SCREEN_LOG_LEVEL_NO_PREFIX), "\n\n");
if (!should_enter) {
log_cleanup_display();
return FASTBOOT_SKIPPED;
}
} else {
/* We did not initialize the display, so don't need to clean it up here. */
return FASTBOOT_SKIPPED;
}
}
if (!should_enter) {
log_cleanup_display();
return FASTBOOT_SKIPPED;
}
print(SCREEN_LOG_LEVEL_DEBUG, "Entering fastboot.\n");
print(SCREEN_LOG_LEVEL_DEBUG, "Entering fastboot. (forced = %d)\n", force);
ams::xusb::Initialize();
print(SCREEN_LOG_LEVEL_DEBUG, "Finished initializing USB hardware.\n");
ams::xusb::EnableDevice(fastboot_gadget);
print((ScreenLogLevel) (SCREEN_LOG_LEVEL_NONE | SCREEN_LOG_LEVEL_NO_PREFIX), "Fastboot mode:\n");
print((ScreenLogLevel) (SCREEN_LOG_LEVEL_NONE | SCREEN_LOG_LEVEL_NO_PREFIX), "-------------------------------\n");
print((ScreenLogLevel) (SCREEN_LOG_LEVEL_NONE | SCREEN_LOG_LEVEL_NO_PREFIX), "Volume up: Reboot to RCM.\n");
@ -71,6 +79,6 @@ extern "C" fastboot_return fastboot_enter(const bct0_t *bct0) {
fastboot_return r = fastboot_gadget.Run();
log_cleanup_display();
return r;
}

View file

@ -29,7 +29,7 @@ enum fastboot_return {
FASTBOOT_CHAINLOAD,
};
enum fastboot_return fastboot_enter(const bct0_t *bct0);
enum fastboot_return fastboot_enter(const bct0_t *bct0, bool force);
#ifdef __cplusplus
}

View file

@ -28,6 +28,7 @@
#include "lib/vsprintf.h"
#include "display/video_fb.h"
#include "fastboot/fastboot.h"
#include "btn.h"
extern void (*__program_exit_callback)(int rc);
@ -79,16 +80,6 @@ static void setup_env(void) {
/* Set up the exception handlers. */
setup_exception_handlers();
/* Mount the SD card. */
if (!mount_sd()) {
fatal_error("Failed to mount SD card!\n");
}
}
static void cleanup_env(void) {
/* Unmount the SD card. */
unmount_sd();
}
static void exit_callback(int rc) {
@ -96,8 +87,8 @@ static void exit_callback(int rc) {
relocate_and_chainload();
}
int main(void) {
const char *bct0_string;
int main(void) {
const char *bct0_string = DEFAULT_BCT0;
stage2_args_t *stage2_args;
uint32_t stage2_version = 0;
bct0_t bct0;
@ -108,46 +99,126 @@ int main(void) {
/* Check for panics. */
check_and_display_panic();
/* Load the BCT0 configuration ini off of the SD. */
bct0_string = load_config();
bool should_greet = true;
bool skip_fastboot = false;
bool stage2_loaded = false;
bool has_sd_card = false;
/* Parse the BCT0 configuration ini. */
if (bct0_parse(bct0_string, &bct0) < 0) {
fatal_error("Failed to parse BCT.ini!\n");
while (!stage2_loaded) {
/* Try to mount the SD card and load configuration. */
if (has_sd_card || mount_sd()) {
/* Load the BCT0 configuration ini off of the SD. */
bct0_string = load_config();
/* Parse the BCT0 configuration ini. */
if (bct0_parse(bct0_string, &bct0) < 0) {
fatal_error("Failed to parse BCT.ini!\n");
}
/* Override the global logging level. */
log_set_log_level(bct0.log_level);
if (should_greet && bct0.log_level != SCREEN_LOG_LEVEL_NONE) {
/* Initialize the display for debugging. */
log_setup_display();
/* Say hello. */
print(SCREEN_LOG_LEVEL_DEBUG | SCREEN_LOG_LEVEL_NO_PREFIX, "Welcome to Atmosph\xe8re Fus\xe9" "e!\n");
print(SCREEN_LOG_LEVEL_DEBUG, "Using color linear framebuffer at 0x%p!\n", log_get_display_framebuffer());
should_greet = false;
}
/* Run the MTC binary, if it hasn't already been run. */
if (!stage2_run_mtc(&bct0)) {
print(SCREEN_LOG_LEVEL_WARNING, "DRAM training failed! Continuing with untrained DRAM.\n");
}
/* Assert that our configuration is sane. */
stage2_validate_config(&bct0);
has_sd_card = true;
} else {
/* Initialize the display to show messages. */
log_setup_display();
/* Override logging level. */
log_set_log_level(SCREEN_LOG_LEVEL_INFO);
/* Prompt user for action. */
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "Failed to mount SD card!\n");
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, " Press Volume Up to retry.\n");
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, " Press Volume Down to enter fastboot mode.\n");
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "\n Press POWER to reboot.\n");
/* Wait for user action. */
uint32_t last_button = btn_read();
while (true) {
uint32_t button = btn_read();
if (button & BTN_VOL_UP && !(last_button & BTN_VOL_UP)) {
/* Skip the rest of the loop and return to beginning. If we
* succeed, don't offer to enter fastboot. */
skip_fastboot = true;
break;
}
if (button & BTN_VOL_DOWN && !(last_button & BTN_VOL_DOWN)) {
/* Do not skip entering fastboot mode, even if we were previously requested to. */
skip_fastboot = false;
break;
}
if (button & BTN_POWER) {
/* Reboot. */
reboot_to_self();
}
last_button = button;
}
log_cleanup_display();
}
if (!skip_fastboot) {
/* Try to enter fastboot if we are configured to, or force it if SD mount failed and we reached this point. */
switch(fastboot_enter(&bct0, !has_sd_card)) {
case FASTBOOT_INVALID:
case FASTBOOT_SKIPPED:
break;
case FASTBOOT_LOAD_STAGE2:
/* Return to start of loop to reload configuration and try again. Do
not attempt to enter fastboot again if config loads correctly,
but do offer to enter fastboot again if SD mount still fails. */
skip_fastboot = true;
continue;
case FASTBOOT_CHAINLOAD:
print(SCREEN_LOG_LEVEL_DEBUG, "fastboot: chainloading\n");
/* Break out of outer loop. Note that it is possible to reach
* this codepath with no SD card, in which case we forward the
* default BCT0 string to stage2.. */
stage2_loaded = true;
continue;
}
}
/* Load stage2 if the SD card mounted successfully and fastboot didn't continue out of the loop. */
if (has_sd_card) {
print(SCREEN_LOG_LEVEL_DEBUG, "Loading stage2 from sd card...\n");
stage2_load(&bct0);
print(SCREEN_LOG_LEVEL_DEBUG, "Finished loading stage2.\n");
stage2_loaded = true;
}
}
/* Override the global logging level. */
log_set_log_level(bct0.log_level);
if (bct0.log_level != SCREEN_LOG_LEVEL_NONE) {
/* Initialize the display for debugging. */
log_setup_display();
}
/* Say hello. */
print(SCREEN_LOG_LEVEL_DEBUG | SCREEN_LOG_LEVEL_NO_PREFIX, "Welcome to Atmosph\xe8re Fus\xe9" "e!\n");
print(SCREEN_LOG_LEVEL_DEBUG, "Using color linear framebuffer at 0x%p!\n", log_get_display_framebuffer());
/* Run the MTC binary. */
if (!stage2_run_mtc(&bct0)) {
print(SCREEN_LOG_LEVEL_WARNING, "DRAM training failed! Continuing with untrained DRAM.\n");
}
/* Assert that our configuration is sane. */
stage2_validate_config(&bct0);
/* Try to enter fastboot, if we are configured to. */
switch(fastboot_enter(&bct0)) {
case FASTBOOT_INVALID:
case FASTBOOT_SKIPPED:
case FASTBOOT_LOAD_STAGE2:
/* Load the loader payload into DRAM. */
stage2_load(&bct0);
break;
case FASTBOOT_CHAINLOAD:
print(SCREEN_LOG_LEVEL_DEBUG, "fastboot: chainloading\n");
break;
}
print(SCREEN_LOG_LEVEL_DEBUG, "Continuing to stage2...\n");
/* Setup argument data. */
strcpy(g_chainloader_arg_data, bct0.stage2_path);
@ -157,8 +228,10 @@ int main(void) {
strcpy(stage2_args->bct0, bct0_string);
g_chainloader_argc = 2;
/* Terminate the boot environment. */
cleanup_env();
/* Cleanup environment. */
if (has_sd_card) {
unmount_sd();
}
if (bct0.log_level != SCREEN_LOG_LEVEL_NONE) {
/* Wait a while for debugging. */
@ -168,6 +241,8 @@ int main(void) {
log_cleanup_display();
}
print(SCREEN_LOG_LEVEL_DEBUG, "Exiting...\n");
/* Finally, after the cleanup routines (__libc_fini_array, etc.) are called, jump to Stage2. */
__program_exit_callback = exit_callback;
return 0;

View file

@ -148,7 +148,7 @@ static void _check_and_display_atmosphere_fatal_error(void) {
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "Error Desc: %s (0x%x)\n", get_error_desc_str(ctx.error_desc), ctx.error_desc);
/* Save context to the SD card. */
{
if (mount_sd()) {
char filepath[0x40];
snprintf(filepath, sizeof(filepath) - 1, "/atmosphere/fatal_errors/report_%016llx.bin", ctx.report_identifier);
filepath[sizeof(filepath)-1] = 0;
@ -157,6 +157,10 @@ static void _check_and_display_atmosphere_fatal_error(void) {
} else {
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "Report saved to %s\n", filepath);
}
unmount_sd();
} else {
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "Failed to mount SD card to save report!\n");
}
/* Try to print a fix suggestion via automatic error detection. */

View file

@ -20,8 +20,13 @@
#include "utils.h"
bool stage2_run_mtc(const bct0_t *bct0) {
static bool has_run_mtc = false;
FILINFO info;
size_t size;
if (has_run_mtc) {
return true;
}
/* Check if the MTC binary is present. */
if (f_stat(bct0->stage2_mtc_path, &info) != FR_OK) {
@ -51,6 +56,8 @@ bool stage2_run_mtc(const bct0_t *bct0) {
/* Cleanup right away. */
memset((void *)bct0->stage2_load_address, 0, size);
has_run_mtc = true;
return mtc_res;
}