diff --git a/chainloader/source/main.c b/chainloader/source/main.c index 302a1df..e01c4ce 100644 --- a/chainloader/source/main.c +++ b/chainloader/source/main.c @@ -28,9 +28,8 @@ #include "cache.h" #include "firm.h" -void main(int argc, char **argv) +void main(int argc, char **argv, Firm *firm) { - Firm *firm = (Firm *)0x20001000; char *argvPassed[2], absPath[24 + 255]; struct fb fbs[2]; diff --git a/source/config.h b/source/config.h index 7761e47..83a1709 100644 --- a/source/config.h +++ b/source/config.h @@ -69,6 +69,8 @@ typedef enum ConfigurationStatus CREATE_CONFIGURATION } ConfigurationStatus; +extern CfgData configData; + bool readConfig(void); void writeConfig(bool isConfigOptions); void configMenu(bool oldPinStatus, u32 oldPinMode); diff --git a/source/crypto.c b/source/crypto.c index 65030d2..564b464 100755 --- a/source/crypto.c +++ b/source/crypto.c @@ -33,6 +33,7 @@ #include "crypto.h" #include "memory.h" +#include "emunand.h" #include "strings.h" #include "utils.h" #include "fatfs/sdmmc/sdmmc.h" @@ -421,12 +422,18 @@ int ctrNandWrite(u32 sector, u32 sectorCount, const u8 *inbuf) return result; } -bool decryptExeFs(Cxi *cxi) +u32 decryptExeFs(Cxi *cxi) { - if(memcmp(cxi->ncch.magic, "NCCH", 4) != 0) return false; + if(memcmp(cxi->ncch.magic, "NCCH", 4) != 0) return 0; + + if(cxi->ncch.exeFsOffset != 5) return 0; + + u8 *exeFsOffset = (u8 *)cxi + 6 * 0x200; - u8 *exeFsOffset = (u8 *)cxi + (cxi->ncch.exeFsOffset + 1) * 0x200; u32 exeFsSize = (cxi->ncch.exeFsSize - 1) * 0x200; + + if(exeFsSize > 0x400000) return 0; + __attribute__((aligned(4))) u8 ncchCtr[AES_BLOCK_SIZE] = {0}; for(u32 i = 0; i < 8; i++) @@ -438,12 +445,12 @@ bool decryptExeFs(Cxi *cxi) aes_use_keyslot(0x2C); aes(cxi, exeFsOffset, exeFsSize / AES_BLOCK_SIZE, ncchCtr, AES_CTR_MODE, AES_INPUT_BE | AES_INPUT_NORMAL); - return memcmp(cxi, "FIRM", 4) == 0; + return memcmp(cxi, "FIRM", 4) == 0 ? exeFsSize : 0; } -bool decryptNusFirm(const Ticket *ticket, Cxi *cxi, u32 ncchSize) +u32 decryptNusFirm(const Ticket *ticket, Cxi *cxi, u32 ncchSize) { - if(memcmp(ticket->sigIssuer, "Root", 4) != 0) return false; + if(memcmp(ticket->sigIssuer, "Root", 4) != 0) return 0; __attribute__((aligned(4))) static const u8 keyY0x3D[AES_BLOCK_SIZE] = {0x0C, 0x76, 0x72, 0x30, 0xF0, 0x99, 0x8F, 0x1C, 0x46, 0x82, 0x82, 0x02, 0xFA, 0xAC, 0xBE, 0x4C}; __attribute__((aligned(4))) u8 titleKey[AES_BLOCK_SIZE], diff --git a/source/crypto.h b/source/crypto.h index 63b5263..2bf4729 100755 --- a/source/crypto.h +++ b/source/crypto.h @@ -110,8 +110,6 @@ #define SHA_224_HASH_SIZE (224 / 8) #define SHA_1_HASH_SIZE (160 / 8) -extern u32 emuOffset, - emuHeader; extern FirmwareSource firmSource; void sha(void *res, const void *src, u32 size, u32 mode); @@ -119,8 +117,8 @@ void sha(void *res, const void *src, u32 size, u32 mode); int ctrNandInit(void); int ctrNandRead(u32 sector, u32 sectorCount, u8 *outbuf); int ctrNandWrite(u32 sector, u32 sectorCount, const u8 *inbuf); -bool decryptExeFs(Cxi *cxi); -bool decryptNusFirm(const Ticket *ticket, Cxi *cxi, u32 ncchSize); +u32 decryptExeFs(Cxi *cxi); +u32 decryptNusFirm(const Ticket *ticket, Cxi *cxi, u32 ncchSize); void setupKeyslots(void); void kernel9Loader(Arm9Bin *arm9Section); void computePinHash(u8 *outbuf, const u8 *inbuf); diff --git a/source/emunand.h b/source/emunand.h index 9fc4cdc..99e605a 100644 --- a/source/emunand.h +++ b/source/emunand.h @@ -34,5 +34,8 @@ #define ROUND_TO_4MB(a) (((a) + 0x2000 - 1) & (~(0x2000 - 1))) +extern u32 emuOffset, + emuHeader; + void locateEmuNand(FirmwareSource *nandType); u32 patchEmuNand(u8 *arm9Section, u32 kernel9Size, u8 *process9Offset, u32 process9Size, u8 *kernel9Address); diff --git a/source/firm.c b/source/firm.c index 7031331..e21032c 100755 --- a/source/firm.c +++ b/source/firm.c @@ -39,7 +39,74 @@ #include "fmt.h" #include "../build/bundled.h" -static inline bool loadFirmFromStorage(FirmwareType firmType) +static Firm *firm = (Firm *)0x20001000; + +static __attribute__((noinline)) bool overlaps(u32 as, u32 ae, u32 bs, u32 be) +{ + if(as <= bs && bs <= ae) + return true; + if(bs <= as && as <= be) + return true; + return false; +} + +static __attribute__((noinline)) bool inRange(u32 as, u32 ae, u32 bs, u32 be) +{ + if(as >= bs && ae <= be) + return true; + return false; +} + +static bool checkFirm(u32 payloadSize) +{ + if(memcmp(firm->magic, "FIRM", 4) != 0 || firm->arm9Entry == NULL) //Allow for the ARM11 entrypoint to be zero in which case nothing is done on the ARM11 side + return false; + + bool arm9EpFound = false, + arm11EpFound = false; + + u32 size = 0x200; + for(u32 i = 0; i < 4; i++) + size += firm->section[i].size; + + if(payloadSize < size) return false; + + for(u32 i = 0; i < 4; i++) + { + FirmSection *section = &firm->section[i]; + + //Allow empty sections + if(section->size == 0) + continue; + + if((section->offset < 0x200) || + (section->address + section->size < section->address) || //Overflow check + ((u32)section->address & 3) || (section->offset & 0x1FF) || (section->size & 0x1FF) || //Alignment check + (overlaps((u32)section->address, (u32)section->address + section->size, (u32)firm, (u32)firm + size)) || + ((!inRange((u32)section->address, (u32)section->address + section->size, 0x08000000, 0x08000000 + 0x00100000)) && + (!inRange((u32)section->address, (u32)section->address + section->size, 0x18000000, 0x18000000 + 0x00600000)) && + (!inRange((u32)section->address, (u32)section->address + section->size, 0x1FF00000, 0x1FFFFC00)) && + (!inRange((u32)section->address, (u32)section->address + section->size, 0x20000000, 0x20000000 + 0x8000000)))) + return false; + + __attribute__((aligned(4))) u8 hash[0x20]; + + sha(hash, (u8 *)firm + section->offset, section->size, SHA_256_MODE); + + if(memcmp(hash, section->hash, 0x20) != 0) + return false; + + if(firm->arm9Entry >= section->address && firm->arm9Entry < (section->address + section->size)) + arm9EpFound = true; + + if(firm->arm11Entry >= section->address && firm->arm11Entry < (section->address + section->size)) + arm11EpFound = true; + } + + return arm9EpFound && (firm->arm11Entry == NULL || arm11EpFound); +} + +static inline u32 loadFirmFromStorage(FirmwareType firmType) { const char *firmwareFiles[] = { "native.firm", @@ -58,24 +125,108 @@ static inline bool loadFirmFromStorage(FirmwareType firmType) u32 firmSize = fileRead(firm, firmType == NATIVE_FIRM1X2X ? firmwareFiles[0] : firmwareFiles[(u32)firmType], 0x400000 + sizeof(Cxi) + 0x200); - if(!firmSize) return false; + if(!firmSize) return 0; - if(firmSize <= sizeof(Cxi) + 0x200) error("The FIRM in /luma is not valid."); + static const char *extFirmError = "The external FIRM is not valid."; + + if(firmSize <= sizeof(Cxi) + 0x200) error(extFirmError); if(memcmp(firm, "FIRM", 4) != 0) { + if(firmSize <= sizeof(Cxi) + 0x400) error(extFirmError); + u8 cetk[0xA50]; - if(fileRead(cetk, firmType == NATIVE_FIRM1X2X ? cetkFiles[0] : cetkFiles[(u32)firmType], sizeof(cetk)) != sizeof(cetk) || - !decryptNusFirm((Ticket *)(cetk + 0x140), (Cxi *)firm, firmSize)) - error("The FIRM in /luma is encrypted or corrupted."); + if(fileRead(cetk, firmType == NATIVE_FIRM1X2X ? cetkFiles[0] : cetkFiles[(u32)firmType], sizeof(cetk)) != sizeof(cetk)) + error("The cetk is missing or corrupted."); + + firmSize = decryptNusFirm((Ticket *)(cetk + 0x140), (Cxi *)firm, firmSize); + + if(!firmSize) error("Unable to decrypt the external FIRM."); } + return firmSize; +} + +u32 loadNintendoFirm(FirmwareType *firmType, FirmwareSource nandType, bool loadFromStorage, bool isSafeMode) +{ + //Load FIRM from CTRNAND + u32 firmVersion = firmRead(firm, (u32)*firmType); + + if(firmVersion == 0xFFFFFFFF) error("Failed to get the CTRNAND FIRM."); + + bool mustLoadFromStorage = false; + + if(!ISN3DS && *firmType == NATIVE_FIRM && !ISDEVUNIT) + { + if(firmVersion < 0x18) + { + //We can't boot < 3.x EmuNANDs + if(nandType != FIRMWARE_SYSNAND) + error("An old unsupported EmuNAND has been detected.\nLuma3DS is unable to boot it."); + + if(isSafeMode) error("SAFE_MODE is not supported on 1.x/2.x FIRM."); + + *firmType = NATIVE_FIRM1X2X; + } + + //We can't boot a 3.x/4.x NATIVE_FIRM, load one from SD/CTRNAND + else if(firmVersion < 0x25) mustLoadFromStorage = true; + } + + bool loadedFromStorage = false; + u32 firmSize; + + if(loadFromStorage || mustLoadFromStorage) + { + u32 result = loadFirmFromStorage(*firmType); + + if(result != 0) + { + loadedFromStorage = true; + firmSize = result; + } + } + + if(!loadedFromStorage) + { + if(mustLoadFromStorage) error("An old unsupported FIRM has been detected.\nCopy an external FIRM to boot."); + firmSize = decryptExeFs((Cxi *)firm); + if(!firmSize) error("Unable to decrypt the CTRNAND FIRM."); + } + + if(!checkFirm(firmSize)) error("The %s FIRM is invalid or corrupted.", loadedFromStorage ? "external" : "CTRNAND"); + //Check that the FIRM is right for the console from the ARM9 section address if((firm->section[3].offset != 0 ? firm->section[3].address : firm->section[2].address) != (ISN3DS ? (u8 *)0x8006000 : (u8 *)0x8006800)) - error("The FIRM in /luma is not for this console."); + error("The %s FIRM is not for this console.", loadedFromStorage ? "external" : "CTRNAND"); - return true; + return loadedFromStorage || ISDEVUNIT ? 0xFFFFFFFF : firmVersion; +} + +void loadHomebrewFirm(u32 pressed) +{ + char path[10 + 255]; + + bool found = !pressed ? payloadMenu(path) : findPayload(path, pressed); + + if(!found) return; + + u32 maxPayloadSize = (u32)((u8 *)0x27FFE000 - (u8 *)firm); + + u32 payloadSize = fileRead(firm, path, maxPayloadSize); + + if(payloadSize <= 0x200 || !checkFirm(payloadSize)) error("The payload is invalid or corrupted."); + + char absPath[24 + 255]; + + if(isSdMode) sprintf(absPath, "sdmc:/luma/%s", path); + else sprintf(absPath, "nand:/rw/luma/%s", path); + + char *argv[2] = {absPath, (char *)fbs}; + initScreens(); + + launchFirm((firm->reserved2[0] & 1) ? 2 : 1, argv); } static inline void mergeSection0(FirmwareType firmType, bool loadFromStorage) @@ -163,43 +314,6 @@ static inline void mergeSection0(FirmwareType firmType, bool loadFromStorage) } } -u32 loadFirm(FirmwareType *firmType, FirmwareSource nandType, bool loadFromStorage, bool isSafeMode) -{ - //Load FIRM from CTRNAND - u32 firmVersion = firmRead(firm, (u32)*firmType); - - if(firmVersion == 0xFFFFFFFF) error("Failed to get the CTRNAND FIRM."); - - bool mustLoadFromStorage = false; - - if(!ISN3DS && *firmType == NATIVE_FIRM && !ISDEVUNIT) - { - if(firmVersion < 0x18) - { - //We can't boot < 3.x EmuNANDs - if(nandType != FIRMWARE_SYSNAND) - error("An old unsupported EmuNAND has been detected.\nLuma3DS is unable to boot it."); - - if(isSafeMode) error("SAFE_MODE is not supported on 1.x/2.x FIRM."); - - *firmType = NATIVE_FIRM1X2X; - } - - //We can't boot a 3.x/4.x NATIVE_FIRM, load one from SD/CTRNAND - else if(firmVersion < 0x25) mustLoadFromStorage = true; - } - - if((loadFromStorage || mustLoadFromStorage) && loadFirmFromStorage(*firmType)) firmVersion = 0xFFFFFFFF; - else - { - if(mustLoadFromStorage) error("An old unsupported FIRM has been detected.\nCopy a firmware.bin in /luma to boot."); - if(!decryptExeFs((Cxi *)firm)) error("The CTRNAND FIRM is corrupted."); - if(ISDEVUNIT) firmVersion = 0xFFFFFFFF; - } - - return firmVersion; -} - u32 patchNativeFirm(u32 firmVersion, FirmwareSource nandType, bool loadFromStorage, bool isSafeMode, bool doUnitinfoPatch) { u8 *arm9Section = (u8 *)firm + firm->section[2].offset, @@ -382,71 +496,6 @@ u32 patch1x2xNativeAndSafeFirm(void) return ret; } -static __attribute__((noinline)) bool overlaps(u32 as, u32 ae, u32 bs, u32 be) -{ - if(as <= bs && bs <= ae) - return true; - if(bs <= as && as <= be) - return true; - return false; -} - -static __attribute__((noinline)) bool inRange(u32 as, u32 ae, u32 bs, u32 be) -{ - if(as >= bs && ae <= be) - return true; - return false; -} - -bool checkFirmPayload(u32 payloadSize) -{ - if(memcmp(firm->magic, "FIRM", 4) != 0 || firm->arm9Entry == NULL) //Allow for the ARM11 entrypoint to be zero in which case nothing is done on the ARM11 side - return false; - - bool arm9EpFound = false, - arm11EpFound = false; - - u32 size = 0x200; - for(u32 i = 0; i < 4; i++) - size += firm->section[i].size; - - if(size != payloadSize) return false; - - for(u32 i = 0; i < 4; i++) - { - FirmSection *section = &firm->section[i]; - - //Allow empty sections - if(section->size == 0) - continue; - - if((section->offset < 0x200) || - (section->address + section->size < section->address) || //Overflow check - ((u32)section->address & 3) || (section->offset & 0x1FF) || (section->size & 0x1FF) || //Alignment check - (overlaps((u32)section->address, (u32)section->address + section->size, (u32)firm, (u32)firm + size)) || - ((!inRange((u32)section->address, (u32)section->address + section->size, 0x08000000, 0x08000000 + 0x00100000)) && - (!inRange((u32)section->address, (u32)section->address + section->size, 0x18000000, 0x18000000 + 0x00600000)) && - (!inRange((u32)section->address, (u32)section->address + section->size, 0x1FF00000, 0x1FFFFC00)) && - (!inRange((u32)section->address, (u32)section->address + section->size, 0x20000000, 0x20000000 + 0x8000000)))) - return false; - - __attribute__((aligned(4))) u8 hash[0x20]; - - sha(hash, (u8 *)firm + section->offset, section->size, SHA_256_MODE); - - if(memcmp(hash, section->hash, 0x20) != 0) - return false; - - if(firm->arm9Entry >= section->address && firm->arm9Entry < (section->address + section->size)) - arm9EpFound = true; - - if(firm->arm11Entry >= section->address && firm->arm11Entry < (section->address + section->size)) - arm11EpFound = true; - } - - return arm9EpFound && (firm->arm11Entry == NULL || arm11EpFound); -} - void launchFirm(int argc, char **argv) { u32 *chainloaderAddress = (u32 *)0x01FF9000; @@ -456,5 +505,5 @@ void launchFirm(int argc, char **argv) memcpy(chainloaderAddress, chainloader_bin, chainloader_bin_size); // No need to flush caches here, the chainloader is in ITCM - ((void (*)(int, char **, u32))chainloaderAddress)(argc, argv, 0x0000BEEF); + ((void (*)(int, char **, Firm *))chainloaderAddress)(argc, argv, firm); } diff --git a/source/firm.h b/source/firm.h index 5ef3424..f9c7d38 100644 --- a/source/firm.h +++ b/source/firm.h @@ -29,13 +29,10 @@ #include "types.h" #include "3dsheaders.h" -static Firm *const firm = (Firm *const)0x20001000; - -u32 loadFirm(FirmwareType *firmType, FirmwareSource nandType, bool loadFromStorage, bool isSafeMode); +u32 loadNintendoFirm(FirmwareType *firmType, FirmwareSource nandType, bool loadFromStorage, bool isSafeMode); +void loadHomebrewFirm(u32 pressed); u32 patchNativeFirm(u32 firmVersion, FirmwareSource nandType, bool loadFromStorage, bool isSafeMode, bool doUnitinfoPatch); u32 patchTwlFirm(u32 firmVersion, bool loadFromStorage, bool doUnitinfoPatch); u32 patchAgbFirm(bool loadFromStorage, bool doUnitinfoPatch); u32 patch1x2xNativeAndSafeFirm(void); - -bool checkFirmPayload(u32 payloadSize); void launchFirm(int argc, char **argv); diff --git a/source/fs.c b/source/fs.c index 658c75e..a251ef3 100644 --- a/source/fs.c +++ b/source/fs.c @@ -121,66 +121,44 @@ void fileDelete(const char *path) f_unlink(path); } -void loadPayload(u32 pressed, const char *payloadPath) +bool findPayload(char *path, u32 pressed) { - u32 payloadSize = 0, - maxPayloadSize = (u32)((u8 *)0x27FFE000 - (u8 *)firm); + const char *pattern; - char absPath[24 + _MAX_LFN]; - char path[10 + _MAX_LFN]; + if(pressed & BUTTON_LEFT) pattern = PATTERN("left"); + else if(pressed & BUTTON_RIGHT) pattern = PATTERN("right"); + else if(pressed & BUTTON_UP) pattern = PATTERN("up"); + else if(pressed & BUTTON_DOWN) pattern = PATTERN("down"); + else if(pressed & BUTTON_START) pattern = PATTERN("start"); + else if(pressed & BUTTON_B) pattern = PATTERN("b"); + else if(pressed & BUTTON_X) pattern = PATTERN("x"); + else if(pressed & BUTTON_Y) pattern = PATTERN("y"); + else if(pressed & BUTTON_R1) pattern = PATTERN("r"); + else if(pressed & BUTTON_A) pattern = PATTERN("a"); + else pattern = PATTERN("select"); - if(payloadPath == NULL) - { - const char *pattern; + DIR dir; + FILINFO info; + FRESULT result; - if(pressed & BUTTON_LEFT) pattern = PATTERN("left"); - else if(pressed & BUTTON_RIGHT) pattern = PATTERN("right"); - else if(pressed & BUTTON_UP) pattern = PATTERN("up"); - else if(pressed & BUTTON_DOWN) pattern = PATTERN("down"); - else if(pressed & BUTTON_START) pattern = PATTERN("start"); - else if(pressed & BUTTON_B) pattern = PATTERN("b"); - else if(pressed & BUTTON_X) pattern = PATTERN("x"); - else if(pressed & BUTTON_Y) pattern = PATTERN("y"); - else if(pressed & BUTTON_R1) pattern = PATTERN("r"); - else if(pressed & BUTTON_A) pattern = PATTERN("a"); - else pattern = PATTERN("select"); + result = f_findfirst(&dir, &info, "payloads", pattern); - DIR dir; - FILINFO info; - FRESULT result; + if(result != FR_OK) return false; - result = f_findfirst(&dir, &info, "payloads", pattern); + f_closedir(&dir); - if(result != FR_OK) return; + if(!info.fname[0]) return false; - f_closedir(&dir); + sprintf(path, "payloads/%s", info.fname); - if(!info.fname[0]) return; - - sprintf(path, "payloads/%s", info.fname); - - } - else sprintf(path, "%s", payloadPath); - - payloadSize = fileRead(firm, path, maxPayloadSize); - - if(payloadSize <= 0x200 || !checkFirmPayload(payloadSize)) return; - - if(isSdMode) sprintf(absPath, "sdmc:/luma/%s", path); - else sprintf(absPath, "nand:/rw/luma/%s", path); - - char *argv[2] = {absPath, (char *)fbs}; - initScreens(); - - launchFirm((firm->reserved2[0] & 1) ? 2 : 1, argv); + return true; } -void payloadMenu(void) +bool payloadMenu(char *path) { DIR dir; - char path[62] = "payloads"; - if(f_opendir(&dir, path) != FR_OK) return; + if(f_opendir(&dir, "payloads") != FR_OK) return false; FILINFO info; u32 payloadNum = 0; @@ -205,7 +183,7 @@ void payloadMenu(void) f_closedir(&dir); - if(!payloadNum) return; + if(!payloadNum) return false; u32 pressed = 0, selectedPayload = 0; @@ -261,12 +239,14 @@ void payloadMenu(void) if(pressed != BUTTON_START) { sprintf(path, "payloads/%s.firm", payloadList[selectedPayload]); - loadPayload(0, path); - error("The payload is too large or corrupted."); + + return true; } while(HID_PAD & MENU_BUTTONS); wait(2000ULL); + + return false; } u32 firmRead(void *dest, u32 firmType) @@ -308,7 +288,7 @@ u32 firmRead(void *dest, u32 firmType) //Complete the string with the .app name sprintf(path, "%s/%08x.app", folderPath, firmVersion); - if(fileRead(dest, path, 0x400000 + sizeof(Cxi) + 0x200) <= sizeof(Cxi) + 0x200) firmVersion = 0xFFFFFFFF; + if(fileRead(dest, path, 0x400000 + sizeof(Cxi) + 0x200) <= sizeof(Cxi) + 0x400) firmVersion = 0xFFFFFFFF; exit: return firmVersion; diff --git a/source/fs.h b/source/fs.h index 4e20a5d..c2993f7 100644 --- a/source/fs.h +++ b/source/fs.h @@ -35,7 +35,7 @@ u32 fileRead(void *dest, const char *path, u32 maxSize); u32 getFileSize(const char *path); bool fileWrite(const void *buffer, const char *path, u32 size); void fileDelete(const char *path); -void loadPayload(u32 pressed, const char *payloadPath); -void payloadMenu(void); +bool findPayload(char *path, u32 pressed); +bool payloadMenu(char *path); u32 firmRead(void *dest, u32 firmType); void findDumpFile(const char *folderPath, char *fileName); diff --git a/source/main.c b/source/main.c index cbc1d6b..02ea145 100644 --- a/source/main.c +++ b/source/main.c @@ -207,11 +207,11 @@ void main(int argc, char **argv, u32 magicWord) if((pressed & (BUTTON_START | BUTTON_L1)) == BUTTON_START) { - payloadMenu(); + loadHomebrewFirm(0); pressed = HID_PAD; } else if(((pressed & SINGLE_PAYLOAD_BUTTONS) && !(pressed & (BUTTON_L1 | BUTTON_R1 | BUTTON_A))) || - ((pressed & L_PAYLOAD_BUTTONS) && (pressed & BUTTON_L1))) loadPayload(pressed, NULL); + ((pressed & L_PAYLOAD_BUTTONS) && (pressed & BUTTON_L1))) loadHomebrewFirm(pressed); if(splashMode == 2) loadSplash(); @@ -286,7 +286,7 @@ boot: if(isSdMode && !mountFs(false, false)) error("Failed to mount CTRNAND."); bool loadFromStorage = CONFIG(LOADEXTFIRMSANDMODULES); - u32 firmVersion = loadFirm(&firmType, firmSource, loadFromStorage, isSafeMode); + u32 firmVersion = loadNintendoFirm(&firmType, firmSource, loadFromStorage, isSafeMode); bool doUnitinfoPatch = CONFIG(PATCHUNITINFO); u32 res; diff --git a/source/patches.h b/source/patches.h index 4574447..63f7f3f 100644 --- a/source/patches.h +++ b/source/patches.h @@ -37,8 +37,6 @@ #include "types.h" -extern CfgData configData; - u8 *getProcess9Info(u8 *pos, u32 size, u32 *process9Size, u32 *process9MemAddr); u32 *getKernel11Info(u8 *pos, u32 size, u32 *baseK11VA, u8 **freeK11Space, u32 **arm11SvcHandler, u32 **arm11ExceptionsPage); void installMMUHook(u8 *pos, u32 size, u8 **freeK11Space); diff --git a/source/screen.h b/source/screen.h index c697bf2..5ce60c7 100644 --- a/source/screen.h +++ b/source/screen.h @@ -63,7 +63,6 @@ typedef enum } Arm11Operation; extern struct fb fbs[2]; -extern CfgData configData; void prepareArm11ForFirmlaunch(void); void deinitScreens(void);