Compare commits

...

7 Commits
v3.13 ... v3.14

Author SHA1 Message Date
Aurora
feff28a4fe Added multi redNAND support (thanks to @Desterly for the original commit) 2016-03-26 17:48:12 +01:00
Aurora
b3d25ce64a Better commenting 2016-03-26 17:28:47 +01:00
Aurora
0f44205959 Simplified patching, yet one memsearch less, fixed override with A+L when boot options are forced 2016-03-26 17:25:05 +01:00
Aurora
1861d556a6 Spaces and stuff
Makes things more uniform
2016-03-25 18:17:12 +01:00
Aurora
9b1df43687 Useless casts again 2016-03-25 01:58:42 +01:00
Aurora
56e0157d64 Forgot about MCU reboots 2016-03-24 17:33:32 +01:00
Aurora
d23cd5acd5 More logical this way 2016-03-24 17:24:16 +01:00
10 changed files with 90 additions and 84 deletions

View File

@@ -15,17 +15,21 @@ void getEmunandSect(u32 *off, u32 *head, u32 emuNAND){
u32 nandOffset = emuNAND == 1 ? 0 : u32 nandOffset = emuNAND == 1 ? 0 :
(nandSize > 0x200000 ? 0x400000 : 0x200000); (nandSize > 0x200000 ? 0x400000 : 0x200000);
//Check for Gateway emuNAND
if(sdmmc_sdcard_readsectors(nandOffset + nandSize, 1, temp) == 0){ if(sdmmc_sdcard_readsectors(nandOffset + nandSize, 1, temp) == 0){
if(*(u32 *)(temp + 0x100) == NCSD_MAGIC){ if(*(u32 *)(temp + 0x100) == NCSD_MAGIC){
*off = nandOffset; *off = nandOffset;
*head = nandOffset + nandSize; *head = nandOffset + nandSize;
} }
//Check for RedNAND
else if(sdmmc_sdcard_readsectors(nandOffset + 1, 1, temp) == 0){
if(*(u32 *)(temp + 0x100) == NCSD_MAGIC){
*off = nandOffset + 1;
*head = nandOffset + 1;
}
//Fallback to the first emuNAND if there's no second one //Fallback to the first emuNAND if there's no second one
else if(emuNAND == 2) getEmunandSect(off, head, 1); else if(emuNAND == 2) getEmunandSect(off, head, 1);
//Check if a RedNAND is present }
else if(sdmmc_sdcard_readsectors(1, 1, temp) == 0)
if(*(u32 *)(temp + 0x100) != NCSD_MAGIC)
*head = 0;
} }
} }
@@ -45,16 +49,16 @@ void getEmuRW(void *pos, u32 size, u32 *readOff, u32 *writeOff){
*readOff = (u32)memsearch((void *)(*writeOff - 0x1000), pattern, 0x1000, 4) - 6; *readOff = (u32)memsearch((void *)(*writeOff - 0x1000), pattern, 0x1000, 4) - 6;
} }
void *getMPU(void *pos, u32 size){ u32 *getMPU(void *pos, u32 size){
//Look for MPU pattern //Look for MPU pattern
const unsigned char pattern[] = {0x03, 0x00, 0x24, 0x00}; const unsigned char pattern[] = {0x03, 0x00, 0x24, 0x00};
return memsearch(pos, pattern, size, 4); return (u32 *)memsearch(pos, pattern, size, 4);
} }
void *getEmuCode(void *pos, u32 size, u8 *proc9Offset){ void *getEmuCode(u8 *pos, u32 size, u8 *proc9Offset){
const unsigned char pattern[] = {0x00, 0xFF, 0xFF, 0xFF}; const unsigned char pattern[] = {0x00, 0xFF, 0xFF, 0xFF};
//Looking for the last free space before Process9 //Looking for the last free space before Process9
return (u8 *)memsearch(pos, pattern, size - (size - (u32)(proc9Offset - (u8 *)pos)), 4) + 0xD; return (u8 *)memsearch(pos, pattern, size - (size - (u32)(proc9Offset - pos)), 4) + 0xD;
} }

View File

@@ -13,5 +13,5 @@
void getEmunandSect(u32 *off, u32 *head, u32 emuNAND); void getEmunandSect(u32 *off, u32 *head, u32 emuNAND);
u32 getSDMMC(void *pos, u32 size); u32 getSDMMC(void *pos, u32 size);
void getEmuRW(void *pos, u32 size, u32 *readOff, u32 *writeOff); void getEmuRW(void *pos, u32 size, u32 *readOff, u32 *writeOff);
void *getMPU(void *pos, u32 size); u32 *getMPU(void *pos, u32 size);
void *getEmuCode(void *pos, u32 size, u8 *proc9Offset); void *getEmuCode(u8 *pos, u32 size, u8 *proc9Offset);

