Added FIRM version detection, removed firmware.bin loading unless an unsupported O3DS NATIVE_FIRM (pre-5.0) is being loaded, skip patching old unsupported O3DS AGB/TWL FIRMs, only apply 11.0 patches with 11.0 or greater
This commit is contained in:
parent
eb9c74a1ed
commit
c63e46b1a9
@ -218,18 +218,19 @@ void main(void)
|
||||
}
|
||||
}
|
||||
|
||||
loadFirm(firmType, firmType == NATIVE_FIRM && firmSource == ((updatedSys) ? FIRMWARE_SYSNAND : FIRMWARE_EMUNAND));
|
||||
u32 firmVersion = loadFirm(firmType);
|
||||
|
||||
switch(firmType)
|
||||
{
|
||||
case NATIVE_FIRM:
|
||||
patchNativeFirm(nandType, emuHeader, isA9lh);
|
||||
patchNativeFirm(firmVersion, nandType, emuHeader, isA9lh);
|
||||
break;
|
||||
case SAFE_FIRM:
|
||||
patchSafeFirm();
|
||||
break;
|
||||
default:
|
||||
patchLegacyFirm(firmType);
|
||||
//Skip patching on unsupported O3DS AGB/TWL FIRMs
|
||||
if(isN3DS || firmVersion >= (firmType == TWL_FIRM ? 0x16 : 0xB)) patchLegacyFirm(firmType);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -242,29 +243,23 @@ void main(void)
|
||||
launchFirm(firmType, isFirmlaunch);
|
||||
}
|
||||
|
||||
static inline void loadFirm(FirmwareType firmType, bool externalFirm)
|
||||
static inline u32 loadFirm(FirmwareType firmType)
|
||||
{
|
||||
section = firm->section;
|
||||
|
||||
bool externalFirmLoaded = externalFirm &&
|
||||
fileRead(firm, "/luma/firmware.bin") &&
|
||||
(((u32)section[2].address >> 8) & 0xFF) == (isN3DS ? 0x60 : 0x68);
|
||||
//Load FIRM from CTRNAND, unless it's an O3DS and we're loading a pre-5.0 NATIVE FIRM
|
||||
u32 firmVersion = firmRead(firm, (u32)firmType);
|
||||
|
||||
/* If the conditions to load the external FIRM aren't met, or reading fails, or the FIRM
|
||||
doesn't match the console, load FIRM from CTRNAND */
|
||||
if(!externalFirmLoaded)
|
||||
if(!isN3DS && firmType == NATIVE_FIRM && firmVersion < 0x25)
|
||||
{
|
||||
const char *firmFolders[4][2] = {{ "00000002", "20000002" },
|
||||
{ "00000102", "20000102" },
|
||||
{ "00000202", "20000202" },
|
||||
{ "00000003", "20000003" }};
|
||||
|
||||
firmRead(firm, firmFolders[(u32)firmType][isN3DS ? 1 : 0]);
|
||||
decryptExeFs((u8 *)firm);
|
||||
if(!fileRead(firm, "/luma/firmware.bin") || (((u32)section[2].address >> 8) & 0xFF) == (isN3DS ? 0x60 : 0x68)) mcuReboot();
|
||||
}
|
||||
else decryptExeFs((u8 *)firm);
|
||||
|
||||
return firmVersion;
|
||||
}
|
||||
|
||||
static inline void patchNativeFirm(FirmwareSource nandType, u32 emuHeader, bool isA9lh)
|
||||
static inline void patchNativeFirm(u32 firmVersion, FirmwareSource nandType, u32 emuHeader, bool isA9lh)
|
||||
{
|
||||
u8 *arm9Section = (u8 *)firm + section[2].offset;
|
||||
|
||||
@ -275,8 +270,8 @@ static inline void patchNativeFirm(FirmwareSource nandType, u32 emuHeader, bool
|
||||
firm->arm9Entry = (u8 *)0x801B01C;
|
||||
}
|
||||
|
||||
//Sets the 7.x NCCH KeyX and the 6.x gamecard save data KeyY
|
||||
else if(!isA9lh) setRSAMod0DerivedKeys();
|
||||
//Sets the 7.x NCCH KeyX and the 6.x gamecard save data KeyY on >= 6.0 O3DS FIRMs, if not using A9LH
|
||||
else if(!isA9lh && firmVersion >= 0x29) setRSAMod0DerivedKeys();
|
||||
|
||||
//Find the Process9 .code location, size and memory address
|
||||
u32 process9Size,
|
||||
@ -299,11 +294,14 @@ static inline void patchNativeFirm(FirmwareSource nandType, u32 emuHeader, bool
|
||||
//Apply firmlaunch patches, not on 9.0 FIRM as it breaks firmlaunchhax
|
||||
patchFirmlaunches(process9Offset, process9Size, process9MemAddr);
|
||||
|
||||
//Apply anti-anti-DG patches for >= 11.0 firmwares
|
||||
patchTitleInstallMinVersionCheck(process9Offset, process9Size);
|
||||
//11.0 FIRM patches
|
||||
if(firmVersion >= (isN3DS ? 0x21 : 0x52))
|
||||
{
|
||||
//Apply anti-anti-DG patches
|
||||
patchTitleInstallMinVersionCheck(process9Offset, process9Size);
|
||||
|
||||
//Does nothing if svcBackdoor is still there
|
||||
reimplementSvcBackdoor((u8 *)firm + section[1].offset, section[1].size);
|
||||
reimplementSvcBackdoor((u8 *)firm + section[1].offset, section[1].size);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void patchLegacyFirm(FirmwareType firmType)
|
||||
@ -315,7 +313,7 @@ static inline void patchLegacyFirm(FirmwareType firmType)
|
||||
firm->arm9Entry = (u8 *)0x801301C;
|
||||
}
|
||||
|
||||
applyLegacyFirmPatches((u8 *)firm, firmType, isN3DS);
|
||||
applyLegacyFirmPatches((u8 *)firm, firmType);
|
||||
}
|
||||
|
||||
static inline void patchSafeFirm(void)
|
||||
@ -369,12 +367,12 @@ static inline void launchFirm(FirmwareType firmType, bool isFirmlaunch)
|
||||
arm11 = (u32 *)0x1FFFFFF8;
|
||||
}
|
||||
|
||||
flushEntireDCache(); //Ensure that all memory transfers have completed and that the data cache has been flushed
|
||||
flushEntireICache();
|
||||
|
||||
//Set ARM11 kernel entrypoint
|
||||
*arm11 = (u32)firm->arm11Entry;
|
||||
|
||||
flushEntireDCache(); //Ensure that all memory transfers have completed and that the data cache has been flushed
|
||||
flushEntireICache();
|
||||
|
||||
//Final jump to ARM9 kernel
|
||||
((void (*)())firm->arm9Entry)();
|
||||
}
|
@ -53,8 +53,8 @@ typedef enum ConfigurationStatus
|
||||
CREATE_CONFIGURATION = 2
|
||||
} ConfigurationStatus;
|
||||
|
||||
static inline void loadFirm(FirmwareType firmType, bool externalFirm);
|
||||
static inline void patchNativeFirm(FirmwareSource nandType, u32 emuHeader, bool isA9lh);
|
||||
static inline u32 loadFirm(FirmwareType firmType);
|
||||
static inline void patchNativeFirm(u32 firmVersion, FirmwareSource nandType, u32 emuHeader, bool isA9lh);
|
||||
static inline void patchLegacyFirm(FirmwareType firmType);
|
||||
static inline void patchSafeFirm(void);
|
||||
static inline void copySection0AndInjectLoader(void);
|
||||
|
20
source/fs.c
20
source/fs.c
@ -106,14 +106,20 @@ void loadPayload(u32 pressed)
|
||||
|
||||
flushDCacheRange(loaderAddress, loader_size);
|
||||
flushICacheRange(loaderAddress, loader_size);
|
||||
|
||||
((void (*)())loaderAddress)();
|
||||
}
|
||||
}
|
||||
|
||||
void firmRead(void *dest, const char *firmFolder)
|
||||
u32 firmRead(void *dest, u32 firmType)
|
||||
{
|
||||
const char *firmFolders[4][2] = {{ "00000002", "20000002" },
|
||||
{ "00000102", "20000102" },
|
||||
{ "00000202", "20000202" },
|
||||
{ "00000003", "20000003" }};
|
||||
|
||||
char path[48] = "1:/title/00040138/00000000/content";
|
||||
memcpy(&path[18], firmFolder, 8);
|
||||
memcpy(&path[18], firmFolders[firmType][isN3DS ? 1 : 0], 8);
|
||||
|
||||
DIR dir;
|
||||
FILINFO info;
|
||||
@ -149,12 +155,16 @@ void firmRead(void *dest, const char *firmFolder)
|
||||
u32 i = 42;
|
||||
|
||||
//Convert back the .app name from integer to array
|
||||
while(id)
|
||||
u32 tempId = id;
|
||||
|
||||
while(tempId)
|
||||
{
|
||||
static const char hexDigits[] = "0123456789ABCDEF";
|
||||
path[i--] = hexDigits[id & 0xF];
|
||||
id >>= 4;
|
||||
path[i--] = hexDigits[tempId & 0xF];
|
||||
tempId >>= 4;
|
||||
}
|
||||
|
||||
fileRead(dest, path);
|
||||
|
||||
return id;
|
||||
}
|
@ -26,8 +26,10 @@
|
||||
|
||||
#define PATTERN(a) a "_*.bin"
|
||||
|
||||
extern bool isN3DS;
|
||||
|
||||
bool mountFs(void);
|
||||
u32 fileRead(void *dest, const char *path);
|
||||
void fileWrite(const void *buffer, const char *path, u32 size);
|
||||
void loadPayload(u32 pressed);
|
||||
void firmRead(void *dest, const char *firmFolder);
|
||||
u32 firmRead(void *dest, u32 firmType);
|
@ -119,15 +119,12 @@ void reimplementSvcBackdoor(u8 *pos, u32 size)
|
||||
u32 *svcTable = (u32 *)(pos + *(u32 *)(pos + 0xFFFF0008 - svcOffset - 0xFFF00000 + 8) - 0xFFF00000); //SVC handler address
|
||||
while(*svcTable) svcTable++; //Look for SVC0 (NULL)
|
||||
|
||||
if(!svcTable[0x7B])
|
||||
{
|
||||
u32 *freeSpace;
|
||||
for(freeSpace = exceptionsPage; *freeSpace != 0xFFFFFFFF; freeSpace++);
|
||||
u32 *freeSpace;
|
||||
for(freeSpace = exceptionsPage; *freeSpace != 0xFFFFFFFF; freeSpace++);
|
||||
|
||||
memcpy(freeSpace, svcBackdoor, 40);
|
||||
memcpy(freeSpace, svcBackdoor, 40);
|
||||
|
||||
svcTable[0x7B] = 0xFFFF0000 + ((u8 *)freeSpace - (u8 *)exceptionsPage);
|
||||
}
|
||||
svcTable[0x7B] = 0xFFFF0000 + ((u8 *)freeSpace - (u8 *)exceptionsPage);
|
||||
}
|
||||
|
||||
void patchTitleInstallMinVersionCheck(u8 *pos, u32 size)
|
||||
@ -136,10 +133,10 @@ void patchTitleInstallMinVersionCheck(u8 *pos, u32 size)
|
||||
|
||||
u8 *off = memsearch(pos, pattern, size, 4);
|
||||
|
||||
if(off != NULL) off[4] = 0xE0;
|
||||
off[4] = 0xE0;
|
||||
}
|
||||
|
||||
void applyLegacyFirmPatches(u8 *pos, FirmwareType firmType, bool isN3DS)
|
||||
void applyLegacyFirmPatches(u8 *pos, FirmwareType firmType)
|
||||
{
|
||||
const patchData twlPatches[] = {
|
||||
{{0x1650C0, 0x165D64}, {{ 6, 0x00, 0x20, 0x4E, 0xB0, 0x70, 0xBD }}, 0},
|
||||
|
@ -33,6 +33,8 @@ typedef struct patchData {
|
||||
u32 type;
|
||||
} patchData;
|
||||
|
||||
extern bool isN3DS;
|
||||
|
||||
u8 *getProcess9(u8 *pos, u32 size, u32 *process9Size, u32 *process9MemAddr);
|
||||
void patchSignatureChecks(u8 *pos, u32 size);
|
||||
void patchTitleInstallMinVersionCheck(u8 *pos, u32 size);
|
||||
@ -40,5 +42,5 @@ void patchFirmlaunches(u8 *pos, u32 size, u32 process9MemAddr);
|
||||
void patchFirmWrites(u8 *pos, u32 size);
|
||||
void patchFirmWriteSafe(u8 *pos, u32 size);
|
||||
void reimplementSvcBackdoor(u8 *pos, u32 size);
|
||||
void applyLegacyFirmPatches(u8 *pos, FirmwareType firmType, bool isN3DS);
|
||||
void applyLegacyFirmPatches(u8 *pos, FirmwareType firmType);
|
||||
u32 getLoader(u8 *pos, u32 *loaderSize);
|
Reference in New Issue
Block a user