CTRNAND for LayeredFS and small changes

This commit is contained in:
Aurora Wright 2017-04-13 02:49:19 +02:00
parent 5b6bd048a9
commit c95808fa2d
6 changed files with 49 additions and 45 deletions

View File

@ -34,7 +34,7 @@ _start:
bne _mountSd+4 bne _mountSd+4
stmfd sp!, {r0-r4, lr} stmfd sp!, {r0-r4, lr}
sub sp, sp, #4 sub sp, sp, #4
mov r1, #9 load r1, archive
mov r0, sp mov r0, sp
load r4, fsMountArchive load r4, fsMountArchive
blx r4 blx r4
@ -97,10 +97,12 @@ _start:
.pool .pool
.align 4 .align 4
sdmcArchiveName : .dcb "sdmc:", 0 sdmcArchiveName : .word 0xdead0007
.dcb ":", 0
.align 4 .align 4
fsMountArchive : .word 0xdead0005 fsMountArchive : .word 0xdead0005
fsRegisterArchive : .word 0xdead0006 fsRegisterArchive : .word 0xdead0006
archive : .word 0xdead0008
sdmcCustomPath : .word 0xdead0004 sdmcCustomPath : .word 0xdead0004
.close .close

View File

@ -40,18 +40,18 @@ static Result fileOpen(IFile *file, FS_ArchiveID archiveId, const char *path, in
return IFile_Open(file, archiveId, archivePath, filePath, flags); return IFile_Open(file, archiveId, archivePath, filePath, flags);
} }
static bool dirCheck(FS_ArchiveID archiveId, const char *path) static u32 dirCheck(FS_ArchiveID archiveId, const char *path)
{ {
bool ret; u32 ret;
Handle handle; Handle handle;
FS_Archive archive; FS_Archive archive;
FS_Path dirPath = {PATH_ASCII, strnlen(path, 255) + 1, path}, FS_Path dirPath = {PATH_ASCII, strnlen(path, 255) + 1, path},
archivePath = {PATH_EMPTY, 1, (u8 *)""}; archivePath = {PATH_EMPTY, 1, (u8 *)""};
if(R_FAILED(FSLDR_OpenArchive(&archive, archiveId, archivePath))) ret = false; if(R_FAILED(FSLDR_OpenArchive(&archive, archiveId, archivePath))) ret = 1;
else else
{ {
ret = R_SUCCEEDED(FSLDR_OpenDirectory(&handle, archive, dirPath)); ret = R_SUCCEEDED(FSLDR_OpenDirectory(&handle, archive, dirPath)) ? 0 : 2;
if(ret) FSDIRLDR_Close(handle); if(ret) FSDIRLDR_Close(handle);
FSLDR_CloseArchive(archive); FSLDR_CloseArchive(archive);
} }
@ -59,19 +59,23 @@ static bool dirCheck(FS_ArchiveID archiveId, const char *path)
return ret; return ret;
} }
static u32 openLumaFile(IFile *file, const char *path) static bool openLumaFile(IFile *file, const char *path)
{ {
Result res = fileOpen(file, ARCHIVE_SDMC, path, FS_OPEN_READ); Result res = fileOpen(file, ARCHIVE_SDMC, path, FS_OPEN_READ);
if(R_SUCCEEDED(res)) return ARCHIVE_SDMC; if(R_SUCCEEDED(res)) return false;
//Returned if SD is not mounted //Returned if SD is not mounted
return (u32)res == 0xC88044AB && R_SUCCEEDED(fileOpen(file, ARCHIVE_NAND_RW, path, FS_OPEN_READ)) ? ARCHIVE_NAND_RW : 0; return (u32)res == 0xC88044AB && R_SUCCEEDED(fileOpen(file, ARCHIVE_NAND_RW, path, FS_OPEN_READ));
} }
static bool checkLumaDir(const char *path) static u32 checkLumaDir(const char *path)
{ {
return dirCheck(ARCHIVE_SDMC, path); u32 res = dirCheck(ARCHIVE_SDMC, path);
if(!res) return ARCHIVE_SDMC;
return res == 1 && !dirCheck(ARCHIVE_NAND_RW, path) ? ARCHIVE_NAND_RW : 0;
} }
static inline void loadCFWInfo(void) static inline void loadCFWInfo(void)
@ -513,7 +517,11 @@ static inline bool patchRomfsRedirection(u64 progId, u8* code, u32 size)
char path[] = "/luma/titles/0000000000000000/romfs"; char path[] = "/luma/titles/0000000000000000/romfs";
progIdToStr(path + 28, progId); progIdToStr(path + 28, progId);
if(!checkLumaDir(path)) return true; u32 archive = checkLumaDir(path);
if(!archive) return true;
const char *mount = archive == ARCHIVE_SDMC ? "sdmc:" : "nand:";
u32 fsMountArchive = 0xFFFFFFFF, u32 fsMountArchive = 0xFFFFFFFF,
fsRegisterArchive = 0xFFFFFFFF, fsRegisterArchive = 0xFFFFFFFF,
@ -546,7 +554,7 @@ static inline bool patchRomfsRedirection(u64 progId, u8* code, u32 size)
payload32[i] = MAKE_BRANCH(throwFatalError + i * 4, fsTryOpenFile + 4); payload32[i] = MAKE_BRANCH(throwFatalError + i * 4, fsTryOpenFile + 4);
break; break;
case 0xdead0004: case 0xdead0004:
memcpy(payload32 + i, "sdmc:", 5); memcpy(payload32 + i, mount, 5);
memcpy((u8 *)(payload32 + i) + 5, path, sizeof(path)); memcpy((u8 *)(payload32 + i) + 5, path, sizeof(path));
break; break;
case 0xdead0005: case 0xdead0005:
@ -555,6 +563,12 @@ static inline bool patchRomfsRedirection(u64 progId, u8* code, u32 size)
case 0xdead0006: case 0xdead0006:
payload32[i] = 0x100000 + fsRegisterArchive; payload32[i] = 0x100000 + fsRegisterArchive;
break; break;
case 0xdead0007:
memcpy(payload32 + i, mount, 4);
break;
case 0xdead0008:
payload32[i] = archive;
break;
} }
} }

