Merge branch 'master' into developer

Conflicts:
	source/firm.c
	source/patches.h
This commit is contained in:
TuxSH 2016-05-11 01:32:06 +02:00
commit b4029dcd73
10 changed files with 102 additions and 20 deletions

View File

@ -364,7 +364,7 @@ void patchCode(u64 progId, u8 *code, u32 size)
0xE0, 0x1E, 0xFF, 0x2F, 0xE1, 0x01, 0x01, 0x01
};
static const u8 fpdVerPatch = 0x05;
static const u8 fpdVerPatch = 0x06;
//Allow online access to work with old friends modules
patchMemory(code, size,
@ -504,4 +504,4 @@ void patchCode(u64 progId, u8 *code, u32 size)
break;
}
}
}

View File

@ -186,6 +186,7 @@ void configureCFW(const char *configPath)
deinitScreens();
PDN_GPU_CNT = 1;
}
delay(0x1400000);
}
u64 t0 = chrono();
while(chrono() - t0 < 2 * TICKS_PER_SEC); //wait for 2s
}

View File

@ -33,14 +33,15 @@ void clearScreens(void)
memset32(fb->bottom, 0, 0x38400);
}
void loadSplash(void)
u32 loadSplash(void)
{
initScreens();
//Don't delay boot if no splash image is on the SD
if(fileRead(fb->top_left, "/luma/splash.bin") +
fileRead(fb->bottom, "/luma/splashbottom.bin"))
delay(0x1400000);
return 1;
return 0;
}
void drawCharacter(char character, int posX, int posY, u32 color)

View File

@ -19,7 +19,7 @@
#define COLOR_RED 0x0000FF
#define COLOR_BLACK 0x000000
void loadSplash(void);
u32 loadSplash(void);
void clearScreens(void);
void drawCharacter(char character, int posX, int posY, u32 color);
int drawString(const char *string, int posX, int posY, u32 color);

View File

@ -24,6 +24,8 @@ u32 config,
firmSource,
emuOffset;
u64 chronoWhenSplashLoaded = 0;
static inline void patchExceptionHandlersInstall(u8 *arm9Section)
{
static const u8 pattern[] = {
@ -69,6 +71,8 @@ void main(void)
needConfig,
newConfig,
emuHeader;
startChrono(0); //Start the chronometer. It shouldn't be reset.
//Detect the console being used
console = PDN_MPCORE_CFG == 7;
@ -189,8 +193,9 @@ void main(void)
loadPayload(pressed);
//If screens are inited or the corresponding option is set, load splash screen
if(PDN_GPU_CNT != 1 || CONFIG(8)) loadSplash();
if(PDN_GPU_CNT != 1 || CONFIG(8)) chronoWhenSplashLoaded = (u64) loadSplash();
if(chronoWhenSplashLoaded) chronoWhenSplashLoaded = chrono();
//If R is pressed, boot the non-updated NAND with the FIRM of the opposite one
if(pressed & BUTTON_R1)
{
@ -361,6 +366,7 @@ static inline void patchNativeFirm(u32 nandType, u32 emuHeader, u32 a9lhMode)
patchKernelFCRAMAndVRAMMappingPermissions(arm11Section1);
}
reimplementSvcBackdoor(arm11Section1); //Does nothing if svcBackdoor is still there
//Replace the FIRM loader with the injector while copying section0
copySection0AndInjectLoader();
}
@ -420,6 +426,41 @@ static inline void patchReboots(u8 *arm9Section, u8 *proc9Offset)
*pos_fopen = fOpenOffset;
}
static inline void reimplementSvcBackdoor(u8 *arm11Section1)
{
u32 *exceptionsPage = getExceptionVectorsPage(arm11Section1, section[1].size);
if(exceptionsPage == NULL) return;
u32 low24 = (exceptionsPage[2] & 0x00FFFFFF) << 2;
u32 signMask = (u32)(-(low24 >> 25)) & 0xFC000000; //Sign extension
int offset = (int)(low24 | signMask) + 8; //Branch offset + 8 for prefetch
u32* svcTable = (u32 *)(arm11Section1 + *(u32 *)(arm11Section1 + 0xFFFF0008 + offset - 0xFFF00000 + 8) - 0xFFF00000); //svc handler address
while(*svcTable != 0) svcTable++; //svc0 = NULL
if(svcTable[0x7B] != 0) return;
u32 *freeSpace = exceptionsPage;
while(freeSpace < exceptionsPage + 0x400 - 0xA && (freeSpace[0] != 0xFFFFFFFF || freeSpace[1] != 0xFFFFFFFF))
freeSpace++;
if(freeSpace >= exceptionsPage + 0x400 - 0xA) return;
//Official implementation of svcBackdoor
freeSpace[0] = 0xE3CD10FF; //bic r1, sp, #0xff
freeSpace[1] = 0xE3811C0F; //orr r1, r1, #0xf00
freeSpace[2] = 0xE2811028; //add r1, r1, #0x28
freeSpace[3] = 0xE5912000; //ldr r2, [r1]
freeSpace[4] = 0xE9226000; //stmdb r2!, {sp, lr}
freeSpace[5] = 0xE1A0D002; //mov sp, r2
freeSpace[6] = 0xE12FFF30; //blx r0
freeSpace[7] = 0xE8BD0003; //pop {r0, r1}
freeSpace[8] = 0xE1A0D000; //mov sp, r0
freeSpace[9] = 0xE12FFF11; //bx r1
svcTable[0x7B] = 0xFFFF0000 + ((u8 *)freeSpace - (u8 *) exceptionsPage);
}
static inline void copySection0AndInjectLoader(void)
{
u8 *arm11Section0 = (u8 *)firm + section[0].offset;
@ -516,6 +557,9 @@ static inline void launchFirm(u32 firstSectionToCopy, u32 bootType)
for(u32 i = firstSectionToCopy; i < 4 && section[i].size; i++)
memcpy(section[i].address, (u8 *)firm + section[i].offset, section[i].size);
while(chronoWhenSplashLoaded && chrono() - chronoWhenSplashLoaded < 3 * TICKS_PER_SEC);
stopChrono();
//Determine the ARM11 entry to use
vu32 *arm11;
if(bootType) arm11 = (u32 *)0x1FFFFFFC;
@ -530,4 +574,4 @@ static inline void launchFirm(u32 firstSectionToCopy, u32 bootType)
//Final jump to ARM9 kernel
((void (*)())firm->arm9Entry)();
}
}

