diff --git a/source/crypto.c b/source/crypto.c index 8a1e10a..40e7eb4 100755 --- a/source/crypto.c +++ b/source/crypto.c @@ -441,47 +441,24 @@ bool decryptNusFirm(const Ticket *ticket, Cxi *cxi, u32 ncchSize) return decryptExeFs(cxi); } -static inline void twlConsoleInfoInit(void) -{ - u64 twlConsoleId = CFG_UNITINFO != 0 ? OTP_DEVCONSOLEID : (0x80000000ULL | (*(vu64 *)0x01FFB808 ^ 0x8C267B7B358A6AFULL)); - CFG_TWLUNITINFO = CFG_UNITINFO; - OTP_TWLCONSOLEID = twlConsoleId; - - *REG_AESCNT = 0; - - vu32 *k3X = REGs_AESTWLKEYS[3][1], *k1X = REGs_AESTWLKEYS[1][1]; - - k3X[0] = (u32)twlConsoleId; - k3X[3] = (u32)(twlConsoleId >> 32); - - k1X[2] = (u32)(twlConsoleId >> 32); - k1X[3] = (u32)twlConsoleId; -} - void kernel9Loader(Arm9Bin *arm9Section) { //Determine the kernel9loader version u32 k9lVersion; - if(arm9Section == NULL) - k9lVersion = 2; - else + switch(arm9Section->magic[3]) { - switch(arm9Section->magic[3]) - { - case 0xFF: - k9lVersion = 0; - break; - case '1': - k9lVersion = 1; - break; - default: - k9lVersion = 2; - break; - } + case 0xFF: + k9lVersion = 0; + break; + case '1': + k9lVersion = 1; + break; + default: + k9lVersion = 2; } u32 *startOfArm9Bin = (u32 *)((u8 *)arm9Section + 0x800); - bool needToDecrypt = arm9Section != NULL && *startOfArm9Bin != 0x47704770 && *startOfArm9Bin != 0xB0862000; + if(*startOfArm9Bin == 0x47704770 || *startOfArm9Bin == 0xB0862000) return; //Already decrypted //Set 0x11 keyslot __attribute__((aligned(4))) const u8 key1s[2][AES_BLOCK_SIZE] = { @@ -495,68 +472,28 @@ void kernel9Loader(Arm9Bin *arm9Section) aes_setkey(0x11, k9lVersion == 2 ? key2s[ISDEVUNIT ? 1 : 0] : key1s[ISDEVUNIT ? 1 : 0], AES_KEYNORMAL, AES_INPUT_BE | AES_INPUT_NORMAL); - if(needToDecrypt) - { - u8 arm9BinSlot = k9lVersion == 0 ? 0x15 : 0x16; - - //Set keyX - __attribute__((aligned(4))) u8 keyX[AES_BLOCK_SIZE]; - aes_use_keyslot(0x11); - aes(keyX, k9lVersion == 0 ? arm9Section->keyX : arm9Section->slot0x16keyX, 1, NULL, AES_ECB_DECRYPT_MODE, 0); - aes_setkey(arm9BinSlot, keyX, AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL); - - //Set keyY - __attribute__((aligned(4))) u8 keyY[AES_BLOCK_SIZE]; - memcpy(keyY, arm9Section->keyY, sizeof(keyY)); - aes_setkey(arm9BinSlot, keyY, AES_KEYY, AES_INPUT_BE | AES_INPUT_NORMAL); - - //Set CTR - __attribute__((aligned(4))) u8 arm9BinCtr[AES_BLOCK_SIZE]; - memcpy(arm9BinCtr, arm9Section->ctr, sizeof(arm9BinCtr)); - - //Decrypt ARM9 binary - aes_use_keyslot(arm9BinSlot); - aes(startOfArm9Bin, startOfArm9Bin, decAtoi(arm9Section->size, sizeof(arm9Section->size)) / AES_BLOCK_SIZE, arm9BinCtr, AES_CTR_MODE, AES_INPUT_BE | AES_INPUT_NORMAL); - - if(*startOfArm9Bin != 0x47704770 && *startOfArm9Bin != 0xB0862000) error("Failed to decrypt the ARM9 binary."); - } - - __attribute__((aligned(4))) u8 keyBlocks[2][AES_BLOCK_SIZE] = { - {0xA4, 0x8D, 0xE4, 0xF1, 0x0B, 0x36, 0x44, 0xAA, 0x90, 0x31, 0x28, 0xFF, 0x4D, 0xCA, 0x76, 0xDF}, - {0xDD, 0xDA, 0xA4, 0xC6, 0x2C, 0xC4, 0x50, 0xE9, 0xDA, 0xB6, 0x9B, 0x0D, 0x9D, 0x2A, 0x21, 0x98} - }, decKey[AES_BLOCK_SIZE]; - - u8 firstKey; - u32 keyBlocksIndex; - - if(k9lVersion == 2) - { - firstKey = 0x19; - keyBlocksIndex = 1; - } - else - { - firstKey = 0x18; - keyBlocksIndex = 0; - } + u8 arm9BinSlot = k9lVersion == 0 ? 0x15 : 0x16; + //Set keyX + __attribute__((aligned(4))) u8 keyX[AES_BLOCK_SIZE]; aes_use_keyslot(0x11); - for(u8 slot = firstKey; slot < 0x20; slot++, keyBlocks[keyBlocksIndex][0xF]++) - { - aes(decKey, keyBlocks[keyBlocksIndex], 1, NULL, AES_ECB_DECRYPT_MODE, 0); - aes_setkey(slot, decKey, AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL); - } + aes(keyX, k9lVersion == 0 ? arm9Section->keyX : arm9Section->slot0x16keyX, 1, NULL, AES_ECB_DECRYPT_MODE, 0); + aes_setkey(arm9BinSlot, keyX, AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL); - if(k9lVersion == 2) - { - aes_setkey(0x11, key1s[ISDEVUNIT ? 1 : 0], AES_KEYNORMAL, AES_INPUT_BE | AES_INPUT_NORMAL); - aes_use_keyslot(0x11); - aes(decKey, keyBlocks[0], 1, NULL, AES_ECB_DECRYPT_MODE, 0); - aes_setkey(0x18, decKey, AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL); - } + //Set keyY + __attribute__((aligned(4))) u8 keyY[AES_BLOCK_SIZE]; + memcpy(keyY, arm9Section->keyY, sizeof(keyY)); + aes_setkey(arm9BinSlot, keyY, AES_KEYY, AES_INPUT_BE | AES_INPUT_NORMAL); - if(ISSIGHAX) - twlConsoleInfoInit(); + //Set CTR + __attribute__((aligned(4))) u8 arm9BinCtr[AES_BLOCK_SIZE]; + memcpy(arm9BinCtr, arm9Section->ctr, sizeof(arm9BinCtr)); + + //Decrypt ARM9 binary + aes_use_keyslot(arm9BinSlot); + aes(startOfArm9Bin, startOfArm9Bin, decAtoi(arm9Section->size, sizeof(arm9Section->size)) / AES_BLOCK_SIZE, arm9BinCtr, AES_CTR_MODE, AES_INPUT_BE | AES_INPUT_NORMAL); + + if(*startOfArm9Bin != 0x47704770 && *startOfArm9Bin != 0xB0862000) error("Failed to decrypt the ARM9 binary."); } void computePinHash(u8 *outbuf, const u8 *inbuf) diff --git a/source/firm.c b/source/firm.c index 3d3f353..f268aa5 100755 --- a/source/firm.c +++ b/source/firm.c @@ -376,7 +376,7 @@ void launchFirm(FirmwareType firmType, bool loadFromStorage) for(; sectionNum < 4 && firm->section[sectionNum].size != 0; sectionNum++) memcpy(firm->section[sectionNum].address, (u8 *)firm + firm->section[sectionNum].offset, firm->section[sectionNum].size); - if(!ISFIRMLAUNCH) deinitScreens(); + if(!isFirmlaunch) deinitScreens(); //Set ARM11 kernel entrypoint ARM11_CORE0_MAILBOX_ENTRYPOINT = (u32)firm->arm11Entry; diff --git a/source/fs.c b/source/fs.c index 395deee..f313b3b 100644 --- a/source/fs.c +++ b/source/fs.c @@ -189,9 +189,6 @@ void loadPayload(u32 pressed, const char *payloadPath) char absPath[24 + _MAX_LFN] = {0}; char path[10 + _MAX_LFN] = {0}; - u16 mountPoint[5] = {0}; - for(u32 i = 0; i < 4 && launchedPath[i] != u':'; i++) - if(payloadPath == NULL) { const char *pattern; @@ -212,7 +209,6 @@ void loadPayload(u32 pressed, const char *payloadPath) FILINFO info; FRESULT result; - result = f_findfirst(&dir, &info, "payloads", pattern); if(result != FR_OK) return; @@ -226,13 +222,13 @@ void loadPayload(u32 pressed, const char *payloadPath) } else sprintf(path, "%s", payloadPath); - payloadSize = fileRead(firm, path, maxPayloadSize); + payloadSize = fileRead(firm, path, maxPayloadSize); if(!payloadSize || !checkFirmPayload()) return; writeConfig(true); - if(memcmp(mountPoint, u"nand", 8)) + if(memcmp(launchedPath, u"nand", 8)) sprintf(absPath, "nand:/rw/luma/%s", path); else sprintf(absPath, "sdmc:/luma/%s", path); diff --git a/source/main.c b/source/main.c index 0960248..1b5cef5 100644 --- a/source/main.c +++ b/source/main.c @@ -38,19 +38,18 @@ extern CfgData configData; extern ConfigurationStatus needConfig; extern FirmwareSource firmSource; -u16 launchedFirmTidLow[8]; -u16 launchedPath[7 + 255]; +bool isFirmlaunch; +u16 launchedPath[41]; void main(int argc, char **argv) { bool isSafeMode = false, isNoForceFlagSet = false; + char errbuf[46]; u32 emuHeader; FirmwareType firmType; FirmwareSource nandType; - char errbuf[128]; - switch(argc) { case 0: @@ -60,12 +59,12 @@ void main(int argc, char **argv) case 1: //Normal boot { u32 i; - for(i = 0; i < 6 + 255 && argv[0][i] != 0; i++) //Copy and convert the path to utf16 + for(i = 0; i < 40 && argv[0][i] != 0; i++) //Copy and convert the path to utf16 launchedPath[i] = argv[0][i]; - for(; i < 7 + 255; i++) + for(; i < 41; i++) launchedPath[i] = 0; - memset(launchedFirmTidLow, 0, 16); + isFirmlaunch = false; break; } @@ -73,34 +72,32 @@ void main(int argc, char **argv) { u32 i; u16 *p = (u16 *)argv[0]; - for(i = 0; i < 6 + 255 && p[i] != 0; i++) + for(i = 0; i < 40 && p[i] != 0; i++) launchedPath[i] = p[i]; - for(; i < 7 + 255; i++) + for(; i < 41; i++) launchedPath[i] = 0; - memcpy(launchedFirmTidLow, (u16 *)argv[1], 16); + isFirmlaunch = true; break; } default: - sprintf(errbuf, "Unsupported launcher (argc = %d > 2).", argc); + { + sprintf(errbuf, "Unsupported launcher (argc = %d).", argc); error(errbuf); break; + } } - u16 mountPoint[5] = {0}; - for(u32 i = 0; i < 4 && launchedPath[i] != u':'; i++) - mountPoint[i] = launchedPath[i]; - //Mount SD or CTRNAND bool isSdMode; - if(memcmp(mountPoint, u"sdmc", 8) == 0) + if(memcmp(launchedPath, u"sdmc", 8) == 0) { if(!mountFs(true, false)) error("Failed to mount SD."); isSdMode = true; } - else if(memcmp(mountPoint, u"nand", 8) == 0) + else if(memcmp(launchedPath, u"nand", 8) == 0) { firmSource = FIRMWARE_SYSNAND; if(!mountFs(false, true)) error("Failed to mount SD and CTRNAND."); @@ -108,11 +105,10 @@ void main(int argc, char **argv) } else { - char mount8[5] = {0}; - for(u32 i = 0 ; i < 4; i++) - mount8[i] = (char)mountPoint[i]; - - sprintf(errbuf, "Launched from an unsupported location: %s.", mount8); + char mountPoint[5] = {0}; + for(u32 i = 0; i < 4 && launchedPath[i] != u':'; i++) + mountPoint[i] = (char)launchedPath[i]; + sprintf(errbuf, "Launched from an unsupported location: %s.", mountPoint); error(errbuf); } @@ -120,19 +116,19 @@ void main(int argc, char **argv) needConfig = readConfig() ? MODIFY_CONFIGURATION : CREATE_CONFIGURATION; //Determine if this is a firmlaunch boot - if(ISFIRMLAUNCH) + if(isFirmlaunch) { if(needConfig == CREATE_CONFIGURATION) mcuPowerOff(); - switch(launchedFirmTidLow[7]) + switch(argv[1][14]) { - case u'2': - firmType = (FirmwareType)(launchedFirmTidLow[5] - u'0'); + case '2': + firmType = (FirmwareType)(argv[1][10] - '0'); break; - case u'3': + case '3': firmType = SAFE_FIRM; break; - case u'1': + case '1': firmType = SYSUPDATER_FIRM; break; } @@ -285,7 +281,7 @@ boot: else if(firmSource != FIRMWARE_SYSNAND) locateEmuNand(&emuHeader, &firmSource); - if(!ISFIRMLAUNCH) + if(!isFirmlaunch) { configData.config = (configData.config & 0xFFFFFF80) | ((u32)isNoForceFlagSet << 6) | ((u32)firmSource << 3) | (u32)nandType; writeConfig(false); diff --git a/source/patches.c b/source/patches.c index a2c8588..4f75fdd 100644 --- a/source/patches.c +++ b/source/patches.c @@ -120,10 +120,9 @@ u32 patchFirmlaunches(u8 *pos, u32 size, u32 process9MemAddr) const u8 pattern[] = {0xE2, 0x20, 0x20, 0x90}; u32 pathLen; - for(pathLen = 0; launchedPath[pathLen] != 0; pathLen++); + for(pathLen = 0; pathLen < 41 && launchedPath[pathLen] != 0; pathLen++); - if(pathLen > 82) - return 1; + if(launchedPath[pathLen] != 0) return 1; u8 *off = memsearch(pos, pattern, size, sizeof(pattern)); @@ -142,7 +141,7 @@ u32 patchFirmlaunches(u8 *pos, u32 size, u32 process9MemAddr) *pos_fopen = fOpenOffset; u16 *fname = (u16 *)memsearch(off, u"sdmc", reboot_bin_size, 8); - memcpy(fname, launchedPath, 82); + memcpy(fname, launchedPath, 2 * (1 + pathLen)); return 0; } diff --git a/source/screen.c b/source/screen.c index 12bf956..4d7f0fb 100644 --- a/source/screen.c +++ b/source/screen.c @@ -42,7 +42,7 @@ #include "i2c.h" #include "utils.h" -static vu32 *arm11Entry; +static vu32 *arm11Entry = (vu32 *)0x1FFFFFFC; static const u32 brightness[4] = {0x5F, 0x4C, 0x39, 0x26}; @@ -57,8 +57,6 @@ static void invokeArm11Function(void (*func)()) if(!hasCopiedStub) { - arm11Entry = (vu32 *)((ISSIGHAX) ? 0x1FFFFFFC : 0x1FFFFFF8); - flushDCacheRange(&arm11Entry, 4); memcpy((void *)ARM11_STUB_ADDRESS, arm11Stub, 0x2C); hasCopiedStub = true; } diff --git a/source/types.h b/source/types.h index 66ba955..8d7ef44 100644 --- a/source/types.h +++ b/source/types.h @@ -60,8 +60,6 @@ typedef volatile s64 vs64; #define ISN3DS (PDN_MPCORE_CFG == 7) #define ISDEVUNIT (CFG_UNITINFO != 0) -#define ISSIGHAX (!(CFG_SYSPROT9 & 2)) -#define ISFIRMLAUNCH (launchedFirmTidLow[5] != 0) typedef struct __attribute__((packed)) { @@ -115,4 +113,5 @@ typedef enum FirmwareType } FirmwareType; extern u16 launchedFirmTidLow[8]; -extern u16 launchedPath[7 + 255]; +extern u16 launchedPath[41]; +extern bool isFirmlaunch; diff --git a/source/utils.c b/source/utils.c index 1f2fe8f..7a283cc 100644 --- a/source/utils.c +++ b/source/utils.c @@ -89,7 +89,7 @@ u32 waitInput(bool isMenu) void mcuPowerOff(void) { - if(!ISFIRMLAUNCH && ARESCREENSINITIALIZED) clearScreens(false); + if(!isFirmlaunch && ARESCREENSINITIALIZED) clearScreens(false); //Ensure that all memory transfers have completed and that the data cache has been flushed flushEntireDCache(); @@ -106,7 +106,7 @@ void wait(u64 amount) void error(const char *message) { - if(!ISFIRMLAUNCH) + if(!isFirmlaunch) { initScreens();