View File

@ -322,8 +322,6 @@ static void sha(void *res, const void *src, u32 size, u32 mode)
void twlConsoleInfoInit(void) void twlConsoleInfoInit(void)
{ {
if(CFG_SYSPROT9 & 2) return; //sorry, the lennies are currently missing
u64 twlConsoleId = CFG_UNITINFO != 0 ? OTP_DEVCONSOLEID : (0x80000000ULL | (*(vu64 *)0x01FFB808 ^ 0x8C267B7B358A6AFULL)); u64 twlConsoleId = CFG_UNITINFO != 0 ? OTP_DEVCONSOLEID : (0x80000000ULL | (*(vu64 *)0x01FFB808 ^ 0x8C267B7B358A6AFULL));
CFG_TWLUNITINFO = CFG_UNITINFO; CFG_TWLUNITINFO = CFG_UNITINFO;
OTP_TWLCONSOLEID = twlConsoleId; OTP_TWLCONSOLEID = twlConsoleId;
@ -482,28 +480,6 @@ bool decryptNusFirm(const Ticket *ticket, Cxi *cxi, u32 ncchSize)
return decryptExeFs(cxi); return decryptExeFs(cxi);
} }
void setN3DS96Keys(void)
{
//Set 0x11 keyslot
__attribute__((aligned(4))) const u8 key2s[2][AES_BLOCK_SIZE] = {
{0x42, 0x3F, 0x81, 0x7A, 0x23, 0x52, 0x58, 0x31, 0x6E, 0x75, 0x8E, 0x3A, 0x39, 0x43, 0x2E, 0xD0},
{0xFF, 0x77, 0xA0, 0x9A, 0x99, 0x81, 0xE9, 0x48, 0xEC, 0x51, 0xC9, 0x32, 0x5D, 0x14, 0xEC, 0x25}
};
aes_setkey(0x11, key2s[ISDEVUNIT ? 1 : 0], AES_KEYNORMAL, AES_INPUT_BE | AES_INPUT_NORMAL);
__attribute__((aligned(4))) u8 keyData[AES_BLOCK_SIZE] = {0xDD, 0xDA, 0xA4, 0xC6, 0x2C, 0xC4, 0x50, 0xE9, 0xDA, 0xB6, 0x9B, 0x0D, 0x9D, 0x2A, 0x21, 0x98},
decKey[sizeof(keyData)];
//Set keys 0x19..0x1F keyXs
aes_use_keyslot(0x11);
for(u8 slot = 0x19; slot < 0x20; slot++, keyData[0xF]++)
{
aes(decKey, keyData, 1, NULL, AES_ECB_DECRYPT_MODE, 0);
aes_setkey(slot, decKey, AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL);
}
}
void kernel9Loader(Arm9Bin *arm9Section) void kernel9Loader(Arm9Bin *arm9Section)
{ {
//Determine the kernel9loader version //Determine the kernel9loader version
@ -561,6 +537,21 @@ void kernel9Loader(Arm9Bin *arm9Section)
if(*startOfArm9Bin != 0x47704770 && *startOfArm9Bin != 0xB0862000) error("Failed to decrypt the ARM9 binary."); if(*startOfArm9Bin != 0x47704770 && *startOfArm9Bin != 0xB0862000) error("Failed to decrypt the ARM9 binary.");
} }
//Set >=9.6 KeyXs
if(k9lVersion == 2)
{
__attribute__((aligned(4))) u8 keyData[AES_BLOCK_SIZE] = {0xDD, 0xDA, 0xA4, 0xC6, 0x2C, 0xC4, 0x50, 0xE9, 0xDA, 0xB6, 0x9B, 0x0D, 0x9D, 0x2A, 0x21, 0x98},
decKey[sizeof(keyData)];
//Set keys 0x19..0x1F keyXs
aes_use_keyslot(0x11);
for(u8 slot = 0x19; slot < 0x20; slot++, keyData[0xF]++)
{
aes(decKey, keyData, 1, NULL, AES_ECB_DECRYPT_MODE, 0);
aes_setkey(slot, decKey, AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL);
}
}
} }
void computePinHash(u8 *outbuf, const u8 *inbuf) void computePinHash(u8 *outbuf, const u8 *inbuf)

