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:
Aurora 2016-07-18 16:58:29 +02:00
parent eb9c74a1ed
commit c63e46b1a9
6 changed files with 55 additions and 46 deletions

View File

@ -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,12 +294,15 @@ 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
//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);
}
}
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)();
}

View File

@ -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);

View File

@ -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;
}

View File

@ -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);

View File

@ -119,8 +119,6 @@ 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++);
@ -128,7 +126,6 @@ void reimplementSvcBackdoor(u8 *pos, u32 size)
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},

View File

@ -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);