Refactor payload loading, fix messy externs, add safety checks to Nintendo FIRMs, fix some Nintendo FIRMs not being loaded as payloads

This commit is contained in:
Aurora Wright 2017-06-10 02:39:00 +02:00
parent 901d4992c0
commit 0c68750056
12 changed files with 218 additions and 186 deletions

View File

@ -28,9 +28,8 @@
#include "cache.h" #include "cache.h"
#include "firm.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], char *argvPassed[2],
absPath[24 + 255]; absPath[24 + 255];
struct fb fbs[2]; struct fb fbs[2];

View File

@ -69,6 +69,8 @@ typedef enum ConfigurationStatus
CREATE_CONFIGURATION CREATE_CONFIGURATION
} ConfigurationStatus; } ConfigurationStatus;
extern CfgData configData;
bool readConfig(void); bool readConfig(void);
void writeConfig(bool isConfigOptions); void writeConfig(bool isConfigOptions);
void configMenu(bool oldPinStatus, u32 oldPinMode); void configMenu(bool oldPinStatus, u32 oldPinMode);

View File

@ -33,6 +33,7 @@
#include "crypto.h" #include "crypto.h"
#include "memory.h" #include "memory.h"
#include "emunand.h"
#include "strings.h" #include "strings.h"
#include "utils.h" #include "utils.h"
#include "fatfs/sdmmc/sdmmc.h" #include "fatfs/sdmmc/sdmmc.h"
@ -421,12 +422,18 @@ int ctrNandWrite(u32 sector, u32 sectorCount, const u8 *inbuf)
return result; 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; u32 exeFsSize = (cxi->ncch.exeFsSize - 1) * 0x200;
if(exeFsSize > 0x400000) return 0;
__attribute__((aligned(4))) u8 ncchCtr[AES_BLOCK_SIZE] = {0}; __attribute__((aligned(4))) u8 ncchCtr[AES_BLOCK_SIZE] = {0};
for(u32 i = 0; i < 8; i++) for(u32 i = 0; i < 8; i++)
@ -438,12 +445,12 @@ bool decryptExeFs(Cxi *cxi)
aes_use_keyslot(0x2C); aes_use_keyslot(0x2C);
aes(cxi, exeFsOffset, exeFsSize / AES_BLOCK_SIZE, ncchCtr, AES_CTR_MODE, AES_INPUT_BE | AES_INPUT_NORMAL); 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))) 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], __attribute__((aligned(4))) u8 titleKey[AES_BLOCK_SIZE],

View File

@ -110,8 +110,6 @@
#define SHA_224_HASH_SIZE (224 / 8) #define SHA_224_HASH_SIZE (224 / 8)
#define SHA_1_HASH_SIZE (160 / 8) #define SHA_1_HASH_SIZE (160 / 8)
extern u32 emuOffset,
emuHeader;
extern FirmwareSource firmSource; extern FirmwareSource firmSource;
void sha(void *res, const void *src, u32 size, u32 mode); 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 ctrNandInit(void);
int ctrNandRead(u32 sector, u32 sectorCount, u8 *outbuf); 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); u32 decryptExeFs(Cxi *cxi);
bool decryptNusFirm(const Ticket *ticket, Cxi *cxi, u32 ncchSize); u32 decryptNusFirm(const Ticket *ticket, Cxi *cxi, u32 ncchSize);
void setupKeyslots(void); 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

@ -34,5 +34,8 @@
#define ROUND_TO_4MB(a) (((a) + 0x2000 - 1) & (~(0x2000 - 1))) #define ROUND_TO_4MB(a) (((a) + 0x2000 - 1) & (~(0x2000 - 1)))
extern u32 emuOffset,
emuHeader;
void locateEmuNand(FirmwareSource *nandType); void locateEmuNand(FirmwareSource *nandType);
u32 patchEmuNand(u8 *arm9Section, u32 kernel9Size, u8 *process9Offset, u32 process9Size, u8 *kernel9Address); u32 patchEmuNand(u8 *arm9Section, u32 kernel9Size, u8 *process9Offset, u32 process9Size, u8 *kernel9Address);

View File

