From 28e5d8107f8adbb6196846e3e29c1f756b38a5bb Mon Sep 17 00:00:00 2001 From: Aurora Wright Date: Fri, 26 May 2017 03:07:39 +0200 Subject: [PATCH] Remove hardcoded CTRNAND FAT offsets, calculate them from parsing NCSD + CTR MBR --- source/crypto.c | 35 +++++++++++++++++++++++++---------- source/crypto.h | 5 +++-- source/emunand.c | 13 +++++++------ source/emunand.h | 4 ++-- source/fatfs/diskio.c | 15 ++------------- source/firm.c | 4 ++-- source/firm.h | 2 +- source/main.c | 7 +++---- 8 files changed, 45 insertions(+), 40 deletions(-) diff --git a/source/crypto.c b/source/crypto.c index 36ca27f..0ef1a3b 100755 --- a/source/crypto.c +++ b/source/crypto.c @@ -320,7 +320,7 @@ void sha(void *res, const void *src, u32 size, u32 mode) __attribute__((aligned(4))) static u8 nandCtr[AES_BLOCK_SIZE]; static u8 nandSlot; -static u32 fatStart; +static u32 fatStart = 0; FirmwareSource firmSource; @@ -333,7 +333,7 @@ __attribute__((aligned(4))) static const u8 key1s[2][AES_BLOCK_SIZE] = { {0xFF, 0x77, 0xA0, 0x9A, 0x99, 0x81, 0xE9, 0x48, 0xEC, 0x51, 0xC9, 0x32, 0x5D, 0x14, 0xEC, 0x25} }; -void ctrNandInit(void) +int ctrNandInit(void) { __attribute__((aligned(4))) u8 cid[AES_BLOCK_SIZE], shaSum[SHA_256_HASH_SIZE]; @@ -342,16 +342,31 @@ void ctrNandInit(void) sha(shaSum, cid, sizeof(cid), SHA_256_MODE); memcpy(nandCtr, shaSum, sizeof(nandCtr)); - if(ISN3DS) + nandSlot = ISN3DS ? 0x05 : 0x04; + + u8 __attribute__((aligned(4))) temp[0x200]; + + int result; + + //Read NCSD header + result = firmSource == FIRMWARE_SYSNAND ? sdmmc_nand_readsectors(0, 1, temp) : sdmmc_sdcard_readsectors(emuHeader, 1, temp); + + if(!result) { - nandSlot = 0x05; - fatStart = 0x5CAD7; - } - else - { - nandSlot = 0x04; - fatStart = 0x5CAE5; + u32 partitionNum = 1; //TWL partitions need to be first + + for(u8 *partitionId = temp + 0x111; *partitionId != 1; partitionId++, partitionNum++); + + u32 ctrMbrOffset = *((u32 *)(temp + 0x120) + (2 * partitionNum)); + + //Read CTR MBR + result = ctrNandRead(ctrMbrOffset, 1, temp); + + //Calculate final CTRNAND FAT offset + if(!result) fatStart = ctrMbrOffset + *(u32 *)(temp + 0x1C6); } + + return result; } int ctrNandRead(u32 sector, u32 sectorCount, u8 *outbuf) diff --git a/source/crypto.h b/source/crypto.h index aa613fb..1e452aa 100755 --- a/source/crypto.h +++ b/source/crypto.h @@ -104,13 +104,14 @@ #define SHA_224_HASH_SIZE (224 / 8) #define SHA_1_HASH_SIZE (160 / 8) -extern u32 emuOffset; +extern u32 emuOffset, + emuHeader; extern FirmwareSource firmSource; void aes(void *dst, const void *src, u32 blockCount, void *iv, u32 mode, u32 ivMode); void sha(void *res, const void *src, u32 size, u32 mode); -void ctrNandInit(void); +int ctrNandInit(void); int ctrNandRead(u32 sector, u32 sectorCount, u8 *outbuf); int ctrNandWrite(u32 sector, u32 sectorCount, const u8 *inbuf); bool decryptExeFs(Cxi *cxi); diff --git a/source/emunand.c b/source/emunand.c index c33111f..393ade6 100644 --- a/source/emunand.c +++ b/source/emunand.c @@ -29,9 +29,10 @@ #include "fatfs/sdmmc/sdmmc.h" #include "../build/bundled.h" -u32 emuOffset; +u32 emuOffset, + emuHeader; -void locateEmuNand(u32 *emuHeader, FirmwareSource *nandType) +void locateEmuNand(FirmwareSource *nandType) { static u8 __attribute__((aligned(4))) temp[0x200]; static u32 nandSize = 0, @@ -70,7 +71,7 @@ void locateEmuNand(u32 *emuHeader, FirmwareSource *nandType) if(!sdmmc_sdcard_readsectors(nandOffset + 1, 1, temp) && memcmp(temp + 0x100, "NCSD", 4) == 0) { emuOffset = nandOffset + 1; - *emuHeader = nandOffset + 1; + emuHeader = nandOffset + 1; return; } @@ -78,7 +79,7 @@ void locateEmuNand(u32 *emuHeader, FirmwareSource *nandType) else if(i != 2 && !sdmmc_sdcard_readsectors(nandOffset + nandSize, 1, temp) && memcmp(temp + 0x100, "NCSD", 4) == 0) { emuOffset = nandOffset; - *emuHeader = nandOffset + nandSize; + emuHeader = nandOffset + nandSize; return; } } @@ -90,7 +91,7 @@ void locateEmuNand(u32 *emuHeader, FirmwareSource *nandType) if(*nandType != FIRMWARE_EMUNAND) { *nandType = FIRMWARE_EMUNAND; - locateEmuNand(emuHeader, nandType); + locateEmuNand(nandType); } else *nandType = FIRMWARE_SYSNAND; } @@ -161,7 +162,7 @@ static inline u32 patchMpu(u8 *pos, u32 size) return 0; } -u32 patchEmuNand(u8 *arm9Section, u32 kernel9Size, u8 *process9Offset, u32 process9Size, u32 emuHeader, u8 *kernel9Address) +u32 patchEmuNand(u8 *arm9Section, u32 kernel9Size, u8 *process9Offset, u32 process9Size, u8 *kernel9Address) { u8 *freeK9Space; diff --git a/source/emunand.h b/source/emunand.h index 59c9e38..06ecaa5 100644 --- a/source/emunand.h +++ b/source/emunand.h @@ -30,5 +30,5 @@ #define ROUND_TO_4MB(a) (((a) + 0x2000 - 1) & (~(0x2000 - 1))) -void locateEmuNand(u32 *emuHeader, FirmwareSource *nandType); -u32 patchEmuNand(u8 *arm9Section, u32 kernel9Size, u8 *process9Offset, u32 process9Size, u32 emuHeader, u8 *kernel9Address); \ No newline at end of file +void locateEmuNand(FirmwareSource *nandType); +u32 patchEmuNand(u8 *arm9Section, u32 kernel9Size, u8 *process9Offset, u32 process9Size, u8 *kernel9Address); \ No newline at end of file diff --git a/source/fatfs/diskio.c b/source/fatfs/diskio.c index 4dd504c..5a25921 100644 --- a/source/fatfs/diskio.c +++ b/source/fatfs/diskio.c @@ -37,23 +37,12 @@ DSTATUS disk_initialize ( BYTE pdrv /* Physical drive nmuber to identify the drive */ ) { - DSTATUS ret; static u32 sdmmcInitResult = 4; if(sdmmcInitResult == 4) sdmmcInitResult = sdmmc_sdcard_init(); - if(pdrv == CTRNAND) - { - if(!(sdmmcInitResult & 1)) - { - ctrNandInit(); - ret = 0; - } - else ret = STA_NOINIT; - } - else ret = (!(sdmmcInitResult & 2)) ? 0 : STA_NOINIT; - - return ret; + return ((pdrv == SDCARD && !(sdmmcInitResult & 2)) || + (pdrv == CTRNAND && !(sdmmcInitResult & 1) && !ctrNandInit())) ? 0 : STA_NOINIT; } diff --git a/source/firm.c b/source/firm.c index 2dbff17..14aa6c4 100755 --- a/source/firm.c +++ b/source/firm.c @@ -197,7 +197,7 @@ u32 loadFirm(FirmwareType *firmType, FirmwareSource nandType, bool loadFromStora return firmVersion; } -u32 patchNativeFirm(u32 firmVersion, FirmwareSource nandType, u32 emuHeader, bool loadFromStorage, bool isSafeMode, bool doUnitinfoPatch, bool enableExceptionHandlers) +u32 patchNativeFirm(u32 firmVersion, FirmwareSource nandType, bool loadFromStorage, bool isSafeMode, bool doUnitinfoPatch, bool enableExceptionHandlers) { u8 *arm9Section = (u8 *)firm + firm->section[2].offset, *arm11Section1 = (u8 *)firm + firm->section[1].offset; @@ -229,7 +229,7 @@ u32 patchNativeFirm(u32 firmVersion, FirmwareSource nandType, u32 emuHeader, boo ret += patchSignatureChecks(process9Offset, process9Size); //Apply EmuNAND patches - if(nandType != FIRMWARE_SYSNAND) ret += patchEmuNand(arm9Section, kernel9Size, process9Offset, process9Size, emuHeader, firm->section[2].address); + if(nandType != FIRMWARE_SYSNAND) ret += patchEmuNand(arm9Section, kernel9Size, process9Offset, process9Size, firm->section[2].address); //Apply FIRM0/1 writes patches on SysNAND to protect A9LH else ret += patchFirmWrites(process9Offset, process9Size); diff --git a/source/firm.h b/source/firm.h index 6647efb..674b0a2 100644 --- a/source/firm.h +++ b/source/firm.h @@ -28,7 +28,7 @@ static Firm *const firm = (Firm *const)0x20001000; u32 loadFirm(FirmwareType *firmType, FirmwareSource nandType, bool loadFromStorage, bool isSafeMode); -u32 patchNativeFirm(u32 firmVersion, FirmwareSource nandType, u32 emuHeader, bool loadFromStorage, bool isSafeMode, bool doUnitinfoPatch, bool enableExceptionHandlers); +u32 patchNativeFirm(u32 firmVersion, FirmwareSource nandType, bool loadFromStorage, bool isSafeMode, bool doUnitinfoPatch, bool enableExceptionHandlers); u32 patchTwlFirm(u32 firmVersion, bool loadFromStorage, bool doUnitinfoPatch); u32 patchAgbFirm(bool loadFromStorage, bool doUnitinfoPatch); u32 patch1x2xNativeAndSafeFirm(bool enableExceptionHandlers); diff --git a/source/main.c b/source/main.c index 48671bb..0723d83 100644 --- a/source/main.c +++ b/source/main.c @@ -46,7 +46,6 @@ void main(int argc, char **argv, u32 magicWord) { bool isSafeMode = false, isNoForceFlagSet = false; - u32 emuHeader; FirmwareType firmType; FirmwareSource nandType; @@ -266,13 +265,13 @@ boot: //If we need to boot EmuNAND, make sure it exists if(nandType != FIRMWARE_SYSNAND) { - locateEmuNand(&emuHeader, &nandType); + locateEmuNand(&nandType); if(nandType == FIRMWARE_SYSNAND) firmSource = FIRMWARE_SYSNAND; } //Same if we're using EmuNAND as the FIRM source else if(firmSource != FIRMWARE_SYSNAND) - locateEmuNand(&emuHeader, &firmSource); + locateEmuNand(&firmSource); if(!isFirmlaunch) { @@ -291,7 +290,7 @@ boot: switch(firmType) { case NATIVE_FIRM: - res = patchNativeFirm(firmVersion, nandType, emuHeader, loadFromStorage, isSafeMode, doUnitinfoPatch, enableExceptionHandlers); + res = patchNativeFirm(firmVersion, nandType, loadFromStorage, isSafeMode, doUnitinfoPatch, enableExceptionHandlers); break; case TWL_FIRM: res = patchTwlFirm(firmVersion, loadFromStorage, doUnitinfoPatch);