emummc: Add boot entry emuMMC selection

Using the key `emupath` on a boot entry will load the selected emuMMC.
This can also be forced by using the correct boot cfg storage bit and writing the path at the emummc path offset. Check readme for these.

This can only be used if the emuMMC was created via Nyx. because of the raw_based and file_based files that have emuMMC info.
(emupath=emuMMC/RAW1, emupath=emuMMC/SD00, etc)
This commit is contained in:
CTCaer 2020-04-27 09:30:53 +03:00
parent 3fa537e54a
commit 4160037c81
6 changed files with 117 additions and 20 deletions

View file

@ -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.

View file

@ -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);
}

View file

@ -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)

View file

@ -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);

View file

@ -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];
};

View file

@ -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];
};