bootloader: improve launch code

- Fix error not showing if payload is missing or can't be read
- Move errors to their callee function to save binary space
- Refactor various parameters and comments
- Reduce size on some errors
- Do not read HOS specific config in case of payload launch
- Remove unneeded code
This commit is contained in:
CTCaer 2022-10-11 07:21:41 +03:00
parent e7866387cd
commit c0b16320cc
3 changed files with 134 additions and 163 deletions

View file

@ -158,7 +158,7 @@ int parse_fss(launch_ctxt_t *ctxt, const char *path)
// Check if valid FSS0 and parse it. // Check if valid FSS0 and parse it.
if (fss_meta->magic == FSS0_MAGIC) if (fss_meta->magic == FSS0_MAGIC)
{ {
gfx_printf("Found FSS/PK3, Atmosphere %d.%d.%d-%08x\n" gfx_printf("Atmosphere %d.%d.%d-%08x via FSS0/PKG3\n"
"Max HOS: %d.%d.%d\n" "Max HOS: %d.%d.%d\n"
"Unpacking.. ", "Unpacking.. ",
fss_meta->version >> 24, (fss_meta->version >> 16) & 0xFF, (fss_meta->version >> 8) & 0xFF, fss_meta->git_rev, fss_meta->version >> 24, (fss_meta->version >> 16) & 0xFF, (fss_meta->version >> 8) & 0xFF, fss_meta->git_rev,

View file

@ -1178,5 +1178,7 @@ int hos_launch(ini_sec_t *cfg)
error: error:
emmc_end(); emmc_end();
EPRINTF("\nFailed to launch HOS!");
return 0; return 0;
} }

View file

@ -181,7 +181,7 @@ bool is_ipl_updated(void *buf, char *path, bool force)
return true; return true;
} }
int launch_payload(char *path, bool update, bool clear_screen) void launch_payload(char *path, bool update, bool clear_screen)
{ {
if (clear_screen) if (clear_screen)
gfx_clear_grey(0x1B); gfx_clear_grey(0x1B);
@ -254,8 +254,8 @@ int launch_payload(char *path, bool update, bool clear_screen)
// Some cards (Sandisk U1), do not like a fast power cycle. Wait min 100ms. // Some cards (Sandisk U1), do not like a fast power cycle. Wait min 100ms.
sdmmc_storage_init_wait_sd(); sdmmc_storage_init_wait_sd();
void (*ext_payload_ptr)() = (void *)EXT_PAYLOAD_ADDR;
void (*update_ptr)() = (void *)RCM_PAYLOAD_ADDR; void (*update_ptr)() = (void *)RCM_PAYLOAD_ADDR;
void (*ext_payload_ptr)() = (void *)EXT_PAYLOAD_ADDR;
// Launch our payload. // Launch our payload.
if (!update) if (!update)
@ -268,7 +268,11 @@ int launch_payload(char *path, bool update, bool clear_screen)
} }
out: out:
return 1; if (!update)
{
gfx_con.mute = false;
EPRINTF("Failed to launch payload!");
}
} }
void launch_tools() void launch_tools()
@ -318,7 +322,7 @@ void launch_tools()
if (i > 0) if (i > 0)
{ {
memset(&ments[i + 2], 0, sizeof(ment_t)); memset(&ments[i + 2], 0, sizeof(ment_t));
menu_t menu = { ments, "Choose a file to launch", 0, 0 }; menu_t menu = { ments, "Choose a payload", 0, 0 };
file_sec = (char *)tui_do_menu(&menu); file_sec = (char *)tui_do_menu(&menu);
@ -333,7 +337,7 @@ void launch_tools()
} }
} }
else else
EPRINTF("No payloads or modules found."); EPRINTF("No payloads found.");
free(ments); free(ments);
free(filelist); free(filelist);
@ -344,7 +348,6 @@ void launch_tools()
memcpy(dir + strlen(dir), file_sec, strlen(file_sec) + 1); memcpy(dir + strlen(dir), file_sec, strlen(file_sec) + 1);
launch_payload(dir, false, true); launch_payload(dir, false, true);
EPRINTF("Failed to launch payload.");
} }
failed_sd_mount: failed_sd_mount:
@ -359,8 +362,8 @@ void ini_list_launcher()
u8 max_entries = 61; u8 max_entries = 61;
char *payload_path = NULL; char *payload_path = NULL;
char *emummc_path = NULL; char *emummc_path = NULL;
ini_sec_t *cfg_sec = NULL; ini_sec_t *cfg_sec = NULL;
LIST_INIT(ini_list_sections); LIST_INIT(ini_list_sections);
gfx_clear_grey(0x1B); gfx_clear_grey(0x1B);
@ -372,7 +375,7 @@ void ini_list_launcher()
// Check that ini files exist and parse them. // Check that ini files exist and parse them.
if (!ini_parse(&ini_list_sections, "bootloader/ini", true)) if (!ini_parse(&ini_list_sections, "bootloader/ini", true))
{ {
EPRINTF("Could not find any ini\nin bootloader/ini!"); EPRINTF("No .ini files in bootloader/ini!");
goto parse_failed; goto parse_failed;
} }
@ -382,7 +385,7 @@ void ini_list_launcher()
ments[0].caption = "Back"; ments[0].caption = "Back";
ments[1].type = MENT_CHGLINE; ments[1].type = MENT_CHGLINE;
u32 i = 2; u32 sec_idx = 2;
LIST_FOREACH_ENTRY(ini_sec_t, ini_sec, &ini_list_sections, link) LIST_FOREACH_ENTRY(ini_sec_t, ini_sec, &ini_list_sections, link)
{ {
if (!strcmp(ini_sec->name, "config") || if (!strcmp(ini_sec->name, "config") ||
@ -390,49 +393,30 @@ void ini_list_launcher()
ini_sec->type == INI_NEWLINE) ini_sec->type == INI_NEWLINE)
continue; continue;
ments[i].type = ini_sec->type; ments[sec_idx].type = ini_sec->type;
ments[i].caption = ini_sec->name; ments[sec_idx].caption = ini_sec->name;
ments[i].data = ini_sec; ments[sec_idx].data = ini_sec;
if (ini_sec->type == MENT_CAPTION) if (ini_sec->type == MENT_CAPTION)
ments[i].color = ini_sec->color; ments[sec_idx].color = ini_sec->color;
i++; sec_idx++;
if ((i - 1) > max_entries) if ((sec_idx - 1) > max_entries)
break; break;
} }
if (i > 2) if (sec_idx > 2)
{ {
memset(&ments[i], 0, sizeof(ment_t)); memset(&ments[sec_idx], 0, sizeof(ment_t));
menu_t menu = { menu_t menu = {
ments, "Launch ini configurations", 0, 0 ments, "Launch ini entries", 0, 0
}; };
cfg_sec = (ini_sec_t *)tui_do_menu(&menu); cfg_sec = (ini_sec_t *)tui_do_menu(&menu);
if (cfg_sec)
{
u32 non_cfg = 1;
for (u32 j = 2; j < i; j++)
{
if (ments[j].type != INI_CHOICE)
non_cfg++;
if (ments[j].data == cfg_sec)
{
b_cfg.boot_cfg = BOOT_CFG_FROM_LAUNCH;
b_cfg.autoboot = j - non_cfg;
b_cfg.autoboot_list = 1;
break;
}
}
}
payload_path = ini_check_payload_section(cfg_sec); payload_path = ini_check_payload_section(cfg_sec);
if (cfg_sec) if (cfg_sec && !payload_path)
{ {
LIST_FOREACH_ENTRY(ini_kv_t, kv, &cfg_sec->kvs, link) LIST_FOREACH_ENTRY(ini_kv_t, kv, &cfg_sec->kvs, link)
{ {
@ -441,13 +425,13 @@ void ini_list_launcher()
else if (!strcmp("emupath", kv->key)) else if (!strcmp("emupath", kv->key))
emummc_path = kv->val; emummc_path = kv->val;
} }
}
if (emummc_path && !emummc_set_path(emummc_path)) if (emummc_path && !emummc_set_path(emummc_path))
{ {
EPRINTF("emupath is wrong!"); EPRINTF("emupath is wrong!");
goto wrong_emupath; goto wrong_emupath;
} }
}
if (!cfg_sec) if (!cfg_sec)
{ {
@ -466,14 +450,12 @@ parse_failed:
if (payload_path) if (payload_path)
{ {
// Try to launch Payload.
launch_payload(payload_path, false, true); launch_payload(payload_path, false, true);
EPRINTF("Failed to launch payload.");
free(payload_path);
} }
else if (!hos_launch(cfg_sec)) else if (!hos_launch(cfg_sec))
{ {
wrong_emupath: wrong_emupath:
EPRINTF("Failed to launch HOS.");
if (emummc_path) if (emummc_path)
{ {
sd_mount(); sd_mount();
@ -520,13 +502,14 @@ void launch_firmware()
ments[2].type = MENT_HANDLER; ments[2].type = MENT_HANDLER;
ments[2].caption = "Payloads..."; ments[2].caption = "Payloads...";
ments[2].handler = launch_tools; ments[2].handler = launch_tools;
ments[3].type = MENT_HANDLER; ments[3].type = MENT_HANDLER;
ments[3].caption = "More configs..."; ments[3].caption = "More configs...";
ments[3].handler = ini_list_launcher; ments[3].handler = ini_list_launcher;
ments[4].type = MENT_CHGLINE; ments[4].type = MENT_CHGLINE;
u32 i = 5; u32 sec_idx = 5;
LIST_FOREACH_ENTRY(ini_sec_t, ini_sec, &ini_sections, link) LIST_FOREACH_ENTRY(ini_sec_t, ini_sec, &ini_sections, link)
{ {
if (!strcmp(ini_sec->name, "config") || if (!strcmp(ini_sec->name, "config") ||
@ -534,54 +517,36 @@ void launch_firmware()
ini_sec->type == INI_NEWLINE) ini_sec->type == INI_NEWLINE)
continue; continue;
ments[i].type = ini_sec->type; ments[sec_idx].type = ini_sec->type;
ments[i].caption = ini_sec->name; ments[sec_idx].caption = ini_sec->name;
ments[i].data = ini_sec; ments[sec_idx].data = ini_sec;
if (ini_sec->type == MENT_CAPTION) if (ini_sec->type == MENT_CAPTION)
ments[i].color = ini_sec->color; ments[sec_idx].color = ini_sec->color;
i++; sec_idx++;
if ((i - 4) > max_entries) if ((sec_idx - 4) > max_entries)
break; break;
} }
if (i < 6) if (sec_idx < 6)
{ {
ments[i].type = MENT_CAPTION; ments[sec_idx].type = MENT_CAPTION;
ments[i].caption = "No main configs found..."; ments[sec_idx].caption = "No main configs found...";
ments[i].color = TXT_CLR_WARNING; ments[sec_idx].color = TXT_CLR_WARNING;
i++; sec_idx++;
} }
memset(&ments[i], 0, sizeof(ment_t)); memset(&ments[sec_idx], 0, sizeof(ment_t));
menu_t menu = { menu_t menu = {
ments, "Launch configurations", 0, 0 ments, "Launch configurations", 0, 0
}; };
cfg_sec = (ini_sec_t *)tui_do_menu(&menu); cfg_sec = (ini_sec_t *)tui_do_menu(&menu);
if (cfg_sec)
{
u8 non_cfg = 4;
for (u32 j = 5; j < i; j++)
{
if (ments[j].type != INI_CHOICE)
non_cfg++;
if (ments[j].data == cfg_sec)
{
b_cfg.boot_cfg = BOOT_CFG_FROM_LAUNCH;
b_cfg.autoboot = j - non_cfg;
b_cfg.autoboot_list = 0;
break;
}
}
}
payload_path = ini_check_payload_section(cfg_sec); payload_path = ini_check_payload_section(cfg_sec);
if (cfg_sec) if (cfg_sec && !payload_path)
{ {
LIST_FOREACH_ENTRY(ini_kv_t, kv, &cfg_sec->kvs, link) LIST_FOREACH_ENTRY(ini_kv_t, kv, &cfg_sec->kvs, link)
{ {
@ -590,13 +555,13 @@ void launch_firmware()
if (!strcmp("emupath", kv->key)) if (!strcmp("emupath", kv->key))
emummc_path = kv->val; emummc_path = kv->val;
} }
}
if (emummc_path && !emummc_set_path(emummc_path)) if (emummc_path && !emummc_set_path(emummc_path))
{ {
EPRINTF("emupath is wrong!"); EPRINTF("emupath is wrong!");
goto wrong_emupath; goto wrong_emupath;
} }
}
if (!cfg_sec) if (!cfg_sec)
{ {
@ -616,14 +581,12 @@ parse_failed:
if (payload_path) if (payload_path)
{ {
// Try to launch Payload.
launch_payload(payload_path, false, true); launch_payload(payload_path, false, true);
EPRINTF("Failed to launch payload.");
free(payload_path);
} }
else if (!hos_launch(cfg_sec)) else if (!hos_launch(cfg_sec))
{ {
wrong_emupath: wrong_emupath:
EPRINTF("Failed to launch HOS.");
if (emummc_path) if (emummc_path)
{ {
sd_mount(); sd_mount();
@ -673,15 +636,13 @@ void nyx_load_run()
// Set Nyx mode. // Set Nyx mode.
nyx_str->cfg = 0; nyx_str->cfg = 0;
if (b_cfg.extra_cfg)
{
if (b_cfg.extra_cfg & EXTRA_CFG_NYX_UMS) if (b_cfg.extra_cfg & EXTRA_CFG_NYX_UMS)
{ {
b_cfg.extra_cfg &= ~(EXTRA_CFG_NYX_UMS); b_cfg.extra_cfg &= ~(EXTRA_CFG_NYX_UMS);
nyx_str->cfg |= NYX_CFG_UMS; nyx_str->cfg |= NYX_CFG_UMS;
nyx_str->cfg |= b_cfg.ums << 24; nyx_str->cfg |= b_cfg.ums << 24;
} }
}
// Set hekate version used to boot Nyx. // Set hekate version used to boot Nyx.
nyx_str->version = ipl_ver.version - 0x303030; // Convert ASCII to numbers. nyx_str->version = ipl_ver.version - 0x303030; // Convert ASCII to numbers.
@ -689,12 +650,13 @@ void nyx_load_run()
// Set SD card initialization info. // Set SD card initialization info.
nyx_str->info.magic = NYX_NEW_INFO; nyx_str->info.magic = NYX_NEW_INFO;
nyx_str->info.sd_init = sd_get_mode(); nyx_str->info.sd_init = sd_get_mode();
// Set SD card error info.
u16 *sd_errors = sd_get_error_count(); u16 *sd_errors = sd_get_error_count();
for (u32 i = 0; i < 3; i++) for (u32 i = 0; i < 3; i++)
nyx_str->info.sd_errors[i] = sd_errors[i]; nyx_str->info.sd_errors[i] = sd_errors[i];
//memcpy((u8 *)nyx_str->irama, (void *)IRAM_BASE, 0x8000); reloc_meta_t *reloc = (reloc_meta_t *)(IPL_LOAD_ADDR + RELOC_META_OFF);
volatile reloc_meta_t *reloc = (reloc_meta_t *)(IPL_LOAD_ADDR + RELOC_META_OFF);
memcpy((u8 *)nyx_str->hekate, (u8 *)reloc->start, reloc->end - reloc->start); memcpy((u8 *)nyx_str->hekate, (u8 *)reloc->start, reloc->end - reloc->start);
void (*nyx_ptr)() = (void *)nyx; void (*nyx_ptr)() = (void *)nyx;
@ -722,17 +684,17 @@ static ini_sec_t *get_ini_sec_from_id(ini_sec_t *ini_sec, char **bootlogoCustomE
else else
break; break;
} }
if (!strcmp("logopath", kv->key))
*bootlogoCustomEntry = kv->val;
if (!strcmp("emummc_force_disable", kv->key))
h_cfg.emummc_force_disable = atoi(kv->val);
if (!strcmp("emupath", kv->key)) if (!strcmp("emupath", kv->key))
*emummc_path = kv->val; *emummc_path = kv->val;
else if (!strcmp("logopath", kv->key))
*bootlogoCustomEntry = kv->val;
else if (!strcmp("emummc_force_disable", kv->key))
h_cfg.emummc_force_disable = atoi(kv->val);
} }
if (!cfg_sec) if (!cfg_sec)
{ {
*bootlogoCustomEntry = NULL;
*emummc_path = NULL; *emummc_path = NULL;
*bootlogoCustomEntry = NULL;
h_cfg.emummc_force_disable = false; h_cfg.emummc_force_disable = false;
} }
@ -782,10 +744,10 @@ static void _auto_launch_firmware()
u32 pos_y; u32 pos_y;
}; };
u32 boot_entry_id = 0;
ini_sec_t *cfg_sec = NULL;
char *emummc_path = NULL; char *emummc_path = NULL;
char *bootlogoCustomEntry = NULL; char *bootlogoCustomEntry = NULL;
ini_sec_t *cfg_sec = NULL;
u32 boot_entry_id = 0;
bool config_entry_found = false; bool config_entry_found = false;
auto_launch_update(); auto_launch_update();
@ -872,10 +834,10 @@ static void _auto_launch_firmware()
{ {
if (!strcmp("logopath", kv->key)) if (!strcmp("logopath", kv->key))
bootlogoCustomEntry = kv->val; bootlogoCustomEntry = kv->val;
else if (!strcmp("emummc_force_disable", kv->key))
h_cfg.emummc_force_disable = atoi(kv->val);
else if (!strcmp("emupath", kv->key)) else if (!strcmp("emupath", kv->key))
emummc_path = kv->val; emummc_path = kv->val;
else if (!strcmp("emummc_force_disable", kv->key))
h_cfg.emummc_force_disable = atoi(kv->val);
} }
} }
if (cfg_sec) if (cfg_sec)
@ -917,10 +879,10 @@ static void _auto_launch_firmware()
{ {
if (!strcmp("logopath", kv->key)) if (!strcmp("logopath", kv->key))
bootlogoCustomEntry = kv->val; bootlogoCustomEntry = kv->val;
else if (!strcmp("emummc_force_disable", kv->key))
h_cfg.emummc_force_disable = atoi(kv->val);
else if (!strcmp("emupath", kv->key)) else if (!strcmp("emupath", kv->key))
emummc_path = kv->val; emummc_path = kv->val;
else if (!strcmp("emummc_force_disable", kv->key))
h_cfg.emummc_force_disable = atoi(kv->val);
} }
} }
if (cfg_sec) if (cfg_sec)
@ -937,18 +899,20 @@ skip_list:
if (!cfg_sec) if (!cfg_sec)
goto out; // No configurations or auto boot is disabled. goto out; // No configurations or auto boot is disabled.
u8 *bitmap = NULL;
struct _bmp_data bmpData;
bool bootlogoFound = false;
if (!(b_cfg.boot_cfg & BOOT_CFG_FROM_LAUNCH) && h_cfg.bootwait) if (!(b_cfg.boot_cfg & BOOT_CFG_FROM_LAUNCH) && h_cfg.bootwait)
{ {
u32 fsize; u32 fsize;
u8 *logo_buf = NULL; u8 *logo_buf = NULL;
u8 *bitmap = NULL;
struct _bmp_data bmpData;
bool bootlogoFound = false;
if (bootlogoCustomEntry) // Check if user set custom logo path at the boot entry. // Check if user set custom logo path at the boot entry.
if (bootlogoCustomEntry)
bitmap = (u8 *)sd_file_read(bootlogoCustomEntry, &fsize); bitmap = (u8 *)sd_file_read(bootlogoCustomEntry, &fsize);
if (!bitmap) // Custom entry bootlogo not found, trying default custom one. // Custom entry bootlogo not found, trying default custom one.
if (!bitmap)
bitmap = (u8 *)sd_file_read("bootloader/bootlogo.bmp", &fsize); bitmap = (u8 *)sd_file_read("bootloader/bootlogo.bmp", &fsize);
if (bitmap) if (bitmap)
@ -1018,9 +982,9 @@ skip_list:
if (payload_path) if (payload_path)
{ {
// Try to launch Payload.
launch_payload(payload_path, false, false); launch_payload(payload_path, false, false);
free(payload_path); goto error;
goto payload_error;
} }
else else
{ {
@ -1036,15 +1000,13 @@ skip_list:
hos_launch(cfg_sec); hos_launch(cfg_sec);
wrong_emupath: wrong_emupath:
EPRINTF("\nFailed to launch HOS!");
if (emummc_path || b_cfg.boot_cfg & BOOT_CFG_TO_EMUMMC) if (emummc_path || b_cfg.boot_cfg & BOOT_CFG_TO_EMUMMC)
{ {
sd_mount(); sd_mount();
emummc_load_cfg(); // Reload emuMMC config in case of emupath. emummc_load_cfg(); // Reload emuMMC config in case of emupath.
} }
payload_error: error:
gfx_con.mute = false; gfx_con.mute = false;
gfx_printf("\nPress any key...\n"); gfx_printf("\nPress any key...\n");
display_backlight_brightness(h_cfg.backlight, 1000); display_backlight_brightness(h_cfg.backlight, 1000);
@ -1087,14 +1049,17 @@ typedef struct _pstore_buf {
static void _show_errors() static void _show_errors()
{ {
u32 *excp_enabled = (u32 *)EXCP_EN_ADDR;
u32 *excp_type = (u32 *)EXCP_TYPE_ADDR;
u32 *excp_lr = (u32 *)EXCP_LR_ADDR; u32 *excp_lr = (u32 *)EXCP_LR_ADDR;
u32 *excp_type = (u32 *)EXCP_TYPE_ADDR;
u32 *excp_enabled = (u32 *)EXCP_EN_ADDR;
u32 panic_status = hw_rst_status & 0xFFFFF; u32 panic_status = hw_rst_status & 0xFFFFF;
// Check for exception error.
if (*excp_enabled == EXCP_MAGIC) if (*excp_enabled == EXCP_MAGIC)
h_cfg.errors |= ERR_EXCEPTION; h_cfg.errors |= ERR_EXCEPTION;
// Check for L4T kernel panic.
if (PMC(APBDEV_PMC_SCRATCH37) == PMC_SCRATCH37_KERNEL_PANIC_MAGIC) if (PMC(APBDEV_PMC_SCRATCH37) == PMC_SCRATCH37_KERNEL_PANIC_MAGIC)
{ {
// Set error and clear flag. // Set error and clear flag.
@ -1102,13 +1067,17 @@ static void _show_errors()
PMC(APBDEV_PMC_SCRATCH37) = 0; PMC(APBDEV_PMC_SCRATCH37) = 0;
} }
// Check for watchdog panic.
if (hw_rst_reason == PMC_RST_STATUS_WATCHDOG && panic_status && if (hw_rst_reason == PMC_RST_STATUS_WATCHDOG && panic_status &&
panic_status <= 0xFF && panic_status != 0x20 && panic_status != 0x21) panic_status <= 0xFF && panic_status != 0x20 && panic_status != 0x21)
{
h_cfg.errors |= ERR_PANIC_CODE; h_cfg.errors |= ERR_PANIC_CODE;
}
// Check if we had a panic while in CFW. // Check if we had a panic while in CFW.
secmon_exo_check_panic(); secmon_exo_check_panic();
// Handle errors.
if (h_cfg.errors) if (h_cfg.errors)
{ {
gfx_clear_grey(0x1B); gfx_clear_grey(0x1B);