diff --git a/README.md b/README.md index 909bd94..e663dff 100644 --- a/README.md +++ b/README.md @@ -75,6 +75,7 @@ You can find a template [Here](./res/hekate_ipl_template.ini) | fullsvcperm=1 | Disables SVC verification (full services permission) | | debugmode=1 | Enables Debug mode. Obsolete when used with exosphere as secmon. | | atmosphere=1 | Enables Atmosphère patching. | +| emupath={SD folder} | Forces emuMMC to use the selected one. (=emuMMC/RAW1, =emuMMC/SD00, etc). emuMMC must be created by hekate because it uses the raw_based/file_based files. | | nouserexceptions=1 | Disables usermode exception handlers when paired with Exosphère. | | userpmu=1 | Allows user access to PMU when paired with Exosphère. | | emummc_force_disable=1 | Disabled emuMMC if it's enabled. | @@ -97,14 +98,15 @@ This is in case the kips are incompatible between them. If compatible, you can o hekate has a boot storage in the binary that helps it configure it outside of BPMP enviroment: -| Offset / Name | Description | -| -------------------- | ----------------------------------------------------------------- | -| '0x94' boot_cfg | bit0: Force AutoBoot, bit1: Show launch log, bit2: Boot from ID, bit7: sept run. | -| '0x95' autoboot | If `Force AutoBoot`: 0: Force go to menu, else boot that entry. | -| '0x96' autoboot_list | If `Force AutoBoot` and `autoboot` then it boots from ini folder. | -| '0x97' extra_cfg | bit7: Force Nyx to run `Dump pkg1/2`. | -| '0x98' id[8] | When Boot from ID is set, it will search all inis automatically and find the boot entry with that id and boot it. Must be NULL terminated. | -| '0x98' xt_str[128] | Depends on the set cfg bits. | +| Offset / Name | Description | +| ----------------------- | ----------------------------------------------------------------- | +| '0x94' boot_cfg | bit0: `Force AutoBoot`, bit1: `Show launch log`, bit2: Boot from ID, bit3: `Boot to emuMMC`, bit7: `sept run`. | +| '0x95' autoboot | If `Force AutoBoot`: 0: Force go to menu, else boot that entry. | +| '0x96' autoboot_list | If `Force AutoBoot` and `autoboot` then it boots from ini folder. | +| '0x97' extra_cfg | bit7: Force Nyx to run `Dump pkg1/2`. | +| '0x98' xt_str[128] | Depends on the set cfg bits. | +| '0x98' id[8] | When `Boot from ID` is set, it will search all inis automatically and find the boot entry with that id and boot it. Must be NULL terminated. | +| '0xA0' emummc_path[120] | When `Boot to emuMMC` is set, it will override the current emuMMC (boot entry or emummc.ini). Must be NULL terminated. | If the main .ini is not found, it is created on the first hekate boot. diff --git a/bootloader/main.c b/bootloader/main.c index c66cbec..6f4c263 100644 --- a/bootloader/main.c +++ b/bootloader/main.c @@ -280,7 +280,7 @@ bool is_ipl_updated(void *buf, char *path, bool force) f_open(&fp, path, FA_WRITE | FA_CREATE_ALWAYS); f_write(&fp, (u8 *)reloc->start, reloc->end - reloc->start, NULL); - + // Write needed tag in case injected ipl uses old versioning. f_write(&fp, "ICTC49", 6, NULL); @@ -326,7 +326,7 @@ int launch_payload(char *path, bool update) if (f_read(&fp, buf, size, NULL)) { f_close(&fp); - + goto out; } @@ -476,6 +476,7 @@ void ini_list_launcher() { u8 max_entries = 61; char *payload_path = NULL; + char *emummc_path = NULL; ini_sec_t *cfg_sec = NULL; LIST_INIT(ini_list_sections); @@ -539,6 +540,20 @@ void ini_list_launcher() payload_path = ini_check_payload_section(cfg_sec); + if (cfg_sec) + { + LIST_FOREACH_ENTRY(ini_kv_t, kv, &cfg_sec->kvs, link) + { + if (!strcmp("emummc_force_disable", kv->key)) + h_cfg.emummc_force_disable = atoi(kv->val); + else if (!strcmp("emupath", kv->key)) + emummc_path = kv->val; + } + } + + if (emummc_path) + emummc_set_path(emummc_path); + if (cfg_sec && !payload_path) check_sept(cfg_sec); @@ -569,6 +584,13 @@ void ini_list_launcher() else if (!hos_launch(cfg_sec)) { EPRINTF("Failed to launch firmware."); + + if (emummc_path) + { + sd_mount(); + emummc_load_cfg(); + } + btn_wait(); } @@ -581,6 +603,7 @@ void launch_firmware() { u8 max_entries = 61; char *payload_path = NULL; + char *emummc_path = NULL; ini_sec_t *cfg_sec = NULL; LIST_INIT(ini_sections); @@ -663,9 +686,14 @@ void launch_firmware() { if (!strcmp("emummc_force_disable", kv->key)) h_cfg.emummc_force_disable = atoi(kv->val); + if (!strcmp("emupath", kv->key)) + emummc_path = kv->val; } } + if (emummc_path) + emummc_set_path(emummc_path); + if (cfg_sec && !payload_path) check_sept(cfg_sec); @@ -699,7 +727,14 @@ void launch_firmware() free(payload_path); } else if (!hos_launch(cfg_sec)) + { EPRINTF("Failed to launch firmware."); + if (emummc_path) + { + sd_mount(); + emummc_load_cfg(); + } + } out: sd_unmount(); @@ -771,7 +806,7 @@ void nyx_load_run() (*nyx_ptr)(); } -static ini_sec_t *get_ini_sec_from_id(ini_sec_t *ini_sec, char **bootlogoCustomEntry) +static ini_sec_t *get_ini_sec_from_id(ini_sec_t *ini_sec, char **bootlogoCustomEntry, char **emummc_path) { ini_sec_t *cfg_sec = NULL; @@ -788,10 +823,13 @@ static ini_sec_t *get_ini_sec_from_id(ini_sec_t *ini_sec, char **bootlogoCustomE *bootlogoCustomEntry = kv->val; if (!strcmp("emummc_force_disable", kv->key)) h_cfg.emummc_force_disable = atoi(kv->val); + if (!strcmp("emupath", kv->key)) + *emummc_path = kv->val; } if (!cfg_sec) { *bootlogoCustomEntry = NULL; + *emummc_path = NULL; h_cfg.emummc_force_disable = false; } @@ -812,6 +850,7 @@ static void _auto_launch_firmware() u8 *BOOTLOGO = NULL; char *payload_path = NULL; + char *emummc_path = NULL; u32 btn = 0; bool boot_from_id = (b_cfg.boot_cfg & BOOT_CFG_FROM_ID) && (b_cfg.boot_cfg & BOOT_CFG_AUTOBOOT_EN); if (boot_from_id) @@ -902,7 +941,7 @@ static void _auto_launch_firmware() } if (boot_from_id) - cfg_sec = get_ini_sec_from_id(ini_sec, &bootlogoCustomEntry); + cfg_sec = get_ini_sec_from_id(ini_sec, &bootlogoCustomEntry, &emummc_path); else if (h_cfg.autoboot == boot_entry_id && configEntry) { cfg_sec = ini_sec; @@ -910,8 +949,10 @@ static void _auto_launch_firmware() { if (!strcmp("logopath", kv->key)) bootlogoCustomEntry = kv->val; - if (!strcmp("emummc_force_disable", kv->key)) + else if (!strcmp("emummc_force_disable", kv->key)) h_cfg.emummc_force_disable = atoi(kv->val); + else if (!strcmp("emupath", kv->key)) + emummc_path = kv->val; } } if (cfg_sec) @@ -942,7 +983,7 @@ static void _auto_launch_firmware() continue; if (boot_from_id) - cfg_sec = get_ini_sec_from_id(ini_sec_list, &bootlogoCustomEntry); + cfg_sec = get_ini_sec_from_id(ini_sec_list, &bootlogoCustomEntry, &emummc_path); else if (h_cfg.autoboot == boot_entry_id) { h_cfg.emummc_force_disable = false; @@ -951,8 +992,10 @@ static void _auto_launch_firmware() { if (!strcmp("logopath", kv->key)) bootlogoCustomEntry = kv->val; - if (!strcmp("emummc_force_disable", kv->key)) + else if (!strcmp("emummc_force_disable", kv->key)) h_cfg.emummc_force_disable = atoi(kv->val); + else if (!strcmp("emupath", kv->key)) + emummc_path = kv->val; } } if (cfg_sec) @@ -1064,9 +1107,19 @@ skip_list: } else { + if (b_cfg.boot_cfg & BOOT_CFG_TO_EMUMMC) + emummc_set_path(b_cfg.emummc_path); + else if (emummc_path) + emummc_set_path(emummc_path); check_sept(cfg_sec); hos_launch(cfg_sec); + if (emummc_path || b_cfg.boot_cfg & BOOT_CFG_TO_EMUMMC) + { + sd_mount(); + emummc_load_cfg(); + } + EPRINTF("\nFailed to launch HOS!"); gfx_printf("\nPress any key...\n"); msleep(500); @@ -1077,9 +1130,9 @@ out: gfx_con.mute = false; // Clear boot reasons from binary. - if (b_cfg.boot_cfg & BOOT_CFG_FROM_ID) + if (b_cfg.boot_cfg & (BOOT_CFG_FROM_ID | BOOT_CFG_TO_EMUMMC)) memset(b_cfg.xt_str, 0, sizeof(b_cfg.xt_str)); - b_cfg.boot_cfg &= ~(BOOT_CFG_AUTOBOOT_EN | BOOT_CFG_FROM_LAUNCH | BOOT_CFG_FROM_ID); + b_cfg.boot_cfg &= ~(BOOT_CFG_AUTOBOOT_EN | BOOT_CFG_FROM_LAUNCH | BOOT_CFG_FROM_ID | BOOT_CFG_TO_EMUMMC); h_cfg.emummc_force_disable = false; nyx_load_run(); @@ -1254,7 +1307,7 @@ static void _check_low_battery() free(battery_icon); free(charging_icon); free(no_charging_icon); - + // Re enable Low Battery Monitor shutdown. max77620_low_battery_monitor_config(true); } diff --git a/bootloader/storage/emummc.c b/bootloader/storage/emummc.c index e3eb7ae..fa38f0f 100644 --- a/bootloader/storage/emummc.c +++ b/bootloader/storage/emummc.c @@ -38,7 +38,6 @@ extern void sd_unmount(); void emummc_load_cfg() { - sd_mount(); emu_cfg.enabled = 0; emu_cfg.path = NULL; emu_cfg.nintendo_path = NULL; @@ -47,7 +46,8 @@ void emummc_load_cfg() emu_cfg.file_based_part_size = 0; emu_cfg.active_part = 0; emu_cfg.fs_ver = 0; - emu_cfg.emummc_file_based_path = (char *)malloc(0x80); + if (!emu_cfg.emummc_file_based_path) + emu_cfg.emummc_file_based_path = (char *)malloc(0x80); LIST_INIT(ini_sections); if (ini_parse(&ini_sections, "emuMMC/emummc.ini", false)) @@ -78,6 +78,43 @@ void emummc_load_cfg() } } +void emummc_set_path(char *path) +{ + FIL fp; + bool found = false; + + strcpy(emu_cfg.emummc_file_based_path, path); + strcat(emu_cfg.emummc_file_based_path, "/raw_based"); + + if (!f_open(&fp, emu_cfg.emummc_file_based_path, FA_READ)) + { + if (!f_read(&fp, &emu_cfg.sector, 4, NULL)) + if (emu_cfg.sector) + found = true; + } + else + { + strcpy(emu_cfg.emummc_file_based_path, path); + strcat(emu_cfg.emummc_file_based_path, "/file_based"); + + if (!f_stat(emu_cfg.emummc_file_based_path, NULL)) + { + emu_cfg.sector = 0; + emu_cfg.path = path; + + found = true; + } + } + + if (found) + { + emu_cfg.enabled = 1; + emu_cfg.id = 0; + strcpy(emu_cfg.nintendo_path, path); + strcpy(emu_cfg.nintendo_path, "/Nintendo"); + } +} + static int emummc_raw_get_part_off(int part_idx) { switch (part_idx) diff --git a/bootloader/storage/emummc.h b/bootloader/storage/emummc.h index 5ef8cfd..8a34f20 100644 --- a/bootloader/storage/emummc.h +++ b/bootloader/storage/emummc.h @@ -50,6 +50,7 @@ typedef struct _emummc_cfg_t emummc_cfg_t emu_cfg; void emummc_load_cfg(); +void emummc_set_path(char *path); int emummc_storage_init_mmc(sdmmc_storage_t *storage, sdmmc_t *sdmmc); int emummc_storage_end(sdmmc_storage_t *storage); int emummc_storage_read(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, void *buf); diff --git a/bootloader/utils/types.h b/bootloader/utils/types.h index e0c43fe..96044dc 100644 --- a/bootloader/utils/types.h +++ b/bootloader/utils/types.h @@ -55,6 +55,7 @@ typedef int bool; #define BOOT_CFG_AUTOBOOT_EN (1 << 0) #define BOOT_CFG_FROM_LAUNCH (1 << 1) #define BOOT_CFG_FROM_ID (1 << 2) +#define BOOT_CFG_TO_EMUMMC (1 << 3) #define BOOT_CFG_SEPT_RUN (1 << 7) #define EXTRA_CFG_KEYS (1 << 0) @@ -75,6 +76,7 @@ typedef struct __attribute__((__packed__)) _boot_cfg_t struct { char id[8]; + char emummc_path[0x78]; }; u8 xt_str[0x80]; }; diff --git a/nyx/nyx_gui/utils/types.h b/nyx/nyx_gui/utils/types.h index e0c43fe..96044dc 100644 --- a/nyx/nyx_gui/utils/types.h +++ b/nyx/nyx_gui/utils/types.h @@ -55,6 +55,7 @@ typedef int bool; #define BOOT_CFG_AUTOBOOT_EN (1 << 0) #define BOOT_CFG_FROM_LAUNCH (1 << 1) #define BOOT_CFG_FROM_ID (1 << 2) +#define BOOT_CFG_TO_EMUMMC (1 << 3) #define BOOT_CFG_SEPT_RUN (1 << 7) #define EXTRA_CFG_KEYS (1 << 0) @@ -75,6 +76,7 @@ typedef struct __attribute__((__packed__)) _boot_cfg_t struct { char id[8]; + char emummc_path[0x78]; }; u8 xt_str[0x80]; };