View File

@@ -50,10 +50,13 @@ void setupCFW(void){
//Attempt to read the configuration file //Attempt to read the configuration file
const char configPath[] = "aurei/config.bin"; const char configPath[] = "aurei/config.bin";
u16 config = 0; u16 config = 0;
u32 needConfig = fileRead((u8 *)&config, configPath, 2) ? 1 : 2; u32 needConfig = fileRead(&config, configPath, 2) ? 1 : 2;
//Determine if A9LH is installed //Determine if A9LH is installed
if(a9lhBoot || (config >> 2) & 0x1){ if(a9lhBoot || (config >> 2) & 0x1){
if(pressed == SAFE_MODE)
error("Using Safe Mode would brick you, or remove A9LH!");
a9lhSetup = 1; a9lhSetup = 1;
//Check setting for > 9.2 sysNAND //Check setting for > 9.2 sysNAND
updatedSys = config & 0x1; updatedSys = config & 0x1;
@@ -81,9 +84,6 @@ void setupCFW(void){
if((pressed & BUTTON_L1) && (pressed & PAYLOAD_BUTTONS) && if((pressed & BUTTON_L1) && (pressed & PAYLOAD_BUTTONS) &&
pressed != SAFE_MODE) loadPayload(); pressed != SAFE_MODE) loadPayload();
if(a9lhSetup && pressed == SAFE_MODE)
error("Using Safe Mode would brick you, or remove A9LH!");
//If no configuration file exists or SELECT is held, load configuration menu //If no configuration file exists or SELECT is held, load configuration menu
if(needConfig == 2 || (pressed & BUTTON_SELECT)) if(needConfig == 2 || (pressed & BUTTON_SELECT))
configureCFW(configPath); configureCFW(configPath);
@@ -92,7 +92,7 @@ void setupCFW(void){
if(PDN_GPU_CNT != 0x1) loadSplash(); if(PDN_GPU_CNT != 0x1) loadSplash();
/* If L is pressed, boot 9.0 FIRM */ /* If L is pressed, boot 9.0 FIRM */
if(pressed == BUTTON_L1) mode = 0; if(pressed & BUTTON_L1) mode = 0;
/* If L or R aren't pressed on a 9.0/9.2 sysNAND, or the 9.0 FIRM is selected /* If L or R aren't pressed on a 9.0/9.2 sysNAND, or the 9.0 FIRM is selected
or R is pressed on a > 9.2 sysNAND, boot emuNAND */ or R is pressed on a > 9.2 sysNAND, boot emuNAND */
@@ -116,7 +116,7 @@ void setupCFW(void){
if(bootConfig != (config & 0xFF00)){ if(bootConfig != (config & 0xFF00)){
//Preserve user settings (first byte) //Preserve user settings (first byte)
u16 tempConfig = ((config & 0xFF) | bootConfig); u16 tempConfig = ((config & 0xFF) | bootConfig);
fileWrite((u8 *)&tempConfig, configPath, 2); fileWrite(&tempConfig, configPath, 2);
} }
} }
@@ -148,7 +148,7 @@ void loadFirm(void){
(mode ? "/aurei/firmware.bin" : "/aurei/firmware90.bin"); (mode ? "/aurei/firmware.bin" : "/aurei/firmware90.bin");
firmSize = fileSize(path); firmSize = fileSize(path);
if(!firmSize) error("aurei/firmware(90).bin doesn't exist"); if(!firmSize) error("aurei/firmware(90).bin doesn't exist");
fileRead((u8 *)firmLocation, path, firmSize); fileRead(firmLocation, path, firmSize);
} }
section = firmLocation->section; section = firmLocation->section;
@@ -165,8 +165,8 @@ void loadFirm(void){
//NAND redirection //NAND redirection
static void loadEmu(u8 *proc9Offset){ static void loadEmu(u8 *proc9Offset){
u32 emuOffset = 1, u32 emuOffset,
emuHeader = 1, emuHeader = 0,
emuRead, emuRead,
emuWrite; emuWrite;
@@ -176,7 +176,7 @@ static void loadEmu(u8 *proc9Offset){
//No emuNAND detected //No emuNAND detected
if(!emuHeader) error("No emuNAND has been detected"); if(!emuHeader) error("No emuNAND has been detected");
//Copy the emuNAND patch //Copy emuNAND code
void *emuCodeOffset = getEmuCode(arm9Section, section[2].size, proc9Offset); void *emuCodeOffset = getEmuCode(arm9Section, section[2].size, proc9Offset);
memcpy(emuCodeOffset, emunand, emunand_size); memcpy(emuCodeOffset, emunand, emunand_size);
@@ -191,17 +191,23 @@ static void loadEmu(u8 *proc9Offset){
*pos_sdmmc = getSDMMC(arm9Section, section[2].size); *pos_sdmmc = getSDMMC(arm9Section, section[2].size);
//Calculate offset for the hooks //Calculate offset for the hooks
*(u32 *)(nandRedir + 4) = (u32)emuCodeOffset - (u32)firmLocation - u32 branchOffset = (u32)emuCodeOffset - (u32)firmLocation -
section[2].offset + (u32)section[2].address; section[2].offset + (u32)section[2].address;
//Add emunand hooks //Add emunand hooks
getEmuRW(arm9Section, section[2].size, &emuRead, &emuWrite); getEmuRW(arm9Section, section[2].size, &emuRead, &emuWrite);
memcpy((void *)emuRead, nandRedir, sizeof(nandRedir)); *(u16 *)emuRead = nandRedir[0];
memcpy((void *)emuWrite, nandRedir, sizeof(nandRedir)); *((u16 *)emuRead + 1) = nandRedir[1];
*((u32 *)emuRead + 1) = branchOffset;
*(u16 *)emuWrite = nandRedir[0];
*((u16 *)emuWrite + 1) = nandRedir[1];
*((u32 *)emuWrite + 1) = branchOffset;
//Set MPU for emu code region //Set MPU for emu code region
void *mpuOffset = getMPU(arm9Section, section[2].size); u32 *mpuOffset = getMPU(arm9Section, section[2].size);
memcpy(mpuOffset, mpu, sizeof(mpu)); *mpuOffset = mpuPatch[0];
*(mpuOffset + 6) = mpuPatch[1];
*(mpuOffset + 9) = mpuPatch[2];
} }
//Patches //Patches
@@ -219,13 +225,17 @@ void patchFirm(void){
//Patch FIRM reboots, not on 9.0 FIRM as it breaks firmlaunchhax //Patch FIRM reboots, not on 9.0 FIRM as it breaks firmlaunchhax
if(mode){ if(mode){
//Read reboot code from SD //Calculate offset for the firmlaunch code
void *rebootOffset = getReboot(arm9Section, section[2].size); void *rebootOffset = getReboot(arm9Section, section[2].size);
//Calculate offset for the fOpen function
u32 fOpenOffset = getfOpen(proc9Offset, rebootOffset);
//Copy firmlaunch code
memcpy(rebootOffset, reboot, reboot_size); memcpy(rebootOffset, reboot, reboot_size);
//Calculate the fOpen offset and put it in the right location //Put the fOpen offset in the right location
u32 *pos_fopen = (u32 *)memsearch(rebootOffset, "OPEN", reboot_size, 4); u32 *pos_fopen = (u32 *)memsearch(rebootOffset, "OPEN", reboot_size, 4);
*pos_fopen = getfOpen(arm9Section, section[2].size, proc9Offset); *pos_fopen = fOpenOffset;
//Patch path for emuNAND-patched FIRM //Patch path for emuNAND-patched FIRM
if(emuNAND){ if(emuNAND){
@@ -237,8 +247,9 @@ void patchFirm(void){
if(a9lhSetup && !emuNAND){ if(a9lhSetup && !emuNAND){
//Patch FIRM partitions writes on sysNAND to protect A9LH //Patch FIRM partitions writes on sysNAND to protect A9LH
void *writeOffset = getFirmWrite(arm9Section, section[2].size); u16 *writeOffset = getFirmWrite(arm9Section, section[2].size);
memcpy(writeOffset, writeBlock, sizeof(writeBlock)); *writeOffset = writeBlock[0];
*(writeOffset + 1) = writeBlock[1];
} }
//Disable signature checks //Disable signature checks
@@ -246,8 +257,9 @@ void patchFirm(void){
sigOffset2; sigOffset2;
getSignatures(firmLocation, firmSize, &sigOffset, &sigOffset2); getSignatures(firmLocation, firmSize, &sigOffset, &sigOffset2);
memcpy((void *)sigOffset, sigPat1, sizeof(sigPat1)); *(u16 *)sigOffset = sigPatch[0];
memcpy((void *)sigOffset2, sigPat2, sizeof(sigPat2)); *(u16 *)sigOffset2 = sigPatch[0];
*((u16 *)sigOffset2 + 1) = sigPatch[1];
//Patch ARM9 entrypoint on N3DS to skip arm9loader //Patch ARM9 entrypoint on N3DS to skip arm9loader
if(console) if(console)
@@ -255,7 +267,7 @@ void patchFirm(void){
//Write patched FIRM to SD if needed //Write patched FIRM to SD if needed
if(selectedFirm) if(selectedFirm)
if(!fileWrite((u8 *)firmLocation, patchedFirms[selectedFirm - 1], firmSize)) if(!fileWrite(firmLocation, patchedFirms[selectedFirm - 1], firmSize))
error("Couldn't write the patched FIRM (no free space?)"); error("Couldn't write the patched FIRM (no free space?)");
} }

View File

@@ -14,7 +14,7 @@ u32 mountSD(void){
return 1; return 1;
} }
u32 fileRead(u8 *dest, const char *path, u32 size){ u32 fileRead(void *dest, const char *path, u32 size){
FRESULT fr; FRESULT fr;
FIL fp; FIL fp;
unsigned int br = 0; unsigned int br = 0;
@@ -29,7 +29,7 @@ u32 fileRead(u8 *dest, const char *path, u32 size){
return fr ? 0 : 1; return fr ? 0 : 1;
} }
u32 fileWrite(const u8 *buffer, const char *path, u32 size){ u32 fileWrite(const void *buffer, const char *path, u32 size){
FRESULT fr; FRESULT fr;
FIL fp; FIL fp;
unsigned int br = 0; unsigned int br = 0;

View File

@@ -9,8 +9,8 @@
#include "types.h" #include "types.h"
u32 mountSD(void); u32 mountSD(void);
u32 fileRead(u8 *dest, const char *path, u32 size); u32 fileRead(void *dest, const char *path, u32 size);
u32 fileWrite(const u8 *buffer, const char *path, u32 size); u32 fileWrite(const void *buffer, const char *path, u32 size);
u32 fileSize(const char *path); u32 fileSize(const char *path);
u32 fileExists(const char *path); u32 fileExists(const char *path);
void fileDelete(const char *path); void fileDelete(const char *path);

View File

@@ -36,8 +36,7 @@ int memcmp(const void *buf1, const void *buf2, u32 size){
} }
void *memsearch(void *start_pos, const void *search, u32 size, u32 size_search){ void *memsearch(void *start_pos, const void *search, u32 size, u32 size_search){
for(void *pos = start_pos + size - size_search; pos >= start_pos; pos--){ for(u8 *pos = (u8 *)start_pos + size - size_search; pos >= (u8 *)start_pos; pos--)
if(memcmp(pos, search, size_search) == 0) return pos; if(memcmp(pos, search, size_search) == 0) return pos;
}
return NULL; return NULL;
} }

View File

@@ -11,19 +11,13 @@
* Patches * Patches
**************************************************/ **************************************************/
const u8 mpu[0x2C] = { const u32 mpuPatch[3] = {0x00360003, 0x00200603, 0x001C0603};
0x03, 0x00, 0x36, 0x00, 0x00, 0x00, 0x10, 0x10, 0x01, 0x00, 0x00, 0x01, 0x03, 0x00, 0x36, 0x00,
0x00, 0x00, 0x00, 0x20, 0x01, 0x01, 0x01, 0x01, 0x03, 0x06, 0x20, 0x00, 0x00, 0x00, 0x00, 0x08,
0x01, 0x01, 0x01, 0x01, 0x03, 0x06, 0x1C, 0x00, 0x00, 0x00, 0x02, 0x08
};
//Branch to emunand function. To be filled in const u16 nandRedir[2] = {0x4C00, 0x47A0};
u8 nandRedir[0x08] = {0x00, 0x4C, 0xA0, 0x47, 0x00, 0x00, 0x00, 0x00};
const u8 sigPat1[2] = {0x00, 0x20}; const u16 sigPatch[2] = {0x2000, 0x4770};
const u8 sigPat2[4] = {0x00, 0x20, 0x70, 0x47};
const u8 writeBlock[4] = {0x00, 0x20, 0xC0, 0x46}; const u16 writeBlock[2] = {0x2000, 0x46C0};
/************************************************** /**************************************************
* Functions * Functions
@@ -49,22 +43,20 @@ void *getReboot(void *pos, u32 size){
return (u8 *)memsearch(pos, pattern, size, 4) - 0x10; return (u8 *)memsearch(pos, pattern, size, 4) - 0x10;
} }
u32 getfOpen(void *pos, u32 size, u8 *proc9Offset){ u32 getfOpen(u8 *proc9Offset, void *rebootOffset){
//Offset Process9 code gets loaded to in memory (defined in ExHeader) //Offset Process9 code gets loaded to in memory (defined in ExHeader)
u32 p9MemAddr = *(u32 *)(proc9Offset + 0xC); u32 p9MemAddr = *(u32 *)(proc9Offset + 0xC);
//Start of Process9 .code section (start of NCCH + ExeFS offset + ExeFS header size) //Process9 code offset (start of NCCH + ExeFS offset + ExeFS header size)
u32 p9CodeOff = (u32)(proc9Offset - 0x204) + (*(u32 *)(proc9Offset - 0x64) * 0x200) + 0x200; u32 p9CodeOff = (u32)(proc9Offset - 0x204) + (*(u32 *)(proc9Offset - 0x64) * 0x200) + 0x200;
//Calculate fOpen //Firmlaunch function offset - offset in BLX opcode (A4-16 - ARM DDI 0100E) + 1
const unsigned char pattern[] = {0xB0, 0x04, 0x98, 0x0D}; return (u32)rebootOffset + 9 - (-((*(u32 *)rebootOffset & 0x00FFFFFF) << 2) & 0xFFFFF) - p9CodeOff + p9MemAddr;
return (u32)memsearch(pos, pattern, size, 4) - 2 - p9CodeOff + p9MemAddr;
} }
void *getFirmWrite(void *pos, u32 size){ u16 *getFirmWrite(void *pos, u32 size){
//Look for FIRM writing code //Look for FIRM writing code
u8 *firmwrite = (u8 *)memsearch(pos, "exe:", size, 4); u8 *const off = (u8 *)memsearch(pos, "exe:", size, 4);
const unsigned char pattern[] = {0x00, 0x28, 0x01, 0xDA}; const unsigned char pattern[] = {0x00, 0x28, 0x01, 0xDA};
return memsearch(firmwrite - 0x100, pattern, 0x100, 4); return (u16 *)memsearch(off - 0x100, pattern, 0x100, 4);
} }

View File

@@ -11,11 +11,10 @@
/************************************************** /**************************************************
* Patches * Patches
**************************************************/ **************************************************/
const u8 mpu[0x2C]; const u32 mpuPatch[3];
u8 nandRedir[0x08]; const u16 nandRedir[2];
const u8 sigPat1[2]; const u16 sigPatch[2];
const u8 sigPat2[4]; const u16 writeBlock[2];
const u8 writeBlock[4];
/************************************************** /**************************************************
* Functions * Functions
@@ -23,5 +22,5 @@ const u8 writeBlock[4];
u8 *getProc9(void *pos, u32 size); u8 *getProc9(void *pos, u32 size);
void getSignatures(void *pos, u32 size, u32 *off, u32 *off2); void getSignatures(void *pos, u32 size, u32 *off, u32 *off2);
void *getReboot(void *pos, u32 size); void *getReboot(void *pos, u32 size);
u32 getfOpen(void *pos, u32 size, u8 *proc9Offset); u32 getfOpen(u8 *proc9Offset, void *rebootOffset);
void *getFirmWrite(void *pos, u32 size); u16 *getFirmWrite(void *pos, u32 size);

View File

@@ -63,7 +63,7 @@ void configureCFW(const char *configPath){
//Read and parse the existing configuration //Read and parse the existing configuration
u16 tempConfig = 0; u16 tempConfig = 0;
fileRead((u8 *)&tempConfig, configPath, 2); fileRead(&tempConfig, configPath, 2);
for(u32 i = 0; i < OPTIONS; i++) for(u32 i = 0; i < OPTIONS; i++)
options.enabled[i] = (tempConfig >> i) & 0x1; options.enabled[i] = (tempConfig >> i) & 0x1;
@@ -94,7 +94,7 @@ void configureCFW(const char *configPath){
//Parse and write the selected options //Parse and write the selected options
for(u32 i = 0; i < OPTIONS; i++) for(u32 i = 0; i < OPTIONS; i++)
tempConfig |= options.enabled[i] << i; tempConfig |= options.enabled[i] << i;
fileWrite((u8 *)&tempConfig, configPath, 2); fileWrite(&tempConfig, configPath, 2);
//Reboot //Reboot
i2cWriteRegister(I2C_DEV_MCU, 0x20, 1 << 2); i2cWriteRegister(I2C_DEV_MCU, 0x20, 1 << 2);