[eMMC Tools] Support for partial restore

Co-Authored-By: emvym3two <emvym3two@users.noreply.github.com>
This commit is contained in:
Kostas Missos 2019-03-09 00:09:36 +02:00
parent 4b78198f33
commit 50eff41351
2 changed files with 113 additions and 9 deletions

View file

@ -595,20 +595,78 @@ void dump_emmc_user() { _dump_emmc_selected(PART_USER); }
void dump_emmc_boot() { _dump_emmc_selected(PART_BOOT); } void dump_emmc_boot() { _dump_emmc_selected(PART_BOOT); }
void dump_emmc_rawnand() { _dump_emmc_selected(PART_RAW); } void dump_emmc_rawnand() { _dump_emmc_selected(PART_RAW); }
static int _restore_emmc_part(char *sd_path, sdmmc_storage_t *storage, emmc_part_t *part) static int _restore_emmc_part(char *sd_path, sdmmc_storage_t *storage, emmc_part_t *part, bool allow_multi_part)
{ {
static const u32 SECTORS_TO_MIB_COEFF = 11; static const u32 SECTORS_TO_MIB_COEFF = 11;
u32 totalSectors = part->lba_end - part->lba_start + 1; u32 totalSectors = part->lba_end - part->lba_start + 1;
u32 currPartIdx = 0;
u32 numSplitParts = 0;
u32 lbaStartPart = part->lba_start; u32 lbaStartPart = part->lba_start;
int res = 0; int res = 0;
char *outFilename = sd_path; char *outFilename = sd_path;
u32 sdPathLen = strlen(sd_path);
u64 fileSize = 0;
u64 totalCheckFileSize = 0;
gfx_con.fntsz = 8; gfx_con.fntsz = 8;
FIL fp; FIL fp;
FILINFO fno;
gfx_printf(&gfx_con, "\nFilename: %s\n", outFilename); gfx_printf(&gfx_con, "\nFilename: %s\n", outFilename);
bool use_multipart = false;
if (allow_multi_part)
{
// Check to see if there is a combined file and if so then use that.
if (f_stat(outFilename, &fno))
{
// If not, check if there are partial files and the total size matches.
gfx_printf(&gfx_con, "\nFile not found, checking for part files.\n");
// Store console pos, so we dont take too much room.
gfx_con_getpos(&gfx_con, &gfx_con.savedx, &gfx_con.savedy);
outFilename[sdPathLen++] = '.';
// Stat total size of the part files.
while ((u32)((u64)totalCheckFileSize >> (u64)9) != totalSectors)
{
_update_filename(outFilename, sdPathLen, 99, numSplitParts);
gfx_con_setpos(&gfx_con, gfx_con.savedx, gfx_con.savedy);
gfx_printf(&gfx_con, "\nFilename: %s\n", outFilename);
if (f_stat(outFilename, &fno))
{
WPRINTFARGS("Error (%d) file not found '%s'. Aborting...\n", res, outFilename);
return 0;
}
else
totalCheckFileSize += (u64)fno.fsize;
numSplitParts++;
}
gfx_printf(&gfx_con, "\n%X sectors total.\n", (u32)((u64)totalCheckFileSize >> (u64)9));
if ((u32)((u64)totalCheckFileSize >> (u64)9) != totalSectors)
{
gfx_con.fntsz = 16;
EPRINTF("Size of SD Card split backups does not match,\neMMC's selected part size.\n");
return 0;
}
else
{
use_multipart = true;
_update_filename(outFilename, sdPathLen, numSplitParts, 0);
}
}
}
gfx_con_setpos(&gfx_con, gfx_con.savedx, gfx_con.savedy);
res = f_open(&fp, outFilename, FA_READ); res = f_open(&fp, outFilename, FA_READ);
if (res) if (res)
{ {
@ -620,8 +678,7 @@ static int _restore_emmc_part(char *sd_path, sdmmc_storage_t *storage, emmc_part
return 0; return 0;
} }
//TODO: Should we keep this check? else if (!use_multipart && (((u32)((u64)f_size(&fp) >> (u64)9)) != totalSectors)) // Check total restore size vs emmc size.
else if (((u32)((u64)f_size(&fp) >> (u64)9)) != totalSectors)
{ {
gfx_con.fntsz = 16; gfx_con.fntsz = 16;
EPRINTF("Size of the SD Card backup does not match,\neMMC's selected part size.\n"); EPRINTF("Size of the SD Card backup does not match,\neMMC's selected part size.\n");
@ -630,7 +687,11 @@ static int _restore_emmc_part(char *sd_path, sdmmc_storage_t *storage, emmc_part
return 0; return 0;
} }
else else
gfx_printf(&gfx_con, "\nTotal restore size: %d MiB.\n\n", ((u32)((u64)f_size(&fp) >> (u64)9)) >> SECTORS_TO_MIB_COEFF); {
fileSize = (u64)f_size(&fp);
gfx_printf(&gfx_con, "\nTotal restore size: %d MiB.\n\n",
((u32)((use_multipart ? ((u64)totalCheckFileSize >> (u64)9) : fileSize) >> (u64)9)) >> SECTORS_TO_MIB_COEFF);
}
const u32 NUM_SECTORS_PER_ITER = 8192; // 4MB Cache. const u32 NUM_SECTORS_PER_ITER = 8192; // 4MB Cache.
@ -643,8 +704,51 @@ static int _restore_emmc_part(char *sd_path, sdmmc_storage_t *storage, emmc_part
u32 num = 0; u32 num = 0;
u32 pct = 0; u32 pct = 0;
gfx_con_getpos(&gfx_con, &gfx_con.savedx, &gfx_con.savedy);
while (totalSectors > 0) while (totalSectors > 0)
{ {
// If we have more than one part, check the size for the split parts and make sure that the bytes written is not more than that.
if (numSplitParts != 0 && bytesWritten >= fileSize)
{
// If we have more bytes written then close the file pointer and increase the part index we are using
f_close(&fp);
memset(&fp, 0, sizeof(fp));
currPartIdx++;
if (h_cfg.verification)
{
// Verify part.
if (_dump_emmc_verify(storage, lbaStartPart, outFilename, part))
{
EPRINTF("\nPress any key and try again...\n");
return 0;
}
}
_update_filename(outFilename, sdPathLen, numSplitParts, currPartIdx);
// Read from next part.
gfx_con_setpos(&gfx_con, gfx_con.savedx, gfx_con.savedy);
gfx_printf(&gfx_con, "Filename: %s\n\n", outFilename);
lbaStartPart = lba_curr;
// Try to open the next file part
res = f_open(&fp, outFilename, FA_READ);
if (res)
{
gfx_con.fntsz = 16;
EPRINTFARGS("Error (%d) opening file %s.\n", res, outFilename);
return 0;
}
fileSize = (u64)f_size(&fp);
bytesWritten = 0;
}
retryCount = 0; retryCount = 0;
num = MIN(totalSectors, NUM_SECTORS_PER_ITER); num = MIN(totalSectors, NUM_SECTORS_PER_ITER);
@ -781,7 +885,7 @@ static void _restore_emmc_selected(emmcPartType_t restoreType)
sdmmc_storage_set_mmc_partition(&storage, i + 1); sdmmc_storage_set_mmc_partition(&storage, i + 1);
emmcsn_path_impl(sdPath, "/restore", bootPart.name, &storage); emmcsn_path_impl(sdPath, "/restore", bootPart.name, &storage);
res = _restore_emmc_part(sdPath, &storage, &bootPart); res = _restore_emmc_part(sdPath, &storage, &bootPart, false);
} }
} }
@ -797,7 +901,7 @@ static void _restore_emmc_selected(emmcPartType_t restoreType)
part->name, part->lba_start, part->lba_end, 0xFFCCCCCC); part->name, part->lba_start, part->lba_end, 0xFFCCCCCC);
emmcsn_path_impl(sdPath, "/restore/partitions/", part->name, &storage); emmcsn_path_impl(sdPath, "/restore/partitions/", part->name, &storage);
res = _restore_emmc_part(sdPath, &storage, part); res = _restore_emmc_part(sdPath, &storage, part, false);
} }
nx_emmc_gpt_free(&gpt); nx_emmc_gpt_free(&gpt);
} }
@ -817,7 +921,7 @@ static void _restore_emmc_selected(emmcPartType_t restoreType)
rawPart.name, rawPart.lba_start, rawPart.lba_end, 0xFFCCCCCC); rawPart.name, rawPart.lba_start, rawPart.lba_end, 0xFFCCCCCC);
emmcsn_path_impl(sdPath, "/restore", rawPart.name, &storage); emmcsn_path_impl(sdPath, "/restore", rawPart.name, &storage);
res = _restore_emmc_part(sdPath, &storage, &rawPart); res = _restore_emmc_part(sdPath, &storage, &rawPart, true);
} }
} }

View file

@ -1046,7 +1046,7 @@ ment_t ment_restore[] = {
MDEF_CHGLINE(), MDEF_CHGLINE(),
MDEF_CAPTION("------ Full --------", 0xFF0AB9E6), MDEF_CAPTION("------ Full --------", 0xFF0AB9E6),
MDEF_HANDLER("Restore eMMC BOOT0/1", restore_emmc_boot), MDEF_HANDLER("Restore eMMC BOOT0/1", restore_emmc_boot),
MDEF_HANDLER("Restore eMMC RAW GPP (exFAT only)", restore_emmc_rawnand), MDEF_HANDLER("Restore eMMC RAW GPP", restore_emmc_rawnand),
MDEF_CHGLINE(), MDEF_CHGLINE(),
MDEF_CAPTION("-- GPP Partitions --", 0xFF0AB9E6), MDEF_CAPTION("-- GPP Partitions --", 0xFF0AB9E6),
MDEF_HANDLER("Restore GPP partitions", restore_emmc_gpp_parts), MDEF_HANDLER("Restore GPP partitions", restore_emmc_gpp_parts),