@ -39,7 +39,74 @@
#include "fmt.h" #include "fmt.h"
#include "../build/bundled.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[] = { const char *firmwareFiles[] = {
"native.firm", "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); 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(memcmp(firm, "FIRM", 4) != 0)
{ {
if(firmSize <= sizeof(Cxi) + 0x400) error(extFirmError);
u8 cetk[0xA50]; u8 cetk[0xA50];
if(fileRead(cetk, firmType == NATIVE_FIRM1X2X ? cetkFiles[0] : cetkFiles[(u32)firmType], sizeof(cetk)) != sizeof(cetk) || if(fileRead(cetk, firmType == NATIVE_FIRM1X2X ? cetkFiles[0] : cetkFiles[(u32)firmType], sizeof(cetk)) != sizeof(cetk))
!decryptNusFirm((Ticket *)(cetk + 0x140), (Cxi *)firm, firmSize)) error("The cetk is missing or corrupted.");
error("The FIRM in /luma is encrypted 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 //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)) 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) 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) u32 patchNativeFirm(u32 firmVersion, FirmwareSource nandType, bool loadFromStorage, bool isSafeMode, bool doUnitinfoPatch)
{ {
u8 *arm9Section = (u8 *)firm + firm->section[2].offset, u8 *arm9Section = (u8 *)firm + firm->section[2].offset,
@ -382,71 +496,6 @@ u32 patch1x2xNativeAndSafeFirm(void)
return ret; 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) void launchFirm(int argc, char **argv)
{ {
u32 *chainloaderAddress = (u32 *)0x01FF9000; u32 *chainloaderAddress = (u32 *)0x01FF9000;
@ -456,5 +505,5 @@ void launchFirm(int argc, char **argv)
memcpy(chainloaderAddress, chainloader_bin, chainloader_bin_size); memcpy(chainloaderAddress, chainloader_bin, chainloader_bin_size);
// No need to flush caches here, the chainloader is in ITCM // 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);
} }

View File

@ -29,13 +29,10 @@
#include "types.h" #include "types.h"
#include "3dsheaders.h" #include "3dsheaders.h"
static Firm *const firm = (Firm *const)0x20001000; u32 loadNintendoFirm(FirmwareType *firmType, FirmwareSource nandType, bool loadFromStorage, bool isSafeMode);
void loadHomebrewFirm(u32 pressed);
u32 loadFirm(FirmwareType *firmType, FirmwareSource nandType, bool loadFromStorage, bool isSafeMode);
u32 patchNativeFirm(u32 firmVersion, FirmwareSource nandType, bool loadFromStorage, bool isSafeMode, bool doUnitinfoPatch); u32 patchNativeFirm(u32 firmVersion, FirmwareSource nandType, bool loadFromStorage, bool isSafeMode, bool doUnitinfoPatch);
u32 patchTwlFirm(u32 firmVersion, bool loadFromStorage, bool doUnitinfoPatch); u32 patchTwlFirm(u32 firmVersion, bool loadFromStorage, bool doUnitinfoPatch);
u32 patchAgbFirm(bool loadFromStorage, bool doUnitinfoPatch); u32 patchAgbFirm(bool loadFromStorage, bool doUnitinfoPatch);
u32 patch1x2xNativeAndSafeFirm(void); u32 patch1x2xNativeAndSafeFirm(void);
bool checkFirmPayload(u32 payloadSize);
void launchFirm(int argc, char **argv); void launchFirm(int argc, char **argv);

View File

@ -121,16 +121,8 @@ void fileDelete(const char *path)
f_unlink(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);
char absPath[24 + _MAX_LFN];
char path[10 + _MAX_LFN];
if(payloadPath == NULL)
{
const char *pattern; const char *pattern;
if(pressed & BUTTON_LEFT) pattern = PATTERN("left"); if(pressed & BUTTON_LEFT) pattern = PATTERN("left");
@ -151,36 +143,22 @@ void loadPayload(u32 pressed, const char *payloadPath)
result = f_findfirst(&dir, &info, "payloads", pattern); result = f_findfirst(&dir, &info, "payloads", pattern);
if(result != FR_OK) return; if(result != FR_OK) return false;
f_closedir(&dir); f_closedir(&dir);
if(!info.fname[0]) return; if(!info.fname[0]) return false;
sprintf(path, "payloads/%s", info.fname); sprintf(path, "payloads/%s", info.fname);
} return true;
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);
} }
void payloadMenu(void) bool payloadMenu(char *path)
{ {
DIR dir; 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; FILINFO info;
u32 payloadNum = 0; u32 payloadNum = 0;
@ -205,7 +183,7 @@ void payloadMenu(void)
f_closedir(&dir); f_closedir(&dir);
if(!payloadNum) return; if(!payloadNum) return false;
u32 pressed = 0, u32 pressed = 0,
selectedPayload = 0; selectedPayload = 0;
@ -261,12 +239,14 @@ void payloadMenu(void)
if(pressed != BUTTON_START) if(pressed != BUTTON_START)
{ {
sprintf(path, "payloads/%s.firm", payloadList[selectedPayload]); 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); while(HID_PAD & MENU_BUTTONS);
wait(2000ULL); wait(2000ULL);
return false;
} }
u32 firmRead(void *dest, u32 firmType) u32 firmRead(void *dest, u32 firmType)
@ -308,7 +288,7 @@ u32 firmRead(void *dest, u32 firmType)
//Complete the string with the .app name //Complete the string with the .app name
sprintf(path, "%s/%08x.app", folderPath, firmVersion); 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: exit:
return firmVersion; return firmVersion;

View File

@ -35,7 +35,7 @@ u32 fileRead(void *dest, const char *path, u32 maxSize);
u32 getFileSize(const char *path); u32 getFileSize(const char *path);
bool fileWrite(const void *buffer, const char *path, u32 size); bool fileWrite(const void *buffer, const char *path, u32 size);
void fileDelete(const char *path); void fileDelete(const char *path);
void loadPayload(u32 pressed, const char *payloadPath); bool findPayload(char *path, u32 pressed);
void payloadMenu(void); bool payloadMenu(char *path);
u32 firmRead(void *dest, u32 firmType); u32 firmRead(void *dest, u32 firmType);
void findDumpFile(const char *folderPath, char *fileName); void findDumpFile(const char *folderPath, char *fileName);

View File

@ -207,11 +207,11 @@ void main(int argc, char **argv, u32 magicWord)
if((pressed & (BUTTON_START | BUTTON_L1)) == BUTTON_START) if((pressed & (BUTTON_START | BUTTON_L1)) == BUTTON_START)
{ {
payloadMenu(); loadHomebrewFirm(0);
pressed = HID_PAD; pressed = HID_PAD;
} }
else if(((pressed & SINGLE_PAYLOAD_BUTTONS) && !(pressed & (BUTTON_L1 | BUTTON_R1 | BUTTON_A))) || 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(); if(splashMode == 2) loadSplash();
@ -286,7 +286,7 @@ boot:
if(isSdMode && !mountFs(false, false)) error("Failed to mount CTRNAND."); if(isSdMode && !mountFs(false, false)) error("Failed to mount CTRNAND.");
bool loadFromStorage = CONFIG(LOADEXTFIRMSANDMODULES); bool loadFromStorage = CONFIG(LOADEXTFIRMSANDMODULES);
u32 firmVersion = loadFirm(&firmType, firmSource, loadFromStorage, isSafeMode); u32 firmVersion = loadNintendoFirm(&firmType, firmSource, loadFromStorage, isSafeMode);
bool doUnitinfoPatch = CONFIG(PATCHUNITINFO); bool doUnitinfoPatch = CONFIG(PATCHUNITINFO);
u32 res; u32 res;

View File

@ -37,8 +37,6 @@
#include "types.h" #include "types.h"
extern CfgData configData;
u8 *getProcess9Info(u8 *pos, u32 size, u32 *process9Size, u32 *process9MemAddr); u8 *getProcess9Info(u8 *pos, u32 size, u32 *process9Size, u32 *process9MemAddr);
u32 *getKernel11Info(u8 *pos, u32 size, u32 *baseK11VA, u8 **freeK11Space, u32 **arm11SvcHandler, u32 **arm11ExceptionsPage); u32 *getKernel11Info(u8 *pos, u32 size, u32 *baseK11VA, u8 **freeK11Space, u32 **arm11SvcHandler, u32 **arm11ExceptionsPage);
void installMMUHook(u8 *pos, u32 size, u8 **freeK11Space); void installMMUHook(u8 *pos, u32 size, u8 **freeK11Space);

View File

@ -63,7 +63,6 @@ typedef enum
} Arm11Operation; } Arm11Operation;
extern struct fb fbs[2]; extern struct fb fbs[2];
extern CfgData configData;
void prepareArm11ForFirmlaunch(void); void prepareArm11ForFirmlaunch(void);
void deinitScreens(void); void deinitScreens(void);