2020-12-30 21:51:07 +00:00
|
|
|
#include "emmcfile.h"
|
|
|
|
#include "../gfx/gfx.h"
|
|
|
|
#include "emummc.h"
|
|
|
|
#include "mountmanager.h"
|
|
|
|
#include <libs/fatfs/ff.h>
|
|
|
|
#include "nx_emmc.h"
|
|
|
|
#include <mem/heap.h>
|
|
|
|
#include "../err.h"
|
|
|
|
#include "../tegraexplorer/tconf.h"
|
|
|
|
#include "../gfx/gfxutils.h"
|
|
|
|
#include "../hid/hid.h"
|
|
|
|
#include <storage/nx_sd.h>
|
|
|
|
#include <string.h>
|
2020-12-31 11:55:26 +00:00
|
|
|
#include "../fs/fsutils.h"
|
2021-03-17 15:35:22 +00:00
|
|
|
#include "nx_emmc_bis.h"
|
2020-12-30 21:51:07 +00:00
|
|
|
|
|
|
|
// Uses default storage in nx_emmc.c
|
|
|
|
// Expects the correct mmc & partition to be set
|
2021-03-17 15:35:22 +00:00
|
|
|
ErrCode_t EmmcDumpToFile(const char *path, u32 lba_start, u32 lba_end, u8 force, u8 crypt){
|
2020-12-30 21:51:07 +00:00
|
|
|
FIL fp;
|
|
|
|
u32 curLba = lba_start;
|
|
|
|
u32 totalSectors = lba_end - lba_start + 1;
|
|
|
|
|
2020-12-31 11:55:26 +00:00
|
|
|
if (FileExists(path) && !force){
|
|
|
|
return newErrCode(TE_WARN_FILE_EXISTS);
|
|
|
|
}
|
|
|
|
|
2020-12-30 21:51:07 +00:00
|
|
|
int res = f_open(&fp, path, FA_CREATE_ALWAYS | FA_WRITE);
|
|
|
|
if (res){
|
|
|
|
return newErrCode(res);
|
|
|
|
}
|
|
|
|
|
|
|
|
ErrCode_t err = newErrCode(0);
|
|
|
|
|
|
|
|
u8 *buff = malloc(TConf.FSBuffSize);
|
|
|
|
|
2020-12-31 11:55:26 +00:00
|
|
|
if (!buff)
|
|
|
|
return newErrCode(TE_ERR_MEM_ALLOC_FAIL);
|
|
|
|
|
2020-12-30 21:51:07 +00:00
|
|
|
u32 x, y;
|
|
|
|
gfx_con_getpos(&x, &y);
|
|
|
|
|
|
|
|
while (totalSectors > 0){
|
|
|
|
u32 num = MIN(totalSectors, TConf.FSBuffSize / NX_EMMC_BLOCKSIZE);
|
2021-03-17 15:35:22 +00:00
|
|
|
|
|
|
|
int readRes = 0;
|
|
|
|
if (crypt)
|
|
|
|
readRes = !nx_emmc_bis_read(curLba, num, buff);
|
|
|
|
else
|
|
|
|
readRes = emummc_storage_read(&emmc_storage, curLba, num, buff);
|
|
|
|
|
|
|
|
if (!readRes){
|
2020-12-30 21:51:07 +00:00
|
|
|
err = newErrCode(TE_ERR_EMMC_READ_FAIL);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((res = f_write(&fp, buff, num * NX_EMMC_BLOCKSIZE, NULL))){
|
|
|
|
err = newErrCode(res);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
curLba += num;
|
|
|
|
totalSectors -= num;
|
|
|
|
|
|
|
|
u32 percent = ((curLba - lba_start) * 100) / ((lba_end - lba_start + 1));
|
|
|
|
gfx_printf("[%3d%%]", percent);
|
|
|
|
gfx_con_setpos(x, y);
|
|
|
|
}
|
|
|
|
|
|
|
|
f_close(&fp);
|
|
|
|
free(buff);
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2021-03-17 15:35:22 +00:00
|
|
|
ErrCode_t EmmcRestoreFromFile(const char *path, u32 lba_start, u32 lba_end, u8 force, u8 crypt){
|
2020-12-31 11:55:26 +00:00
|
|
|
FIL fp;
|
|
|
|
u32 curLba = lba_start;
|
|
|
|
u32 totalSectorsDest = lba_end - lba_start + 1;
|
|
|
|
|
|
|
|
int res = f_open(&fp, path, FA_OPEN_ALWAYS | FA_READ);
|
|
|
|
if (res)
|
|
|
|
return newErrCode(res);
|
|
|
|
|
|
|
|
u64 totalSizeSrc = f_size(&fp);
|
|
|
|
u32 totalSectorsSrc = totalSizeSrc / NX_EMMC_BLOCKSIZE;
|
|
|
|
|
|
|
|
if (totalSectorsSrc > totalSectorsDest) // We don't close the file here, oh well
|
|
|
|
return newErrCode(TE_ERR_FILE_TOO_BIG_FOR_DEST);
|
|
|
|
|
|
|
|
if (totalSectorsSrc < totalSectorsDest && !force)
|
|
|
|
return newErrCode(TE_WARN_FILE_TOO_SMALL_FOR_DEST);
|
|
|
|
|
|
|
|
u8 *buff = malloc(TConf.FSBuffSize);
|
|
|
|
ErrCode_t err = newErrCode(0);
|
|
|
|
|
|
|
|
if (!buff)
|
|
|
|
return newErrCode(TE_ERR_MEM_ALLOC_FAIL);
|
|
|
|
|
|
|
|
u32 x, y;
|
|
|
|
gfx_con_getpos(&x, &y);
|
|
|
|
|
|
|
|
while (totalSectorsSrc > 0){
|
|
|
|
u32 num = MIN(totalSectorsSrc, TConf.FSBuffSize / NX_EMMC_BLOCKSIZE);
|
|
|
|
|
|
|
|
if ((res = f_read(&fp, buff, num * NX_EMMC_BLOCKSIZE, NULL))){
|
|
|
|
err = newErrCode(res);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2021-03-17 15:35:22 +00:00
|
|
|
int writeRes = 0;
|
|
|
|
if (crypt)
|
|
|
|
writeRes = !nx_emmc_bis_write(curLba, num, buff);
|
|
|
|
else
|
|
|
|
writeRes = emummc_storage_write(&emmc_storage, curLba, num, buff);
|
|
|
|
|
|
|
|
if (!writeRes){
|
2020-12-31 11:55:26 +00:00
|
|
|
err = newErrCode(TE_ERR_EMMC_WRITE_FAIL);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
curLba += num;
|
|
|
|
totalSectorsSrc -= num;
|
|
|
|
|
|
|
|
u32 percent = ((curLba - lba_start) * 100) / ((totalSizeSrc / NX_EMMC_BLOCKSIZE));
|
|
|
|
gfx_printf("[%3d%%]", percent);
|
|
|
|
gfx_con_setpos(x, y);
|
|
|
|
}
|
|
|
|
|
|
|
|
f_close(&fp);
|
|
|
|
free(buff);
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2021-03-17 15:35:22 +00:00
|
|
|
int isSystemPartCrypt(emmc_part_t *part){
|
|
|
|
switch (part->index){
|
|
|
|
case 0:
|
|
|
|
case 1:
|
|
|
|
case 8:
|
|
|
|
case 9:
|
|
|
|
case 10:
|
|
|
|
return 1;
|
|
|
|
default:
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-31 11:55:26 +00:00
|
|
|
ErrCode_t DumpOrWriteEmmcPart(const char *path, const char *part, u8 write, u8 force){
|
2020-12-30 21:51:07 +00:00
|
|
|
const u32 BOOT_PART_SIZE = emmc_storage.ext_csd.boot_mult << 17;
|
2020-12-31 11:55:26 +00:00
|
|
|
u32 lba_start = 0;
|
|
|
|
u32 lba_end = 0;
|
2021-03-17 15:35:22 +00:00
|
|
|
u8 crypt = false;
|
2020-12-30 21:51:07 +00:00
|
|
|
|
|
|
|
if (!sd_mount())
|
|
|
|
return newErrCode(TE_ERR_NO_SD);
|
|
|
|
|
[script] Make equivalent to tsV1
Fixed: functions in functions
Added functions: version, menu, pathCombine, pathEscFolder, fileMove, fileCopy, fileDel, mmcConnect, mmcMount, mkdir, dirRead, dirCopy, dirDel, mmcDump, mmcRestore
2021-01-04 00:55:58 +00:00
|
|
|
if (TConf.currentMMCConnected == MMC_CONN_None)
|
|
|
|
return newErrCode(TE_ERR_PARTITION_NOT_FOUND);
|
|
|
|
|
2020-12-30 21:51:07 +00:00
|
|
|
if (!memcmp(part, "BOOT0", 5)){
|
|
|
|
emummc_storage_set_mmc_partition(&emmc_storage, 1);
|
2020-12-31 11:55:26 +00:00
|
|
|
lba_end = (BOOT_PART_SIZE / NX_EMMC_BLOCKSIZE) - 1;
|
2020-12-30 21:51:07 +00:00
|
|
|
}
|
|
|
|
else if (!memcmp(part, "BOOT1", 5)){
|
|
|
|
emummc_storage_set_mmc_partition(&emmc_storage, 2);
|
2020-12-31 11:55:26 +00:00
|
|
|
lba_end = (BOOT_PART_SIZE / NX_EMMC_BLOCKSIZE) - 1;
|
2020-12-30 21:51:07 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
emummc_storage_set_mmc_partition(&emmc_storage, 0);
|
|
|
|
|
|
|
|
emmc_part_t *system_part = nx_emmc_part_find(GetCurGPT(), part);
|
|
|
|
if (!system_part)
|
|
|
|
return newErrCode(TE_ERR_PARTITION_NOT_FOUND);
|
|
|
|
|
2021-05-23 22:57:58 +01:00
|
|
|
if (isSystemPartCrypt(system_part) && TConf.keysDumped){
|
2021-03-17 15:35:22 +00:00
|
|
|
nx_emmc_bis_init(system_part);
|
|
|
|
crypt = true;
|
|
|
|
lba_start = 0;
|
|
|
|
lba_end = system_part->lba_end - system_part->lba_start;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
lba_start = system_part->lba_start;
|
|
|
|
lba_end = system_part->lba_end;
|
|
|
|
}
|
2020-12-30 21:51:07 +00:00
|
|
|
}
|
2020-12-31 11:55:26 +00:00
|
|
|
|
2021-03-17 15:35:22 +00:00
|
|
|
return ((write) ? EmmcRestoreFromFile(path, lba_start, lba_end, force, crypt) : EmmcDumpToFile(path, lba_start, lba_end, force, crypt));
|
2020-12-30 21:51:07 +00:00
|
|
|
}
|