View File

@ -114,7 +114,6 @@ int ctrNandWrite(u32 sector, u32 sectorCount, const u8 *inbuf);
void set6x7xKeys(void); void set6x7xKeys(void);
bool decryptExeFs(Cxi *cxi); bool decryptExeFs(Cxi *cxi);
bool decryptNusFirm(const Ticket *ticket, Cxi *cxi, u32 ncchSize); bool decryptNusFirm(const Ticket *ticket, Cxi *cxi, u32 ncchSize);
void setN3DS96Keys(void);
void kernel9Loader(Arm9Bin *arm9Section); void kernel9Loader(Arm9Bin *arm9Section);
void computePinHash(u8 *outbuf, const u8 *inbuf); void computePinHash(u8 *outbuf, const u8 *inbuf);
void backupAndRestoreShaHash(bool isRestore); void backupAndRestoreShaHash(bool isRestore);

View File

@ -117,6 +117,9 @@ u32 patchNativeFirm(u32 firmVersion, FirmwareSource nandType, u32 emuHeader, boo
u8 *arm9Section = (u8 *)firm + firm->section[2].offset, u8 *arm9Section = (u8 *)firm + firm->section[2].offset,
*arm11Section1 = (u8 *)firm + firm->section[1].offset; *arm11Section1 = (u8 *)firm + firm->section[1].offset;
//On sighax cold boot, initialize TWL keys
if(!(CFG_SYSPROT9 & 2)) twlConsoleInfoInit();
if(ISN3DS) if(ISN3DS)
{ {
//Decrypt ARM9Bin and patch ARM9 entrypoint to skip kernel9loader //Decrypt ARM9Bin and patch ARM9 entrypoint to skip kernel9loader
@ -173,11 +176,8 @@ u32 patchNativeFirm(u32 firmVersion, FirmwareSource nandType, u32 emuHeader, boo
} }
//11.3 FIRM patches //11.3 FIRM patches
if(firmVersion >= (ISN3DS ? 0x2D : 0x5C)) if(firmVersion >= (ISN3DS ? 0x2D : 0x5C)) //Stub svc 0x59
{
//Stub svc 0x59
ret += stubSvcRestrictGpuDma(arm11Section1, arm11SvcTable, baseK11VA); ret += stubSvcRestrictGpuDma(arm11Section1, arm11SvcTable, baseK11VA);
}
ret += implementSvcGetCFWInfo(arm11Section1, arm11SvcTable, baseK11VA, &freeK11Space, isSafeMode); ret += implementSvcGetCFWInfo(arm11Section1, arm11SvcTable, baseK11VA, &freeK11Space, isSafeMode);

View File

@ -98,12 +98,10 @@ void main(void)
//Save old options and begin saving the new boot configuration //Save old options and begin saving the new boot configuration
configTemp = (configData.config & 0xFFFFFF00) | ((u32)ISA9LH << 6); configTemp = (configData.config & 0xFFFFFF00) | ((u32)ISA9LH << 6);
twlConsoleInfoInit();
setN3DS96Keys();
//If it's a MCU reboot, try to force boot options //If it's a MCU reboot, try to force boot options
if(ISA9LH && CFG_BOOTENV && needConfig != CREATE_CONFIGURATION) if(ISA9LH && CFG_BOOTENV && needConfig != CREATE_CONFIGURATION)
{ {
//Always force a SysNAND boot when quitting AGB_FIRM //Always force a SysNAND boot when quitting AGB_FIRM
if(CFG_BOOTENV == 7) if(CFG_BOOTENV == 7)
{ {