diff --git a/bootloader/config/config.c b/bootloader/config/config.c index bbda2f8..af8e6aa 100644 --- a/bootloader/config/config.c +++ b/bootloader/config/config.c @@ -36,7 +36,7 @@ void set_default_configuration() h_cfg.autoboot = 0; h_cfg.autoboot_list = 0; h_cfg.bootwait = 3; - h_cfg.verification = 2; + h_cfg.verification = 1; h_cfg.se_keygen_done = 0; h_cfg.sbar_time_keeping = 0; h_cfg.backlight = 100; @@ -453,9 +453,9 @@ void config_verification() ments[1].type = MENT_CHGLINE; - memcpy(vr_text, " Disable (Fastest)", 19); - memcpy(vr_text + 64, " Sparse (Fast)", 16); - memcpy(vr_text + 128, " Full (Slow)", 16); + memcpy(vr_text, " Disable (Fastest - Unsafe)", 28); + memcpy(vr_text + 64, " Sparse (Fast - Safe)", 23); + memcpy(vr_text + 128, " Full (Slow - Safe)", 23); for (u32 i = 0; i < 3; i++) { diff --git a/bootloader/frontend/fe_emmc_tools.c b/bootloader/frontend/fe_emmc_tools.c index ccea1ed..482c8f9 100644 --- a/bootloader/frontend/fe_emmc_tools.c +++ b/bootloader/frontend/fe_emmc_tools.c @@ -31,6 +31,10 @@ #include "../utils/btn.h" #include "../utils/util.h" +#define EMMC_BUF_ALIGNED 0x85000000 +#define SDXC_BUF_ALIGNED 0x86000000 +#define MIXD_BUF_ALIGNED 0x87000000 + extern sdmmc_t sd_sdmmc; extern sdmmc_storage_t sd_storage; extern FATFS sd_fs; @@ -43,6 +47,7 @@ extern void emmcsn_path_impl(char *path, char *sub_dir, char *filename, sdmmc_st static int _dump_emmc_verify(sdmmc_storage_t *storage, u32 lba_curr, char *outFilename, emmc_part_t *part) { FIL fp; + u8 sparseShouldVerify = 0; u32 btn = 0; u32 prevPct = 200; int res = 0; @@ -54,14 +59,10 @@ static int _dump_emmc_verify(sdmmc_storage_t *storage, u32 lba_curr, char *outFi { u32 totalSectorsVer = (u32)((u64)f_size(&fp) >> (u64)9); - u32 numSectorsPerIter = 0; - if (totalSectorsVer > 0x200000) - numSectorsPerIter = 8192; //4MB Cache - else - numSectorsPerIter = 512; //256KB Cache + const u32 NUM_SECTORS_PER_ITER = 8192; // 4MB Cache. - u8 *bufEm = (u8 *)calloc(numSectorsPerIter, NX_EMMC_BLOCKSIZE); - u8 *bufSd = (u8 *)calloc(numSectorsPerIter, NX_EMMC_BLOCKSIZE); + u8 *bufEm = (u8 *)EMMC_BUF_ALIGNED; + u8 *bufSd = (u8 *)SDXC_BUF_ALIGNED; u32 pct = (u64)((u64)(lba_curr - part->lba_start) * 100u) / (u64)(part->lba_end - part->lba_start); tui_pbar(&gfx_con, 0, gfx_con.y, pct, 0xFF96FF00, 0xFF155500); @@ -69,53 +70,47 @@ static int _dump_emmc_verify(sdmmc_storage_t *storage, u32 lba_curr, char *outFi u32 num = 0; while (totalSectorsVer > 0) { - num = MIN(totalSectorsVer, numSectorsPerIter); - - if (!sdmmc_storage_read(storage, lba_curr, num, bufEm)) + num = MIN(totalSectorsVer, NUM_SECTORS_PER_ITER); + + // Check every time or every 4. + // Every 4 protects from fake sd, sector corruption and frequent I/O corruption. + // Full provides all that, plus protection from extremely rare I/O corruption. + if ((h_cfg.verification & 2) || !(sparseShouldVerify % 4)) { - gfx_con.fntsz = 16; - EPRINTFARGS("\nFailed to read %d blocks (@LBA %08X),\nfrom eMMC!\n\nVerification failed..\n", - num, lba_curr); + if (!sdmmc_storage_read(storage, lba_curr, num, bufEm)) + { + gfx_con.fntsz = 16; + EPRINTFARGS("\nFailed to read %d blocks (@LBA %08X),\nfrom eMMC!\n\nVerification failed..\n", + num, lba_curr); + + f_close(&fp); + return 1; + } + if (f_read(&fp, bufSd, num << 9, NULL)) + { + gfx_con.fntsz = 16; + EPRINTFARGS("\nFailed to read %d blocks (@LBA %08X),\nfrom sd card!\n\nVerification failed..\n", num, lba_curr); + + f_close(&fp); + return 1; + } - free(bufEm); - free(bufSd); - f_close(&fp); - return 1; - } - if (f_read(&fp, bufSd, num << 9, NULL)) - { - gfx_con.fntsz = 16; - EPRINTFARGS("\nFailed to read %d blocks (@LBA %08X),\nfrom sd card!\n\nVerification failed..\n", num, lba_curr); - - free(bufEm); - free(bufSd); - f_close(&fp); - return 1; - } - - switch (h_cfg.verification) - { - case 1: - res = memcmp32sparse((u32 *)bufEm, (u32 *)bufSd, num << 9); - break; - case 2: - default: - se_calc_sha256(&hashEm, bufEm, num << 9); - se_calc_sha256(&hashSd, bufSd, num << 9); + se_calc_sha256(hashEm, bufEm, num << 9); + se_calc_sha256(hashSd, bufSd, num << 9); res = memcmp(hashEm, hashSd, 0x10); - break; - } - if (res) - { - gfx_con.fntsz = 16; - EPRINTFARGS("\nSD card and eMMC data (@LBA %08X),\ndo not match!\n\nVerification failed..\n", lba_curr); - free(bufEm); - free(bufSd); - f_close(&fp); - return 1; + if (res) + { + gfx_con.fntsz = 16; + EPRINTFARGS("\nSD and eMMC data (@LBA %08X),\ndo not match!\n\nVerification failed..\n", lba_curr); + + f_close(&fp); + return 1; + } } + sparseShouldVerify++; + pct = (u64)((u64)(lba_curr - part->lba_start) * 100u) / (u64)(part->lba_end - part->lba_start); if (pct != prevPct) { @@ -130,19 +125,15 @@ static int _dump_emmc_verify(sdmmc_storage_t *storage, u32 lba_curr, char *outFi if ((btn & BTN_VOL_DOWN) && (btn & BTN_VOL_UP)) { gfx_con.fntsz = 16; - WPRINTF("\n\nThe verification was cancelled!"); + WPRINTF("\n\nVerification was cancelled!"); EPRINTF("\nPress any key...\n"); - msleep(1500); + msleep(1000); - free(bufEm); - free(bufSd); f_close(&fp); return 0; } } - free(bufEm); - free(bufSd); f_close(&fp); tui_pbar(&gfx_con, 0, gfx_con.y, pct, 0xFFCCCCCC, 0xFF555555); @@ -157,6 +148,17 @@ static int _dump_emmc_verify(sdmmc_storage_t *storage, u32 lba_curr, char *outFi } } +void _update_filename(char *outFilename, u32 sdPathLen, u32 numSplitParts, u32 currPartIdx) +{ + if (numSplitParts >= 10 && currPartIdx < 10) + { + outFilename[sdPathLen] = '0'; + itoa(currPartIdx, &outFilename[sdPathLen + 1], 10); + } + else + itoa(currPartIdx, &outFilename[sdPathLen], 10); +} + static int _dump_emmc_part(char *sd_path, sdmmc_storage_t *storage, emmc_part_t *part) { static const u32 FAT32_FILESIZE_LIMIT = 0xFFFFFFFF; @@ -187,7 +189,7 @@ static int _dump_emmc_part(char *sd_path, sdmmc_storage_t *storage, emmc_part_t if ((sd_storage.csd.capacity >> (20 - sd_storage.csd.read_blkbits)) <= 8192) multipartSplitSize = (1u << 30); // Maximum parts fitting the free space available. - maxSplitParts = (sd_fs.free_clst * sd_fs.csize) / (multipartSplitSize / 512); + maxSplitParts = (sd_fs.free_clst * sd_fs.csize) / (multipartSplitSize / NX_EMMC_BLOCKSIZE); // Check if the USER partition or the RAW eMMC fits the sd card free space. if (totalSectors > (sd_fs.free_clst * sd_fs.csize)) @@ -238,28 +240,8 @@ static int _dump_emmc_part(char *sd_path, sdmmc_storage_t *storage, emmc_part_t outFilename[sdPathLen++] = '.'; - if (!partialDumpInProgress) - { - outFilename[sdPathLen] = '0'; - if (numSplitParts >= 10) - { - outFilename[sdPathLen + 1] = '0'; - outFilename[sdPathLen + 2] = 0; - } - else - outFilename[sdPathLen + 1] = 0; - } // Continue from where we left, if Partial Backup in progress. - else - { - if (numSplitParts >= 10 && currPartIdx < 10) - { - outFilename[sdPathLen] = '0'; - itoa(currPartIdx, &outFilename[sdPathLen + 1], 10); - } - else - itoa(currPartIdx, &outFilename[sdPathLen], 10); - } + _update_filename(outFilename, sdPathLen, numSplitParts, partialDumpInProgress ? currPartIdx : 0); } FIL fp; @@ -268,7 +250,7 @@ static int _dump_emmc_part(char *sd_path, sdmmc_storage_t *storage, emmc_part_t { f_close(&fp); gfx_con.fntsz = 16; - + WPRINTF("An existing backup has been detected!"); WPRINTF("Press POWER to Continue.\nPress VOL to go to the menu.\n"); msleep(500); @@ -289,12 +271,9 @@ static int _dump_emmc_part(char *sd_path, sdmmc_storage_t *storage, emmc_part_t return 0; } - u32 numSectorsPerIter = 0; - if (totalSectors > 0x200000) - numSectorsPerIter = 8192; - else - numSectorsPerIter = 512; - u8 *buf = (u8 *)calloc(numSectorsPerIter, NX_EMMC_BLOCKSIZE); + const u32 NUM_SECTORS_PER_ITER = 8192; + + u8 *buf = (u8 *)MIXD_BUF_ALIGNED; u32 lba_curr = part->lba_start; u32 lbaStartPart = part->lba_start; @@ -333,18 +312,11 @@ static int _dump_emmc_part(char *sd_path, sdmmc_storage_t *storage, emmc_part_t { EPRINTF("\nPress any key and try again...\n"); - free(buf); return 0; } } - if (numSplitParts >= 10 && currPartIdx < 10) - { - outFilename[sdPathLen] = '0'; - itoa(currPartIdx, &outFilename[sdPathLen + 1], 10); - } - else - itoa(currPartIdx, &outFilename[sdPathLen], 10); + _update_filename(outFilename, sdPathLen, numSplitParts, currPartIdx); // Always create partial.idx before next part, in case a fatal error occurs. if (isSmallSdCard) @@ -360,7 +332,6 @@ static int _dump_emmc_part(char *sd_path, sdmmc_storage_t *storage, emmc_part_t gfx_con.fntsz = 16; EPRINTF("\nError creating partial.idx file.\n"); - free(buf); return 0; } @@ -374,7 +345,6 @@ static int _dump_emmc_part(char *sd_path, sdmmc_storage_t *storage, emmc_part_t 4. Select the SAME option again to continue.\n"); gfx_con.fntsz = 16; - free(buf); return 1; } } @@ -389,7 +359,6 @@ static int _dump_emmc_part(char *sd_path, sdmmc_storage_t *storage, emmc_part_t gfx_con.fntsz = 16; EPRINTFARGS("Error (%d) creating file %s.\n", res, outFilename); - free(buf); return 0; } bytesWritten = 0; @@ -400,7 +369,7 @@ static int _dump_emmc_part(char *sd_path, sdmmc_storage_t *storage, emmc_part_t } retryCount = 0; - num = MIN(totalSectors, numSectorsPerIter); + num = MIN(totalSectors, NUM_SECTORS_PER_ITER); while (!sdmmc_storage_read(storage, lba_curr, num, buf)) { EPRINTFARGS("Error reading %d blocks @ LBA %08X,\nfrom eMMC (try %d), retrying...", @@ -414,7 +383,6 @@ static int _dump_emmc_part(char *sd_path, sdmmc_storage_t *storage, emmc_part_t num, lba_curr); EPRINTF("\nPress any key and try again...\n"); - free(buf); f_close(&fp); f_unlink(outFilename); @@ -428,7 +396,6 @@ static int _dump_emmc_part(char *sd_path, sdmmc_storage_t *storage, emmc_part_t EPRINTFARGS("\nFatal error (%d) when writing to SD Card", res); EPRINTF("\nPress any key and try again...\n"); - free(buf); f_close(&fp); f_unlink(outFilename); @@ -460,7 +427,6 @@ static int _dump_emmc_part(char *sd_path, sdmmc_storage_t *storage, emmc_part_t EPRINTF("\nPress any key...\n"); msleep(1500); - free(buf); f_close(&fp); f_unlink(outFilename); @@ -470,7 +436,6 @@ static int _dump_emmc_part(char *sd_path, sdmmc_storage_t *storage, emmc_part_t tui_pbar(&gfx_con, 0, gfx_con.y, 100, 0xFFCCCCCC, 0xFF555555); // Backup operation ended successfully. - free(buf); f_close(&fp); if (h_cfg.verification) @@ -664,13 +629,9 @@ static int _restore_emmc_part(char *sd_path, sdmmc_storage_t *storage, emmc_part else gfx_printf(&gfx_con, "\nTotal restore size: %d MiB.\n\n", ((u32)((u64)f_size(&fp) >> (u64)9)) >> SECTORS_TO_MIB_COEFF); - u32 numSectorsPerIter = 0; - if (totalSectors > 0x200000) - numSectorsPerIter = 8192; //4MB Cache - else - numSectorsPerIter = 512; //256KB Cache + const u32 NUM_SECTORS_PER_ITER = 8192; // 4MB Cache. - u8 *buf = (u8 *)calloc(numSectorsPerIter, NX_EMMC_BLOCKSIZE); + u8 *buf = (u8 *)MIXD_BUF_ALIGNED; u32 lba_curr = part->lba_start; u32 bytesWritten = 0; @@ -682,7 +643,7 @@ static int _restore_emmc_part(char *sd_path, sdmmc_storage_t *storage, emmc_part while (totalSectors > 0) { retryCount = 0; - num = MIN(totalSectors, numSectorsPerIter); + num = MIN(totalSectors, NUM_SECTORS_PER_ITER); res = f_read(&fp, buf, NX_EMMC_BLOCKSIZE * num, NULL); if (res) @@ -691,7 +652,6 @@ static int _restore_emmc_part(char *sd_path, sdmmc_storage_t *storage, emmc_part EPRINTFARGS("\nFatal error (%d) when reading from SD Card", res); EPRINTF("\nYour device may be in an inoperative state!\n\nPress any key and try again now...\n"); - free(buf); f_close(&fp); return 0; } @@ -708,7 +668,6 @@ static int _restore_emmc_part(char *sd_path, sdmmc_storage_t *storage, emmc_part num, lba_curr); EPRINTF("\nYour device may be in an inoperative state!\n\nPress any key and try again...\n"); - free(buf); f_close(&fp); return 0; } @@ -727,7 +686,6 @@ static int _restore_emmc_part(char *sd_path, sdmmc_storage_t *storage, emmc_part tui_pbar(&gfx_con, 0, gfx_con.y, 100, 0xFFCCCCCC, 0xFF555555); // Restore operation ended successfully. - free(buf); f_close(&fp); if (h_cfg.verification) @@ -769,13 +727,13 @@ static void _restore_emmc_selected(emmcPartType_t restoreType) } gfx_con_getpos(&gfx_con, &gfx_con.savedx, &gfx_con.savedy); - u8 value = 10; - while (value > 0) + u8 failsafe_wait = 10; + while (failsafe_wait > 0) { gfx_con_setpos(&gfx_con, gfx_con.savedx, gfx_con.savedy); - gfx_printf(&gfx_con, "%kWait... (%ds) %k", 0xFF888888, value, 0xFFCCCCCC); + gfx_printf(&gfx_con, "%kWait... (%ds) %k", 0xFF888888, failsafe_wait, 0xFFCCCCCC); msleep(1000); - value--; + failsafe_wait--; } gfx_con_setpos(&gfx_con, gfx_con.savedx, gfx_con.savedy); diff --git a/bootloader/utils/util.c b/bootloader/utils/util.c index c34764a..7673057 100644 --- a/bootloader/utils/util.c +++ b/bootloader/utils/util.c @@ -120,31 +120,3 @@ u32 crc32c(const void *buf, u32 len) } return ~crc; } - -u32 memcmp32sparse(const u32 *buf1, const u32 *buf2, u32 len) -{ - u32 len32 = len / 4; - - if (!(len32 % 32)) - { - while (len32) - { - len32 -= 32; - if(buf1[len32] != buf2[len32]) - return 1; - } - } - else - { - while (len32) - { - len32 -= 32; - if(buf1[len32] != buf2[len32]) - return 1; - if (len32 < 32) - return 0; - } - } - - return 0; -} diff --git a/bootloader/utils/util.h b/bootloader/utils/util.h index 3b57703..8aa3632 100644 --- a/bootloader/utils/util.h +++ b/bootloader/utils/util.h @@ -41,8 +41,4 @@ void power_off(); void exec_cfg(u32 *base, const cfg_op_t *ops, u32 num_ops); u32 crc32c(const void *buf, u32 len); -/* This is a faster implementation of memcmp that checks two u32 values */ -/* every 128 Bytes block. Intented only for Backup and Restore */ -u32 memcmp32sparse(const u32 *buf1, const u32 *buf2, u32 len); - #endif