mirror of
https://github.com/Scandal-UK/Incognito_RCM.git
synced 2024-11-22 20:06:42 +00:00
reading, writing, verifing working
This commit is contained in:
parent
ee01f32e53
commit
357e25dc45
4 changed files with 284 additions and 230 deletions
2
Makefile
2
Makefile
|
@ -15,7 +15,7 @@ LPVERSION_BUGFX := 2
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
|
|
||||||
TARGET := Incognito_RCM
|
TARGET := Incognito_RCM_new
|
||||||
BUILDDIR := build
|
BUILDDIR := build
|
||||||
OUTPUTDIR := output
|
OUTPUTDIR := output
|
||||||
SOURCEDIR = source
|
SOURCEDIR = source
|
||||||
|
|
|
@ -56,13 +56,14 @@ sdmmc_storage_t storage;
|
||||||
sdmmc_t sdmmc;
|
sdmmc_t sdmmc;
|
||||||
emmc_part_t *system_part;
|
emmc_part_t *system_part;
|
||||||
emmc_part_t *prodinfo_part;
|
emmc_part_t *prodinfo_part;
|
||||||
u32 start_time, end_time;
|
|
||||||
|
|
||||||
#define ENCRYPTED 1
|
#define ENCRYPTED 1
|
||||||
#define DECRYPTED 0
|
#define DECRYPTED 0
|
||||||
#define SECTORS_IN_CLUSTER 32
|
#define SECTORS_IN_CLUSTER 32
|
||||||
#define PRODINFO_SIZE 0x3FBC00
|
#define PRODINFO_SIZE 0x3FBC00
|
||||||
|
|
||||||
|
#define BACKUP_NAME_EMUNAND "sd:/prodinfo_emunand.bin"
|
||||||
|
#define BACKUP_NAME_SYSNAND "sd:/prodinfo_sysnand.bin"
|
||||||
|
|
||||||
static u8 temp_key[0x10],
|
static u8 temp_key[0x10],
|
||||||
bis_key[4][0x20] = {0},
|
bis_key[4][0x20] = {0},
|
||||||
|
@ -90,20 +91,13 @@ bool dump_keys()
|
||||||
|
|
||||||
gfx_print_header();
|
gfx_print_header();
|
||||||
|
|
||||||
// gfx_printf("[%kLo%kck%kpi%kck%k_R%kCM%k v%d.%d.%d%k]\n\n",
|
|
||||||
// colors[0], colors[1], colors[2], colors[3], colors[4], colors[5], 0xFFFF00FF, LP_VER_MJ, LP_VER_MN, LP_VER_BF, 0xFFCCCCCC);
|
|
||||||
|
|
||||||
gfx_printf("%kGetting bis_keys...\n", COLOR_YELLOW);
|
gfx_printf("%kGetting bis_keys...\n", COLOR_YELLOW);
|
||||||
|
|
||||||
start_time = get_tmr_us();
|
|
||||||
//u32 begin_time = get_tmr_us();
|
|
||||||
u32 retries = 0;
|
u32 retries = 0;
|
||||||
// u32 color_idx = 0;
|
|
||||||
|
|
||||||
tsec_ctxt_t tsec_ctxt;
|
tsec_ctxt_t tsec_ctxt;
|
||||||
|
|
||||||
emummc_storage_init_mmc(&storage, &sdmmc);
|
emummc_storage_init_mmc(&storage, &sdmmc);
|
||||||
// TPRINTFARGS("%kMMC init... ", colors[(color_idx++) % 6]);
|
|
||||||
|
|
||||||
// Read package1.
|
// Read package1.
|
||||||
u8 *pkg1 = (u8 *)malloc(0x40000);
|
u8 *pkg1 = (u8 *)malloc(0x40000);
|
||||||
|
@ -181,8 +175,6 @@ bool dump_keys()
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//TPRINTFARGS("%kTSEC key(s)... ", colors[(color_idx++) % 6]);
|
|
||||||
|
|
||||||
// Master key derivation
|
// Master key derivation
|
||||||
if (pkg1_id->kb == KB_FIRMWARE_VERSION_620 && _key_exists(tsec_keys + 0x10))
|
if (pkg1_id->kb == KB_FIRMWARE_VERSION_620 && _key_exists(tsec_keys + 0x10))
|
||||||
{
|
{
|
||||||
|
@ -233,8 +225,6 @@ bool dump_keys()
|
||||||
}
|
}
|
||||||
free(keyblob_block);
|
free(keyblob_block);
|
||||||
|
|
||||||
//TPRINTFARGS("%kMaster keys... ", colors[(color_idx++) % 6]);
|
|
||||||
|
|
||||||
u32 key_generation = 0;
|
u32 key_generation = 0;
|
||||||
if (pkg1_id->kb >= KB_FIRMWARE_VERSION_500)
|
if (pkg1_id->kb >= KB_FIRMWARE_VERSION_500)
|
||||||
{
|
{
|
||||||
|
@ -286,22 +276,23 @@ bool dump_keys()
|
||||||
|
|
||||||
gfx_printf("%kGot keys!\n", COLOR_GREEN);
|
gfx_printf("%kGot keys!\n", COLOR_GREEN);
|
||||||
char serial[15];
|
char serial[15];
|
||||||
readData((u8 *)serial, 0x250, 15, ENCRYPTED);
|
readData((u8 *)serial, 0x250, 15, ENCRYPTED, NULL);
|
||||||
|
|
||||||
gfx_printf("%kCurrent serial:%s\n\n", COLOR_BLUE, serial);
|
gfx_printf("%kCurrent serial:%s\n\n", COLOR_BLUE, serial);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void erase(u32 offset, u32 length)
|
bool erase(u32 offset, u32 length)
|
||||||
{
|
{
|
||||||
|
|
||||||
u8 *tmp = (u8 *)calloc(length, sizeof(u8));
|
u8 *tmp = (u8 *)calloc(length, sizeof(u8));
|
||||||
writeData(tmp, offset, length, ENCRYPTED);
|
bool result = writeData(tmp, offset, length, ENCRYPTED, NULL);
|
||||||
free(tmp);
|
free(tmp);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void writeSerial()
|
bool writeSerial()
|
||||||
{
|
{
|
||||||
const char *junkSerial;
|
const char *junkSerial;
|
||||||
if (!emu_cfg.enabled || h_cfg.emummc_force_disable)
|
if (!emu_cfg.enabled || h_cfg.emummc_force_disable)
|
||||||
|
@ -313,39 +304,62 @@ void writeSerial()
|
||||||
junkSerial = "XAW00000000001";
|
junkSerial = "XAW00000000001";
|
||||||
}
|
}
|
||||||
|
|
||||||
writeData((u8 *)junkSerial, 0x250, 14, ENCRYPTED);
|
return writeData((u8 *)junkSerial, 0x250, 14, ENCRYPTED, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void incognito()
|
bool incognito()
|
||||||
{
|
{
|
||||||
|
gfx_printf("%kChecking if backup exists...\n", COLOR_YELLOW);
|
||||||
|
if (!checkBackupExists())
|
||||||
|
{
|
||||||
|
gfx_printf("%kI'm sorry Dave, I'm afraid I can't do that...\n%kWill make a backup first...\n", COLOR_RED, COLOR_YELLOW);
|
||||||
|
if (!backupProdinfo())
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
gfx_printf("%kWriting junk serial...\n", COLOR_YELLOW);
|
gfx_printf("%kWriting junk serial...\n", COLOR_YELLOW);
|
||||||
|
if (!writeSerial())
|
||||||
writeSerial();
|
return false;
|
||||||
|
;
|
||||||
gfx_printf("%kErasing client cert...\n", COLOR_YELLOW);
|
gfx_printf("%kErasing client cert...\n", COLOR_YELLOW);
|
||||||
erase(0x0AE0, 0x800); // client cert
|
if (!erase(0x0AE0, 0x800)) // client cert
|
||||||
|
return false;
|
||||||
|
;
|
||||||
gfx_printf("%kErasing private key...\n", COLOR_YELLOW);
|
gfx_printf("%kErasing private key...\n", COLOR_YELLOW);
|
||||||
erase(0x3AE0, 0x130); // private key
|
if (!erase(0x3AE0, 0x130)) // private key
|
||||||
|
return false;
|
||||||
|
;
|
||||||
gfx_printf("%kErasing deviceId 1/2...\n", COLOR_YELLOW);
|
gfx_printf("%kErasing deviceId 1/2...\n", COLOR_YELLOW);
|
||||||
erase(0x35E1, 0x006); // deviceId
|
if (!erase(0x35E1, 0x006)) // deviceId
|
||||||
|
return false;
|
||||||
|
;
|
||||||
gfx_printf("%kErasing deviceId 2/2...\n", COLOR_YELLOW);
|
gfx_printf("%kErasing deviceId 2/2...\n", COLOR_YELLOW);
|
||||||
erase(0x36E1, 0x006); // deviceId
|
if (!erase(0x36E1, 0x006)) // deviceId
|
||||||
|
return false;
|
||||||
|
;
|
||||||
gfx_printf("%kErasing device cert 1/2...\n", COLOR_YELLOW);
|
gfx_printf("%kErasing device cert 1/2...\n", COLOR_YELLOW);
|
||||||
erase(0x02B0, 0x180); // device cert
|
if (!erase(0x02B0, 0x180)) // device cert
|
||||||
|
return false;
|
||||||
|
;
|
||||||
gfx_printf("%kErasing device cert 2/2...\n", COLOR_YELLOW);
|
gfx_printf("%kErasing device cert 2/2...\n", COLOR_YELLOW);
|
||||||
erase(0x3D70, 0x240); // device cert
|
if (!erase(0x3D70, 0x240)) // device cert
|
||||||
|
return false;
|
||||||
|
;
|
||||||
gfx_printf("%kErasing device key...\n", COLOR_YELLOW);
|
gfx_printf("%kErasing device key...\n", COLOR_YELLOW);
|
||||||
|
if (!erase(0x3FC0, 0x240)) // device key
|
||||||
erase(0x3FC0, 0x240); // device key
|
return false;
|
||||||
|
;
|
||||||
gfx_printf("%kWriting client cert hash...\n", COLOR_YELLOW);
|
gfx_printf("%kWriting client cert hash...\n", COLOR_YELLOW);
|
||||||
|
if (!writeClientCertHash())
|
||||||
writeClientCertHash();
|
return false;
|
||||||
|
;
|
||||||
gfx_printf("%kWriting CAL0 hash...\n", COLOR_YELLOW);
|
gfx_printf("%kWriting CAL0 hash...\n", COLOR_YELLOW);
|
||||||
|
if (!writeCal0Hash())
|
||||||
writeCal0Hash();
|
return false;
|
||||||
|
;
|
||||||
|
|
||||||
gfx_printf("\n%kIncognito done!\n\n", COLOR_GREEN);
|
gfx_printf("\n%kIncognito done!\n\n", COLOR_GREEN);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 divideCeil(u32 x, u32 y)
|
u32 divideCeil(u32 x, u32 y)
|
||||||
|
@ -358,7 +372,7 @@ void cleanUp()
|
||||||
|
|
||||||
h_cfg.emummc_force_disable = emummc_load_cfg();
|
h_cfg.emummc_force_disable = emummc_load_cfg();
|
||||||
//nx_emmc_gpt_free(&gpt);
|
//nx_emmc_gpt_free(&gpt);
|
||||||
// emummc_storage_end(&storage);
|
//emummc_storage_end(&storage);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _generate_kek(u32 ks, const void *key_source, void *master_key, const void *kek_seed, const void *key_seed)
|
static void _generate_kek(u32 ks, const void *key_source, void *master_key, const void *kek_seed, const void *key_seed)
|
||||||
|
@ -381,14 +395,18 @@ static inline u32 _read_le_u32(const void *buffer, u32 offset)
|
||||||
(*(u8 *)(buffer + offset + 3) << 0x18);
|
(*(u8 *)(buffer + offset + 3) << 0x18);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool readData(u8 *buffer, u32 offset, u32 length, u8 enc)
|
bool readData(u8 *buffer, u32 offset, u32 length, u8 enc, void (*progress_callback)(u32, u32))
|
||||||
{
|
{
|
||||||
|
|
||||||
|
if (progress_callback != NULL)
|
||||||
|
{
|
||||||
|
(*progress_callback)(0, length);
|
||||||
|
}
|
||||||
bool result = false;
|
bool result = false;
|
||||||
u32 sector = (offset / NX_EMMC_BLOCKSIZE);
|
u32 sector = (offset / NX_EMMC_BLOCKSIZE);
|
||||||
u32 newOffset = (offset % NX_EMMC_BLOCKSIZE);
|
u32 newOffset = (offset % NX_EMMC_BLOCKSIZE);
|
||||||
|
|
||||||
u32 sectorCount = divideCeil(newOffset + length - 1, NX_EMMC_BLOCKSIZE) + 1;
|
u32 sectorCount = divideCeil(newOffset + length, NX_EMMC_BLOCKSIZE);
|
||||||
//u32 sectorCount = ((newOffset + length - 1) / (NX_EMMC_BLOCKSIZE)) + 1;
|
|
||||||
|
|
||||||
u8 *tmp = (u8 *)malloc(sectorCount * NX_EMMC_BLOCKSIZE);
|
u8 *tmp = (u8 *)malloc(sectorCount * NX_EMMC_BLOCKSIZE);
|
||||||
|
|
||||||
|
@ -399,31 +417,44 @@ bool readData(u8 *buffer, u32 offset, u32 length, u8 enc)
|
||||||
u32 sectorsToRead = SECTORS_IN_CLUSTER - clusterOffset;
|
u32 sectorsToRead = SECTORS_IN_CLUSTER - clusterOffset;
|
||||||
if (disk_read_prod(tmp + (sectorOffset * NX_EMMC_BLOCKSIZE), sector, sectorsToRead, enc) != RES_OK)
|
if (disk_read_prod(tmp + (sectorOffset * NX_EMMC_BLOCKSIZE), sector, sectorsToRead, enc) != RES_OK)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
sector += sectorsToRead;
|
sector += sectorsToRead;
|
||||||
sectorCount -= sectorsToRead;
|
sectorCount -= sectorsToRead;
|
||||||
clusterOffset = 0;
|
clusterOffset = 0;
|
||||||
sectorOffset += sectorsToRead;
|
sectorOffset += sectorsToRead;
|
||||||
|
if (progress_callback != NULL)
|
||||||
|
{
|
||||||
|
(*progress_callback)(sectorOffset * NX_EMMC_BLOCKSIZE, length);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (sectorCount == 0)
|
if (sectorCount == 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
if (disk_read_prod(tmp + (sectorOffset * NX_EMMC_BLOCKSIZE), sector, sectorCount, enc) != RES_OK)
|
if (disk_read_prod(tmp + (sectorOffset * NX_EMMC_BLOCKSIZE), sector, sectorCount, enc) != RES_OK)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
|
||||||
memcpy(buffer, tmp + newOffset, length);
|
memcpy(buffer, tmp + newOffset, length);
|
||||||
done:
|
done:
|
||||||
result = true;
|
result = true;
|
||||||
|
if (progress_callback != NULL)
|
||||||
|
{
|
||||||
|
(*progress_callback)(length, length);
|
||||||
|
}
|
||||||
out:
|
out:
|
||||||
free(tmp);
|
free(tmp);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool writeData(u8 *buffer, u32 offset, u32 length, u8 enc)
|
bool writeData(u8 *buffer, u32 offset, u32 length, u8 enc, void (*progress_callback)(u32, u32))
|
||||||
{
|
{
|
||||||
|
if (progress_callback != NULL)
|
||||||
|
{
|
||||||
|
(*progress_callback)(0, length);
|
||||||
|
}
|
||||||
bool result = false;
|
bool result = false;
|
||||||
|
|
||||||
|
u32 initialLength = length;
|
||||||
|
|
||||||
u8 *tmp_sec = (u8 *)malloc(NX_EMMC_BLOCKSIZE);
|
u8 *tmp_sec = (u8 *)malloc(NX_EMMC_BLOCKSIZE);
|
||||||
u8 *tmp = NULL;
|
u8 *tmp = NULL;
|
||||||
|
|
||||||
|
@ -433,49 +464,58 @@ bool writeData(u8 *buffer, u32 offset, u32 length, u8 enc)
|
||||||
// if there is a sector offset, read involved sector, write data to it with offset and write back whole sector to be sector aligned
|
// if there is a sector offset, read involved sector, write data to it with offset and write back whole sector to be sector aligned
|
||||||
if (newOffset > 0)
|
if (newOffset > 0)
|
||||||
{
|
{
|
||||||
|
u32 bytesToRead = NX_EMMC_BLOCKSIZE - newOffset;
|
||||||
u32 bytesToRead;
|
u32 bytesToWrite;
|
||||||
if (length > NX_EMMC_BLOCKSIZE)
|
if (length >= bytesToRead)
|
||||||
{
|
{
|
||||||
bytesToRead = NX_EMMC_BLOCKSIZE - newOffset;
|
bytesToWrite = bytesToRead;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
bytesToRead = length - newOffset;
|
bytesToWrite = length;
|
||||||
}
|
}
|
||||||
if (disk_read_prod(tmp_sec, sector, 1, enc) != RES_OK)
|
if (disk_read_prod(tmp_sec, sector, 1, enc) != RES_OK)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
memcpy(tmp_sec + newOffset, buffer, bytesToRead);
|
memcpy(tmp_sec + newOffset, buffer, bytesToWrite);
|
||||||
if (disk_write_prod(tmp_sec, sector, 1, enc) != RES_OK)
|
if (disk_write_prod(tmp_sec, sector, 1, enc) != RES_OK)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
sector++;
|
|
||||||
length -= bytesToRead;
|
|
||||||
newOffset = bytesToRead;
|
|
||||||
|
|
||||||
|
sector++;
|
||||||
|
length -= bytesToWrite;
|
||||||
|
newOffset = bytesToWrite;
|
||||||
|
|
||||||
|
if (progress_callback != NULL)
|
||||||
|
{
|
||||||
|
(*progress_callback)(initialLength - length, initialLength);
|
||||||
|
}
|
||||||
// are we done?
|
// are we done?
|
||||||
if (length == 0)
|
if (length == 0)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
// write whole sectors in chunks while being cluster aligned
|
// write whole sectors in chunks while being cluster aligned
|
||||||
u32 sectorCount = (length - 1 / NX_EMMC_BLOCKSIZE) + 1;
|
u32 sectorCount = ((length - 1) / NX_EMMC_BLOCKSIZE);
|
||||||
tmp = (u8 *)malloc(sectorCount * NX_EMMC_BLOCKSIZE);
|
tmp = (u8 *)malloc(sectorCount * NX_EMMC_BLOCKSIZE);
|
||||||
|
|
||||||
u32 clusterOffset = sector % SECTORS_IN_CLUSTER;
|
u32 clusterOffset = sector % SECTORS_IN_CLUSTER;
|
||||||
u32 sectorOffset = 0;
|
u32 sectorOffset = 0;
|
||||||
while (clusterOffset + sectorCount > SECTORS_IN_CLUSTER)
|
while (clusterOffset + sectorCount >= SECTORS_IN_CLUSTER)
|
||||||
{
|
{
|
||||||
u32 sectorsToRead = SECTORS_IN_CLUSTER - clusterOffset;
|
u32 sectorsToRead = SECTORS_IN_CLUSTER - clusterOffset;
|
||||||
if (disk_write_prod(buffer + newOffset + (sectorOffset * NX_EMMC_BLOCKSIZE), sector, sectorsToRead, enc) != RES_OK)
|
if (disk_write_prod(buffer + newOffset + (sectorOffset * NX_EMMC_BLOCKSIZE), sector, sectorsToRead, enc) != RES_OK)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
sector += sectorsToRead;
|
sector += sectorsToRead;
|
||||||
sectorOffset += sectorsToRead;
|
sectorOffset += sectorsToRead;
|
||||||
sectorCount -= sectorsToRead;
|
sectorCount -= sectorsToRead;
|
||||||
clusterOffset = 0;
|
clusterOffset = 0;
|
||||||
length -= sectorsToRead * NX_EMMC_BLOCKSIZE;
|
length -= sectorsToRead * NX_EMMC_BLOCKSIZE;
|
||||||
|
|
||||||
|
if (progress_callback != NULL)
|
||||||
|
{
|
||||||
|
(*progress_callback)(initialLength - length, initialLength);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// write remaining sectors
|
// write remaining sectors
|
||||||
|
@ -483,98 +523,100 @@ bool writeData(u8 *buffer, u32 offset, u32 length, u8 enc)
|
||||||
{
|
{
|
||||||
if (disk_write_prod(buffer + newOffset + (sectorOffset * NX_EMMC_BLOCKSIZE), sector, sectorCount, enc) != RES_OK)
|
if (disk_write_prod(buffer + newOffset + (sectorOffset * NX_EMMC_BLOCKSIZE), sector, sectorCount, enc) != RES_OK)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
length -= sectorCount * NX_EMMC_BLOCKSIZE;
|
length -= sectorCount * NX_EMMC_BLOCKSIZE;
|
||||||
sector += sectorCount;
|
sector += sectorCount;
|
||||||
sectorOffset += sectorCount;
|
sectorOffset += sectorCount;
|
||||||
|
|
||||||
|
if (progress_callback != NULL)
|
||||||
|
{
|
||||||
|
(*progress_callback)(initialLength - length, initialLength);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// if there is data remaining that is smaller than a sector, read that sector, write remaining data to it and write back whole sector
|
// if there is data remaining that is smaller than a sector, read that sector, write remaining data to it and write back whole sector
|
||||||
if (length == 0)
|
if (length == 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (length >= NX_EMMC_BLOCKSIZE)
|
|
||||||
|
if (length > NX_EMMC_BLOCKSIZE)
|
||||||
{
|
{
|
||||||
gfx_printf("\n%kERROR, ERROR!! remaining length: %d\n", COLOR_RED, length);
|
gfx_printf("%kERROR, ERRO! Length is %d!\n", COLOR_RED, length);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (disk_read_prod(tmp_sec, sector, 1, enc) != RES_OK)
|
if (disk_read_prod(tmp_sec, sector, 1, enc) != RES_OK)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
memcpy(tmp, buffer + newOffset + (sectorOffset * NX_EMMC_BLOCKSIZE), length);
|
memcpy(tmp_sec, buffer + newOffset + (sectorOffset * NX_EMMC_BLOCKSIZE), length);
|
||||||
if (disk_write_prod(tmp_sec, sector, 1, enc) != RES_OK)
|
if (disk_write_prod(tmp_sec, sector, 1, enc) != RES_OK)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
done:
|
done:
|
||||||
result = true;
|
result = true;
|
||||||
|
if (progress_callback != NULL)
|
||||||
|
{
|
||||||
|
(*progress_callback)(initialLength, initialLength);
|
||||||
|
}
|
||||||
out:
|
out:
|
||||||
free(tmp_sec);
|
free(tmp_sec);
|
||||||
free(tmp);
|
free(tmp);
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
// u32 sector = (offset / NX_EMMC_BLOCKSIZE);
|
|
||||||
// u32 newOffset = (offset % NX_EMMC_BLOCKSIZE);
|
|
||||||
|
|
||||||
// u8 sectorCount = ((newOffset + length - 1) / (NX_EMMC_BLOCKSIZE)) + 1;
|
|
||||||
|
|
||||||
// u8 *tmp = (u8 *)malloc(sectorCount * NX_EMMC_BLOCKSIZE);
|
|
||||||
|
|
||||||
// disk_read_prod(tmp, sector, sectorCount, 1);
|
|
||||||
|
|
||||||
// memcpy(tmp + newOffset, buffer, length);
|
|
||||||
|
|
||||||
// disk_write_prod(tmp, sector, sectorCount, enc);
|
|
||||||
|
|
||||||
// free(tmp);
|
|
||||||
|
|
||||||
// return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool writeHash(u32 hashOffset, u32 offset, u32 sz)
|
bool writeHash(u32 hashOffset, u32 offset, u32 sz)
|
||||||
{
|
{
|
||||||
|
bool result = false;
|
||||||
u8 *buffer = (u8 *)malloc(sz);
|
u8 *buffer = (u8 *)malloc(sz);
|
||||||
readData(buffer, offset, sz, ENCRYPTED);
|
if (!readData(buffer, offset, sz, ENCRYPTED, NULL))
|
||||||
|
{
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
u8 hash[0x20];
|
u8 hash[0x20];
|
||||||
se_calc_sha256(hash, buffer, sz);
|
se_calc_sha256(hash, buffer, sz);
|
||||||
|
|
||||||
writeData(hash, hashOffset, 0x20, ENCRYPTED);
|
if (!writeData(hash, hashOffset, 0x20, ENCRYPTED, NULL))
|
||||||
|
{
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
result = true;
|
||||||
|
out:
|
||||||
free(buffer);
|
free(buffer);
|
||||||
return true;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void test(){
|
void test()
|
||||||
u32 size = 262144;
|
{
|
||||||
gfx_printf("%kTest reading %s bytes\n", COLOR_ORANGE, size);
|
// u32 size = 262144;
|
||||||
u8 *buffer = (u8 *)malloc(NX_EMMC_BLOCKSIZE);
|
// gfx_printf("%kTest reading %d bytes\n", COLOR_ORANGE, size);
|
||||||
u8* bigBuffer = (u8 *)malloc(size);
|
// u8 *buffer = (u8 *)malloc(NX_EMMC_BLOCKSIZE);
|
||||||
u32 offset = 0;
|
// u8* bigBuffer = (u8 *)malloc(size);
|
||||||
readData(bigBuffer, 0, size, ENCRYPTED);
|
// u32 offset = 0;
|
||||||
while(size > NX_EMMC_BLOCKSIZE){
|
// readData(bigBuffer, 0, size, ENCRYPTED);
|
||||||
readData(buffer, offset, NX_EMMC_BLOCKSIZE, ENCRYPTED);
|
// while(size > NX_EMMC_BLOCKSIZE){
|
||||||
if(memcmp(buffer, bigBuffer + offset, NX_EMMC_BLOCKSIZE) != 0){
|
// readData(buffer, offset, NX_EMMC_BLOCKSIZE, ENCRYPTED);
|
||||||
gfx_printf("arry mismatch on offset %d", offset);
|
// if(memcmp(buffer, bigBuffer + offset, NX_EMMC_BLOCKSIZE) != 0){
|
||||||
|
// gfx_printf("arry mismatch on offset %d", offset);
|
||||||
|
|
||||||
}
|
// }
|
||||||
size -= NX_EMMC_BLOCKSIZE;
|
// size -= NX_EMMC_BLOCKSIZE;
|
||||||
offset += NX_EMMC_BLOCKSIZE;
|
// offset += NX_EMMC_BLOCKSIZE;
|
||||||
}
|
// }
|
||||||
free(buffer);
|
// free(buffer);
|
||||||
free(bigBuffer);
|
// free(bigBuffer);
|
||||||
gfx_printf("%Reading Done!\n", COLOR_ORANGE, size);
|
// gfx_printf("%Reading Done!\n", COLOR_ORANGE, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool verifyHash(u32 hashOffset, u32 offset, u32 sz)
|
bool verifyHash(u32 hashOffset, u32 offset, u32 sz)
|
||||||
{
|
{
|
||||||
bool result = false;
|
bool result = false;
|
||||||
u8 *buffer = (u8 *)malloc(sz);
|
u8 *buffer = (u8 *)malloc(sz);
|
||||||
readData(buffer, offset, sz, ENCRYPTED);
|
readData(buffer, offset, sz, ENCRYPTED, NULL);
|
||||||
u8 hash1[0x20];
|
u8 hash1[0x20];
|
||||||
se_calc_sha256(hash1, buffer, sz);
|
se_calc_sha256(hash1, buffer, sz);
|
||||||
|
|
||||||
u8 hash2[0x20];
|
u8 hash2[0x20];
|
||||||
|
|
||||||
readData(hash2, hashOffset, 0x20, ENCRYPTED);
|
readData(hash2, hashOffset, 0x20, ENCRYPTED, NULL);
|
||||||
|
|
||||||
if (memcmp(hash1, hash2, 0x20))
|
if (memcmp(hash1, hash2, 0x20))
|
||||||
{
|
{
|
||||||
|
@ -594,14 +636,14 @@ bool verifyHash(u32 hashOffset, u32 offset, u32 sz)
|
||||||
u32 certSize()
|
u32 certSize()
|
||||||
{
|
{
|
||||||
u32 buffer;
|
u32 buffer;
|
||||||
readData((u8 *)&buffer, 0x0AD0, sizeof(buffer), ENCRYPTED);
|
readData((u8 *)&buffer, 0x0AD0, sizeof(buffer), ENCRYPTED, NULL);
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 calibrationDataSize()
|
u32 calibrationDataSize()
|
||||||
{
|
{
|
||||||
u32 buffer;
|
u32 buffer;
|
||||||
readData((u8 *)&buffer, 0x08, sizeof(buffer), ENCRYPTED);
|
readData((u8 *)&buffer, 0x08, sizeof(buffer), ENCRYPTED, NULL);
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -634,7 +676,7 @@ bool verifyProdinfo()
|
||||||
if (verifyClientCertHash() && verifyCal0Hash())
|
if (verifyClientCertHash() && verifyCal0Hash())
|
||||||
{
|
{
|
||||||
char serial[15];
|
char serial[15];
|
||||||
readData((u8 *)serial, 0x250, 15, ENCRYPTED);
|
readData((u8 *)serial, 0x250, 15, ENCRYPTED, NULL);
|
||||||
gfx_printf("%kVerification successful!\n%kNew Serial:%s\n", COLOR_GREEN, COLOR_BLUE, serial);
|
gfx_printf("%kVerification successful!\n%kNew Serial:%s\n", COLOR_GREEN, COLOR_BLUE, serial);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -642,8 +684,14 @@ bool verifyProdinfo()
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_progress(size_t count, size_t max)
|
void print_progress(u32 count, u32 max)
|
||||||
{
|
{
|
||||||
|
u32 cur_x = gfx_con.x;
|
||||||
|
u32 cur_y = gfx_con.y;
|
||||||
|
|
||||||
|
const u8 width = 20;
|
||||||
|
count = (int)((count * 100 / (float)max) / (100 / width));
|
||||||
|
max = width;
|
||||||
const char prefix[] = "Progress: [";
|
const char prefix[] = "Progress: [";
|
||||||
const char suffix[] = "]";
|
const char suffix[] = "]";
|
||||||
const size_t prefix_length = sizeof(prefix) - 1;
|
const size_t prefix_length = sizeof(prefix) - 1;
|
||||||
|
@ -660,9 +708,12 @@ void print_progress(size_t count, size_t max)
|
||||||
strcpy(&buffer[prefix_length + i], suffix);
|
strcpy(&buffer[prefix_length + i], suffix);
|
||||||
gfx_printf("%k%s %d%%\n", COLOR_BLUE, buffer, (100 / max) * count);
|
gfx_printf("%k%s %d%%\n", COLOR_BLUE, buffer, (100 / max) * count);
|
||||||
free(buffer);
|
free(buffer);
|
||||||
|
gfx_con.x = cur_x;
|
||||||
|
gfx_con.y = cur_y;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool getLastBackup(){
|
bool getLastBackup()
|
||||||
|
{
|
||||||
DIR dir;
|
DIR dir;
|
||||||
//char* path = "sd:/incognito";
|
//char* path = "sd:/incognito";
|
||||||
char path[255];
|
char path[255];
|
||||||
|
@ -670,151 +721,146 @@ bool getLastBackup(){
|
||||||
FILINFO fno;
|
FILINFO fno;
|
||||||
FRESULT res;
|
FRESULT res;
|
||||||
|
|
||||||
res = f_opendir(&dir, path); /* Open the directory */
|
res = f_opendir(&dir, path); /* Open the directory */
|
||||||
if (res == FR_OK) {
|
if (res == FR_OK)
|
||||||
for (;;) {
|
{
|
||||||
res = f_readdir(&dir, &fno); /* Read a directory item */
|
for (;;)
|
||||||
if (res != FR_OK || fno.fname[0] == 0) break; /* Break on error or end of dir */
|
{
|
||||||
if ((fno.fattrib & AM_DIR) == 0) { /* It is not a directory */
|
res = f_readdir(&dir, &fno); /* Read a directory item */
|
||||||
gfx_printf("%s/%s\n", path, fno.fname);
|
if (res != FR_OK || fno.fname[0] == 0)
|
||||||
|
break; /* Break on error or end of dir */
|
||||||
|
if ((fno.fattrib & AM_DIR) == 0)
|
||||||
|
{ /* It is not a directory */
|
||||||
|
gfx_printf("%s/%s\n", path, fno.fname);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
f_closedir(&dir);
|
f_closedir(&dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool backupProdinfo()
|
bool checkBackupExists()
|
||||||
{
|
{
|
||||||
char *name;
|
char *name;
|
||||||
if (!emu_cfg.enabled || h_cfg.emummc_force_disable)
|
if (!emu_cfg.enabled || h_cfg.emummc_force_disable)
|
||||||
{
|
{
|
||||||
name = "sd:/prodinfo_sysnand.bin";
|
name = BACKUP_NAME_SYSNAND;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
name = BACKUP_NAME_EMUNAND;
|
||||||
|
}
|
||||||
|
return f_stat(name, NULL) == FR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
name = "sd:/prodinfo_emunand.bin";
|
bool backupProdinfo()
|
||||||
|
{
|
||||||
|
bool result = false;
|
||||||
|
char *name;
|
||||||
|
if (!emu_cfg.enabled || h_cfg.emummc_force_disable)
|
||||||
|
{
|
||||||
|
name = BACKUP_NAME_SYSNAND;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
name = BACKUP_NAME_EMUNAND;
|
||||||
}
|
}
|
||||||
|
|
||||||
gfx_printf("%kBacking up %s...\n", COLOR_YELLOW, name);
|
gfx_printf("%kBacking up %s...\n", COLOR_YELLOW, name);
|
||||||
|
if (checkBackupExists())
|
||||||
if (f_stat(name, NULL))
|
|
||||||
{
|
{
|
||||||
f_unlink(name);
|
gfx_printf("%kBackup already exists!\nWill rename old backup.\n", COLOR_YELLOW);
|
||||||
}
|
u32 filenameSuffix = 0;
|
||||||
FIL fp;
|
char newName[255];
|
||||||
f_open(&fp, name, FA_CREATE_ALWAYS | FA_WRITE);
|
do
|
||||||
u8 *bufferNX = (u8 *)malloc(NX_EMMC_BLOCKSIZE);
|
|
||||||
u32 size = PRODINFO_SIZE;
|
|
||||||
|
|
||||||
u8 percentDone = 0;
|
|
||||||
u32 offset = 0;
|
|
||||||
const u8 step = 5;
|
|
||||||
|
|
||||||
u32 iterations = size / NX_EMMC_BLOCKSIZE;
|
|
||||||
u32 printCount = iterations / (100 / step);
|
|
||||||
|
|
||||||
u32 x = gfx_con.x;
|
|
||||||
u32 y = gfx_con.y;
|
|
||||||
|
|
||||||
while (size > NX_EMMC_BLOCKSIZE)
|
|
||||||
{
|
|
||||||
readData(bufferNX, offset, NX_EMMC_BLOCKSIZE, ENCRYPTED);
|
|
||||||
f_write(&fp, bufferNX, NX_EMMC_BLOCKSIZE, NULL);
|
|
||||||
f_sync(&fp);
|
|
||||||
|
|
||||||
offset += NX_EMMC_BLOCKSIZE;
|
|
||||||
size -= NX_EMMC_BLOCKSIZE;
|
|
||||||
if (iterations % printCount == 0)
|
|
||||||
{
|
{
|
||||||
print_progress(percentDone / step, 100 / step);
|
sprintf(newName, "%s.%d", name, filenameSuffix);
|
||||||
gfx_con.x = x;
|
filenameSuffix++;
|
||||||
gfx_con.y = y;
|
} while (f_stat(newName, NULL) == FR_OK);
|
||||||
percentDone += step;
|
f_rename(name, newName);
|
||||||
}
|
gfx_printf("%kOld backup renamed to %s\n", COLOR_YELLOW, newName);
|
||||||
iterations--;
|
|
||||||
}
|
}
|
||||||
if (size > 0)
|
|
||||||
|
FIL fp;
|
||||||
|
if (f_open(&fp, name, FA_CREATE_ALWAYS | FA_WRITE) != FR_OK)
|
||||||
{
|
{
|
||||||
readData(bufferNX, offset, size, ENCRYPTED);
|
gfx_printf("\n%kCannot write to %s!\n", COLOR_RED, name);
|
||||||
f_write(&fp, bufferNX, size, NULL);
|
return false;
|
||||||
f_sync(&fp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
print_progress(100 / step, 100 / step);
|
u8 *bufferNX = (u8 *)malloc(PRODINFO_SIZE);
|
||||||
|
gfx_printf("%kReading from NAND...\n", COLOR_YELLOW);
|
||||||
|
if (!readData(bufferNX, 0, PRODINFO_SIZE, ENCRYPTED, print_progress))
|
||||||
|
{
|
||||||
|
gfx_printf("\n%kError reading from NAND!\n", COLOR_RED);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
gfx_printf("%k\nWriting to file...\n", COLOR_YELLOW);
|
||||||
|
u32 bytesWritten;
|
||||||
|
if (f_write(&fp, bufferNX, PRODINFO_SIZE, &bytesWritten) != FR_OK || bytesWritten != PRODINFO_SIZE)
|
||||||
|
{
|
||||||
|
gfx_printf("\n%kError writing to file!\nPlease try again. If this doesn't work, you don't have a working backup!\n", COLOR_RED);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
f_sync(&fp);
|
||||||
|
|
||||||
|
result = true;
|
||||||
|
gfx_printf("\n%kBackup to %s done!\n\n", COLOR_GREEN, name);
|
||||||
|
|
||||||
|
out:
|
||||||
f_close(&fp);
|
f_close(&fp);
|
||||||
free(bufferNX);
|
free(bufferNX);
|
||||||
gfx_printf("%k\nBackup %s done!\n\n", COLOR_GREEN, name);
|
|
||||||
|
|
||||||
return true;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool restoreProdinfo()
|
bool restoreProdinfo()
|
||||||
{
|
{
|
||||||
|
bool result = false;
|
||||||
sd_mount();
|
sd_mount();
|
||||||
|
|
||||||
char *name;
|
char *name;
|
||||||
if (!emu_cfg.enabled || h_cfg.emummc_force_disable)
|
if (!emu_cfg.enabled || h_cfg.emummc_force_disable)
|
||||||
{
|
{
|
||||||
name = "sd:/prodinfo_sysnand.bin";
|
name = BACKUP_NAME_SYSNAND;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
name = BACKUP_NAME_EMUNAND;
|
||||||
name = "sd:/prodinfo_emunand.bin";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
gfx_printf("%kRestoring %s...\n", COLOR_YELLOW, name);
|
gfx_printf("%kRestoring from %s...\n", COLOR_YELLOW, name);
|
||||||
|
|
||||||
FIL fp;
|
FIL fp;
|
||||||
if (f_open(&fp, name, FA_READ) != FR_OK)
|
if (f_open(&fp, name, FA_READ) != FR_OK)
|
||||||
{
|
{
|
||||||
gfx_printf("\nCannot open%s!\n", name);
|
gfx_printf("\n%kCannot open %s!\n", COLOR_RED, name);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
u8 bufferNX[NX_EMMC_BLOCKSIZE];
|
|
||||||
|
|
||||||
u32 size = PRODINFO_SIZE;
|
u8 *bufferNX = (u8 *)malloc(PRODINFO_SIZE);
|
||||||
|
u32 bytesRead;
|
||||||
u8 percentDone = 0;
|
gfx_printf("%kReading from file...\n", COLOR_YELLOW);
|
||||||
u32 offset = 0;
|
if (f_read(&fp, bufferNX, PRODINFO_SIZE, &bytesRead) != FR_OK || bytesRead != PRODINFO_SIZE)
|
||||||
const u8 step = 5;
|
|
||||||
|
|
||||||
u32 iterations = size / NX_EMMC_BLOCKSIZE;
|
|
||||||
u32 printCount = iterations / (100 / step);
|
|
||||||
|
|
||||||
u32 x = gfx_con.x;
|
|
||||||
u32 y = gfx_con.y;
|
|
||||||
|
|
||||||
while (size > NX_EMMC_BLOCKSIZE)
|
|
||||||
{
|
{
|
||||||
f_read(&fp, bufferNX, NX_EMMC_BLOCKSIZE, NULL);
|
gfx_printf("\n%kError reading from file!\n", COLOR_RED);
|
||||||
writeData(bufferNX, offset, NX_EMMC_BLOCKSIZE, ENCRYPTED);
|
goto out;
|
||||||
offset += NX_EMMC_BLOCKSIZE;
|
|
||||||
size -= NX_EMMC_BLOCKSIZE;
|
|
||||||
if (iterations % printCount == 0)
|
|
||||||
{
|
|
||||||
print_progress(percentDone / step, 100 / step);
|
|
||||||
gfx_con.x = x;
|
|
||||||
gfx_con.y = y;
|
|
||||||
percentDone += step;
|
|
||||||
}
|
|
||||||
iterations--;
|
|
||||||
}
|
}
|
||||||
if (size > 0)
|
gfx_printf("%kWriting to NAND...\n", COLOR_YELLOW);
|
||||||
|
if (!writeData(bufferNX, 0, PRODINFO_SIZE, ENCRYPTED, print_progress))
|
||||||
{
|
{
|
||||||
f_read(&fp, bufferNX, size, NULL);
|
gfx_printf("\n%kError writing to NAND!\nThis is bad. Try again, because your switch probably won't boot.\n"
|
||||||
writeData(bufferNX, offset, size, ENCRYPTED);
|
"If you see this error again, you should restore via NAND backup in hekate.\n",
|
||||||
|
COLOR_RED);
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
print_progress(100 / step, 100 / step);
|
|
||||||
|
|
||||||
|
result = true;
|
||||||
|
gfx_printf("\n%kRestore from %s done!\n\n", COLOR_GREEN, name);
|
||||||
|
out:
|
||||||
f_close(&fp);
|
f_close(&fp);
|
||||||
|
free(bufferNX);
|
||||||
|
|
||||||
gfx_printf("%kRestore %s done!\n\n", COLOR_GREEN, name);
|
return result;
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,14 +24,16 @@ void test();
|
||||||
//testing
|
//testing
|
||||||
|
|
||||||
bool dump_keys();
|
bool dump_keys();
|
||||||
void incognito();
|
bool incognito();
|
||||||
void cleanUp();
|
void cleanUp();
|
||||||
bool readData(u8 *buffer, u32 offset, u32 length, u8 enc);
|
bool readData(u8 *buffer, u32 offset, u32 length, u8 enc, void (*progress_callback)(u32, u32));
|
||||||
bool writeData(u8 *buffer, u32 offset, u32 length, u8 enc);
|
bool writeData(u8 *buffer, u32 offset, u32 length, u8 enc, void (*progress_callback)(u32, u32));
|
||||||
bool writeClientCertHash();
|
bool writeClientCertHash();
|
||||||
bool writeCal0Hash();
|
bool writeCal0Hash();
|
||||||
bool verifyProdinfo();
|
bool verifyProdinfo();
|
||||||
bool backupProdinfo();
|
bool backupProdinfo();
|
||||||
bool restoreProdinfo();
|
bool restoreProdinfo();
|
||||||
|
bool checkBackupExists();
|
||||||
|
void print_progress(u32 count, u32 max);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -155,15 +155,18 @@ void incognito_sysnand()
|
||||||
h_cfg.emummc_force_disable = true;
|
h_cfg.emummc_force_disable = true;
|
||||||
b_cfg.extra_cfg &= ~EXTRA_CFG_DUMP_EMUMMC;
|
b_cfg.extra_cfg &= ~EXTRA_CFG_DUMP_EMUMMC;
|
||||||
if (!dump_keys())
|
if (!dump_keys())
|
||||||
|
goto out;
|
||||||
|
if (!incognito())
|
||||||
{
|
{
|
||||||
cleanUp();
|
gfx_printf("%kError applying Incognito!\nWill restore backup!\n", COLOR_RED);
|
||||||
return;
|
backupProdinfo();
|
||||||
}
|
}
|
||||||
//incognito();
|
if (!verifyProdinfo())
|
||||||
test();
|
{
|
||||||
verifyProdinfo();
|
gfx_printf("%kThis should not happen!\nTry restoring or restore via NAND backup from hekate!\n", COLOR_RED);
|
||||||
|
}
|
||||||
|
out:
|
||||||
cleanUp();
|
cleanUp();
|
||||||
|
|
||||||
gfx_printf("\n%k---------------\n%kPress any key to return to the main menu.", COLOR_YELLOW, COLOR_ORANGE);
|
gfx_printf("\n%k---------------\n%kPress any key to return to the main menu.", COLOR_YELLOW, COLOR_ORANGE);
|
||||||
btn_wait();
|
btn_wait();
|
||||||
}
|
}
|
||||||
|
@ -175,13 +178,17 @@ void incognito_emunand()
|
||||||
emu_cfg.enabled = 1;
|
emu_cfg.enabled = 1;
|
||||||
b_cfg.extra_cfg |= EXTRA_CFG_DUMP_EMUMMC;
|
b_cfg.extra_cfg |= EXTRA_CFG_DUMP_EMUMMC;
|
||||||
if (!dump_keys())
|
if (!dump_keys())
|
||||||
|
goto out;
|
||||||
|
if (!incognito())
|
||||||
{
|
{
|
||||||
cleanUp();
|
gfx_printf("%kError applying Incognito!\nWill restore backup!\n", COLOR_RED);
|
||||||
return;
|
backupProdinfo();
|
||||||
}
|
}
|
||||||
test();
|
if (!verifyProdinfo())
|
||||||
//incognito();
|
{
|
||||||
verifyProdinfo();
|
gfx_printf("%kThis should not happen!\nTry restoring or restore via NAND backup from hekate!\n", COLOR_RED);
|
||||||
|
}
|
||||||
|
out:
|
||||||
cleanUp();
|
cleanUp();
|
||||||
gfx_printf("\n%k---------------\n%kPress any key to return to the main menu.", COLOR_YELLOW, COLOR_ORANGE);
|
gfx_printf("\n%k---------------\n%kPress any key to return to the main menu.", COLOR_YELLOW, COLOR_ORANGE);
|
||||||
btn_wait();
|
btn_wait();
|
||||||
|
@ -192,11 +199,10 @@ void backup_sysnand()
|
||||||
h_cfg.emummc_force_disable = true;
|
h_cfg.emummc_force_disable = true;
|
||||||
b_cfg.extra_cfg &= ~EXTRA_CFG_DUMP_EMUMMC;
|
b_cfg.extra_cfg &= ~EXTRA_CFG_DUMP_EMUMMC;
|
||||||
if (!dump_keys())
|
if (!dump_keys())
|
||||||
{
|
goto out;
|
||||||
cleanUp();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
backupProdinfo();
|
backupProdinfo();
|
||||||
|
out:
|
||||||
cleanUp();
|
cleanUp();
|
||||||
gfx_printf("\n%k---------------\n%kPress any key to return to the main menu.", COLOR_YELLOW, COLOR_ORANGE);
|
gfx_printf("\n%k---------------\n%kPress any key to return to the main menu.", COLOR_YELLOW, COLOR_ORANGE);
|
||||||
btn_wait();
|
btn_wait();
|
||||||
|
@ -209,12 +215,10 @@ void backup_emunand()
|
||||||
emu_cfg.enabled = 1;
|
emu_cfg.enabled = 1;
|
||||||
b_cfg.extra_cfg |= EXTRA_CFG_DUMP_EMUMMC;
|
b_cfg.extra_cfg |= EXTRA_CFG_DUMP_EMUMMC;
|
||||||
if (!dump_keys())
|
if (!dump_keys())
|
||||||
{
|
goto out;
|
||||||
cleanUp();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
backupProdinfo();
|
backupProdinfo();
|
||||||
|
out:
|
||||||
cleanUp();
|
cleanUp();
|
||||||
gfx_printf("\n%k---------------\n%kPress any key to return to the main menu.", COLOR_YELLOW, COLOR_ORANGE);
|
gfx_printf("\n%k---------------\n%kPress any key to return to the main menu.", COLOR_YELLOW, COLOR_ORANGE);
|
||||||
btn_wait();
|
btn_wait();
|
||||||
|
@ -225,13 +229,14 @@ void restore_sysnand()
|
||||||
h_cfg.emummc_force_disable = true;
|
h_cfg.emummc_force_disable = true;
|
||||||
b_cfg.extra_cfg &= ~EXTRA_CFG_DUMP_EMUMMC;
|
b_cfg.extra_cfg &= ~EXTRA_CFG_DUMP_EMUMMC;
|
||||||
if (!dump_keys())
|
if (!dump_keys())
|
||||||
{
|
goto out;
|
||||||
cleanUp();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
restoreProdinfo();
|
restoreProdinfo();
|
||||||
verifyProdinfo();
|
if (!verifyProdinfo())
|
||||||
|
{
|
||||||
|
gfx_printf("%kThis should not happen!\nTry restoring or restore via NAND backup from hekate!\n", COLOR_RED);
|
||||||
|
}
|
||||||
|
out:
|
||||||
cleanUp();
|
cleanUp();
|
||||||
gfx_printf("\n%k---------------\n%kPress any key to return to the main menu.", COLOR_YELLOW, COLOR_ORANGE);
|
gfx_printf("\n%k---------------\n%kPress any key to return to the main menu.", COLOR_YELLOW, COLOR_ORANGE);
|
||||||
btn_wait();
|
btn_wait();
|
||||||
|
@ -243,19 +248,20 @@ void restore_emunand()
|
||||||
return;
|
return;
|
||||||
emu_cfg.enabled = 1;
|
emu_cfg.enabled = 1;
|
||||||
b_cfg.extra_cfg |= EXTRA_CFG_DUMP_EMUMMC;
|
b_cfg.extra_cfg |= EXTRA_CFG_DUMP_EMUMMC;
|
||||||
|
|
||||||
if (!dump_keys())
|
if (!dump_keys())
|
||||||
{
|
goto out;
|
||||||
cleanUp();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
restoreProdinfo();
|
restoreProdinfo();
|
||||||
verifyProdinfo();
|
if (!verifyProdinfo())
|
||||||
|
{
|
||||||
|
gfx_printf("%kThis should not happen!\nTry restoring or restore via NAND backup from hekate!\n", COLOR_RED);
|
||||||
|
}
|
||||||
|
out:
|
||||||
cleanUp();
|
cleanUp();
|
||||||
gfx_printf("\n%k---------------\n%kPress any key to return to the main menu.", COLOR_YELLOW, COLOR_ORANGE);
|
gfx_printf("\n%k---------------\n%kPress any key to return to the main menu.", COLOR_YELLOW, COLOR_ORANGE);
|
||||||
btn_wait();
|
btn_wait();
|
||||||
}
|
}
|
||||||
|
|
||||||
ment_t ment_top[] = {
|
ment_t ment_top[] = {
|
||||||
MDEF_HANDLER("Backup (SysNAND)", backup_sysnand, COLOR_ORANGE),
|
MDEF_HANDLER("Backup (SysNAND)", backup_sysnand, COLOR_ORANGE),
|
||||||
MDEF_HANDLER("Backup (emuMMC)", backup_emunand, COLOR_ORANGE),
|
MDEF_HANDLER("Backup (emuMMC)", backup_emunand, COLOR_ORANGE),
|
||||||
|
|
Loading…
Reference in a new issue