diff --git a/bdk/libs/fatfs/ff.c b/bdk/libs/fatfs/ff.c index 94f4522..fe9a374 100644 --- a/bdk/libs/fatfs/ff.c +++ b/bdk/libs/fatfs/ff.c @@ -39,6 +39,7 @@ #include "ff.h" /* Declarations of FatFs API */ #include "diskio.h" /* Declarations of device I/O functions */ #include +#include "../../storage/nx_sd.h" #define EFSPRINTF(text, ...) print_error(); gfx_printf("%k"text"%k\n", 0xFFFFFF00, 0xFFFFFFFF); //#define EFSPRINTF(...) @@ -5861,7 +5862,7 @@ FRESULT f_mkfs ( if (vol < 0) return FR_INVALID_DRIVE; if (FatFs[vol]) FatFs[vol]->fs_type = 0; /* Clear the volume if mounted */ pdrv = LD2PD(vol); /* Physical drive */ - part = LD2PT(vol); /* Partition (0:create as new, 1-4:get from partition table) */ + part = 1; /* Partition (0:create as new, 1-4:get from partition table) */ /* Check physical drive status */ stat = disk_initialize(pdrv); @@ -5892,7 +5893,7 @@ FRESULT f_mkfs ( if (!buf || sz_buf == 0) return FR_NOT_ENOUGH_CORE; /* Determine where the volume to be located (b_vol, sz_vol) */ - if (FF_MULTI_PARTITION && part != 0) { + if (part > 0) { /* Get partition information from partition table in the MBR */ if (disk_read(pdrv, buf, 0, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); /* Load MBR */ if (ld_word(buf + BS_55AA) != 0xAA55) LEAVE_MKFS(FR_MKFS_ABORTED); /* Check if MBR is valid */ @@ -6262,7 +6263,7 @@ FRESULT f_mkfs ( } /* Update partition information */ - if (FF_MULTI_PARTITION && part != 0) { /* Created in the existing partition */ + if (part != 0) { /* Created in the existing partition */ /* Update system ID in the partition table */ if (disk_read(pdrv, buf, 0, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); /* Read the MBR */ buf[MBR_Table + (part - 1) * SZ_PTE + PTE_System] = sys; /* Set system ID */ @@ -6371,7 +6372,81 @@ FRESULT f_fdisk ( #endif /* FF_MULTI_PARTITION */ #endif /* FF_USE_MKFS && !FF_FS_READONLY */ +extern sdmmc_storage_t sd_storage; +FRESULT f_fdisk_mod ( + BYTE pdrv, /* Physical drive number */ + const DWORD* szt, /* Pointer to the size table for each partitions */ + void* work +) +{ + UINT i, n, sz_cyl, tot_cyl, e_cyl; + BYTE s_hd, e_hd, *p, *buf = (BYTE*)work; + DSTATUS stat; + DWORD sz_disk, p_sect, b_cyl, b_sect; + FRESULT res; + + stat = disk_initialize(pdrv); + if (stat & STA_NOINIT) return FR_NOT_READY; + if (stat & STA_PROTECT) return FR_WRITE_PROTECTED; + sz_disk = sd_storage.csd.capacity; + + if (!buf) return FR_NOT_ENOUGH_CORE; + + /* Determine the CHS without any consideration of the drive geometry */ + for (n = 16; n < 256 && sz_disk / n / 63 > 1024; n *= 2) ; + if (n == 256) n--; + e_hd = (BYTE)(n - 1); + sz_cyl = 63 * n; + tot_cyl = sz_disk / sz_cyl; + + /* Create partition table */ + mem_set(buf, 0, 0x10000); + p = buf + MBR_Table; b_cyl = 0, b_sect = 0; + for (i = 0; i < 4; i++, p += SZ_PTE) { + p_sect = szt[i]; /* Number of sectors */ + + if (p_sect == 0) + continue; + + if (i == 0) { /* Exclude first 16MiB of sd */ + s_hd = 1; + b_sect += 32768; p_sect -= 32768; + } + else + s_hd = 0; + + b_cyl = b_sect / sz_cyl; + e_cyl = ((b_sect + p_sect) / sz_cyl) - 1; /* End cylinder */ + + if (e_cyl >= tot_cyl) + LEAVE_MKFS(FR_INVALID_PARAMETER); + + + /* Set partition table */ + p[1] = s_hd; /* Start head */ + p[2] = (BYTE)(((b_cyl >> 2) & 0xC0) | 1); /* Start sector */ + p[3] = (BYTE)b_cyl; /* Start cylinder */ + p[4] = 0x07; /* System type (temporary setting) */ + p[5] = e_hd; /* End head */ + p[6] = (BYTE)(((e_cyl >> 2) & 0xC0) | 63); /* End sector */ + p[7] = (BYTE)e_cyl; /* End cylinder */ + st_dword(p + 8, b_sect); /* Start sector in LBA */ + st_dword(p + 12, p_sect); /* Number of sectors */ + /* Next partition */ + + for (u32 cursect = 0; cursect < 512; cursect++){ + disk_write(pdrv, buf + 0x4000, b_sect + (64 * cursect), 64); + } + + b_sect += p_sect; + } + st_word(p, 0xAA55); /* MBR signature (always at offset 510) */ + + /* Write it to the MBR */ + res = (disk_write(pdrv, buf, 0, 1) == RES_OK && disk_ioctl(pdrv, CTRL_SYNC, 0) == RES_OK) ? FR_OK : FR_DISK_ERR; + LEAVE_MKFS(res); +} #if FF_USE_STRFUNC diff --git a/bdk/libs/fatfs/ff.h b/bdk/libs/fatfs/ff.h index a83cf63..29b1ba2 100644 --- a/bdk/libs/fatfs/ff.h +++ b/bdk/libs/fatfs/ff.h @@ -291,6 +291,7 @@ FRESULT f_expand (FIL* fp, FSIZE_t fsz, BYTE opt); /* Allocate a contiguous FRESULT f_mount (FATFS* fs, const TCHAR* path, BYTE opt); /* Mount/Unmount a logical drive */ FRESULT f_mkfs (const TCHAR* path, BYTE opt, DWORD au, void* work, UINT len); /* Create a FAT volume */ FRESULT f_fdisk (BYTE pdrv, const DWORD* szt, void* work); /* Divide a physical drive into some partitions */ +FRESULT f_fdisk_mod (BYTE pdrv, const DWORD* szt, void* work); // Modded version of f_fdisk that works:tm: FRESULT f_setcp (WORD cp); /* Set current code page */ int f_putc (TCHAR c, FIL* fp); /* Put a character to the file */ int f_puts (const TCHAR* str, FIL* cp); /* Put a string to the file */ diff --git a/source/gfx/gfxutils.c b/source/gfx/gfxutils.c index 5227f14..c90ed71 100644 --- a/source/gfx/gfxutils.c +++ b/source/gfx/gfxutils.c @@ -45,9 +45,9 @@ int MakeHorizontalMenu(MenuEntry_t *entries, int len, int spacesBetween, u32 bg) return highlight; else if (input->b) return 0; - else if (input->left && highlight > 0) + else if ((input->left || input->down) && highlight > 0) highlight--; - else if (input->right && highlight < len - 1) + else if ((input->right || input->up) && highlight < len - 1) highlight++; } } \ No newline at end of file diff --git a/source/libs/fatfs/diskio.c b/source/libs/fatfs/diskio.c index 1cf422d..987266b 100644 --- a/source/libs/fatfs/diskio.c +++ b/source/libs/fatfs/diskio.c @@ -98,11 +98,39 @@ DRESULT disk_write ( /*-----------------------------------------------------------------------*/ /* Miscellaneous Functions */ /*-----------------------------------------------------------------------*/ +static u32 part_rsvd_size = 0; DRESULT disk_ioctl ( - BYTE pdrv, /* Physical drive number (0..) */ + BYTE pdrv, /* Physical drive nmuber (0..) */ BYTE cmd, /* Control code */ void *buff /* Buffer to send/receive control data */ ) { + DWORD *buf = (DWORD *)buff; + + if (pdrv == DRIVE_SD) + { + switch (cmd) + { + case GET_SECTOR_COUNT: + *buf = sd_storage.sec_cnt - part_rsvd_size; + break; + case GET_BLOCK_SIZE: + *buf = 32768; // Align to 16MB. + break; + } + } + else if (pdrv == DRIVE_RAM) + { + switch (cmd) + { + case GET_SECTOR_COUNT: + *buf = RAM_DISK_SZ >> 9; // 1GB. + break; + case GET_BLOCK_SIZE: + *buf = 2048; // Align to 1MB. + break; + } + } + return RES_OK; } diff --git a/source/libs/fatfs/ffconf.h b/source/libs/fatfs/ffconf.h index 4b914b3..9f021f0 100644 --- a/source/libs/fatfs/ffconf.h +++ b/source/libs/fatfs/ffconf.h @@ -38,7 +38,7 @@ / f_findnext(). (0:Disable, 1:Enable 2:Enable with matching altname[] too) */ -#define FF_USE_MKFS 0 +#define FF_USE_MKFS 1 /* This option switches f_mkfs() function. (0:Disable or 1:Enable) */ #define FF_FASTFS 0 diff --git a/source/storage/mountmanager.h b/source/storage/mountmanager.h index 926ac6e..40b9358 100644 --- a/source/storage/mountmanager.h +++ b/source/storage/mountmanager.h @@ -13,4 +13,5 @@ int connectMMC(u8 mmcType); ErrCode_t mountMMCPart(const char *partition); void SetKeySlots(); void unmountMMCPart(); -link_t *GetCurGPT(); \ No newline at end of file +link_t *GetCurGPT(); +void disconnectMMC(); \ No newline at end of file diff --git a/source/storage/nx_sd.c b/source/storage/nx_sd.c index fa284fa..5529884 100644 --- a/source/storage/nx_sd.c +++ b/source/storage/nx_sd.c @@ -22,7 +22,7 @@ #include #include -static bool sd_mounted = false; +bool sd_mounted = false; static u16 sd_errors[3] = { 0 }; // Init and Read/Write errors. static u32 sd_mode = SD_UHS_SDR82; @@ -130,12 +130,15 @@ bool sd_initialize(bool power_cycle) return false; } +bool is_sd_inited = false; + bool sd_mount() { if (sd_mounted) return true; int res = !sd_initialize(false); + is_sd_inited = !res; if (res) { diff --git a/source/tegraexplorer/mainmenu.c b/source/tegraexplorer/mainmenu.c index fc21878..a4683ca 100644 --- a/source/tegraexplorer/mainmenu.c +++ b/source/tegraexplorer/mainmenu.c @@ -12,6 +12,7 @@ #include "../storage/mountmanager.h" #include "../storage/gptmenu.h" #include "../storage/emummc.h" +#include MenuEntry_t mainMenuEntries[] = { {.R = 255, .G = 255, .B = 255, .skip = 1, .name = "-- Main Menu --"}, @@ -20,15 +21,18 @@ MenuEntry_t mainMenuEntries[] = { {.optionUnion = COLORTORGB(COLOR_YELLOW), .name = "Emummc"}, {.B = 255, .G = 255, .name = "Test Controllers"}, {.R = 255, .name = "Cause an exception"}, + {.R = 255, .name = "Partition the sd"}, {.optionUnion = COLORTORGB(COLOR_BLUE), .name = "Dump Firmware"}, {.optionUnion = COLORTORGB(COLOR_ORANGE), .name = "View dumped keys"}, - {.R = 255, .name = "Reboot to payload"} + {.optionUnion = COLORTORGB(COLOR_ORANGE)}, + {.R = 255, .name = "Reboot to payload"}, + {.R = 255, .name = "Reboot to RCM"} }; void HandleSD(){ gfx_clearscreen(); TConf.curExplorerLoc = LOC_SD; - if (!sd_mount()){ + if (!sd_mount() || sd_get_card_removed()){ gfx_printf("Sd is not mounted!"); hidWait(); } @@ -67,6 +71,12 @@ void ViewKeys(){ hidWait(); } +extern bool sd_mounted; + +void MountOrUnmountSD(){ + (sd_mounted) ? sd_unmount() : sd_mount(); +} + menuPaths mainMenuPaths[] = { NULL, HandleSD, @@ -74,16 +84,24 @@ menuPaths mainMenuPaths[] = { HandleEMUMMC, TestControllers, CrashTE, + FormatSD, DumpSysFw, ViewKeys, - RebootToPayload + MountOrUnmountSD, + RebootToPayload, + reboot_rcm }; void EnterMainMenu(){ while (1){ + if (sd_get_card_removed()) + sd_unmount(); + + mainMenuEntries[1].hide = !sd_mounted; mainMenuEntries[2].hide = !TConf.keysDumped; - mainMenuEntries[3].hide = (!TConf.keysDumped || !emu_cfg.enabled); - mainMenuEntries[6].hide = !TConf.keysDumped; + mainMenuEntries[3].hide = (!TConf.keysDumped || !emu_cfg.enabled || !sd_mounted); + mainMenuEntries[7].hide = !TConf.keysDumped; + mainMenuEntries[9].name = (sd_mounted) ? "Unmount SD" : "Mount SD"; FunctionMenuHandler(mainMenuEntries, ARR_LEN(mainMenuEntries), mainMenuPaths, ALWAYSREDRAW); } } diff --git a/source/tegraexplorer/tools.c b/source/tegraexplorer/tools.c index 1edf682..b32bbe4 100644 --- a/source/tegraexplorer/tools.c +++ b/source/tegraexplorer/tools.c @@ -17,6 +17,7 @@ #include "../fs/readers/folderReader.h" #include #include "../fs/fscopy.h" +#include "../utils/utils.h" void TestControllers(){ gfx_clearscreen(); @@ -137,4 +138,79 @@ void DumpSysFw(){ gfx_printf("\n\nDone! Time taken: %ds\nPress any key to exit", get_tmr_s() - timer); free(baseSdPath); hidWait(); +} + +extern sdmmc_storage_t sd_storage; +extern bool is_sd_inited; + +MenuEntry_t FatAndEmu[] = { + {.optionUnion = COLORTORGB(COLOR_ORANGE), .name = "Back to main menu"}, + {.optionUnion = COLORTORGB(COLOR_GREEN), .name = "Fat32 + EmuMMC"}, + {.optionUnion = COLORTORGB(COLOR_BLUE), .name = "Only Fat32"} +}; + +void FormatSD(){ + gfx_clearscreen(); + disconnectMMC(); + DWORD plist[] = {0,0,0,0}; + bool emummc = 0; + int res; + + if (!is_sd_inited || sd_get_card_removed()) + return; + + gfx_printf("\nDo you want to partition for an emummc?\n"); + res = MakeHorizontalMenu(FatAndEmu, ARR_LEN(FatAndEmu), 3, COLOR_DEFAULT); + + if (!res) + return; + + emummc = !(res - 1); + + plist[0] = sd_storage.csd.capacity; + if (emummc){ + plist[0] -= 61145088; + u32 allignedSectors = plist[0] - plist[0] % 2048; + plist[1] = 61145088 + plist[0] % 2048; + plist[0] = allignedSectors; + } + + SETCOLOR(COLOR_RED, COLOR_DEFAULT); + gfx_printf("\n\nAre you sure you want to format your sd?\nThis will delete everything on your SD card!\nThis action is irreversible!\n\n"); + WaitFor(1500); + + gfx_printf("%kAre you sure? ", COLOR_WHITE); + if (!MakeYesNoHorzMenu(3, COLOR_DEFAULT)){ + return; + } + + RESETCOLOR; + + gfx_printf("\n\nStarting Partitioning & Formatting\n"); + + for (int i = 0; i < 2; i++){ + gfx_printf("Part %d: %dKiB\n", i + 1, plist[i] / 2); + } + + u8 *work = malloc(TConf.FSBuffSize); + res = f_fdisk_mod(0, plist, work); + + if (!res){ + res = f_mkfs("sd:", FM_FAT32, 32768, work, TConf.FSBuffSize); + } + + sd_unmount(); + + if (res){ + DrawError(newErrCode(res)); + gfx_clearscreen(); + gfx_printf("Something went wrong\nPress any key to exit"); + } + else { + sd_mount(); + gfx_printf("\nDone!\nPress any key to exit"); + } + + free(work); + hidWait(); } \ No newline at end of file diff --git a/source/tegraexplorer/tools.h b/source/tegraexplorer/tools.h index 49ce2bf..f3e5815 100644 --- a/source/tegraexplorer/tools.h +++ b/source/tegraexplorer/tools.h @@ -2,4 +2,5 @@ void RebootToPayload(); void TestControllers(); -void DumpSysFw(); \ No newline at end of file +void DumpSysFw(); +void FormatSD(); \ No newline at end of file diff --git a/source/utils/utils.c b/source/utils/utils.c index 752ba7d..24f57fc 100644 --- a/source/utils/utils.c +++ b/source/utils/utils.c @@ -2,6 +2,7 @@ #include #include #include +#include char *CpyStr(const char* in){ int len = strlen(in); @@ -29,4 +30,9 @@ bool StrEndsWith(char *begin, char *end){ return !strcmp(begin, end); return 0; +} + +void WaitFor(u32 ms){ + u32 a = get_tmr_ms(); + while (a + ms > get_tmr_ms()); } \ No newline at end of file diff --git a/source/utils/utils.h b/source/utils/utils.h index 0899aca..df8c5e2 100644 --- a/source/utils/utils.h +++ b/source/utils/utils.h @@ -4,5 +4,6 @@ char *CpyStr(const char* in); void MaskIn(char *mod, u32 bitstream, char mask); bool StrEndsWith(char *begin, char *end); +void WaitFor(u32 ms); #define FREE(x) free(x); x = NULL; \ No newline at end of file