diff --git a/include/arm11/menu/menu_func.h b/include/arm11/menu/menu_func.h index af281f5..04e6b7a 100644 --- a/include/arm11/menu/menu_func.h +++ b/include/arm11/menu/menu_func.h @@ -21,8 +21,7 @@ #include "types.h" #define NAND_BACKUP_PATH "sdmc:/3DS" // NAND backups standard path -#define NAND_BACKUP_SIZE 1979711488 // <-- d0k3's NAND backup size -#define DEVICE_BUFSIZE (128 * 1024) // 128KiB +#define DEVICE_BUFSIZE (256 * 1024) // 256 KiB #define PROGRESS_WIDTH 20 u32 menuPresetNandTools(void); diff --git a/source/arm11/menu/menu_func.c b/source/arm11/menu/menu_func.c index 92a9fdd..a625030 100644 --- a/source/arm11/menu/menu_func.c +++ b/source/arm11/menu/menu_func.c @@ -344,6 +344,10 @@ goto fail; } + // get NAND size (return value in sectors) + const s64 nand_size = fGetDeviceSize(FS_DEVICE_NAND) * 0x200; + if (!nand_size) panicMsg("NAND size is zero"); + // console serial number char serial[0x10] = { 0 }; // serial from SecureInfo_? @@ -373,11 +377,10 @@ goto fail; } - // reserve space for NAND backup / needs work (!!!) - // !MISSING! Actually use the actual size of the NAND - ee_printf("Reserving space...\n"); + // reserve space for NAND backup + ee_printf("NAND size: %lli MiB\nReserving space...\n", nand_size / 0x0100000); updateScreens(); - if ((fLseek(fHandle, NAND_BACKUP_SIZE) != 0) || (fTell(fHandle) != NAND_BACKUP_SIZE)) + if ((fLseek(fHandle, nand_size) != 0) || (fTell(fHandle) != nand_size)) { fClose(fHandle); fUnlink(fpath); @@ -404,11 +407,11 @@ // all done, ready to do the NAND backup ee_printf("\n"); - for (s64 p = 0; p < NAND_BACKUP_SIZE; p += DEVICE_BUFSIZE) + for (s64 p = 0; p < nand_size; p += DEVICE_BUFSIZE) { - s64 readBytes = (NAND_BACKUP_SIZE - p > DEVICE_BUFSIZE) ? DEVICE_BUFSIZE : NAND_BACKUP_SIZE - p; + s64 readBytes = (nand_size - p > DEVICE_BUFSIZE) ? DEVICE_BUFSIZE : nand_size - p; s32 errcode = 0; - ee_printf_progress("NAND backup", PROGRESS_WIDTH, p, NAND_BACKUP_SIZE); + ee_printf_progress("NAND backup", PROGRESS_WIDTH, p, nand_size); updateScreens(); if ((errcode = fReadToDeviceBuffer(devHandle, p, readBytes, dbufHandle)) != 0) @@ -435,7 +438,7 @@ } // NAND access finalized - ee_printf_progress("NAND backup", PROGRESS_WIDTH, NAND_BACKUP_SIZE, NAND_BACKUP_SIZE); + ee_printf_progress("NAND backup", PROGRESS_WIDTH, nand_size, nand_size); ee_printf("\n\nNAND backup finished.\n"); result = 0; @@ -461,50 +464,61 @@ u32 menuRestoreNand(PrintConsole* term_con, PrintConsole* menu_con, u32 param) { u32 result = 1; - + // select & clear console consoleSelect(term_con); consoleClear(); - + // ensure SD mounted if (!fsEnsureMounted("sdmc:")) { ee_printf("SD not inserted or corrupt!\n"); goto fail; } - - + + // get NAND size (return value in sectors) + const s64 nand_size = fGetDeviceSize(FS_DEVICE_NAND) * 0x200; + if (!nand_size) panicMsg("NAND size is zero"); + + ee_printf_screen_center("Select a NAND backup for restore.\nPress [HOME] to cancel."); updateScreens(); char fpath[256]; if (!menuFileSelector(fpath, menu_con, NAND_BACKUP_PATH, "*nand*.bin", false)) return 1; // canceled by user - - // may be only of interest when not doing forced restore - // *MISSING* check NAND backup validity (header, file size, crypto) - // *MISSING* ensure the NAND backup does not change the partitioning - // *MISSING* protect sector 0x00, sector 0x96 and the FIRM partitions for safe restore - - - // select & clear console + + // may be only of interest when not doing forced restore + // *MISSING* check NAND backup validity (header, file size, crypto) + // *MISSING* ensure the NAND backup does not change the partitioning + // *MISSING* protect sector 0x00, sector 0x96 and the FIRM partitions for safe restore + + + // select & clear console consoleSelect(term_con); consoleClear(); - - ee_printf("Restoring NAND backup:\n%s\n\nPreparing NAND restore...\n", fpath); + + // check NAND backup (when not forced) + if (!param && (fVerifyNandImage(fpath) != 0)) + { + ee_printf("%s\nNot a valid NAND backup for this 3DS!\n", fpath); + goto fail; + } + + ee_printf("Restoring NAND backup:\n%s\n\nPreparing NAND restore...\n", fpath); updateScreens(); - - - // open file handle + + + // open file handle s32 fHandle; if ((fHandle = fOpen(fpath, FS_OPEN_EXISTING | FS_OPEN_READ)) < 0) { ee_printf("Cannot open file!\n"); goto fail; } - - // setup device read + + // setup device read s32 devHandle = fPrepareRawAccess(FS_DEVICE_NAND); if (devHandle < 0) { @@ -518,24 +532,32 @@ s32 dbufHandle = fCreateDeviceBuffer(DEVICE_BUFSIZE); if (dbufHandle < 0) panicMsg("Out of memory"); - - - // check file size - ee_printf("File size: %lu MiB\n", fSize(fHandle) / 0x100000); - if (fSize(fHandle) > NAND_BACKUP_SIZE) - { - ee_printf("Size exceeds available space!\n"); - goto fail_close_handles; - } - - - // all done, ready to do the NAND backup - ee_printf("\n"); - for (s64 p = 0; p < NAND_BACKUP_SIZE; p += DEVICE_BUFSIZE) + + + // check file size + ee_printf("File size: %lu MiB\n", fSize(fHandle) / 0x100000); + ee_printf("NAND size: %lli MiB\n", nand_size / 0x100000); + updateScreens(); + if (fSize(fHandle) > nand_size) { - s64 readBytes = (NAND_BACKUP_SIZE - p > DEVICE_BUFSIZE) ? DEVICE_BUFSIZE : NAND_BACKUP_SIZE - p; + ee_printf("Size exceeds available space!\n"); + goto fail_close_handles; + } + + + // setup NAND protection + if (fSetNandProtection(!param) != 0) + panicMsg("Set NAND protection failed."); + ee_printf("NAND protection: %s\n", !param ? "enabled" : "disabled"); + + + // all done, ready to do the NAND backup + ee_printf("\n"); + for (s64 p = 0; p < nand_size; p += DEVICE_BUFSIZE) + { + s64 readBytes = (nand_size - p > DEVICE_BUFSIZE) ? DEVICE_BUFSIZE : nand_size - p; s32 errcode = 0; - ee_printf_progress("NAND restore", PROGRESS_WIDTH, p, NAND_BACKUP_SIZE); + ee_printf_progress("NAND restore", PROGRESS_WIDTH, p, nand_size); updateScreens(); if ((errcode = fReadToDeviceBuffer(fHandle, p, readBytes, dbufHandle)) != 0) @@ -562,7 +584,7 @@ } // NAND access finalized - ee_printf_progress("NAND restore", PROGRESS_WIDTH, NAND_BACKUP_SIZE, NAND_BACKUP_SIZE); + ee_printf_progress("NAND restore", PROGRESS_WIDTH, nand_size, nand_size); ee_printf("\n\nNAND restore finished.\n"); result = 0;