mirror of
https://github.com/CTCaer/hekate
synced 2024-12-22 11:21:23 +00:00
hekate/nyx: improve cyclomatic complexity
This commit is contained in:
parent
2f1d1572f7
commit
aee5861f65
9 changed files with 1733 additions and 1701 deletions
|
@ -192,87 +192,87 @@ int launch_payload(char *path, bool update, bool clear_screen)
|
||||||
gfx_clear_grey(0x1B);
|
gfx_clear_grey(0x1B);
|
||||||
gfx_con_setpos(0, 0);
|
gfx_con_setpos(0, 0);
|
||||||
|
|
||||||
if (sd_mount())
|
if (!sd_mount())
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
FIL fp;
|
||||||
|
if (f_open(&fp, path, FA_READ))
|
||||||
{
|
{
|
||||||
FIL fp;
|
gfx_con.mute = false;
|
||||||
if (f_open(&fp, path, FA_READ))
|
EPRINTFARGS("Payload file is missing!\n(%s)", path);
|
||||||
{
|
|
||||||
gfx_con.mute = false;
|
|
||||||
EPRINTFARGS("Payload file is missing!\n(%s)", path);
|
|
||||||
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read and copy the payload to our chosen address
|
// Read and copy the payload to our chosen address
|
||||||
void *buf;
|
void *buf;
|
||||||
u32 size = f_size(&fp);
|
u32 size = f_size(&fp);
|
||||||
|
|
||||||
if (size < 0x30000)
|
if (size < 0x30000)
|
||||||
buf = (void *)RCM_PAYLOAD_ADDR;
|
buf = (void *)RCM_PAYLOAD_ADDR;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
coreboot_addr = (void *)(COREBOOT_END_ADDR - size);
|
coreboot_addr = (void *)(COREBOOT_END_ADDR - size);
|
||||||
buf = coreboot_addr;
|
buf = coreboot_addr;
|
||||||
if (h_cfg.t210b01)
|
if (h_cfg.t210b01)
|
||||||
{
|
|
||||||
f_close(&fp);
|
|
||||||
|
|
||||||
gfx_con.mute = false;
|
|
||||||
EPRINTF("Coreboot not allowed on Mariko!");
|
|
||||||
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (f_read(&fp, buf, size, NULL))
|
|
||||||
{
|
{
|
||||||
f_close(&fp);
|
f_close(&fp);
|
||||||
|
|
||||||
|
gfx_con.mute = false;
|
||||||
|
EPRINTF("Coreboot not allowed on Mariko!");
|
||||||
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (f_read(&fp, buf, size, NULL))
|
||||||
|
{
|
||||||
f_close(&fp);
|
f_close(&fp);
|
||||||
|
|
||||||
if (update && is_ipl_updated(buf, path, false))
|
goto out;
|
||||||
goto out;
|
}
|
||||||
|
|
||||||
sd_end();
|
f_close(&fp);
|
||||||
|
|
||||||
if (size < 0x30000)
|
if (update && is_ipl_updated(buf, path, false))
|
||||||
{
|
goto out;
|
||||||
if (update)
|
|
||||||
memcpy((u8 *)(RCM_PAYLOAD_ADDR + PATCHED_RELOC_SZ), &b_cfg, sizeof(boot_cfg_t)); // Transfer boot cfg.
|
|
||||||
else
|
|
||||||
reloc_patcher(PATCHED_RELOC_ENTRY, EXT_PAYLOAD_ADDR, ALIGN(size, 0x10));
|
|
||||||
|
|
||||||
hw_reinit_workaround(false, byte_swap_32(*(u32 *)(buf + size - sizeof(u32))));
|
sd_end();
|
||||||
}
|
|
||||||
|
if (size < 0x30000)
|
||||||
|
{
|
||||||
|
if (update)
|
||||||
|
memcpy((u8 *)(RCM_PAYLOAD_ADDR + PATCHED_RELOC_SZ), &b_cfg, sizeof(boot_cfg_t)); // Transfer boot cfg.
|
||||||
else
|
else
|
||||||
{
|
reloc_patcher(PATCHED_RELOC_ENTRY, EXT_PAYLOAD_ADDR, ALIGN(size, 0x10));
|
||||||
reloc_patcher(PATCHED_RELOC_ENTRY, EXT_PAYLOAD_ADDR, 0x7000);
|
|
||||||
|
|
||||||
// Get coreboot seamless display magic.
|
hw_reinit_workaround(false, byte_swap_32(*(u32 *)(buf + size - sizeof(u32))));
|
||||||
u32 magic = 0;
|
}
|
||||||
char *magic_ptr = buf + COREBOOT_VER_OFF;
|
else
|
||||||
memcpy(&magic, magic_ptr + strlen(magic_ptr) - 4, 4);
|
{
|
||||||
hw_reinit_workaround(true, magic);
|
reloc_patcher(PATCHED_RELOC_ENTRY, EXT_PAYLOAD_ADDR, 0x7000);
|
||||||
}
|
|
||||||
|
|
||||||
// Some cards (Sandisk U1), do not like a fast power cycle. Wait min 100ms.
|
// Get coreboot seamless display magic.
|
||||||
sdmmc_storage_init_wait_sd();
|
u32 magic = 0;
|
||||||
|
char *magic_ptr = buf + COREBOOT_VER_OFF;
|
||||||
|
memcpy(&magic, magic_ptr + strlen(magic_ptr) - 4, 4);
|
||||||
|
hw_reinit_workaround(true, magic);
|
||||||
|
}
|
||||||
|
|
||||||
void (*ext_payload_ptr)() = (void *)EXT_PAYLOAD_ADDR;
|
// Some cards (Sandisk U1), do not like a fast power cycle. Wait min 100ms.
|
||||||
void (*update_ptr)() = (void *)RCM_PAYLOAD_ADDR;
|
sdmmc_storage_init_wait_sd();
|
||||||
|
|
||||||
// Launch our payload.
|
void (*ext_payload_ptr)() = (void *)EXT_PAYLOAD_ADDR;
|
||||||
if (!update)
|
void (*update_ptr)() = (void *)RCM_PAYLOAD_ADDR;
|
||||||
(*ext_payload_ptr)();
|
|
||||||
else
|
// Launch our payload.
|
||||||
{
|
if (!update)
|
||||||
// Set updated flag to skip check on launch.
|
(*ext_payload_ptr)();
|
||||||
EMC(EMC_SCRATCH0) |= EMC_HEKA_UPD;
|
else
|
||||||
(*update_ptr)();
|
{
|
||||||
}
|
// Set updated flag to skip check on launch.
|
||||||
|
EMC(EMC_SCRATCH0) |= EMC_HEKA_UPD;
|
||||||
|
(*update_ptr)();
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
@ -282,25 +282,6 @@ out:
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void auto_launch_update()
|
|
||||||
{
|
|
||||||
// Check if already chainloaded update and clear flag. Otherwise check for updates.
|
|
||||||
if (EMC(EMC_SCRATCH0) & EMC_HEKA_UPD)
|
|
||||||
EMC(EMC_SCRATCH0) &= ~EMC_HEKA_UPD;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Check if update.bin exists and is newer and launch it. Otherwise create it.
|
|
||||||
if (!f_stat("bootloader/update.bin", NULL))
|
|
||||||
launch_payload("bootloader/update.bin", true, false);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
u8 *buf = calloc(0x200, 1);
|
|
||||||
is_ipl_updated(buf, "bootloader/update.bin", true);
|
|
||||||
free(buf);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void launch_tools()
|
void launch_tools()
|
||||||
{
|
{
|
||||||
u8 max_entries = 61;
|
u8 max_entries = 61;
|
||||||
|
@ -313,63 +294,60 @@ void launch_tools()
|
||||||
gfx_clear_grey(0x1B);
|
gfx_clear_grey(0x1B);
|
||||||
gfx_con_setpos(0, 0);
|
gfx_con_setpos(0, 0);
|
||||||
|
|
||||||
if (sd_mount())
|
if (!sd_mount())
|
||||||
{
|
{
|
||||||
dir = (char *)malloc(256);
|
|
||||||
|
|
||||||
memcpy(dir, "bootloader/payloads", 20);
|
|
||||||
|
|
||||||
filelist = dirlist(dir, NULL, false, false);
|
|
||||||
|
|
||||||
u32 i = 0;
|
|
||||||
|
|
||||||
if (filelist)
|
|
||||||
{
|
|
||||||
// Build configuration menu.
|
|
||||||
ments[0].type = MENT_BACK;
|
|
||||||
ments[0].caption = "Back";
|
|
||||||
ments[1].type = MENT_CHGLINE;
|
|
||||||
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
if (i > max_entries || !filelist[i * 256])
|
|
||||||
break;
|
|
||||||
ments[i + 2].type = INI_CHOICE;
|
|
||||||
ments[i + 2].caption = &filelist[i * 256];
|
|
||||||
ments[i + 2].data = &filelist[i * 256];
|
|
||||||
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i > 0)
|
|
||||||
{
|
|
||||||
memset(&ments[i + 2], 0, sizeof(ment_t));
|
|
||||||
menu_t menu = { ments, "Choose a file to launch", 0, 0 };
|
|
||||||
|
|
||||||
file_sec = (char *)tui_do_menu(&menu);
|
|
||||||
|
|
||||||
if (!file_sec)
|
|
||||||
{
|
|
||||||
free(ments);
|
|
||||||
free(dir);
|
|
||||||
free(filelist);
|
|
||||||
sd_end();
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
EPRINTF("No payloads or modules found.");
|
|
||||||
|
|
||||||
free(ments);
|
free(ments);
|
||||||
free(filelist);
|
goto failed_sd_mount;
|
||||||
|
}
|
||||||
|
|
||||||
|
dir = (char *)malloc(256);
|
||||||
|
memcpy(dir, "bootloader/payloads", 20);
|
||||||
|
|
||||||
|
filelist = dirlist(dir, NULL, false, false);
|
||||||
|
|
||||||
|
u32 i = 0;
|
||||||
|
|
||||||
|
if (filelist)
|
||||||
|
{
|
||||||
|
// Build configuration menu.
|
||||||
|
ments[0].type = MENT_BACK;
|
||||||
|
ments[0].caption = "Back";
|
||||||
|
ments[1].type = MENT_CHGLINE;
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
if (i > max_entries || !filelist[i * 256])
|
||||||
|
break;
|
||||||
|
ments[i + 2].type = INI_CHOICE;
|
||||||
|
ments[i + 2].caption = &filelist[i * 256];
|
||||||
|
ments[i + 2].data = &filelist[i * 256];
|
||||||
|
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i > 0)
|
||||||
|
{
|
||||||
|
memset(&ments[i + 2], 0, sizeof(ment_t));
|
||||||
|
menu_t menu = { ments, "Choose a file to launch", 0, 0 };
|
||||||
|
|
||||||
|
file_sec = (char *)tui_do_menu(&menu);
|
||||||
|
|
||||||
|
if (!file_sec)
|
||||||
|
{
|
||||||
|
free(ments);
|
||||||
|
free(dir);
|
||||||
|
free(filelist);
|
||||||
|
sd_end();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
EPRINTF("No payloads or modules found.");
|
||||||
free(ments);
|
|
||||||
goto out;
|
free(ments);
|
||||||
}
|
free(filelist);
|
||||||
|
|
||||||
if (file_sec)
|
if (file_sec)
|
||||||
{
|
{
|
||||||
|
@ -380,7 +358,7 @@ void launch_tools()
|
||||||
EPRINTF("Failed to launch payload.");
|
EPRINTF("Failed to launch payload.");
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
failed_sd_mount:
|
||||||
sd_end();
|
sd_end();
|
||||||
free(dir);
|
free(dir);
|
||||||
|
|
||||||
|
@ -399,94 +377,101 @@ void ini_list_launcher()
|
||||||
gfx_clear_grey(0x1B);
|
gfx_clear_grey(0x1B);
|
||||||
gfx_con_setpos(0, 0);
|
gfx_con_setpos(0, 0);
|
||||||
|
|
||||||
if (sd_mount())
|
if (!sd_mount())
|
||||||
|
goto parse_failed;
|
||||||
|
|
||||||
|
// 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!");
|
||||||
{
|
goto parse_failed;
|
||||||
// Build configuration menu.
|
|
||||||
ment_t *ments = (ment_t *)malloc(sizeof(ment_t) * (max_entries + 3));
|
|
||||||
ments[0].type = MENT_BACK;
|
|
||||||
ments[0].caption = "Back";
|
|
||||||
ments[1].type = MENT_CHGLINE;
|
|
||||||
|
|
||||||
u32 i = 2;
|
|
||||||
LIST_FOREACH_ENTRY(ini_sec_t, ini_sec, &ini_list_sections, link)
|
|
||||||
{
|
|
||||||
if (!strcmp(ini_sec->name, "config") ||
|
|
||||||
ini_sec->type == INI_COMMENT || ini_sec->type == INI_NEWLINE)
|
|
||||||
continue;
|
|
||||||
ments[i].type = ini_sec->type;
|
|
||||||
ments[i].caption = ini_sec->name;
|
|
||||||
ments[i].data = ini_sec;
|
|
||||||
if (ini_sec->type == MENT_CAPTION)
|
|
||||||
ments[i].color = ini_sec->color;
|
|
||||||
i++;
|
|
||||||
|
|
||||||
if ((i - 1) > max_entries)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (i > 2)
|
|
||||||
{
|
|
||||||
memset(&ments[i], 0, sizeof(ment_t));
|
|
||||||
menu_t menu = {
|
|
||||||
ments, "Launch ini configurations", 0, 0
|
|
||||||
};
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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))
|
|
||||||
{
|
|
||||||
EPRINTF("emupath is wrong!");
|
|
||||||
goto wrong_emupath;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!cfg_sec)
|
|
||||||
{
|
|
||||||
free(ments);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
EPRINTF("No extra configs found.");
|
|
||||||
free(ments);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
EPRINTF("Could not find any ini\nin bootloader/ini!");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Build configuration menu.
|
||||||
|
ment_t *ments = (ment_t *)malloc(sizeof(ment_t) * (max_entries + 3));
|
||||||
|
ments[0].type = MENT_BACK;
|
||||||
|
ments[0].caption = "Back";
|
||||||
|
ments[1].type = MENT_CHGLINE;
|
||||||
|
|
||||||
|
u32 i = 2;
|
||||||
|
LIST_FOREACH_ENTRY(ini_sec_t, ini_sec, &ini_list_sections, link)
|
||||||
|
{
|
||||||
|
if (!strcmp(ini_sec->name, "config") ||
|
||||||
|
ini_sec->type == INI_COMMENT ||
|
||||||
|
ini_sec->type == INI_NEWLINE)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ments[i].type = ini_sec->type;
|
||||||
|
ments[i].caption = ini_sec->name;
|
||||||
|
ments[i].data = ini_sec;
|
||||||
|
|
||||||
|
if (ini_sec->type == MENT_CAPTION)
|
||||||
|
ments[i].color = ini_sec->color;
|
||||||
|
i++;
|
||||||
|
|
||||||
|
if ((i - 1) > max_entries)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i > 2)
|
||||||
|
{
|
||||||
|
memset(&ments[i], 0, sizeof(ment_t));
|
||||||
|
menu_t menu = {
|
||||||
|
ments, "Launch ini configurations", 0, 0
|
||||||
|
};
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
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))
|
||||||
|
{
|
||||||
|
EPRINTF("emupath is wrong!");
|
||||||
|
goto wrong_emupath;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!cfg_sec)
|
||||||
|
{
|
||||||
|
free(ments);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
EPRINTF("No extra configs found.");
|
||||||
|
free(ments);
|
||||||
|
|
||||||
|
parse_failed:
|
||||||
if (!cfg_sec)
|
if (!cfg_sec)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
@ -524,108 +509,116 @@ void launch_firmware()
|
||||||
gfx_clear_grey(0x1B);
|
gfx_clear_grey(0x1B);
|
||||||
gfx_con_setpos(0, 0);
|
gfx_con_setpos(0, 0);
|
||||||
|
|
||||||
if (sd_mount())
|
if (!sd_mount())
|
||||||
|
goto parse_failed;
|
||||||
|
|
||||||
|
// Load emuMMC configuration.
|
||||||
|
emummc_load_cfg();
|
||||||
|
|
||||||
|
// Check that main configuration exists and parse it.
|
||||||
|
if (!ini_parse(&ini_sections, "bootloader/hekate_ipl.ini", false))
|
||||||
{
|
{
|
||||||
// Load emuMMC configuration.
|
EPRINTF("Could not open 'bootloader/hekate_ipl.ini'!");
|
||||||
emummc_load_cfg();
|
goto parse_failed;
|
||||||
|
|
||||||
if (ini_parse(&ini_sections, "bootloader/hekate_ipl.ini", false))
|
|
||||||
{
|
|
||||||
// Build configuration menu.
|
|
||||||
ment_t *ments = (ment_t *)malloc(sizeof(ment_t) * (max_entries + 6));
|
|
||||||
ments[0].type = MENT_BACK;
|
|
||||||
ments[0].caption = "Back";
|
|
||||||
ments[1].type = MENT_CHGLINE;
|
|
||||||
|
|
||||||
ments[2].type = MENT_HANDLER;
|
|
||||||
ments[2].caption = "Payloads...";
|
|
||||||
ments[2].handler = launch_tools;
|
|
||||||
ments[3].type = MENT_HANDLER;
|
|
||||||
ments[3].caption = "More configs...";
|
|
||||||
ments[3].handler = ini_list_launcher;
|
|
||||||
|
|
||||||
ments[4].type = MENT_CHGLINE;
|
|
||||||
|
|
||||||
u32 i = 5;
|
|
||||||
LIST_FOREACH_ENTRY(ini_sec_t, ini_sec, &ini_sections, link)
|
|
||||||
{
|
|
||||||
if (!strcmp(ini_sec->name, "config") ||
|
|
||||||
ini_sec->type == INI_COMMENT || ini_sec->type == INI_NEWLINE)
|
|
||||||
continue;
|
|
||||||
ments[i].type = ini_sec->type;
|
|
||||||
ments[i].caption = ini_sec->name;
|
|
||||||
ments[i].data = ini_sec;
|
|
||||||
if (ini_sec->type == MENT_CAPTION)
|
|
||||||
ments[i].color = ini_sec->color;
|
|
||||||
i++;
|
|
||||||
|
|
||||||
if ((i - 4) > max_entries)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (i < 6)
|
|
||||||
{
|
|
||||||
ments[i].type = MENT_CAPTION;
|
|
||||||
ments[i].caption = "No main configs found...";
|
|
||||||
ments[i].color = 0xFFFFDD00;
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
memset(&ments[i], 0, sizeof(ment_t));
|
|
||||||
menu_t menu = {
|
|
||||||
ments, "Launch configurations", 0, 0
|
|
||||||
};
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
if (!strcmp("emupath", kv->key))
|
|
||||||
emummc_path = kv->val;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (emummc_path && !emummc_set_path(emummc_path))
|
|
||||||
{
|
|
||||||
EPRINTF("emupath is wrong!");
|
|
||||||
goto wrong_emupath;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!cfg_sec)
|
|
||||||
{
|
|
||||||
free(ments);
|
|
||||||
sd_end();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
free(ments);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
EPRINTF("Could not open 'bootloader/hekate_ipl.ini'.\nMake sure it exists!");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Build configuration menu.
|
||||||
|
ment_t *ments = (ment_t *)malloc(sizeof(ment_t) * (max_entries + 6));
|
||||||
|
ments[0].type = MENT_BACK;
|
||||||
|
ments[0].caption = "Back";
|
||||||
|
ments[1].type = MENT_CHGLINE;
|
||||||
|
|
||||||
|
ments[2].type = MENT_HANDLER;
|
||||||
|
ments[2].caption = "Payloads...";
|
||||||
|
ments[2].handler = launch_tools;
|
||||||
|
ments[3].type = MENT_HANDLER;
|
||||||
|
ments[3].caption = "More configs...";
|
||||||
|
ments[3].handler = ini_list_launcher;
|
||||||
|
|
||||||
|
ments[4].type = MENT_CHGLINE;
|
||||||
|
|
||||||
|
u32 i = 5;
|
||||||
|
LIST_FOREACH_ENTRY(ini_sec_t, ini_sec, &ini_sections, link)
|
||||||
|
{
|
||||||
|
if (!strcmp(ini_sec->name, "config") ||
|
||||||
|
ini_sec->type == INI_COMMENT ||
|
||||||
|
ini_sec->type == INI_NEWLINE)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ments[i].type = ini_sec->type;
|
||||||
|
ments[i].caption = ini_sec->name;
|
||||||
|
ments[i].data = ini_sec;
|
||||||
|
|
||||||
|
if (ini_sec->type == MENT_CAPTION)
|
||||||
|
ments[i].color = ini_sec->color;
|
||||||
|
i++;
|
||||||
|
|
||||||
|
if ((i - 4) > max_entries)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i < 6)
|
||||||
|
{
|
||||||
|
ments[i].type = MENT_CAPTION;
|
||||||
|
ments[i].caption = "No main configs found...";
|
||||||
|
ments[i].color = 0xFFFFDD00;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&ments[i], 0, sizeof(ment_t));
|
||||||
|
menu_t menu = {
|
||||||
|
ments, "Launch configurations", 0, 0
|
||||||
|
};
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
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);
|
||||||
|
if (!strcmp("emupath", kv->key))
|
||||||
|
emummc_path = kv->val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (emummc_path && !emummc_set_path(emummc_path))
|
||||||
|
{
|
||||||
|
EPRINTF("emupath is wrong!");
|
||||||
|
goto wrong_emupath;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!cfg_sec)
|
||||||
|
{
|
||||||
|
free(ments);
|
||||||
|
sd_end();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(ments);
|
||||||
|
|
||||||
|
parse_failed:
|
||||||
if (!cfg_sec)
|
if (!cfg_sec)
|
||||||
{
|
{
|
||||||
gfx_printf("\nPress any key...\n");
|
gfx_printf("\nPress any key...\n");
|
||||||
|
@ -769,6 +762,25 @@ static void _bootloader_corruption_protect()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void auto_launch_update()
|
||||||
|
{
|
||||||
|
// Check if already chainloaded update and clear flag. Otherwise check for updates.
|
||||||
|
if (EMC(EMC_SCRATCH0) & EMC_HEKA_UPD)
|
||||||
|
EMC(EMC_SCRATCH0) &= ~EMC_HEKA_UPD;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Check if update.bin exists and is newer and launch it. Otherwise create it.
|
||||||
|
if (!f_stat("bootloader/update.bin", NULL))
|
||||||
|
launch_payload("bootloader/update.bin", true, false);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
u8 *buf = calloc(0x200, 1);
|
||||||
|
is_ipl_updated(buf, "bootloader/update.bin", true);
|
||||||
|
free(buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void _auto_launch_firmware()
|
static void _auto_launch_firmware()
|
||||||
{
|
{
|
||||||
struct _bmp_data
|
struct _bmp_data
|
||||||
|
@ -784,6 +796,8 @@ static void _auto_launch_firmware()
|
||||||
char *emummc_path = NULL;
|
char *emummc_path = NULL;
|
||||||
char *bootlogoCustomEntry = NULL;
|
char *bootlogoCustomEntry = NULL;
|
||||||
ini_sec_t *cfg_sec = NULL;
|
ini_sec_t *cfg_sec = NULL;
|
||||||
|
u32 boot_entry_id = 0;
|
||||||
|
bool config_entry_found = false;
|
||||||
|
|
||||||
auto_launch_update();
|
auto_launch_update();
|
||||||
|
|
||||||
|
@ -803,142 +817,137 @@ static void _auto_launch_firmware()
|
||||||
if (f_stat("bootloader/hekate_ipl.ini", NULL))
|
if (f_stat("bootloader/hekate_ipl.ini", NULL))
|
||||||
create_config_entry();
|
create_config_entry();
|
||||||
|
|
||||||
if (ini_parse(&ini_sections, "bootloader/hekate_ipl.ini", false))
|
// Parse hekate main configuration.
|
||||||
{
|
if (!ini_parse(&ini_sections, "bootloader/hekate_ipl.ini", false))
|
||||||
u32 configEntry = 0;
|
|
||||||
u32 boot_entry_id = 0;
|
|
||||||
|
|
||||||
// Load configuration.
|
|
||||||
LIST_FOREACH_ENTRY(ini_sec_t, ini_sec, &ini_sections, link)
|
|
||||||
{
|
|
||||||
// Skip other ini entries for autoboot.
|
|
||||||
if (ini_sec->type == INI_CHOICE)
|
|
||||||
{
|
|
||||||
if (!strcmp(ini_sec->name, "config"))
|
|
||||||
{
|
|
||||||
configEntry = 1;
|
|
||||||
LIST_FOREACH_ENTRY(ini_kv_t, kv, &ini_sec->kvs, link)
|
|
||||||
{
|
|
||||||
if (!strcmp("autoboot", kv->key))
|
|
||||||
h_cfg.autoboot = atoi(kv->val);
|
|
||||||
else if (!strcmp("autoboot_list", kv->key))
|
|
||||||
h_cfg.autoboot_list = atoi(kv->val);
|
|
||||||
else if (!strcmp("bootwait", kv->key))
|
|
||||||
{
|
|
||||||
h_cfg.bootwait = atoi(kv->val);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Clamp value to default if it exceeds 20s to protect against corruption.
|
|
||||||
* Allow up to 20s though for use in cases where user needs lots of time.
|
|
||||||
* For example dock-only use and r2p with enough time to reach dock and cancel it.
|
|
||||||
*/
|
|
||||||
if (h_cfg.bootwait > 20)
|
|
||||||
h_cfg.bootwait = 3;
|
|
||||||
}
|
|
||||||
else if (!strcmp("backlight", kv->key))
|
|
||||||
h_cfg.backlight = atoi(kv->val);
|
|
||||||
else if (!strcmp("autohosoff", kv->key))
|
|
||||||
h_cfg.autohosoff = atoi(kv->val);
|
|
||||||
else if (!strcmp("autonogc", kv->key))
|
|
||||||
h_cfg.autonogc = atoi(kv->val);
|
|
||||||
else if (!strcmp("updater2p", kv->key))
|
|
||||||
h_cfg.updater2p = atoi(kv->val);
|
|
||||||
else if (!strcmp("bootprotect", kv->key))
|
|
||||||
h_cfg.bootprotect = atoi(kv->val);
|
|
||||||
}
|
|
||||||
boot_entry_id++;
|
|
||||||
|
|
||||||
// Override autoboot.
|
|
||||||
if (b_cfg.boot_cfg & BOOT_CFG_AUTOBOOT_EN)
|
|
||||||
{
|
|
||||||
h_cfg.autoboot = b_cfg.autoboot;
|
|
||||||
h_cfg.autoboot_list = b_cfg.autoboot_list;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Apply bootloader protection against corruption.
|
|
||||||
_bootloader_corruption_protect();
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (boot_from_id)
|
|
||||||
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;
|
|
||||||
LIST_FOREACH_ENTRY(ini_kv_t, kv, &cfg_sec->kvs, link)
|
|
||||||
{
|
|
||||||
if (!strcmp("logopath", kv->key))
|
|
||||||
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))
|
|
||||||
emummc_path = kv->val;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (cfg_sec)
|
|
||||||
break;
|
|
||||||
boot_entry_id++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (h_cfg.autohosoff && !(b_cfg.boot_cfg & BOOT_CFG_AUTOBOOT_EN))
|
|
||||||
check_power_off_from_hos();
|
|
||||||
|
|
||||||
if (h_cfg.autoboot_list || (boot_from_id && !cfg_sec))
|
|
||||||
{
|
|
||||||
if (boot_from_id && cfg_sec)
|
|
||||||
goto skip_list;
|
|
||||||
|
|
||||||
cfg_sec = NULL;
|
|
||||||
boot_entry_id = 1;
|
|
||||||
bootlogoCustomEntry = NULL;
|
|
||||||
|
|
||||||
if (ini_parse(&ini_list_sections, "bootloader/ini", true))
|
|
||||||
{
|
|
||||||
LIST_FOREACH_ENTRY(ini_sec_t, ini_sec_list, &ini_list_sections, link)
|
|
||||||
{
|
|
||||||
if (ini_sec_list->type == INI_CHOICE)
|
|
||||||
{
|
|
||||||
if (!strcmp(ini_sec_list->name, "config"))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (boot_from_id)
|
|
||||||
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;
|
|
||||||
cfg_sec = ini_sec_list;
|
|
||||||
LIST_FOREACH_ENTRY(ini_kv_t, kv, &cfg_sec->kvs, link)
|
|
||||||
{
|
|
||||||
if (!strcmp("logopath", kv->key))
|
|
||||||
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))
|
|
||||||
emummc_path = kv->val;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (cfg_sec)
|
|
||||||
break;
|
|
||||||
boot_entry_id++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
skip_list:
|
|
||||||
// Add missing configuration entry.
|
|
||||||
if (!configEntry)
|
|
||||||
create_config_entry();
|
|
||||||
|
|
||||||
if (!cfg_sec)
|
|
||||||
goto out; // No configurations or auto boot is disabled.
|
|
||||||
}
|
|
||||||
else
|
|
||||||
goto out; // Can't load hekate_ipl.ini.
|
goto out; // Can't load hekate_ipl.ini.
|
||||||
|
|
||||||
|
// Load configuration.
|
||||||
|
LIST_FOREACH_ENTRY(ini_sec_t, ini_sec, &ini_sections, link)
|
||||||
|
{
|
||||||
|
// Skip other ini entries for autoboot.
|
||||||
|
if (ini_sec->type == INI_CHOICE)
|
||||||
|
{
|
||||||
|
if (!config_entry_found && !strcmp(ini_sec->name, "config"))
|
||||||
|
{
|
||||||
|
config_entry_found = true;
|
||||||
|
LIST_FOREACH_ENTRY(ini_kv_t, kv, &ini_sec->kvs, link)
|
||||||
|
{
|
||||||
|
if (!strcmp("autoboot", kv->key))
|
||||||
|
h_cfg.autoboot = atoi(kv->val);
|
||||||
|
else if (!strcmp("autoboot_list", kv->key))
|
||||||
|
h_cfg.autoboot_list = atoi(kv->val);
|
||||||
|
else if (!strcmp("bootwait", kv->key))
|
||||||
|
{
|
||||||
|
h_cfg.bootwait = atoi(kv->val);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Clamp value to default if it exceeds 20s to protect against corruption.
|
||||||
|
* Allow up to 20s though for use in cases where user needs lots of time.
|
||||||
|
* For example dock-only use and r2p with enough time to reach dock and cancel it.
|
||||||
|
*/
|
||||||
|
if (h_cfg.bootwait > 20)
|
||||||
|
h_cfg.bootwait = 3;
|
||||||
|
}
|
||||||
|
else if (!strcmp("backlight", kv->key))
|
||||||
|
h_cfg.backlight = atoi(kv->val);
|
||||||
|
else if (!strcmp("autohosoff", kv->key))
|
||||||
|
h_cfg.autohosoff = atoi(kv->val);
|
||||||
|
else if (!strcmp("autonogc", kv->key))
|
||||||
|
h_cfg.autonogc = atoi(kv->val);
|
||||||
|
else if (!strcmp("updater2p", kv->key))
|
||||||
|
h_cfg.updater2p = atoi(kv->val);
|
||||||
|
else if (!strcmp("bootprotect", kv->key))
|
||||||
|
h_cfg.bootprotect = atoi(kv->val);
|
||||||
|
}
|
||||||
|
boot_entry_id++;
|
||||||
|
|
||||||
|
// Override autoboot.
|
||||||
|
if (b_cfg.boot_cfg & BOOT_CFG_AUTOBOOT_EN)
|
||||||
|
{
|
||||||
|
h_cfg.autoboot = b_cfg.autoboot;
|
||||||
|
h_cfg.autoboot_list = b_cfg.autoboot_list;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply bootloader protection against corruption.
|
||||||
|
_bootloader_corruption_protect();
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (boot_from_id)
|
||||||
|
cfg_sec = get_ini_sec_from_id(ini_sec, &bootlogoCustomEntry, &emummc_path);
|
||||||
|
else if (h_cfg.autoboot == boot_entry_id && config_entry_found)
|
||||||
|
{
|
||||||
|
cfg_sec = ini_sec;
|
||||||
|
LIST_FOREACH_ENTRY(ini_kv_t, kv, &cfg_sec->kvs, link)
|
||||||
|
{
|
||||||
|
if (!strcmp("logopath", kv->key))
|
||||||
|
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))
|
||||||
|
emummc_path = kv->val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (cfg_sec)
|
||||||
|
break;
|
||||||
|
boot_entry_id++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (h_cfg.autohosoff && !(b_cfg.boot_cfg & BOOT_CFG_AUTOBOOT_EN))
|
||||||
|
check_power_off_from_hos();
|
||||||
|
|
||||||
|
if (h_cfg.autoboot_list || (boot_from_id && !cfg_sec))
|
||||||
|
{
|
||||||
|
if (boot_from_id && cfg_sec)
|
||||||
|
goto skip_list;
|
||||||
|
|
||||||
|
cfg_sec = NULL;
|
||||||
|
boot_entry_id = 1;
|
||||||
|
bootlogoCustomEntry = NULL;
|
||||||
|
|
||||||
|
if (!ini_parse(&ini_list_sections, "bootloader/ini", true))
|
||||||
|
goto skip_list;
|
||||||
|
|
||||||
|
LIST_FOREACH_ENTRY(ini_sec_t, ini_sec_list, &ini_list_sections, link)
|
||||||
|
{
|
||||||
|
if (ini_sec_list->type != INI_CHOICE)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!strcmp(ini_sec_list->name, "config"))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (boot_from_id)
|
||||||
|
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;
|
||||||
|
cfg_sec = ini_sec_list;
|
||||||
|
LIST_FOREACH_ENTRY(ini_kv_t, kv, &cfg_sec->kvs, link)
|
||||||
|
{
|
||||||
|
if (!strcmp("logopath", kv->key))
|
||||||
|
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))
|
||||||
|
emummc_path = kv->val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (cfg_sec)
|
||||||
|
break;
|
||||||
|
boot_entry_id++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
skip_list:
|
||||||
|
// Add missing configuration entry.
|
||||||
|
if (!config_entry_found)
|
||||||
|
create_config_entry();
|
||||||
|
|
||||||
|
if (!cfg_sec)
|
||||||
|
goto out; // No configurations or auto boot is disabled.
|
||||||
|
|
||||||
u8 *bitmap = NULL;
|
u8 *bitmap = NULL;
|
||||||
struct _bmp_data bmpData;
|
struct _bmp_data bmpData;
|
||||||
bool bootlogoFound = false;
|
bool bootlogoFound = false;
|
||||||
|
|
|
@ -950,124 +950,125 @@ static int _restore_emmc_part(emmc_tool_gui_t *gui, char *sd_path, int active_pa
|
||||||
bool use_multipart = false;
|
bool use_multipart = false;
|
||||||
bool check_4MB_aligned = true;
|
bool check_4MB_aligned = true;
|
||||||
|
|
||||||
if (allow_multi_part)
|
if (!allow_multi_part)
|
||||||
|
goto multipart_not_allowed;
|
||||||
|
|
||||||
|
// Check to see if there is a combined file and if so then use that.
|
||||||
|
if (f_stat(outFilename, &fno))
|
||||||
{
|
{
|
||||||
// Check to see if there is a combined file and if so then use that.
|
// If not, check if there are partial files and the total size matches.
|
||||||
if (f_stat(outFilename, &fno))
|
s_printf(gui->txt_buf, "\nNo single file, checking for part files...\n");
|
||||||
|
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
|
||||||
|
manual_system_maintenance(true);
|
||||||
|
|
||||||
|
outFilename[sdPathLen++] = '.';
|
||||||
|
|
||||||
|
_update_filename(outFilename, sdPathLen, numSplitParts);
|
||||||
|
|
||||||
|
s_printf(gui->txt_buf, "#96FF00 Filepath:#\n%s\n#96FF00 Filename:# #FF8000 %s#",
|
||||||
|
gui->base_path, outFilename + strlen(gui->base_path));
|
||||||
|
lv_label_ins_text(gui->label_info, LV_LABEL_POS_LAST, gui->txt_buf);
|
||||||
|
|
||||||
|
// Stat total size of the part files.
|
||||||
|
while ((u32)((u64)totalCheckFileSize >> (u64)9) != totalSectors)
|
||||||
{
|
{
|
||||||
// If not, check if there are partial files and the total size matches.
|
|
||||||
s_printf(gui->txt_buf, "\nNo single file, checking for part files...\n");
|
|
||||||
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
|
|
||||||
manual_system_maintenance(true);
|
|
||||||
|
|
||||||
outFilename[sdPathLen++] = '.';
|
|
||||||
|
|
||||||
_update_filename(outFilename, sdPathLen, numSplitParts);
|
_update_filename(outFilename, sdPathLen, numSplitParts);
|
||||||
|
|
||||||
s_printf(gui->txt_buf, "#96FF00 Filepath:#\n%s\n#96FF00 Filename:# #FF8000 %s#",
|
s_printf(gui->txt_buf, "%s#", outFilename + strlen(gui->base_path));
|
||||||
gui->base_path, outFilename + strlen(gui->base_path));
|
lv_label_cut_text(gui->label_info,
|
||||||
|
strlen(lv_label_get_text(gui->label_info)) - strlen(outFilename + strlen(gui->base_path)) - 1,
|
||||||
|
strlen(outFilename + strlen(gui->base_path)) + 1);
|
||||||
lv_label_ins_text(gui->label_info, LV_LABEL_POS_LAST, gui->txt_buf);
|
lv_label_ins_text(gui->label_info, LV_LABEL_POS_LAST, gui->txt_buf);
|
||||||
|
manual_system_maintenance(true);
|
||||||
|
|
||||||
// Stat total size of the part files.
|
if ((u32)((u64)totalCheckFileSize >> (u64)9) > totalSectors)
|
||||||
while ((u32)((u64)totalCheckFileSize >> (u64)9) != totalSectors)
|
|
||||||
{
|
{
|
||||||
_update_filename(outFilename, sdPathLen, numSplitParts);
|
s_printf(gui->txt_buf, "#FF8000 Size of SD Card split backup exceeds#\n#FF8000 eMMC's selected part size!#\n#FFDD00 Aborting...#");
|
||||||
|
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
|
||||||
s_printf(gui->txt_buf, "%s#", outFilename + strlen(gui->base_path));
|
|
||||||
lv_label_cut_text(gui->label_info,
|
|
||||||
strlen(lv_label_get_text(gui->label_info)) - strlen(outFilename + strlen(gui->base_path)) - 1,
|
|
||||||
strlen(outFilename + strlen(gui->base_path)) + 1);
|
|
||||||
lv_label_ins_text(gui->label_info, LV_LABEL_POS_LAST, gui->txt_buf);
|
|
||||||
manual_system_maintenance(true);
|
manual_system_maintenance(true);
|
||||||
|
|
||||||
if ((u32)((u64)totalCheckFileSize >> (u64)9) > totalSectors)
|
return 0;
|
||||||
|
}
|
||||||
|
else if (f_stat(outFilename, &fno))
|
||||||
|
{
|
||||||
|
if (!gui->raw_emummc)
|
||||||
{
|
{
|
||||||
s_printf(gui->txt_buf, "#FF8000 Size of SD Card split backup exceeds#\n#FF8000 eMMC's selected part size!#\n#FFDD00 Aborting...#");
|
s_printf(gui->txt_buf, "#FFDD00 Error (%d) file not found#\n#FFDD00 %s.#\n\n", res, outFilename);
|
||||||
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
|
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
|
||||||
manual_system_maintenance(true);
|
manual_system_maintenance(true);
|
||||||
|
|
||||||
return 0;
|
// Attempt a smaller restore.
|
||||||
}
|
if (numSplitParts)
|
||||||
else if (f_stat(outFilename, &fno))
|
break;
|
||||||
{
|
|
||||||
if (!gui->raw_emummc)
|
|
||||||
{
|
|
||||||
s_printf(gui->txt_buf, "#FFDD00 Error (%d) file not found#\n#FFDD00 %s.#\n\n", res, outFilename);
|
|
||||||
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
|
|
||||||
manual_system_maintenance(true);
|
|
||||||
|
|
||||||
// Attempt a smaller restore.
|
|
||||||
if (numSplitParts)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Set new total sectors and lba end sector for percentage calculations.
|
|
||||||
totalSectors = (u32)((u64)totalCheckFileSize >> (u64)9);
|
|
||||||
lba_end = totalSectors + part->lba_start - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Restore folder is empty.
|
|
||||||
if (!numSplitParts)
|
|
||||||
{
|
|
||||||
s_printf(gui->txt_buf, "#FFDD00 Restore folder is empty.#\n\n");
|
|
||||||
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
|
|
||||||
manual_system_maintenance(true);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
totalCheckFileSize += (u64)fno.fsize;
|
// Set new total sectors and lba end sector for percentage calculations.
|
||||||
|
totalSectors = (u32)((u64)totalCheckFileSize >> (u64)9);
|
||||||
if (check_4MB_aligned && (((u64)fno.fsize) % SZ_4M))
|
lba_end = totalSectors + part->lba_start - 1;
|
||||||
{
|
|
||||||
s_printf(gui->txt_buf, "#FFDD00 The split file must be a#\n#FFDD00 multiple of 4 MiB.#\n#FFDD00 Aborting...#", res, outFilename);
|
|
||||||
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
|
|
||||||
manual_system_maintenance(true);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
check_4MB_aligned = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
numSplitParts++;
|
// Restore folder is empty.
|
||||||
}
|
if (!numSplitParts)
|
||||||
|
|
||||||
s_printf(gui->txt_buf, "%X sectors total.\n", (u32)((u64)totalCheckFileSize >> (u64)9));
|
|
||||||
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
|
|
||||||
manual_system_maintenance(true);
|
|
||||||
|
|
||||||
if ((u32)((u64)totalCheckFileSize >> (u64)9) != totalSectors)
|
|
||||||
{
|
|
||||||
lv_obj_t *warn_mbox_bg = create_mbox_text(
|
|
||||||
"#FF8000 Size of SD Card split backup does not match#\n#FF8000 eMMC's selected part size!#\n\n"
|
|
||||||
"#FFDD00 The backup might be corrupted,#\n#FFDD00 or missing files!#\n#FFDD00 Aborting is suggested!#\n\n"
|
|
||||||
"Press #FF8000 POWER# to Continue.\nPress #FF8000 VOL# to abort.", false);
|
|
||||||
manual_system_maintenance(true);
|
|
||||||
|
|
||||||
if (!(btn_wait() & BTN_POWER))
|
|
||||||
{
|
{
|
||||||
lv_obj_del(warn_mbox_bg);
|
s_printf(gui->txt_buf, "#FFDD00 Restore folder is empty.#\n\n");
|
||||||
s_printf(gui->txt_buf, "#FF0000 Size of SD Card split backup does not match#\n#FF0000 eMMC's selected part size!#\n");
|
|
||||||
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
|
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
|
||||||
manual_system_maintenance(true);
|
manual_system_maintenance(true);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
lv_obj_del(warn_mbox_bg);
|
|
||||||
|
|
||||||
// Set new total sectors and lba end sector for percentage calculations.
|
|
||||||
totalSectors = (u32)((u64)totalCheckFileSize >> (u64)9);
|
|
||||||
lba_end = totalSectors + part->lba_start - 1;
|
|
||||||
}
|
}
|
||||||
use_multipart = true;
|
else
|
||||||
_update_filename(outFilename, sdPathLen, 0);
|
{
|
||||||
|
totalCheckFileSize += (u64)fno.fsize;
|
||||||
|
|
||||||
|
if (check_4MB_aligned && (((u64)fno.fsize) % SZ_4M))
|
||||||
|
{
|
||||||
|
s_printf(gui->txt_buf, "#FFDD00 The split file must be a#\n#FFDD00 multiple of 4 MiB.#\n#FFDD00 Aborting...#", res, outFilename);
|
||||||
|
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
|
||||||
|
manual_system_maintenance(true);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
check_4MB_aligned = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
numSplitParts++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s_printf(gui->txt_buf, "%X sectors total.\n", (u32)((u64)totalCheckFileSize >> (u64)9));
|
||||||
|
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
|
||||||
|
manual_system_maintenance(true);
|
||||||
|
|
||||||
|
if ((u32)((u64)totalCheckFileSize >> (u64)9) != totalSectors)
|
||||||
|
{
|
||||||
|
lv_obj_t *warn_mbox_bg = create_mbox_text(
|
||||||
|
"#FF8000 Size of SD Card split backup does not match#\n#FF8000 eMMC's selected part size!#\n\n"
|
||||||
|
"#FFDD00 The backup might be corrupted,#\n#FFDD00 or missing files!#\n#FFDD00 Aborting is suggested!#\n\n"
|
||||||
|
"Press #FF8000 POWER# to Continue.\nPress #FF8000 VOL# to abort.", false);
|
||||||
|
manual_system_maintenance(true);
|
||||||
|
|
||||||
|
if (!(btn_wait() & BTN_POWER))
|
||||||
|
{
|
||||||
|
lv_obj_del(warn_mbox_bg);
|
||||||
|
s_printf(gui->txt_buf, "#FF0000 Size of SD Card split backup does not match#\n#FF0000 eMMC's selected part size!#\n");
|
||||||
|
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
|
||||||
|
manual_system_maintenance(true);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
lv_obj_del(warn_mbox_bg);
|
||||||
|
|
||||||
|
// Set new total sectors and lba end sector for percentage calculations.
|
||||||
|
totalSectors = (u32)((u64)totalCheckFileSize >> (u64)9);
|
||||||
|
lba_end = totalSectors + part->lba_start - 1;
|
||||||
|
}
|
||||||
|
use_multipart = true;
|
||||||
|
_update_filename(outFilename, sdPathLen, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
multipart_not_allowed:
|
||||||
res = f_open(&fp, outFilename, FA_READ);
|
res = f_open(&fp, outFilename, FA_READ);
|
||||||
if (use_multipart)
|
if (use_multipart)
|
||||||
{
|
{
|
||||||
|
|
|
@ -42,26 +42,28 @@ void load_emummc_cfg(emummc_cfg_t *emu_info)
|
||||||
|
|
||||||
// Parse emuMMC configuration.
|
// Parse emuMMC configuration.
|
||||||
LIST_INIT(ini_sections);
|
LIST_INIT(ini_sections);
|
||||||
if (ini_parse(&ini_sections, "emuMMC/emummc.ini", false))
|
if (!ini_parse(&ini_sections, "emuMMC/emummc.ini", false))
|
||||||
|
return;
|
||||||
|
|
||||||
|
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, "emummc"))
|
||||||
{
|
{
|
||||||
if (!strcmp(ini_sec->name, "emummc"))
|
LIST_FOREACH_ENTRY(ini_kv_t, kv, &ini_sec->kvs, link)
|
||||||
{
|
{
|
||||||
LIST_FOREACH_ENTRY(ini_kv_t, kv, &ini_sec->kvs, link)
|
if (!strcmp("enabled", kv->key))
|
||||||
{
|
emu_info->enabled = atoi(kv->val);
|
||||||
if (!strcmp("enabled", kv->key))
|
else if (!strcmp("sector", kv->key))
|
||||||
emu_info->enabled = atoi(kv->val);
|
emu_info->sector = strtol(kv->val, NULL, 16);
|
||||||
else if (!strcmp("sector", kv->key))
|
else if (!strcmp("id", kv->key))
|
||||||
emu_info->sector = strtol(kv->val, NULL, 16);
|
emu_info->id = strtol(kv->val, NULL, 16);
|
||||||
else if (!strcmp("id", kv->key))
|
else if (!strcmp("path", kv->key))
|
||||||
emu_info->id = strtol(kv->val, NULL, 16);
|
emu_info->path = kv->val;
|
||||||
else if (!strcmp("path", kv->key))
|
else if (!strcmp("nintendo_path", kv->key))
|
||||||
emu_info->path = kv->val;
|
emu_info->nintendo_path = kv->val;
|
||||||
else if (!strcmp("nintendo_path", kv->key))
|
|
||||||
emu_info->nintendo_path = kv->val;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -262,6 +264,7 @@ static int _dump_emummc_file_part(emmc_tool_gui_t *gui, char *sd_path, sdmmc_sto
|
||||||
|
|
||||||
retryCount = 0;
|
retryCount = 0;
|
||||||
num = MIN(totalSectors, NUM_SECTORS_PER_ITER);
|
num = MIN(totalSectors, NUM_SECTORS_PER_ITER);
|
||||||
|
|
||||||
while (!sdmmc_storage_read(storage, lba_curr, num, buf))
|
while (!sdmmc_storage_read(storage, lba_curr, num, buf))
|
||||||
{
|
{
|
||||||
s_printf(gui->txt_buf,
|
s_printf(gui->txt_buf,
|
||||||
|
@ -405,6 +408,7 @@ void dump_emummc_file(emmc_tool_gui_t *gui)
|
||||||
memset(&bootPart, 0, sizeof(bootPart));
|
memset(&bootPart, 0, sizeof(bootPart));
|
||||||
bootPart.lba_start = 0;
|
bootPart.lba_start = 0;
|
||||||
bootPart.lba_end = (BOOT_PART_SIZE / EMMC_BLOCKSIZE) - 1;
|
bootPart.lba_end = (BOOT_PART_SIZE / EMMC_BLOCKSIZE) - 1;
|
||||||
|
|
||||||
for (i = 0; i < 2; i++)
|
for (i = 0; i < 2; i++)
|
||||||
{
|
{
|
||||||
strcpy(bootPart.name, "BOOT");
|
strcpy(bootPart.name, "BOOT");
|
||||||
|
@ -448,24 +452,23 @@ void dump_emummc_file(emmc_tool_gui_t *gui)
|
||||||
rawPart.lba_start = 0;
|
rawPart.lba_start = 0;
|
||||||
rawPart.lba_end = RAW_AREA_NUM_SECTORS - 1;
|
rawPart.lba_end = RAW_AREA_NUM_SECTORS - 1;
|
||||||
strcpy(rawPart.name, "GPP");
|
strcpy(rawPart.name, "GPP");
|
||||||
{
|
|
||||||
s_printf(txt_buf, "#00DDFF %02d: %s#\n#00DDFF Range: 0x%08X - 0x%08X#\n\n",
|
|
||||||
i, rawPart.name, rawPart.lba_start, rawPart.lba_end);
|
|
||||||
lv_label_set_text(gui->label_info, txt_buf);
|
|
||||||
s_printf(txt_buf, "%02d: %s... ", i, rawPart.name);
|
|
||||||
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, txt_buf);
|
|
||||||
manual_system_maintenance(true);
|
|
||||||
|
|
||||||
res = _dump_emummc_file_part(gui, sdPath, &emmc_storage, &rawPart);
|
s_printf(txt_buf, "#00DDFF %02d: %s#\n#00DDFF Range: 0x%08X - 0x%08X#\n\n",
|
||||||
|
i, rawPart.name, rawPart.lba_start, rawPart.lba_end);
|
||||||
|
lv_label_set_text(gui->label_info, txt_buf);
|
||||||
|
s_printf(txt_buf, "%02d: %s... ", i, rawPart.name);
|
||||||
|
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, txt_buf);
|
||||||
|
manual_system_maintenance(true);
|
||||||
|
|
||||||
if (!res)
|
res = _dump_emummc_file_part(gui, sdPath, &emmc_storage, &rawPart);
|
||||||
s_printf(txt_buf, "#FFDD00 Failed!#\n");
|
|
||||||
else
|
|
||||||
s_printf(txt_buf, "Done!\n");
|
|
||||||
|
|
||||||
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, txt_buf);
|
if (!res)
|
||||||
manual_system_maintenance(true);
|
s_printf(txt_buf, "#FFDD00 Failed!#\n");
|
||||||
}
|
else
|
||||||
|
s_printf(txt_buf, "Done!\n");
|
||||||
|
|
||||||
|
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, txt_buf);
|
||||||
|
manual_system_maintenance(true);
|
||||||
|
|
||||||
out_failed:
|
out_failed:
|
||||||
timer = get_tmr_s() - timer;
|
timer = get_tmr_s() - timer;
|
||||||
|
|
|
@ -1608,149 +1608,151 @@ static lv_res_t _create_window_home_launch(lv_obj_t *btn)
|
||||||
u32 curr_btn_idx = 0; // Active buttons.
|
u32 curr_btn_idx = 0; // Active buttons.
|
||||||
LIST_INIT(ini_sections);
|
LIST_INIT(ini_sections);
|
||||||
|
|
||||||
if (sd_mount())
|
if (!sd_mount())
|
||||||
|
goto failed_sd_mount;
|
||||||
|
|
||||||
|
// Check if we use custom system icons.
|
||||||
|
bool icon_sw_custom = !f_stat("bootloader/res/icon_switch_custom.bmp", NULL);
|
||||||
|
bool icon_pl_custom = !f_stat("bootloader/res/icon_payload_custom.bmp", NULL);
|
||||||
|
|
||||||
|
// Choose what to parse.
|
||||||
|
bool ini_parse_success = false;
|
||||||
|
if (!more_cfg)
|
||||||
|
ini_parse_success = ini_parse(&ini_sections, "bootloader/hekate_ipl.ini", false);
|
||||||
|
else
|
||||||
|
ini_parse_success = ini_parse(&ini_sections, "bootloader/ini", true);
|
||||||
|
|
||||||
|
if (combined_cfg && !ini_parse_success)
|
||||||
{
|
{
|
||||||
// Check if we use custom system icons.
|
|
||||||
bool icon_sw_custom = !f_stat("bootloader/res/icon_switch_custom.bmp", NULL);
|
|
||||||
bool icon_pl_custom = !f_stat("bootloader/res/icon_payload_custom.bmp", NULL);
|
|
||||||
|
|
||||||
// Choose what to parse.
|
|
||||||
bool ini_parse_success = false;
|
|
||||||
if (!more_cfg)
|
|
||||||
ini_parse_success = ini_parse(&ini_sections, "bootloader/hekate_ipl.ini", false);
|
|
||||||
else
|
|
||||||
ini_parse_success = ini_parse(&ini_sections, "bootloader/ini", true);
|
|
||||||
|
|
||||||
if (combined_cfg && !ini_parse_success)
|
|
||||||
{
|
|
||||||
ini_parsing:
|
ini_parsing:
|
||||||
// Reinit list.
|
// Reinit list.
|
||||||
ini_sections.prev = &ini_sections;
|
ini_sections.prev = &ini_sections;
|
||||||
ini_sections.next = &ini_sections;
|
ini_sections.next = &ini_sections;
|
||||||
ini_parse_success = ini_parse(&ini_sections, "bootloader/ini", true);
|
ini_parse_success = ini_parse(&ini_sections, "bootloader/ini", true);
|
||||||
more_cfg = true;
|
more_cfg = true;
|
||||||
}
|
|
||||||
|
|
||||||
if (ini_parse_success)
|
|
||||||
{
|
|
||||||
// Iterate to all boot entries and load icons.
|
|
||||||
u32 entry_idx = 1;
|
|
||||||
|
|
||||||
LIST_FOREACH_ENTRY(ini_sec_t, ini_sec, &ini_sections, link)
|
|
||||||
{
|
|
||||||
if (!strcmp(ini_sec->name, "config") || (ini_sec->type != INI_CHOICE))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
icon_path = NULL;
|
|
||||||
bool payload = false;
|
|
||||||
bool img_colorize = false;
|
|
||||||
lv_img_dsc_t *bmp = NULL;
|
|
||||||
lv_obj_t *img = NULL;
|
|
||||||
|
|
||||||
// Check for icons.
|
|
||||||
LIST_FOREACH_ENTRY(ini_kv_t, kv, &ini_sec->kvs, link)
|
|
||||||
{
|
|
||||||
if (!strcmp("icon", kv->key))
|
|
||||||
icon_path = kv->val;
|
|
||||||
else if (!strcmp("payload", kv->key))
|
|
||||||
payload = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If icon not found, check res folder for section_name.bmp.
|
|
||||||
// If not, use defaults.
|
|
||||||
if (!icon_path)
|
|
||||||
{
|
|
||||||
s_printf(tmp_path, "bootloader/res/%s.bmp", ini_sec->name);
|
|
||||||
bmp = bmp_to_lvimg_obj(tmp_path);
|
|
||||||
if (!bmp)
|
|
||||||
{
|
|
||||||
s_printf(tmp_path, "bootloader/res/%s_hue.bmp", ini_sec->name);
|
|
||||||
bmp = bmp_to_lvimg_obj(tmp_path);
|
|
||||||
if (bmp)
|
|
||||||
img_colorize = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!bmp && payload)
|
|
||||||
{
|
|
||||||
bmp = icon_payload;
|
|
||||||
|
|
||||||
if (!icon_pl_custom)
|
|
||||||
img_colorize = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
bmp = bmp_to_lvimg_obj(icon_path);
|
|
||||||
|
|
||||||
// Check if colorization is enabled.
|
|
||||||
if (bmp && strlen(icon_path) > 8 && !memcmp(icon_path + strlen(icon_path) - 8, "_hue", 4))
|
|
||||||
img_colorize = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Enable button.
|
|
||||||
lv_obj_set_opa_scale(launch_ctxt.btn[curr_btn_idx], LV_OPA_COVER);
|
|
||||||
|
|
||||||
// Default to switch logo if no icon found at all.
|
|
||||||
if (!bmp)
|
|
||||||
{
|
|
||||||
bmp = icon_switch;
|
|
||||||
|
|
||||||
if (!icon_sw_custom)
|
|
||||||
img_colorize = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Set icon.
|
|
||||||
if (bmp)
|
|
||||||
{
|
|
||||||
img = lv_img_create(launch_ctxt.btn[curr_btn_idx], NULL);
|
|
||||||
|
|
||||||
if (img_colorize)
|
|
||||||
lv_img_set_style(img, &img_style);
|
|
||||||
|
|
||||||
lv_img_set_src(img, bmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add button mask/radius and align icon.
|
|
||||||
lv_obj_t *btn = lv_btn_create(launch_ctxt.btn[curr_btn_idx], NULL);
|
|
||||||
lv_obj_set_size(btn, 200, 200);
|
|
||||||
lv_btn_set_style(btn, LV_BTN_STYLE_REL, &btn_home_transp_rel);
|
|
||||||
lv_btn_set_style(btn, LV_BTN_STYLE_PR, &btn_home_transp_pr);
|
|
||||||
if (img)
|
|
||||||
lv_obj_align(img, NULL, LV_ALIGN_CENTER, 0, 0);
|
|
||||||
|
|
||||||
// Set autoboot index.
|
|
||||||
ext = lv_obj_get_ext_attr(btn);
|
|
||||||
ext->idx = entry_idx;
|
|
||||||
ext = lv_obj_get_ext_attr(launch_ctxt.btn[curr_btn_idx]); // Redundancy.
|
|
||||||
ext->idx = entry_idx;
|
|
||||||
|
|
||||||
// Set action.
|
|
||||||
if (!more_cfg)
|
|
||||||
lv_btn_set_action(btn, LV_BTN_ACTION_CLICK, _launch_action);
|
|
||||||
else
|
|
||||||
lv_btn_set_action(btn, LV_BTN_ACTION_CLICK, _launch_more_cfg_action);
|
|
||||||
|
|
||||||
// Set button's label text.
|
|
||||||
lv_label_set_text(launch_ctxt.label[curr_btn_idx], ini_sec->name);
|
|
||||||
lv_obj_set_opa_scale(launch_ctxt.label[curr_btn_idx], LV_OPA_COVER);
|
|
||||||
|
|
||||||
// Set rolling text if name is big.
|
|
||||||
if (strlen(ini_sec->name) > 22)
|
|
||||||
lv_label_set_long_mode(launch_ctxt.label[curr_btn_idx], LV_LABEL_LONG_ROLL);
|
|
||||||
|
|
||||||
entry_idx++;
|
|
||||||
curr_btn_idx++;
|
|
||||||
|
|
||||||
// Check if we exceed max buttons.
|
|
||||||
if (curr_btn_idx >= max_entries)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Reiterate the loop with more cfgs if combined.
|
|
||||||
if (combined_cfg && (curr_btn_idx < 8) && !more_cfg)
|
|
||||||
goto ini_parsing;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!ini_parse_success)
|
||||||
|
goto ini_parse_failed;
|
||||||
|
|
||||||
|
// Iterate to all boot entries and load icons.
|
||||||
|
u32 entry_idx = 1;
|
||||||
|
LIST_FOREACH_ENTRY(ini_sec_t, ini_sec, &ini_sections, link)
|
||||||
|
{
|
||||||
|
if (!strcmp(ini_sec->name, "config") || (ini_sec->type != INI_CHOICE))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
icon_path = NULL;
|
||||||
|
bool payload = false;
|
||||||
|
bool img_colorize = false;
|
||||||
|
lv_img_dsc_t *bmp = NULL;
|
||||||
|
lv_obj_t *img = NULL;
|
||||||
|
|
||||||
|
// Check for icons.
|
||||||
|
LIST_FOREACH_ENTRY(ini_kv_t, kv, &ini_sec->kvs, link)
|
||||||
|
{
|
||||||
|
if (!strcmp("icon", kv->key))
|
||||||
|
icon_path = kv->val;
|
||||||
|
else if (!strcmp("payload", kv->key))
|
||||||
|
payload = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If icon not found, check res folder for section_name.bmp.
|
||||||
|
// If not, use defaults.
|
||||||
|
if (!icon_path)
|
||||||
|
{
|
||||||
|
s_printf(tmp_path, "bootloader/res/%s.bmp", ini_sec->name);
|
||||||
|
bmp = bmp_to_lvimg_obj(tmp_path);
|
||||||
|
if (!bmp)
|
||||||
|
{
|
||||||
|
s_printf(tmp_path, "bootloader/res/%s_hue.bmp", ini_sec->name);
|
||||||
|
bmp = bmp_to_lvimg_obj(tmp_path);
|
||||||
|
if (bmp)
|
||||||
|
img_colorize = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!bmp && payload)
|
||||||
|
{
|
||||||
|
bmp = icon_payload;
|
||||||
|
|
||||||
|
if (!icon_pl_custom)
|
||||||
|
img_colorize = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bmp = bmp_to_lvimg_obj(icon_path);
|
||||||
|
|
||||||
|
// Check if colorization is enabled.
|
||||||
|
if (bmp && strlen(icon_path) > 8 && !memcmp(icon_path + strlen(icon_path) - 8, "_hue", 4))
|
||||||
|
img_colorize = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enable button.
|
||||||
|
lv_obj_set_opa_scale(launch_ctxt.btn[curr_btn_idx], LV_OPA_COVER);
|
||||||
|
|
||||||
|
// Default to switch logo if no icon found at all.
|
||||||
|
if (!bmp)
|
||||||
|
{
|
||||||
|
bmp = icon_switch;
|
||||||
|
|
||||||
|
if (!icon_sw_custom)
|
||||||
|
img_colorize = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Set icon.
|
||||||
|
if (bmp)
|
||||||
|
{
|
||||||
|
img = lv_img_create(launch_ctxt.btn[curr_btn_idx], NULL);
|
||||||
|
|
||||||
|
if (img_colorize)
|
||||||
|
lv_img_set_style(img, &img_style);
|
||||||
|
|
||||||
|
lv_img_set_src(img, bmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add button mask/radius and align icon.
|
||||||
|
lv_obj_t *btn = lv_btn_create(launch_ctxt.btn[curr_btn_idx], NULL);
|
||||||
|
lv_obj_set_size(btn, 200, 200);
|
||||||
|
lv_btn_set_style(btn, LV_BTN_STYLE_REL, &btn_home_transp_rel);
|
||||||
|
lv_btn_set_style(btn, LV_BTN_STYLE_PR, &btn_home_transp_pr);
|
||||||
|
if (img)
|
||||||
|
lv_obj_align(img, NULL, LV_ALIGN_CENTER, 0, 0);
|
||||||
|
|
||||||
|
// Set autoboot index.
|
||||||
|
ext = lv_obj_get_ext_attr(btn);
|
||||||
|
ext->idx = entry_idx;
|
||||||
|
ext = lv_obj_get_ext_attr(launch_ctxt.btn[curr_btn_idx]); // Redundancy.
|
||||||
|
ext->idx = entry_idx;
|
||||||
|
|
||||||
|
// Set action.
|
||||||
|
if (!more_cfg)
|
||||||
|
lv_btn_set_action(btn, LV_BTN_ACTION_CLICK, _launch_action);
|
||||||
|
else
|
||||||
|
lv_btn_set_action(btn, LV_BTN_ACTION_CLICK, _launch_more_cfg_action);
|
||||||
|
|
||||||
|
// Set button's label text.
|
||||||
|
lv_label_set_text(launch_ctxt.label[curr_btn_idx], ini_sec->name);
|
||||||
|
lv_obj_set_opa_scale(launch_ctxt.label[curr_btn_idx], LV_OPA_COVER);
|
||||||
|
|
||||||
|
// Set rolling text if name is big.
|
||||||
|
if (strlen(ini_sec->name) > 22)
|
||||||
|
lv_label_set_long_mode(launch_ctxt.label[curr_btn_idx], LV_LABEL_LONG_ROLL);
|
||||||
|
|
||||||
|
entry_idx++;
|
||||||
|
curr_btn_idx++;
|
||||||
|
|
||||||
|
// Check if we exceed max buttons.
|
||||||
|
if (curr_btn_idx >= max_entries)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ini_parse_failed:
|
||||||
|
// Reiterate the loop with more cfgs if combined.
|
||||||
|
if (combined_cfg && (curr_btn_idx < 8) && !more_cfg)
|
||||||
|
goto ini_parsing;
|
||||||
|
|
||||||
|
failed_sd_mount:
|
||||||
if (curr_btn_idx < 1)
|
if (curr_btn_idx < 1)
|
||||||
no_boot_entries = true;
|
no_boot_entries = true;
|
||||||
|
|
||||||
|
|
|
@ -782,26 +782,27 @@ static lv_res_t _create_mbox_emummc_migrate(lv_obj_t *btn)
|
||||||
for (int i = 1; i < 4; i++)
|
for (int i = 1; i < 4; i++)
|
||||||
{
|
{
|
||||||
mbr_ctx.sector_start = mbr->partitions[i].start_sct;
|
mbr_ctx.sector_start = mbr->partitions[i].start_sct;
|
||||||
if (mbr_ctx.sector_start)
|
|
||||||
|
if (!mbr_ctx.sector_start)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
sdmmc_storage_read(&sd_storage, mbr_ctx.sector_start + 0xC001, 1, efi_part);
|
||||||
|
if (!memcmp(efi_part, "EFI PART", 8))
|
||||||
{
|
{
|
||||||
sdmmc_storage_read(&sd_storage, mbr_ctx.sector_start + 0xC001, 1, efi_part);
|
mbr_ctx.sector_start += 0x8000;
|
||||||
|
emummc = true;
|
||||||
|
mbr_ctx.part_idx = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sdmmc_storage_read(&sd_storage, mbr_ctx.sector_start + 0x4001, 1, efi_part);
|
||||||
if (!memcmp(efi_part, "EFI PART", 8))
|
if (!memcmp(efi_part, "EFI PART", 8))
|
||||||
{
|
{
|
||||||
mbr_ctx.sector_start += 0x8000;
|
|
||||||
emummc = true;
|
emummc = true;
|
||||||
mbr_ctx.part_idx = i;
|
mbr_ctx.part_idx = i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
sdmmc_storage_read(&sd_storage, mbr_ctx.sector_start + 0x4001, 1, efi_part);
|
|
||||||
if (!memcmp(efi_part, "EFI PART", 8))
|
|
||||||
{
|
|
||||||
emummc = true;
|
|
||||||
mbr_ctx.part_idx = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1329,194 +1329,197 @@ static lv_res_t _create_mbox_benchmark(bool sd_bench)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (res)
|
if (res)
|
||||||
lv_mbox_set_text(mbox, "#FFDD00 Failed to init Storage!#");
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
int error = 0;
|
lv_mbox_set_text(mbox, "#FFDD00 Failed to init Storage!#");
|
||||||
u32 iters = 3;
|
goto out;
|
||||||
u32 offset_chunk_start = ALIGN_DOWN(storage->sec_cnt / 3, 0x8000); // Align to 16MB.
|
}
|
||||||
if (storage->sec_cnt < 0xC00000)
|
|
||||||
iters -= 2; // 4GB card.
|
|
||||||
|
|
||||||
for (u32 iter_curr = 0; iter_curr < iters; iter_curr++)
|
int error = 0;
|
||||||
|
u32 iters = 3;
|
||||||
|
u32 offset_chunk_start = ALIGN_DOWN(storage->sec_cnt / 3, 0x8000); // Align to 16MB.
|
||||||
|
if (storage->sec_cnt < 0xC00000)
|
||||||
|
iters -= 2; // 4GB card.
|
||||||
|
|
||||||
|
for (u32 iter_curr = 0; iter_curr < iters; iter_curr++)
|
||||||
|
{
|
||||||
|
u32 pct = 0;
|
||||||
|
u32 prevPct = 200;
|
||||||
|
u32 timer = 0;
|
||||||
|
u32 lba_curr = 0;
|
||||||
|
u32 sector = offset_chunk_start * iter_curr;
|
||||||
|
u32 sector_num = 0x8000; // 16MB chunks.
|
||||||
|
u32 data_remaining = 0x200000; // 1GB.
|
||||||
|
|
||||||
|
s_printf(txt_buf + strlen(txt_buf), "#C7EA46 %d/3# - Sector Offset #C7EA46 %08X#:\n", iter_curr + 1, sector);
|
||||||
|
|
||||||
|
while (data_remaining)
|
||||||
{
|
{
|
||||||
u32 pct = 0;
|
u32 time_taken = get_tmr_us();
|
||||||
u32 prevPct = 200;
|
error = !sdmmc_storage_read(storage, sector + lba_curr, sector_num, (u8 *)MIXD_BUF_ALIGNED);
|
||||||
u32 timer = 0;
|
time_taken = get_tmr_us() - time_taken;
|
||||||
u32 lba_curr = 0;
|
timer += time_taken;
|
||||||
u32 sector = offset_chunk_start * iter_curr;
|
|
||||||
u32 sector_num = 0x8000; // 16MB chunks.
|
|
||||||
u32 data_remaining = 0x200000; // 1GB.
|
|
||||||
|
|
||||||
s_printf(txt_buf + strlen(txt_buf), "#C7EA46 %d/3# - Sector Offset #C7EA46 %08X#:\n", iter_curr + 1, sector);
|
manual_system_maintenance(false);
|
||||||
|
data_remaining -= sector_num;
|
||||||
|
lba_curr += sector_num;
|
||||||
|
|
||||||
while (data_remaining)
|
pct = (lba_curr * 100) / 0x200000;
|
||||||
|
if (pct != prevPct)
|
||||||
{
|
{
|
||||||
u32 time_taken = get_tmr_us();
|
lv_bar_set_value(bar, pct);
|
||||||
error = !sdmmc_storage_read(storage, sector + lba_curr, sector_num, (u8 *)MIXD_BUF_ALIGNED);
|
manual_system_maintenance(true);
|
||||||
time_taken = get_tmr_us() - time_taken;
|
|
||||||
timer += time_taken;
|
|
||||||
|
|
||||||
manual_system_maintenance(false);
|
prevPct = pct;
|
||||||
data_remaining -= sector_num;
|
|
||||||
lba_curr += sector_num;
|
|
||||||
|
|
||||||
pct = (lba_curr * 100) / 0x200000;
|
if (btn_read_vol() == (BTN_VOL_UP | BTN_VOL_DOWN))
|
||||||
if (pct != prevPct)
|
error = -1;
|
||||||
{
|
|
||||||
lv_bar_set_value(bar, pct);
|
|
||||||
manual_system_maintenance(true);
|
|
||||||
|
|
||||||
prevPct = pct;
|
|
||||||
|
|
||||||
if (btn_read_vol() == (BTN_VOL_UP | BTN_VOL_DOWN))
|
|
||||||
error = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (error)
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
lv_bar_set_value(bar, 100);
|
|
||||||
|
|
||||||
u32 rate_1k = ((u64)1024 * 1000 * 1000 * 1000) / timer;
|
|
||||||
s_printf(txt_buf + strlen(txt_buf),
|
|
||||||
" Sequential 16MiB - Rate: #C7EA46 %3d.%02d MiB/s#\n",
|
|
||||||
rate_1k / 1000, (rate_1k % 1000) / 10);
|
|
||||||
lv_label_set_text(lbl_status, txt_buf);
|
|
||||||
lv_obj_align(lbl_status, NULL, LV_ALIGN_CENTER, 0, 0);
|
|
||||||
lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0);
|
|
||||||
manual_system_maintenance(true);
|
|
||||||
|
|
||||||
pct = 0;
|
|
||||||
prevPct = 200;
|
|
||||||
timer = 0;
|
|
||||||
lba_curr = 0;
|
|
||||||
sector_num = 8; // 4KB chunks.
|
|
||||||
data_remaining = 0x100000; // 512MB.
|
|
||||||
|
|
||||||
while (data_remaining)
|
|
||||||
{
|
|
||||||
u32 time_taken = get_tmr_us();
|
|
||||||
error = !sdmmc_storage_read(storage, sector + lba_curr, sector_num, (u8 *)MIXD_BUF_ALIGNED);
|
|
||||||
time_taken = get_tmr_us() - time_taken;
|
|
||||||
timer += time_taken;
|
|
||||||
|
|
||||||
manual_system_maintenance(false);
|
|
||||||
data_remaining -= sector_num;
|
|
||||||
lba_curr += sector_num;
|
|
||||||
|
|
||||||
pct = (lba_curr * 100) / 0x100000;
|
|
||||||
if (pct != prevPct)
|
|
||||||
{
|
|
||||||
lv_bar_set_value(bar, pct);
|
|
||||||
manual_system_maintenance(true);
|
|
||||||
|
|
||||||
prevPct = pct;
|
|
||||||
|
|
||||||
if (btn_read_vol() == (BTN_VOL_UP | BTN_VOL_DOWN))
|
|
||||||
error = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (error)
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
lv_bar_set_value(bar, 100);
|
|
||||||
|
|
||||||
rate_1k = ((u64)512 * 1000 * 1000 * 1000) / timer;
|
|
||||||
u32 iops_1k = ((u64)512 * 1024 * 1000 * 1000 * 1000) / (4096 / 1024) / timer / 1000;
|
|
||||||
s_printf(txt_buf + strlen(txt_buf),
|
|
||||||
" Sequential 4KiB - Rate: #C7EA46 %3d.%02d MiB/s#, IOPS: #C7EA46 %4d#\n",
|
|
||||||
rate_1k / 1000, (rate_1k % 1000) / 10, iops_1k);
|
|
||||||
lv_label_set_text(lbl_status, txt_buf);
|
|
||||||
lv_obj_align(lbl_status, NULL, LV_ALIGN_CENTER, 0, 0);
|
|
||||||
lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0);
|
|
||||||
manual_system_maintenance(true);
|
|
||||||
|
|
||||||
u32 lba_idx = 0;
|
|
||||||
u32 *random_offsets = malloc(0x20000 * sizeof(u32));
|
|
||||||
u32 random_numbers[4];
|
|
||||||
for (u32 i = 0; i < 0x20000; i += 4)
|
|
||||||
{
|
|
||||||
// Generate new random numbers.
|
|
||||||
while (!se_gen_prng128(random_numbers))
|
|
||||||
;
|
|
||||||
// Clamp offsets to 512MBrange.
|
|
||||||
random_offsets[i + 0] = random_numbers[0] % 0x100000;
|
|
||||||
random_offsets[i + 1] = random_numbers[1] % 0x100000;
|
|
||||||
random_offsets[i + 2] = random_numbers[2] % 0x100000;
|
|
||||||
random_offsets[i + 3] = random_numbers[3] % 0x100000;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pct = 0;
|
if (error)
|
||||||
prevPct = 200;
|
goto error;
|
||||||
timer = 0;
|
|
||||||
data_remaining = 0x100000; // 512MB.
|
|
||||||
|
|
||||||
while (data_remaining)
|
|
||||||
{
|
|
||||||
u32 time_taken = get_tmr_us();
|
|
||||||
error = !sdmmc_storage_read(storage, sector + random_offsets[lba_idx], sector_num, (u8 *)MIXD_BUF_ALIGNED);
|
|
||||||
time_taken = get_tmr_us() - time_taken;
|
|
||||||
timer += time_taken;
|
|
||||||
|
|
||||||
manual_system_maintenance(false);
|
|
||||||
data_remaining -= sector_num;
|
|
||||||
lba_idx++;
|
|
||||||
|
|
||||||
pct = (lba_idx * 100) / 0x20000;
|
|
||||||
if (pct != prevPct)
|
|
||||||
{
|
|
||||||
lv_bar_set_value(bar, pct);
|
|
||||||
manual_system_maintenance(true);
|
|
||||||
|
|
||||||
prevPct = pct;
|
|
||||||
|
|
||||||
if (btn_read_vol() == (BTN_VOL_UP | BTN_VOL_DOWN))
|
|
||||||
error = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (error)
|
|
||||||
{
|
|
||||||
free(random_offsets);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
lv_bar_set_value(bar, 100);
|
|
||||||
|
|
||||||
// Calculate rate and IOPS for 512MB transfer.
|
|
||||||
rate_1k = ((u64)512 * 1000 * 1000 * 1000) / timer;
|
|
||||||
iops_1k = ((u64)512 * 1024 * 1000 * 1000 * 1000) / (4096 / 1024) / timer / 1000;
|
|
||||||
s_printf(txt_buf + strlen(txt_buf),
|
|
||||||
" Random 4KiB - Rate: #C7EA46 %3d.%02d MiB/s#, IOPS: #C7EA46 %4d#\n",
|
|
||||||
rate_1k / 1000, (rate_1k % 1000) / 10, iops_1k);
|
|
||||||
if (iter_curr == iters - 1)
|
|
||||||
txt_buf[strlen(txt_buf) - 1] = 0; // Cut off last line change.
|
|
||||||
lv_label_set_text(lbl_status, txt_buf);
|
|
||||||
lv_obj_align(lbl_status, NULL, LV_ALIGN_CENTER, 0, 0);
|
|
||||||
lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0);
|
|
||||||
manual_system_maintenance(true);
|
|
||||||
free(random_offsets);
|
|
||||||
}
|
}
|
||||||
|
lv_bar_set_value(bar, 100);
|
||||||
|
|
||||||
|
u32 rate_1k = ((u64)1024 * 1000 * 1000 * 1000) / timer;
|
||||||
|
s_printf(txt_buf + strlen(txt_buf),
|
||||||
|
" Sequential 16MiB - Rate: #C7EA46 %3d.%02d MiB/s#\n",
|
||||||
|
rate_1k / 1000, (rate_1k % 1000) / 10);
|
||||||
|
lv_label_set_text(lbl_status, txt_buf);
|
||||||
|
lv_obj_align(lbl_status, NULL, LV_ALIGN_CENTER, 0, 0);
|
||||||
|
lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0);
|
||||||
|
manual_system_maintenance(true);
|
||||||
|
|
||||||
|
pct = 0;
|
||||||
|
prevPct = 200;
|
||||||
|
timer = 0;
|
||||||
|
lba_curr = 0;
|
||||||
|
sector_num = 8; // 4KB chunks.
|
||||||
|
data_remaining = 0x100000; // 512MB.
|
||||||
|
|
||||||
|
while (data_remaining)
|
||||||
|
{
|
||||||
|
u32 time_taken = get_tmr_us();
|
||||||
|
error = !sdmmc_storage_read(storage, sector + lba_curr, sector_num, (u8 *)MIXD_BUF_ALIGNED);
|
||||||
|
time_taken = get_tmr_us() - time_taken;
|
||||||
|
timer += time_taken;
|
||||||
|
|
||||||
|
manual_system_maintenance(false);
|
||||||
|
data_remaining -= sector_num;
|
||||||
|
lba_curr += sector_num;
|
||||||
|
|
||||||
|
pct = (lba_curr * 100) / 0x100000;
|
||||||
|
if (pct != prevPct)
|
||||||
|
{
|
||||||
|
lv_bar_set_value(bar, pct);
|
||||||
|
manual_system_maintenance(true);
|
||||||
|
|
||||||
|
prevPct = pct;
|
||||||
|
|
||||||
|
if (btn_read_vol() == (BTN_VOL_UP | BTN_VOL_DOWN))
|
||||||
|
error = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error)
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
lv_bar_set_value(bar, 100);
|
||||||
|
|
||||||
|
rate_1k = ((u64)512 * 1000 * 1000 * 1000) / timer;
|
||||||
|
u32 iops_1k = ((u64)512 * 1024 * 1000 * 1000 * 1000) / (4096 / 1024) / timer / 1000;
|
||||||
|
s_printf(txt_buf + strlen(txt_buf),
|
||||||
|
" Sequential 4KiB - Rate: #C7EA46 %3d.%02d MiB/s#, IOPS: #C7EA46 %4d#\n",
|
||||||
|
rate_1k / 1000, (rate_1k % 1000) / 10, iops_1k);
|
||||||
|
lv_label_set_text(lbl_status, txt_buf);
|
||||||
|
lv_obj_align(lbl_status, NULL, LV_ALIGN_CENTER, 0, 0);
|
||||||
|
lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0);
|
||||||
|
manual_system_maintenance(true);
|
||||||
|
|
||||||
|
u32 lba_idx = 0;
|
||||||
|
u32 *random_offsets = malloc(0x20000 * sizeof(u32));
|
||||||
|
u32 random_numbers[4];
|
||||||
|
for (u32 i = 0; i < 0x20000; i += 4)
|
||||||
|
{
|
||||||
|
// Generate new random numbers.
|
||||||
|
while (!se_gen_prng128(random_numbers))
|
||||||
|
;
|
||||||
|
// Clamp offsets to 512MBrange.
|
||||||
|
random_offsets[i + 0] = random_numbers[0] % 0x100000;
|
||||||
|
random_offsets[i + 1] = random_numbers[1] % 0x100000;
|
||||||
|
random_offsets[i + 2] = random_numbers[2] % 0x100000;
|
||||||
|
random_offsets[i + 3] = random_numbers[3] % 0x100000;
|
||||||
|
}
|
||||||
|
|
||||||
|
pct = 0;
|
||||||
|
prevPct = 200;
|
||||||
|
timer = 0;
|
||||||
|
data_remaining = 0x100000; // 512MB.
|
||||||
|
|
||||||
|
while (data_remaining)
|
||||||
|
{
|
||||||
|
u32 time_taken = get_tmr_us();
|
||||||
|
error = !sdmmc_storage_read(storage, sector + random_offsets[lba_idx], sector_num, (u8 *)MIXD_BUF_ALIGNED);
|
||||||
|
time_taken = get_tmr_us() - time_taken;
|
||||||
|
timer += time_taken;
|
||||||
|
|
||||||
|
manual_system_maintenance(false);
|
||||||
|
data_remaining -= sector_num;
|
||||||
|
lba_idx++;
|
||||||
|
|
||||||
|
pct = (lba_idx * 100) / 0x20000;
|
||||||
|
if (pct != prevPct)
|
||||||
|
{
|
||||||
|
lv_bar_set_value(bar, pct);
|
||||||
|
manual_system_maintenance(true);
|
||||||
|
|
||||||
|
prevPct = pct;
|
||||||
|
|
||||||
|
if (btn_read_vol() == (BTN_VOL_UP | BTN_VOL_DOWN))
|
||||||
|
error = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error)
|
||||||
|
{
|
||||||
|
free(random_offsets);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lv_bar_set_value(bar, 100);
|
||||||
|
|
||||||
|
// Calculate rate and IOPS for 512MB transfer.
|
||||||
|
rate_1k = ((u64)512 * 1000 * 1000 * 1000) / timer;
|
||||||
|
iops_1k = ((u64)512 * 1024 * 1000 * 1000 * 1000) / (4096 / 1024) / timer / 1000;
|
||||||
|
s_printf(txt_buf + strlen(txt_buf),
|
||||||
|
" Random 4KiB - Rate: #C7EA46 %3d.%02d MiB/s#, IOPS: #C7EA46 %4d#\n",
|
||||||
|
rate_1k / 1000, (rate_1k % 1000) / 10, iops_1k);
|
||||||
|
if (iter_curr == iters - 1)
|
||||||
|
txt_buf[strlen(txt_buf) - 1] = 0; // Cut off last line change.
|
||||||
|
lv_label_set_text(lbl_status, txt_buf);
|
||||||
|
lv_obj_align(lbl_status, NULL, LV_ALIGN_CENTER, 0, 0);
|
||||||
|
lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0);
|
||||||
|
manual_system_maintenance(true);
|
||||||
|
free(random_offsets);
|
||||||
|
}
|
||||||
|
|
||||||
error:
|
error:
|
||||||
if (error)
|
if (error)
|
||||||
{
|
{
|
||||||
if (error == -1)
|
if (error == -1)
|
||||||
s_printf(txt_buf + strlen(txt_buf), "\n#FFDD00 Aborted!#");
|
s_printf(txt_buf + strlen(txt_buf), "\n#FFDD00 Aborted!#");
|
||||||
else
|
|
||||||
s_printf(txt_buf + strlen(txt_buf), "\n#FFDD00 IO Error occurred!#");
|
|
||||||
|
|
||||||
lv_label_set_text(lbl_status, txt_buf);
|
|
||||||
lv_obj_align(lbl_status, NULL, LV_ALIGN_CENTER, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
lv_obj_del(bar);
|
|
||||||
|
|
||||||
if (sd_bench)
|
|
||||||
sd_unmount();
|
|
||||||
else
|
else
|
||||||
sdmmc_storage_end(&emmc_storage);
|
s_printf(txt_buf + strlen(txt_buf), "\n#FFDD00 IO Error occurred!#");
|
||||||
|
|
||||||
|
lv_label_set_text(lbl_status, txt_buf);
|
||||||
|
lv_obj_align(lbl_status, NULL, LV_ALIGN_CENTER, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lv_obj_del(bar);
|
||||||
|
|
||||||
|
if (sd_bench)
|
||||||
|
sd_unmount();
|
||||||
|
else
|
||||||
|
sdmmc_storage_end(&emmc_storage);
|
||||||
|
|
||||||
|
out:
|
||||||
free(txt_buf);
|
free(txt_buf);
|
||||||
|
|
||||||
lv_mbox_add_btns(mbox, mbox_btn_map, mbox_action); // Important. After set_text.
|
lv_mbox_add_btns(mbox, mbox_btn_map, mbox_action); // Important. After set_text.
|
||||||
|
@ -1559,233 +1562,234 @@ static lv_res_t _create_window_emmc_info_status(lv_obj_t *btn)
|
||||||
{
|
{
|
||||||
lv_label_set_text(lb_desc, "#FFDD00 Failed to init eMMC!#");
|
lv_label_set_text(lb_desc, "#FFDD00 Failed to init eMMC!#");
|
||||||
lv_obj_set_width(lb_desc, lv_obj_get_width(desc));
|
lv_obj_set_width(lb_desc, lv_obj_get_width(desc));
|
||||||
|
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
u32 speed = 0;
|
||||||
|
char *rsvd_blocks;
|
||||||
|
char life_a_txt[8];
|
||||||
|
char life_b_txt[8];
|
||||||
|
u32 cache = emmc_storage.ext_csd.cache_size;
|
||||||
|
u32 life_a = emmc_storage.ext_csd.dev_life_est_a;
|
||||||
|
u32 life_b = emmc_storage.ext_csd.dev_life_est_b;
|
||||||
|
u16 card_type = emmc_storage.ext_csd.card_type;
|
||||||
|
char card_type_support[96];
|
||||||
|
card_type_support[0] = 0;
|
||||||
|
|
||||||
|
// Identify manufacturer. Only official eMMCs.
|
||||||
|
switch (emmc_storage.cid.manfid)
|
||||||
{
|
{
|
||||||
u32 speed = 0;
|
case 0x11:
|
||||||
char *rsvd_blocks;
|
strcat(txt_buf, "Toshiba ");
|
||||||
char life_a_txt[8];
|
break;
|
||||||
char life_b_txt[8];
|
case 0x15:
|
||||||
u32 cache = emmc_storage.ext_csd.cache_size;
|
strcat(txt_buf, "Samsung ");
|
||||||
u32 life_a = emmc_storage.ext_csd.dev_life_est_a;
|
break;
|
||||||
u32 life_b = emmc_storage.ext_csd.dev_life_est_b;
|
case 0x45: // Unofficial.
|
||||||
u16 card_type = emmc_storage.ext_csd.card_type;
|
strcat(txt_buf, "SanDisk ");
|
||||||
char card_type_support[96];
|
lv_win_add_btn(win, NULL, SYMBOL_FILE_ALT" Device Report", _create_mbox_emmc_sandisk_report);
|
||||||
card_type_support[0] = 0;
|
break;
|
||||||
|
case 0x90:
|
||||||
// Identify manufacturer. Only official eMMCs.
|
strcat(txt_buf, "SK Hynix ");
|
||||||
switch (emmc_storage.cid.manfid)
|
break;
|
||||||
{
|
|
||||||
case 0x11:
|
|
||||||
strcat(txt_buf, "Toshiba ");
|
|
||||||
break;
|
|
||||||
case 0x15:
|
|
||||||
strcat(txt_buf, "Samsung ");
|
|
||||||
break;
|
|
||||||
case 0x45: // Unofficial.
|
|
||||||
strcat(txt_buf, "SanDisk ");
|
|
||||||
lv_win_add_btn(win, NULL, SYMBOL_FILE_ALT" Device Report", _create_mbox_emmc_sandisk_report);
|
|
||||||
break;
|
|
||||||
case 0x90:
|
|
||||||
strcat(txt_buf, "SK Hynix ");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
s_printf(txt_buf + strlen(txt_buf), "(%02X)\n%c%c%c%c%c%c\n%d.%d\n%04X\n%02d/%04d\n\n",
|
|
||||||
emmc_storage.cid.manfid,
|
|
||||||
emmc_storage.cid.prod_name[0], emmc_storage.cid.prod_name[1], emmc_storage.cid.prod_name[2],
|
|
||||||
emmc_storage.cid.prod_name[3], emmc_storage.cid.prod_name[4], emmc_storage.cid.prod_name[5],
|
|
||||||
emmc_storage.cid.prv & 0xF, emmc_storage.cid.prv >> 4,
|
|
||||||
emmc_storage.cid.serial, emmc_storage.cid.month, emmc_storage.cid.year);
|
|
||||||
|
|
||||||
if (card_type & EXT_CSD_CARD_TYPE_HS_26)
|
|
||||||
{
|
|
||||||
strcat(card_type_support, "HS26");
|
|
||||||
speed = (26 << 16) | 26;
|
|
||||||
}
|
|
||||||
if (card_type & EXT_CSD_CARD_TYPE_HS_52)
|
|
||||||
{
|
|
||||||
strcat(card_type_support, ", HS52");
|
|
||||||
speed = (52 << 16) | 52;
|
|
||||||
}
|
|
||||||
if (card_type & EXT_CSD_CARD_TYPE_DDR_1_8V)
|
|
||||||
{
|
|
||||||
strcat(card_type_support, ", DDR52 1.8V");
|
|
||||||
speed = (52 << 16) | 104;
|
|
||||||
}
|
|
||||||
if (card_type & EXT_CSD_CARD_TYPE_HS200_1_8V)
|
|
||||||
{
|
|
||||||
strcat(card_type_support, ", HS200 1.8V");
|
|
||||||
speed = (200 << 16) | 200;
|
|
||||||
}
|
|
||||||
if (card_type & EXT_CSD_CARD_TYPE_HS400_1_8V)
|
|
||||||
{
|
|
||||||
strcat(card_type_support, ", HS400 1.8V");
|
|
||||||
speed = (200 << 16) | 400;
|
|
||||||
}
|
|
||||||
|
|
||||||
strcpy(life_a_txt, "-");
|
|
||||||
strcpy(life_b_txt, "-");
|
|
||||||
|
|
||||||
// Normalize cells life.
|
|
||||||
if (life_a) // SK Hynix is 0 (undefined).
|
|
||||||
{
|
|
||||||
life_a--;
|
|
||||||
life_a = (10 - life_a) * 10;
|
|
||||||
s_printf(life_a_txt, "%d%%", life_a);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (life_b) // Toshiba is 0 (undefined).
|
|
||||||
{
|
|
||||||
life_b--;
|
|
||||||
life_b = (10 - life_b) * 10;
|
|
||||||
s_printf(life_b_txt, "%d%%", life_b);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (emmc_storage.ext_csd.pre_eol_info)
|
|
||||||
{
|
|
||||||
case 1:
|
|
||||||
rsvd_blocks = "Normal (< 80%)";
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
rsvd_blocks = "Warning (> 80%)";
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
rsvd_blocks = "Critical (> 90%)";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
rsvd_blocks = "#FF8000 Unknown#";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
s_printf(txt_buf + strlen(txt_buf),
|
|
||||||
"#00DDFF V1.%d (rev 1.%d)#\n%02X\n%d MB/s (%d MHz)\n%d MB/s\n%s\n%d %s\n%d MiB\nA: %s, B: %s\n%s",
|
|
||||||
emmc_storage.ext_csd.ext_struct, emmc_storage.ext_csd.rev,
|
|
||||||
emmc_storage.csd.cmdclass, speed & 0xFFFF, (speed >> 16) & 0xFFFF,
|
|
||||||
emmc_storage.csd.busspeed, card_type_support,
|
|
||||||
!(cache % 1024) ? (cache / 1024) : cache, !(cache % 1024) ? "MiB" : "KiB",
|
|
||||||
emmc_storage.ext_csd.max_enh_mult * 512 / 1024,
|
|
||||||
life_a_txt, life_b_txt, rsvd_blocks);
|
|
||||||
|
|
||||||
lv_label_set_static_text(lb_desc,
|
|
||||||
"#00DDFF CID:#\n"
|
|
||||||
"Vendor ID:\n"
|
|
||||||
"Model:\n"
|
|
||||||
"Prod Rev:\n"
|
|
||||||
"S/N:\n"
|
|
||||||
"Month/Year:\n\n"
|
|
||||||
"#00DDFF Ext CSD:#\n"
|
|
||||||
"Cmd Classes:\n"
|
|
||||||
"Max Rate:\n"
|
|
||||||
"Current Rate:\n"
|
|
||||||
"Type Support:\n\n"
|
|
||||||
"Write Cache:\n"
|
|
||||||
"Enhanced Area:\n"
|
|
||||||
"Estimated Life:\n"
|
|
||||||
"Reserved Used:"
|
|
||||||
);
|
|
||||||
lv_obj_set_width(lb_desc, lv_obj_get_width(desc));
|
|
||||||
|
|
||||||
lv_obj_t *val = lv_cont_create(win, NULL);
|
|
||||||
lv_obj_set_size(val, LV_HOR_RES / 11 * 3, LV_VER_RES - (LV_DPI * 11 / 7) - 5);
|
|
||||||
|
|
||||||
lv_obj_t * lb_val = lv_label_create(val, lb_desc);
|
|
||||||
|
|
||||||
lv_label_set_text(lb_val, txt_buf);
|
|
||||||
|
|
||||||
lv_obj_set_width(lb_val, lv_obj_get_width(val));
|
|
||||||
lv_obj_align(val, desc, LV_ALIGN_OUT_RIGHT_MID, 0, 0);
|
|
||||||
|
|
||||||
lv_obj_t *desc2 = lv_cont_create(win, NULL);
|
|
||||||
lv_obj_set_size(desc2, LV_HOR_RES / 2 / 4 * 4, LV_VER_RES - (LV_DPI * 11 / 7) - 5);
|
|
||||||
|
|
||||||
lv_obj_t * lb_desc2 = lv_label_create(desc2, lb_desc);
|
|
||||||
lv_label_set_style(lb_desc2, &monospace_text);
|
|
||||||
|
|
||||||
u32 boot_size = emmc_storage.ext_csd.boot_mult << 17;
|
|
||||||
u32 rpmb_size = emmc_storage.ext_csd.rpmb_mult << 17;
|
|
||||||
strcpy(txt_buf, "#00DDFF eMMC Physical Partitions:#\n");
|
|
||||||
s_printf(txt_buf + strlen(txt_buf), "1: #96FF00 BOOT0# Size: %6d KiB (Sect: 0x%08X)\n", boot_size / 1024, boot_size / 512);
|
|
||||||
s_printf(txt_buf + strlen(txt_buf), "2: #96FF00 BOOT1# Size: %6d KiB (Sect: 0x%08X)\n", boot_size / 1024, boot_size / 512);
|
|
||||||
s_printf(txt_buf + strlen(txt_buf), "3: #96FF00 RPMB# Size: %6d KiB (Sect: 0x%08X)\n", rpmb_size / 1024, rpmb_size / 512);
|
|
||||||
s_printf(txt_buf + strlen(txt_buf), "0: #96FF00 GPP# Size: %6d MiB (Sect: 0x%08X)\n", emmc_storage.sec_cnt >> SECTORS_TO_MIB_COEFF, emmc_storage.sec_cnt);
|
|
||||||
strcat(txt_buf, "\n#00DDFF GPP (eMMC USER) Partition Table:#\n");
|
|
||||||
|
|
||||||
sdmmc_storage_set_mmc_partition(&emmc_storage, EMMC_GPP);
|
|
||||||
LIST_INIT(gpt);
|
|
||||||
emmc_gpt_parse(&gpt);
|
|
||||||
|
|
||||||
u32 idx = 0;
|
|
||||||
LIST_FOREACH_ENTRY(emmc_part_t, part, &gpt, link)
|
|
||||||
{
|
|
||||||
if (idx > 10)
|
|
||||||
{
|
|
||||||
strcat(txt_buf, "#FFDD00 Table does not fit on screen!#");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (part->index < 2)
|
|
||||||
{
|
|
||||||
s_printf(txt_buf + strlen(txt_buf), "%02d: #96FF00 %s#%s Size: %d MiB (Sect: 0x%X), Start: %06X\n",
|
|
||||||
part->index, part->name, !part->name[8] ? " " : "",
|
|
||||||
(part->lba_end - part->lba_start + 1) >> SECTORS_TO_MIB_COEFF,
|
|
||||||
part->lba_end - part->lba_start + 1, part->lba_start);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
s_printf(txt_buf + strlen(txt_buf), "%02d: #96FF00 %s#\n Size: %7d MiB (Sect: 0x%07X), Start: %07X\n",
|
|
||||||
part->index, part->name, (part->lba_end - part->lba_start + 1) >> SECTORS_TO_MIB_COEFF,
|
|
||||||
part->lba_end - part->lba_start + 1, part->lba_start);
|
|
||||||
}
|
|
||||||
|
|
||||||
idx++;
|
|
||||||
}
|
|
||||||
if (!idx)
|
|
||||||
strcat(txt_buf, "#FFDD00 Partition table is empty!#");
|
|
||||||
|
|
||||||
emmc_gpt_free(&gpt);
|
|
||||||
|
|
||||||
lv_label_set_text(lb_desc2, txt_buf);
|
|
||||||
lv_obj_set_width(lb_desc2, lv_obj_get_width(desc2));
|
|
||||||
lv_obj_align(desc2, val, LV_ALIGN_OUT_RIGHT_MID, LV_DPI / 6, 0);
|
|
||||||
|
|
||||||
u16 *emmc_errors = emmc_get_error_count();
|
|
||||||
if (emmc_get_mode() < EMMC_MMC_HS400 ||
|
|
||||||
emmc_errors[EMMC_ERROR_INIT_FAIL] ||
|
|
||||||
emmc_errors[EMMC_ERROR_RW_FAIL] ||
|
|
||||||
emmc_errors[EMMC_ERROR_RW_RETRY])
|
|
||||||
{
|
|
||||||
lv_obj_t *dark_bg = lv_obj_create(lv_scr_act(), NULL);
|
|
||||||
lv_obj_set_style(dark_bg, &mbox_darken);
|
|
||||||
lv_obj_set_size(dark_bg, LV_HOR_RES, LV_VER_RES);
|
|
||||||
|
|
||||||
static const char * mbox_btn_map[] = { "\211", "\222OK", "\211", "" };
|
|
||||||
lv_obj_t * mbox = lv_mbox_create(dark_bg, NULL);
|
|
||||||
lv_mbox_set_recolor_text(mbox, true);
|
|
||||||
|
|
||||||
s_printf(txt_buf,
|
|
||||||
"#FF8000 eMMC Issues Check#\n\n"
|
|
||||||
"#FFDD00 Your eMMC is initialized in slower mode,#\n"
|
|
||||||
"#FFDD00 or init/read/write errors occurred!#\n"
|
|
||||||
"#FFDD00 This might mean hardware issues!#\n\n"
|
|
||||||
"#00DDFF Bus Speed:# %d MB/s\n\n"
|
|
||||||
"#00DDFF SDMMC4 Errors:#\n"
|
|
||||||
"Init fails: %d\n"
|
|
||||||
"Read/Write fails: %d\n"
|
|
||||||
"Read/Write errors: %d",
|
|
||||||
emmc_storage.csd.busspeed,
|
|
||||||
emmc_errors[EMMC_ERROR_INIT_FAIL],
|
|
||||||
emmc_errors[EMMC_ERROR_RW_FAIL],
|
|
||||||
emmc_errors[EMMC_ERROR_RW_RETRY]);
|
|
||||||
|
|
||||||
lv_mbox_set_text(mbox, txt_buf);
|
|
||||||
lv_mbox_add_btns(mbox, mbox_btn_map, mbox_action);
|
|
||||||
lv_obj_set_width(mbox, LV_HOR_RES / 9 * 5);
|
|
||||||
lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0);
|
|
||||||
lv_obj_set_top(mbox, true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s_printf(txt_buf + strlen(txt_buf), "(%02X)\n%c%c%c%c%c%c\n%d.%d\n%04X\n%02d/%04d\n\n",
|
||||||
|
emmc_storage.cid.manfid,
|
||||||
|
emmc_storage.cid.prod_name[0], emmc_storage.cid.prod_name[1], emmc_storage.cid.prod_name[2],
|
||||||
|
emmc_storage.cid.prod_name[3], emmc_storage.cid.prod_name[4], emmc_storage.cid.prod_name[5],
|
||||||
|
emmc_storage.cid.prv & 0xF, emmc_storage.cid.prv >> 4,
|
||||||
|
emmc_storage.cid.serial, emmc_storage.cid.month, emmc_storage.cid.year);
|
||||||
|
|
||||||
|
if (card_type & EXT_CSD_CARD_TYPE_HS_26)
|
||||||
|
{
|
||||||
|
strcat(card_type_support, "HS26");
|
||||||
|
speed = (26 << 16) | 26;
|
||||||
|
}
|
||||||
|
if (card_type & EXT_CSD_CARD_TYPE_HS_52)
|
||||||
|
{
|
||||||
|
strcat(card_type_support, ", HS52");
|
||||||
|
speed = (52 << 16) | 52;
|
||||||
|
}
|
||||||
|
if (card_type & EXT_CSD_CARD_TYPE_DDR_1_8V)
|
||||||
|
{
|
||||||
|
strcat(card_type_support, ", DDR52 1.8V");
|
||||||
|
speed = (52 << 16) | 104;
|
||||||
|
}
|
||||||
|
if (card_type & EXT_CSD_CARD_TYPE_HS200_1_8V)
|
||||||
|
{
|
||||||
|
strcat(card_type_support, ", HS200 1.8V");
|
||||||
|
speed = (200 << 16) | 200;
|
||||||
|
}
|
||||||
|
if (card_type & EXT_CSD_CARD_TYPE_HS400_1_8V)
|
||||||
|
{
|
||||||
|
strcat(card_type_support, ", HS400 1.8V");
|
||||||
|
speed = (200 << 16) | 400;
|
||||||
|
}
|
||||||
|
|
||||||
|
strcpy(life_a_txt, "-");
|
||||||
|
strcpy(life_b_txt, "-");
|
||||||
|
|
||||||
|
// Normalize cells life.
|
||||||
|
if (life_a) // SK Hynix is 0 (undefined).
|
||||||
|
{
|
||||||
|
life_a--;
|
||||||
|
life_a = (10 - life_a) * 10;
|
||||||
|
s_printf(life_a_txt, "%d%%", life_a);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (life_b) // Toshiba is 0 (undefined).
|
||||||
|
{
|
||||||
|
life_b--;
|
||||||
|
life_b = (10 - life_b) * 10;
|
||||||
|
s_printf(life_b_txt, "%d%%", life_b);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (emmc_storage.ext_csd.pre_eol_info)
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
rsvd_blocks = "Normal (< 80%)";
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
rsvd_blocks = "Warning (> 80%)";
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
rsvd_blocks = "Critical (> 90%)";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
rsvd_blocks = "#FF8000 Unknown#";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
s_printf(txt_buf + strlen(txt_buf),
|
||||||
|
"#00DDFF V1.%d (rev 1.%d)#\n%02X\n%d MB/s (%d MHz)\n%d MB/s\n%s\n%d %s\n%d MiB\nA: %s, B: %s\n%s",
|
||||||
|
emmc_storage.ext_csd.ext_struct, emmc_storage.ext_csd.rev,
|
||||||
|
emmc_storage.csd.cmdclass, speed & 0xFFFF, (speed >> 16) & 0xFFFF,
|
||||||
|
emmc_storage.csd.busspeed, card_type_support,
|
||||||
|
!(cache % 1024) ? (cache / 1024) : cache, !(cache % 1024) ? "MiB" : "KiB",
|
||||||
|
emmc_storage.ext_csd.max_enh_mult * 512 / 1024,
|
||||||
|
life_a_txt, life_b_txt, rsvd_blocks);
|
||||||
|
|
||||||
|
lv_label_set_static_text(lb_desc,
|
||||||
|
"#00DDFF CID:#\n"
|
||||||
|
"Vendor ID:\n"
|
||||||
|
"Model:\n"
|
||||||
|
"Prod Rev:\n"
|
||||||
|
"S/N:\n"
|
||||||
|
"Month/Year:\n\n"
|
||||||
|
"#00DDFF Ext CSD:#\n"
|
||||||
|
"Cmd Classes:\n"
|
||||||
|
"Max Rate:\n"
|
||||||
|
"Current Rate:\n"
|
||||||
|
"Type Support:\n\n"
|
||||||
|
"Write Cache:\n"
|
||||||
|
"Enhanced Area:\n"
|
||||||
|
"Estimated Life:\n"
|
||||||
|
"Reserved Used:"
|
||||||
|
);
|
||||||
|
lv_obj_set_width(lb_desc, lv_obj_get_width(desc));
|
||||||
|
|
||||||
|
lv_obj_t *val = lv_cont_create(win, NULL);
|
||||||
|
lv_obj_set_size(val, LV_HOR_RES / 11 * 3, LV_VER_RES - (LV_DPI * 11 / 7) - 5);
|
||||||
|
|
||||||
|
lv_obj_t * lb_val = lv_label_create(val, lb_desc);
|
||||||
|
|
||||||
|
lv_label_set_text(lb_val, txt_buf);
|
||||||
|
|
||||||
|
lv_obj_set_width(lb_val, lv_obj_get_width(val));
|
||||||
|
lv_obj_align(val, desc, LV_ALIGN_OUT_RIGHT_MID, 0, 0);
|
||||||
|
|
||||||
|
lv_obj_t *desc2 = lv_cont_create(win, NULL);
|
||||||
|
lv_obj_set_size(desc2, LV_HOR_RES / 2 / 4 * 4, LV_VER_RES - (LV_DPI * 11 / 7) - 5);
|
||||||
|
|
||||||
|
lv_obj_t * lb_desc2 = lv_label_create(desc2, lb_desc);
|
||||||
|
lv_label_set_style(lb_desc2, &monospace_text);
|
||||||
|
|
||||||
|
u32 boot_size = emmc_storage.ext_csd.boot_mult << 17;
|
||||||
|
u32 rpmb_size = emmc_storage.ext_csd.rpmb_mult << 17;
|
||||||
|
strcpy(txt_buf, "#00DDFF eMMC Physical Partitions:#\n");
|
||||||
|
s_printf(txt_buf + strlen(txt_buf), "1: #96FF00 BOOT0# Size: %6d KiB (Sect: 0x%08X)\n", boot_size / 1024, boot_size / 512);
|
||||||
|
s_printf(txt_buf + strlen(txt_buf), "2: #96FF00 BOOT1# Size: %6d KiB (Sect: 0x%08X)\n", boot_size / 1024, boot_size / 512);
|
||||||
|
s_printf(txt_buf + strlen(txt_buf), "3: #96FF00 RPMB# Size: %6d KiB (Sect: 0x%08X)\n", rpmb_size / 1024, rpmb_size / 512);
|
||||||
|
s_printf(txt_buf + strlen(txt_buf), "0: #96FF00 GPP# Size: %6d MiB (Sect: 0x%08X)\n", emmc_storage.sec_cnt >> SECTORS_TO_MIB_COEFF, emmc_storage.sec_cnt);
|
||||||
|
strcat(txt_buf, "\n#00DDFF GPP (eMMC USER) Partition Table:#\n");
|
||||||
|
|
||||||
|
sdmmc_storage_set_mmc_partition(&emmc_storage, EMMC_GPP);
|
||||||
|
LIST_INIT(gpt);
|
||||||
|
emmc_gpt_parse(&gpt);
|
||||||
|
|
||||||
|
u32 idx = 0;
|
||||||
|
LIST_FOREACH_ENTRY(emmc_part_t, part, &gpt, link)
|
||||||
|
{
|
||||||
|
if (idx > 10)
|
||||||
|
{
|
||||||
|
strcat(txt_buf, "#FFDD00 Table does not fit on screen!#");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (part->index < 2)
|
||||||
|
{
|
||||||
|
s_printf(txt_buf + strlen(txt_buf), "%02d: #96FF00 %s#%s Size: %d MiB (Sect: 0x%X), Start: %06X\n",
|
||||||
|
part->index, part->name, !part->name[8] ? " " : "",
|
||||||
|
(part->lba_end - part->lba_start + 1) >> SECTORS_TO_MIB_COEFF,
|
||||||
|
part->lba_end - part->lba_start + 1, part->lba_start);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
s_printf(txt_buf + strlen(txt_buf), "%02d: #96FF00 %s#\n Size: %7d MiB (Sect: 0x%07X), Start: %07X\n",
|
||||||
|
part->index, part->name, (part->lba_end - part->lba_start + 1) >> SECTORS_TO_MIB_COEFF,
|
||||||
|
part->lba_end - part->lba_start + 1, part->lba_start);
|
||||||
|
}
|
||||||
|
|
||||||
|
idx++;
|
||||||
|
}
|
||||||
|
if (!idx)
|
||||||
|
strcat(txt_buf, "#FFDD00 Partition table is empty!#");
|
||||||
|
|
||||||
|
emmc_gpt_free(&gpt);
|
||||||
|
|
||||||
|
lv_label_set_text(lb_desc2, txt_buf);
|
||||||
|
lv_obj_set_width(lb_desc2, lv_obj_get_width(desc2));
|
||||||
|
lv_obj_align(desc2, val, LV_ALIGN_OUT_RIGHT_MID, LV_DPI / 6, 0);
|
||||||
|
|
||||||
|
u16 *emmc_errors = emmc_get_error_count();
|
||||||
|
if (emmc_get_mode() < EMMC_MMC_HS400 ||
|
||||||
|
emmc_errors[EMMC_ERROR_INIT_FAIL] ||
|
||||||
|
emmc_errors[EMMC_ERROR_RW_FAIL] ||
|
||||||
|
emmc_errors[EMMC_ERROR_RW_RETRY])
|
||||||
|
{
|
||||||
|
lv_obj_t *dark_bg = lv_obj_create(lv_scr_act(), NULL);
|
||||||
|
lv_obj_set_style(dark_bg, &mbox_darken);
|
||||||
|
lv_obj_set_size(dark_bg, LV_HOR_RES, LV_VER_RES);
|
||||||
|
|
||||||
|
static const char * mbox_btn_map[] = { "\211", "\222OK", "\211", "" };
|
||||||
|
lv_obj_t * mbox = lv_mbox_create(dark_bg, NULL);
|
||||||
|
lv_mbox_set_recolor_text(mbox, true);
|
||||||
|
|
||||||
|
s_printf(txt_buf,
|
||||||
|
"#FF8000 eMMC Issues Check#\n\n"
|
||||||
|
"#FFDD00 Your eMMC is initialized in slower mode,#\n"
|
||||||
|
"#FFDD00 or init/read/write errors occurred!#\n"
|
||||||
|
"#FFDD00 This might mean hardware issues!#\n\n"
|
||||||
|
"#00DDFF Bus Speed:# %d MB/s\n\n"
|
||||||
|
"#00DDFF SDMMC4 Errors:#\n"
|
||||||
|
"Init fails: %d\n"
|
||||||
|
"Read/Write fails: %d\n"
|
||||||
|
"Read/Write errors: %d",
|
||||||
|
emmc_storage.csd.busspeed,
|
||||||
|
emmc_errors[EMMC_ERROR_INIT_FAIL],
|
||||||
|
emmc_errors[EMMC_ERROR_RW_FAIL],
|
||||||
|
emmc_errors[EMMC_ERROR_RW_RETRY]);
|
||||||
|
|
||||||
|
lv_mbox_set_text(mbox, txt_buf);
|
||||||
|
lv_mbox_add_btns(mbox, mbox_btn_map, mbox_action);
|
||||||
|
lv_obj_set_width(mbox, LV_HOR_RES / 9 * 5);
|
||||||
|
lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0);
|
||||||
|
lv_obj_set_top(mbox, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
sdmmc_storage_end(&emmc_storage);
|
sdmmc_storage_end(&emmc_storage);
|
||||||
free(txt_buf);
|
free(txt_buf);
|
||||||
|
|
||||||
|
|
|
@ -993,66 +993,67 @@ static lv_res_t _create_mbox_fix_touchscreen(lv_obj_t *btn)
|
||||||
}
|
}
|
||||||
|
|
||||||
u8 err[2];
|
u8 err[2];
|
||||||
if (touch_panel_ito_test(err))
|
if (!touch_panel_ito_test(err))
|
||||||
|
goto ito_failed;
|
||||||
|
|
||||||
|
if (!err[0] && !err[1])
|
||||||
{
|
{
|
||||||
if (!err[0] && !err[1])
|
res = touch_execute_autotune();
|
||||||
{
|
if (res)
|
||||||
res = touch_execute_autotune();
|
goto out;
|
||||||
if (res)
|
}
|
||||||
goto out;
|
else
|
||||||
}
|
{
|
||||||
else
|
touch_sense_enable();
|
||||||
{
|
|
||||||
touch_sense_enable();
|
|
||||||
|
|
||||||
s_printf(txt_buf, "#FFFF00 ITO Test: ");
|
s_printf(txt_buf, "#FFFF00 ITO Test: ");
|
||||||
switch (err[0])
|
switch (err[0])
|
||||||
{
|
{
|
||||||
case ITO_FORCE_OPEN:
|
case ITO_FORCE_OPEN:
|
||||||
strcat(txt_buf, "Force Open");
|
strcat(txt_buf, "Force Open");
|
||||||
break;
|
break;
|
||||||
case ITO_SENSE_OPEN:
|
case ITO_SENSE_OPEN:
|
||||||
strcat(txt_buf, "Sense Open");
|
strcat(txt_buf, "Sense Open");
|
||||||
break;
|
break;
|
||||||
case ITO_FORCE_SHRT_GND:
|
case ITO_FORCE_SHRT_GND:
|
||||||
strcat(txt_buf, "Force Short to GND");
|
strcat(txt_buf, "Force Short to GND");
|
||||||
break;
|
break;
|
||||||
case ITO_SENSE_SHRT_GND:
|
case ITO_SENSE_SHRT_GND:
|
||||||
strcat(txt_buf, "Sense Short to GND");
|
strcat(txt_buf, "Sense Short to GND");
|
||||||
break;
|
break;
|
||||||
case ITO_FORCE_SHRT_VCM:
|
case ITO_FORCE_SHRT_VCM:
|
||||||
strcat(txt_buf, "Force Short to VDD");
|
strcat(txt_buf, "Force Short to VDD");
|
||||||
break;
|
break;
|
||||||
case ITO_SENSE_SHRT_VCM:
|
case ITO_SENSE_SHRT_VCM:
|
||||||
strcat(txt_buf, "Sense Short to VDD");
|
strcat(txt_buf, "Sense Short to VDD");
|
||||||
break;
|
break;
|
||||||
case ITO_FORCE_SHRT_FORCE:
|
case ITO_FORCE_SHRT_FORCE:
|
||||||
strcat(txt_buf, "Force Short to Force");
|
strcat(txt_buf, "Force Short to Force");
|
||||||
break;
|
break;
|
||||||
case ITO_SENSE_SHRT_SENSE:
|
case ITO_SENSE_SHRT_SENSE:
|
||||||
strcat(txt_buf, "Sense Short to Sense");
|
strcat(txt_buf, "Sense Short to Sense");
|
||||||
break;
|
break;
|
||||||
case ITO_F2E_SENSE:
|
case ITO_F2E_SENSE:
|
||||||
strcat(txt_buf, "Force Short to Sense");
|
strcat(txt_buf, "Force Short to Sense");
|
||||||
break;
|
break;
|
||||||
case ITO_FPC_FORCE_OPEN:
|
case ITO_FPC_FORCE_OPEN:
|
||||||
strcat(txt_buf, "FPC Force Open");
|
strcat(txt_buf, "FPC Force Open");
|
||||||
break;
|
break;
|
||||||
case ITO_FPC_SENSE_OPEN:
|
case ITO_FPC_SENSE_OPEN:
|
||||||
strcat(txt_buf, "FPC Sense Open");
|
strcat(txt_buf, "FPC Sense Open");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
strcat(txt_buf, "Unknown");
|
strcat(txt_buf, "Unknown");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
|
||||||
s_printf(txt_buf + strlen(txt_buf), " (%d), Chn: %d#\n\n", err[0], err[1]);
|
|
||||||
strcat(txt_buf, "#FFFF00 The touchscreen calibration failed!");
|
|
||||||
lv_mbox_set_text(mbox, txt_buf);
|
|
||||||
goto out2;
|
|
||||||
}
|
}
|
||||||
|
s_printf(txt_buf + strlen(txt_buf), " (%d), Chn: %d#\n\n", err[0], err[1]);
|
||||||
|
strcat(txt_buf, "#FFFF00 The touchscreen calibration failed!");
|
||||||
|
lv_mbox_set_text(mbox, txt_buf);
|
||||||
|
goto out2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ito_failed:
|
||||||
touch_sense_enable();
|
touch_sense_enable();
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
|
|
@ -540,183 +540,183 @@ static lv_res_t _action_flash_linux_data(lv_obj_t * btns, const char * txt)
|
||||||
|
|
||||||
bool succeeded = false;
|
bool succeeded = false;
|
||||||
|
|
||||||
|
if (btn_idx)
|
||||||
|
return LV_RES_INV;
|
||||||
|
|
||||||
// Flash Linux.
|
// Flash Linux.
|
||||||
if (!btn_idx)
|
lv_obj_t *dark_bg = lv_obj_create(lv_scr_act(), NULL);
|
||||||
|
lv_obj_set_style(dark_bg, &mbox_darken);
|
||||||
|
lv_obj_set_size(dark_bg, LV_HOR_RES, LV_VER_RES);
|
||||||
|
|
||||||
|
static const char *mbox_btn_map[] = { "\211", "\222OK", "\211", "" };
|
||||||
|
static const char *mbox_btn_map2[] = { "\223Delete Installation Files", "\221OK", "" };
|
||||||
|
lv_obj_t *mbox = lv_mbox_create(dark_bg, NULL);
|
||||||
|
lv_mbox_set_recolor_text(mbox, true);
|
||||||
|
lv_obj_set_width(mbox, LV_HOR_RES / 10 * 5);
|
||||||
|
|
||||||
|
lv_mbox_set_text(mbox, "#FF8000 Linux Flasher#");
|
||||||
|
|
||||||
|
lv_obj_t *lbl_status = lv_label_create(mbox, NULL);
|
||||||
|
lv_label_set_recolor(lbl_status, true);
|
||||||
|
lv_label_set_text(lbl_status, "#C7EA46 Status:# Flashing Linux...");
|
||||||
|
|
||||||
|
// Create container to keep content inside.
|
||||||
|
lv_obj_t *h1 = lv_cont_create(mbox, NULL);
|
||||||
|
lv_cont_set_fit(h1, true, true);
|
||||||
|
lv_cont_set_style(h1, &lv_style_transp_tight);
|
||||||
|
|
||||||
|
lv_obj_t *bar = lv_bar_create(h1, NULL);
|
||||||
|
lv_obj_set_size(bar, LV_DPI * 30 / 10, LV_DPI / 5);
|
||||||
|
lv_bar_set_range(bar, 0, 100);
|
||||||
|
lv_bar_set_value(bar, 0);
|
||||||
|
|
||||||
|
lv_obj_t *label_pct = lv_label_create(h1, NULL);
|
||||||
|
lv_label_set_recolor(label_pct, true);
|
||||||
|
lv_label_set_text(label_pct, " "SYMBOL_DOT" 0%");
|
||||||
|
lv_label_set_style(label_pct, lv_theme_get_current()->label.prim);
|
||||||
|
lv_obj_align(label_pct, bar, LV_ALIGN_OUT_RIGHT_MID, LV_DPI / 20, 0);
|
||||||
|
|
||||||
|
lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0);
|
||||||
|
lv_obj_set_top(mbox, true);
|
||||||
|
|
||||||
|
sd_mount();
|
||||||
|
|
||||||
|
int res = 0;
|
||||||
|
char *path = malloc(1024);
|
||||||
|
char *txt_buf = malloc(SZ_4K);
|
||||||
|
strcpy(path, "switchroot/install/l4t.00");
|
||||||
|
u32 path_len = strlen(path) - 2;
|
||||||
|
|
||||||
|
FIL fp;
|
||||||
|
|
||||||
|
res = f_open(&fp, path, FA_READ);
|
||||||
|
if (res)
|
||||||
{
|
{
|
||||||
lv_obj_t *dark_bg = lv_obj_create(lv_scr_act(), NULL);
|
lv_label_set_text(lbl_status, "#FFDD00 Error:# Failed to open 1st part!");
|
||||||
lv_obj_set_style(dark_bg, &mbox_darken);
|
|
||||||
lv_obj_set_size(dark_bg, LV_HOR_RES, LV_VER_RES);
|
|
||||||
|
|
||||||
static const char *mbox_btn_map[] = { "\211", "\222OK", "\211", "" };
|
goto exit;
|
||||||
static const char *mbox_btn_map2[] = { "\223Delete Installation Files", "\221OK", "" };
|
}
|
||||||
lv_obj_t *mbox = lv_mbox_create(dark_bg, NULL);
|
|
||||||
lv_mbox_set_recolor_text(mbox, true);
|
|
||||||
lv_obj_set_width(mbox, LV_HOR_RES / 10 * 5);
|
|
||||||
|
|
||||||
lv_mbox_set_text(mbox, "#FF8000 Linux Flasher#");
|
u64 fileSize = (u64)f_size(&fp);
|
||||||
|
|
||||||
lv_obj_t *lbl_status = lv_label_create(mbox, NULL);
|
u32 num = 0;
|
||||||
lv_label_set_recolor(lbl_status, true);
|
u32 pct = 0;
|
||||||
lv_label_set_text(lbl_status, "#C7EA46 Status:# Flashing Linux...");
|
u32 lba_curr = 0;
|
||||||
|
u32 bytesWritten = 0;
|
||||||
|
u32 currPartIdx = 0;
|
||||||
|
u32 prevPct = 200;
|
||||||
|
int retryCount = 0;
|
||||||
|
u32 total_size_sct = l4t_flash_ctxt.image_size_sct;
|
||||||
|
|
||||||
// Create container to keep content inside.
|
u8 *buf = (u8 *)MIXD_BUF_ALIGNED;
|
||||||
lv_obj_t *h1 = lv_cont_create(mbox, NULL);
|
DWORD *clmt = f_expand_cltbl(&fp, SZ_4M, 0);
|
||||||
lv_cont_set_fit(h1, true, true);
|
|
||||||
lv_cont_set_style(h1, &lv_style_transp_tight);
|
|
||||||
|
|
||||||
lv_obj_t *bar = lv_bar_create(h1, NULL);
|
while (total_size_sct > 0)
|
||||||
lv_obj_set_size(bar, LV_DPI * 30 / 10, LV_DPI / 5);
|
{
|
||||||
lv_bar_set_range(bar, 0, 100);
|
// If we have more than one part, check the size for the split parts and make sure that the bytes written is not more than that.
|
||||||
lv_bar_set_value(bar, 0);
|
if (bytesWritten >= fileSize)
|
||||||
|
|
||||||
lv_obj_t *label_pct = lv_label_create(h1, NULL);
|
|
||||||
lv_label_set_recolor(label_pct, true);
|
|
||||||
lv_label_set_text(label_pct, " "SYMBOL_DOT" 0%");
|
|
||||||
lv_label_set_style(label_pct, lv_theme_get_current()->label.prim);
|
|
||||||
lv_obj_align(label_pct, bar, LV_ALIGN_OUT_RIGHT_MID, LV_DPI / 20, 0);
|
|
||||||
|
|
||||||
lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0);
|
|
||||||
lv_obj_set_top(mbox, true);
|
|
||||||
|
|
||||||
sd_mount();
|
|
||||||
|
|
||||||
int res = 0;
|
|
||||||
char *path = malloc(1024);
|
|
||||||
char *txt_buf = malloc(SZ_4K);
|
|
||||||
strcpy(path, "switchroot/install/l4t.00");
|
|
||||||
u32 path_len = strlen(path) - 2;
|
|
||||||
|
|
||||||
FIL fp;
|
|
||||||
|
|
||||||
res = f_open(&fp, path, FA_READ);
|
|
||||||
if (res)
|
|
||||||
{
|
{
|
||||||
lv_label_set_text(lbl_status, "#FFDD00 Error:# Failed to open 1st part!");
|
// If we have more bytes written then close the file pointer and increase the part index we are using
|
||||||
|
f_close(&fp);
|
||||||
|
free(clmt);
|
||||||
|
memset(&fp, 0, sizeof(fp));
|
||||||
|
currPartIdx++;
|
||||||
|
|
||||||
goto exit;
|
if (currPartIdx < 10)
|
||||||
}
|
|
||||||
|
|
||||||
u64 fileSize = (u64)f_size(&fp);
|
|
||||||
|
|
||||||
u32 num = 0;
|
|
||||||
u32 pct = 0;
|
|
||||||
u32 lba_curr = 0;
|
|
||||||
u32 bytesWritten = 0;
|
|
||||||
u32 currPartIdx = 0;
|
|
||||||
u32 prevPct = 200;
|
|
||||||
int retryCount = 0;
|
|
||||||
u32 total_size_sct = l4t_flash_ctxt.image_size_sct;
|
|
||||||
|
|
||||||
u8 *buf = (u8 *)MIXD_BUF_ALIGNED;
|
|
||||||
DWORD *clmt = f_expand_cltbl(&fp, SZ_4M, 0);
|
|
||||||
|
|
||||||
while (total_size_sct > 0)
|
|
||||||
{
|
|
||||||
// If we have more than one part, check the size for the split parts and make sure that the bytes written is not more than that.
|
|
||||||
if (bytesWritten >= fileSize)
|
|
||||||
{
|
{
|
||||||
// If we have more bytes written then close the file pointer and increase the part index we are using
|
path[path_len] = '0';
|
||||||
f_close(&fp);
|
itoa(currPartIdx, &path[path_len + 1], 10);
|
||||||
free(clmt);
|
|
||||||
memset(&fp, 0, sizeof(fp));
|
|
||||||
currPartIdx++;
|
|
||||||
|
|
||||||
if (currPartIdx < 10)
|
|
||||||
{
|
|
||||||
path[path_len] = '0';
|
|
||||||
itoa(currPartIdx, &path[path_len + 1], 10);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
itoa(currPartIdx, &path[path_len], 10);
|
|
||||||
|
|
||||||
// Try to open the next file part
|
|
||||||
res = f_open(&fp, path, FA_READ);
|
|
||||||
if (res)
|
|
||||||
{
|
|
||||||
s_printf(txt_buf, "#FFDD00 Error:# Failed to open part %d#", currPartIdx);
|
|
||||||
lv_label_set_text(lbl_status, txt_buf);
|
|
||||||
manual_system_maintenance(true);
|
|
||||||
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
fileSize = (u64)f_size(&fp);
|
|
||||||
bytesWritten = 0;
|
|
||||||
clmt = f_expand_cltbl(&fp, SZ_4M, 0);
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
itoa(currPartIdx, &path[path_len], 10);
|
||||||
|
|
||||||
retryCount = 0;
|
// Try to open the next file part
|
||||||
num = MIN(total_size_sct, 8192);
|
res = f_open(&fp, path, FA_READ);
|
||||||
|
|
||||||
res = f_read_fast(&fp, buf, num << 9);
|
|
||||||
manual_system_maintenance(false);
|
|
||||||
|
|
||||||
if (res)
|
if (res)
|
||||||
{
|
{
|
||||||
lv_label_set_text(lbl_status, "#FFDD00 Error:# Reading from SD!");
|
s_printf(txt_buf, "#FFDD00 Error:# Failed to open part %d#", currPartIdx);
|
||||||
|
lv_label_set_text(lbl_status, txt_buf);
|
||||||
|
manual_system_maintenance(true);
|
||||||
|
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
fileSize = (u64)f_size(&fp);
|
||||||
|
bytesWritten = 0;
|
||||||
|
clmt = f_expand_cltbl(&fp, SZ_4M, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
retryCount = 0;
|
||||||
|
num = MIN(total_size_sct, 8192);
|
||||||
|
|
||||||
|
res = f_read_fast(&fp, buf, num << 9);
|
||||||
|
manual_system_maintenance(false);
|
||||||
|
|
||||||
|
if (res)
|
||||||
|
{
|
||||||
|
lv_label_set_text(lbl_status, "#FFDD00 Error:# Reading from SD!");
|
||||||
|
manual_system_maintenance(true);
|
||||||
|
|
||||||
|
f_close(&fp);
|
||||||
|
free(clmt);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
res = !sdmmc_storage_write(&sd_storage, lba_curr + l4t_flash_ctxt.offset_sct, num, buf);
|
||||||
|
|
||||||
|
manual_system_maintenance(false);
|
||||||
|
|
||||||
|
while (res)
|
||||||
|
{
|
||||||
|
msleep(150);
|
||||||
|
manual_system_maintenance(true);
|
||||||
|
|
||||||
|
if (retryCount >= 3)
|
||||||
|
{
|
||||||
|
lv_label_set_text(lbl_status, "#FFDD00 Error:# Writing to SD!");
|
||||||
manual_system_maintenance(true);
|
manual_system_maintenance(true);
|
||||||
|
|
||||||
f_close(&fp);
|
f_close(&fp);
|
||||||
free(clmt);
|
free(clmt);
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
res = !sdmmc_storage_write(&sd_storage, lba_curr + l4t_flash_ctxt.offset_sct, num, buf);
|
res = !sdmmc_storage_write(&sd_storage, lba_curr + l4t_flash_ctxt.offset_sct, num, buf);
|
||||||
|
|
||||||
manual_system_maintenance(false);
|
manual_system_maintenance(false);
|
||||||
|
|
||||||
while (res)
|
|
||||||
{
|
|
||||||
msleep(150);
|
|
||||||
manual_system_maintenance(true);
|
|
||||||
|
|
||||||
if (retryCount >= 3)
|
|
||||||
{
|
|
||||||
lv_label_set_text(lbl_status, "#FFDD00 Error:# Writing to SD!");
|
|
||||||
manual_system_maintenance(true);
|
|
||||||
|
|
||||||
f_close(&fp);
|
|
||||||
free(clmt);
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
res = !sdmmc_storage_write(&sd_storage, lba_curr + l4t_flash_ctxt.offset_sct, num, buf);
|
|
||||||
manual_system_maintenance(false);
|
|
||||||
}
|
|
||||||
pct = (u64)((u64)lba_curr * 100u) / (u64)l4t_flash_ctxt.image_size_sct;
|
|
||||||
if (pct != prevPct)
|
|
||||||
{
|
|
||||||
lv_bar_set_value(bar, pct);
|
|
||||||
s_printf(txt_buf, " #DDDDDD "SYMBOL_DOT"# %d%%", pct);
|
|
||||||
lv_label_set_text(label_pct, txt_buf);
|
|
||||||
manual_system_maintenance(true);
|
|
||||||
prevPct = pct;
|
|
||||||
}
|
|
||||||
|
|
||||||
lba_curr += num;
|
|
||||||
total_size_sct -= num;
|
|
||||||
bytesWritten += num * EMMC_BLOCKSIZE;
|
|
||||||
}
|
}
|
||||||
lv_bar_set_value(bar, 100);
|
pct = (u64)((u64)lba_curr * 100u) / (u64)l4t_flash_ctxt.image_size_sct;
|
||||||
lv_label_set_text(label_pct, " "SYMBOL_DOT" 100%");
|
if (pct != prevPct)
|
||||||
manual_system_maintenance(true);
|
{
|
||||||
|
lv_bar_set_value(bar, pct);
|
||||||
|
s_printf(txt_buf, " #DDDDDD "SYMBOL_DOT"# %d%%", pct);
|
||||||
|
lv_label_set_text(label_pct, txt_buf);
|
||||||
|
manual_system_maintenance(true);
|
||||||
|
prevPct = pct;
|
||||||
|
}
|
||||||
|
|
||||||
// Restore operation ended successfully.
|
lba_curr += num;
|
||||||
f_close(&fp);
|
total_size_sct -= num;
|
||||||
free(clmt);
|
bytesWritten += num * EMMC_BLOCKSIZE;
|
||||||
|
}
|
||||||
|
lv_bar_set_value(bar, 100);
|
||||||
|
lv_label_set_text(label_pct, " "SYMBOL_DOT" 100%");
|
||||||
|
manual_system_maintenance(true);
|
||||||
|
|
||||||
succeeded = true;
|
// Restore operation ended successfully.
|
||||||
|
f_close(&fp);
|
||||||
|
free(clmt);
|
||||||
|
|
||||||
|
succeeded = true;
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
free(path);
|
free(path);
|
||||||
free(txt_buf);
|
free(txt_buf);
|
||||||
|
|
||||||
if (!succeeded)
|
if (!succeeded)
|
||||||
lv_mbox_add_btns(mbox, mbox_btn_map, mbox_action);
|
lv_mbox_add_btns(mbox, mbox_btn_map, mbox_action);
|
||||||
else
|
else
|
||||||
lv_mbox_add_btns(mbox, mbox_btn_map2, _action_delete_linux_installer_files);
|
lv_mbox_add_btns(mbox, mbox_btn_map2, _action_delete_linux_installer_files);
|
||||||
lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0);
|
lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0);
|
||||||
|
|
||||||
sd_unmount();
|
sd_unmount();
|
||||||
}
|
|
||||||
|
|
||||||
return LV_RES_INV;
|
return LV_RES_INV;
|
||||||
}
|
}
|
||||||
|
@ -856,36 +856,34 @@ static lv_res_t _action_check_flash_linux(lv_obj_t *btn)
|
||||||
itoa(idx, &path[23], 10);
|
itoa(idx, &path[23], 10);
|
||||||
|
|
||||||
// Check for alignment.
|
// Check for alignment.
|
||||||
if (!f_stat(path, &fno))
|
if (f_stat(path, &fno))
|
||||||
{
|
|
||||||
if ((u64)fno.fsize % SZ_4M)
|
|
||||||
{
|
|
||||||
// Check if last part.
|
|
||||||
idx++;
|
|
||||||
if (idx < 10)
|
|
||||||
{
|
|
||||||
path[23] = '0';
|
|
||||||
itoa(idx, &path[23 + 1], 10);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
itoa(idx, &path[23], 10);
|
|
||||||
|
|
||||||
// If not the last part, unaligned size is not permitted.
|
|
||||||
if (!f_stat(path, NULL)) // NULL: Don't override current part fs info.
|
|
||||||
{
|
|
||||||
lv_label_set_text(lbl_status, "#FFDD00 Error:# The image is not aligned to 4 MiB!");
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Last part. Align size to LBA (512 bytes).
|
|
||||||
fno.fsize = ALIGN((u64)fno.fsize, 512);
|
|
||||||
idx--;
|
|
||||||
}
|
|
||||||
l4t_flash_ctxt.image_size_sct += (u64)fno.fsize >> 9;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
if ((u64)fno.fsize % SZ_4M)
|
||||||
|
{
|
||||||
|
// Check if last part.
|
||||||
|
idx++;
|
||||||
|
if (idx < 10)
|
||||||
|
{
|
||||||
|
path[23] = '0';
|
||||||
|
itoa(idx, &path[23 + 1], 10);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
itoa(idx, &path[23], 10);
|
||||||
|
|
||||||
|
// If not the last part, unaligned size is not permitted.
|
||||||
|
if (!f_stat(path, NULL)) // NULL: Don't override current part fs info.
|
||||||
|
{
|
||||||
|
lv_label_set_text(lbl_status, "#FFDD00 Error:# The image is not aligned to 4 MiB!");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Last part. Align size to LBA (512 bytes).
|
||||||
|
fno.fsize = ALIGN((u64)fno.fsize, 512);
|
||||||
|
idx--;
|
||||||
|
}
|
||||||
|
l4t_flash_ctxt.image_size_sct += (u64)fno.fsize >> 9;
|
||||||
|
|
||||||
idx++;
|
idx++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -950,236 +948,244 @@ static lv_res_t _action_flash_android_data(lv_obj_t * btns, const char * txt)
|
||||||
// Delete parent mbox.
|
// Delete parent mbox.
|
||||||
mbox_action(btns, txt);
|
mbox_action(btns, txt);
|
||||||
|
|
||||||
|
if (btn_idx)
|
||||||
|
return LV_RES_INV;
|
||||||
|
|
||||||
// Flash Android components.
|
// Flash Android components.
|
||||||
if (!btn_idx)
|
char path[128];
|
||||||
|
gpt_t *gpt = calloc(1, sizeof(gpt_t));
|
||||||
|
char *txt_buf = malloc(SZ_4K);
|
||||||
|
|
||||||
|
lv_obj_t *dark_bg = lv_obj_create(lv_scr_act(), NULL);
|
||||||
|
lv_obj_set_style(dark_bg, &mbox_darken);
|
||||||
|
lv_obj_set_size(dark_bg, LV_HOR_RES, LV_VER_RES);
|
||||||
|
|
||||||
|
static const char *mbox_btn_map[] = { "\211", "\222OK", "\211", "" };
|
||||||
|
static const char *mbox_btn_map2[] = { "\222Continue", "\222No", "" };
|
||||||
|
lv_obj_t *mbox = lv_mbox_create(dark_bg, NULL);
|
||||||
|
lv_mbox_set_recolor_text(mbox, true);
|
||||||
|
lv_obj_set_width(mbox, LV_HOR_RES / 9 * 6);
|
||||||
|
|
||||||
|
lv_mbox_set_text(mbox, "#FF8000 Android Flasher#");
|
||||||
|
|
||||||
|
lv_obj_t *lbl_status = lv_label_create(mbox, NULL);
|
||||||
|
lv_label_set_recolor(lbl_status, true);
|
||||||
|
lv_label_set_text(lbl_status, "#C7EA46 Status:# Searching for files and partitions...");
|
||||||
|
|
||||||
|
lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0);
|
||||||
|
lv_obj_set_top(mbox, true);
|
||||||
|
|
||||||
|
manual_system_maintenance(true);
|
||||||
|
|
||||||
|
sd_mount();
|
||||||
|
|
||||||
|
// Read main GPT.
|
||||||
|
sdmmc_storage_read(&sd_storage, 1, sizeof(gpt_t) >> 9, gpt);
|
||||||
|
|
||||||
|
bool boot_twrp = false;
|
||||||
|
if (memcmp(&gpt->header.signature, "EFI PART", 8) || gpt->header.num_part_ents > 128)
|
||||||
{
|
{
|
||||||
char path[128];
|
lv_label_set_text(lbl_status, "#FFDD00 Error:# No Android GPT was found!");
|
||||||
gpt_t *gpt = calloc(1, sizeof(gpt_t));
|
goto error;
|
||||||
char *txt_buf = malloc(SZ_4K);
|
}
|
||||||
|
|
||||||
lv_obj_t *dark_bg = lv_obj_create(lv_scr_act(), NULL);
|
u32 offset_sct = 0;
|
||||||
lv_obj_set_style(dark_bg, &mbox_darken);
|
u32 size_sct = 0;
|
||||||
lv_obj_set_size(dark_bg, LV_HOR_RES, LV_VER_RES);
|
|
||||||
|
|
||||||
static const char *mbox_btn_map[] = { "\211", "\222OK", "\211", "" };
|
strcpy(path, "switchroot/install/boot.img");
|
||||||
static const char *mbox_btn_map2[] = { "\222Continue", "\222No", "" };
|
if (f_stat(path, NULL))
|
||||||
lv_obj_t *mbox = lv_mbox_create(dark_bg, NULL);
|
{
|
||||||
lv_mbox_set_recolor_text(mbox, true);
|
s_printf(txt_buf, "#FF8000 Warning:# Kernel image not found!\n");
|
||||||
lv_obj_set_width(mbox, LV_HOR_RES / 9 * 6);
|
goto boot_img_not_found;
|
||||||
|
}
|
||||||
|
|
||||||
lv_mbox_set_text(mbox, "#FF8000 Android Flasher#");
|
for (u32 i = 0; i < gpt->header.num_part_ents; i++)
|
||||||
|
{
|
||||||
lv_obj_t *lbl_status = lv_label_create(mbox, NULL);
|
if (!memcmp(gpt->entries[i].name, (char[]) { 'L', 0, 'N', 0, 'X', 0 }, 6))
|
||||||
lv_label_set_recolor(lbl_status, true);
|
|
||||||
lv_label_set_text(lbl_status, "#C7EA46 Status:# Searching for files and partitions...");
|
|
||||||
|
|
||||||
lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0);
|
|
||||||
lv_obj_set_top(mbox, true);
|
|
||||||
|
|
||||||
manual_system_maintenance(true);
|
|
||||||
|
|
||||||
sd_mount();
|
|
||||||
|
|
||||||
// Read main GPT.
|
|
||||||
sdmmc_storage_read(&sd_storage, 1, sizeof(gpt_t) >> 9, gpt);
|
|
||||||
|
|
||||||
bool boot_twrp = false;
|
|
||||||
if (memcmp(&gpt->header.signature, "EFI PART", 8) || gpt->header.num_part_ents > 128)
|
|
||||||
{
|
{
|
||||||
lv_label_set_text(lbl_status, "#FFDD00 Error:# No Android GPT was found!");
|
offset_sct = gpt->entries[i].lba_start;
|
||||||
goto error;
|
size_sct = (gpt->entries[i].lba_end + 1) - gpt->entries[i].lba_start;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
strcpy(path, "switchroot/install/boot.img");
|
if (i > 126)
|
||||||
if (!f_stat(path, NULL))
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (offset_sct && size_sct)
|
||||||
|
{
|
||||||
|
u32 file_size = 0;
|
||||||
|
u8 *buf = sd_file_read(path, &file_size);
|
||||||
|
|
||||||
|
if (file_size % 0x200)
|
||||||
{
|
{
|
||||||
u32 offset_sct = 0;
|
file_size = ALIGN(file_size, 0x200);
|
||||||
u32 size_sct = 0;
|
u8 *buf_tmp = calloc(file_size, 1);
|
||||||
for (u32 i = 0; i < gpt->header.num_part_ents; i++)
|
memcpy(buf_tmp, buf, file_size);
|
||||||
{
|
free(buf);
|
||||||
if (!memcmp(gpt->entries[i].name, (char[]) { 'L', 0, 'N', 0, 'X', 0 }, 6))
|
buf = buf_tmp;
|
||||||
{
|
|
||||||
offset_sct = gpt->entries[i].lba_start;
|
|
||||||
size_sct = (gpt->entries[i].lba_end + 1) - gpt->entries[i].lba_start;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i > 126)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (offset_sct && size_sct)
|
|
||||||
{
|
|
||||||
u32 file_size = 0;
|
|
||||||
u8 *buf = sd_file_read(path, &file_size);
|
|
||||||
|
|
||||||
if (file_size % 0x200)
|
|
||||||
{
|
|
||||||
file_size = ALIGN(file_size, 0x200);
|
|
||||||
u8 *buf_tmp = calloc(file_size, 1);
|
|
||||||
memcpy(buf_tmp, buf, file_size);
|
|
||||||
free(buf);
|
|
||||||
buf = buf_tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((file_size >> 9) > size_sct)
|
|
||||||
s_printf(txt_buf, "#FF8000 Warning:# Kernel image too big!\n");
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sdmmc_storage_write(&sd_storage, offset_sct, file_size >> 9, buf);
|
|
||||||
|
|
||||||
s_printf(txt_buf, "#C7EA46 Success:# Kernel image flashed!\n");
|
|
||||||
f_unlink(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
free(buf);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
s_printf(txt_buf, "#FF8000 Warning:# Kernel partition not found!\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((file_size >> 9) > size_sct)
|
||||||
|
s_printf(txt_buf, "#FF8000 Warning:# Kernel image too big!\n");
|
||||||
else
|
else
|
||||||
s_printf(txt_buf, "#FF8000 Warning:# Kernel image not found!\n");
|
|
||||||
|
|
||||||
lv_label_set_text(lbl_status, txt_buf);
|
|
||||||
manual_system_maintenance(true);
|
|
||||||
|
|
||||||
strcpy(path, "switchroot/install/twrp.img");
|
|
||||||
if (!f_stat(path, NULL))
|
|
||||||
{
|
{
|
||||||
u32 offset_sct = 0;
|
sdmmc_storage_write(&sd_storage, offset_sct, file_size >> 9, buf);
|
||||||
u32 size_sct = 0;
|
|
||||||
for (u32 i = 0; i < gpt->header.num_part_ents; i++)
|
|
||||||
{
|
|
||||||
if (!memcmp(gpt->entries[i].name, (char[]) { 'S', 0, 'O', 0, 'S', 0 }, 6))
|
|
||||||
{
|
|
||||||
offset_sct = gpt->entries[i].lba_start;
|
|
||||||
size_sct = (gpt->entries[i].lba_end + 1) - gpt->entries[i].lba_start;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i > 126)
|
s_printf(txt_buf, "#C7EA46 Success:# Kernel image flashed!\n");
|
||||||
break;
|
f_unlink(path);
|
||||||
}
|
|
||||||
|
|
||||||
if (offset_sct && size_sct)
|
|
||||||
{
|
|
||||||
u32 file_size = 0;
|
|
||||||
u8 *buf = sd_file_read(path, &file_size);
|
|
||||||
|
|
||||||
if (file_size % 0x200)
|
|
||||||
{
|
|
||||||
file_size = ALIGN(file_size, 0x200);
|
|
||||||
u8 *buf_tmp = calloc(file_size, 1);
|
|
||||||
memcpy(buf_tmp, buf, file_size);
|
|
||||||
free(buf);
|
|
||||||
buf = buf_tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((file_size >> 9) > size_sct)
|
|
||||||
strcat(txt_buf, "#FF8000 Warning:# TWRP image too big!\n");
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sdmmc_storage_write(&sd_storage, offset_sct, file_size >> 9, buf);
|
|
||||||
strcat(txt_buf, "#C7EA46 Success:# TWRP image flashed!\n");
|
|
||||||
f_unlink(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
free(buf);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
strcat(txt_buf, "#FF8000 Warning:# TWRP partition not found!\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free(buf);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
s_printf(txt_buf, "#FF8000 Warning:# Kernel partition not found!\n");
|
||||||
|
|
||||||
|
boot_img_not_found:
|
||||||
|
lv_label_set_text(lbl_status, txt_buf);
|
||||||
|
manual_system_maintenance(true);
|
||||||
|
|
||||||
|
strcpy(path, "switchroot/install/twrp.img");
|
||||||
|
if (f_stat(path, NULL))
|
||||||
|
{
|
||||||
|
strcat(txt_buf, "#FF8000 Warning:# TWRP image not found!\n");
|
||||||
|
goto twrp_not_found;
|
||||||
|
}
|
||||||
|
|
||||||
|
offset_sct = 0;
|
||||||
|
size_sct = 0;
|
||||||
|
for (u32 i = 0; i < gpt->header.num_part_ents; i++)
|
||||||
|
{
|
||||||
|
if (!memcmp(gpt->entries[i].name, (char[]) { 'S', 0, 'O', 0, 'S', 0 }, 6))
|
||||||
|
{
|
||||||
|
offset_sct = gpt->entries[i].lba_start;
|
||||||
|
size_sct = (gpt->entries[i].lba_end + 1) - gpt->entries[i].lba_start;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i > 126)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (offset_sct && size_sct)
|
||||||
|
{
|
||||||
|
u32 file_size = 0;
|
||||||
|
u8 *buf = sd_file_read(path, &file_size);
|
||||||
|
|
||||||
|
if (file_size % 0x200)
|
||||||
|
{
|
||||||
|
file_size = ALIGN(file_size, 0x200);
|
||||||
|
u8 *buf_tmp = calloc(file_size, 1);
|
||||||
|
memcpy(buf_tmp, buf, file_size);
|
||||||
|
free(buf);
|
||||||
|
buf = buf_tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((file_size >> 9) > size_sct)
|
||||||
|
strcat(txt_buf, "#FF8000 Warning:# TWRP image too big!\n");
|
||||||
else
|
else
|
||||||
strcat(txt_buf, "#FF8000 Warning:# TWRP image not found!\n");
|
|
||||||
|
|
||||||
lv_label_set_text(lbl_status, txt_buf);
|
|
||||||
manual_system_maintenance(true);
|
|
||||||
|
|
||||||
strcpy(path, "switchroot/install/tegra210-icosa.dtb");
|
|
||||||
if (!f_stat(path, NULL))
|
|
||||||
{
|
{
|
||||||
u32 offset_sct = 0;
|
sdmmc_storage_write(&sd_storage, offset_sct, file_size >> 9, buf);
|
||||||
u32 size_sct = 0;
|
strcat(txt_buf, "#C7EA46 Success:# TWRP image flashed!\n");
|
||||||
for (u32 i = 0; i < gpt->header.num_part_ents; i++)
|
f_unlink(path);
|
||||||
{
|
|
||||||
if (!memcmp(gpt->entries[i].name, (char[]) { 'D', 0, 'T', 0, 'B', 0 }, 6))
|
|
||||||
{
|
|
||||||
offset_sct = gpt->entries[i].lba_start;
|
|
||||||
size_sct = (gpt->entries[i].lba_end + 1) - gpt->entries[i].lba_start;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i > 126)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (offset_sct && size_sct)
|
|
||||||
{
|
|
||||||
u32 file_size = 0;
|
|
||||||
u8 *buf = sd_file_read(path, &file_size);
|
|
||||||
|
|
||||||
if (file_size % 0x200)
|
|
||||||
{
|
|
||||||
file_size = ALIGN(file_size, 0x200);
|
|
||||||
u8 *buf_tmp = calloc(file_size, 1);
|
|
||||||
memcpy(buf_tmp, buf, file_size);
|
|
||||||
free(buf);
|
|
||||||
buf = buf_tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((file_size >> 9) > size_sct)
|
|
||||||
strcat(txt_buf, "#FF8000 Warning:# DTB image too big!");
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sdmmc_storage_write(&sd_storage, offset_sct, file_size >> 9, buf);
|
|
||||||
strcat(txt_buf, "#C7EA46 Success:# DTB image flashed!");
|
|
||||||
f_unlink(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
free(buf);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
strcat(txt_buf, "#FF8000 Warning:# DTB partition not found!");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free(buf);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
strcat(txt_buf, "#FF8000 Warning:# TWRP partition not found!\n");
|
||||||
|
|
||||||
|
twrp_not_found:
|
||||||
|
lv_label_set_text(lbl_status, txt_buf);
|
||||||
|
manual_system_maintenance(true);
|
||||||
|
|
||||||
|
strcpy(path, "switchroot/install/tegra210-icosa.dtb");
|
||||||
|
if (f_stat(path, NULL))
|
||||||
|
{
|
||||||
|
strcat(txt_buf, "#FF8000 Warning:# DTB image not found!");
|
||||||
|
|
||||||
|
goto dtb_not_found;
|
||||||
|
}
|
||||||
|
|
||||||
|
offset_sct = 0;
|
||||||
|
size_sct = 0;
|
||||||
|
for (u32 i = 0; i < gpt->header.num_part_ents; i++)
|
||||||
|
{
|
||||||
|
if (!memcmp(gpt->entries[i].name, (char[]) { 'D', 0, 'T', 0, 'B', 0 }, 6))
|
||||||
|
{
|
||||||
|
offset_sct = gpt->entries[i].lba_start;
|
||||||
|
size_sct = (gpt->entries[i].lba_end + 1) - gpt->entries[i].lba_start;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i > 126)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (offset_sct && size_sct)
|
||||||
|
{
|
||||||
|
u32 file_size = 0;
|
||||||
|
u8 *buf = sd_file_read(path, &file_size);
|
||||||
|
|
||||||
|
if (file_size % 0x200)
|
||||||
|
{
|
||||||
|
file_size = ALIGN(file_size, 0x200);
|
||||||
|
u8 *buf_tmp = calloc(file_size, 1);
|
||||||
|
memcpy(buf_tmp, buf, file_size);
|
||||||
|
free(buf);
|
||||||
|
buf = buf_tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((file_size >> 9) > size_sct)
|
||||||
|
strcat(txt_buf, "#FF8000 Warning:# DTB image too big!");
|
||||||
else
|
else
|
||||||
strcat(txt_buf, "#FF8000 Warning:# DTB image not found!");
|
|
||||||
|
|
||||||
lv_label_set_text(lbl_status, txt_buf);
|
|
||||||
|
|
||||||
// Check if TWRP is flashed unconditionally.
|
|
||||||
for (u32 i = 0; i < gpt->header.num_part_ents; i++)
|
|
||||||
{
|
{
|
||||||
if (!memcmp(gpt->entries[i].name, (char[]) { 'S', 0, 'O', 0, 'S', 0 }, 6))
|
sdmmc_storage_write(&sd_storage, offset_sct, file_size >> 9, buf);
|
||||||
{
|
strcat(txt_buf, "#C7EA46 Success:# DTB image flashed!");
|
||||||
u8 *buf = malloc(512);
|
f_unlink(path);
|
||||||
sdmmc_storage_read(&sd_storage, gpt->entries[i].lba_start, 1, buf);
|
|
||||||
if (!memcmp(buf, "ANDROID", 7))
|
|
||||||
boot_twrp = true;
|
|
||||||
free(buf);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i > 126)
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free(buf);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
strcat(txt_buf, "#FF8000 Warning:# DTB partition not found!");
|
||||||
|
|
||||||
|
dtb_not_found:
|
||||||
|
lv_label_set_text(lbl_status, txt_buf);
|
||||||
|
|
||||||
|
// Check if TWRP is flashed unconditionally.
|
||||||
|
for (u32 i = 0; i < gpt->header.num_part_ents; i++)
|
||||||
|
{
|
||||||
|
if (!memcmp(gpt->entries[i].name, (char[]) { 'S', 0, 'O', 0, 'S', 0 }, 6))
|
||||||
|
{
|
||||||
|
u8 *buf = malloc(512);
|
||||||
|
sdmmc_storage_read(&sd_storage, gpt->entries[i].lba_start, 1, buf);
|
||||||
|
if (!memcmp(buf, "ANDROID", 7))
|
||||||
|
boot_twrp = true;
|
||||||
|
free(buf);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i > 126)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
error:
|
error:
|
||||||
if (boot_twrp)
|
if (boot_twrp)
|
||||||
{
|
{
|
||||||
strcat(txt_buf,"\n\nDo you want to reboot into TWRP\nto finish Android installation?");
|
strcat(txt_buf,"\n\nDo you want to reboot into TWRP\nto finish Android installation?");
|
||||||
lv_label_set_text(lbl_status, txt_buf);
|
lv_label_set_text(lbl_status, txt_buf);
|
||||||
lv_mbox_add_btns(mbox, mbox_btn_map2, _action_reboot_twrp);
|
lv_mbox_add_btns(mbox, mbox_btn_map2, _action_reboot_twrp);
|
||||||
}
|
|
||||||
else
|
|
||||||
lv_mbox_add_btns(mbox, mbox_btn_map, mbox_action);
|
|
||||||
|
|
||||||
lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0);
|
|
||||||
|
|
||||||
free(txt_buf);
|
|
||||||
free(gpt);
|
|
||||||
|
|
||||||
sd_unmount();
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
lv_mbox_add_btns(mbox, mbox_btn_map, mbox_action);
|
||||||
|
|
||||||
|
lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0);
|
||||||
|
|
||||||
|
free(txt_buf);
|
||||||
|
free(gpt);
|
||||||
|
|
||||||
|
sd_unmount();
|
||||||
|
|
||||||
return LV_RES_INV;
|
return LV_RES_INV;
|
||||||
}
|
}
|
||||||
|
@ -1409,54 +1415,58 @@ static lv_res_t _create_mbox_start_partitioning(lv_obj_t *btn)
|
||||||
|
|
||||||
u32 cluster_size = 65536;
|
u32 cluster_size = 65536;
|
||||||
u32 mkfs_error = f_mkfs("sd:", FM_FAT32, cluster_size, buf, SZ_4M);
|
u32 mkfs_error = f_mkfs("sd:", FM_FAT32, cluster_size, buf, SZ_4M);
|
||||||
|
|
||||||
|
if (!mkfs_error)
|
||||||
|
goto mkfs_no_error;
|
||||||
|
|
||||||
|
// Retry by halving cluster size.
|
||||||
|
while (cluster_size > 4096)
|
||||||
|
{
|
||||||
|
cluster_size /= 2;
|
||||||
|
mkfs_error = f_mkfs("sd:", FM_FAT32, cluster_size, buf, SZ_4M);
|
||||||
|
|
||||||
|
if (!mkfs_error)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (mkfs_error)
|
if (mkfs_error)
|
||||||
{
|
{
|
||||||
// Retry by halving cluster size.
|
// Failed to format.
|
||||||
while (cluster_size > 4096)
|
s_printf((char *)buf, "#FFDD00 Error:# Failed to format disk (%d)!\n\n"
|
||||||
{
|
"Remove the SD card and check that is OK.\nIf not, format it, reinsert it and\npress #FF8000 POWER#!", mkfs_error);
|
||||||
cluster_size /= 2;
|
|
||||||
mkfs_error = f_mkfs("sd:", FM_FAT32, cluster_size, buf, SZ_4M);
|
|
||||||
|
|
||||||
if (!mkfs_error)
|
lv_label_set_text(lbl_status, (char *)buf);
|
||||||
break;
|
lv_label_set_text(lbl_paths[0], " ");
|
||||||
|
manual_system_maintenance(true);
|
||||||
|
|
||||||
|
sd_end();
|
||||||
|
|
||||||
|
while (!(btn_wait() & BTN_POWER));
|
||||||
|
|
||||||
|
sd_mount();
|
||||||
|
|
||||||
|
if (!part_info.backup_possible)
|
||||||
|
{
|
||||||
|
f_chdrive("sd:");
|
||||||
|
f_mkdir(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mkfs_error)
|
lv_label_set_text(lbl_status, "#00DDFF Status:# Restoring files...");
|
||||||
|
manual_system_maintenance(true);
|
||||||
|
if (_backup_and_restore_files(path, &total_files, &total_size, "sd:", "ram:", NULL))
|
||||||
{
|
{
|
||||||
// Failed to format.
|
lv_label_set_text(lbl_status, "#FFDD00 Error:# Failed to restore files!");
|
||||||
s_printf((char *)buf, "#FFDD00 Error:# Failed to format disk (%d)!\n\n"
|
|
||||||
"Remove the SD card and check that is OK.\nIf not, format it, reinsert it and\npress #FF8000 POWER#!", mkfs_error);
|
|
||||||
|
|
||||||
lv_label_set_text(lbl_status, (char *)buf);
|
|
||||||
lv_label_set_text(lbl_paths[0], " ");
|
|
||||||
manual_system_maintenance(true);
|
|
||||||
|
|
||||||
sd_end();
|
|
||||||
|
|
||||||
while (!(btn_wait() & BTN_POWER));
|
|
||||||
|
|
||||||
sd_mount();
|
|
||||||
|
|
||||||
if (!part_info.backup_possible)
|
|
||||||
{
|
|
||||||
f_chdrive("sd:");
|
|
||||||
f_mkdir(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
lv_label_set_text(lbl_status, "#00DDFF Status:# Restoring files...");
|
|
||||||
manual_system_maintenance(true);
|
|
||||||
if (_backup_and_restore_files(path, &total_files, &total_size, "sd:", "ram:", NULL))
|
|
||||||
{
|
|
||||||
lv_label_set_text(lbl_status, "#FFDD00 Error:# Failed to restore files!");
|
|
||||||
free(buf);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
lv_label_set_text(lbl_status, "#00DDFF Status:# Restored files but the operation failed!");
|
|
||||||
f_mount(NULL, "ram:", 1); // Unmount ramdisk.
|
|
||||||
free(buf);
|
free(buf);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lv_label_set_text(lbl_status, "#00DDFF Status:# Restored files but the operation failed!");
|
||||||
|
f_mount(NULL, "ram:", 1); // Unmount ramdisk.
|
||||||
|
free(buf);
|
||||||
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mkfs_no_error:
|
||||||
free(buf);
|
free(buf);
|
||||||
|
|
||||||
f_mount(&sd_fs, "sd:", 1); // Mount SD card.
|
f_mount(&sd_fs, "sd:", 1); // Mount SD card.
|
||||||
|
|
|
@ -138,67 +138,67 @@ lv_res_t launch_payload(lv_obj_t *list)
|
||||||
strcpy(path,"bootloader/payloads/");
|
strcpy(path,"bootloader/payloads/");
|
||||||
strcat(path, filename);
|
strcat(path, filename);
|
||||||
|
|
||||||
if (sd_mount())
|
if (!sd_mount())
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
FIL fp;
|
||||||
|
if (f_open(&fp, path, FA_READ))
|
||||||
{
|
{
|
||||||
FIL fp;
|
EPRINTFARGS("Payload file is missing!\n(%s)", path);
|
||||||
if (f_open(&fp, path, FA_READ))
|
|
||||||
{
|
|
||||||
EPRINTFARGS("Payload file is missing!\n(%s)", path);
|
|
||||||
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read and copy the payload to our chosen address
|
// Read and copy the payload to our chosen address
|
||||||
void *buf;
|
void *buf;
|
||||||
u32 size = f_size(&fp);
|
u32 size = f_size(&fp);
|
||||||
|
|
||||||
if (size < 0x30000)
|
if (size < 0x30000)
|
||||||
buf = (void *)RCM_PAYLOAD_ADDR;
|
buf = (void *)RCM_PAYLOAD_ADDR;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
coreboot_addr = (void *)(COREBOOT_END_ADDR - size);
|
coreboot_addr = (void *)(COREBOOT_END_ADDR - size);
|
||||||
buf = coreboot_addr;
|
buf = coreboot_addr;
|
||||||
if (h_cfg.t210b01)
|
if (h_cfg.t210b01)
|
||||||
{
|
|
||||||
f_close(&fp);
|
|
||||||
|
|
||||||
EPRINTF("Coreboot not allowed on Mariko!");
|
|
||||||
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (f_read(&fp, buf, size, NULL))
|
|
||||||
{
|
{
|
||||||
f_close(&fp);
|
f_close(&fp);
|
||||||
|
|
||||||
|
EPRINTF("Coreboot not allowed on Mariko!");
|
||||||
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (f_read(&fp, buf, size, NULL))
|
||||||
|
{
|
||||||
f_close(&fp);
|
f_close(&fp);
|
||||||
|
|
||||||
sd_end();
|
goto out;
|
||||||
|
|
||||||
if (size < 0x30000)
|
|
||||||
{
|
|
||||||
reloc_patcher(PATCHED_RELOC_ENTRY, EXT_PAYLOAD_ADDR, ALIGN(size, 0x10));
|
|
||||||
hw_reinit_workaround(false, byte_swap_32(*(u32 *)(buf + size - sizeof(u32))));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
reloc_patcher(PATCHED_RELOC_ENTRY, EXT_PAYLOAD_ADDR, 0x7000);
|
|
||||||
hw_reinit_workaround(true, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void (*ext_payload_ptr)() = (void *)EXT_PAYLOAD_ADDR;
|
|
||||||
|
|
||||||
// Some cards (Sandisk U1), do not like a fast power cycle. Wait min 100ms.
|
|
||||||
sdmmc_storage_init_wait_sd();
|
|
||||||
|
|
||||||
// Launch our payload.
|
|
||||||
(*ext_payload_ptr)();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
f_close(&fp);
|
||||||
|
|
||||||
|
sd_end();
|
||||||
|
|
||||||
|
if (size < 0x30000)
|
||||||
|
{
|
||||||
|
reloc_patcher(PATCHED_RELOC_ENTRY, EXT_PAYLOAD_ADDR, ALIGN(size, 0x10));
|
||||||
|
hw_reinit_workaround(false, byte_swap_32(*(u32 *)(buf + size - sizeof(u32))));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
reloc_patcher(PATCHED_RELOC_ENTRY, EXT_PAYLOAD_ADDR, 0x7000);
|
||||||
|
hw_reinit_workaround(true, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void (*ext_payload_ptr)() = (void *)EXT_PAYLOAD_ADDR;
|
||||||
|
|
||||||
|
// Some cards (Sandisk U1), do not like a fast power cycle. Wait min 100ms.
|
||||||
|
sdmmc_storage_init_wait_sd();
|
||||||
|
|
||||||
|
// Launch our payload.
|
||||||
|
(*ext_payload_ptr)();
|
||||||
|
|
||||||
out:
|
out:
|
||||||
sd_unmount();
|
sd_unmount();
|
||||||
|
|
||||||
|
@ -210,71 +210,72 @@ void load_saved_configuration()
|
||||||
LIST_INIT(ini_sections);
|
LIST_INIT(ini_sections);
|
||||||
LIST_INIT(ini_nyx_sections);
|
LIST_INIT(ini_nyx_sections);
|
||||||
|
|
||||||
// Load hekate configuration.
|
if (!ini_parse(&ini_sections, "bootloader/hekate_ipl.ini", false))
|
||||||
if (ini_parse(&ini_sections, "bootloader/hekate_ipl.ini", false))
|
goto skip_main_cfg_parse;
|
||||||
{
|
|
||||||
LIST_FOREACH_ENTRY(ini_sec_t, ini_sec, &ini_sections, link)
|
|
||||||
{
|
|
||||||
// Only parse config section.
|
|
||||||
if (ini_sec->type == INI_CHOICE && !strcmp(ini_sec->name, "config"))
|
|
||||||
{
|
|
||||||
LIST_FOREACH_ENTRY(ini_kv_t, kv, &ini_sec->kvs, link)
|
|
||||||
{
|
|
||||||
if (!strcmp("autoboot", kv->key))
|
|
||||||
h_cfg.autoboot = atoi(kv->val);
|
|
||||||
else if (!strcmp("autoboot_list", kv->key))
|
|
||||||
h_cfg.autoboot_list = atoi(kv->val);
|
|
||||||
else if (!strcmp("bootwait", kv->key))
|
|
||||||
h_cfg.bootwait = atoi(kv->val);
|
|
||||||
else if (!strcmp("backlight", kv->key))
|
|
||||||
{
|
|
||||||
h_cfg.backlight = atoi(kv->val);
|
|
||||||
if (h_cfg.backlight <= 20)
|
|
||||||
h_cfg.backlight = 30;
|
|
||||||
}
|
|
||||||
else if (!strcmp("autohosoff", kv->key))
|
|
||||||
h_cfg.autohosoff = atoi(kv->val);
|
|
||||||
else if (!strcmp("autonogc", kv->key))
|
|
||||||
h_cfg.autonogc = atoi(kv->val);
|
|
||||||
else if (!strcmp("updater2p", kv->key))
|
|
||||||
h_cfg.updater2p = atoi(kv->val);
|
|
||||||
else if (!strcmp("bootprotect", kv->key))
|
|
||||||
h_cfg.bootprotect = atoi(kv->val);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
// Load hekate configuration.
|
||||||
|
LIST_FOREACH_ENTRY(ini_sec_t, ini_sec, &ini_sections, link)
|
||||||
|
{
|
||||||
|
// Only parse config section.
|
||||||
|
if (ini_sec->type == INI_CHOICE && !strcmp(ini_sec->name, "config"))
|
||||||
|
{
|
||||||
|
LIST_FOREACH_ENTRY(ini_kv_t, kv, &ini_sec->kvs, link)
|
||||||
|
{
|
||||||
|
if (!strcmp("autoboot", kv->key))
|
||||||
|
h_cfg.autoboot = atoi(kv->val);
|
||||||
|
else if (!strcmp("autoboot_list", kv->key))
|
||||||
|
h_cfg.autoboot_list = atoi(kv->val);
|
||||||
|
else if (!strcmp("bootwait", kv->key))
|
||||||
|
h_cfg.bootwait = atoi(kv->val);
|
||||||
|
else if (!strcmp("backlight", kv->key))
|
||||||
|
{
|
||||||
|
h_cfg.backlight = atoi(kv->val);
|
||||||
|
if (h_cfg.backlight <= 20)
|
||||||
|
h_cfg.backlight = 30;
|
||||||
|
}
|
||||||
|
else if (!strcmp("autohosoff", kv->key))
|
||||||
|
h_cfg.autohosoff = atoi(kv->val);
|
||||||
|
else if (!strcmp("autonogc", kv->key))
|
||||||
|
h_cfg.autonogc = atoi(kv->val);
|
||||||
|
else if (!strcmp("updater2p", kv->key))
|
||||||
|
h_cfg.updater2p = atoi(kv->val);
|
||||||
|
else if (!strcmp("bootprotect", kv->key))
|
||||||
|
h_cfg.bootprotect = atoi(kv->val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load Nyx configuration.
|
skip_main_cfg_parse:
|
||||||
if (ini_parse(&ini_nyx_sections, "bootloader/nyx.ini", false))
|
if (!ini_parse(&ini_nyx_sections, "bootloader/nyx.ini", false))
|
||||||
{
|
return;
|
||||||
LIST_FOREACH_ENTRY(ini_sec_t, ini_sec, &ini_nyx_sections, link)
|
|
||||||
{
|
|
||||||
// Only parse config section.
|
|
||||||
if (ini_sec->type == INI_CHOICE && !strcmp(ini_sec->name, "config"))
|
|
||||||
{
|
|
||||||
LIST_FOREACH_ENTRY(ini_kv_t, kv, &ini_sec->kvs, link)
|
|
||||||
{
|
|
||||||
if (!strcmp("themecolor", kv->key))
|
|
||||||
n_cfg.themecolor = atoi(kv->val);
|
|
||||||
else if (!strcmp("timeoff", kv->key))
|
|
||||||
n_cfg.timeoff = strtol(kv->val, NULL, 16);
|
|
||||||
else if (!strcmp("homescreen", kv->key))
|
|
||||||
n_cfg.home_screen = atoi(kv->val);
|
|
||||||
else if (!strcmp("verification", kv->key))
|
|
||||||
n_cfg.verification = atoi(kv->val);
|
|
||||||
else if (!strcmp("umsemmcrw", kv->key))
|
|
||||||
n_cfg.ums_emmc_rw = atoi(kv->val) == 1;
|
|
||||||
else if (!strcmp("jcdisable", kv->key))
|
|
||||||
n_cfg.jc_disable = atoi(kv->val) == 1;
|
|
||||||
else if (!strcmp("bpmpclock", kv->key))
|
|
||||||
n_cfg.bpmp_clock = strtol(kv->val, NULL, 10);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
// Load Nyx configuration.
|
||||||
|
LIST_FOREACH_ENTRY(ini_sec_t, ini_sec, &ini_nyx_sections, link)
|
||||||
|
{
|
||||||
|
// Only parse config section.
|
||||||
|
if (ini_sec->type == INI_CHOICE && !strcmp(ini_sec->name, "config"))
|
||||||
|
{
|
||||||
|
LIST_FOREACH_ENTRY(ini_kv_t, kv, &ini_sec->kvs, link)
|
||||||
|
{
|
||||||
|
if (!strcmp("themecolor", kv->key))
|
||||||
|
n_cfg.themecolor = atoi(kv->val);
|
||||||
|
else if (!strcmp("timeoff", kv->key))
|
||||||
|
n_cfg.timeoff = strtol(kv->val, NULL, 16);
|
||||||
|
else if (!strcmp("homescreen", kv->key))
|
||||||
|
n_cfg.home_screen = atoi(kv->val);
|
||||||
|
else if (!strcmp("verification", kv->key))
|
||||||
|
n_cfg.verification = atoi(kv->val);
|
||||||
|
else if (!strcmp("umsemmcrw", kv->key))
|
||||||
|
n_cfg.ums_emmc_rw = atoi(kv->val) == 1;
|
||||||
|
else if (!strcmp("jcdisable", kv->key))
|
||||||
|
n_cfg.jc_disable = atoi(kv->val) == 1;
|
||||||
|
else if (!strcmp("bpmpclock", kv->key))
|
||||||
|
n_cfg.bpmp_clock = strtol(kv->val, NULL, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue