From 250f068211baa09b12e0973824d2894321aa2ebf Mon Sep 17 00:00:00 2001 From: shchmue Date: Tue, 17 Sep 2019 09:51:30 -0600 Subject: [PATCH] Add menu and option to dump keys from emuMMC --- source/config/config.c | 614 ------------------------------------- source/config/config.h | 7 - source/gfx/tui.c | 227 ++++++++++++++ source/gfx/tui.h | 66 ++++ source/keys/keys.c | 46 +-- source/libs/fatfs/diskio.c | 5 +- source/libs/fatfs/ffconf.h | 6 +- source/main.c | 84 ++++- source/power/max17050.c | 5 + source/storage/emummc.c | 266 ++++++++++++++++ source/storage/emummc.h | 59 ++++ source/storage/nx_emmc.c | 5 +- source/utils/types.h | 4 + 13 files changed, 726 insertions(+), 668 deletions(-) create mode 100644 source/gfx/tui.c create mode 100644 source/gfx/tui.h create mode 100644 source/storage/emummc.c create mode 100644 source/storage/emummc.h diff --git a/source/config/config.c b/source/config/config.c index f9df696..2fa964b 100644 --- a/source/config/config.c +++ b/source/config/config.c @@ -20,7 +20,6 @@ #include "config.h" #include "ini.h" #include "../gfx/gfx.h" -#include "../gfx/tui.h" #include "../libs/fatfs/ff.h" #include "../soc/t210.h" #include "../storage/sdmmc.h" @@ -53,616 +52,3 @@ void set_default_configuration() sd_power_cycle_time_start = 0xFFFFFFF; } -int create_config_entry() -{ - if (!sd_mount()) - return 1; - - char lbuf[32]; - FIL fp; - bool mainIniFound = false; - - LIST_INIT(ini_sections); - - if (ini_parse(&ini_sections, "bootloader/hekate_ipl.ini", false)) - mainIniFound = true; - else - { - u8 res = f_open(&fp, "bootloader/hekate_ipl.ini", FA_READ); - if (res == FR_NO_FILE || res == FR_NO_PATH) - { - f_mkdir("bootloader"); - f_mkdir("bootloader/ini"); - f_mkdir("bootloader/payloads"); - f_mkdir("bootloader/sys"); - } - else - { - if (!res) - f_close(&fp); - return 1; - } - } - - if (f_open(&fp, "bootloader/hekate_ipl.ini", FA_WRITE | FA_CREATE_ALWAYS) != FR_OK) - return 1; - // Add config entry. - f_puts("[config]\nautoboot=", &fp); - itoa(h_cfg.autoboot, lbuf, 10); - f_puts(lbuf, &fp); - f_puts("\nautoboot_list=", &fp); - itoa(h_cfg.autoboot_list, lbuf, 10); - f_puts(lbuf, &fp); - f_puts("\nbootwait=", &fp); - itoa(h_cfg.bootwait, lbuf, 10); - f_puts(lbuf, &fp); - f_puts("\nverification=", &fp); - itoa(h_cfg.verification, lbuf, 10); - f_puts(lbuf, &fp); - f_puts("\nbacklight=", &fp); - itoa(h_cfg.backlight, lbuf, 10); - f_puts(lbuf, &fp); - f_puts("\nautohosoff=", &fp); - itoa(h_cfg.autohosoff, lbuf, 10); - f_puts(lbuf, &fp); - f_puts("\nautonogc=", &fp); - itoa(h_cfg.autonogc, lbuf, 10); - f_puts(lbuf, &fp); - if (h_cfg.brand) - { - f_puts("\nbrand=", &fp); - f_puts(h_cfg.brand, &fp); - } - if (h_cfg.tagline) - { - f_puts("\ntagline=", &fp); - f_puts(h_cfg.tagline, &fp); - } - f_puts("\n", &fp); - - if (mainIniFound) - { - // 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(); - - return 0; -} - -#pragma GCC push_options -#pragma GCC optimize ("Os") - -static void _save_config() -{ - gfx_clear_grey(0x1B); - gfx_con_setpos(0, 0); - - if (!create_config_entry()) - gfx_puts("\nConfiguration was saved!\n"); - else - EPRINTF("\nConfiguration saving failed!"); - gfx_puts("\nPress any key..."); -} - -static void _config_autoboot_list(void *ent) -{ - gfx_clear_grey(0x1B); - gfx_con_setpos(0, 0); - - u32 *temp_autoboot = NULL; - - LIST_INIT(ini_sections); - - u8 max_entries = 30; - - 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, "bootloader/ini", true)) - { - // Build configuration menu. - 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_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 - 1) || !h_cfg.autoboot_list) - boot_text[(i - 1) * 512] = ' '; - - else - boot_text[(i - 1) * 512] = '*'; - memcpy(boot_text + (i - 1) * 512 + 1, ini_sec->name, strlen(ini_sec->name) + 1); - boot_text[strlen(ini_sec->name) + (i - 1) * 512 + 1] = 0; - ments[i].caption = &boot_text[(i - 1) * 512]; - } - ments[i].type = ini_sec->type; - ments[i].data = &boot_values[i - 1]; - i++; - - if ((i - 1) > max_entries) - break; - } - } - - memset(&ments[i], 0, sizeof(ment_t)); - menu_t menu = {ments, "Select an entry to auto boot", 0, 0}; - temp_autoboot = (u32 *)tui_do_menu(&menu); - if (temp_autoboot != NULL) - { - h_cfg.autoboot = *(u32 *)temp_autoboot; - h_cfg.autoboot_list = 1; - _save_config(); - - ment_t *tmp = (ment_t *)ent; - tmp->data = NULL; - } - else - goto out2; - } - else - { - EPRINTF("Could not open 'bootloader/hekate_ipl.ini'.\nMake sure it exists!."); - goto out; - } - } - -out:; - btn_wait(); -out2:; - free(ments); - free(boot_values); - free(boot_text); - - sd_unmount(); -} - -void config_autoboot() -{ - gfx_clear_grey(0x1B); - gfx_con_setpos(0, 0); - - u32 *temp_autoboot = NULL; - - LIST_INIT(ini_sections); - - u8 max_entries = 30; - - ment_t *ments = (ment_t *)malloc(sizeof(ment_t) * (max_entries + 5)); - 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, "bootloader/hekate_ipl.ini", false)) - { - // Build configuration menu. - ments[0].type = MENT_BACK; - ments[0].caption = "Back"; - - ments[1].type = MENT_CHGLINE; - - ments[2].type = MENT_DATA; - if (!h_cfg.autoboot) - ments[2].caption = "*Disable"; - else - ments[2].caption = " Disable"; - ments[2].data = &boot_values[0]; - - ments[3].type = MENT_HDLR_RE; - if (h_cfg.autoboot_list) - ments[3].caption = "*More configs..."; - else - ments[3].caption = " More configs..."; - ments[3].handler = _config_autoboot_list; - ments[3].data = (void *)0xCAFE; - - ments[4].type = MENT_CHGLINE; - - u32 i = 5; - 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 - 4) || h_cfg.autoboot_list) - boot_text[(i - 4) * 512] = ' '; - - else - boot_text[(i - 4) * 512] = '*'; - memcpy(boot_text + (i - 4) * 512 + 1, ini_sec->name, strlen(ini_sec->name) + 1); - boot_text[strlen(ini_sec->name) + (i - 4) * 512 + 1] = 0; - ments[i].caption = &boot_text[(i - 4) * 512]; - } - ments[i].type = ini_sec->type; - ments[i].data = &boot_values[i - 4]; - i++; - - if ((i - 4) > max_entries) - break; - } - } - if (i < 6 && !h_cfg.autoboot_list) - { - ments[i].type = MENT_CAPTION; - ments[i].caption = "No main configurations found..."; - ments[i].color = 0xFFFFDD00; - i++; - } - - 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(&menu); - if (temp_autoboot != NULL) - { - h_cfg.autoboot = *(u32 *)temp_autoboot; - h_cfg.autoboot_list = 0; - _save_config(); - } - else - goto out2; - } - else - { - EPRINTF("Could not open 'bootloader/hekate_ipl.ini'.\nMake sure it exists!."); - goto out; - } - } - -out:; - btn_wait(); -out2:; - free(ments); - free(boot_values); - free(boot_text); - - sd_unmount(); - - if (temp_autoboot == NULL) - return; -} - -void config_bootdelay() -{ - gfx_clear_grey(0x1B); - gfx_con_setpos(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_DATA; - 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", 9); - - ments[i + 2].type = MENT_DATA; - 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(&menu); - if (temp_bootwait != NULL) - { - h_cfg.bootwait = *(u32 *)temp_bootwait; - _save_config(); - } - - free(ments); - free(delay_values); - free(delay_text); - - if (temp_bootwait == NULL) - return; - btn_wait(); -} - -void config_verification() -{ - gfx_clear_grey(0x1B); - gfx_con_setpos(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_DATA; - 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 (Fastest - Unsafe)", 28); - memcpy(vr_text + 64, " Sparse (Fast - Safe)", 23); - memcpy(vr_text + 128, " Full (Slow - Safe)", 23); - - for (u32 i = 0; i < 3; i++) - { - if (h_cfg.verification != i) - vr_text[64 * i] = ' '; - 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(&menu); - if (temp_verification != NULL) - { - h_cfg.verification = *(u32 *)temp_verification; - _save_config(); - } - - free(ments); - free(vr_values); - free(vr_text); - - if (temp_verification == NULL) - return; - btn_wait(); -} - -void config_backlight() -{ - gfx_clear_grey(0x1B); - gfx_con_setpos(0, 0); - - u32 bri_entries = 11; - - ment_t *ments = (ment_t *)malloc(sizeof(ment_t) * (bri_entries + 3)); - u32 *bri_values = (u32 *)malloc(sizeof(u32) * bri_entries); - char *bri_text = (char *)malloc(8 * bri_entries); - - for (u32 j = 1; j < bri_entries; j++) - bri_values[j] = j * 10; - - ments[0].type = MENT_BACK; - ments[0].caption = "Back"; - - ments[1].type = MENT_CHGLINE; - - u32 i = 0; - for (i = 1; i < bri_entries; i++) - { - if ((h_cfg.backlight / 20) != i) - bri_text[i * 32] = ' '; - else - bri_text[i * 32] = '*'; - - if (i < 10) - { - bri_text[i * 32 + 1] = i + '0'; - memcpy(bri_text + i * 32 + 2, "0%", 3); - } - else - memcpy(bri_text + i * 32 + 1, "100%", 5); - - ments[i + 1].type = MENT_DATA; - ments[i + 1].caption = bri_text + i * 32; - ments[i + 1].data = &bri_values[i]; - } - - memset(&ments[i + 1], 0, sizeof(ment_t)); - menu_t menu = {ments, "Backlight brightness", 0, 0}; - - u32 *temp_backlight = (u32 *)tui_do_menu(&menu); - if (temp_backlight != NULL) - { - h_cfg.backlight = (*(u32 *)temp_backlight) * 2; - _save_config(); - } - - free(ments); - free(bri_values); - free(bri_text); - - if (temp_backlight == NULL) - return; - btn_wait(); -} - -void config_auto_hos_poweroff() -{ - gfx_clear_grey(0x1B); - gfx_con_setpos(0, 0); - - ment_t *ments = (ment_t *)malloc(sizeof(ment_t) * 6); - u32 *hp_values = (u32 *)malloc(sizeof(u32) * 3); - - for (u32 j = 0; j < 3; j++) - { - hp_values[j] = j; - ments[j + 2].type = MENT_DATA; - ments[j + 2].data = &hp_values[j]; - } - - ments[0].type = MENT_BACK; - ments[0].caption = "Back"; - - ments[1].type = MENT_CHGLINE; - - if (h_cfg.autohosoff == 1) - { - ments[2].caption = " Disable"; - ments[3].caption = "*Enable"; - ments[4].caption = " Enable (No logo)"; - } - else if (h_cfg.autohosoff >= 2) - { - ments[2].caption = " Disable"; - ments[3].caption = " Enable"; - ments[4].caption = "*Enable (No logo)"; - } - else - { - ments[2].caption = "*Disable"; - ments[3].caption = " Enable"; - ments[4].caption = " Enable (No logo)"; - } - - memset(&ments[5], 0, sizeof(ment_t)); - menu_t menu = {ments, "Power off if woke up from HOS", 0, 0}; - - u32 *temp_autohosoff = (u32 *)tui_do_menu(&menu); - if (temp_autohosoff != NULL) - { - h_cfg.autohosoff = *(u32 *)temp_autohosoff; - _save_config(); - } - - free(ments); - free(hp_values); - - if (temp_autohosoff == NULL) - return; - btn_wait(); -} - -void config_nogc() -{ - gfx_clear_grey(0x1B); - gfx_con_setpos(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_DATA; - ments[j + 2].data = &cb_values[j]; - } - - ments[0].type = MENT_BACK; - ments[0].caption = "Back"; - - ments[1].type = MENT_CHGLINE; - - if (h_cfg.autonogc) - { - ments[2].caption = " Disable"; - ments[3].caption = "*Auto"; - } - else - { - ments[2].caption = "*Disable"; - ments[3].caption = " Auto"; - } - - memset(&ments[4], 0, sizeof(ment_t)); - menu_t menu = {ments, "No Gamecard", 0, 0}; - - u32 *temp_nogc = (u32 *)tui_do_menu(&menu); - if (temp_nogc != NULL) - { - h_cfg.autonogc = *(u32 *)temp_nogc; - _save_config(); - } - - free(ments); - free(cb_values); - - if (temp_nogc == NULL) - return; - btn_wait(); -} - -#pragma GCC pop_options diff --git a/source/config/config.h b/source/config/config.h index 8cd34e1..1f6c36d 100644 --- a/source/config/config.h +++ b/source/config/config.h @@ -46,12 +46,5 @@ typedef enum } hsysmodule_t; void set_default_configuration(); -int create_config_entry(); -void config_autoboot(); -void config_bootdelay(); -void config_verification(); -void config_backlight(); -void config_auto_hos_poweroff(); -void config_nogc(); #endif /* _CONFIG_H_ */ diff --git a/source/gfx/tui.c b/source/gfx/tui.c new file mode 100644 index 0000000..4960c8c --- /dev/null +++ b/source/gfx/tui.c @@ -0,0 +1,227 @@ +/* + * Copyright (c) 2018 naehrwert + * 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 "di.h" +#include "tui.h" +#include "../utils/btn.h" +#include "../config/config.h" +#include "../power/max17050.h" +#include "../utils/util.h" + +#ifdef MENU_LOGO_ENABLE +extern u8 *Kc_MENU_LOGO; +#define X_MENU_LOGO 119 +#define Y_MENU_LOGO 57 +#define X_POS_MENU_LOGO 577 +#define Y_POS_MENU_LOGO 1179 +#endif //MENU_LOGO_ENABLE + +extern hekate_config h_cfg; + +void tui_sbar(bool force_update) +{ + u32 cx, cy; + + u32 timePassed = get_tmr_s() - h_cfg.sbar_time_keeping; + if (!force_update) + if (timePassed < 5) + return; + + u8 prevFontSize = gfx_con.fntsz; + gfx_con.fntsz = 16; + h_cfg.sbar_time_keeping = get_tmr_s(); + + u32 battPercent = 0; + int battVoltCurr = 0; + + gfx_con_getpos(&cx, &cy); + gfx_con_setpos(0, 1260); + + max17050_get_property(MAX17050_RepSOC, (int *)&battPercent); + max17050_get_property(MAX17050_VCELL, &battVoltCurr); + + gfx_clear_partial_grey(0x30, 1256, 24); + gfx_printf("%K%k Battery: %d.%d%% (%d mV) - Charge:", 0xFF303030, 0xFF888888, + (battPercent >> 8) & 0xFF, (battPercent & 0xFF) / 26, battVoltCurr); + + max17050_get_property(MAX17050_Current, &battVoltCurr); + + if (battVoltCurr >= 0) + gfx_printf(" %k+%d mA%k%K\n", + 0xFF008800, battVoltCurr / 1000, 0xFFCCCCCC, 0xFF1B1B1B); + else + gfx_printf(" %k-%d mA%k%K\n", + 0xFF880000, (~battVoltCurr) / 1000, 0xFFCCCCCC, 0xFF1B1B1B); + gfx_con.fntsz = prevFontSize; + gfx_con_setpos(cx, cy); +} + +void tui_pbar(int x, int y, u32 val, u32 fgcol, u32 bgcol) +{ + u32 cx, cy; + if (val > 200) + val = 200; + + gfx_con_getpos(&cx, &cy); + + gfx_con_setpos(x, y); + + gfx_printf("%k[%3d%%]%k", fgcol, val, 0xFFCCCCCC); + + x += 7 * gfx_con.fntsz; + + for (int i = 0; i < (gfx_con.fntsz >> 3) * 6; i++) + { + gfx_line(x, y + i + 1, x + 3 * val, y + i + 1, fgcol); + gfx_line(x + 3 * val, y + i + 1, x + 3 * 100, y + i + 1, bgcol); + } + + gfx_con_setpos(cx, cy); + + // Update status bar. + tui_sbar(false); +} + +void *tui_do_menu(menu_t *menu) +{ + int idx = 0, prev_idx = 0, cnt = 0x7FFFFFFF; + + gfx_clear_partial_grey(0x1B, 0, 1256); + tui_sbar(true); + +#ifdef MENU_LOGO_ENABLE + gfx_set_rect_rgb(Kc_MENU_LOGO, + X_MENU_LOGO, Y_MENU_LOGO, X_POS_MENU_LOGO, Y_POS_MENU_LOGO); +#endif //MENU_LOGO_ENABLE + + while (true) + { + gfx_con_setcol(0xFFCCCCCC, 1, 0xFF1B1B1B); + gfx_con_setpos(menu->x, menu->y); + gfx_printf("[%kLo%kck%kpi%kck%k_R%kCM%k v%d.%d.%d%k]\n\n", + colors[0], colors[1], colors[2], colors[3], colors[4], colors[5], 0xFFFF00FF, LP_VER_MJ, LP_VER_MN, LP_VER_BF, 0xFFCCCCCC); + + // Skip caption or seperator lines selection. + while (menu->ents[idx].type == MENT_CAPTION || + menu->ents[idx].type == MENT_CHGLINE) + { + if (prev_idx <= idx || (!idx && prev_idx == cnt - 1)) + { + idx++; + if (idx > (cnt - 1)) + { + idx = 0; + prev_idx = 0; + } + } + else + { + idx--; + if (idx < 0) + { + idx = cnt - 1; + prev_idx = cnt; + } + } + } + prev_idx = idx; + + // Draw the menu. + for (cnt = 0; menu->ents[cnt].type != MENT_END; cnt++) + { + if (cnt == idx) + gfx_con_setcol(0xFF1B1B1B, 1, 0xFFCCCCCC); + else + gfx_con_setcol(0xFFCCCCCC, 1, 0xFF1B1B1B); + // if (menu->ents[cnt].type == MENT_CAPTION) + // gfx_printf("%k %s", menu->ents[cnt].color, menu->ents[cnt].caption); + if (menu->ents[cnt].type != MENT_CHGLINE) { + if (cnt == idx) + gfx_printf(" %s", menu->ents[cnt].caption); + else + gfx_printf("%k %s", menu->ents[cnt].color, menu->ents[cnt].caption);//gfx_printf(" %s", menu->ents[cnt].caption); + } + if(menu->ents[cnt].type == MENT_MENU) + gfx_printf("%k...", 0xFF0099EE); + gfx_printf(" \n"); + } + gfx_con_setcol(0xFFCCCCCC, 1, 0xFF1B1B1B); + gfx_putc('\n'); + + // Print help and battery status. + gfx_con_setpos(0, 1127); + if (h_cfg.emummc_force_disable) + gfx_printf("%kNo emuMMC config found.\n", 0xFF800000); + gfx_con_setpos(0, 1191); + gfx_printf("%k VOL: Move up/down\n PWR: Select option%k", 0xFF555555, 0xFFCCCCCC); + + display_backlight_brightness(h_cfg.backlight, 1000); + + // Wait for user command. + u32 btn = btn_wait(); + + if (btn & BTN_VOL_DOWN && idx < (cnt - 1)) + idx++; + else if (btn & BTN_VOL_DOWN && idx == (cnt - 1)) + { + idx = 0; + prev_idx = -1; + } + if (btn & BTN_VOL_UP && idx > 0) + idx--; + else if (btn & BTN_VOL_UP && idx == 0) + { + idx = cnt - 1; + prev_idx = cnt; + } + if (btn & BTN_POWER) + { + ment_t *ent = &menu->ents[idx]; + switch (ent->type) + { + case MENT_HANDLER: + ent->handler(ent->data); + break; + case MENT_MENU: + return tui_do_menu(ent->menu); + break; + case MENT_DATA: + return ent->data; + break; + case MENT_BACK: + return NULL; + break; + case MENT_HDLR_RE: + ent->handler(ent); + if (!ent->data) + return NULL; + break; + default: + break; + } + gfx_con.fntsz = 16; + gfx_clear_partial_grey(0x1B, 0, 1256); +#ifdef MENU_LOGO_ENABLE + gfx_set_rect_rgb(Kc_MENU_LOGO, + X_MENU_LOGO, Y_MENU_LOGO, X_POS_MENU_LOGO, Y_POS_MENU_LOGO); +#endif //MENU_LOGO_ENABLE + } + tui_sbar(false); + } + + return NULL; +} diff --git a/source/gfx/tui.h b/source/gfx/tui.h new file mode 100644 index 0000000..2b7d3f7 --- /dev/null +++ b/source/gfx/tui.h @@ -0,0 +1,66 @@ +/* +* Copyright (c) 2018 naehrwert +* 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 _TUI_H_ +#define _TUI_H_ + +#include "../utils/types.h" +#include "gfx.h" + +#define MENT_END 0 +#define MENT_HANDLER 1 +#define MENT_MENU 2 +#define MENT_DATA 3 +#define MENT_BACK 4 +#define MENT_CAPTION 5 +#define MENT_CHGLINE 6 +#define MENT_HDLR_RE 7 + +typedef struct _ment_t +{ + u32 type; + const char *caption; + u32 color; + void *data; + union + { + void(*handler)(void *); + struct _menu_t *menu; + }; +} ment_t; + +typedef struct _menu_t +{ + ment_t *ents; + const char *caption; + u32 x; + u32 y; +} menu_t; + +#define MDEF_END() {MENT_END} +#define MDEF_HANDLER(caption, _handler, color) { MENT_HANDLER, caption, color, NULL, { .handler = _handler } } +#define MDEF_HANDLER_EX(caption, data, _handler, color) { MENT_HANDLER, caption, color, data, { .handler = _handler } } +#define MDEF_MENU(caption, _menu) { MENT_MENU, caption, 0, NULL, { .menu = _menu } } +#define MDEF_BACK() { MENT_BACK, "Back" } +#define MDEF_CAPTION(caption, color) { MENT_CAPTION, caption, color } +#define MDEF_CHGLINE() {MENT_CHGLINE} + +void tui_sbar(bool force_update); +void tui_pbar(int x, int y, u32 val, u32 fgcol, u32 bgcol); +void *tui_do_menu(menu_t *menu); + +#endif diff --git a/source/keys/keys.c b/source/keys/keys.c index 6572449..6c25aec 100644 --- a/source/keys/keys.c +++ b/source/keys/keys.c @@ -19,6 +19,7 @@ #include "../config/config.h" #include "../gfx/di.h" #include "../gfx/gfx.h" +#include "../gfx/tui.h" #include "../hos/pkg1.h" #include "../hos/pkg2.h" #include "../hos/sept.h" @@ -32,6 +33,7 @@ #include "../soc/fuse.h" #include "../soc/smmu.h" #include "../soc/t210.h" +#include "../storage/emummc.h" #include "../storage/nx_emmc.h" #include "../storage/sdmmc.h" #include "../utils/btn.h" @@ -91,8 +93,6 @@ static u8 temp_key[0x10], package2_key[KB_FIRMWARE_VERSION_MAX+1][0x10] = {0}, titlekek[KB_FIRMWARE_VERSION_MAX+1][0x10] = {0}; -static const u32 colors[6] = {COLOR_RED, COLOR_ORANGE, COLOR_YELLOW, COLOR_GREEN, COLOR_BLUE, COLOR_VIOLET}; - // key functions static bool _key_exists(const void *data) { return memcmp(data, zeros, 0x10); }; static void _save_key(const char *name, const void *data, const u32 len, char *outbuf); @@ -105,26 +105,27 @@ static void _update_ctr(u8 *ctr, u32 ofs); void dump_keys() { display_backlight_brightness(100, 1000); - gfx_clear_grey(0x1B); + gfx_clear_partial_grey(0x1B, 0, 1256); gfx_con_setpos(0, 0); gfx_printf("[%kLo%kck%kpi%kck%k_R%kCM%k v%d.%d.%d%k]\n\n", colors[0], colors[1], colors[2], colors[3], colors[4], colors[5], 0xFFFF00FF, LP_VER_MJ, LP_VER_MN, LP_VER_BF, 0xFFCCCCCC); start_time = get_tmr_us(); + u32 begin_time = get_tmr_us(); u32 retries = 0; u32 color_idx = 0; tsec_ctxt_t tsec_ctxt; sdmmc_t sdmmc; - sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_4, SDMMC_BUS_WIDTH_8, 4); + emummc_storage_init_mmc(&storage, &sdmmc); TPRINTFARGS("%kMMC init... ", colors[(color_idx++) % 6]); // Read package1. u8 *pkg1 = (u8 *)malloc(0x40000); - sdmmc_storage_set_mmc_partition(&storage, 1); - sdmmc_storage_read(&storage, 0x100000 / NX_EMMC_BLOCKSIZE, 0x40000 / NX_EMMC_BLOCKSIZE, pkg1); + emummc_storage_set_mmc_partition(&storage, 1); + emummc_storage_read(&storage, 0x100000 / NX_EMMC_BLOCKSIZE, 0x40000 / NX_EMMC_BLOCKSIZE, pkg1); const pkg1_id_t *pkg1_id = pkg1_identify(pkg1); if (!pkg1_id) { EPRINTF("Unknown pkg1 version."); @@ -154,6 +155,7 @@ void dump_keys() { } if (pkg1_id->kb >= KB_FIRMWARE_VERSION_700) { + sd_mount(); if (!f_stat("sd:/sept/payload.bak", NULL)) { f_unlink("sd:/sept/payload.bin"); f_rename("sd:/sept/payload.bak", "sd:/sept/payload.bin"); @@ -277,7 +279,7 @@ get_tsec: ; } // verify keyblob is not corrupt - sdmmc_storage_read(&storage, 0x180000 / NX_EMMC_BLOCKSIZE + i, 1, keyblob_block); + emummc_storage_read(&storage, 0x180000 / NX_EMMC_BLOCKSIZE + i, 1, keyblob_block); se_aes_key_set(3, keyblob_mac_key[i], 0x10); se_aes_cmac(3, keyblob_mac, 0x10, keyblob_block + 0x10, 0xa0); if (memcmp(keyblob_block, keyblob_mac, 0x10)) { @@ -336,7 +338,7 @@ get_tsec: ; u8 *pkg2 = NULL; pkg2_kip1_info_t *ki = NULL; - sdmmc_storage_set_mmc_partition(&storage, 0); + emummc_storage_set_mmc_partition(&storage, 0); // Parse eMMC GPT. LIST_INIT(gpt); nx_emmc_gpt_parse(&gpt, &storage); @@ -380,7 +382,7 @@ get_tsec: ; EPRINTF("Failed to derive Package2 key."); goto pkg2_done; } else if (pkg2_kb != pkg1_id->kb) - EPRINTF("Warning: Package1-Package2 mismatch."); + EPRINTFARGS("Warning! Package1-Package2 mismatch: %d, %d", pkg1_id->kb, pkg2_kb); pkg2_hdr = pkg2_decrypt(pkg2); if (!pkg2_hdr) { @@ -749,7 +751,7 @@ pkg2_done: dismount: f_mount(NULL, "emmc:", 1); nx_emmc_gpt_free(&gpt); - sdmmc_storage_end(&storage); + emummc_storage_end(&storage); // derive eticket_rsa_kek and ssl_rsa_kek if (_key_exists(es_keys[0]) && _key_exists(es_keys[1]) && _key_exists(master_key[0])) { @@ -828,31 +830,29 @@ key_output: ; //gfx_con.fntsz = 8; gfx_puts(text_buffer); gfx_con.fntsz = 16; - TPRINTFARGS("\n%kFound %d keys.\n%kLockpick totally", colors[(color_idx) % 6], _key_count, colors[(color_idx + 1) % 6]); - color_idx += 2; + end_time = get_tmr_us(); + gfx_printf("\n%kFound %d keys.", colors[(color_idx++) % 6], _key_count); + _key_count = 0; + gfx_printf("\n%kLockpick totally done in %d us", colors[(color_idx++) % 6], end_time - begin_time); + gfx_printf("\n%kFound through master_key_%02x\n", colors[(color_idx++) % 6], MAX_KEY - 1); - f_mkdir("switch"); + f_mkdir("sd:/switch"); char keyfile_path[30] = "sd:/switch/"; if (!(fuse_read_odm(4) & 3)) sprintf(&keyfile_path[11], "prod.keys"); else sprintf(&keyfile_path[11], "dev.keys"); - if (!sd_save_to_file(text_buffer, strlen(text_buffer), keyfile_path) && !f_stat(keyfile_path, &fno)) { + if (sd_mount() && !sd_save_to_file(text_buffer, strlen(text_buffer), keyfile_path) && !f_stat(keyfile_path, &fno)) { gfx_printf("%kWrote %d bytes to %s\n", colors[(color_idx++) % 6], (u32)fno.fsize, keyfile_path); } else EPRINTF("Failed to save keys to SD."); - sd_unmount(); + h_cfg.emummc_force_disable = emummc_load_cfg(); out_wait: - gfx_printf("\n%kVOL + -> Reboot to RCM\n%kVOL - -> Reboot normally\n%kPower -> Power off", colors[(color_idx) % 6], colors[(color_idx + 1) % 6], colors[(color_idx + 2) % 6]); + sd_unmount(); + gfx_printf("\n%kPress any key to return to the main menu.", colors[(color_idx) % 6], colors[(color_idx + 1) % 6], colors[(color_idx + 2) % 6]); - u32 btn = btn_wait(); - if (btn & BTN_VOL_UP) - reboot_rcm(); - else if (btn & BTN_VOL_DOWN) - reboot_normal(); - else - power_off(); + btn_wait(); } static void _save_key(const char *name, const void *data, const u32 len, char *outbuf) { diff --git a/source/libs/fatfs/diskio.c b/source/libs/fatfs/diskio.c index f33f011..97f8336 100644 --- a/source/libs/fatfs/diskio.c +++ b/source/libs/fatfs/diskio.c @@ -42,10 +42,11 @@ typedef struct { u32 visit_count; u8 tweak[0x10]; u8 cached_sector[0x200]; + u8 align[8]; } sector_cache_t; - + #define MAX_SEC_CACHE_ENTRIES 64 -static sector_cache_t *sector_cache = (sector_cache_t*)0x40020000; +static sector_cache_t *sector_cache = (sector_cache_t*)0x40022000; static u32 secindex = 0; DSTATUS disk_status ( diff --git a/source/libs/fatfs/ffconf.h b/source/libs/fatfs/ffconf.h index ca13b33..221c909 100644 --- a/source/libs/fatfs/ffconf.h +++ b/source/libs/fatfs/ffconf.h @@ -25,7 +25,7 @@ / 3: f_lseek() function is removed in addition to 2. */ -#define FF_USE_STRFUNC 0 +#define FF_USE_STRFUNC 2 /* This option switches string functions, f_gets(), f_putc(), f_puts() and f_printf(). / / 0: Disable string functions. @@ -33,7 +33,7 @@ / 2: Enable with LF-CRLF conversion. */ -#define FF_USE_FIND 0 +#define FF_USE_FIND 1 /* This option switches filtered directory read functions, f_findfirst() and / f_findnext(). (0:Disable, 1:Enable 2:Enable with matching altname[] too) */ @@ -50,7 +50,7 @@ /* This option switches f_expand function. (0:Disable or 1:Enable) */ -#define FF_USE_CHMOD 0 +#define FF_USE_CHMOD 1 /* This option switches attribute manipulation functions, f_chmod() and f_utime(). / (0:Disable or 1:Enable) Also FF_FS_READONLY needs to be 0 to enable this option. */ diff --git a/source/main.c b/source/main.c index fb03dc7..3fcdef5 100644 --- a/source/main.c +++ b/source/main.c @@ -21,13 +21,16 @@ #include "config/config.h" #include "gfx/di.h" #include "gfx/gfx.h" +#include "gfx/tui.h" #include "libs/fatfs/ff.h" #include "mem/heap.h" #include "power/max77620.h" #include "rtc/max77620-rtc.h" #include "soc/bpmp.h" #include "soc/hw_init.h" +#include "storage/emummc.h" #include "storage/sdmmc.h" +#include "utils/sprintf.h" #include "utils/util.h" #include "keys/keys.h" @@ -79,27 +82,27 @@ void sd_unmount() void *sd_file_read(const char *path, u32 *fsize) { - FIL fp; - if (f_open(&fp, path, FA_READ) != FR_OK) - return NULL; + FIL fp; + if (f_open(&fp, path, FA_READ) != FR_OK) + return NULL; - u32 size = f_size(&fp); - if (fsize) - *fsize = size; + u32 size = f_size(&fp); + if (fsize) + *fsize = size; - void *buf = malloc(size); + void *buf = malloc(size); - if (f_read(&fp, buf, size, NULL) != FR_OK) - { - free(buf); - f_close(&fp); + if (f_read(&fp, buf, size, NULL) != FR_OK) + { + free(buf); + f_close(&fp); - return NULL; - } + return NULL; + } - f_close(&fp); + f_close(&fp); - return buf; + return buf; } int sd_save_to_file(void *buf, u32 size, const char *filename) @@ -145,6 +148,34 @@ void reloc_patcher(u32 payload_dst, u32 payload_src, u32 payload_size) } } +void dump_sysnand() +{ + h_cfg.emummc_force_disable = true; + b_cfg.extra_cfg &= ~EXTRA_CFG_DUMP_EMUMMC; + dump_keys(); +} + +void dump_emunand() +{ + if (h_cfg.emummc_force_disable) + return; + emu_cfg.enabled = 1; + b_cfg.extra_cfg |= EXTRA_CFG_DUMP_EMUMMC; + dump_keys(); +} + +ment_t ment_top[] = { + MDEF_HANDLER("Dump keys from SysNAND", dump_sysnand, COLOR_RED), + MDEF_HANDLER("Dump keys from emuMMC", dump_emunand, COLOR_ORANGE), + MDEF_CAPTION("---------------", COLOR_YELLOW), + MDEF_HANDLER("Reboot (Normal)", reboot_normal, COLOR_GREEN), + MDEF_HANDLER("Reboot (RCM)", reboot_rcm, COLOR_BLUE), + MDEF_HANDLER("Power off", power_off, COLOR_VIOLET), + MDEF_END() +}; + +menu_t menu_top = { ment_top, NULL, 0, 0 }; + #define IPL_STACK_TOP 0x4003F000 #define IPL_HEAP_START 0x90020000 @@ -166,6 +197,25 @@ void ipl_main() bpmp_clk_rate_set(BPMP_CLK_SUPER_BOOST); - sd_mount(); - dump_keys(); + h_cfg.emummc_force_disable = emummc_load_cfg(); + + if (b_cfg.boot_cfg & BOOT_CFG_SEPT_RUN) + { + if (!(b_cfg.extra_cfg & EXTRA_CFG_DUMP_EMUMMC)) + h_cfg.emummc_force_disable = true; + dump_keys(); + } + + if (h_cfg.emummc_force_disable) + { + ment_top[1].type = MENT_CAPTION; + ment_top[1].color = 0xFF555555; + ment_top[1].handler = NULL; + } + + while (true) + tui_do_menu(&menu_top); + + while (true) + bpmp_halt(); } diff --git a/source/power/max17050.c b/source/power/max17050.c index 2a2c8f6..d34c340 100644 --- a/source/power/max17050.c +++ b/source/power/max17050.c @@ -43,6 +43,9 @@ #define MAX17050_VMAX_TOLERANCE 50 /* 50 mV */ +#pragma GCC push_options +#pragma GCC optimize ("Os") + int max17050_get_property(enum MAX17050_reg reg, int *value) { u16 data; @@ -264,3 +267,5 @@ int max17050_fix_configuration() return 0; } + +#pragma GCC pop_options \ No newline at end of file diff --git a/source/storage/emummc.c b/source/storage/emummc.c new file mode 100644 index 0000000..deae70e --- /dev/null +++ b/source/storage/emummc.c @@ -0,0 +1,266 @@ +/* + * Copyright (C) 2019 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 "emummc.h" +#include "sdmmc.h" +#include "../config/config.h" +#include "../config/ini.h" +#include "../gfx/gfx.h" +#include "../libs/fatfs/ff.h" +#include "../mem/heap.h" +#include "../utils/list.h" +#include "../utils/types.h" + +extern sdmmc_t sd_sdmmc; +extern sdmmc_storage_t sd_storage; +extern FATFS sd_fs; + +extern hekate_config h_cfg; + +extern bool sd_mount(); +extern void sd_unmount(); + +bool emummc_load_cfg() +{ + sd_mount(); + emu_cfg.enabled = 0; + emu_cfg.path = NULL; + emu_cfg.nintendo_path = NULL; + emu_cfg.sector = 0; + emu_cfg.id = 0; + emu_cfg.file_based_part_size = 0; + emu_cfg.active_part = 0; + emu_cfg.fs_ver = 0; + emu_cfg.emummc_file_based_path = (char *)malloc(0x80); + + LIST_INIT(ini_sections); + if (ini_parse(&ini_sections, "emuMMC/emummc.ini", false)) + { + LIST_FOREACH_ENTRY(ini_sec_t, ini_sec, &ini_sections, link) + { + if (ini_sec->type == INI_CHOICE) + { + if (strcmp(ini_sec->name, "emummc")) + continue; + + LIST_FOREACH_ENTRY(ini_kv_t, kv, &ini_sec->kvs, link) + { + if (!strcmp("enabled", kv->key)) + emu_cfg.enabled = atoi(kv->val); + else if (!strcmp("sector", kv->key)) + emu_cfg.sector = strtol(kv->val, NULL, 16); + else if (!strcmp("id", kv->key)) + emu_cfg.id = strtol(kv->val, NULL, 16); + else if (!strcmp("path", kv->key)) + emu_cfg.path = kv->val; + else if (!strcmp("nintendo_path", kv->key)) + emu_cfg.nintendo_path = kv->val; + } + break; + } + } + return 0; + } + return 1; +} + +static int emummc_raw_get_part_off(int part_idx) +{ + switch (part_idx) + { + case 0: + return 2; + case 1: + return 0; + case 2: + return 1; + } + return 2; +} + + +int emummc_storage_init_mmc(sdmmc_storage_t *storage, sdmmc_t *sdmmc) +{ + FILINFO fno; + if (!sdmmc_storage_init_mmc(storage, sdmmc, SDMMC_4, SDMMC_BUS_WIDTH_8, 4)) + { + EPRINTF("Failed to init eMMC."); + + goto out; + } + if (h_cfg.emummc_force_disable) + return 1; + + emu_cfg.active_part = 0; + if (!sd_mount()) + goto out; + + if (emu_cfg.enabled && !emu_cfg.sector) + { + strcpy(emu_cfg.emummc_file_based_path, emu_cfg.path); + strcat(emu_cfg.emummc_file_based_path, "/eMMC"); + + if (f_stat(emu_cfg.emummc_file_based_path, &fno)) + { + EPRINTF("Failed to open eMMC folder."); + goto out; + } + f_chmod(emu_cfg.emummc_file_based_path, AM_ARC, AM_ARC); + + strcat(emu_cfg.emummc_file_based_path, "/00"); + if (f_stat(emu_cfg.emummc_file_based_path, &fno)) + { + EPRINTF("Failed to open emuMMC rawnand."); + goto out; + } + emu_cfg.file_based_part_size = fno.fsize >> 9; + } + return 1; + +out: + return 0; +} + +int emummc_storage_end(sdmmc_storage_t *storage) +{ + sd_unmount(); + sdmmc_storage_end(storage); + + return 1; +} + +int emummc_storage_read(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, void *buf) +{ + FIL fp; + if (!emu_cfg.enabled || h_cfg.emummc_force_disable) + return sdmmc_storage_read(storage, sector, num_sectors, buf); + else if (emu_cfg.sector) + { + sector += emu_cfg.sector; + sector += emummc_raw_get_part_off(emu_cfg.active_part) * 0x2000; + return sdmmc_storage_read(&sd_storage, sector, num_sectors, buf); + } + else + { + if (!emu_cfg.active_part) + { + u32 file_part = sector / emu_cfg.file_based_part_size; + sector = sector % emu_cfg.file_based_part_size; + if (file_part >= 10) + itoa(file_part, emu_cfg.emummc_file_based_path + strlen(emu_cfg.emummc_file_based_path) - 2, 10); + else + { + emu_cfg.emummc_file_based_path[strlen(emu_cfg.emummc_file_based_path) - 2] = '0'; + itoa(file_part, emu_cfg.emummc_file_based_path + strlen(emu_cfg.emummc_file_based_path) - 1, 10); + } + } + if (f_open(&fp, emu_cfg.emummc_file_based_path, FA_READ)) + { + EPRINTF("Failed to open emuMMC image."); + return 0; + } + f_lseek(&fp, (u64)sector << 9); + if (f_read(&fp, buf, (u64)num_sectors << 9, NULL)) + { + EPRINTF("Failed to read emuMMC image."); + f_close(&fp); + return 0; + } + + f_close(&fp); + return 1; + } + + return 1; +} + +int emummc_storage_write(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, void *buf) +{ + FIL fp; + if (!emu_cfg.enabled || h_cfg.emummc_force_disable) + return sdmmc_storage_write(storage, sector, num_sectors, buf); + else if (emu_cfg.sector) + { + sector += emu_cfg.sector; + sector += emummc_raw_get_part_off(emu_cfg.active_part) * 0x2000; + return sdmmc_storage_write(&sd_storage, sector, num_sectors, buf); + } + else + { + if (!emu_cfg.active_part) + { + u32 file_part = sector / emu_cfg.file_based_part_size; + sector = sector % emu_cfg.file_based_part_size; + if (file_part >= 10) + itoa(file_part, emu_cfg.emummc_file_based_path + strlen(emu_cfg.emummc_file_based_path) - 2, 10); + else + { + emu_cfg.emummc_file_based_path[strlen(emu_cfg.emummc_file_based_path) - 2] = '0'; + itoa(file_part, emu_cfg.emummc_file_based_path + strlen(emu_cfg.emummc_file_based_path) - 1, 10); + } + } + if (f_open(&fp, emu_cfg.emummc_file_based_path, FA_WRITE)) + { + gfx_printf("e5\n"); + return 0; + } + f_lseek(&fp, (u64)sector << 9); + if (f_write(&fp, buf, (u64)num_sectors << 9, NULL)) + { + gfx_printf("e6\n"); + f_close(&fp); + return 0; + } + + f_close(&fp); + return 1; + } +} + +int emummc_storage_set_mmc_partition(sdmmc_storage_t *storage, u32 partition) +{ + emu_cfg.active_part = partition; + + if (!emu_cfg.enabled || h_cfg.emummc_force_disable) + sdmmc_storage_set_mmc_partition(storage, partition); + else if (emu_cfg.sector) + return 1; + else + { + strcpy(emu_cfg.emummc_file_based_path, emu_cfg.path); + strcat(emu_cfg.emummc_file_based_path, "/eMMC"); + + switch (partition) + { + case 0: + strcat(emu_cfg.emummc_file_based_path, "/00"); + break; + case 1: + strcat(emu_cfg.emummc_file_based_path, "/BOOT0"); + break; + case 2: + strcat(emu_cfg.emummc_file_based_path, "/BOOT1"); + break; + } + + return 1; + } + + return 1; +} diff --git a/source/storage/emummc.h b/source/storage/emummc.h new file mode 100644 index 0000000..635332f --- /dev/null +++ b/source/storage/emummc.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2019 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 EMUMMC_H +#define EMUMMC_H + +#include "sdmmc.h" +#include "../utils/types.h" + +typedef enum +{ + EMUMMC_TYPE_NONE = 0, + EMUMMC_TYPE_PARTITION = 1, + EMUMMC_TYPE_FILES = 2, +} emummc_type_t; + +typedef enum { + EMUMMC_MMC_NAND = 0, + EMUMMC_MMC_SD = 1, + EMUMMC_MMC_GC = 2, +} emummc_mmc_t; + +typedef struct _emummc_cfg_t +{ + int enabled; + u64 sector; + u16 id; + char *path; + char *nintendo_path; + // Internal. + char *emummc_file_based_path; + u32 file_based_part_size; + u32 active_part; + int fs_ver; +} emummc_cfg_t; + +emummc_cfg_t emu_cfg; + +bool emummc_load_cfg(); +int emummc_storage_init_mmc(sdmmc_storage_t *storage, sdmmc_t *sdmmc); +int emummc_storage_end(sdmmc_storage_t *storage); +int emummc_storage_read(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, void *buf); +int emummc_storage_write(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, void *buf); +int emummc_storage_set_mmc_partition(sdmmc_storage_t *storage, u32 partition); + +#endif \ No newline at end of file diff --git a/source/storage/nx_emmc.c b/source/storage/nx_emmc.c index a65dced..8e0fb63 100644 --- a/source/storage/nx_emmc.c +++ b/source/storage/nx_emmc.c @@ -17,6 +17,7 @@ #include #include "nx_emmc.h" +#include "emummc.h" #include "../mem/heap.h" #include "../utils/list.h" @@ -24,7 +25,7 @@ void nx_emmc_gpt_parse(link_t *gpt, sdmmc_storage_t *storage) { u8 *buf = (u8 *)malloc(NX_GPT_NUM_BLOCKS * NX_EMMC_BLOCKSIZE); - sdmmc_storage_read(storage, NX_GPT_FIRST_LBA, NX_GPT_NUM_BLOCKS, buf); + emummc_storage_read(storage, NX_GPT_FIRST_LBA, NX_GPT_NUM_BLOCKS, buf); gpt_header_t *hdr = (gpt_header_t *)buf; for (u32 i = 0; i < hdr->num_part_ents; i++) @@ -65,7 +66,7 @@ int nx_emmc_part_read(sdmmc_storage_t *storage, emmc_part_t *part, u32 sector_of // The last LBA is inclusive. if (part->lba_start + sector_off > part->lba_end) return 0; - return sdmmc_storage_read(storage, part->lba_start + sector_off, num_sectors, buf); + return emummc_storage_read(storage, part->lba_start + sector_off, num_sectors, buf); } int nx_emmc_part_write(sdmmc_storage_t *storage, emmc_part_t *part, u32 sector_off, u32 num_sectors, void *buf) diff --git a/source/utils/types.h b/source/utils/types.h index 579c274..e5dcb22 100644 --- a/source/utils/types.h +++ b/source/utils/types.h @@ -68,6 +68,8 @@ typedef volatile unsigned char vu8; typedef volatile unsigned short vu16; typedef volatile unsigned int vu32; +static const u32 colors[6] = {COLOR_RED, COLOR_ORANGE, COLOR_YELLOW, COLOR_GREEN, COLOR_BLUE, COLOR_VIOLET}; + typedef int bool; #define true 1 #define false 0 @@ -76,6 +78,8 @@ typedef int bool; #define BOOT_CFG_FROM_LAUNCH (1 << 1) #define BOOT_CFG_SEPT_RUN (1 << 7) +#define EXTRA_CFG_DUMP_EMUMMC (1 << 0) + typedef struct __attribute__((__packed__)) _boot_cfg_t { u8 boot_cfg;