Refactoring, fix bugs, move loader to itcm (without overwriting exception handlers), support for running Luma standalone

This commit is contained in:
Aurora Wright 2017-05-24 15:18:31 +02:00 committed by TuxSH
parent 0b65fcbdd7
commit 9f30244bfb
10 changed files with 163 additions and 82 deletions

View File

@ -4,11 +4,18 @@ OUTPUT_ARCH(arm)
ENTRY(_start) ENTRY(_start)
SECTIONS SECTIONS
{ {
. = 0x27FFE000; . = 0x01FF9000;
__start__ = ABSOLUTE(.);
.text : ALIGN(4) { *(.text.start) *(.text*); . = ALIGN(4); } .text : ALIGN(4) { *(.text.start) *(.text*); . = ALIGN(4); }
.rodata : ALIGN(4) { *(.rodata*); . = ALIGN(4); } .rodata : ALIGN(4) { *(.rodata*); . = ALIGN(4); }
.data : ALIGN(4) { *(.data*); . = ALIGN(8); *(.bss* COMMON); . = ALIGN(8); } .data : ALIGN(4) { *(.data*); . = ALIGN(8); *(.bss* COMMON); . = ALIGN(8); }
. = ALIGN(4); . = ALIGN(4);
__end__ = ABSOLUTE(.);
__stack_top__ = 0x01FFB800;
__stack_bottom__ = 0x01FFA800;
} }

View File

@ -27,25 +27,29 @@
void main(int argc, char **argv) void main(int argc, char **argv)
{ {
Firm *firm = (Firm *)0x20001000; Firm *firm = (Firm *)0x20001000;
char *argvPassed[2],
absPath[24 + 255];
struct fb fbs[2]; struct fb fbs[2];
char absPath[24 + 255];
if(argc == 2) if(argc > 0)
{
struct fb *fbsrc = (struct fb *)argv[1];
fbs[0] = fbsrc[0];
fbs[1] = fbsrc[1];
}
if(argc >= 1)
{ {
u32 i; u32 i;
for(i = 0; i < sizeof(absPath) - 1 && argv[0][i] != 0; i++) for(i = 0; i < sizeof(absPath) - 1 && argv[0][i] != 0; i++)
absPath[i] = argv[0][i]; absPath[i] = argv[0][i];
absPath[i] = 0; absPath[i] = 0;
argvPassed[0] = (char *)absPath;
} }
char *argvPassed[2] = {absPath, (char *)&fbs}; if(argc == 2)
{
struct fb *fbsrc = (struct fb *)argv[1];
fbs[0] = fbsrc[0];
fbs[1] = fbsrc[1];
argvPassed[1] = (char *)&fbs;
}
launchFirm(firm, argc, argvPassed); launchFirm(firm, argc, argvPassed);
} }

View File

@ -24,7 +24,7 @@
.align 4 .align 4
.global _start .global _start
_start: _start:
ldr sp, =0x27ffe000 ldr sp, =__stack_top__
b main b main
.text .text

View File

