Merge from master, fix derp, cleanup
This commit is contained in:
commit
477414a636
2
Makefile
2
Makefile
@ -28,7 +28,7 @@ dir_out := out
|
|||||||
ASFLAGS := -mcpu=arm946e-s
|
ASFLAGS := -mcpu=arm946e-s
|
||||||
CFLAGS := -Wall -Wextra -MMD -MP -marm $(ASFLAGS) -fno-builtin -fshort-wchar -std=c11 -Wno-main -O2 -flto -ffast-math
|
CFLAGS := -Wall -Wextra -MMD -MP -marm $(ASFLAGS) -fno-builtin -fshort-wchar -std=c11 -Wno-main -O2 -flto -ffast-math
|
||||||
LDFLAGS := -nostartfiles
|
LDFLAGS := -nostartfiles
|
||||||
FLAGS := name=$(name).dat dir_out=$(abspath $(dir_out)) ICON=$(abspath icon.png) APP_DESCRIPTION="Noob-friendly 3DS CFW." APP_AUTHOR="Aurora Wright" --no-print-directory
|
FLAGS := name=$(name).dat dir_out=$(abspath $(dir_out)) ICON=$(abspath icon.png) APP_DESCRIPTION="Noob-friendly 3DS CFW." APP_AUTHOR="Aurora Wright/TuxSH" --no-print-directory
|
||||||
|
|
||||||
objects = $(patsubst $(dir_source)/%.s, $(dir_build)/%.o, \
|
objects = $(patsubst $(dir_source)/%.s, $(dir_build)/%.o, \
|
||||||
$(patsubst $(dir_source)/%.c, $(dir_build)/%.o, \
|
$(patsubst $(dir_source)/%.c, $(dir_build)/%.o, \
|
||||||
|
@ -476,13 +476,13 @@ void patchCode(u64 progId, u8 *code, u32 size)
|
|||||||
case 0x0004013000003702LL: // RO
|
case 0x0004013000003702LL: // RO
|
||||||
{
|
{
|
||||||
static const u8 sigCheckPattern[] = {
|
static const u8 sigCheckPattern[] = {
|
||||||
0x30, 0x40, 0x2D, 0xE9, 0x02, 0x50, 0xA0, 0xE1
|
0x30, 0x40, 0x2D, 0xE9, 0x02
|
||||||
};
|
};
|
||||||
static const u8 sha256ChecksPattern1[] = {
|
static const u8 sha256ChecksPattern1[] = {
|
||||||
0x30, 0x40, 0x2D, 0xE9, 0x24, 0xD0, 0x4D, 0xE2
|
0x30, 0x40, 0x2D, 0xE9, 0x24
|
||||||
};
|
};
|
||||||
static const u8 sha256ChecksPattern2[] = {
|
static const u8 sha256ChecksPattern2[] = {
|
||||||
0xF8, 0x4F, 0x2D, 0xE9, 0x01, 0x70, 0xA0, 0xE1
|
0xF8, 0x4F, 0x2D, 0xE9, 0x01
|
||||||
};
|
};
|
||||||
|
|
||||||
static const u8 stub[] = {
|
static const u8 stub[] = {
|
||||||
|
@ -22,7 +22,6 @@
|
|||||||
#define BUTTON_DOWN (1 << 7)
|
#define BUTTON_DOWN (1 << 7)
|
||||||
|
|
||||||
#define SAFE_MODE (BUTTON_R1 | BUTTON_L1 | BUTTON_A | BUTTON_UP)
|
#define SAFE_MODE (BUTTON_R1 | BUTTON_L1 | BUTTON_A | BUTTON_UP)
|
||||||
#define OVERRIDE_BUTTONS (BUTTON_B ^ 0xFFF)
|
|
||||||
#define SINGLE_PAYLOAD_BUTTONS (BUTTON_LEFT | BUTTON_RIGHT | BUTTON_UP | BUTTON_DOWN | BUTTON_START | BUTTON_X | BUTTON_Y)
|
#define SINGLE_PAYLOAD_BUTTONS (BUTTON_LEFT | BUTTON_RIGHT | BUTTON_UP | BUTTON_DOWN | BUTTON_START | BUTTON_X | BUTTON_Y)
|
||||||
#define L_PAYLOAD_BUTTONS (BUTTON_R1 | BUTTON_A | BUTTON_SELECT)
|
#define L_PAYLOAD_BUTTONS (BUTTON_R1 | BUTTON_A | BUTTON_SELECT)
|
||||||
#define MENU_BUTTONS (BUTTON_LEFT | BUTTON_RIGHT | BUTTON_UP | BUTTON_DOWN | BUTTON_A | BUTTON_START)
|
#define MENU_BUTTONS (BUTTON_LEFT | BUTTON_RIGHT | BUTTON_UP | BUTTON_DOWN | BUTTON_A | BUTTON_START)
|
@ -64,8 +64,8 @@ static inline void patchNANDRW(u8 *pos, u32 size, u32 branchOffset)
|
|||||||
//Look for read/write code
|
//Look for read/write code
|
||||||
const u8 pattern[] = {0x1E, 0x00, 0xC8, 0x05};
|
const u8 pattern[] = {0x1E, 0x00, 0xC8, 0x05};
|
||||||
|
|
||||||
u16 *readOffset = (u16 *)memsearch(pos, pattern, size, 4) - 3;
|
u16 *readOffset = (u16 *)memsearch(pos, pattern, size, 4) - 3,
|
||||||
u16 *writeOffset = (u16 *)memsearch((u8 *)(readOffset + 5), pattern, 0x100, 4) - 3;
|
*writeOffset = (u16 *)memsearch((u8 *)(readOffset + 5), pattern, 0x100, 4) - 3;
|
||||||
|
|
||||||
*readOffset = nandRedir[0];
|
*readOffset = nandRedir[0];
|
||||||
readOffset[1] = nandRedir[1];
|
readOffset[1] = nandRedir[1];
|
||||||
@ -96,8 +96,8 @@ void patchEmuNAND(u8 *arm9Section, u32 arm9SectionSize, u8 *process9Offset, u32
|
|||||||
memcpy(emuCodeOffset, emunand, emunand_size);
|
memcpy(emuCodeOffset, emunand, emunand_size);
|
||||||
|
|
||||||
//Add the data of the found emuNAND
|
//Add the data of the found emuNAND
|
||||||
u32 *pos_offset = (u32 *)memsearch(emuCodeOffset, "NAND", emunand_size, 4);
|
u32 *pos_offset = (u32 *)memsearch(emuCodeOffset, "NAND", emunand_size, 4),
|
||||||
u32 *pos_header = (u32 *)memsearch(emuCodeOffset, "NCSD", emunand_size, 4);
|
*pos_header = (u32 *)memsearch(emuCodeOffset, "NCSD", emunand_size, 4);
|
||||||
*pos_offset = emuOffset;
|
*pos_offset = emuOffset;
|
||||||
*pos_header = emuHeader;
|
*pos_header = emuHeader;
|
||||||
|
|
||||||
|
@ -122,29 +122,29 @@ void main(void)
|
|||||||
{
|
{
|
||||||
nandType = 0;
|
nandType = 0;
|
||||||
firmSource = updatedSys ? 0 : BOOTCONFIG(2, 1);
|
firmSource = updatedSys ? 0 : BOOTCONFIG(2, 1);
|
||||||
needConfig--;
|
needConfig = 0;
|
||||||
|
|
||||||
//Flag to prevent multiple boot options-forcing
|
//Flag to prevent multiple boot options-forcing
|
||||||
newConfig |= 1 << 4;
|
newConfig |= 1 << 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Else, force the last used boot options unless a payload button or A/L/R are pressed
|
/* Else, force the last used boot options unless a button is pressed
|
||||||
or the no-forcing flag is set */
|
or the no-forcing flag is set */
|
||||||
else if(!(pressed & OVERRIDE_BUTTONS) && !BOOTCONFIG(4, 1))
|
else if(!pressed && !BOOTCONFIG(4, 1))
|
||||||
{
|
{
|
||||||
nandType = BOOTCONFIG(0, 3);
|
nandType = BOOTCONFIG(0, 3);
|
||||||
firmSource = BOOTCONFIG(2, 1);
|
firmSource = BOOTCONFIG(2, 1);
|
||||||
needConfig--;
|
needConfig = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//If the SAFE MODE combo is held, force a sysNAND boot
|
//If the SAFE MODE combo is held, force a sysNAND boot
|
||||||
else if(pressed == SAFE_MODE)
|
else if(pressed == SAFE_MODE)
|
||||||
{
|
{
|
||||||
a9lhMode++;
|
a9lhMode = 2;
|
||||||
nandType = 0;
|
nandType = 0;
|
||||||
firmSource = 0;
|
firmSource = 0;
|
||||||
needConfig--;
|
needConfig = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -180,7 +180,7 @@ void main(void)
|
|||||||
|
|
||||||
/* If we're booting emuNAND the second emuNAND is set as default and B isn't pressed,
|
/* If we're booting emuNAND the second emuNAND is set as default and B isn't pressed,
|
||||||
or vice-versa, boot the second emuNAND */
|
or vice-versa, boot the second emuNAND */
|
||||||
if(nandType && (CONFIG(3) == !(pressed & BUTTON_B))) nandType++;
|
if(nandType && (CONFIG(3) == !(pressed & BUTTON_B))) nandType = 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -260,7 +260,8 @@ static inline void loadFirm(u32 firmType, u32 externalFirm)
|
|||||||
|
|
||||||
static inline void patchNativeFirm(u32 nandType, u32 emuHeader, u32 a9lhMode)
|
static inline void patchNativeFirm(u32 nandType, u32 emuHeader, u32 a9lhMode)
|
||||||
{
|
{
|
||||||
u8 *arm9Section = (u8 *)firm + section[2].offset;
|
u8 *arm9Section = (u8 *)firm + section[2].offset,
|
||||||
|
*arm11Section1 = (u8 *)firm + section[1].offset;
|
||||||
|
|
||||||
u32 nativeFirmType;
|
u32 nativeFirmType;
|
||||||
|
|
||||||
@ -299,9 +300,6 @@ static inline void patchNativeFirm(u32 nandType, u32 emuHeader, u32 a9lhMode)
|
|||||||
//Apply signature patches
|
//Apply signature patches
|
||||||
patchSignatureChecks(process9Offset, process9Size);
|
patchSignatureChecks(process9Offset, process9Size);
|
||||||
|
|
||||||
//Apply anti-anti-DG patches for >= 11.0 firmwares
|
|
||||||
if(nativeFirmType == 1) patchTitleInstallMinVersionCheck(process9Offset, process9Size);
|
|
||||||
|
|
||||||
//Apply emuNAND patches
|
//Apply emuNAND patches
|
||||||
if(nandType)
|
if(nandType)
|
||||||
{
|
{
|
||||||
@ -315,8 +313,14 @@ static inline void patchNativeFirm(u32 nandType, u32 emuHeader, u32 a9lhMode)
|
|||||||
//Apply firmlaunch patches, not on 9.0 FIRM as it breaks firmlaunchhax
|
//Apply firmlaunch patches, not on 9.0 FIRM as it breaks firmlaunchhax
|
||||||
if(nativeFirmType || a9lhMode == 2) patchFirmlaunches(process9Offset, process9Size, process9MemAddr);
|
if(nativeFirmType || a9lhMode == 2) patchFirmlaunches(process9Offset, process9Size, process9MemAddr);
|
||||||
|
|
||||||
|
if(nativeFirmType == 1)
|
||||||
|
{
|
||||||
|
//Apply anti-anti-DG patches for >= 11.0 firmwares
|
||||||
|
patchTitleInstallMinVersionCheck(process9Offset, process9Size);
|
||||||
|
|
||||||
//Does nothing if svcBackdoor is still there
|
//Does nothing if svcBackdoor is still there
|
||||||
if(nativeFirmType == 1) reimplementSvcBackdoor((u8 *)firm + section[1].offset, section[1].size);
|
reimplementSvcBackdoor(arm11Section1, section[1].size);
|
||||||
|
}
|
||||||
|
|
||||||
if(DEVMODE)
|
if(DEVMODE)
|
||||||
{
|
{
|
||||||
@ -324,7 +328,7 @@ static inline void patchNativeFirm(u32 nandType, u32 emuHeader, u32 a9lhMode)
|
|||||||
patchUnitInfoValueSet(arm9Section, section[2].size);
|
patchUnitInfoValueSet(arm9Section, section[2].size);
|
||||||
|
|
||||||
//Make FCRAM (and VRAM as a side effect) globally executable from arm11 kernel
|
//Make FCRAM (and VRAM as a side effect) globally executable from arm11 kernel
|
||||||
patchKernelFCRAMAndVRAMMappingPermissions(arm9Section, section[2].size);
|
patchKernelFCRAMAndVRAMMappingPermissions(arm11Section1, section[1].size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,18 +34,9 @@ void patchSignatureChecks(u8 *pos, u32 size)
|
|||||||
off2[1] = sigPatch[1];
|
off2[1] = sigPatch[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
void patchTitleInstallMinVersionCheck(u8 *pos, u32 size)
|
|
||||||
{
|
|
||||||
const u8 pattern[] = {0x89, 0x0A, 0x81, 0x42, 0x02, 0xD2};
|
|
||||||
|
|
||||||
u8 *off = memsearch(pos, pattern, size, 6);
|
|
||||||
|
|
||||||
if(off != NULL) off[5] = 0xE0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void patchFirmlaunches(u8 *pos, u32 size, u32 process9MemAddr)
|
void patchFirmlaunches(u8 *pos, u32 size, u32 process9MemAddr)
|
||||||
{
|
{
|
||||||
//Look for FIRM reboot code
|
//Look for firmlaunch code
|
||||||
const u8 pattern[] = {0xDE, 0x1F, 0x8D, 0xE2};
|
const u8 pattern[] = {0xDE, 0x1F, 0x8D, 0xE2};
|
||||||
|
|
||||||
u8 *off = memsearch(pos, pattern, size, 4) - 0x10;
|
u8 *off = memsearch(pos, pattern, size, 4) - 0x10;
|
||||||
@ -90,33 +81,27 @@ void patchFirmWriteSafe(u8 *pos, u32 size)
|
|||||||
|
|
||||||
void patchExceptionHandlersInstall(u8 *pos, u32 size)
|
void patchExceptionHandlersInstall(u8 *pos, u32 size)
|
||||||
{
|
{
|
||||||
static const u8 pattern[] = {
|
const u8 pattern[] = {0x50, 0x50, 0x9F, 0xE5};
|
||||||
0x18, 0x10, 0x80, 0xE5,
|
|
||||||
0x10, 0x10, 0x80, 0xE5,
|
|
||||||
0x20, 0x10, 0x80, 0xE5,
|
|
||||||
0x28, 0x10, 0x80, 0xE5,
|
|
||||||
}; //i.e when it stores ldr pc, [pc, #-4]
|
|
||||||
|
|
||||||
u32* off = (u32 *)(memsearch(pos, pattern, size, sizeof(pattern)));
|
u32 *off = (u32 *)memsearch(pos, pattern, size, 4) - 1;
|
||||||
if(off == NULL) return;
|
|
||||||
off += sizeof(pattern)/4;
|
|
||||||
|
|
||||||
u32 r0 = 0x08000000;
|
u32 r0 = 0x08000000;
|
||||||
|
|
||||||
for(; *off != 0xE3A01040; off++) //until mov r1, #0x40
|
for(; *off != 0xE3A01040; off++) //Until mov r1, #0x40
|
||||||
{
|
{
|
||||||
if((*off >> 26) != 0x39 || ((*off >> 16) & 0xf) != 0 || ((*off >> 25) & 1) != 0 || ((*off >> 20) & 5) != 0)
|
if((*off >> 26) != 0x39 || ((*off >> 16) & 0xF) != 0 || ((*off >> 25) & 1) != 0 || ((*off >> 20) & 5) != 0)
|
||||||
continue; //discard everything that's not str rX, [r0, #imm](!)
|
continue; //Discard everything that's not str rX, [r0, #imm](!)
|
||||||
|
|
||||||
int rD = (*off >> 12) & 0xf;
|
int rD = (*off >> 12) & 0xF,
|
||||||
int offset = (*off & 0xfff) * ((((*off >> 23) & 1) == 0) ? -1 : 1);
|
offset = (*off & 0xFFF) * ((((*off >> 23) & 1) == 0) ? -1 : 1),
|
||||||
int writeback = (*off >> 21) & 1, pre = (*off >> 24) & 1;
|
writeback = (*off >> 21) & 1,
|
||||||
|
pre = (*off >> 24) & 1;
|
||||||
|
|
||||||
u32 addr = r0 + ((pre || !writeback) ? offset : 0);
|
u32 addr = r0 + ((pre || !writeback) ? offset : 0);
|
||||||
if(addr != 0x08000014 && addr != 0x08000004)
|
if(addr != 0x08000014 && addr != 0x08000004)
|
||||||
*off = 0xE1A00000; //nop
|
*off = 0xE1A00000; //nop
|
||||||
else
|
else
|
||||||
*off = 0xE5800000 | (rD << 12) | (addr & 0xfff); //preserve IRQ and svc handlers
|
*off = 0xE5800000 | (rD << 12) | (addr & 0xFFF); //Preserve IRQ and SVC handlers
|
||||||
|
|
||||||
if(!pre) addr += offset;
|
if(!pre) addr += offset;
|
||||||
if(writeback) r0 = addr;
|
if(writeback) r0 = addr;
|
||||||
@ -129,20 +114,18 @@ void patchUnitInfoValueSet(u8 *pos, u32 size)
|
|||||||
const u8 pattern[] = {0x01, 0x10, 0xA0, 0x13};
|
const u8 pattern[] = {0x01, 0x10, 0xA0, 0x13};
|
||||||
|
|
||||||
u8 *off = memsearch(pos, pattern, size, 4);
|
u8 *off = memsearch(pos, pattern, size, 4);
|
||||||
if(off != NULL) off[3] = 0xE3;
|
|
||||||
|
off[3] = 0xE3;
|
||||||
}
|
}
|
||||||
|
|
||||||
void patchKernelFCRAMAndVRAMMappingPermissions(u8 *pos, u32 size)
|
void patchKernelFCRAMAndVRAMMappingPermissions(u8 *pos, u32 size)
|
||||||
{
|
{
|
||||||
static const u8 MMUConfigPattern[] = {
|
//Look for MMU config
|
||||||
0xC4, 0xDD, 0xFA, 0x1F,
|
const u8 pattern[] = {0xC4, 0xDD, 0xFA, 0x1F};
|
||||||
0x16, 0x64, 0x01, 0x00,
|
|
||||||
0xBC, 0xDD, 0xFA, 0x1F,
|
|
||||||
0x00, 0x50, 0xFF, 0x1F
|
|
||||||
};
|
|
||||||
|
|
||||||
u32* off = (u32 *)memsearch(pos, MMUConfigPattern, size, sizeof(MMUConfigPattern));
|
u32* off = (u32 *)memsearch(pos, pattern, size, 4);
|
||||||
if(off != NULL) off[1] &= ~(1 << 4); //clear XN bit
|
|
||||||
|
if(off != NULL) off[1] &= ~(1 << 4); //Clear XN bit
|
||||||
}
|
}
|
||||||
|
|
||||||
void reimplementSvcBackdoor(u8 *pos, u32 size)
|
void reimplementSvcBackdoor(u8 *pos, u32 size)
|
||||||
@ -178,6 +161,15 @@ void reimplementSvcBackdoor(u8 *pos, u32 size)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void patchTitleInstallMinVersionCheck(u8 *pos, u32 size)
|
||||||
|
{
|
||||||
|
const u8 pattern[] = {0x0A, 0x81, 0x42, 0x02};
|
||||||
|
|
||||||
|
u8 *off = memsearch(pos, pattern, size, 4);
|
||||||
|
|
||||||
|
if(off != NULL) off[4] = 0xE0;
|
||||||
|
}
|
||||||
|
|
||||||
void applyLegacyFirmPatches(u8 *pos, u32 firmType, u32 console)
|
void applyLegacyFirmPatches(u8 *pos, u32 firmType, u32 console)
|
||||||
{
|
{
|
||||||
const patchData twlPatches[] = {
|
const patchData twlPatches[] = {
|
||||||
|
Reference in New Issue
Block a user