Merge branch 'master' into developer
Conflicts: source/config.c source/config.h
This commit is contained in:
commit
84f3eddaf8
@ -5,10 +5,14 @@ payload_maxsize equ 0x10000 ; Maximum size for the payload (maximum that CakeB
|
|||||||
|
|
||||||
.create "build/reboot.bin", 0
|
.create "build/reboot.bin", 0
|
||||||
.arm
|
.arm
|
||||||
; Interesting registers and locations to keep in mind, set before this code is ran:
|
; Interesting registers and locations to keep in mind, set just before this code is ran:
|
||||||
; - sp + 0x3A8 - 0x70: FIRM path in exefs.
|
; - r1: FIRM path in exefs.
|
||||||
; - r7 (which is sp + 0x3A8 - 0x198): Reserved space for file handle
|
; - r7: pointer to file object
|
||||||
; - *(sp + 0x3A8 - 0x198) + 0x28: fread function.
|
; - *r7: vtable
|
||||||
|
; - *(vtable + 0x28): fread function
|
||||||
|
; - *(r7 + 8): file handle
|
||||||
|
|
||||||
|
mov r8, r1
|
||||||
|
|
||||||
pxi_wait_recv:
|
pxi_wait_recv:
|
||||||
ldr r2, =0x44846
|
ldr r2, =0x44846
|
||||||
@ -47,7 +51,7 @@ payload_maxsize equ 0x10000 ; Maximum size for the payload (maximum that CakeB
|
|||||||
cmp r4, #0
|
cmp r4, #0
|
||||||
movne r3, #0x12000 ; Skip the first 0x12000 bytes.
|
movne r3, #0x12000 ; Skip the first 0x12000 bytes.
|
||||||
moveq r3, payload_maxsize
|
moveq r3, payload_maxsize
|
||||||
ldr r6, [sp, #0x3A8-0x198]
|
ldr r6, [r7]
|
||||||
ldr r6, [r6, #0x28]
|
ldr r6, [r6, #0x28]
|
||||||
blx r6
|
blx r6
|
||||||
cmp r4, #0
|
cmp r4, #0
|
||||||
@ -55,8 +59,7 @@ payload_maxsize equ 0x10000 ; Maximum size for the payload (maximum that CakeB
|
|||||||
bne read_payload ; Go read the real payload.
|
bne read_payload ; Go read the real payload.
|
||||||
|
|
||||||
; Copy the low TID (in UTF-16) of the wanted firm to the 5th byte of the payload
|
; Copy the low TID (in UTF-16) of the wanted firm to the 5th byte of the payload
|
||||||
add r0, sp, #0x3A8 - 0x70
|
add r0, r8, 0x1A
|
||||||
add r0, 0x1A
|
|
||||||
add r1, r0, #0x10
|
add r1, r0, #0x10
|
||||||
ldr r2, =payload_addr + 4
|
ldr r2, =payload_addr + 4
|
||||||
copy_TID_low:
|
copy_TID_low:
|
||||||
@ -75,7 +78,7 @@ payload_maxsize equ 0x10000 ; Maximum size for the payload (maximum that CakeB
|
|||||||
goto_reboot:
|
goto_reboot:
|
||||||
; Jump to reboot code
|
; Jump to reboot code
|
||||||
ldr r0, =(kernelcode_start - goto_reboot - 12)
|
ldr r0, =(kernelcode_start - goto_reboot - 12)
|
||||||
add r0, pc
|
add r0, pc ; pc is two instructions ahead of the instruction being executed (12 = 2*4 + 4)
|
||||||
swi 0x7B
|
swi 0x7B
|
||||||
|
|
||||||
die:
|
die:
|
||||||
|
@ -44,7 +44,7 @@ patch:
|
|||||||
cmp r7, r6
|
cmp r7, r6
|
||||||
bne end
|
bne end
|
||||||
|
|
||||||
ldr r7, =#0xabcdabcd ; offset of the dev launcher (will be replaced later)
|
ldr r7, [launcher] ; offset of the dev launcher (will be replaced later)
|
||||||
add r7, r9
|
add r7, r9
|
||||||
|
|
||||||
adr r5, patchesStart
|
adr r5, patchesStart
|
||||||
@ -81,7 +81,9 @@ patch:
|
|||||||
|
|
||||||
end:
|
end:
|
||||||
|
|
||||||
pop {r0-r11, pc}
|
pop {r0-r11, pc}
|
||||||
|
|
||||||
|
launcher: .ascii "LAUN"
|
||||||
|
|
||||||
.align 2
|
.align 2
|
||||||
.thumb
|
.thumb
|
||||||
@ -141,4 +143,4 @@ patchesEnd:
|
|||||||
|
|
||||||
.pool
|
.pool
|
||||||
|
|
||||||
.close
|
.close
|
||||||
|
@ -21,12 +21,50 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include "memory.h"
|
||||||
|
#include "fs.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "screen.h"
|
#include "screen.h"
|
||||||
#include "draw.h"
|
#include "draw.h"
|
||||||
#include "buttons.h"
|
#include "buttons.h"
|
||||||
|
|
||||||
void configureCFW(void)
|
bool readConfig(const char *configPath)
|
||||||
|
{
|
||||||
|
if(fileRead(&configData, configPath) != sizeof(cfgData) ||
|
||||||
|
memcmp(configData.magic, "CONF", 4) != 0 ||
|
||||||
|
configData.formatVersionMajor != CONFIG_VERSIONMAJOR ||
|
||||||
|
configData.formatVersionMinor != CONFIG_VERSIONMINOR)
|
||||||
|
{
|
||||||
|
configData.config = 0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void writeConfig(const char *configPath, u32 configTemp)
|
||||||
|
{
|
||||||
|
/* If the configuration is different from previously, overwrite it.
|
||||||
|
Just the no-forcing flag being set is not enough */
|
||||||
|
if((configTemp & 0xFFFFFFEF) != configData.config)
|
||||||
|
{
|
||||||
|
//Merge the new options and new boot configuration
|
||||||
|
configData.config = (configData.config & 0xFFFFFFC0) | (configTemp & 0x3F);
|
||||||
|
|
||||||
|
memcpy(configData.magic, "CONF", 4);
|
||||||
|
configData.formatVersionMajor = CONFIG_VERSIONMAJOR;
|
||||||
|
configData.formatVersionMinor = CONFIG_VERSIONMINOR;
|
||||||
|
|
||||||
|
if(!fileWrite(&configData, configPath, sizeof(cfgData)))
|
||||||
|
{
|
||||||
|
createDirectory("luma");
|
||||||
|
if(!fileWrite(&configData, configPath, sizeof(cfgData)))
|
||||||
|
error("Error writing the configuration file");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void configure(void)
|
||||||
{
|
{
|
||||||
initScreens();
|
initScreens();
|
||||||
|
|
||||||
@ -42,10 +80,10 @@ void configureCFW(void)
|
|||||||
"( ) Use second EmuNAND as default",
|
"( ) Use second EmuNAND as default",
|
||||||
"( ) Enable region/language emu. and ext. .code",
|
"( ) Enable region/language emu. and ext. .code",
|
||||||
"( ) Show current NAND in System Settings",
|
"( ) Show current NAND in System Settings",
|
||||||
|
"( ) Enable experimental TwlBg patches",
|
||||||
"( ) Show GBA boot screen in patched AGB_FIRM",
|
"( ) Show GBA boot screen in patched AGB_FIRM",
|
||||||
"( ) Display splash screen before payloads",
|
"( ) Display splash screen before payloads",
|
||||||
"( ) Use a PIN",
|
"( ) Use a PIN",
|
||||||
"( ) Enable experimental TwlBg patches",
|
|
||||||
"( ) Disable access checks" };
|
"( ) Disable access checks" };
|
||||||
|
|
||||||
struct multiOption {
|
struct multiOption {
|
||||||
@ -188,13 +226,13 @@ void configureCFW(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Preserve the last-used boot options (last 12 bits)
|
//Preserve the last-used boot options (last 12 bits)
|
||||||
config &= 0x3F;
|
configData.config &= 0x3F;
|
||||||
|
|
||||||
//Parse and write the new configuration
|
//Parse and write the new configuration
|
||||||
for(u32 i = 0; i < multiOptionsAmount; i++)
|
for(u32 i = 0; i < multiOptionsAmount; i++)
|
||||||
config |= multiOptions[i].enabled << (i * 2 + 6);
|
configData.config |= multiOptions[i].enabled << (i * 2 + 6);
|
||||||
for(u32 i = 0; i < singleOptionsAmount; i++)
|
for(u32 i = 0; i < singleOptionsAmount; i++)
|
||||||
config |= (singleOptions[i].enabled ? 1 : 0) << (i + 16);
|
configData.config |= (singleOptions[i].enabled ? 1 : 0) << (i + 16);
|
||||||
|
|
||||||
//Wait for the pressed buttons to change
|
//Wait for the pressed buttons to change
|
||||||
while(HID_PAD == BUTTON_START);
|
while(HID_PAD == BUTTON_START);
|
||||||
|
@ -24,12 +24,24 @@
|
|||||||
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
#define CONFIG(a) (((config >> (a + 16)) & 1) != 0)
|
#define CONFIG(a) (((configData.config >> (a + 16)) & 1) != 0)
|
||||||
#define MULTICONFIG(a) ((config >> (a * 2 + 6)) & 3)
|
#define MULTICONFIG(a) ((configData.config >> (a * 2 + 6)) & 3)
|
||||||
#define BOOTCONFIG(a, b) ((config >> a) & b)
|
#define BOOTCONFIG(a, b) ((configData.config >> a) & b)
|
||||||
|
|
||||||
#define DEV_OPTIONS MULTICONFIG(2)
|
#define DEV_OPTIONS MULTICONFIG(2)
|
||||||
|
#define CONFIG_VERSIONMAJOR 1
|
||||||
|
#define CONFIG_VERSIONMINOR 0
|
||||||
|
|
||||||
extern u32 config;
|
typedef struct __attribute__((packed))
|
||||||
|
{
|
||||||
|
char magic[4];
|
||||||
|
u16 formatVersionMajor, formatVersionMinor;
|
||||||
|
|
||||||
void configureCFW(void);
|
u32 config;
|
||||||
|
} cfgData;
|
||||||
|
|
||||||
|
extern cfgData configData;
|
||||||
|
|
||||||
|
bool readConfig(const char *configPath);
|
||||||
|
void writeConfig(const char *configPath, u32 configTemp);
|
||||||
|
void configure(void);
|
@ -36,16 +36,16 @@
|
|||||||
#include "pin.h"
|
#include "pin.h"
|
||||||
#include "../build/injector.h"
|
#include "../build/injector.h"
|
||||||
|
|
||||||
extern u16 launchedFirmTIDLow[8]; //defined in start.s
|
extern u16 launchedFirmTIDLow[8]; //Defined in start.s
|
||||||
|
|
||||||
static firmHeader *const firm = (firmHeader *)0x24000000;
|
static firmHeader *const firm = (firmHeader *)0x24000000;
|
||||||
static const firmSectionHeader *section;
|
static const firmSectionHeader *section;
|
||||||
|
|
||||||
u32 config,
|
u32 emuOffset;
|
||||||
emuOffset;
|
|
||||||
|
|
||||||
bool isN3DS, isDevUnit, isFirmlaunch;
|
bool isN3DS, isDevUnit, isFirmlaunch;
|
||||||
|
|
||||||
|
cfgData configData;
|
||||||
FirmwareSource firmSource;
|
FirmwareSource firmSource;
|
||||||
|
|
||||||
void main(void)
|
void main(void)
|
||||||
@ -71,7 +71,7 @@ void main(void)
|
|||||||
const char configPath[] = "/luma/config.bin";
|
const char configPath[] = "/luma/config.bin";
|
||||||
|
|
||||||
//Attempt to read the configuration file
|
//Attempt to read the configuration file
|
||||||
needConfig = fileRead(&config, configPath) ? MODIFY_CONFIGURATION : CREATE_CONFIGURATION;
|
needConfig = readConfig(configPath) ? MODIFY_CONFIGURATION : CREATE_CONFIGURATION;
|
||||||
|
|
||||||
if(DEV_OPTIONS != 2)
|
if(DEV_OPTIONS != 2)
|
||||||
{
|
{
|
||||||
@ -104,11 +104,8 @@ void main(void)
|
|||||||
//Determine if booting with A9LH
|
//Determine if booting with A9LH
|
||||||
isA9lh = !PDN_SPI_CNT;
|
isA9lh = !PDN_SPI_CNT;
|
||||||
|
|
||||||
//Determine if the user chose to use the SysNAND FIRM as default for a R boot
|
|
||||||
bool useSysAsDefault = isA9lh ? CONFIG(1) : false;
|
|
||||||
|
|
||||||
//Save old options and begin saving the new boot configuration
|
//Save old options and begin saving the new boot configuration
|
||||||
configTemp = (config & 0xFFFFFFC0) | ((u32)isA9lh << 3);
|
configTemp = (configData.config & 0xFFFFFFC0) | ((u32)isA9lh << 3);
|
||||||
|
|
||||||
//If it's a MCU reboot, try to force boot options
|
//If it's a MCU reboot, try to force boot options
|
||||||
if(isA9lh && CFG_BOOTENV)
|
if(isA9lh && CFG_BOOTENV)
|
||||||
@ -117,7 +114,7 @@ void main(void)
|
|||||||
if(CFG_BOOTENV == 7)
|
if(CFG_BOOTENV == 7)
|
||||||
{
|
{
|
||||||
nandType = FIRMWARE_SYSNAND;
|
nandType = FIRMWARE_SYSNAND;
|
||||||
firmSource = useSysAsDefault ? FIRMWARE_SYSNAND : (FirmwareSource)BOOTCONFIG(2, 1);
|
firmSource = CONFIG(1) ? FIRMWARE_SYSNAND : (FirmwareSource)BOOTCONFIG(2, 1);
|
||||||
needConfig = DONT_CONFIGURE;
|
needConfig = DONT_CONFIGURE;
|
||||||
|
|
||||||
//Flag to prevent multiple boot options-forcing
|
//Flag to prevent multiple boot options-forcing
|
||||||
@ -126,7 +123,7 @@ void main(void)
|
|||||||
|
|
||||||
/* Else, force the last used boot options unless a button is 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 && !BOOTCONFIG(4, 1))
|
else if(needConfig != CREATE_CONFIGURATION && !pressed && !BOOTCONFIG(4, 1))
|
||||||
{
|
{
|
||||||
nandType = (FirmwareSource)BOOTCONFIG(0, 3);
|
nandType = (FirmwareSource)BOOTCONFIG(0, 3);
|
||||||
firmSource = (FirmwareSource)BOOTCONFIG(2, 1);
|
firmSource = (FirmwareSource)BOOTCONFIG(2, 1);
|
||||||
@ -139,7 +136,7 @@ void main(void)
|
|||||||
{
|
{
|
||||||
PINData pin;
|
PINData pin;
|
||||||
|
|
||||||
bool pinExists = CONFIG(7) && readPin(&pin);
|
bool pinExists = CONFIG(8) && readPin(&pin);
|
||||||
|
|
||||||
//If we get here we should check the PIN (if it exists) in all cases
|
//If we get here we should check the PIN (if it exists) in all cases
|
||||||
if(pinExists) verifyPin(&pin);
|
if(pinExists) verifyPin(&pin);
|
||||||
@ -149,9 +146,9 @@ void main(void)
|
|||||||
|
|
||||||
if(shouldLoadConfigurationMenu)
|
if(shouldLoadConfigurationMenu)
|
||||||
{
|
{
|
||||||
configureCFW();
|
configure();
|
||||||
|
|
||||||
if(!pinExists && CONFIG(7)) newPin();
|
if(!pinExists && CONFIG(8)) newPin();
|
||||||
|
|
||||||
chrono(2);
|
chrono(2);
|
||||||
|
|
||||||
@ -169,7 +166,7 @@ void main(void)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if(CONFIG(6) && loadSplash()) pressed = HID_PAD;
|
if(CONFIG(7) && loadSplash()) pressed = HID_PAD;
|
||||||
|
|
||||||
/* If L and R/A/Select or one of the single payload buttons are pressed,
|
/* If L and R/A/Select or one of the single payload buttons are pressed,
|
||||||
chainload an external payload (the PIN, if any, has been verified)*/
|
chainload an external payload (the PIN, if any, has been verified)*/
|
||||||
@ -177,7 +174,10 @@ void main(void)
|
|||||||
|
|
||||||
if(shouldLoadPayload) loadPayload(pressed);
|
if(shouldLoadPayload) loadPayload(pressed);
|
||||||
|
|
||||||
if(!CONFIG(6)) loadSplash();
|
if(!CONFIG(7)) loadSplash();
|
||||||
|
|
||||||
|
//Determine if the user chose to use the SysNAND FIRM as default for a R boot
|
||||||
|
bool useSysAsDefault = isA9lh ? CONFIG(1) : false;
|
||||||
|
|
||||||
//If R is pressed, boot the non-updated NAND with the FIRM of the opposite one
|
//If R is pressed, boot the non-updated NAND with the FIRM of the opposite one
|
||||||
if(pressed & BUTTON_R1)
|
if(pressed & BUTTON_R1)
|
||||||
@ -215,21 +215,7 @@ void main(void)
|
|||||||
if(!isFirmlaunch)
|
if(!isFirmlaunch)
|
||||||
{
|
{
|
||||||
configTemp |= (u32)nandType | ((u32)firmSource << 2);
|
configTemp |= (u32)nandType | ((u32)firmSource << 2);
|
||||||
|
writeConfig(configPath, configTemp);
|
||||||
/* If the configuration is different from previously, overwrite it.
|
|
||||||
Just the no-forcing flag being set is not enough */
|
|
||||||
if((configTemp & 0xFFFFFFEF) != config)
|
|
||||||
{
|
|
||||||
//Merge the new options and new boot configuration
|
|
||||||
config = (config & 0xFFFFFFC0) | (configTemp & 0x3F);
|
|
||||||
|
|
||||||
if(!fileWrite(&config, configPath, 4))
|
|
||||||
{
|
|
||||||
createDirectory("luma");
|
|
||||||
if(!fileWrite(&config, configPath, 4))
|
|
||||||
error("Error writing the configuration file");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 firmVersion = loadFirm(firmType);
|
u32 firmVersion = loadFirm(firmType);
|
||||||
@ -388,7 +374,7 @@ static inline void patchLegacyFirm(FirmwareType firmType)
|
|||||||
|
|
||||||
applyLegacyFirmPatches((u8 *)firm, firmType);
|
applyLegacyFirmPatches((u8 *)firm, firmType);
|
||||||
|
|
||||||
if(firmType == TWL_FIRM && CONFIG(8))
|
if(firmType == TWL_FIRM && CONFIG(5))
|
||||||
patchTwlBg((u8 *)firm + section[1].offset);
|
patchTwlBg((u8 *)firm + section[1].offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,6 +24,11 @@
|
|||||||
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
|
#define CFG_BOOTENV (*(vu32 *)0x10010000)
|
||||||
|
#define CFG_UNITINFO (*(vu8 *)0x10010010)
|
||||||
|
#define PDN_MPCORE_CFG (*(vu32 *)0x10140FFC)
|
||||||
|
#define PDN_SPI_CNT (*(vu32 *)0x101401C0)
|
||||||
|
|
||||||
//FIRM Header layout
|
//FIRM Header layout
|
||||||
typedef struct firmSectionHeader {
|
typedef struct firmSectionHeader {
|
||||||
u32 offset;
|
u32 offset;
|
||||||
|
@ -32,7 +32,7 @@ static u32 *arm11ExceptionsPage = NULL;
|
|||||||
static u32 *arm11SvcTable = NULL;
|
static u32 *arm11SvcTable = NULL;
|
||||||
static u32 *arm11SvcHandler = NULL;
|
static u32 *arm11SvcHandler = NULL;
|
||||||
|
|
||||||
static u8 *freeK11Space = NULL; //other than the one used for svcBackdoor
|
static u8 *freeK11Space = NULL;
|
||||||
|
|
||||||
static void findArm11ExceptionsPageAndSvcHandlerAndTable(u8 *pos, u32 size)
|
static void findArm11ExceptionsPageAndSvcHandlerAndTable(u8 *pos, u32 size)
|
||||||
{
|
{
|
||||||
@ -51,21 +51,9 @@ static void findFreeK11Space(u8 *pos, u32 size)
|
|||||||
{
|
{
|
||||||
if(freeK11Space == NULL)
|
if(freeK11Space == NULL)
|
||||||
{
|
{
|
||||||
const u8 bogus_pattern[] = { 0x1E, 0xFF, 0x2F, 0xE1, 0x1E, 0xFF, 0x2F, 0xE1, 0x1E, 0xFF,
|
const u8 pattern[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
|
||||||
0x2F, 0xE1, 0x00, 0x10, 0xA0, 0xE3, 0x00, 0x10, 0xC0, 0xE5,
|
|
||||||
0x1E, 0xFF, 0x2F, 0xE1 };
|
|
||||||
|
|
||||||
u32 *someSpace = (u32 *)memsearch(pos, bogus_pattern, size, 24);
|
freeK11Space = memsearch(pos, pattern, size, 5) + 1;
|
||||||
|
|
||||||
// We couldn't find the place where to begin our search of an empty block
|
|
||||||
if (someSpace == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Advance until we reach the padding area (filled with 0xFF)
|
|
||||||
u32 *freeSpace;
|
|
||||||
for(freeSpace = someSpace; *freeSpace != 0xFFFFFFFF; freeSpace++);
|
|
||||||
|
|
||||||
freeK11Space = (u8 *)freeSpace;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -117,9 +105,9 @@ void patchSignatureChecks(u8 *pos, u32 size)
|
|||||||
void patchFirmlaunches(u8 *pos, u32 size, u32 process9MemAddr)
|
void patchFirmlaunches(u8 *pos, u32 size, u32 process9MemAddr)
|
||||||
{
|
{
|
||||||
//Look for firmlaunch code
|
//Look for firmlaunch code
|
||||||
const u8 pattern[] = {0xDE, 0x1F, 0x8D, 0xE2};
|
const u8 pattern[] = {0xE2, 0x20, 0x20, 0x90};
|
||||||
|
|
||||||
u8 *off = memsearch(pos, pattern, size, 4) - 0x10;
|
u8 *off = memsearch(pos, pattern, size, 4) - 0x13;
|
||||||
|
|
||||||
//Firmlaunch function offset - offset in BLX opcode (A4-16 - ARM DDI 0100E) + 1
|
//Firmlaunch function offset - offset in BLX opcode (A4-16 - ARM DDI 0100E) + 1
|
||||||
u32 fOpenOffset = (u32)(off + 9 - (-((*(u32 *)off & 0x00FFFFFF) << 2) & (0xFFFFFF << 2)) - pos + process9MemAddr);
|
u32 fOpenOffset = (u32)(off + 9 - (-((*(u32 *)off & 0x00FFFFFF) << 2) & (0xFFFFFF << 2)) - pos + process9MemAddr);
|
||||||
@ -303,7 +291,7 @@ void patchUnitInfoValueSet(u8 *pos, u32 size)
|
|||||||
|
|
||||||
u8 *off = memsearch(pos, pattern, size, 4);
|
u8 *off = memsearch(pos, pattern, size, 4);
|
||||||
|
|
||||||
off[0] = (CFG_UNITINFO == 0) ? 1 : 0;
|
off[0] = (isDevUnit) ? 0 : 1;
|
||||||
off[3] = 0xE3;
|
off[3] = 0xE3;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -325,29 +313,28 @@ void reimplementSvcBackdoor(u8 *pos, u32 size)
|
|||||||
|
|
||||||
if(!arm11SvcTable[0x7B])
|
if(!arm11SvcTable[0x7B])
|
||||||
{
|
{
|
||||||
u32 *freeSpace;
|
findFreeK11Space(pos, size);
|
||||||
for(freeSpace = arm11ExceptionsPage; *freeSpace != 0xFFFFFFFF; freeSpace++);
|
|
||||||
|
|
||||||
memcpy(freeSpace, svcBackdoor, 40);
|
memcpy(freeK11Space, svcBackdoor, 40);
|
||||||
|
|
||||||
arm11SvcTable[0x7B] = 0xFFFF0000 + ((u8 *)freeSpace - (u8 *)arm11ExceptionsPage);
|
arm11SvcTable[0x7B] = 0xFFF00000 + freeK11Space - pos;
|
||||||
|
freeK11Space += 40;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void implementSvcGetCFWInfo(u8 *pos, u32 size)
|
void implementSvcGetCFWInfo(u8 *pos, u32 size)
|
||||||
{
|
{
|
||||||
const char *rev = REVISION;
|
|
||||||
bool isRelease;
|
|
||||||
|
|
||||||
findArm11ExceptionsPageAndSvcHandlerAndTable(pos, size);
|
|
||||||
findFreeK11Space(pos, size);
|
findFreeK11Space(pos, size);
|
||||||
|
|
||||||
memcpy(freeK11Space, svcGetCFWInfo, svcGetCFWInfo_size);
|
memcpy(freeK11Space, svcGetCFWInfo, svcGetCFWInfo_size);
|
||||||
|
|
||||||
CFWInfo *info = (CFWInfo *)memsearch(freeK11Space, "LUMA", svcGetCFWInfo_size, 4);
|
CFWInfo *info = (CFWInfo *)memsearch(freeK11Space, "LUMA", svcGetCFWInfo_size, 4);
|
||||||
|
|
||||||
|
const char *rev = REVISION;
|
||||||
|
bool isRelease;
|
||||||
|
|
||||||
info->commitHash = COMMIT_HASH;
|
info->commitHash = COMMIT_HASH;
|
||||||
info->config = config;
|
info->config = configData.config;
|
||||||
info->versionMajor = (u8)(rev[1] - '0');
|
info->versionMajor = (u8)(rev[1] - '0');
|
||||||
info->versionMinor = (u8)(rev[3] - '0');
|
info->versionMinor = (u8)(rev[3] - '0');
|
||||||
if(rev[4] == '.')
|
if(rev[4] == '.')
|
||||||
@ -355,12 +342,13 @@ void implementSvcGetCFWInfo(u8 *pos, u32 size)
|
|||||||
info->versionBuild = (u8)(rev[5] - '0');
|
info->versionBuild = (u8)(rev[5] - '0');
|
||||||
isRelease = rev[6] == 0;
|
isRelease = rev[6] == 0;
|
||||||
}
|
}
|
||||||
else
|
else isRelease = rev[4] == 0;
|
||||||
isRelease = rev[4] == 0;
|
|
||||||
|
|
||||||
info->flags = 1 /* dev branch */ | (((isRelease) ? 1 : 0) << 1) /* is release */;
|
info->flags = 1 /* dev branch */ | (((isRelease) ? 1 : 0) << 1) /* is release */;
|
||||||
|
|
||||||
arm11SvcTable[0x2E] = 0xFFF00000 + freeK11Space - pos; //stubbed svc
|
findArm11ExceptionsPageAndSvcHandlerAndTable(pos, size);
|
||||||
|
|
||||||
|
arm11SvcTable[0x2E] = 0xFFF00000 + freeK11Space - pos; //Stubbed svc
|
||||||
freeK11Space += svcGetCFWInfo_size;
|
freeK11Space += svcGetCFWInfo_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -394,7 +382,7 @@ void applyLegacyFirmPatches(u8 *pos, FirmwareType firmType)
|
|||||||
/* Calculate the amount of patches to apply. Only count the boot screen patch for AGB_FIRM
|
/* Calculate the amount of patches to apply. Only count the boot screen patch for AGB_FIRM
|
||||||
if the matching option was enabled (keep it as last) */
|
if the matching option was enabled (keep it as last) */
|
||||||
u32 numPatches = firmType == TWL_FIRM ? (sizeof(twlPatches) / sizeof(patchData)) :
|
u32 numPatches = firmType == TWL_FIRM ? (sizeof(twlPatches) / sizeof(patchData)) :
|
||||||
(sizeof(agbPatches) / sizeof(patchData) - !CONFIG(5));
|
(sizeof(agbPatches) / sizeof(patchData) - !CONFIG(6));
|
||||||
const patchData *patches = firmType == TWL_FIRM ? twlPatches : agbPatches;
|
const patchData *patches = firmType == TWL_FIRM ? twlPatches : agbPatches;
|
||||||
|
|
||||||
//Patch
|
//Patch
|
||||||
@ -417,12 +405,14 @@ void applyLegacyFirmPatches(u8 *pos, FirmwareType firmType)
|
|||||||
void patchTwlBg(u8 *pos)
|
void patchTwlBg(u8 *pos)
|
||||||
{
|
{
|
||||||
u8 *dst = pos + ((isN3DS) ? 0xFEA4 : 0xFCA0);
|
u8 *dst = pos + ((isN3DS) ? 0xFEA4 : 0xFCA0);
|
||||||
u16 *src1 = (u16 *)(pos + ((isN3DS) ? 0xE38 : 0xE3C)), *src2 = (u16 *)(pos + ((isN3DS) ? 0xE54 : 0xE58));
|
|
||||||
memcpy(dst, twl_k11modules, twl_k11modules_size); //install k11 hook
|
memcpy(dst, twl_k11modules, twl_k11modules_size); //Install K11 hook
|
||||||
|
|
||||||
u32 *off;
|
u32 *off = (u32 *)memsearch(dst, "LAUN", twl_k11modules_size, 4);
|
||||||
for(off = (u32 *)dst; *off != 0xABCDABCD; off++);
|
*off = (isN3DS) ? 0xCDE88 : 0xCD5F8; //Dev SRL launcher offset
|
||||||
*off = (isN3DS) ? 0xCDE88 : 0xCD5F8; //dev SRL launcher offset
|
|
||||||
|
u16 *src1 = (u16 *)(pos + ((isN3DS) ? 0xE38 : 0xE3C)),
|
||||||
|
*src2 = (u16 *)(pos + ((isN3DS) ? 0xE54 : 0xE58));
|
||||||
|
|
||||||
//Construct BLX instructions:
|
//Construct BLX instructions:
|
||||||
src1[0] = 0xF000 | ((((u32)dst - (u32)src1 - 4) & (0xFFF << 11)) >> 12);
|
src1[0] = 0xF000 | ((((u32)dst - (u32)src1 - 4) & (0xFFF << 11)) >> 12);
|
||||||
|
@ -47,8 +47,7 @@ typedef struct __attribute__((packed))
|
|||||||
u32 config;
|
u32 config;
|
||||||
} CFWInfo;
|
} CFWInfo;
|
||||||
|
|
||||||
extern bool isN3DS;
|
extern bool isN3DS, isDevUnit;
|
||||||
extern u32 config;
|
|
||||||
|
|
||||||
u8 *getProcess9(u8 *pos, u32 size, u32 *process9Size, u32 *process9MemAddr);
|
u8 *getProcess9(u8 *pos, u32 size, u32 *process9Size, u32 *process9MemAddr);
|
||||||
u32* getInfoForArm11ExceptionHandlers(u8 *pos, u32 size, u32 *stackAddr, u32 *codeSetOffset);
|
u32* getInfoForArm11ExceptionHandlers(u8 *pos, u32 size, u32 *stackAddr, u32 *codeSetOffset);
|
||||||
|
30
source/pin.c
30
source/pin.c
@ -36,11 +36,14 @@
|
|||||||
|
|
||||||
bool readPin(PINData *out)
|
bool readPin(PINData *out)
|
||||||
{
|
{
|
||||||
u8 __attribute__((aligned(4))) zeroes[16] = {0};
|
if(fileRead(out, "/luma/pin.bin") != sizeof(PINData) ||
|
||||||
u8 __attribute__((aligned(4))) tmp[32] = {0};
|
memcmp(out->magic, "PINF", 4) != 0 ||
|
||||||
|
out->formatVersionMajor != PIN_VERSIONMAJOR ||
|
||||||
|
out->formatVersionMinor != PIN_VERSIONMINOR)
|
||||||
|
return false;
|
||||||
|
|
||||||
if(fileRead(out, "/luma/pin.bin") != sizeof(PINData)) return false;
|
u8 __attribute__((aligned(4))) zeroes[16] = {0};
|
||||||
if(memcmp(out->magic, "PINF", 4) != 0) return false;
|
u8 __attribute__((aligned(4))) tmp[32];
|
||||||
|
|
||||||
computePINHash(tmp, zeroes, 1);
|
computePINHash(tmp, zeroes, 1);
|
||||||
|
|
||||||
@ -89,13 +92,13 @@ void newPin(void)
|
|||||||
charDrawPos += 2 * SPACING_X;
|
charDrawPos += 2 * SPACING_X;
|
||||||
}
|
}
|
||||||
|
|
||||||
PINData pin = {0};
|
PINData pin;
|
||||||
u8 __attribute__((aligned(4))) tmp[32] = {0};
|
u8 __attribute__((aligned(4))) tmp[32];
|
||||||
u8 __attribute__((aligned(4))) zeroes[16] = {0};
|
u8 __attribute__((aligned(4))) zeroes[16] = {0};
|
||||||
|
|
||||||
memcpy(pin.magic, "PINF", 4);
|
memcpy(pin.magic, "PINF", 4);
|
||||||
pin.formatVersionMajor = 1;
|
pin.formatVersionMajor = PIN_VERSIONMAJOR;
|
||||||
pin.formatVersionMinor = 0;
|
pin.formatVersionMinor = PIN_VERSIONMINOR;
|
||||||
|
|
||||||
computePINHash(tmp, zeroes, 1);
|
computePINHash(tmp, zeroes, 1);
|
||||||
memcpy(pin.testHash, tmp, 32);
|
memcpy(pin.testHash, tmp, 32);
|
||||||
@ -103,8 +106,13 @@ void newPin(void)
|
|||||||
computePINHash(tmp, enteredPassword, (PIN_LENGTH + 15) / 16);
|
computePINHash(tmp, enteredPassword, (PIN_LENGTH + 15) / 16);
|
||||||
memcpy(pin.hash, tmp, 32);
|
memcpy(pin.hash, tmp, 32);
|
||||||
|
|
||||||
fileWrite(&pin, "/luma/pin.bin", sizeof(PINData));
|
if(!fileWrite(&pin, "/luma/pin.bin", sizeof(PINData)))
|
||||||
|
{
|
||||||
|
createDirectory("luma");
|
||||||
|
if(!fileWrite(&pin, "/luma/pin.bin", sizeof(PINData)))
|
||||||
|
error("Error writing the PIN file");
|
||||||
|
}
|
||||||
|
|
||||||
while(HID_PAD & PIN_BUTTONS);
|
while(HID_PAD & PIN_BUTTONS);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,7 +153,7 @@ void verifyPin(PINData *in)
|
|||||||
|
|
||||||
if(cnt >= PIN_LENGTH)
|
if(cnt >= PIN_LENGTH)
|
||||||
{
|
{
|
||||||
u8 __attribute__((aligned(4))) tmp[32] = {0};
|
u8 __attribute__((aligned(4))) tmp[32];
|
||||||
|
|
||||||
computePINHash(tmp, enteredPassword, (PIN_LENGTH + 15) / 16);
|
computePINHash(tmp, enteredPassword, (PIN_LENGTH + 15) / 16);
|
||||||
unlock = memcmp(in->hash, tmp, 32) == 0;
|
unlock = memcmp(in->hash, tmp, 32) == 0;
|
||||||
|
@ -31,6 +31,8 @@
|
|||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
#define PIN_LENGTH 4
|
#define PIN_LENGTH 4
|
||||||
|
#define PIN_VERSIONMAJOR 1
|
||||||
|
#define PIN_VERSIONMINOR 0
|
||||||
|
|
||||||
typedef struct __attribute__((packed))
|
typedef struct __attribute__((packed))
|
||||||
{
|
{
|
||||||
|
@ -242,7 +242,7 @@ void initScreens(void)
|
|||||||
|
|
||||||
if(PDN_GPU_CNT == 1)
|
if(PDN_GPU_CNT == 1)
|
||||||
{
|
{
|
||||||
flushDCacheRange(&config, 4);
|
flushDCacheRange(&configData, sizeof(cfgData));
|
||||||
flushDCacheRange((void *)fb, sizeof(struct fb));
|
flushDCacheRange((void *)fb, sizeof(struct fb));
|
||||||
invokeArm11Function(ARM11);
|
invokeArm11Function(ARM11);
|
||||||
|
|
||||||
|
@ -29,6 +29,8 @@
|
|||||||
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
|
#define PDN_GPU_CNT (*(vu8 *)0x10141200)
|
||||||
|
|
||||||
#define ARM11_STUB_ADDRESS (0x25000000 - 0x30) //It's currently only 0x28 bytes large. We're putting 0x30 just to be sure here
|
#define ARM11_STUB_ADDRESS (0x25000000 - 0x30) //It's currently only 0x28 bytes large. We're putting 0x30 just to be sure here
|
||||||
#define WAIT_FOR_ARM9() *arm11Entry = 0; while(!*arm11Entry); ((void (*)())*arm11Entry)();
|
#define WAIT_FOR_ARM9() *arm11Entry = 0; while(!*arm11Entry); ((void (*)())*arm11Entry)();
|
||||||
|
|
||||||
|
@ -26,13 +26,6 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
#define CFG_BOOTENV (*(vu32 *)0x10010000)
|
|
||||||
#define CFG_UNITINFO (*(vu8 *)0x10010010)
|
|
||||||
|
|
||||||
#define PDN_MPCORE_CFG (*(vu32 *)0x10140FFC)
|
|
||||||
#define PDN_SPI_CNT (*(vu32 *)0x101401C0)
|
|
||||||
#define PDN_GPU_CNT (*(vu8 *)0x10141200)
|
|
||||||
|
|
||||||
//Common data types
|
//Common data types
|
||||||
typedef uint8_t u8;
|
typedef uint8_t u8;
|
||||||
typedef uint16_t u16;
|
typedef uint16_t u16;
|
||||||
@ -43,7 +36,7 @@ typedef volatile u16 vu16;
|
|||||||
typedef volatile u32 vu32;
|
typedef volatile u32 vu32;
|
||||||
typedef volatile u64 vu64;
|
typedef volatile u64 vu64;
|
||||||
|
|
||||||
//Used by multiple files:
|
//Used by multiple files
|
||||||
typedef enum FirmwareSource
|
typedef enum FirmwareSource
|
||||||
{
|
{
|
||||||
FIRMWARE_SYSNAND = 0,
|
FIRMWARE_SYSNAND = 0,
|
||||||
|
@ -27,8 +27,6 @@
|
|||||||
#include "draw.h"
|
#include "draw.h"
|
||||||
#include "cache.h"
|
#include "cache.h"
|
||||||
|
|
||||||
extern bool isFirmlaunch;
|
|
||||||
|
|
||||||
u32 waitInput(void)
|
u32 waitInput(void)
|
||||||
{
|
{
|
||||||
u32 pressedKey = 0,
|
u32 pressedKey = 0,
|
||||||
|
@ -28,6 +28,8 @@
|
|||||||
#define REG_TIMER_CNT(i) *(vu16 *)(0x10003002 + 4 * i)
|
#define REG_TIMER_CNT(i) *(vu16 *)(0x10003002 + 4 * i)
|
||||||
#define REG_TIMER_VAL(i) *(vu16 *)(0x10003000 + 4 * i)
|
#define REG_TIMER_VAL(i) *(vu16 *)(0x10003000 + 4 * i)
|
||||||
|
|
||||||
|
extern bool isFirmlaunch;
|
||||||
|
|
||||||
u32 waitInput(void);
|
u32 waitInput(void);
|
||||||
void mcuReboot(void);
|
void mcuReboot(void);
|
||||||
void mcuPowerOff(void);
|
void mcuPowerOff(void);
|
||||||
|
Reference in New Issue
Block a user