mirror of
https://github.com/Scandal-UK/Incognito_RCM.git
synced 2024-11-22 20:06:42 +00:00
decrypting and reading ready, encrypting and writing todo
This commit is contained in:
parent
4ce94bc2b1
commit
76bfd54fd2
4 changed files with 250 additions and 63 deletions
|
@ -23,7 +23,7 @@
|
||||||
#include "../hos/pkg1.h"
|
#include "../hos/pkg1.h"
|
||||||
#include "../hos/pkg2.h"
|
#include "../hos/pkg2.h"
|
||||||
#include "../hos/sept.h"
|
#include "../hos/sept.h"
|
||||||
//#include "../libs/fatfs/ff.h"
|
#include "../libs/fatfs/ff.h"
|
||||||
#include "../mem/heap.h"
|
#include "../mem/heap.h"
|
||||||
#include "../mem/mc.h"
|
#include "../mem/mc.h"
|
||||||
#include "../mem/sdram.h"
|
#include "../mem/sdram.h"
|
||||||
|
@ -158,6 +158,7 @@ void dump_keys() {
|
||||||
MAX_KEY = pkg1_id->kb + 1;
|
MAX_KEY = pkg1_id->kb + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (pkg1_id->kb >= KB_FIRMWARE_VERSION_700) {
|
if (pkg1_id->kb >= KB_FIRMWARE_VERSION_700) {
|
||||||
// sd_mount();
|
// sd_mount();
|
||||||
// if (!f_stat("sd:/sept/payload.bak", NULL)) {
|
// if (!f_stat("sd:/sept/payload.bak", NULL)) {
|
||||||
|
@ -374,12 +375,22 @@ void dump_keys() {
|
||||||
se_aes_key_set(8, bis_key[0] + 0x00, 0x10);
|
se_aes_key_set(8, bis_key[0] + 0x00, 0x10);
|
||||||
se_aes_key_set(9, bis_key[0] + 0x10, 0x10);
|
se_aes_key_set(9, bis_key[0] + 0x10, 0x10);
|
||||||
|
|
||||||
u32 length = 0x18;
|
//u32 length = 0x18;
|
||||||
u8* buffer = (u8 *)malloc(length);
|
u8 buffer[0x18];// = (u8 *)malloc(length);
|
||||||
readData(buffer, 0x250, length);
|
readData(buffer, 0x250, sizeof(buffer));
|
||||||
|
|
||||||
gfx_hexdump(0, buffer, length);
|
|
||||||
free(buffer);
|
// const char junkSerial[] = "XAJ40030770863";
|
||||||
|
// gfx_hexdump(0, (u8 *)junkSerial, strlen(junkSerial));
|
||||||
|
// writeData((u8 *)junkSerial, 0x250, strlen(junkSerial));
|
||||||
|
|
||||||
|
gfx_hexdump(0, buffer, sizeof(buffer));
|
||||||
|
//free(buffer);
|
||||||
|
|
||||||
|
verify();
|
||||||
|
|
||||||
|
writeClientCertHash();
|
||||||
|
writeCal0Hash();
|
||||||
|
|
||||||
verify();
|
verify();
|
||||||
// free(tmp_copy);
|
// free(tmp_copy);
|
||||||
|
@ -388,6 +399,7 @@ void dump_keys() {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// pkg2_done:
|
// pkg2_done:
|
||||||
// // free(pkg2);
|
// // free(pkg2);
|
||||||
// // free(ki);
|
// // free(ki);
|
||||||
|
@ -605,7 +617,7 @@ bool readData(u8 *buffer, u32 offset, u32 length)
|
||||||
u32 sector = (offset / NX_EMMC_BLOCKSIZE);
|
u32 sector = (offset / NX_EMMC_BLOCKSIZE);
|
||||||
u32 newOffset = (offset % NX_EMMC_BLOCKSIZE);
|
u32 newOffset = (offset % NX_EMMC_BLOCKSIZE);
|
||||||
|
|
||||||
u8 sectorCount = ((newOffset + length) / NX_EMMC_BLOCKSIZE) + 1;
|
u8 sectorCount = ((newOffset + length - 1) / (NX_EMMC_BLOCKSIZE)) + 1;
|
||||||
|
|
||||||
// if(length + newOffset > NX_EMMC_BLOCKSIZE * 2){
|
// if(length + newOffset > NX_EMMC_BLOCKSIZE * 2){
|
||||||
// EPRINTF("TOO BIG!!");
|
// EPRINTF("TOO BIG!!");
|
||||||
|
@ -614,7 +626,7 @@ bool readData(u8 *buffer, u32 offset, u32 length)
|
||||||
//bool needMultipleSectors = newOffset + length > NX_EMMC_BLOCKSIZE;
|
//bool needMultipleSectors = newOffset + length > NX_EMMC_BLOCKSIZE;
|
||||||
|
|
||||||
u8 *tmp = (u8 *)malloc(sectorCount * NX_EMMC_BLOCKSIZE);
|
u8 *tmp = (u8 *)malloc(sectorCount * NX_EMMC_BLOCKSIZE);
|
||||||
disk_read_mod(tmp, sector, sectorCount, &storage, prodinfo_part);
|
disk_read_prod(tmp, sector, sectorCount);
|
||||||
|
|
||||||
// if (!needMultipleSectors)
|
// if (!needMultipleSectors)
|
||||||
// {
|
// {
|
||||||
|
@ -634,9 +646,46 @@ bool readData(u8 *buffer, u32 offset, u32 length)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool verifyHash(u32 hashOffset, u32 offset, u32 sz)
|
bool writeData(u8 *buffer, u32 offset, u32 length)
|
||||||
|
{
|
||||||
|
|
||||||
|
u32 sector = (offset / NX_EMMC_BLOCKSIZE);
|
||||||
|
u32 newOffset = (offset % NX_EMMC_BLOCKSIZE);
|
||||||
|
|
||||||
|
u8 sectorCount = ((newOffset + length - 1) / (NX_EMMC_BLOCKSIZE)) + 1;
|
||||||
|
|
||||||
|
// if(length + newOffset > NX_EMMC_BLOCKSIZE * 2){
|
||||||
|
// EPRINTF("TOO BIG!!");
|
||||||
|
// }
|
||||||
|
|
||||||
|
//bool needMultipleSectors = newOffset + length > NX_EMMC_BLOCKSIZE;
|
||||||
|
|
||||||
|
u8 *tmp = (u8 *)malloc(sectorCount * NX_EMMC_BLOCKSIZE);
|
||||||
|
disk_read_prod(tmp, sector, sectorCount);
|
||||||
|
|
||||||
|
// if (!needMultipleSectors)
|
||||||
|
// {
|
||||||
|
// gfx_hexdump(0, tmp + newOffset, length);
|
||||||
|
memcpy(tmp + newOffset, buffer, length);
|
||||||
|
|
||||||
|
disk_write_prod(tmp, sector, sectorCount);
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// u32 newLength = (newOffset + length) - NX_EMMC_BLOCKSIZE;
|
||||||
|
// memcpy(buffer, tmp + newOffset, newLength);
|
||||||
|
// disk_read_mod(tmp, sector + 1, 1, &storage, prodinfo_part);
|
||||||
|
// memcpy(buffer + newLength, tmp, length - newLength);
|
||||||
|
// }
|
||||||
|
|
||||||
|
free(tmp);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool writeHash(u32 hashOffset, u32 offset, u32 sz)
|
||||||
{
|
{
|
||||||
bool result = false;
|
|
||||||
u8 *buffer = (u8 *)malloc(NX_EMMC_BLOCKSIZE);
|
u8 *buffer = (u8 *)malloc(NX_EMMC_BLOCKSIZE);
|
||||||
|
|
||||||
SHA256_CTX ctx;
|
SHA256_CTX ctx;
|
||||||
|
@ -646,19 +695,60 @@ bool verifyHash(u32 hashOffset, u32 offset, u32 sz)
|
||||||
{
|
{
|
||||||
|
|
||||||
readData(buffer, offset, NX_EMMC_BLOCKSIZE);
|
readData(buffer, offset, NX_EMMC_BLOCKSIZE);
|
||||||
|
// gfx_hexdump(0, buffer + NX_EMMC_BLOCKSIZE - 8, 8);
|
||||||
sha256_update(&ctx, buffer, NX_EMMC_BLOCKSIZE);
|
sha256_update(&ctx, buffer, NX_EMMC_BLOCKSIZE);
|
||||||
|
|
||||||
sz -= NX_EMMC_BLOCKSIZE;
|
sz -= NX_EMMC_BLOCKSIZE;
|
||||||
offset += NX_EMMC_BLOCKSIZE;
|
offset += NX_EMMC_BLOCKSIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
readData(buffer, offset, sz);
|
if(sz > 0){
|
||||||
|
|
||||||
|
|
||||||
|
readData(buffer, offset, sz);
|
||||||
sha256_update(&ctx, buffer, sz);
|
sha256_update(&ctx, buffer, sz);
|
||||||
u8 *hash1 = (u8 *)malloc(0x20);
|
}
|
||||||
|
u8 hash[0x20];
|
||||||
|
sha256_final(&ctx, hash);
|
||||||
|
|
||||||
|
writeData(hash, hashOffset, 0x20);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
free(buffer);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool verifyHash(u32 hashOffset, u32 offset, u32 sz)
|
||||||
|
{
|
||||||
|
bool result = false;
|
||||||
|
u8 *buffer = (u8 *)malloc(NX_EMMC_BLOCKSIZE);
|
||||||
|
|
||||||
|
SHA256_CTX ctx;
|
||||||
|
sha256_init(&ctx);
|
||||||
|
|
||||||
|
while (sz > 64)
|
||||||
|
{
|
||||||
|
|
||||||
|
readData(buffer, offset, 64);
|
||||||
|
// gfx_hexdump(0, buffer + NX_EMMC_BLOCKSIZE - 8, 8);
|
||||||
|
sha256_update(&ctx, buffer, 64);
|
||||||
|
|
||||||
|
sz -= 64;
|
||||||
|
offset += 64;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(sz > 0){
|
||||||
|
|
||||||
|
|
||||||
|
readData(buffer, offset, sz);
|
||||||
|
sha256_update(&ctx, buffer, sz);
|
||||||
|
}
|
||||||
|
u8 hash1[0x20];
|
||||||
sha256_final(&ctx, hash1);
|
sha256_final(&ctx, hash1);
|
||||||
|
|
||||||
u8 *hash2 = (u8 *)malloc(0x20);
|
u8 hash2[0x20];
|
||||||
//se_calc_sha256(hash1, buffer, sz);
|
//se_calc_sha256(hash1, buffer, sz);
|
||||||
//sha256CalculateHash(hash1, buffer, sz);
|
//sha256CalculateHash(hash1, buffer, sz);
|
||||||
|
|
||||||
|
@ -667,22 +757,16 @@ bool verifyHash(u32 hashOffset, u32 offset, u32 sz)
|
||||||
if (memcmp(hash1, hash2, 0x20))
|
if (memcmp(hash1, hash2, 0x20))
|
||||||
{
|
{
|
||||||
EPRINTF("error: hash verification failed\n");
|
EPRINTF("error: hash verification failed\n");
|
||||||
//printf("error: hash verification failed for %x %d\n", (long)offset, (long)sz);
|
|
||||||
|
|
||||||
//print(hash1, 0x20);
|
|
||||||
//print(hash2, 0x20);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
result = true;
|
result = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
gfx_hexdump(0, hash1, 0x08);
|
gfx_hexdump(0, hash1, 0x20);
|
||||||
gfx_hexdump(0, hash2, 0x08);
|
gfx_hexdump(0, hash2, 0x20);
|
||||||
|
|
||||||
free(buffer);
|
free(buffer);
|
||||||
free(hash1);
|
|
||||||
free(hash2);
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -690,10 +774,8 @@ u32 certSize()
|
||||||
{
|
{
|
||||||
u32 buffer;
|
u32 buffer;
|
||||||
readData((u8 *)&buffer, 0x0AD0, sizeof(buffer));
|
readData((u8 *)&buffer, 0x0AD0, sizeof(buffer));
|
||||||
EPRINTF("certSize");
|
// EPRINTF("certSize");
|
||||||
gfx_hexdump(0, (u8 *)&buffer, sizeof(buffer));
|
// gfx_hexdump(0, (u8 *)&buffer, sizeof(buffer));
|
||||||
buffer = _read_le_u32(&buffer, 0);
|
|
||||||
gfx_hexdump(0, (u8 *)&buffer, sizeof(buffer));
|
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -701,17 +783,102 @@ u32 calibrationDataSize()
|
||||||
{
|
{
|
||||||
u32 buffer;
|
u32 buffer;
|
||||||
readData((u8 *)&buffer, 0x08, sizeof(buffer));
|
readData((u8 *)&buffer, 0x08, sizeof(buffer));
|
||||||
EPRINTF("calSize");
|
// EPRINTF("calSize");
|
||||||
gfx_hexdump(0, (u8 *)&buffer, sizeof(buffer));
|
// gfx_hexdump(0, (u8 *)&buffer, sizeof(buffer));
|
||||||
buffer = _read_le_u32(&buffer, 0);
|
|
||||||
gfx_hexdump(0, (u8 *)&buffer, sizeof(buffer));
|
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool writeCal0Hash()
|
||||||
|
{
|
||||||
|
return writeHash(0x20, 0x40, calibrationDataSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool writeClientCertHash()
|
||||||
|
{
|
||||||
|
return writeHash(0x12E0, 0xAE0, certSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool verifyCal0Hash(){
|
||||||
|
return verifyHash(0x20, 0x40, calibrationDataSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool verifyClientCertHash()
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
return verifyHash(0x12E0, 0xAE0, certSize());
|
||||||
|
}
|
||||||
|
|
||||||
bool verify()
|
bool verify()
|
||||||
{
|
{
|
||||||
bool r = verifyHash(0x12E0, 0x0AE0, certSize()); // client cert hash
|
return verifyClientCertHash() & verifyCal0Hash();
|
||||||
r &= verifyHash(0x20, 0x0040, calibrationDataSize()); // calibration hash
|
// bool r = verifyHash(0x12E0, 0xAE0, certSize()); // client cert hash
|
||||||
|
// r &= verifyHash(0x20, 0x40, calibrationDataSize()); // calibration hash
|
||||||
|
|
||||||
return r;
|
// return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void backup(){
|
||||||
|
sd_mount();
|
||||||
|
if (f_stat("sd:/prodinfo.bin", NULL)){
|
||||||
|
f_unlink("sd:/prodinfo.bin");
|
||||||
|
}
|
||||||
|
FIL fp;
|
||||||
|
f_open(&fp, "sd:/prodinfo.bin", FA_CREATE_NEW | FA_WRITE);
|
||||||
|
u8 bufferNX[NX_EMMC_BLOCKSIZE];
|
||||||
|
u32 size = 0x3FBC00;
|
||||||
|
u32 offset = 0;
|
||||||
|
while(size > NX_EMMC_BLOCKSIZE){
|
||||||
|
readData(bufferNX, offset, NX_EMMC_BLOCKSIZE);
|
||||||
|
f_write(&fp, bufferNX, NX_EMMC_BLOCKSIZE, NULL);
|
||||||
|
offset += NX_EMMC_BLOCKSIZE;
|
||||||
|
size -= NX_EMMC_BLOCKSIZE;
|
||||||
|
}
|
||||||
|
if(size > 0){
|
||||||
|
readData(bufferNX, offset, size);
|
||||||
|
f_write(&fp, bufferNX, size, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
f_close(&fp);
|
||||||
|
|
||||||
|
gfx_printf("\n%kBackup unecrypted done!", 4);
|
||||||
|
|
||||||
|
|
||||||
|
if (f_stat("sd:/prodinfoENC.bin", NULL)){
|
||||||
|
f_unlink("sd:/prodinfoENC.bin");
|
||||||
|
}
|
||||||
|
|
||||||
|
f_open(&fp, "sd:/prodinfoENC.bin", FA_CREATE_NEW | FA_WRITE);
|
||||||
|
size = 0x3FBC00;
|
||||||
|
offset = 0;
|
||||||
|
while(size > NX_EMMC_BLOCKSIZE){
|
||||||
|
nx_emmc_part_read(&storage, prodinfo_part, offset, 1, bufferNX);
|
||||||
|
f_write(&fp, bufferNX, NX_EMMC_BLOCKSIZE, NULL);
|
||||||
|
offset ++;
|
||||||
|
size -= NX_EMMC_BLOCKSIZE;
|
||||||
|
}
|
||||||
|
if(size > 0){
|
||||||
|
nx_emmc_part_read(&storage, prodinfo_part, offset, 1, bufferNX);
|
||||||
|
f_write(&fp, bufferNX, size, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
f_close(&fp);
|
||||||
|
|
||||||
|
gfx_printf("\n%kBackup encrypted done!", 4);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// bool erase(u32 offset, u32 sz)
|
||||||
|
// {
|
||||||
|
// u8 zero = 0;
|
||||||
|
|
||||||
|
// for (u64 i = 0; i < sz; i++)
|
||||||
|
// {
|
||||||
|
// fsStorageWrite(&m_sh, offset + i, &zero, 1);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
|
|
@ -21,6 +21,9 @@
|
||||||
|
|
||||||
void dump_keys();
|
void dump_keys();
|
||||||
bool readData(u8 *buffer, u32 offset, u32 length);
|
bool readData(u8 *buffer, u32 offset, u32 length);
|
||||||
|
bool writeData(u8 *buffer, u32 offset, u32 length);
|
||||||
|
bool writeClientCertHash();
|
||||||
|
bool writeCal0Hash();
|
||||||
bool verify();
|
bool verify();
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
extern sdmmc_storage_t sd_storage;
|
extern sdmmc_storage_t sd_storage;
|
||||||
extern sdmmc_storage_t storage;
|
extern sdmmc_storage_t storage;
|
||||||
extern emmc_part_t *system_part;
|
extern emmc_part_t *system_part;
|
||||||
|
extern emmc_part_t *prodinfo_part;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u32 sector;
|
u32 sector;
|
||||||
|
@ -127,13 +128,12 @@ out:;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
DRESULT disk_read_mod (
|
DRESULT disk_read_prod (
|
||||||
|
|
||||||
BYTE *buff, /* Data buffer to store read data */
|
BYTE *buff, /* Data buffer to store read data */
|
||||||
DWORD sector, /* Start sector in LBA */
|
DWORD sector, /* Start sector in LBA */
|
||||||
UINT count, /* Number of sectors to read */
|
UINT count /* Number of sectors to read */
|
||||||
sdmmc_storage_t *storage,
|
)
|
||||||
emmc_part_t *partition)
|
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
|
@ -141,30 +141,11 @@ DRESULT disk_read_mod (
|
||||||
__attribute__ ((aligned (16))) static u64 prev_cluster = -1;
|
__attribute__ ((aligned (16))) static u64 prev_cluster = -1;
|
||||||
__attribute__ ((aligned (16))) static u32 prev_sector = 0;
|
__attribute__ ((aligned (16))) static u32 prev_sector = 0;
|
||||||
u32 tweak_exp = 0;
|
u32 tweak_exp = 0;
|
||||||
bool regen_tweak = true, cache_sector = false;
|
bool regen_tweak = true;
|
||||||
|
|
||||||
u32 s = 0;
|
|
||||||
if (count == 1) {
|
|
||||||
for ( ; s < secindex; s++) {
|
|
||||||
if (sector_cache[s].sector == sector) {
|
|
||||||
sector_cache[s].visit_count++;
|
|
||||||
memcpy(buff, sector_cache[s].cached_sector, 0x200);
|
|
||||||
memcpy(tweak, sector_cache[s].tweak, 0x10);
|
|
||||||
prev_sector = sector;
|
|
||||||
prev_cluster = sector / 0x20;
|
|
||||||
return RES_OK;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// add to cache
|
|
||||||
if (s == secindex && s < MAX_SEC_CACHE_ENTRIES) {
|
|
||||||
sector_cache[s].sector = sector;
|
|
||||||
sector_cache[s].visit_count++;
|
|
||||||
cache_sector = true;
|
|
||||||
secindex++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nx_emmc_part_read(storage, partition, sector, count, buff)) {
|
|
||||||
|
if (nx_emmc_part_read(&storage, prodinfo_part, sector, count, buff)) {
|
||||||
if (prev_cluster != sector / 0x20) { // sector in different cluster than last read
|
if (prev_cluster != sector / 0x20) { // sector in different cluster than last read
|
||||||
prev_cluster = sector / 0x20;
|
prev_cluster = sector / 0x20;
|
||||||
tweak_exp = sector % 0x20;
|
tweak_exp = sector % 0x20;
|
||||||
|
@ -177,10 +158,7 @@ DRESULT disk_read_mod (
|
||||||
|
|
||||||
// fatfs will never pull more than a cluster
|
// fatfs will never pull more than a cluster
|
||||||
_emmc_xts(9, 8, 0, tweak, regen_tweak, tweak_exp, prev_cluster, buff, buff, count * 0x200);
|
_emmc_xts(9, 8, 0, tweak, regen_tweak, tweak_exp, prev_cluster, buff, buff, count * 0x200);
|
||||||
if (cache_sector) {
|
|
||||||
memcpy(sector_cache[s].cached_sector, buff, 0x200);
|
|
||||||
memcpy(sector_cache[s].tweak, tweak, 0x10);
|
|
||||||
}
|
|
||||||
prev_sector = sector + count - 1;
|
prev_sector = sector + count - 1;
|
||||||
return RES_OK;
|
return RES_OK;
|
||||||
}
|
}
|
||||||
|
@ -188,6 +166,44 @@ DRESULT disk_read_mod (
|
||||||
return RES_ERROR;
|
return RES_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DRESULT disk_write_prod (
|
||||||
|
|
||||||
|
BYTE *buff, /* Data buffer to store read data */
|
||||||
|
DWORD sector, /* Start sector in LBA */
|
||||||
|
UINT count /* Number of sectors to read */
|
||||||
|
)
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
__attribute__ ((aligned (16))) static u8 tweak[0x10];
|
||||||
|
__attribute__ ((aligned (16))) static u64 prev_cluster = -1;
|
||||||
|
__attribute__ ((aligned (16))) static u32 prev_sector = 0;
|
||||||
|
u32 tweak_exp = 0;
|
||||||
|
bool regen_tweak = true;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (prev_cluster != sector / 0x20) { // sector in different cluster than last read
|
||||||
|
prev_cluster = sector / 0x20;
|
||||||
|
tweak_exp = sector % 0x20;
|
||||||
|
} else if (sector > prev_sector) { // sector in same cluster and past last sector
|
||||||
|
tweak_exp = sector - prev_sector - 1;
|
||||||
|
regen_tweak = false;
|
||||||
|
} else { // sector in same cluster and before or same as last sector
|
||||||
|
tweak_exp = sector % 0x20;
|
||||||
|
}
|
||||||
|
|
||||||
|
// fatfs will never pull more than a cluster
|
||||||
|
_emmc_xts(9, 8, 1, tweak, regen_tweak, tweak_exp, prev_cluster, buff, buff, count * 0x200);
|
||||||
|
nx_emmc_part_write(&storage, prodinfo_part, sector, count, buff);
|
||||||
|
prev_sector = sector + count - 1;
|
||||||
|
return RES_OK;
|
||||||
|
|
||||||
|
|
||||||
|
// return RES_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
DRESULT disk_read (
|
DRESULT disk_read (
|
||||||
BYTE pdrv, /* Physical drive number to identify the drive */
|
BYTE pdrv, /* Physical drive number to identify the drive */
|
||||||
|
|
|
@ -33,7 +33,8 @@ typedef enum {
|
||||||
DSTATUS disk_initialize (BYTE pdrv);
|
DSTATUS disk_initialize (BYTE pdrv);
|
||||||
DSTATUS disk_status (BYTE pdrv);
|
DSTATUS disk_status (BYTE pdrv);
|
||||||
DRESULT disk_read (BYTE pdrv, BYTE* buff, DWORD sector, UINT count);
|
DRESULT disk_read (BYTE pdrv, BYTE* buff, DWORD sector, UINT count);
|
||||||
DRESULT disk_read_mod (BYTE *buff, DWORD sector, UINT count, sdmmc_storage_t *storage, emmc_part_t *partition);
|
DRESULT disk_read_prod (BYTE *buff, DWORD sector, UINT count);
|
||||||
|
DRESULT disk_write_prod (BYTE *buff, DWORD sector, UINT count);
|
||||||
DRESULT disk_write (BYTE pdrv, const BYTE* buff, DWORD sector, UINT count);
|
DRESULT disk_write (BYTE pdrv, const BYTE* buff, DWORD sector, UINT count);
|
||||||
DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void* buff);
|
DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void* buff);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue