diff --git a/Makefile b/Makefile index abe123c..2fd89c6 100755 --- a/Makefile +++ b/Makefile @@ -10,6 +10,7 @@ SOURCEDIR := ipl OBJS = $(addprefix $(BUILD)/, \ start.o \ main.o \ + config.o \ btn.o \ clock.o \ cluster.o \ diff --git a/ipl/config.c b/ipl/config.c new file mode 100644 index 0000000..2951a55 --- /dev/null +++ b/ipl/config.c @@ -0,0 +1,437 @@ +/* +* Copyright (c) 2018 CTCaer +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see . +*/ + +#include +#include + +#include "btn.h" +#include "config.h" +#include "ff.h" +#include "ini.h" +#include "list.h" +#include "tui.h" +#include "util.h" +#include "gfx.h" + +extern gfx_ctxt_t gfx_ctxt; +extern gfx_con_t gfx_con; +//TODO: Create more macros (info, header, debug, etc) with different colors and utilize them for consistency. +#define EPRINTF(text) gfx_printf(&gfx_con, "%k"text"%k\n", 0xFFFF0000, 0xFFCCCCCC) +#define EPRINTFARGS(text, args...) gfx_printf(&gfx_con, "%k"text"%k\n", 0xFFFF0000, args, 0xFFCCCCCC) + +extern hekate_config h_cfg; +extern int sd_mount(); +extern int sd_unmount(); + +void set_default_configuration() +{ + h_cfg.autoboot = 0; + h_cfg.bootwait = 3; + h_cfg.customlogo = 0; + h_cfg.verification = 2; +} + +int create_config_entry() +{ + if (!sd_mount()) + return 1; + + char lbuf[16]; + FIL fp; + + LIST_INIT(ini_sections); + + if (ini_parse(&ini_sections, "hekate_ipl.ini")) + { + if (f_open(&fp, "hekate_ipl.ini", FA_WRITE | FA_CREATE_ALWAYS) != FR_OK) + return 0; + // Add config entry. + f_puts("[config]\nautoboot=", &fp); + itoa(h_cfg.autoboot, lbuf, 10); + f_puts(lbuf, &fp); + f_puts("\nbootwait=", &fp); + itoa(h_cfg.bootwait, lbuf, 10); + f_puts(lbuf, &fp); + f_puts("\ncustomlogo=", &fp); + itoa(h_cfg.customlogo, lbuf, 10); + f_puts(lbuf, &fp); + f_puts("\nverification=", &fp); + itoa(h_cfg.verification, lbuf, 10); + f_puts(lbuf, &fp); + f_puts("\n", &fp); + + // Re-construct existing entries. + LIST_FOREACH_ENTRY(ini_sec_t, ini_sec, &ini_sections, link) + { + if (!strcmp(ini_sec->name, "config")) + continue; + + switch (ini_sec->type) + { + case INI_CHOICE: // Re-construct Boot entry [ ]. + f_puts("[", &fp); + f_puts(ini_sec->name, &fp); + f_puts("]\n", &fp); + // Re-construct boot entry's config. + LIST_FOREACH_ENTRY(ini_kv_t, kv, &ini_sec->kvs, link) + { + f_puts(kv->key, &fp); + f_puts("=", &fp); + f_puts(kv->val, &fp); + f_puts("\n", &fp); + } + break; + case INI_CAPTION: // Re-construct caption entry { }. + f_puts("{", &fp); + f_puts(ini_sec->name, &fp); + f_puts("}\n", &fp); + break; + case INI_NEWLINE: // Re-construct cosmetic newline \n. + f_puts("\n", &fp); + break; + case INI_COMMENT: // Re-construct comment entry #. + f_puts("#", &fp); + f_puts(ini_sec->name, &fp); + f_puts("\n", &fp); + break; + } + } + + f_close(&fp); + sd_unmount(); + } + else + return 1; + + ini_free(&ini_sections); + + return 0; +} + +void config_autoboot() +{ + gfx_clear_grey(&gfx_ctxt, 0x1B); + gfx_con_setpos(&gfx_con, 0, 0); + + u32 *temp_autoboot = NULL; + + LIST_INIT(ini_sections); + + u8 max_entries = 29; + int ini_freed = 1; + + ment_t *ments = (ment_t *)malloc(sizeof(ment_t) * (max_entries + 3)); + u32 *boot_values = (u32 *)malloc(sizeof(u32) * max_entries); + char *boot_text = (char *)malloc(512 * max_entries); + + for (u32 j = 0; j < max_entries; j++) + boot_values[j] = j; + + if (sd_mount()) + { + if (ini_parse(&ini_sections, "hekate_ipl.ini")) + { + ini_freed = 0; + + // Build configuration menu. + ments[0].type = MENT_BACK; + ments[0].caption = "Back"; + + ments[1].type = MENT_CHGLINE; + + ments[2].type = MENT_CHOICE; + if (!h_cfg.autoboot) + ments[2].caption = "*Disable"; + else + ments[2].caption = " Disable"; + ments[2].data = &boot_values[0]; + + u32 i = 3; + 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")) + continue; + + if (strlen(ini_sec->name) > 510) + ments[i].caption = ini_sec->name; + else + { + if (h_cfg.autoboot != (i - 2)) + boot_text[(i - 2) * 512] = ' '; + + else + boot_text[(i - 2) * 512] = '*'; + memcpy(boot_text + (i - 2) * 512 + 1, ini_sec->name, strlen(ini_sec->name)); + boot_text[strlen(ini_sec->name) + (i - 2) * 512 + 1] = 0; + ments[i].caption = &boot_text[(i - 2) * 512]; + } + ments[i].type = ini_sec->type; + ments[i].data = &boot_values[i - 2]; + i++; + + if (i > max_entries) + break; + } + } + if (i < 4) + { + EPRINTF("No launch configurations found."); + goto out; + } + + memset(&ments[i], 0, sizeof(ment_t)); + menu_t menu = { + ments, "Disable or select entry to auto boot", 0, 0 + }; + temp_autoboot = (u32 *)tui_do_menu(&gfx_con, &menu); + if (temp_autoboot != NULL) + { + gfx_clear_grey(&gfx_ctxt, 0x1B); + gfx_con_setpos(&gfx_con, 0, 0); + + h_cfg.autoboot = *(u32 *)temp_autoboot; + // Save choice to ini file. + if (!create_config_entry()) + gfx_puts(&gfx_con, "\nConfiguration was saved!\n"); + else + EPRINTF("\nConfiguration saving failed!"); + gfx_puts(&gfx_con, "\nPress any key..."); + } + else + goto out2; + } + else + { + EPRINTF("Could not find or open 'hekate_ipl.ini'.\nMake sure it exists in SD Card!."); + goto out; + } + } + +out:; + btn_wait(); +out2:; + free(ments); + free(boot_values); + free(boot_text); + if (!ini_freed) + ini_free(&ini_sections); + + sd_unmount(); + + if (temp_autoboot == NULL) + return; +} + +void config_bootdelay() +{ + gfx_clear_grey(&gfx_ctxt, 0x1B); + gfx_con_setpos(&gfx_con, 0, 0); + + u32 delay_entries = 6; + + ment_t *ments = (ment_t *)malloc(sizeof(ment_t) * (delay_entries + 3)); + u32 *delay_values = (u32 *)malloc(sizeof(u32) * delay_entries); + char *delay_text = (char *)malloc(32 * delay_entries); + + for (u32 j = 0; j < delay_entries; j++) + delay_values[j] = j; + + ments[0].type = MENT_BACK; + ments[0].caption = "Back"; + + ments[1].type = MENT_CHGLINE; + + ments[2].type = MENT_CHOICE; + if (h_cfg.bootwait) + ments[2].caption = " 0 seconds (Bootlogo disabled)"; + else + ments[2].caption = "*0 seconds (Bootlogo disabled)"; + ments[2].data = &delay_values[0]; + + u32 i = 0; + for (i = 1; i < delay_entries; i++) + { + if (h_cfg.bootwait != i) + delay_text[i * 32] = ' '; + else + delay_text[i * 32] = '*'; + delay_text[i * 32 + 1] = i + '0'; + memcpy(delay_text + i * 32 + 2, " seconds\0", 9); + + ments[i + 2].type = MENT_CHOICE; + ments[i + 2].caption = delay_text + i * 32; + ments[i + 2].data = &delay_values[i]; + } + + memset(&ments[i + 2], 0, sizeof(ment_t)); + menu_t menu = { + ments, "Time delay for entering bootloader menu", 0, 0 + }; + + u32 *temp_bootwait = (u32 *)tui_do_menu(&gfx_con, &menu); + if (temp_bootwait != NULL) + { + gfx_clear_grey(&gfx_ctxt, 0x1B); + gfx_con_setpos(&gfx_con, 0, 0); + + h_cfg.bootwait = *(u32 *)temp_bootwait; + // Save choice to ini file. + if (!create_config_entry()) + gfx_puts(&gfx_con, "\nConfiguration was saved!\n"); + else + EPRINTF("\nConfiguration saving failed!"); + gfx_puts(&gfx_con, "\nPress any key..."); + } + + free(ments); + free(delay_values); + free(delay_text); + + if (temp_bootwait == NULL) + return; + btn_wait(); +} + +void config_customlogo() +{ + gfx_clear_grey(&gfx_ctxt, 0x1B); + gfx_con_setpos(&gfx_con, 0, 0); + + ment_t *ments = (ment_t *)malloc(sizeof(ment_t) * 5); + u32 *cb_values = (u32 *)malloc(sizeof(u32) * 2); + + for (u32 j = 0; j < 2; j++) + { + cb_values[j] = j; + ments[j + 2].type = MENT_CHOICE; + ments[j + 2].data = &cb_values[j]; + } + + ments[0].type = MENT_BACK; + ments[0].caption = "Back"; + + ments[1].type = MENT_CHGLINE; + + if (h_cfg.customlogo) + { + ments[2].caption = " Disable"; + ments[3].caption = "*Enable"; + + } + else + { + ments[2].caption = "*Disable"; + ments[3].caption = " Enable"; + } + + memset(&ments[4], 0, sizeof(ment_t)); + menu_t menu = { + ments, "Custom bootlogo", 0, 0 + }; + + u32 *temp_customlogo = (u32 *)tui_do_menu(&gfx_con, &menu); + if (temp_customlogo != NULL) + { + gfx_clear_grey(&gfx_ctxt, 0x1B); + gfx_con_setpos(&gfx_con, 0, 0); + + h_cfg.customlogo = *(u32 *)temp_customlogo; + // Save choice to ini file. + if (!create_config_entry()) + gfx_puts(&gfx_con, "\nConfiguration was saved!\n"); + else + EPRINTF("\nConfiguration saving failed!"); + gfx_puts(&gfx_con, "\nPress any key..."); + } + + free(ments); + free(cb_values); + + if (temp_customlogo == NULL) + return; + btn_wait(); +} + +void config_verification() +{ + gfx_clear_grey(&gfx_ctxt, 0x1B); + gfx_con_setpos(&gfx_con, 0, 0); + + ment_t *ments = (ment_t *)malloc(sizeof(ment_t) * 6); + u32 *vr_values = (u32 *)malloc(sizeof(u32) * 3); + char *vr_text = (char *)malloc(64 * 3); + + for (u32 j = 0; j < 3; j++) + { + vr_values[j] = j; + ments[j + 2].type = MENT_CHOICE; + ments[j + 2].data = &vr_values[j]; + } + + ments[0].type = MENT_BACK; + ments[0].caption = "Back"; + + ments[1].type = MENT_CHGLINE; + + memcpy(vr_text, " Disable\0", 9); + memcpy(vr_text + 64, " Sparse (Fast - Not reliable)\0", 31); + memcpy(vr_text + 128, " Full (Slow - 100% reliable)\0", 31); + + for (u32 i = 0; i < 3; i++) + { + if (h_cfg.verification != i) + { + vr_text[64 * i] = ' '; + ments[2 + i].caption = vr_text + (i * 64); + } + else + { + vr_text[64 * i] = '*'; + ments[2 + i].caption = vr_text + (i * 64); + } + } + + memset(&ments[5], 0, sizeof(ment_t)); + menu_t menu = { + ments, "Backup & Restore verification", 0, 0 + }; + + u32 *temp_verification = (u32 *)tui_do_menu(&gfx_con, &menu); + if (temp_verification != NULL) + { + gfx_clear_grey(&gfx_ctxt, 0x1B); + gfx_con_setpos(&gfx_con, 0, 0); + + h_cfg.verification = *(u32 *)temp_verification; + // Save choice to ini file. + if (!create_config_entry()) + gfx_puts(&gfx_con, "\nConfiguration was saved!\n"); + else + EPRINTF("\nConfiguration saving failed!"); + gfx_puts(&gfx_con, "\nPress any key..."); + } + + free(ments); + free(vr_values); + free(vr_text); + + if (temp_verification == NULL) + return; + btn_wait(); +} diff --git a/ipl/config.h b/ipl/config.h new file mode 100644 index 0000000..6be3f5b --- /dev/null +++ b/ipl/config.h @@ -0,0 +1,37 @@ +/* +* Copyright (c) 2018 CTCaer +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see . +*/ + +#ifndef _CONFIG_H_ +#define _CONFIG_H_ + +#include "types.h" + +typedef struct _hekate_config +{ + u32 autoboot; + u32 bootwait; + u32 customlogo; + u32 verification; +}hekate_config; + +void set_default_configuration(); +int create_config_entry(); +void config_autoboot(); +void config_bootdelay(); +void config_customlogo(); +void config_verification(); + +#endif /* _CONFIG_H_ */ diff --git a/ipl/main.c b/ipl/main.c index 9b3e985..98804ae 100755 --- a/ipl/main.c +++ b/ipl/main.c @@ -54,6 +54,7 @@ #include "lz.h" #include "max17050.h" #include "bq24193.h" +#include "config.h" //TODO: ugly. gfx_ctxt_t gfx_ctxt; @@ -75,6 +76,8 @@ int sd_mounted; u8 *Kc_MENU_LOGO; #endif //MENU_LOGO_ENABLE +hekate_config h_cfg; + int sd_mount() { if (sd_mounted) @@ -752,8 +755,8 @@ int dump_emmc_verify(sdmmc_storage_t *storage, u32 lba_curr, char* outFilename, f_close(&fp); return 1; } - //TODO: Replace 2 with config variable - switch (2) + + switch (h_cfg.verification) { case 1: res = memcmp32sparse((u32 *)bufEm, (u32 *)bufSd, num << 9); @@ -948,8 +951,7 @@ int dump_emmc_part(char *sd_path, sdmmc_storage_t *storage, emmc_part_t *part) memset(&fp, 0, sizeof(fp)); currPartIdx++; - //TODO: Replace with the config check. - if (1) + if (h_cfg.verification) { // Verify part. if (dump_emmc_verify(storage, lbaStartPart, outFilename, part)) @@ -1073,8 +1075,7 @@ int dump_emmc_part(char *sd_path, sdmmc_storage_t *storage, emmc_part_t *part) free(buf); f_close(&fp); - //TODO: Replace with the config check. - if (1) + if (h_cfg.verification) { // Verify last part or single file backup. if (dump_emmc_verify(storage, lbaStartPart, outFilename, part)) @@ -1217,7 +1218,7 @@ static void dump_emmc_selected(emmcPartType_t dumpType) timer = get_tmr_s() - timer; gfx_printf(&gfx_con, "Time taken: %dm %ds.\n", timer / 60, timer % 60); sdmmc_storage_end(&storage); - if (res && 1) //TODO: Replace with the config check. + if (res && h_cfg.verification) gfx_printf(&gfx_con, "\n%kFinished and verified!%k\nPress any key...\n",0xFF96FF00, 0xFFCCCCCC); else if (res) gfx_printf(&gfx_con, "\nFinished! Press any key...\n"); @@ -1855,7 +1856,7 @@ void about() btn_wait(); } -/*ment_t ment_options[] = { +ment_t ment_options[] = { MDEF_BACK(), MDEF_CHGLINE(), MDEF_HANDLER("Auto boot", config_autoboot), @@ -1867,7 +1868,7 @@ void about() menu_t menu_options = { ment_options, "Launch options", 0, 0 -};*/ +}; ment_t ment_cinfo[] = { MDEF_BACK(), @@ -1953,7 +1954,7 @@ ment_t ment_tools[] = { MDEF_CAPTION("-- Backup & Restore --", 0xFF0AB9E6), MDEF_MENU("Backup", &menu_backup), //MDEF_MENU("Restore", &menu_restore), - //MDEF_HANDLER("Verification options", config_verification), + MDEF_HANDLER("Verification options", config_verification), MDEF_CHGLINE(), MDEF_CAPTION("-------- Misc --------", 0xFF0AB9E6), MDEF_HANDLER("Dump package1", dump_package1), @@ -1974,7 +1975,7 @@ menu_t menu_tools = { ment_t ment_top[] = { MDEF_HANDLER("Launch firmware", launch_firmware), - //MDEF_MENU("Launch options", &menu_options), + MDEF_MENU("Launch options", &menu_options), MDEF_CAPTION("---------------", 0xFF444444), MDEF_MENU("Tools", &menu_tools), MDEF_MENU("Console info", &menu_cinfo), @@ -2021,6 +2022,7 @@ void ipl_main() // Enable backlight after initializing gfx display_backlight(1); + set_default_configuration(); while (1) tui_do_menu(&gfx_con, &menu_top);