View File

@ -41,6 +41,7 @@ static inline void loadFirm(u32 firmType, u32 externalFirm);
static inline void patchNativeFirm(u32 nandType, u32 emuHeader, u32 a9lhMode);
static inline void patchEmuNAND(u8 *arm9Section, u8 *proc9Offset, u32 emuHeader);
static inline void patchReboots(u8 *arm9Section, u8 *proc9Offset);
static inline void reimplementSvcBackdoor(u8 *arm11Section1);
static inline void copySection0AndInjectLoader(void);
static inline void patchLegacyFirm(u32 firmType);
static inline void patchSafeFirm(void);

View File

@ -97,4 +97,11 @@ u32 getLoader(u8 *pos, u32 *loaderSize)
*loaderSize = size;
return (u32)(off - pos);
}
}
u32* getExceptionVectorsPage(u8 *pos, u32 size)
{
const u8 pattern[] = {0x00,0xB0,0x9C,0xE5,0x0A,0xB0,0x0B,0xE0,0x0A,0x00,0x5B,0xE1,0xFB,0xFF,0xFF,0x1A};
return (u32 *)(memsearch(pos, pattern, size, 16) - 0x2C);
}

View File

@ -26,4 +26,6 @@ u32 getfOpen(u8 *proc9Offset, void *rebootOffset);
u16 *getFirmWrite(u8 *pos, u32 size);
u16 *getFirmWriteSafe(u8 *pos, u32 size);
u8 *getUnitInfoValueSet(u8 *pos, u32 size);
u32 getLoader(u8 *pos, u32 *loaderSize);
u32 getLoader(u8 *pos, u32 *loaderSize);
u32* getExceptionVectorsPage(u8 *pos, u32 size); //Multi-purpose, don't change

View File

@ -33,13 +33,34 @@ u32 waitInput(void)
return key;
}
void delay(u64 length)
{
while(length--) __asm("mov r0, r0");
}
void mcuReboot(void)
{
i2cWriteRegister(I2C_DEV_MCU, 0x20, 1 << 2);
while(1);
}
//TODO: add support for TIMER IRQ
void startChrono(u64 initialTicks)
{
//Based on a NATIVE_FIRM disassembly
*(vu16 *)(0x10003002 + 4 * 0) = 0; //67MHz
for(u32 i = 1; i < 4; i++) *(vu16 *)(0x10003002 + 4 * i) = 4; //Count-up
for(u32 i = 0; i < 4; i++) *(vu16 *)(0x10003000 + 4 * i) = (u16)(initialTicks >> (16 * i));
*(vu16 *)(0x10003002 + 4 * 0) = 0x80; //67MHz; enabled
for(u32 i = 1; i < 4; i++) *(vu16 *)(0x10003002 + 4 * i) = 0x84; //Count-up; enabled
}
u64 chrono(void)
{
u64 res = 0;
for(u32 i = 0; i < 4; i++) res |= *(vu16 *)(0x10003000 + 4 * i) << (16 * i);
return res;
}
void stopChrono(void)
{
for(u32 i = 1; i < 4; i++) *(vu16 *)(0x10003002 + 4 * i) &= ~0x80;
}

View File

@ -7,5 +7,10 @@
#include "types.h"
u32 waitInput(void);
void delay(u64 length);
void mcuReboot(void);
void mcuReboot(void);
#define TICKS_PER_SEC 67027964ULL
void startChrono(u64 initialTicks);
u64 chrono(void);
void stopChrono(void);