diff --git a/bdk/storage/mbr_gpt.c b/bdk/storage/mbr_gpt.c new file mode 100644 index 00000000..09e6f331 --- /dev/null +++ b/bdk/storage/mbr_gpt.c @@ -0,0 +1,39 @@ +#include "mbr_gpt.h" +#include +#include + +bool mbr_has_gpt(const mbr_t *mbr){ + for(u32 i = 0; i < 4; i++){ + if(mbr->partitions[i].type == 0xee){ + return true; + } + } + return false; +} + +void wctombs(const u16 *src, char *dest, u32 len_max){ + const u16 *cur = src; + do{ + *dest++ = *cur & 0xff; + len_max--; + }while(*cur++ && len_max); +} + +void ctowcs(const char *src, u16 *dest, u32 len_max){ + const char *cur = src; + do{ + *dest++ = *cur; + len_max--; + }while(*cur++ && len_max); +} + +s32 gpt_get_part_by_name(gpt_t *gpt, const char* name, s32 prev){ + u16 wc_name[36]; + ctowcs(name, wc_name, 36); + for(s32 i = prev + 1; i < (s32)gpt->header.num_part_ents && i < 128; i++){ + if(!memcmp(wc_name, gpt->entries[i].name, strlen(name) * 2)){ + return i; + } + } + return -1; +} \ No newline at end of file diff --git a/bdk/storage/mbr_gpt.h b/bdk/storage/mbr_gpt.h index 7f381083..e90fb28a 100644 --- a/bdk/storage/mbr_gpt.h +++ b/bdk/storage/mbr_gpt.h @@ -81,4 +81,10 @@ typedef struct _gpt_t gpt_entry_t entries[128]; } gpt_t; +bool mbr_has_gpt(const mbr_t *mbr); +void wctombs(const u16 *src, char *dest, u32 len_max); +void ctowcs(const char *src, u16 *dest, u32 len_max); +s32 gpt_get_part_by_name(gpt_t *gpt, const char* name, s32 prev); + + #endif diff --git a/bdk/utils/types.h b/bdk/utils/types.h index e15fadbf..e06116b0 100644 --- a/bdk/utils/types.h +++ b/bdk/utils/types.h @@ -129,7 +129,11 @@ typedef enum _nyx_ums_type NYX_UMS_EMMC_GPP, NYX_UMS_EMUMMC_BOOT0, NYX_UMS_EMUMMC_BOOT1, - NYX_UMS_EMUMMC_GPP + NYX_UMS_EMUMMC_GPP, + NYX_UMS_BOOT_STRG_SD, + NYX_UMS_BOOT_STRG_BOOT1, + NYX_UMS_BOOT_STRG_BOOT1_1MB, + NYX_UMS_BOOT_STRG_GPP, } nyx_ums_type; typedef struct __attribute__((__packed__)) _boot_cfg_t diff --git a/bootloader/storage/emummc.c b/bootloader/storage/emummc.c index 405b5053..56a1727f 100644 --- a/bootloader/storage/emummc.c +++ b/bootloader/storage/emummc.c @@ -14,6 +14,7 @@ * along with this program. If not, see . */ +#include #include #include #include @@ -85,30 +86,47 @@ bool emummc_set_path(char *path) if (!f_open(&fp, emu_cfg.emummc_file_based_path, FA_READ)) { - if (!f_read(&fp, &emu_cfg.sector, 4, NULL)) - if (emu_cfg.sector) + if (!f_read(&fp, &emu_cfg.sector, 4, NULL)){ + if (emu_cfg.sector){ found = true; - } - else - { - // strcpy(emu_cfg.emummc_file_based_path, "sd:"); - strcpy(emu_cfg.emummc_file_based_path, ""); - strcat(emu_cfg.emummc_file_based_path, path); - strcat(emu_cfg.emummc_file_based_path, "/file_based"); - - if (!f_stat(emu_cfg.emummc_file_based_path, NULL)) - { - emu_cfg.sector = 0; - emu_cfg.path = path; - - found = true; + emu_cfg.enabled = 1; + goto out; + } } } - if (found) + strcpy(emu_cfg.emummc_file_based_path, ""); + strcat(emu_cfg.emummc_file_based_path, path); + strcat(emu_cfg.emummc_file_based_path, "/raw_emmc_based"); + if (!f_open(&fp, emu_cfg.emummc_file_based_path, FA_READ)) { + if (!f_read(&fp, &emu_cfg.sector, 4, NULL)){ + if (emu_cfg.sector){ + found = true; + emu_cfg.enabled = 4; + goto out; + } + } + } + + // strcpy(emu_cfg.emummc_file_based_path, "sd:"); + strcpy(emu_cfg.emummc_file_based_path, ""); + strcat(emu_cfg.emummc_file_based_path, path); + strcat(emu_cfg.emummc_file_based_path, "/file_based"); + if (!f_stat(emu_cfg.emummc_file_based_path, NULL)) + { + emu_cfg.sector = 0; + emu_cfg.path = path; emu_cfg.enabled = 1; + found = true; + goto out; + } + +out: + + if (found) + { // Get ID from path. u32 id_from_path = 0; u32 path_size = strlen(path); @@ -149,7 +167,7 @@ int emummc_storage_init_mmc() if (!emu_cfg.enabled || h_cfg.emummc_force_disable) return 0; - if (!sd_mount()) + if (emu_cfg.enabled == 1 && !sd_mount()) goto out; if (!emu_cfg.sector) @@ -182,7 +200,7 @@ out: int emummc_storage_end() { - if (!emu_cfg.enabled || h_cfg.emummc_force_disable) + if (!emu_cfg.enabled || h_cfg.emummc_force_disable || emu_cfg.enabled == 4) emmc_end(); else sd_end(); @@ -192,6 +210,7 @@ int emummc_storage_end() int emummc_storage_read(u32 sector, u32 num_sectors, void *buf) { + sdmmc_storage_t *storage = emu_cfg.enabled == 4 ? &emmc_storage : &sd_storage; FIL fp; if (!emu_cfg.enabled || h_cfg.emummc_force_disable) return sdmmc_storage_read(&emmc_storage, sector, num_sectors, buf); @@ -199,7 +218,7 @@ int emummc_storage_read(u32 sector, u32 num_sectors, void *buf) { 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); + return sdmmc_storage_read(storage, sector, num_sectors, buf); } else { @@ -237,6 +256,7 @@ int emummc_storage_read(u32 sector, u32 num_sectors, void *buf) int emummc_storage_write(u32 sector, u32 num_sectors, void *buf) { + sdmmc_storage_t *storage = emu_cfg.enabled == 4 ? &emmc_storage : &sd_storage; FIL fp; if (!emu_cfg.enabled || h_cfg.emummc_force_disable) return sdmmc_storage_write(&emmc_storage, sector, num_sectors, buf); @@ -244,7 +264,7 @@ int emummc_storage_write(u32 sector, u32 num_sectors, void *buf) { 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); + return sdmmc_storage_write(storage, sector, num_sectors, buf); } else { @@ -276,12 +296,15 @@ int emummc_storage_write(u32 sector, u32 num_sectors, void *buf) } } - -// TODO: active partition may be changed by boot storage access int emummc_storage_set_mmc_partition(u32 partition) { emu_cfg.active_part = partition; - emmc_set_partition(partition); + + if(emu_cfg.enabled != 4){ + emmc_set_partition(partition); + }else{ + emmc_set_partition(EMMC_GPP); + } if (!emu_cfg.enabled || h_cfg.emummc_force_disable || emu_cfg.sector) return 1; @@ -312,5 +335,5 @@ int emummc_storage_set_mmc_partition(u32 partition) sdmmc_storage_t *emummc_get_storage(){ // TODO: should return &emummc_storage if emummc lives on emmc - return &sd_storage; + return emu_cfg.enabled == 4 ? &emmc_storage : &sd_storage; } diff --git a/nyx/Makefile b/nyx/Makefile index e1529547..b6c8595c 100644 --- a/nyx/Makefile +++ b/nyx/Makefile @@ -27,8 +27,8 @@ OBJS = $(addprefix $(BUILDDIR)/$(TARGET)/, \ start.o exception_handlers.o \ nyx.o heap.o \ gfx.o \ - gui.o gui_info.o gui_tools.o gui_options.o gui_emmc_tools.o gui_emummc_tools.o gui_tools_partition_manager.o \ - fe_emummc_tools.o fe_emmc_tools.o \ + gui.o gui_info.o gui_tools.o gui_options.o gui_emmc_tools.o gui_emummc_tools.o gui_tools_partition_manager.o gui_emu_tools.o gui_emusd_tools.o \ + fe_emummc_tools.o fe_emmc_tools.o fe_emusd_tools.o \ ) # Hardware. @@ -41,7 +41,7 @@ OBJS += $(addprefix $(BUILDDIR)/$(TARGET)/, \ bm92t36.o bq24193.o max17050.o max7762x.o max77620-rtc.o regulator_5v.o \ touch.o joycon.o tmp451.o fan.o \ usbd.o xusbd.o usb_descriptors.o usb_gadget_ums.o usb_gadget_hid.o \ - hw_init.o boot_storage.o sfd.o\ + hw_init.o boot_storage.o sfd.o mbr_gpt.o \ ) # Utilities. diff --git a/nyx/nyx_gui/frontend/fe_emmc_tools.c b/nyx/nyx_gui/frontend/fe_emmc_tools.c index 5af4b232..e1d5c8bd 100644 --- a/nyx/nyx_gui/frontend/fe_emmc_tools.c +++ b/nyx/nyx_gui/frontend/fe_emmc_tools.c @@ -1362,7 +1362,7 @@ multipart_not_allowed: f_close(&fp_raw); s_printf(sdPath, "emuMMC/RAW%d", part_idx); - save_emummc_cfg(part_idx, sector_start, sdPath); + save_emummc_cfg(part_idx, sector_start, sdPath, DRIVE_SD); } return 1; diff --git a/nyx/nyx_gui/frontend/fe_emummc_tools.c b/nyx/nyx_gui/frontend/fe_emummc_tools.c index b4034712..7f519fdc 100644 --- a/nyx/nyx_gui/frontend/fe_emummc_tools.c +++ b/nyx/nyx_gui/frontend/fe_emummc_tools.c @@ -19,6 +19,9 @@ //! fix the dram stuff and the pop ups #include +#include +#include +#include #include #include @@ -77,7 +80,7 @@ void load_emummc_cfg(emummc_cfg_t *emu_info) ini_free(&ini_sections); } -void save_emummc_cfg(u32 part_idx, u32 sector_start, const char *path) +void save_emummc_cfg(u32 part_idx, u32 sector_start, const char *path, u8 drive) { boot_storage_mount(); @@ -89,14 +92,20 @@ void save_emummc_cfg(u32 part_idx, u32 sector_start, const char *path) // Add config entry. f_puts("[emummc]\nenabled=", &fp); - if (part_idx && sector_start) + if (part_idx && sector_start && drive == DRIVE_SD) { + // 1: part. 1, 2: part. 2, 3: part. 3 itoa(part_idx, lbuf, 10); f_puts(lbuf, &fp); + }else if(drive == DRIVE_EMMC && sector_start && part_idx){ + // 4: emmc raw based + f_puts("4", &fp); } else if (path) + // 1: enabled, file based f_puts("1", &fp); else + // 0: disable f_puts("0", &fp); if (!sector_start) @@ -115,8 +124,9 @@ void save_emummc_cfg(u32 part_idx, u32 sector_start, const char *path) // Get ID from path. u32 id_from_path = 0; - if (path && strlen(path) >= 4) + if (path && strlen(path) >= 4){ memcpy(&id_from_path, path + strlen(path) - 4, 4); + } f_puts("\nid=0x", &fp); itoa(id_from_path, lbuf, 16); f_puts(lbuf, &fp); @@ -490,11 +500,11 @@ out_failed: strcpy(sdPath, gui->base_path); strcat(sdPath, "file_based"); FIL fp; - f_open(&fp, sdPath, FA_CREATE_ALWAYS | FA_WRITE); + f_open(&fp, sdPath + 3, FA_CREATE_ALWAYS | FA_WRITE); f_close(&fp); gui->base_path[strlen(gui->base_path) - 1] = 0; - save_emummc_cfg(0, 0, gui->base_path); + save_emummc_cfg(0, 0, gui->base_path, 0); } else s_printf(txt_buf, "Time taken: %dm %ds.", timer / 60, timer % 60); @@ -507,7 +517,7 @@ out: sd_unmount(); } -static int _dump_emummc_raw_part(emmc_tool_gui_t *gui, int active_part, int part_idx, u32 sd_part_off, emmc_part_t *part, u32 resized_count) +static int _dump_emummc_raw_part(emmc_tool_gui_t *gui, int active_part, int part_idx, u32 sd_part_off, emmc_part_t *part, u32 resized_count, u8 drive) { u32 num = 0; u32 pct = 0; @@ -517,6 +527,10 @@ static int _dump_emummc_raw_part(emmc_tool_gui_t *gui, int active_part, int part u32 lba_curr = part->lba_start; u8 *buf = (u8 *)MIXD_BUF_ALIGNED; + u32 cur_emmc_part = emmc_storage.partition; + + sdmmc_storage_t *emu_storge = drive == DRIVE_SD ? &sd_storage : &emmc_storage; + s_printf(gui->txt_buf, "\n\n\n"); lv_label_ins_text(gui->label_info, LV_LABEL_POS_LAST, gui->txt_buf); manual_system_maintenance(true); @@ -539,6 +553,7 @@ static int _dump_emummc_raw_part(emmc_tool_gui_t *gui, int active_part, int part { // Get USER partition info. LIST_INIT(gpt_parsed); + // NOTE: reads from emummc, if enabled emmc_gpt_parse(&gpt_parsed); emmc_part_t *user_part = emmc_part_find(&gpt_parsed, "USER"); if (!user_part) @@ -574,6 +589,9 @@ static int _dump_emummc_raw_part(emmc_tool_gui_t *gui, int active_part, int part num = MIN(totalSectors, NUM_SECTORS_PER_ITER); // Read data from eMMC. + if(emmc_storage.partition != cur_emmc_part){ + emmc_set_partition(cur_emmc_part); + } while (!sdmmc_storage_read(&emmc_storage, lba_curr, num, buf)) { s_printf(gui->txt_buf, @@ -604,12 +622,17 @@ static int _dump_emummc_raw_part(emmc_tool_gui_t *gui, int active_part, int part // Write data to SD card. retryCount = 0; - while (!sdmmc_storage_write(&sd_storage, sd_sector_off + lba_curr, num, buf)) + if(drive == DRIVE_EMMC){ + if(emmc_storage.partition != EMMC_GPP){ + emmc_set_partition(EMMC_GPP); + } + } + while (!sdmmc_storage_write(emu_storge, sd_sector_off + lba_curr, num, buf)) { s_printf(gui->txt_buf, "\n#FFDD00 Error writing %d blocks @LBA %08X,#\n" - "#FFDD00 to SD (try %d). #", - num, lba_curr, ++retryCount); + "#FFDD00 to %s (try %d). #", + num, lba_curr, drive == DRIVE_SD ? "SD" : "eMMC", ++retryCount); lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf); manual_system_maintenance(true); @@ -651,7 +674,7 @@ static int _dump_emummc_raw_part(emmc_tool_gui_t *gui, int active_part, int part manual_system_maintenance(true); // Set partition type to emuMMC (0xE0). - if (active_part == 2) + if (active_part == 2 && drive == DRIVE_SD) { mbr_t mbr; sdmmc_storage_read(&sd_storage, 0, 1, &mbr); @@ -673,7 +696,7 @@ static int _dump_emummc_raw_part(emmc_tool_gui_t *gui, int active_part, int part user_part.lba_start = user_offset; user_part.lba_end = user_offset + user_sectors - 1; strcpy(user_part.name, "USER"); - nx_emmc_bis_init(&user_part, true, &sd_storage, sd_sector_off); + nx_emmc_bis_init(&user_part, true, emu_storge, sd_sector_off); s_printf(gui->txt_buf, "Formatting USER... \n"); lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf); @@ -705,10 +728,20 @@ static int _dump_emummc_raw_part(emmc_tool_gui_t *gui, int active_part, int part manual_system_maintenance(true); // Read MBR, GPT and backup GPT. - mbr_t mbr; + mbr_t mbr = {0}; + mbr.boot_signature = 0xaa55; + mbr.partitions[0].type = 0xee; + mbr.partitions[0].start_sct = 1; + mbr.partitions[0].start_sct_chs.sector = 0x02; + mbr.partitions[0].end_sct_chs.sector = 0xff; + mbr.partitions[0].end_sct_chs.cylinder = 0xff; + mbr.partitions[0].end_sct_chs.head = 0xff; + mbr.partitions[0].size_sct = 0xffffffff; + gpt_t *gpt = zalloc(sizeof(gpt_t)); gpt_header_t gpt_hdr_backup; - sdmmc_storage_read(&emmc_storage, 0, 1, &mbr); + // original mbr may have extra partition when emmc was partitioned before, just set signature and gpt protective entry + // sdmmc_storage_read(&emmc_storage, 0, 1, &mbr); sdmmc_storage_read(&emmc_storage, 1, sizeof(gpt_t) >> 9, gpt); sdmmc_storage_read(&emmc_storage, gpt->header.alt_lba, 1, &gpt_hdr_backup); @@ -727,11 +760,15 @@ static int _dump_emummc_raw_part(emmc_tool_gui_t *gui, int active_part, int part return 0; } + // remove all partition entries past user + memset(&gpt->entries[gpt_entry_idx + 1], 0, sizeof(gpt->entries[0]) * (128 - (gpt_entry_idx + 1))); + // Set new emuMMC size and USER size. mbr.partitions[0].size_sct = resized_count; gpt->entries[gpt_entry_idx].lba_end = user_part.lba_end; // Update Main GPT. + gpt->header.num_part_ents = gpt_entry_idx + 1; gpt->header.alt_lba = resized_count - 1; gpt->header.last_use_lba = resized_count - 34; gpt->header.part_ents_crc32 = crc32_calc(0, (const u8 *)gpt->entries, sizeof(gpt_entry_t) * gpt->header.num_part_ents); @@ -746,20 +783,20 @@ static int _dump_emummc_raw_part(emmc_tool_gui_t *gui, int active_part, int part gpt_hdr_backup.crc32 = crc32_calc(0, (const u8 *)&gpt_hdr_backup, gpt_hdr_backup.size); // Write main GPT. - sdmmc_storage_write(&sd_storage, sd_sector_off + gpt->header.my_lba, sizeof(gpt_t) >> 9, gpt); + sdmmc_storage_write(emu_storge, sd_sector_off + gpt->header.my_lba, sizeof(gpt_t) >> 9, gpt); // Write backup GPT partition table. - sdmmc_storage_write(&sd_storage, sd_sector_off + gpt_hdr_backup.part_ent_lba, ((sizeof(gpt_entry_t) * 128) >> 9), gpt->entries); + sdmmc_storage_write(emu_storge, sd_sector_off + gpt_hdr_backup.part_ent_lba, ((sizeof(gpt_entry_t) * 128) >> 9), gpt->entries); // Write backup GPT header. - sdmmc_storage_write(&sd_storage, sd_sector_off + gpt_hdr_backup.my_lba, 1, &gpt_hdr_backup); + sdmmc_storage_write(emu_storge, sd_sector_off + gpt_hdr_backup.my_lba, 1, &gpt_hdr_backup); // Write MBR. - sdmmc_storage_write(&sd_storage, sd_sector_off, 1, &mbr); + sdmmc_storage_write(emu_storge, sd_sector_off, 1, &mbr); // Clear nand patrol. memset(buf, 0, EMMC_BLOCKSIZE); - sdmmc_storage_write(&sd_storage, sd_part_off + NAND_PATROL_SECTOR, 1, buf); + sdmmc_storage_write(emu_storge, sd_part_off + NAND_PATROL_SECTOR, 1, buf); free(gpt); } @@ -786,6 +823,7 @@ static int _emummc_raw_derive_bis_keys(emmc_tool_gui_t *gui, u32 resized_count) emmc_set_partition(EMMC_GPP); LIST_INIT(gpt); emmc_gpt_parse(&gpt); + // reads from emummc, if enabled emmc_part_t *cal0_part = emmc_part_find(&gpt, "PRODINFO"); // check if null nx_emmc_bis_init(cal0_part, false, NULL, 0); nx_emmc_bis_read(0, 0x40, cal0_buff); @@ -841,7 +879,7 @@ static int _emummc_raw_derive_bis_keys(emmc_tool_gui_t *gui, u32 resized_count) return 1; } -void dump_emummc_raw(emmc_tool_gui_t *gui, int part_idx, u32 sector_start, u32 resized_count) +void dump_emummc_raw(emmc_tool_gui_t *gui, int part_idx, u32 sector_start, u32 resized_count, u8 drive) { int res = 0; u32 timer = 0; @@ -855,10 +893,11 @@ void dump_emummc_raw(emmc_tool_gui_t *gui, int part_idx, u32 sector_start, u32 r manual_system_maintenance(true); - // TODO: check result of boot storage mount + sdmmc_storage_t *emu_storage = drive == DRIVE_SD ? &sd_storage : &emmc_storage; + boot_storage_mount(); - if (!sd_mount()) + if (drive == DRIVE_SD && !sd_initialize(false)) { lv_label_set_text(gui->label_info, "#FFDD00 Failed to init SD!#"); goto out; @@ -880,9 +919,9 @@ void dump_emummc_raw(emmc_tool_gui_t *gui, int part_idx, u32 sector_start, u32 r int i = 0; char sdPath[OUT_FILENAME_SZ]; - // Create Restore folders, if they do not exist. - f_mkdir("sd:emuMMC"); - s_printf(sdPath, "sd:emuMMC/RAW%d", part_idx); + // Create folders, if they do not exist. + f_mkdir("emuMMC"); + s_printf(sdPath, drive == DRIVE_SD ? "emuMMC/RAW%d" : "emuMMC/RAW_EMMC%d", part_idx); f_mkdir(sdPath); strcat(sdPath, "/"); strcpy(gui->base_path, sdPath); @@ -897,7 +936,7 @@ void dump_emummc_raw(emmc_tool_gui_t *gui, int part_idx, u32 sector_start, u32 r // Clear partition start. memset((u8 *)MIXD_BUF_ALIGNED, 0, SZ_16M); - sdmmc_storage_write(&sd_storage, sector_start - 0x8000, 0x8000, (u8 *)MIXD_BUF_ALIGNED); + sdmmc_storage_write(emu_storage, sector_start - 0x8000, 0x8000, (u8 *)MIXD_BUF_ALIGNED); for (i = 0; i < 2; i++) { @@ -915,7 +954,7 @@ void dump_emummc_raw(emmc_tool_gui_t *gui, int part_idx, u32 sector_start, u32 r emmc_set_partition(i + 1); strcat(sdPath, bootPart.name); - res = _dump_emummc_raw_part(gui, i, part_idx, sector_start, &bootPart, 0); + res = _dump_emummc_raw_part(gui, i, part_idx, sector_start, &bootPart, 0, drive); if (!res) { @@ -949,7 +988,7 @@ void dump_emummc_raw(emmc_tool_gui_t *gui, int part_idx, u32 sector_start, u32 r lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, txt_buf); manual_system_maintenance(true); - res = _dump_emummc_raw_part(gui, 2, part_idx, sector_start, &rawPart, resized_count); + res = _dump_emummc_raw_part(gui, 2, part_idx, sector_start, &rawPart, resized_count, drive); if (!res) s_printf(txt_buf, "#FFDD00 Failed!#\n"); @@ -968,14 +1007,14 @@ out_failed: { s_printf(txt_buf, "Time taken: %dm %ds.\nFinished!", timer / 60, timer % 60); strcpy(sdPath, gui->base_path); - strcat(sdPath, "raw_based"); + strcat(sdPath, drive == DRIVE_SD ? "raw_based" : "raw_emmc_based"); FIL fp; f_open(&fp, sdPath, FA_CREATE_ALWAYS | FA_WRITE); f_write(&fp, §or_start, 4, NULL); f_close(&fp); gui->base_path[strlen(gui->base_path) - 1] = 0; - save_emummc_cfg(part_idx, sector_start, gui->base_path); + save_emummc_cfg(part_idx, sector_start, gui->base_path, drive); } else s_printf(txt_buf, "Time taken: %dm %ds.", timer / 60, timer % 60); @@ -985,5 +1024,5 @@ out_failed: out: free(txt_buf); free(gui->base_path); - sd_unmount(); + boot_storage_unmount(); } diff --git a/nyx/nyx_gui/frontend/fe_emummc_tools.h b/nyx/nyx_gui/frontend/fe_emummc_tools.h index 55641564..6ed8adf3 100644 --- a/nyx/nyx_gui/frontend/fe_emummc_tools.h +++ b/nyx/nyx_gui/frontend/fe_emummc_tools.h @@ -30,9 +30,9 @@ typedef struct _emummc_cfg_t } emummc_cfg_t; void load_emummc_cfg(emummc_cfg_t *emu_info); -void save_emummc_cfg(u32 part_idx, u32 sector_start, const char *path); +void save_emummc_cfg(u32 part_idx, u32 sector_start, const char *path, u8 drive); void dump_emummc_file(emmc_tool_gui_t *gui); -void dump_emummc_raw(emmc_tool_gui_t *gui, int part_idx, u32 sector_start, u32 resized_count); +void dump_emummc_raw(emmc_tool_gui_t *gui, int part_idx, u32 sector_start, u32 resized_count, u8 drive); void update_emummc_base_folder(char *outFilename, u32 sdPathLen, u32 currPartIdx); #endif diff --git a/nyx/nyx_gui/frontend/fe_emusd_tools.c b/nyx/nyx_gui/frontend/fe_emusd_tools.c new file mode 100644 index 00000000..7cfb6742 --- /dev/null +++ b/nyx/nyx_gui/frontend/fe_emusd_tools.c @@ -0,0 +1,123 @@ +#include "fe_emusd_tools.h" +#include "../storage/sfd.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void load_emusd_cfg(emusd_cfg_t *emu_info){ + memset(emu_info, 0, sizeof(emusd_cfg_t)); + + // Parse emuMMC configuration. + LIST_INIT(ini_sections); + if (!ini_parse(&ini_sections, "emuSD/emusd.ini", false)) + return; + + LIST_FOREACH_ENTRY(ini_sec_t, ini_sec, &ini_sections, link) + { + if (!strcmp(ini_sec->name, "emusd")) + { + LIST_FOREACH_ENTRY(ini_kv_t, kv, &ini_sec->kvs, link) + { + if (!strcmp("enabled", kv->key)) + emu_info->enabled = atoi(kv->val); + else if(!strcmp("sector", kv->key)) + emu_info->sector = strtol(kv->val, NULL, 16); + /*else (!strcmp("id", kv->key)) + emu_info->id = strtol(kv->val, NULL, 16);*/ + } + + break; + } + } + + ini_free(&ini_sections); +} + +void save_emusd_cfg(u32 part_idx, u32 sector_start){ + boot_storage_mount(); + + char lbuf[16]; + FIL fp; + + f_mkdir("emuSD"); + + if (f_open(&fp, "emuSD/emusd.ini", FA_WRITE | FA_CREATE_ALWAYS) != FR_OK) + return; + + // Add config entry. + f_puts("[emusd]\nenabled=", &fp); + if(sector_start){ + f_puts("1", &fp); + }else{ + f_puts("0", &fp); + } + + if(!sector_start){ + f_puts("\nsector=0x0", &fp); + }else{ + f_puts("\nsector=0x", &fp); + itoa(sector_start, lbuf, 16); + f_puts(lbuf, &fp); + } + f_puts("\n", &fp); + + f_close(&fp); +} + +int create_emusd(int part_idx, u32 sector_mbr, u32 sector_start, u32 sector_size, const char *name){ + sfd_init(&emmc_storage, sector_start, sector_size); + + u8 *buf = malloc(SZ_4M); + FIL f; + u32 cluster_size = 65536; + + u32 mkfs_error = f_mkfs("sfd:", FM_FAT32 | FM_SFD, cluster_size, buf, SZ_4M); + + while(mkfs_error != FR_OK && cluster_size > 4096){ + cluster_size /= 2; + mkfs_error = f_mkfs("sfd:", FM_FAT32 | FM_SFD, cluster_size, buf, SZ_4M); + } + + if(mkfs_error == FR_OK){ + FATFS fs; + mkfs_error = f_mount(&fs, "sfd:", 1); + + if(mkfs_error == FR_OK){ + mkfs_error = f_open(&f, "sfd:.no_boot_storage", FA_CREATE_ALWAYS | FA_WRITE); + f_close(&f); + + if(mkfs_error == FR_OK){ + char label[0x30]; + strcpy(label, "sfd:"); + strcat(label, name); + mkfs_error = f_setlabel(label); + + if(mkfs_error == FR_OK){ + u8 random_number[16]; + mbr_t mbr = {0}; + se_gen_prng128(random_number); + memcpy(&mbr.signature, random_number, 4); + mbr.boot_signature = 0xaa55; + mbr.partitions[0].start_sct = sector_start - sector_mbr; + mbr.partitions[0].size_sct = sector_size; + mbr.partitions[0].type = 0x0c; + + mkfs_error = sdmmc_storage_write(&emmc_storage, sector_mbr, 1, &mbr) ? FR_OK : FR_DISK_ERR; + } + } + } + + f_mount(NULL, "sfd:", 0); + } + + sfd_end(); + + return mkfs_error; +} \ No newline at end of file diff --git a/nyx/nyx_gui/frontend/fe_emusd_tools.h b/nyx/nyx_gui/frontend/fe_emusd_tools.h new file mode 100644 index 00000000..2eddc296 --- /dev/null +++ b/nyx/nyx_gui/frontend/fe_emusd_tools.h @@ -0,0 +1,16 @@ +#ifndef _FE_EMUSD_TOOLS_H_ +#define _FE_EMUSD_TOOLS_H_ + +#include "gui.h" + +typedef struct _emusd_cfg_t{ + // 0: disabled, 1: enabled + int enabled; + u32 sector; +} emusd_cfg_t; + +void load_emusd_cfg(emusd_cfg_t *emu_info); +void save_emusd_cfg(u32 part_idx, u32 sector_start); +int create_emusd(int part_idx, u32 sector_mbr, u32 sector_start, u32 sector_size, const char *name); + +#endif diff --git a/nyx/nyx_gui/frontend/gui.c b/nyx/nyx_gui/frontend/gui.c index 5d7b0958..c54e9f59 100644 --- a/nyx/nyx_gui/frontend/gui.c +++ b/nyx/nyx_gui/frontend/gui.c @@ -19,6 +19,7 @@ #include #include "gui.h" +#include "gui_emu_tools.h" #include "gui_emummc_tools.h" #include "gui_tools.h" #include "gui_info.h" @@ -938,6 +939,9 @@ void reload_nyx() void (*main_ptr)() = (void *)nyx_str->hekate; + // TODO: + boot_storage_end(); + emmc_end(); sd_end(); hw_deinit(false, 0); @@ -982,7 +986,7 @@ static void _check_sd_card_removed(void *params) // The following checks if SDMMC_1 is initialized. // If yes and card was removed, shows a message box, // that will reload Nyx, when the card is inserted again. - if (!do_reload && sd_get_card_removed()) + if (!do_reload && sd_get_card_removed() && boot_storage_get_drive() == DRIVE_SD) { lv_obj_t *dark_bg = lv_obj_create(lv_scr_act(), NULL); lv_obj_set_style(dark_bg, &mbox_darken); @@ -1004,7 +1008,7 @@ static void _check_sd_card_removed(void *params) } // If in reload state and card was inserted, reload nyx. - if (do_reload && !sd_get_card_removed()) + if (do_reload && !sd_get_card_removed() && boot_storage_get_drive() == DRIVE_SD) reload_nyx(); } @@ -2028,7 +2032,7 @@ static void _create_tab_home(lv_theme_t *th, lv_obj_t *parent) label_btn = lv_label_create(btn_emummc, label_btn); s_printf(btn_colored_text, "%s%s", text_color, " "SYMBOL_LIST"#"); lv_label_set_text(label_btn, btn_colored_text); - lv_btn_set_action(btn_emummc, LV_BTN_ACTION_CLICK, create_win_emummc_tools); + lv_btn_set_action(btn_emummc, LV_BTN_ACTION_CLICK, create_win_emu_tools); lv_btn_set_layout(btn_emummc, LV_LAYOUT_OFF); lv_obj_align(label_btn, NULL, LV_ALIGN_CENTER, 0, -28); lv_obj_set_pos(btn_emummc, 959, 160); diff --git a/nyx/nyx_gui/frontend/gui_emu_tools.c b/nyx/nyx_gui/frontend/gui_emu_tools.c new file mode 100644 index 00000000..a1311dc0 --- /dev/null +++ b/nyx/nyx_gui/frontend/gui_emu_tools.c @@ -0,0 +1,79 @@ +#include "gui_emu_tools.h" +#include "gui.h" +#include "gui_emummc_tools.h" +#include "gui_emusd_tools.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static lv_obj_t *_create_container(lv_obj_t *parent){ + static lv_style_t h_style; + lv_style_copy(&h_style, &lv_style_transp); + h_style.body.padding.inner = 0; + h_style.body.padding.hor = 0; + h_style.body.padding.ver = 0; + + lv_obj_t *h1 = lv_cont_create(parent, NULL); + lv_cont_set_style(h1, &h_style); + lv_cont_set_fit(h1, false, true); + lv_obj_set_width(h1, LV_HOR_RES - 62); + lv_obj_set_click(h1, false); + lv_cont_set_layout(h1, LV_LAYOUT_OFF); + + return h1; +} + +lv_res_t create_win_emu_tools(lv_obj_t *btn){ + lv_obj_t *win = nyx_create_standard_window(SYMBOL_EDIT " emuMMC Manage"); + + static lv_style_t win_style_no_pad; + lv_style_copy(&win_style_no_pad, lv_win_get_style(win, LV_WIN_STYLE_CONTENT_BG)); + win_style_no_pad.body.padding.hor = 0; + win_style_no_pad.body.padding.inner = 0; + + lv_win_set_style(win, LV_WIN_STYLE_CONTENT_BG, &win_style_no_pad); + + lv_obj_t *tv = lv_tabview_create(win, NULL); + lv_obj_set_size(tv, LV_HOR_RES - 62, 572); + + gfx_printf("w: %d\n",(u32)lv_obj_get_width(tv)); + + static lv_style_t tv_style; + lv_style_copy(&tv_style, lv_theme_get_current()->tabview.btn.rel); + tv_style.body.padding.ver = LV_DPI / 8; + tv_style.body.padding.hor = 0; + + lv_tabview_set_style(tv, LV_TABVIEW_STYLE_BTN_REL, &tv_style); + + if(hekate_bg){ + lv_tabview_set_style(tv, LV_TABVIEW_STYLE_BTN_PR, &tabview_btn_pr); + lv_tabview_set_style(tv, LV_TABVIEW_STYLE_BTN_TGL_PR, &tabview_btn_tgl_pr); + } + + lv_tabview_set_sliding(tv, false); + lv_tabview_set_btns_pos(tv, LV_TABVIEW_BTNS_POS_BOTTOM); + + lv_obj_t *tab_emummc = lv_tabview_add_tab(tv, SYMBOL_CHIP " emuMMC"); + lv_obj_t *tab_emusd = lv_tabview_add_tab(tv, SYMBOL_SD " emuSD"); + + lv_obj_t *line_sep = lv_line_create(tv, NULL); + static const lv_point_t line_pp[] = {{0,0}, {0, LV_DPI / 4}}; + lv_line_set_points(line_sep, line_pp, 2); + lv_line_set_style(line_sep, lv_theme_get_current()->line.decor); + lv_obj_align(line_sep, tv, LV_ALIGN_IN_BOTTOM_MID, -1, -LV_DPI * 2 / 12); + + create_tab_emummc_tools(_create_container(tab_emummc)); + create_tab_emusd_tools(_create_container(tab_emusd)); + + lv_tabview_set_tab_act(tv, 0, false); + + return LV_RES_OK; +} + diff --git a/nyx/nyx_gui/frontend/gui_emu_tools.h b/nyx/nyx_gui/frontend/gui_emu_tools.h new file mode 100644 index 00000000..7efc7970 --- /dev/null +++ b/nyx/nyx_gui/frontend/gui_emu_tools.h @@ -0,0 +1,8 @@ +#ifndef _GUI_EMU_TOOLS_H_ +#define _GUI_EMU_TOOLS_H_ + +#include + +lv_res_t create_win_emu_tools(lv_obj_t *btn); + +#endif \ No newline at end of file diff --git a/nyx/nyx_gui/frontend/gui_emummc_tools.c b/nyx/nyx_gui/frontend/gui_emummc_tools.c index 064a32d7..a1af25a2 100644 --- a/nyx/nyx_gui/frontend/gui_emummc_tools.c +++ b/nyx/nyx_gui/frontend/gui_emummc_tools.c @@ -14,6 +14,12 @@ * along with this program. If not, see . */ +#include +#include +#include +#include +#include +#include #include #include @@ -23,10 +29,22 @@ #include "gui_tools_partition_manager.h" #include #include +#include +#include #include +#include +#include extern char *emmcsn_path_impl(char *path, char *sub_dir, char *filename, sdmmc_storage_t *storage); +typedef struct _emummc_part_cfg_t{ + u8 drive; + bool file_based; + u32 sector; + u32 resized_cnt; + u32 part_idx; +} emummc_part_cfg_t; + typedef struct _mbr_ctxt_t { u32 available; @@ -37,10 +55,21 @@ typedef struct _mbr_ctxt_t u32 sector_start; } mbr_ctxt_t; +typedef struct _gpt_ctxt_t +{ + s32 emmc_part_idx[3]; + u32 emmc_part_size[3]; + u32 emmc_part_offset[3]; + u32 emmc_part_resize_cnt[3]; + u8 emmc_part_cnt; +} gpt_ctxt_t; + static bool emummc_backup; static mbr_ctxt_t mbr_ctx; -static lv_obj_t *emummc_manage_window; -static lv_res_t (*emummc_tools)(lv_obj_t *btn); +static lv_obj_t *emummc_parent_cont; +static lv_res_t (*emummc_tools)(lv_obj_t *parent); +static gpt_ctxt_t gpt_ctx; +static emummc_part_cfg_t emummc_part_cfg; static lv_res_t _action_emummc_window_close(lv_obj_t *btn) { @@ -48,8 +77,8 @@ static lv_res_t _action_emummc_window_close(lv_obj_t *btn) close_btn = NULL; // Delete and relaunch main emuMMC window. - lv_obj_del(emummc_manage_window); - (*emummc_tools)(NULL); + lv_obj_clean(emummc_parent_cont); + (*emummc_tools)(emummc_parent_cont); return LV_RES_INV; } @@ -59,7 +88,7 @@ static void _create_window_emummc() emmc_tool_gui_t emmc_tool_gui_ctxt; lv_obj_t *win; - if (!mbr_ctx.part_idx) + if (emummc_part_cfg.file_based) win = nyx_create_window_custom_close_btn(SYMBOL_DRIVE" Create SD File emuMMC", _action_emummc_window_close); else win = nyx_create_window_custom_close_btn(SYMBOL_DRIVE" Create SD Partition emuMMC", _action_emummc_window_close); @@ -134,10 +163,10 @@ static void _create_window_emummc() lv_obj_align(label_finish, bar, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI * 9 / 20); emmc_tool_gui_ctxt.label_finish = label_finish; - if (!mbr_ctx.part_idx) + if (emummc_part_cfg.file_based) dump_emummc_file(&emmc_tool_gui_ctxt); else - dump_emummc_raw(&emmc_tool_gui_ctxt, mbr_ctx.part_idx, mbr_ctx.sector_start, mbr_ctx.resized_cnt[mbr_ctx.part_idx - 1]); + dump_emummc_raw(&emmc_tool_gui_ctxt, emummc_part_cfg.part_idx, emummc_part_cfg.sector, emummc_part_cfg.resized_cnt, emummc_part_cfg.drive); nyx_window_toggle_buttons(win, false); } @@ -153,8 +182,7 @@ static lv_res_t _create_emummc_raw_format(lv_obj_t * btns, const char * txt) if (!btn_idx) create_window_partition_manager(btns, DRIVE_SD); - mbr_ctx.part_idx = 0; - mbr_ctx.sector_start = 0; + memset(&emummc_part_cfg, 0, sizeof(emummc_part_cfg)); return LV_RES_INV; } @@ -164,40 +192,63 @@ static lv_res_t _create_emummc_raw_action(lv_obj_t * btns, const char * txt) int btn_idx = lv_btnm_get_pressed(btns); lv_obj_t *bg = lv_obj_get_parent(lv_obj_get_parent(btns)); - mbr_ctx.sector_start = 0x8000; // Protective offset. + emummc_part_cfg.sector = 0x8000; // 16mb protective offset - switch (btn_idx) - { - case 0: - mbr_ctx.part_idx = 1; - mbr_ctx.sector_start += mbr_ctx.sector[0]; - break; - case 1: - mbr_ctx.part_idx = 2; - mbr_ctx.sector_start += mbr_ctx.sector[1]; - break; - case 2: - mbr_ctx.part_idx = 3; - mbr_ctx.sector_start += mbr_ctx.sector[2]; - break; - default: - break; - } - - if (btn_idx < 3) - { + if(btn_idx < 3){ + emummc_part_cfg.drive = DRIVE_SD; + emummc_part_cfg.part_idx = btn_idx + 1; + emummc_part_cfg.resized_cnt = mbr_ctx.resized_cnt[btn_idx]; + emummc_part_cfg.sector += mbr_ctx.sector[btn_idx]; lv_obj_set_style(bg, &lv_style_transp); _create_window_emummc(); } - mbr_ctx.part_idx = 0; - mbr_ctx.sector_start = 0; + memset(&emummc_part_cfg, 0, sizeof(emummc_part_cfg)); mbox_action(btns, txt); return LV_RES_INV; } +static lv_res_t _create_emummc_emmc_raw_action(lv_obj_t * btns, const char * txt) +{ + int btn_idx = lv_btnm_get_pressed(btns); + lv_obj_t *bg = lv_obj_get_parent(lv_obj_get_parent(btns)); + + emummc_part_cfg.sector = 0x8000; // Protective offset. + + if(btn_idx < gpt_ctx.emmc_part_cnt){ + emummc_part_cfg.part_idx = gpt_ctx.emmc_part_idx[btn_idx]; + emummc_part_cfg.drive = DRIVE_EMMC; + emummc_part_cfg.resized_cnt = gpt_ctx.emmc_part_resize_cnt[btn_idx]; + emummc_part_cfg.sector += gpt_ctx.emmc_part_offset[btn_idx]; + lv_obj_set_style(bg, &lv_style_transp); + _create_window_emummc(); + } + + memset(&emummc_part_cfg, 0, sizeof(emummc_part_cfg)); + + mbox_action(btns, txt); + + return LV_RES_INV; +} + +static lv_res_t _create_emummc_emmc_raw_format(lv_obj_t * btns, const char * txt) +{ + int btn_idx = lv_btnm_get_pressed(btns); + + // Delete parent mbox. + mbox_action(btns, txt); + + // Create partition window. + if (!btn_idx) + create_window_partition_manager(btns, DRIVE_EMMC); + + memset(&emummc_part_cfg, 0, sizeof(emummc_part_cfg)); + + return LV_RES_INV; +} + static void _create_mbox_emummc_raw() { lv_obj_t *dark_bg = lv_obj_create(lv_scr_act(), NULL); @@ -235,14 +286,14 @@ static void _create_mbox_emummc_raw() bool valid_part = (part_type != 0x83) && (part_type != 0xEE) && (part_type != 0xFF); // Check if at least 4GB and start above 16MB. - if ((part_size >= 0x80F000) && part_start > 0x8000 && valid_part) + if ((part_size >= 0x80F000) && part_start >= 0x8000 && valid_part) { mbr_ctx.available |= BIT(i - 1); mbr_ctx.sector[i - 1] = part_start; - // Only allow up to 16GB resized emuMMC. - // TODO: why? - if (part_size <= 0x2010000) + // *Why?* Only allow up to 16GB resized emuMMC. + // if (part_size < 0x2010000) + if (part_size < emmc_size_safe) mbr_ctx.resized_cnt[i - 1] = part_size - 0xC000; // Save sectors count without protective size and BOOT0/1. else if (part_size >= emmc_size_safe) mbr_ctx.resized_cnt[i - 1] = 0; @@ -313,23 +364,117 @@ static void _create_mbox_emummc_raw() lv_obj_set_top(mbox, true); } +static void _create_mbox_emummc_emmc_raw() +{ + // On SD, emummc partitions always have an MBR entry + + 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_format[] = { "\222Continue", "\222Cancel", "" }; + 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); + + char *txt_buf = (char *)malloc(SZ_16K); + mbr_t *mbr = (mbr_t *)malloc(sizeof(mbr_t)); + gpt_t *gpt = zalloc(sizeof *gpt); + + u32 emmc_safe_size; + + memset(&gpt_ctx, 0, sizeof(gpt_ctx)); + + emmc_mount(); + emmc_safe_size = emmc_storage.sec_cnt + 0xc000; + + sdmmc_storage_read(&emmc_storage, 0, 1, mbr); + + bool has_gpt = mbr_has_gpt(mbr); + + if(has_gpt){ + sdmmc_storage_read(&emmc_storage, 1, sizeof(*gpt) / 0x200, gpt); + + // TODO: should check for emummc guid instead + // TODO: currently hard limited to 3 entries + s32 gpt_idx = gpt_get_part_by_name(gpt, "emummc", -1); + while(gpt_idx != -1){ + u32 offset = gpt->entries[gpt_idx].lba_start; + u32 size = gpt->entries[gpt_idx].lba_end - gpt->entries[gpt_idx].lba_start + 1; + + if(size >= 0x80f000 && offset >= 0x8000){ + gpt_ctx.emmc_part_idx[gpt_ctx.emmc_part_cnt] = gpt_idx; + gpt_ctx.emmc_part_size[gpt_ctx.emmc_part_cnt] = size; + gpt_ctx.emmc_part_offset[gpt_ctx.emmc_part_cnt] = offset; + + if(size < emmc_safe_size){ + gpt_ctx.emmc_part_resize_cnt[gpt_ctx.emmc_part_cnt] = size - 0xc000; + } + + gpt_ctx.emmc_part_cnt++; + } + + gpt_idx = gpt_get_part_by_name(gpt, "emummc", gpt_idx); + } + } + + emmc_end(); + + static char mbox_btn_parts_strs[5][16]; + static char *mbox_btn_parts[] = {(char*)&mbox_btn_parts_strs[0], (char*)&mbox_btn_parts_strs[1], (char*)&mbox_btn_parts_strs[2], (char*)&mbox_btn_parts_strs[3], (char*)&mbox_btn_parts_strs[4]}; + + if(gpt_ctx.emmc_part_cnt){ + s_printf(txt_buf, "#C7EA46 Found applicable partition(s)!#\n" + "#FF8000 Choose a partition to continue:#\n\n"); + for(u32 i = 0; i < gpt_ctx.emmc_part_cnt; i++){ + char name[36]; + wctombs(gpt->entries[gpt_ctx.emmc_part_idx[i]].name, name, 36); + s_printf(txt_buf + strlen(txt_buf), "#%s Part. %d (%s): Start: 0x%x, Size. 0x%x#\n", gpt_ctx.emmc_part_resize_cnt[i] ? "FFDD00" : "C7EA46", gpt_ctx.emmc_part_idx[i], name, gpt_ctx.emmc_part_offset[i], gpt_ctx.emmc_part_size[i]); + s_printf(mbox_btn_parts[i], "\222Part. %d", gpt_ctx.emmc_part_idx[i]); + } + s_printf(mbox_btn_parts[gpt_ctx.emmc_part_cnt], "Cancel"); + mbox_btn_parts[gpt_ctx.emmc_part_cnt + 1][0] = '\0'; + strcat(txt_buf, "\n#FFDD00 Note:# Yellow entries have USER partition resized."); + + lv_mbox_add_btns(mbox, (const char **)mbox_btn_parts, _create_emummc_emmc_raw_action); + }else{ + s_printf(txt_buf, "#FFDD00 Failed to find applicable partition!#\n\n" + "#FF8000 Do you want to partition the eMMC?#\n" + "#FF8000 (You will be asked on how to proceed)#"); + + lv_mbox_add_btns(mbox, mbox_btn_format, _create_emummc_emmc_raw_format); + } + + + lv_mbox_set_text(mbox, txt_buf); + free(txt_buf); + free(mbr); + free(gpt); + + lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0); + lv_obj_set_top(mbox, true); +} + static lv_res_t _create_emummc_action(lv_obj_t * btns, const char * txt) { int btn_idx = lv_btnm_get_pressed(btns); lv_obj_t *bg = lv_obj_get_parent(lv_obj_get_parent(btns)); - mbr_ctx.part_idx = 0; - mbr_ctx.sector_start = 0; + memset(&emummc_part_cfg, 0, sizeof(emummc_part_cfg)); switch (btn_idx) { case 0: lv_obj_set_style(bg, &lv_style_transp); + emummc_part_cfg.file_based = true; _create_window_emummc(); break; case 1: _create_mbox_emummc_raw(); break; + case 2: + _create_mbox_emummc_emmc_raw(); + break; } mbox_action(btns, txt); @@ -346,7 +491,7 @@ static lv_res_t _create_mbox_emummc_create(lv_obj_t *btn) 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[] = { "\222SD File", "\222SD Partition", "\222Cancel", "" }; + static const char * mbox_btn_map[] = { "\222SD File", "\222SD Partition", "\222eMMC Partition", "\222Cancel", "" }; 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); @@ -354,8 +499,8 @@ static lv_res_t _create_mbox_emummc_create(lv_obj_t *btn) lv_mbox_set_text(mbox, "Welcome to #C7EA46 emuMMC# creation tool!\n\n" "Please choose what type of emuMMC you want to create.\n" - "#FF8000 SD File# is saved as files in the FAT partition.\n" - "#FF8000 SD Partition# is saved as raw image in an available partition."); + "#FF8000 SD File# is saved as files in the SD FAT partition.\n" + "#FF8000 SD# and #FF8000 eMMC Partition# is saved as raw image in an available partition."); lv_mbox_add_btns(mbox, mbox_btn_map, _create_emummc_action); @@ -367,20 +512,23 @@ static lv_res_t _create_mbox_emummc_create(lv_obj_t *btn) static void _change_raw_emummc_part_type() { - mbr_t *mbr = (mbr_t *)malloc(sizeof(mbr_t)); - sdmmc_storage_read(&sd_storage, 0, 1, mbr); - mbr->partitions[mbr_ctx.part_idx].type = 0xE0; - sdmmc_storage_write(&sd_storage, 0, 1, mbr); - free(mbr); + // On eMMC, we only consider partitions with the right type GUID to begin with + if(emummc_part_cfg.drive == DRIVE_SD){ + mbr_t *mbr = (mbr_t *)malloc(sizeof(mbr_t)); + sdmmc_storage_read(&sd_storage, 0, 1, mbr); + mbr->partitions[mbr_ctx.part_idx].type = 0xE0; + sdmmc_storage_write(&sd_storage, 0, 1, mbr); + free(mbr); + } } static lv_res_t _save_emummc_cfg_mig_mbox_action(lv_obj_t *btns, const char *txt) { // Delete main emuMMC and popup windows and relaunch main emuMMC window. - lv_obj_del(emummc_manage_window); + lv_obj_clean(emummc_parent_cont); mbox_action(btns, txt); - (*emummc_tools)(NULL); + (*emummc_tools)(emummc_parent_cont); return LV_RES_INV; } @@ -398,7 +546,7 @@ static void _create_emummc_migrated_mbox() lv_mbox_set_text(mbox, "#FF8000 emuMMC Configuration#\n\n" - "#96FF00 The emuMMC configuration#\n#96FF00 was saved to sd card!#"); + "#96FF00 The emuMMC configuration#\n#96FF00 was saved!#"); lv_mbox_add_btns(mbox, mbox_btn_map, _save_emummc_cfg_mig_mbox_action); @@ -420,7 +568,7 @@ static void _migrate_sd_raw_based() f_write(&fp, &mbr_ctx.sector_start, 4, NULL); f_close(&fp); - save_emummc_cfg(1, mbr_ctx.sector_start, "emuMMC/ER00"); + save_emummc_cfg(1, emummc_part_cfg.sector, "emuMMC/ER00", 0); _create_emummc_migrated_mbox(); boot_storage_unmount(); } @@ -428,7 +576,7 @@ static void _migrate_sd_raw_based() static void _migrate_sd_raw_emummc_based() { char *tmp = (char *)malloc(0x80); - s_printf(tmp, "emuMMC/RAW%d", mbr_ctx.part_idx); + s_printf(tmp, "emuMMC/RAW%d", emummc_part_cfg.part_idx); boot_storage_mount(); sd_mount(); @@ -439,15 +587,15 @@ static void _migrate_sd_raw_emummc_based() FIL fp; if (!f_open(&fp, tmp, FA_CREATE_ALWAYS | FA_WRITE)) { - f_write(&fp, &mbr_ctx.sector_start, 4, NULL); + f_write(&fp, &emummc_part_cfg.sector, 4, NULL); f_close(&fp); } - s_printf(tmp, "emuMMC/RAW%d", mbr_ctx.part_idx); + s_printf(tmp, "emuMMC/RAW%d", emummc_part_cfg.part_idx); _change_raw_emummc_part_type(); - save_emummc_cfg(mbr_ctx.part_idx, mbr_ctx.sector_start, tmp); + save_emummc_cfg(emummc_part_cfg.part_idx, emummc_part_cfg.sector, tmp, DRIVE_SD); _create_emummc_migrated_mbox(); free(tmp); @@ -491,12 +639,66 @@ static void _migrate_sd_file_based() free(path); free(path2); - save_emummc_cfg(0, 0, "emuMMC/EF00"); + save_emummc_cfg(0, 0, "emuMMC/EF00",0 ); _create_emummc_migrated_mbox(); sd_unmount(); boot_storage_unmount(); } +static u32 _copy_file(const char *src, const char* dest){ + u32 res = FR_OK; + u8 *buf = (u8*)MIXD_BUF_ALIGNED; + FIL fs; + FIL fd; + DWORD *clmnt_s = NULL; + DWORD *clmnt_d = NULL; + + res = f_open(&fs, src, FA_READ); + if(res != FR_OK){ + goto error; + } + + res = f_open(&fd, src, FA_WRITE | FA_CREATE_ALWAYS); + if(res != FR_OK){ + f_close(&fs); + goto error; + } + + u32 sz = f_size(&fs); + + clmnt_d = f_expand_cltbl(&fd, SZ_4M, sz); + clmnt_s = f_expand_cltbl(&fs, SZ_4M, sz); + + for(u32 i = 0; i < sz; i += SZ_4M){ + // 4M at a time + u32 btr = MIN(SZ_4M, sz - i); + + res = f_read_fast(&fs, buf, btr); + + if(res != FR_OK){ + res = f_write_fast(&fd, buf, btr); + } + + if(res != FR_OK){ + break; + } + } + + if(res != FR_OK){ + f_close(&fd); + f_unlink(dest); + }else{ + f_close(&fd); + } + + f_close(&fs); + free(clmnt_s); + free(clmnt_d); + + error: + return res; +} + static void _migrate_sd_backup_file_based() { char *emu_path = (char *)malloc(128); @@ -536,16 +738,24 @@ static void _migrate_sd_backup_file_based() else emmcsn_path_impl(backup_path, "/emummc", "", NULL); - // TODO: f_rename wont work if src/dst are on different drives - // Move BOOT0. + // rename if on sd, copy otherwise s_printf(backup_file_path, "%s/BOOT0", backup_path); strcpy(emu_path + base_len, "/eMMC/BOOT0"); - f_rename(backup_file_path, emu_path); + if(boot_storage_get_drive() == DRIVE_SD){ + f_rename(backup_file_path, emu_path); + }else{ + _copy_file(backup_file_path, emu_path); + } - // Move BOOT1. + // rename if on sd, copy otherwise s_printf(backup_file_path, "%s/BOOT1", backup_path); strcpy(emu_path + base_len, "/eMMC/BOOT1"); - f_rename(backup_file_path, emu_path); + if(boot_storage_get_drive() == DRIVE_SD){ + f_rename(backup_file_path, emu_path); + }else{ + _copy_file(backup_file_path, emu_path); + } + // Move raw GPP. bool multipart = false; @@ -557,7 +767,11 @@ static void _migrate_sd_backup_file_based() if (!multipart) { strcpy(emu_path + base_len, "/eMMC/00"); - f_rename(backup_file_path, emu_path); + if(boot_storage_get_drive() == DRIVE_SD){ + f_rename(backup_file_path, emu_path); + }else{ + _copy_file(backup_file_path, emu_path); + } } else { @@ -566,8 +780,15 @@ static void _migrate_sd_backup_file_based() { s_printf(backup_file_path, "%s/rawnand.bin.%02d", backup_path, i); s_printf(parts_path, "%s/eMMC/%02d", emu_path, i); - if (f_rename(backup_file_path, parts_path)) + u32 res; + if(boot_storage_get_drive() == DRIVE_SD){ + res = f_rename(backup_file_path, parts_path); + }else{ + res = _copy_file(backup_file_path, parts_path); + } + if(res != FR_OK){ break; + } } } @@ -576,7 +797,7 @@ static void _migrate_sd_backup_file_based() free(backup_path); free(backup_file_path); - save_emummc_cfg(0, 0, "emuMMC/BK00"); + save_emummc_cfg(0, 0, "emuMMC/BK00", 0); _create_emummc_migrated_mbox(); sd_unmount(); boot_storage_unmount(); @@ -594,8 +815,7 @@ static lv_res_t _create_emummc_mig1_action(lv_obj_t * btns, const char * txt) break; } - mbr_ctx.part_idx = 0; - mbr_ctx.sector_start = 0; + memset(&emummc_part_cfg, 0, sizeof(emummc_part_cfg)); mbox_action(btns, txt); @@ -611,8 +831,7 @@ static lv_res_t _create_emummc_mig0_action(lv_obj_t * btns, const char * txt) break; } - mbr_ctx.part_idx = 0; - mbr_ctx.sector_start = 0; + memset(&emummc_part_cfg, 0, sizeof(emummc_part_cfg)); mbox_action(btns, txt); @@ -628,8 +847,7 @@ static lv_res_t _create_emummc_mig2_action(lv_obj_t * btns, const char * txt) break; } - mbr_ctx.part_idx = 0; - mbr_ctx.sector_start = 0; + memset(&emummc_part_cfg, 0, sizeof(emummc_part_cfg)); mbox_action(btns, txt); @@ -645,8 +863,7 @@ static lv_res_t _create_emummc_mig3_action(lv_obj_t * btns, const char * txt) break; } - mbr_ctx.part_idx = 0; - mbr_ctx.sector_start = 0; + memset(&emummc_part_cfg, 0, sizeof(emummc_part_cfg)); mbox_action(btns, txt); @@ -662,8 +879,7 @@ static lv_res_t _create_emummc_mig4_action(lv_obj_t * btns, const char * txt) break; } - mbr_ctx.part_idx = 0; - mbr_ctx.sector_start = 0; + memset(&emummc_part_cfg, 0, sizeof(emummc_part_cfg)); mbox_action(btns, txt); @@ -765,6 +981,12 @@ static lv_res_t _create_emummc_migrate_action(lv_obj_t * btns, const char * txt) typedef struct _emummc_images_t { dirlist_t *dirlist; + + u32 emmc_part_sector[3]; + u32 emmc_part_end[3]; + u32 emmc_part_idx[3]; + char emmc_part_path[3][128]; + u32 part_sector[3]; u32 part_type[3]; u32 part_end[3]; @@ -793,6 +1015,7 @@ static lv_res_t _create_mbox_emummc_migrate(lv_obj_t *btn) u8 *efi_part = (u8 *)malloc(0x200); sd_mount(); + boot_storage_mount(); sdmmc_storage_read(&sd_storage, 0, 1, mbr); emmc_initialize(false); @@ -803,8 +1026,7 @@ static lv_res_t _create_mbox_emummc_migrate(lv_obj_t *btn) bool emummc = false; bool rawnand_backup = false; - mbr_ctx.sector_start = 0; - mbr_ctx.part_idx = 0; + memset(&emummc_part_cfg, 0, sizeof(emummc_part_cfg)); // Try to find a partition based emuMMC. for (int i = 1; i < 4; i++) @@ -817,9 +1039,9 @@ static lv_res_t _create_mbox_emummc_migrate(lv_obj_t *btn) sdmmc_storage_read(&sd_storage, mbr_ctx.sector_start + 0xC001, 1, efi_part); if (!memcmp(efi_part, "EFI PART", 8)) { - mbr_ctx.sector_start += 0x8000; emummc = true; - mbr_ctx.part_idx = i; + emummc_part_cfg.sector += 0x8000; + emummc_part_cfg.part_idx = i; break; } else @@ -828,7 +1050,7 @@ static lv_res_t _create_mbox_emummc_migrate(lv_obj_t *btn) if (!memcmp(efi_part, "EFI PART", 8)) { emummc = true; - mbr_ctx.part_idx = i; + emummc_part_cfg.part_idx = i; break; } } @@ -883,6 +1105,7 @@ static lv_res_t _create_mbox_emummc_migrate(lv_obj_t *btn) } sd_unmount(); + boot_storage_unmount(); emmc_end(); // Check available types and enable the corresponding buttons. @@ -918,12 +1141,12 @@ static lv_res_t _save_emummc_cfg_mbox_action(lv_obj_t *btns, const char *txt) // Free components, delete main emuMMC and popup windows and relaunch main emuMMC window. free(emummc_img->dirlist); lv_obj_del(emummc_img->win); - lv_obj_del(emummc_manage_window); + lv_obj_clean(emummc_parent_cont); free(emummc_img); mbox_action(btns, txt); - (*emummc_tools)(NULL); + (*emummc_tools)(emummc_parent_cont); return LV_RES_INV; } @@ -955,13 +1178,35 @@ static lv_res_t _save_raw_emummc_cfg_action(lv_obj_t * btn) switch (ext->idx) { case 0: - save_emummc_cfg(1, emummc_img->part_sector[0], &emummc_img->part_path[0]); + save_emummc_cfg(1, emummc_img->part_sector[0], &emummc_img->part_path[0], DRIVE_SD); break; case 1: - save_emummc_cfg(2, emummc_img->part_sector[1], &emummc_img->part_path[128]); + save_emummc_cfg(2, emummc_img->part_sector[1], &emummc_img->part_path[128], DRIVE_SD); break; case 2: - save_emummc_cfg(3, emummc_img->part_sector[2], &emummc_img->part_path[256]); + save_emummc_cfg(3, emummc_img->part_sector[2], &emummc_img->part_path[256], DRIVE_SD); + break; + } + + _create_emummc_saved_mbox(); + sd_unmount(); + + return LV_RES_INV; +} + +static lv_res_t _save_emmc_raw_emummc_cfg_action(lv_obj_t * btn) +{ + lv_btn_ext_t *ext = lv_obj_get_ext_attr(btn); + switch (ext->idx) + { + case 0: + save_emummc_cfg(1, emummc_img->emmc_part_sector[0], (char*)&emummc_img->emmc_part_path[0], DRIVE_EMMC); + break; + case 1: + save_emummc_cfg(2, emummc_img->emmc_part_sector[1], (char*)&emummc_img->emmc_part_path[1], DRIVE_EMMC); + break; + case 2: + save_emummc_cfg(3, emummc_img->emmc_part_sector[2], (char*)&emummc_img->emmc_part_path[2], DRIVE_EMMC); break; } @@ -973,7 +1218,7 @@ static lv_res_t _save_raw_emummc_cfg_action(lv_obj_t * btn) static lv_res_t _save_disable_emummc_cfg_action(lv_obj_t * btn) { - save_emummc_cfg(0, 0, NULL); + save_emummc_cfg(0, 0, NULL, 0); _create_emummc_saved_mbox(); sd_unmount(); @@ -982,7 +1227,7 @@ static lv_res_t _save_disable_emummc_cfg_action(lv_obj_t * btn) static lv_res_t _save_file_emummc_cfg_action(lv_obj_t *btn) { - save_emummc_cfg(0, 0, lv_list_get_btn_text(btn)); + save_emummc_cfg(0, 0, lv_list_get_btn_text(btn), 0); _create_emummc_saved_mbox(); sd_unmount(); boot_storage_unmount(); @@ -995,12 +1240,15 @@ static lv_res_t _create_change_emummc_window(lv_obj_t *btn_caller) lv_obj_t *win = nyx_create_standard_window(SYMBOL_SETTINGS" Change emuMMC"); lv_win_add_btn(win, NULL, SYMBOL_POWER" Disable", _save_disable_emummc_cfg_action); + boot_storage_mount(); sd_mount(); + emmc_mount(); - emummc_img = malloc(sizeof(emummc_images_t)); + emummc_img = zalloc(sizeof(emummc_images_t)); emummc_img->win = win; mbr_t *mbr = (mbr_t *)malloc(sizeof(mbr_t)); + gpt_t *gpt = (gpt_t*)malloc(sizeof(gpt_t)); char *path = malloc(512); sdmmc_storage_read(&sd_storage, 0, 1, mbr); @@ -1013,7 +1261,6 @@ static lv_res_t _create_change_emummc_window(lv_obj_t *btn_caller) emummc_img->part_end[i - 1] = emummc_img->part_sector[i - 1] + mbr->partitions[i].size_sct - 1; emummc_img->part_type[i - 1] = mbr->partitions[i].type; } - free(mbr); emummc_img->dirlist = dirlist("emuMMC", NULL, false, true); @@ -1062,6 +1309,50 @@ static lv_res_t _create_change_emummc_window(lv_obj_t *btn_caller) emummc_idx++; } + + u32 emmc_cnt = 0; + sdmmc_storage_read(&emmc_storage, 0, 1, mbr); + if(mbr_has_gpt(mbr)){ + sdmmc_storage_read(&emmc_storage, 1, sizeof(gpt_t) / 0x200, gpt); + + s32 gpt_idx = gpt_get_part_by_name(gpt, "emummc", -1); + while(gpt_idx != -1 && emmc_cnt < 3){ + emummc_img->emmc_part_sector[emmc_cnt] = gpt->entries[gpt_idx].lba_start; + emummc_img->emmc_part_end[emmc_cnt] = gpt->entries[gpt_idx].lba_end; + emummc_img->emmc_part_idx[emmc_cnt] = gpt_idx; + + emmc_cnt++; + gpt_idx = gpt_get_part_by_name(gpt, "emummc", gpt_idx); + } + } + + free(gpt); + free(mbr); + + emummc_idx = 0; + + // Check for eMMC raw partitions, based on the folders in /emuMMC + while(emummc_img->dirlist->name[emummc_idx]){ + s_printf(path, "emuMMC/%s/raw_emmc_based", emummc_img->dirlist->name[emummc_idx]); + + if(!f_stat(path, NULL)){ + f_open(&fp, path, FA_READ); + u32 sector = 0; + f_read(&fp, §or, 4, NULL); + f_close(&fp); + + for(u32 i = 0; i < emmc_cnt; i++){ + if(sector && sector >= emummc_img->emmc_part_sector[i] && sector <= emummc_img->emmc_part_end[i]){ + emummc_img->emmc_part_sector[i] = sector; + emummc_img->emmc_part_end[i] = 0; + s_printf((char*)&emummc_img->emmc_part_path[i], "emuMMC/%s", emummc_img->dirlist->name[emummc_idx]); + } + } + } + emummc_idx++; + } + + emummc_idx = 0; u32 file_based_idx = 0; @@ -1091,7 +1382,7 @@ out0:; lv_obj_t *h1 = lv_cont_create(win, NULL); lv_cont_set_style(h1, &h_style); lv_cont_set_fit(h1, false, true); - lv_obj_set_width(h1, (LV_HOR_RES / 9) * 4); + lv_obj_set_width(h1, (LV_HOR_RES / 17) * 4); lv_obj_set_click(h1, false); lv_cont_set_layout(h1, LV_LAYOUT_OFF); @@ -1104,7 +1395,7 @@ out0:; lv_obj_align(label_txt, label_sep, LV_ALIGN_OUT_BOTTOM_LEFT, LV_DPI / 4, -(LV_DPI / 2)); lv_obj_t *line_sep = lv_line_create(h1, NULL); - static const lv_point_t line_pp[] = { {0, 0}, { LV_HOR_RES - (LV_DPI - (LV_DPI / 4)) * 2, 0} }; + static const lv_point_t line_pp[] = { {0, 0}, { LV_HOR_RES - (LV_DPI - (LV_DPI / 2)) * 2, 0} }; lv_line_set_points(line_sep, line_pp, 2); lv_line_set_style(line_sep, lv_theme_get_current()->line.decor); lv_obj_align(line_sep, label_txt, LV_ALIGN_OUT_BOTTOM_LEFT, -(LV_DPI / 4), LV_DPI / 8); @@ -1144,8 +1435,8 @@ out0:; if (!raw_btn_idx) { lv_btn_set_fit(btn, false, true); - lv_obj_set_width(btn, LV_DPI * 3); - lv_obj_align(btn, line_sep, LV_ALIGN_OUT_BOTTOM_LEFT, LV_DPI / 2, LV_DPI / 5); + lv_obj_set_width(btn, LV_DPI * 2 + LV_DPI / 2); + lv_obj_align(btn, line_sep, LV_ALIGN_OUT_BOTTOM_LEFT, LV_DPI / 3, LV_DPI / 5); } else lv_obj_align(btn, lv_desc, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI / 3); @@ -1160,16 +1451,78 @@ out0:; lv_label_set_text(lv_desc, txt_buf); lv_obj_align(lv_desc, btn, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI / 5); } + + + // Create eMMC Raw container + lv_obj_t *h3 = lv_cont_create(win, NULL); + lv_cont_set_style(h3, &h_style); + lv_cont_set_fit(h3, false, true); + lv_obj_set_width(h3, (LV_HOR_RES / 17) * 4); + lv_obj_set_click(h3, false); + lv_cont_set_layout(h3, LV_LAYOUT_OFF); + + label_sep = lv_label_create(h3, NULL); + lv_label_set_static_text(label_sep, ""); + + lv_obj_t *label_txt2 = lv_label_create(h3, NULL); + lv_label_set_static_text(label_txt2, "eMMC Raw Partitions"); + lv_obj_set_style(label_txt2, lv_theme_get_current()->label.prim); + lv_obj_align(label_txt2, label_sep, LV_ALIGN_OUT_BOTTOM_LEFT, LV_DPI * 2 / 9, -(LV_DPI / 2)); + + line_sep = lv_line_create(h3, line_sep); + lv_obj_align(line_sep, label_txt2, LV_ALIGN_OUT_BOTTOM_LEFT, -(LV_DPI / 4), LV_DPI / 8); + lv_line_set_style(line_sep, lv_theme_get_current()->line.decor); + + for (u32 i = 0; i < 3; i++){ + btn = lv_btn_create(h3, btn); + ext = lv_obj_get_ext_attr(btn); + ext->idx = i; + btn_label = lv_label_create(btn, btn_label); + + lv_btn_set_state(btn, LV_BTN_STATE_REL); + lv_obj_set_click(btn, true); + + s_printf(txt_buf, "eMMC RAW %d", i + 1); + lv_label_set_text(btn_label, txt_buf); + + if (!emummc_img->emmc_part_sector[i] || !emummc_img->emmc_part_path[i][0]) + { + lv_btn_set_state(btn, LV_BTN_STATE_INA); + lv_obj_set_click(btn, false); + } + + if (!i) + { + lv_btn_set_fit(btn, false, true); + lv_obj_set_width(btn, LV_DPI * 2 + LV_DPI / 2); + lv_obj_align(btn, line_sep, LV_ALIGN_OUT_BOTTOM_LEFT, LV_DPI / 3, LV_DPI / 5); + } + else + lv_obj_align(btn, lv_desc, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI / 3); + + lv_btn_set_action(btn, LV_BTN_ACTION_CLICK, _save_emmc_raw_emummc_cfg_action); + + lv_desc = lv_label_create(h3, lv_desc); + lv_label_set_recolor(lv_desc, true); + lv_obj_set_style(lv_desc, &hint_small_style); + + s_printf(txt_buf, "Sector start: 0x%08X\nFolder: %s", emummc_img->emmc_part_sector[i], (char*)&emummc_img->emmc_part_path[i]); + lv_label_set_text(lv_desc, txt_buf); + lv_obj_align(lv_desc, btn, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI / 5); + } + + lv_obj_align(h3, h1, LV_ALIGN_OUT_RIGHT_TOP, LV_DPI / 2, 0); + free(txt_buf); // Create SD File Based container. lv_obj_t *h2 = lv_cont_create(win, NULL); lv_cont_set_style(h2, &h_style); lv_cont_set_fit(h2, false, true); - lv_obj_set_width(h2, (LV_HOR_RES / 9) * 4); + lv_obj_set_width(h2, LV_HOR_RES * 2 / 5); lv_obj_set_click(h2, false); lv_cont_set_layout(h2, LV_LAYOUT_OFF); - lv_obj_align(h2, h1, LV_ALIGN_OUT_RIGHT_TOP, LV_DPI * 17 / 29, 0); + lv_obj_align(h2, h3, LV_ALIGN_OUT_RIGHT_TOP, LV_DPI / 2, 0); label_sep = lv_label_create(h2, NULL); lv_label_set_static_text(label_sep, ""); @@ -1177,7 +1530,7 @@ out0:; lv_obj_t *label_txt3 = lv_label_create(h2, NULL); lv_label_set_static_text(label_txt3, "SD File Based"); lv_obj_set_style(label_txt3, lv_theme_get_current()->label.prim); - lv_obj_align(label_txt3, label_sep, LV_ALIGN_OUT_BOTTOM_LEFT, LV_DPI / 4, -LV_DPI / 7); + lv_obj_align(label_txt3, label_sep, LV_ALIGN_OUT_BOTTOM_LEFT, LV_DPI * 2 / 9, -LV_DPI / 7); line_sep = lv_line_create(h2, line_sep); lv_obj_align(line_sep, label_txt3, LV_ALIGN_OUT_BOTTOM_LEFT, -(LV_DPI / 2), LV_DPI / 8); @@ -1186,7 +1539,7 @@ out0:; lv_obj_t *list_sd_based = lv_list_create(h2, NULL); lv_obj_align(list_sd_based, line_sep, LV_ALIGN_OUT_BOTTOM_LEFT, LV_DPI / 2, LV_DPI / 4); - lv_obj_set_size(list_sd_based, LV_HOR_RES * 4 / 10, LV_VER_RES * 6 / 10); + lv_obj_set_size(list_sd_based, LV_HOR_RES * 4 / 10 - (LV_DPI / 2), LV_VER_RES * 6 / 10); lv_list_set_single_mode(list_sd_based, true); if (!emummc_img->dirlist) @@ -1207,17 +1560,15 @@ out0:; out1: free(path); sd_unmount(); + boot_storage_unmount(); return LV_RES_OK; } -lv_res_t create_win_emummc_tools(lv_obj_t *btn) +lv_res_t create_tab_emummc_tools(lv_obj_t *parent) { - lv_obj_t *win = nyx_create_standard_window(SYMBOL_EDIT" emuMMC Manage"); - - // Set resources to be managed by other windows. - emummc_manage_window = win; - emummc_tools = (void *)create_win_emummc_tools; + emummc_parent_cont = parent; + emummc_tools = &create_tab_emummc_tools; boot_storage_mount(); @@ -1233,7 +1584,7 @@ lv_res_t create_win_emummc_tools(lv_obj_t *btn) h_style.body.padding.ver = LV_DPI / 9; // Create emuMMC Info & Selection container. - lv_obj_t *h1 = lv_cont_create(win, NULL); + lv_obj_t *h1 = lv_cont_create(parent, NULL); lv_cont_set_style(h1, &h_style); lv_cont_set_fit(h1, false, true); lv_obj_set_width(h1, (LV_HOR_RES / 9) * 4); @@ -1246,7 +1597,7 @@ lv_res_t create_win_emummc_tools(lv_obj_t *btn) lv_obj_t *label_txt = lv_label_create(h1, NULL); lv_label_set_static_text(label_txt, "emuMMC Info & Selection"); lv_obj_set_style(label_txt, lv_theme_get_current()->label.prim); - lv_obj_align(label_txt, label_sep, LV_ALIGN_OUT_BOTTOM_LEFT, LV_DPI / 4, -LV_DPI / 9); + lv_obj_align(label_txt, h1, LV_ALIGN_IN_TOP_LEFT, LV_DPI / 4, -LV_DPI / 9); lv_obj_t *line_sep = lv_line_create(h1, NULL); static const lv_point_t line_pp[] = { {0, 0}, { LV_HOR_RES - (LV_DPI - (LV_DPI / 4)) * 2, 0} }; @@ -1266,7 +1617,10 @@ lv_res_t create_win_emummc_tools(lv_obj_t *btn) if (emu_info.enabled) { - if (emu_info.sector) + if(emu_info.enabled == 4){ + s_printf(txt_buf, "#00DDFF Type:# eMMC Raw Partition\n#00DDFF Sector:# 0x%08X\n#00DDFF Nintendo folder:# %s", + emu_info.sector, emu_info.nintendo_path ? emu_info.nintendo_path : ""); + }else if (emu_info.sector) s_printf(txt_buf, "#00DDFF Type:# SD Raw Partition\n#00DDFF Sector:# 0x%08X\n#00DDFF Nintendo folder:# %s", emu_info.sector, emu_info.nintendo_path ? emu_info.nintendo_path : ""); else @@ -1308,7 +1662,7 @@ lv_res_t create_win_emummc_tools(lv_obj_t *btn) lv_obj_align(label_txt2, btn2, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI / 3); // Create emuMMC Tools container. - lv_obj_t *h2 = lv_cont_create(win, NULL); + lv_obj_t *h2 = lv_cont_create(parent, NULL); lv_cont_set_style(h2, &h_style); lv_cont_set_fit(h2, false, true); lv_obj_set_width(h2, (LV_HOR_RES / 9) * 4); @@ -1322,7 +1676,7 @@ lv_res_t create_win_emummc_tools(lv_obj_t *btn) lv_obj_t *label_txt3 = lv_label_create(h2, NULL); lv_label_set_static_text(label_txt3, "emuMMC Tools"); lv_obj_set_style(label_txt3, lv_theme_get_current()->label.prim); - lv_obj_align(label_txt3, label_sep, LV_ALIGN_OUT_BOTTOM_LEFT, LV_DPI / 4, 0); + lv_obj_align(label_txt3, h2, LV_ALIGN_IN_TOP_LEFT, LV_DPI / 4, 0); line_sep = lv_line_create(h2, line_sep); lv_obj_align(line_sep, label_txt3, LV_ALIGN_OUT_BOTTOM_LEFT, -(LV_DPI / 4), LV_DPI / 8); @@ -1338,7 +1692,7 @@ lv_res_t create_win_emummc_tools(lv_obj_t *btn) lv_obj_t *label_txt4 = lv_label_create(h2, NULL); lv_label_set_recolor(label_txt4, true); lv_label_set_static_text(label_txt4, - "Allows you to create a new #C7EA46 SD File# or #C7EA46 SD Raw Partition#\n" + "Allows you to create a new #C7EA46 SD File#, #C7EA46 SD -# or #C7EA46 eMMC Raw Partition#\n" "emuMMC. You can create it from eMMC or a eMMC Backup."); lv_obj_set_style(label_txt4, &hint_small_style); @@ -1360,5 +1714,10 @@ lv_res_t create_win_emummc_tools(lv_obj_t *btn) lv_obj_set_style(label_txt4, &hint_small_style); lv_obj_align(label_txt4, btn4, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI / 3); + + lv_obj_align(h1, parent, LV_ALIGN_IN_TOP_LEFT, 0, 0); + lv_obj_align(h2, h1, LV_ALIGN_OUT_RIGHT_TOP, LV_DPI * 17 / 29, 0); + + return LV_RES_OK; } diff --git a/nyx/nyx_gui/frontend/gui_emummc_tools.h b/nyx/nyx_gui/frontend/gui_emummc_tools.h index d25bb325..2cb8bc36 100644 --- a/nyx/nyx_gui/frontend/gui_emummc_tools.h +++ b/nyx/nyx_gui/frontend/gui_emummc_tools.h @@ -19,6 +19,6 @@ #include -lv_res_t create_win_emummc_tools(lv_obj_t *btn); +lv_res_t create_tab_emummc_tools(lv_obj_t *parent); #endif diff --git a/nyx/nyx_gui/frontend/gui_emusd_tools.c b/nyx/nyx_gui/frontend/gui_emusd_tools.c new file mode 100644 index 00000000..aef18c51 --- /dev/null +++ b/nyx/nyx_gui/frontend/gui_emusd_tools.c @@ -0,0 +1,461 @@ +#include "gui_emusd_tools.h" +#include "fe_emusd_tools.h" +#include "gui_tools_partition_manager.h" +#include "gui.h" +#include +#include +#include +#include +#include +#include +#include "fe_emusd_tools.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +typedef struct _gpt_ctxt_t{ + u32 sector[3]; + u32 sector_mbr[3]; + u32 part_idx[3]; + u32 size[3]; + char name[3][36]; + u8 cnt; + u8 valid_parts[3]; + u8 valid_cnt; +} gpt_ctxt_t; + +static gpt_ctxt_t gpt_ctxt; + +static lv_obj_t *emusd_parent_cont; +static lv_res_t (*emusd_tools)(lv_obj_t *parent); + +static void _get_emusd_parts(gpt_t *gpt){ + u8 cnt = 0; + s32 gpt_idx = gpt_get_part_by_name(gpt, "emusd_mbr", -1); + while(gpt_idx != -1 && cnt < 3){ + u32 sector_mbr = gpt->entries[gpt_idx].lba_start; + gpt_idx = gpt_get_part_by_name(gpt, "emusd", gpt_idx); + if(gpt_idx == -1){ + // should never happen + continue; + } + + u32 sector = gpt->entries[gpt_idx].lba_start; + u32 size = gpt->entries[gpt_idx].lba_end - sector + 1; + + gpt_ctxt.sector_mbr[cnt] = sector_mbr; + gpt_ctxt.sector[cnt] = sector; + gpt_ctxt.part_idx[cnt] = gpt_idx; + gpt_ctxt.size[cnt] = size; + wctombs(gpt->entries[gpt_idx].name, gpt_ctxt.name[cnt], 36); + + cnt++; + + gpt_idx = gpt_get_part_by_name(gpt, "emusd", gpt_idx); + } + gpt_ctxt.cnt = cnt; +} + +static lv_res_t _close_mbox_and_reload(lv_obj_t *btns, const char *txt){ + lv_obj_clean(emusd_parent_cont); + mbox_action(btns, txt); + + (*emusd_tools)(emusd_parent_cont); + + return LV_RES_INV; +} + +static void _create_emusd(u8 idx){ + boot_storage_mount(); + emmc_initialize(false); + + + static const char *mbox_btn_map[] = { "\251", "\222OK", "\251", "" }; + + 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); + + 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); + + char *txt_buf = malloc(SZ_16K); + + strcpy(txt_buf, "#FF8000 emuSD creation tool#\n\n" + "#00DDFF Status:# Formatting emuSD partition..."); + + lv_mbox_set_text(mbox, txt_buf); + lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0); + lv_obj_set_top(mbox, true); + + manual_system_maintenance(true); + + int res = create_emusd(gpt_ctxt.part_idx[idx], gpt_ctxt.sector_mbr[idx], gpt_ctxt.sector[idx], gpt_ctxt.size[idx], gpt_ctxt.name[idx]); + + if(res == FR_OK){ + strcpy(txt_buf, "#FF8000 emuSD creation tool#\n\n" + "#00DDFF Status:# Done!"); + + char path[0x80]; + strcpy(path, "emuSD"); + f_mkdir(path); + s_printf(path + strlen(path), "/RAW_EMMC%d", gpt_ctxt.part_idx[idx]); + f_mkdir(path); + strcat(path, "/raw_emmc_based"); + + FIL f; + f_open(&f, path, FA_CREATE_ALWAYS | FA_WRITE); + f_write(&f, &gpt_ctxt.sector_mbr[idx], 4, NULL); + f_close(&f); + + save_emusd_cfg(gpt_ctxt.part_idx[idx], gpt_ctxt.sector_mbr[idx]); + }else{ + strcpy(txt_buf, "#FF8000 emuSD creation tool#\n\n" + "#00DDFF Status:# Failed to format partition!"); + } + + lv_mbox_set_text(mbox, txt_buf); + lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0); + lv_mbox_add_btns(mbox, mbox_btn_map, _close_mbox_and_reload); + manual_system_maintenance(true); + + boot_storage_unmount(); + emmc_end(); + + free(txt_buf); +} + +static lv_res_t _emusd_create_action(lv_obj_t *btns, const char *txt){ + u32 idx = lv_btnm_get_pressed(btns); + + mbox_action(btns, txt); + + if(idx < gpt_ctxt.cnt){ + _create_emusd(idx); + } + + return LV_RES_INV; +} + +static lv_res_t _emusd_format_action(lv_obj_t *btns, const char *txt){ + u32 idx = lv_btnm_get_pressed(btns); + + mbox_action(btns, txt); + + if(idx){ + create_window_partition_manager(btns, DRIVE_EMMC); + } + + return LV_RES_INV; +} + +static void _change_emusd(u8 idx){ + boot_storage_mount(); + save_emusd_cfg(gpt_ctxt.part_idx[gpt_ctxt.valid_parts[idx]], gpt_ctxt.sector_mbr[gpt_ctxt.valid_parts[idx]]); + boot_storage_unmount(); +} + +static lv_res_t _emusd_change_action(lv_obj_t *btns, const char *txt){ + u32 idx = lv_btnm_get_pressed(btns); + + if(idx < gpt_ctxt.valid_cnt){ + _change_emusd(idx); + _close_mbox_and_reload(btns, txt); + }else if(idx == gpt_ctxt.valid_cnt){ + boot_storage_mount(); + save_emusd_cfg(0, 0); + boot_storage_unmount(); + _close_mbox_and_reload(btns, txt); + }else{ + mbox_action(btns, txt); + } + + return LV_RES_INV; +} + +static lv_res_t _create_mbox_change_emusd(lv_obj_t *btn){ + boot_storage_mount(); + emmc_initialize(false); + + 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); + + 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); + + static char mbox_part_strs[6][0x10]; + static char *mbox_btn_parts[] = {mbox_part_strs[0], mbox_part_strs[1], mbox_part_strs[2], mbox_part_strs[3], mbox_part_strs[4], mbox_part_strs[5]}; + + dirlist_t *emusd_dir_list = dirlist("emuSD", NULL, false, true); + char path[0x80]; + mbr_t mbr = {0}; + gpt_t *gpt = NULL; + char *txt_buf = malloc(SZ_16K); + + u32 emusd_idx = 0; + FIL f; + + sdmmc_storage_read(&emmc_storage, 0, 1, &mbr); + + if(!mbr_has_gpt(&mbr)){ + goto out; + } + + gpt = zalloc(sizeof(*gpt)); + sdmmc_storage_read(&emmc_storage, 1, sizeof(*gpt) / 0x200, gpt); + + _get_emusd_parts(gpt); + + u8 cnt = 0; + + while(emusd_dir_list && emusd_dir_list->name[emusd_idx]){ + s_printf(path, "emuSD/%s/raw_emmc_based", emusd_dir_list->name[emusd_idx]); + if(f_stat(path, NULL) == FR_OK){ + f_open(&f, path, FA_READ); + u32 sector = 0; + f_read(&f, §or, 4, NULL); + f_close(&f); + + for(u32 i = 0; i < gpt_ctxt.cnt ; i++){ + if(sector == gpt_ctxt.sector_mbr[i]){ + s_printf(mbox_btn_parts[cnt], "Part %d", gpt_ctxt.part_idx[i]); + gpt_ctxt.valid_parts[cnt] = i; + cnt++; + } + } + } + emusd_idx++; + } + + gpt_ctxt.valid_cnt = cnt; + + strcpy(mbox_btn_parts[cnt], "Disable"); + strcpy(mbox_btn_parts[cnt + 1], "Cancel"); + mbox_btn_parts[cnt + 2][0] = 0; + + if(cnt){ + strcpy(txt_buf, "#C7EA46 Found emuSD partition(s)!#\n" + "#FF8000 Choose a partition or disable emuSD.#\n\n"); + for(u32 i = 0; i < cnt; i++){ + s_printf(txt_buf + strlen(txt_buf), "Part %d (%s): Start: 0x%x, Size: 0x%x\n", gpt_ctxt.part_idx[gpt_ctxt.valid_parts[i]], gpt_ctxt.name[gpt_ctxt.valid_parts[i]], gpt_ctxt.sector[gpt_ctxt.valid_parts[i]], gpt_ctxt.size[gpt_ctxt.valid_parts[i]]); + } + }else{ + strcpy(txt_buf, "#FF8000 No set up emuSD partitions found.\nFirst, create an emuSD\n#"); + } + + lv_mbox_set_text(mbox, txt_buf); + lv_mbox_add_btns(mbox, (const char **)mbox_btn_parts, _emusd_change_action); + lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0); + + out: + free(gpt); + free(emusd_dir_list); + + boot_storage_unmount(); + emmc_end(); + + return LV_RES_OK; +} + +static lv_res_t _create_mbox_emusd_create(lv_obj_t *btn){ + 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); + + 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); + + static char mbox_part_strs[5][0x10]; + static char *mbox_btn_parts[] = {mbox_part_strs[0], mbox_part_strs[1], mbox_part_strs[2], mbox_part_strs[3], mbox_part_strs[4]}; + static const char *mbox_btn_format[] = {"\222Continue", "\222Cancel", ""}; + + char *txt_buf = (char*)malloc(SZ_16K); + + emmc_initialize(false); + emmc_set_partition(EMMC_GPP); + + gpt_t *gpt = NULL; + mbr_t mbr = {0}; + u8 cnt = 0; + + sdmmc_storage_read(&emmc_storage, 0, 1, &mbr); + + if(mbr_has_gpt(&mbr)){ + gpt = zalloc(sizeof(*gpt)); + sdmmc_storage_read(&emmc_storage, 1, sizeof(*gpt) / 0x200, gpt); + + _get_emusd_parts(gpt); + + cnt = gpt_ctxt.cnt; + } + + if(cnt){ + s_printf(txt_buf, + "#C7EA46 Found applicable eMMC partition(s)!#\n" + "#FF8000 Choose a partition to continue:#\n\n"); + for(u32 i = 0; i < cnt; i++){ + char name[36]; + u8 idx = gpt_ctxt.part_idx[i]; + u32 size = gpt->entries[idx].lba_end - gpt->entries[idx].lba_start + 1; + wctombs(gpt->entries[idx].name, name, 36); + s_printf(txt_buf + strlen(txt_buf), "Part %d (%s): Start: 0x%x, Size: 0x%x\n", idx, name, gpt_ctxt.sector[i], size); + s_printf(mbox_btn_parts[i], "\222Part %d", gpt_ctxt.part_idx[i]); + + } + s_printf(mbox_btn_parts[cnt], "\222Cancel"); + mbox_btn_parts[cnt + 1][0] = '\0'; + + lv_mbox_add_btns(mbox, (const char **)mbox_btn_parts, _emusd_create_action); + }else{ + s_printf(txt_buf, "#FFDD00 Failed to find applicable partition!#\n\n" + "#FF8000 Do you want to partition the eMMC?#\n" + "#FF8000 (You will be asked on how to proceed)#"); + lv_mbox_add_btns(mbox, mbox_btn_format, _emusd_format_action); + } + + lv_mbox_set_text(mbox, txt_buf); + lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0); + + emmc_end(); + + free(txt_buf); + free(gpt); + + return LV_RES_OK; +} + +lv_res_t create_tab_emusd_tools(lv_obj_t *parent) +{ + emusd_parent_cont = parent; + emusd_tools = &create_tab_emusd_tools; + + boot_storage_mount(); + + emusd_cfg_t emu_info; + load_emusd_cfg(&emu_info); + + boot_storage_unmount(); + + static lv_style_t h_style; + lv_style_copy(&h_style, &lv_style_transp); + h_style.body.padding.inner = 0; + h_style.body.padding.hor = LV_DPI - (LV_DPI / 4); + h_style.body.padding.ver = LV_DPI / 9; + + // Create emuSD Info & Selection container. + lv_obj_t *h1 = lv_cont_create(parent, NULL); + lv_cont_set_style(h1, &h_style); + lv_cont_set_fit(h1, false, true); + lv_obj_set_width(h1, (LV_HOR_RES / 9) * 4); + lv_obj_set_click(h1, false); + lv_cont_set_layout(h1, LV_LAYOUT_OFF); + + lv_obj_t *label_sep = lv_label_create(h1, NULL); + lv_label_set_static_text(label_sep, ""); + + lv_obj_t *label_txt = lv_label_create(h1, NULL); + lv_label_set_static_text(label_txt, "emuSD Info & Selection"); + lv_obj_set_style(label_txt, lv_theme_get_current()->label.prim); + lv_obj_align(label_txt, h1, LV_ALIGN_IN_TOP_LEFT, LV_DPI / 4, -LV_DPI / 9); + + lv_obj_t *line_sep = lv_line_create(h1, NULL); + static const lv_point_t line_pp[] = { {0, 0}, { LV_HOR_RES - (LV_DPI - (LV_DPI / 4)) * 2, 0} }; + lv_line_set_points(line_sep, line_pp, 2); + lv_line_set_style(line_sep, lv_theme_get_current()->line.decor); + lv_obj_align(line_sep, label_txt, LV_ALIGN_OUT_BOTTOM_LEFT, -(LV_DPI / 4), LV_DPI / 8); + + // Create emuSD info labels. + lv_obj_t *label_btn = lv_label_create(h1, NULL); + lv_label_set_recolor(label_btn, true); + lv_label_set_static_text(label_btn, emu_info.enabled ? "#96FF00 "SYMBOL_OK" Enabled!#" : "#FF8000 "SYMBOL_CLOSE" Disabled!#"); + lv_obj_align(label_btn, line_sep, LV_ALIGN_OUT_BOTTOM_LEFT, LV_DPI / 4, LV_DPI / 4); + + lv_obj_t *label_txt2 = lv_label_create(h1, NULL); + lv_label_set_recolor(label_txt2, true); + char *txt_buf = (char *)malloc(SZ_16K); + + if (emu_info.enabled) + { + s_printf(txt_buf, "#00DDFF Type:# eMMC Raw Partition\n#00DDFF Sector:# 0x%08X", + emu_info.sector); + + lv_label_set_text(label_txt2, txt_buf); + } + else + { + lv_label_set_static_text(label_txt2, "emuSD is disabled and SD will be used for boot.\n\n"); + } + + free(txt_buf); + + lv_obj_set_style(label_txt2, &hint_small_style); + lv_obj_align(label_txt2, label_btn, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI / 3); + + // Create Change emuMMC button. + lv_obj_t *btn2 = lv_btn_create(h1, NULL); + lv_btn_set_fit(btn2, true, true); + label_btn = lv_label_create(btn2, NULL); + lv_label_set_static_text(label_btn, SYMBOL_SETTINGS" Change emuSD"); + lv_obj_align(btn2, label_txt2, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI * 6 / 10); + lv_btn_set_action(btn2, LV_BTN_ACTION_CLICK, _create_mbox_change_emusd); + + label_txt2 = lv_label_create(h1, NULL); + lv_label_set_recolor(label_txt2, true); + lv_label_set_static_text(label_txt2, + "Choose an emuSD partition\n" + "You can at most have 3 emuSD partitions."); + + lv_obj_set_style(label_txt2, &hint_small_style); + lv_obj_align(label_txt2, btn2, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI / 3); + + // Create emuMMC Tools container. + lv_obj_t *h2 = lv_cont_create(parent, NULL); + lv_cont_set_style(h2, &h_style); + lv_cont_set_fit(h2, false, true); + lv_obj_set_width(h2, (LV_HOR_RES / 9) * 4); + lv_obj_set_click(h2, false); + lv_cont_set_layout(h2, LV_LAYOUT_OFF); + lv_obj_align(h2, h1, LV_ALIGN_OUT_RIGHT_TOP, LV_DPI * 17 / 29, 0); + + label_sep = lv_label_create(h2, NULL); + lv_label_set_static_text(label_sep, ""); + + lv_obj_t *label_txt3 = lv_label_create(h2, NULL); + lv_label_set_static_text(label_txt3, "emuSD Tools"); + lv_obj_set_style(label_txt3, lv_theme_get_current()->label.prim); + lv_obj_align(label_txt3, h2, LV_ALIGN_IN_TOP_LEFT, LV_DPI / 4, 0); + + line_sep = lv_line_create(h2, line_sep); + lv_obj_align(line_sep, label_txt3, LV_ALIGN_OUT_BOTTOM_LEFT, -(LV_DPI / 4), LV_DPI / 8); + + // Create Create emuMMC button. + lv_obj_t *btn3 = lv_btn_create(h2, btn2); + label_btn = lv_label_create(btn3, NULL); + lv_btn_set_fit(btn3, true, true); + lv_label_set_static_text(label_btn, SYMBOL_DRIVE" Create emuSD"); + lv_obj_align(btn3, line_sep, LV_ALIGN_OUT_BOTTOM_LEFT, LV_DPI / 4, LV_DPI / 4); + lv_btn_set_action(btn3, LV_BTN_ACTION_CLICK, _create_mbox_emusd_create); + + lv_obj_t *label_txt4 = lv_label_create(h2, NULL); + lv_label_set_recolor(label_txt4, true); + lv_label_set_static_text(label_txt4, + "Allows you to create a new emuSD on a suitable #C7EA46 eMMC# partition"); + + lv_obj_set_style(label_txt4, &hint_small_style); + lv_obj_align(label_txt4, btn3, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI / 3); + + lv_obj_align(h1, parent, LV_ALIGN_IN_TOP_LEFT, 0, 0); + lv_obj_align(h2, h1, LV_ALIGN_OUT_RIGHT_TOP, LV_DPI * 17 / 29, 0); + + return LV_RES_OK; +} \ No newline at end of file diff --git a/nyx/nyx_gui/frontend/gui_emusd_tools.h b/nyx/nyx_gui/frontend/gui_emusd_tools.h new file mode 100644 index 00000000..274ad02a --- /dev/null +++ b/nyx/nyx_gui/frontend/gui_emusd_tools.h @@ -0,0 +1,8 @@ +#ifndef _GUI_EMUSD_TOOLS_H_ +#define _GUI_EMUSD_TOOLS_H_ + +#include + +lv_res_t create_tab_emusd_tools(lv_obj_t *parent); + +#endif diff --git a/nyx/nyx_gui/frontend/gui_tools.c b/nyx/nyx_gui/frontend/gui_tools.c index c849c72c..7b65e930 100644 --- a/nyx/nyx_gui/frontend/gui_tools.c +++ b/nyx/nyx_gui/frontend/gui_tools.c @@ -34,8 +34,12 @@ #include "../hos/hos.h" #include #include +#include +#include +#include #include #include +#include extern volatile boot_cfg_t *b_cfg; extern hekate_config h_cfg; @@ -225,7 +229,7 @@ static lv_res_t _create_mbox_hid(usb_ctxt_t *usbs) return LV_RES_OK; } -static lv_res_t _create_mbox_ums(usb_ctxt_t *usbs) +static lv_res_t _create_mbox_ums(usb_ctxt_t *usbs, u32 part) { lv_obj_t *dark_bg = lv_obj_create(lv_scr_act(), NULL); lv_obj_set_style(dark_bg, &mbox_darken); @@ -240,38 +244,38 @@ static lv_res_t _create_mbox_ums(usb_ctxt_t *usbs) s_printf(txt_buf, "#FF8000 USB Mass Storage#\n\n#C7EA46 Device:# "); - if (usbs->type == MMC_SD) - { - switch (usbs->partition) - { - case 0: - strcat(txt_buf, "SD Card"); - break; - case EMMC_GPP + 1: - strcat(txt_buf, "emuMMC GPP"); - break; - case EMMC_BOOT0 + 1: - strcat(txt_buf, "emuMMC BOOT0"); - break; - case EMMC_BOOT1 + 1: - strcat(txt_buf, "emuMMC BOOT1"); - break; - } - } - else - { - switch (usbs->partition) - { - case EMMC_GPP + 1: - strcat(txt_buf, "eMMC GPP"); - break; - case EMMC_BOOT0 + 1: + switch(part){ + case NYX_UMS_EMMC_BOOT0: strcat(txt_buf, "eMMC BOOT0"); break; - case EMMC_BOOT1 + 1: + case NYX_UMS_EMMC_BOOT1: strcat(txt_buf, "eMMC BOOT1"); break; - } + case NYX_UMS_EMMC_GPP: + strcat(txt_buf, "eMMC GPP"); + break; + case NYX_UMS_EMUMMC_GPP: + strcat(txt_buf, "emuMMC GPP"); + break; + case NYX_UMS_EMUMMC_BOOT0: + strcat(txt_buf, "emuMMC BOOT0"); + break; + case NYX_UMS_EMUMMC_BOOT1: + strcat(txt_buf, "emuMMC BOOT1"); + break; + case NYX_UMS_SD_CARD: + strcat(txt_buf, "SD Card"); + break; + case NYX_UMS_BOOT_STRG_GPP: + strcat(txt_buf, "Boot storage (eMMC GPP)"); + break; + case NYX_UMS_BOOT_STRG_BOOT1: + case NYX_UMS_BOOT_STRG_BOOT1_1MB: + strcat(txt_buf, "Boot storage (eMMC BOOT1)"); + break; + case NYX_UMS_BOOT_STRG_SD: + strcat(txt_buf, "Boot storage (SD Card)"); + break; } lv_mbox_set_text(mbox, txt_buf); @@ -333,6 +337,13 @@ static lv_res_t _create_mbox_ums_error(int error) lv_obj_set_style(dark_bg, &mbox_darken); lv_obj_set_size(dark_bg, LV_HOR_RES, LV_VER_RES); + + // 1: boot storage fail + // 2: no emu active + // 3: emmc fail + // 4: sd fail + // 5: file based + static const char *mbox_btn_map[] = { "\251", "\222OK", "\251", "" }; lv_obj_t * mbox = lv_mbox_create(dark_bg, NULL); lv_mbox_set_recolor_text(mbox, true); @@ -340,14 +351,23 @@ static lv_res_t _create_mbox_ums_error(int error) switch (error) { case 1: - lv_mbox_set_text(mbox, "#FF8000 USB Mass Storage#\n\n#FFFF00 Error mounting SD Card!#"); + lv_mbox_set_text(mbox, "#FF8000 USB Mass Storage#\n\n#FFFF00 Error mounting boot storage!#"); break; case 2: lv_mbox_set_text(mbox, "#FF8000 USB Mass Storage#\n\n#FFFF00 No emuMMC found active!#"); break; case 3: + lv_mbox_set_text(mbox, "#FF8000 USB Mass Storage#\n\n#FFFF00 Failed to initialize eMMC!#"); + break; + case 4: + lv_mbox_set_text(mbox, "#FF8000 USB Mass Storage#\n\n#FFFF00 Failed to initialize SD Card!#"); + break; + case 5: lv_mbox_set_text(mbox, "#FF8000 USB Mass Storage#\n\n#FFFF00 Active emuMMC is not partition based!#"); break; + case 6: + lv_mbox_set_text(mbox, "#FF8000 USB Mass Storage#\n\n#FFFF00 Corrupt emuMMC partition!#"); + break; } lv_mbox_add_btns(mbox, mbox_btn_map, mbox_action); @@ -424,26 +444,7 @@ lv_res_t action_ums_sd(lv_obj_t *btn) usbs.system_maintenance = &manual_system_maintenance; usbs.set_text = &usb_gadget_set_text; - _create_mbox_ums(&usbs); - - return LV_RES_OK; -} - -static lv_res_t _action_ums_emmc_boot0(lv_obj_t *btn) -{ - if (!nyx_emmc_check_battery_enough()) - return LV_RES_OK; - - usb_ctxt_t usbs; - usbs.type = MMC_EMMC; - usbs.partition = EMMC_BOOT0 + 1; - usbs.offset = 0; - usbs.sectors = 0; - usbs.ro = usb_msc_emmc_read_only; - usbs.system_maintenance = &manual_system_maintenance; - usbs.set_text = &usb_gadget_set_text; - - _create_mbox_ums(&usbs); + _create_mbox_ums(&usbs, NYX_UMS_SD_CARD); return LV_RES_OK; } @@ -457,228 +458,188 @@ static lv_res_t _action_ums_boot_storage(lv_obj_t *btn){ u8 drive = boot_storage_get_drive(); + u32 part; + usb_ctxt_t usbs; usbs.type = drive == DRIVE_SD ? MMC_SD : MMC_EMMC; switch(drive){ case DRIVE_EMMC: + part = NYX_UMS_BOOT_STRG_GPP; usbs.partition = EMMC_GPP + 1; break; case DRIVE_BOOT1: + part = NYX_UMS_BOOT_STRG_BOOT1; + usbs.partition = EMMC_BOOT1 + 1; + break; case DRIVE_BOOT1_1MB: + part = NYX_UMS_BOOT_STRG_BOOT1_1MB; usbs.partition = EMMC_BOOT1 + 1; break; case DRIVE_SD: + part = NYX_UMS_BOOT_STRG_SD; usbs.partition = 0; break; default: boot_storage_unmount(); return LV_RES_OK; } + usbs.offset = drive == DRIVE_BOOT1_1MB ? (0x100000 / 0x200) : 0; usbs.sectors = 0; usbs.ro = false; usbs.system_maintenance = &manual_system_maintenance; usbs.set_text = &usb_gadget_set_text; - _create_mbox_ums(&usbs); + _create_mbox_ums(&usbs, part); boot_storage_unmount(); return LV_RES_OK; } -static lv_res_t _action_ums_emmc_boot1(lv_obj_t *btn) -{ +static lv_res_t _ums_emmc(u32 part){ if (!nyx_emmc_check_battery_enough()) return LV_RES_OK; usb_ctxt_t usbs; usbs.type = MMC_EMMC; - usbs.partition = EMMC_BOOT1 + 1; + + switch(part){ + case NYX_UMS_EMMC_BOOT0: + usbs.partition = EMMC_BOOT0 + 1; + break; + case NYX_UMS_EMMC_BOOT1: + usbs.partition = EMMC_BOOT1 + 1; + break; + case NYX_UMS_EMMC_GPP: + usbs.partition = EMMC_GPP + 1; + break; + } + usbs.offset = 0; usbs.sectors = 0; usbs.ro = usb_msc_emmc_read_only; usbs.system_maintenance = &manual_system_maintenance; usbs.set_text = &usb_gadget_set_text; - _create_mbox_ums(&usbs); + return _create_mbox_ums(&usbs, part); +} - return LV_RES_OK; +static lv_res_t _action_ums_emmc_boot0(lv_obj_t *btn) +{ + return _ums_emmc(NYX_UMS_EMMC_BOOT0); +} + +static lv_res_t _action_ums_emmc_boot1(lv_obj_t *btn) +{ + return _ums_emmc(NYX_UMS_EMMC_BOOT1); } lv_res_t action_ums_emmc_gpp(lv_obj_t *btn) { + return _ums_emmc(NYX_UMS_EMMC_GPP); +} + +static lv_res_t _ums_emummc(u32 part){ if (!nyx_emmc_check_battery_enough()) return LV_RES_OK; usb_ctxt_t usbs; - usbs.type = MMC_EMMC; - usbs.partition = EMMC_GPP + 1; - usbs.offset = 0; - usbs.sectors = 0; - usbs.ro = usb_msc_emmc_read_only; - usbs.system_maintenance = &manual_system_maintenance; - usbs.set_text = &usb_gadget_set_text; + sdmmc_storage_t *storage; + emummc_cfg_t emu_info; - _create_mbox_ums(&usbs); + int error = !boot_storage_mount(); + + if(!error){ + load_emummc_cfg(&emu_info); + if(emu_info.enabled){ + error = 0; + if(emu_info.enabled == 4){ + // emmc raw based + if(!emmc_initialize(false)){ + error = 3; + } + storage = &emmc_storage; + }else if(emu_info.enabled == 1 && emu_info.sector){ + // sd raw based + if(!sd_initialize(false)){ + error = 4; + } + storage = &sd_storage; + }else if(emu_info.enabled == 1 && !emu_info.sector){ + // sd file based + error = 5; + } + }else{ + error = 2; + } + + if(error == 0 && (emu_info.enabled == 4 || (emu_info.enabled == 1 && emu_info.sector))){ + error = 6; + usbs.offset = emu_info.sector; + switch(part){ + case NYX_UMS_EMUMMC_BOOT0: + usbs.offset += 0; + break; + case NYX_UMS_EMUMMC_BOOT1: + usbs.offset += 0x2000; + break; + case NYX_UMS_EMUMMC_GPP: + usbs.offset += 0x4000; + break; + } + + if(part == NYX_UMS_EMUMMC_GPP){ + gpt_header_t *gpt_hdr = malloc(sizeof(*gpt_hdr)); + if(sdmmc_storage_read(storage, usbs.offset + 1, 1, gpt_hdr)){ + if(!memcmp(&gpt_hdr->signature, "EFI PART", 8)){ + error = 0; + usbs.sectors = gpt_hdr->alt_lba + 1; + } + } + free(gpt_hdr); + }else{ + usbs.sectors = 0x2000; + } + } + + if(emu_info.path){ + free(emu_info.path); + } + if(emu_info.nintendo_path){ + free(emu_info.nintendo_path); + } + } + + if(error){ + _create_mbox_ums_error(error); + }else{ + usbs.type = emu_info.enabled == 4 ? MMC_EMMC : MMC_SD; + usbs.partition = EMMC_GPP + 1; + usbs.ro = usb_msc_emmc_read_only; + usbs.system_maintenance = &manual_system_maintenance; + usbs.set_text = &usb_gadget_set_text; + _create_mbox_ums(&usbs, part); + } + + boot_storage_unmount(); return LV_RES_OK; } static lv_res_t _action_ums_emuemmc_boot0(lv_obj_t *btn) { - if (!nyx_emmc_check_battery_enough()) - return LV_RES_OK; - - usb_ctxt_t usbs; - - int error = !sd_mount(); - error &= boot_storage_mount(); - if (!error) - { - emummc_cfg_t emu_info; - load_emummc_cfg(&emu_info); - - error = 2; - if (emu_info.enabled) - { - error = 3; - if (emu_info.sector) - { - error = 0; - usbs.offset = emu_info.sector; - } - } - - if (emu_info.path) - free(emu_info.path); - if (emu_info.nintendo_path) - free(emu_info.nintendo_path); - } - sd_unmount(); - boot_storage_unmount(); - - if (error) - _create_mbox_ums_error(error); - else - { - usbs.type = MMC_SD; - usbs.partition = EMMC_BOOT0 + 1; - usbs.sectors = 0x2000; // Forced 4MB. - usbs.ro = usb_msc_emmc_read_only; - usbs.system_maintenance = &manual_system_maintenance; - usbs.set_text = &usb_gadget_set_text; - _create_mbox_ums(&usbs); - } - - return LV_RES_OK; + return _ums_emummc(NYX_UMS_EMUMMC_BOOT0); } static lv_res_t _action_ums_emuemmc_boot1(lv_obj_t *btn) { - if (!nyx_emmc_check_battery_enough()) - return LV_RES_OK; - - usb_ctxt_t usbs; - - int error = !sd_mount(); - error &= boot_storage_mount(); - if (!error) - { - emummc_cfg_t emu_info; - load_emummc_cfg(&emu_info); - - error = 2; - if (emu_info.enabled) - { - error = 3; - if (emu_info.sector) - { - error = 0; - usbs.offset = emu_info.sector + 0x2000; - } - } - - if (emu_info.path) - free(emu_info.path); - if (emu_info.nintendo_path) - free(emu_info.nintendo_path); - } - sd_unmount(); - boot_storage_unmount(); - - if (error) - _create_mbox_ums_error(error); - else - { - usbs.type = MMC_SD; - usbs.partition = EMMC_BOOT1 + 1; - usbs.sectors = 0x2000; // Forced 4MB. - usbs.ro = usb_msc_emmc_read_only; - usbs.system_maintenance = &manual_system_maintenance; - usbs.set_text = &usb_gadget_set_text; - _create_mbox_ums(&usbs); - } - - return LV_RES_OK; + return _ums_emummc(NYX_UMS_EMUMMC_BOOT1); } static lv_res_t _action_ums_emuemmc_gpp(lv_obj_t *btn) { - if (!nyx_emmc_check_battery_enough()) - return LV_RES_OK; - - usb_ctxt_t usbs; - - int error = !sd_mount(); - error &= boot_storage_mount(); - if (!error) - { - emummc_cfg_t emu_info; - load_emummc_cfg(&emu_info); - - error = 2; - if (emu_info.enabled) - { - error = 3; - if (emu_info.sector) - { - error = 1; - usbs.offset = emu_info.sector + 0x4000; - - u8 *gpt = malloc(SD_BLOCKSIZE); - if (sdmmc_storage_read(&sd_storage, usbs.offset + 1, 1, gpt)) - { - if (!memcmp(gpt, "EFI PART", 8)) - { - error = 0; - usbs.sectors = *(u32 *)(gpt + 0x20) + 1; // Backup LBA + 1. - } - } - } - } - - if (emu_info.path) - free(emu_info.path); - if (emu_info.nintendo_path) - free(emu_info.nintendo_path); - } - sd_unmount(); - boot_storage_unmount(); - - if (error) - _create_mbox_ums_error(error); - else - { - usbs.type = MMC_SD; - usbs.partition = EMMC_GPP + 1; - usbs.ro = usb_msc_emmc_read_only; - usbs.system_maintenance = &manual_system_maintenance; - usbs.set_text = &usb_gadget_set_text; - _create_mbox_ums(&usbs); - } - - return LV_RES_OK; + return _ums_emummc(NYX_UMS_EMUMMC_GPP); } void nyx_run_ums(void *param) diff --git a/nyx/nyx_gui/frontend/gui_tools_partition_manager.c b/nyx/nyx_gui/frontend/gui_tools_partition_manager.c index 45fe5021..238c4d39 100644 --- a/nyx/nyx_gui/frontend/gui_tools_partition_manager.c +++ b/nyx/nyx_gui/frontend/gui_tools_partition_manager.c @@ -2045,8 +2045,6 @@ static lv_res_t _create_mbox_start_partitioning(lv_obj_t *btn) sfd_init(storage, hos_start, hos_size); u32 mkfs_error = _format_fat_partition("sfd:", FM_FAT32 | FM_SFD); - DBG_PRINT("format done"); - u8 *buf = malloc(0x200); if(mkfs_error != FR_OK){ @@ -3174,9 +3172,11 @@ static void _create_mbox_check_files_total_size(u8 drive) } if(!memcmp(entry->name, (char[]){ 'e', 0, 'm', 0, 'u', 0, 's', 0, 'd', 0, '_', 0, 'm', 0, 'b', 0, 'r', 0 }, 18)){ - if(!memcmp(entry->name, (char[]){ 'e', 0, 'm', 0, 'u', 0, 's', 0, 'd', 0 }, 10)){ - bar_emu_sd_size += gpt->entries[i + 1].lba_end - gpt->entries[i].lba_start + 1; - i++; + if((i + 1) < gpt->header.num_part_ents && (i + 1) < 128){ + if(!memcmp(gpt->entries[i + 1].name, (char[]){ 'e', 0, 'm', 0, 'u', 0, 's', 0, 'd', 0 }, 10)){ + bar_emu_sd_size += gpt->entries[i + 1].lba_end - gpt->entries[i].lba_start + 1; + i++; + } } } } @@ -3193,6 +3193,8 @@ static void _create_mbox_check_files_total_size(u8 drive) bar_hos_size = w * (bar_hos_size / SECTORS_PER_GB) / (total_size / SECTORS_PER_GB); bar_emu_size = w * (bar_emu_size / SECTORS_PER_GB) / (total_size / SECTORS_PER_GB); bar_emu_sd_size = w * (bar_emu_sd_size / SECTORS_PER_GB) / (total_size / SECTORS_PER_GB); + // bar_remaining_size = w - bar_emu_sd_size - bar_emu_size - bar_hos_size - bar_hos_os_size - bar_and_size - bar_l4t_size; + // bar_remaining_size = bar_remaining_size <= 7 ? 0 : bar_remaining_size; // Create HOS OS bar. lv_obj_t *bar_hos_os = lv_bar_create(h1, NULL);