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