@ -324,6 +324,15 @@ static u32 fatStart;
FirmwareSource firmSource; FirmwareSource firmSource;
__attribute__((aligned(4))) static const u8 key1s[2][AES_BLOCK_SIZE] = {
{0x07, 0x29, 0x44, 0x38, 0xF8, 0xC9, 0x75, 0x93, 0xAA, 0x0E, 0x4A, 0xB4, 0xAE, 0x84, 0xC1, 0xD8},
{0xA2, 0xF4, 0x00, 0x3C, 0x7A, 0x95, 0x10, 0x25, 0xDF, 0x4E, 0x9E, 0x74, 0xE3, 0x0C, 0x92, 0x99}
},
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}
};
void ctrNandInit(void) void ctrNandInit(void)
{ {
__attribute__((aligned(4))) u8 cid[AES_BLOCK_SIZE], __attribute__((aligned(4))) u8 cid[AES_BLOCK_SIZE],
@ -335,9 +344,6 @@ void ctrNandInit(void)
if(ISN3DS) if(ISN3DS)
{ {
__attribute__((aligned(4))) u8 keyY0x5[AES_BLOCK_SIZE] = {0x4D, 0x80, 0x4F, 0x4E, 0x99, 0x90, 0x19, 0x46, 0x13, 0xA2, 0x04, 0xAC, 0x58, 0x44, 0x60, 0xBE};
aes_setkey(0x05, keyY0x5, AES_KEYY, AES_INPUT_BE | AES_INPUT_NORMAL);
nandSlot = 0x05; nandSlot = 0x05;
fatStart = 0x5CAD7; fatStart = 0x5CAD7;
} }
@ -441,6 +447,73 @@ bool decryptNusFirm(const Ticket *ticket, Cxi *cxi, u32 ncchSize)
return decryptExeFs(cxi); 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 setupKeyslots(void)
{
//Setup 0x24 KeyY
__attribute__((aligned(4))) u8 keyY0x24[AES_BLOCK_SIZE] = {0x74, 0xCA, 0x07, 0x48, 0x84, 0xF4, 0x22, 0x8D, 0xEB, 0x2A, 0x1C, 0xA7, 0x2D, 0x28, 0x77, 0x62};
aes_setkey(0x24, keyY0x24, AES_KEYY, AES_INPUT_BE | AES_INPUT_NORMAL);
//Setup 0x25 KeyX and 0x2F KeyY
__attribute__((aligned(4))) const u8 keyX0x25s[2][AES_BLOCK_SIZE] = {
{0xCE, 0xE7, 0xD8, 0xAB, 0x30, 0xC0, 0x0D, 0xAE, 0x85, 0x0E, 0xF5, 0xE3, 0x82, 0xAC, 0x5A, 0xF3},
{0x81, 0x90, 0x7A, 0x4B, 0x6F, 0x1B, 0x47, 0x32, 0x3A, 0x67, 0x79, 0x74, 0xCE, 0x4A, 0xD7, 0x1B}
},
keyY0x2Fs[2][AES_BLOCK_SIZE] = {
{0xC3, 0x69, 0xBA, 0xA2, 0x1E, 0x18, 0x8A, 0x88, 0xA9, 0xAA, 0x94, 0xE5, 0x50, 0x6A, 0x9F, 0x16},
{0x73, 0x25, 0xC4, 0xEB, 0x14, 0x3A, 0x0D, 0x5F, 0x5D, 0xB6, 0xE5, 0xC5, 0x7A, 0x21, 0x95, 0xAC}
};
aes_setkey(0x25, keyX0x25s[ISDEVUNIT ? 1 : 0], AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL);
aes_setkey(0x2F, keyY0x2Fs[ISDEVUNIT ? 1 : 0], AES_KEYY, AES_INPUT_BE | AES_INPUT_NORMAL);
if(ISN3DS)
{
//Setup 0x05 KeyY
__attribute__((aligned(4))) u8 keyY0x5[AES_BLOCK_SIZE] = {0x4D, 0x80, 0x4F, 0x4E, 0x99, 0x90, 0x19, 0x46, 0x13, 0xA2, 0x04, 0xAC, 0x58, 0x44, 0x60, 0xBE};
aes_setkey(0x05, keyY0x5, AES_KEYY, AES_INPUT_BE | AES_INPUT_NORMAL);
//Setup TWL keys
twlConsoleInfoInit();
}
__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];
//Initialize Key 0x18
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);
//Initialize Key 0x19-0x1F
aes_setkey(0x11, key2s[ISDEVUNIT ? 1 : 0], AES_KEYNORMAL, AES_INPUT_BE | AES_INPUT_NORMAL);
aes_use_keyslot(0x11);
for(u8 slot = 0x19; slot < 0x20; slot++, keyBlocks[1][0xF]++)
{
aes(decKey, keyBlocks[1], 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
@ -460,16 +533,6 @@ void kernel9Loader(Arm9Bin *arm9Section)
u32 *startOfArm9Bin = (u32 *)((u8 *)arm9Section + 0x800); u32 *startOfArm9Bin = (u32 *)((u8 *)arm9Section + 0x800);
if(*startOfArm9Bin == 0x47704770 || *startOfArm9Bin == 0xB0862000) return; //Already decrypted if(*startOfArm9Bin == 0x47704770 || *startOfArm9Bin == 0xB0862000) return; //Already decrypted
//Set 0x11 keyslot
__attribute__((aligned(4))) const u8 key1s[2][AES_BLOCK_SIZE] = {
{0x07, 0x29, 0x44, 0x38, 0xF8, 0xC9, 0x75, 0x93, 0xAA, 0x0E, 0x4A, 0xB4, 0xAE, 0x84, 0xC1, 0xD8},
{0xA2, 0xF4, 0x00, 0x3C, 0x7A, 0x95, 0x10, 0x25, 0xDF, 0x4E, 0x9E, 0x74, 0xE3, 0x0C, 0x92, 0x99}
},
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, k9lVersion == 2 ? key2s[ISDEVUNIT ? 1 : 0] : key1s[ISDEVUNIT ? 1 : 0], AES_KEYNORMAL, AES_INPUT_BE | AES_INPUT_NORMAL); aes_setkey(0x11, k9lVersion == 2 ? key2s[ISDEVUNIT ? 1 : 0] : key1s[ISDEVUNIT ? 1 : 0], AES_KEYNORMAL, AES_INPUT_BE | AES_INPUT_NORMAL);
u8 arm9BinSlot = k9lVersion == 0 ? 0x15 : 0x16; u8 arm9BinSlot = k9lVersion == 0 ? 0x15 : 0x16;

View File

@ -115,5 +115,6 @@ int ctrNandRead(u32 sector, u32 sectorCount, u8 *outbuf);
int ctrNandWrite(u32 sector, u32 sectorCount, const u8 *inbuf); int ctrNandWrite(u32 sector, u32 sectorCount, const u8 *inbuf);
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 setupKeyslots(void);
void kernel9Loader(Arm9Bin *arm9Section); void kernel9Loader(Arm9Bin *arm9Section);
void computePinHash(u8 *outbuf, const u8 *inbuf); void computePinHash(u8 *outbuf, const u8 *inbuf);

View File

@ -76,48 +76,51 @@ static inline bool loadFirmFromStorage(FirmwareType firmType)
static inline void mergeSection0(FirmwareType firmType, bool loadFromStorage) static inline void mergeSection0(FirmwareType firmType, bool loadFromStorage)
{ {
u32 maxModuleSize = firmType == NATIVE_FIRM ? 0x60000 : 0x600000, u32 srcModuleSize;
srcModuleSize;
const char *extModuleSizeError = "The external FIRM modules are too large."; const char *extModuleSizeError = "The external FIRM modules are too large.";
u32 nbModules = 0; u32 nbModules = 0,
u32 nbCustomModules = 0; isCustomModule = false;
struct struct
{ {
char name[8]; char name[8];
u8 *src; u8 *src;
u32 size; u32 size;
} moduleList[8]; } moduleList[6];
//1) Parse info concerning Nintendo's modules //1) Parse info concerning Nintendo's modules
for(u8 *src = (u8 *)firm + firm->section[0].offset, *srcEnd = src + firm->section[0].size; src < srcEnd; src += srcModuleSize) for(u8 *src = (u8 *)firm + firm->section[0].offset, *srcEnd = src + firm->section[0].size; src < srcEnd; src += srcModuleSize, nbModules++)
{ {
memcpy(moduleList[nbModules].name, ((Cxi *)src)->exHeader.systemControlInfo.appTitle, 8); memcpy(moduleList[nbModules].name, ((Cxi *)src)->exHeader.systemControlInfo.appTitle, 8);
moduleList[nbModules].src = src; moduleList[nbModules].src = src;
srcModuleSize = moduleList[nbModules++].size = ((Cxi *)src)->ncch.contentSize * 0x200; srcModuleSize = moduleList[nbModules].size = ((Cxi *)src)->ncch.contentSize * 0x200;
} }
//2) Merge that info with our own modules' if(firmType == NATIVE_FIRM)
for(u8 *src = (u8 *)0x1FF60000; src < (u8 *)(0x1FF60000 + LUMA_SECTION0_SIZE); src += srcModuleSize)
{ {
const char *name = ((Cxi *)src)->exHeader.systemControlInfo.appTitle; //2) Merge that info with our own modules'
for(u8 *src = (u8 *)0x1FF60000; src < (u8 *)(0x1FF60000 + LUMA_SECTION0_SIZE); src += srcModuleSize)
{
const char *name = ((Cxi *)src)->exHeader.systemControlInfo.appTitle;
u32 i; u32 i;
for(i = 0; i < nbModules && memcmp(name, moduleList[i].name, 8) != 0; i++); for(i = 0; i < nbModules && memcmp(name, moduleList[i].name, 8) != 0; i++);
u32 index = i < nbModules || firmType != NATIVE_FIRM ? i : nbModules + nbCustomModules++;
memcpy(moduleList[index].name, ((Cxi *)src)->exHeader.systemControlInfo.appTitle, 8); if(i == nbModules) isCustomModule = true;
moduleList[index].src = src;
srcModuleSize = moduleList[index].size = ((Cxi *)src)->ncch.contentSize * 0x200; memcpy(moduleList[i].name, ((Cxi *)src)->exHeader.systemControlInfo.appTitle, 8);
moduleList[i].src = src;
srcModuleSize = moduleList[i].size = ((Cxi *)src)->ncch.contentSize * 0x200;
}
if(isCustomModule) nbModules++;
} }
nbModules += nbCustomModules; //3) Read or copy the modules
//4) Read or copy the modules
u8 *dst = firm->section[0].address; u8 *dst = firm->section[0].address;
for(u32 i = 0; i < nbModules; i++) for(u32 i = 0, dstModuleSize; i < nbModules; i++)
{ {
const char *moduleName = moduleList[i].name; dstModuleSize = 0;
if(loadFromStorage) if(loadFromStorage)
{ {
@ -126,37 +129,33 @@ static inline void mergeSection0(FirmwareType firmType, bool loadFromStorage)
//Read modules from files if they exist //Read modules from files if they exist
sprintf(fileName, "sysmodules/%.8s.cxi", moduleList[i].name); sprintf(fileName, "sysmodules/%.8s.cxi", moduleList[i].name);
u32 dstModuleSize = getFileSize(fileName); dstModuleSize = getFileSize(fileName);
if(dstModuleSize != 0) if(dstModuleSize != 0)
{ {
if(dstModuleSize > maxModuleSize) error(extModuleSizeError); if(dstModuleSize > 0x60000) error(extModuleSizeError);
if(dstModuleSize <= sizeof(Cxi) + 0x200 || if(dstModuleSize <= sizeof(Cxi) + 0x200 ||
fileRead(dst, fileName, dstModuleSize) != dstModuleSize || fileRead(dst, fileName, dstModuleSize) != dstModuleSize ||
memcmp(((Cxi *)dst)->ncch.magic, "NCCH", 4) != 0 || memcmp(((Cxi *)dst)->ncch.magic, "NCCH", 4) != 0 ||
memcmp(moduleName, ((Cxi *)dst)->exHeader.systemControlInfo.appTitle, sizeof(((Cxi *)dst)->exHeader.systemControlInfo.appTitle)) != 0) memcmp(moduleList[i].name, ((Cxi *)dst)->exHeader.systemControlInfo.appTitle, sizeof(((Cxi *)dst)->exHeader.systemControlInfo.appTitle)) != 0)
error("An external FIRM module is invalid or corrupted."); error("An external FIRM module is invalid or corrupted.");
dst += dstModuleSize; dst += dstModuleSize;
} }
else
{
memcpy(dst, moduleList[i].src, moduleList[i].size);
dst += moduleList[i].size;
}
} }
else
if(!dstModuleSize)
{ {
memcpy(dst, moduleList[i].src, moduleList[i].size); memcpy(dst, moduleList[i].src, moduleList[i].size);
dst += moduleList[i].size; dst += moduleList[i].size;
} }
} }
//5) Patch NATIVE_FIRM if necessary //4) Patch NATIVE_FIRM if necessary
if(nbCustomModules != 0) if(isCustomModule)
{ {
if(patchK11ModuleLoading(firm->section[0].size, dst - firm->section[0].address, nbCustomModules, firm->section[1].address, firm->section[1].size) != 0) if(patchK11ModuleLoading(firm->section[0].size, dst - firm->section[0].address, firm->section[1].address, firm->section[1].size) != 0)
error("Failed to inject custom sysmodule"); error("Failed to inject custom sysmodule");
} }
} }
@ -442,7 +441,7 @@ bool checkFirmPayload(void)
if((section->offset < 0x200) || if((section->offset < 0x200) ||
(section->address + section->size < section->address) || //Overflow check (section->address + section->size < section->address) || //Overflow check
((u32)section->address & 3) || (section->offset & 0x1FF) || (section->size & 0x1FF) || //Alignment check ((u32)section->address & 3) || (section->offset & 0x1FF) || (section->size & 0x1FF) || //Alignment check
(overlaps((u32)section->address, (u32)section->address + section->size, 0x27FFE000 - 0x1000, 0x28000000)) || (overlaps((u32)section->address, (u32)section->address + section->size, 0x01FF8000, 0x01FF8000 + 0x8000)) ||
(overlaps((u32)section->address, (u32)section->address + section->size, 0x1FFFFC00, 0x20000000)) || (overlaps((u32)section->address, (u32)section->address + section->size, 0x1FFFFC00, 0x20000000)) ||
(overlaps((u32)section->address, (u32)section->address + section->size, (u32)firm + section->offset, (u32)firm + size))) (overlaps((u32)section->address, (u32)section->address + section->size, (u32)firm + section->offset, (u32)firm + size)))
return false; return false;
@ -464,7 +463,7 @@ bool checkFirmPayload(void)
void launchFirm(int argc, char **argv) void launchFirm(int argc, char **argv)
{ {
u32 *loaderAddress = (u32 *)0x27FFE000; u32 *loaderAddress = (u32 *)0x01FF9000;
prepareArm11ForFirmlaunch(); prepareArm11ForFirmlaunch();

View File

@ -68,7 +68,11 @@ void main(int argc, char **argv, u32 magicWord)
isFirmlaunch = true; isFirmlaunch = true;
} }
else else
error("Unsupported launcher or entrypoint (magic = 0x%08x, argc = %d).", magicWord, argc); {
const char argv[] = "firm0:";
for(u32 i = 0; i < sizeof(argv); i++) //Copy and convert the path to UTF-16
launchedPath[i] = argv[i];
}
if(memcmp(launchedPath, u"sdmc", 8) == 0) if(memcmp(launchedPath, u"sdmc", 8) == 0)
{ {
@ -81,6 +85,14 @@ void main(int argc, char **argv, u32 magicWord)
if(!mountFs(false, true)) error("Failed to mount CTRNAND."); if(!mountFs(false, true)) error("Failed to mount CTRNAND.");
isSdMode = false; isSdMode = false;
} }
else if(memcmp(launchedPath, u"firm", 8) == 0)
{
setupKeyslots();
if(mountFs(true, false)) isSdMode = true;
else if(mountFs(false, true)) isSdMode = false;
else error("Failed to mount SD and CTRNAND.");
}
else else
{ {
char mountPoint[5]; char mountPoint[5];

View File

@ -237,33 +237,29 @@ u32 patchCheckForDevCommonKey(u8 *pos, u32 size)
return 0; return 0;
} }
u32 patchK11ModuleLoading(u32 section0size, u32 modulesSize, u32 nbCustomModules, u8 *startPos, u32 size) u32 patchK11ModuleLoading(u32 section0size, u32 modulesSize, u8 *pos, u32 size)
{ {
const u8 moduleLoadingPattern[] = { const u8 moduleLoadingPattern[] = {0xE2, 0x05, 0x00, 0x57},
0x01, 0x70, 0x87, 0xE2, // add r7, #1 modulePidPattern[] = {0x06, 0xA0, 0xE1, 0xF2}; //GetSystemInfo
0x05, 0x00, 0x57, 0xE3, // cmp r7, #5
};
//GetSystemInfo u8 *off = memsearch(pos, moduleLoadingPattern, size, 4);
const u8 modulePidPattern[] = {
0x00, 0xF0, 0x20, 0xE3, // nop
0x05, 0x00, 0xA0, 0xE3, // mov r0, #5
};
u8 *off = memsearch(startPos, moduleLoadingPattern, size, 8);
if(off == NULL) return 1; if(off == NULL) return 1;
off[4] += nbCustomModules;
off[1]++;
u32 *off32; u32 *off32;
for(off32 = (u32 *)off; *off32 != 0xE59F0000; off32++); for(off32 = (u32 *)(off - 3); *off32 != 0xE59F0000; off32++);
off32 += 2; off32 += 2;
off32[1] = off32[0] + modulesSize; off32[1] = off32[0] + modulesSize;
for(; *off32 != section0size; off32++); for(; *off32 != section0size; off32++);
*off32 += ((modulesSize + 0x1FF) >> 9) << 9; *off32 += ((modulesSize + 0x1FF) >> 9) << 9;
off = memsearch(startPos, modulePidPattern, size, 8); off = memsearch(pos, modulePidPattern, size, 4);
if(off == NULL) return 1; if(off == NULL) return 1;
off[4] = 6;
off[0xB] = 6;
return 0; return 0;
} }

View File

@ -46,7 +46,7 @@ u32 patchOldFirmWrites(u8 *pos, u32 size);
u32 patchTitleInstallMinVersionChecks(u8 *pos, u32 size, u32 firmVersion); u32 patchTitleInstallMinVersionChecks(u8 *pos, u32 size, u32 firmVersion);
u32 patchZeroKeyNcchEncryptionCheck(u8 *pos, u32 size); u32 patchZeroKeyNcchEncryptionCheck(u8 *pos, u32 size);
u32 patchNandNcchEncryptionCheck(u8 *pos, u32 size); u32 patchNandNcchEncryptionCheck(u8 *pos, u32 size);
u32 patchK11ModuleLoading(u32 section0size, u32 modulesSize, u32 nbCustomModules, u8 *startPos, u32 size); u32 patchK11ModuleLoading(u32 section0size, u32 modulesSize, u8 *startPos, u32 size);
u32 patchCheckForDevCommonKey(u8 *pos, u32 size); u32 patchCheckForDevCommonKey(u8 *pos, u32 size);
u32 reimplementSvcBackdoor(u8 *pos, u32 *arm11SvcTable, u32 baseK11VA, u8 **freeK11Space); u32 reimplementSvcBackdoor(u8 *pos, u32 *arm11SvcTable, u32 baseK11VA, u8 **freeK11Space);
u32 stubSvcRestrictGpuDma(u8 *pos, u32 *arm11SvcTable, u32 baseK11VA); u32 stubSvcRestrictGpuDma(u8 *pos, u32 *arm11SvcTable, u32 baseK11VA);

View File

@ -38,16 +38,15 @@
#include "screen.h" #include "screen.h"
#include "config.h" #include "config.h"
#include "memory.h" #include "memory.h"
#include "cache.h"
#include "i2c.h" #include "i2c.h"
#include "utils.h" #include "utils.h"
struct fb fbs[2];
static const u32 brightness[4] = {0x5F, 0x4C, 0x39, 0x26}; static const u32 brightness[4] = {0x5F, 0x4C, 0x39, 0x26};
static volatile Arm11Operation *operation = (volatile Arm11Operation *)0x1FF80004; static volatile Arm11Operation *operation = (volatile Arm11Operation *)0x1FF80004;
struct fb fbs[2];
static void invokeArm11Function(Arm11Operation op) static void invokeArm11Function(Arm11Operation op)
{ {
while(*operation != ARM11_READY); while(*operation != ARM11_READY);