Merge master and dev builds
This commit is contained in:
parent
eaa4d6323e
commit
420ccdcb82
22
Makefile
22
Makefile
@ -38,15 +38,8 @@ objects = $(patsubst $(dir_source)/%.s, $(dir_build)/%.o, \
|
||||
$(patsubst $(dir_source)/%.c, $(dir_build)/%.o, \
|
||||
$(call rwildcard, $(dir_source), *.s *.c)))
|
||||
|
||||
bundled = $(dir_build)/rebootpatch.h $(dir_build)/emunandpatch.h $(dir_build)/svcGetCFWInfopatch.h $(dir_build)/injector.h $(dir_build)/loader.h
|
||||
|
||||
ifeq ($(strip $(DEV)),TRUE)
|
||||
CFLAGS += -DDEV
|
||||
bundled += $(dir_build)/k11modulespatch.h $(dir_build)/arm9_exceptions.h $(dir_build)/arm11_exceptions.h
|
||||
title := \"$(name) $(revision) (dev) configuration\"
|
||||
else
|
||||
title := \"$(name) $(revision) configuration\"
|
||||
endif
|
||||
bundled = $(dir_build)/rebootpatch.h $(dir_build)/emunandpatch.h $(dir_build)/svcGetCFWInfopatch.h $(dir_build)/injector.h $(dir_build)/loader.h \
|
||||
$(dir_build)/k11modulespatch.h $(dir_build)/arm9_exceptions.h $(dir_build)/arm11_exceptions.h
|
||||
|
||||
.PHONY: all
|
||||
all: launcher a9lh ninjhax menuhax
|
||||
@ -64,11 +57,7 @@ ninjhax: $(dir_out)/3ds/$(name)
|
||||
menuhax: $(dir_out)/menuhax/boot.3dsx
|
||||
|
||||
.PHONY: release
|
||||
ifeq ($(strip $(DEV)),TRUE)
|
||||
release: $(dir_out)/$(name)$(revision)-dev.7z
|
||||
else
|
||||
release: $(dir_out)/$(name)$(revision).7z
|
||||
endif
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
@ -107,9 +96,6 @@ $(dir_out)/pathchanger: $(dir_pathchanger)/pathchanger.py $(dir_pathchanger)/pre
|
||||
@cp -rfT $(dir_pathchanger)/prebuilt $@
|
||||
|
||||
$(dir_out)/$(name)$(revision).7z: all $(dir_out)/pathchanger
|
||||
@7z a -mx $@ ./$(@D)/*
|
||||
|
||||
$(dir_out)/$(name)$(revision)-dev.7z: all $(dir_out)/pathchanger
|
||||
@7z a -mx $@ ./$(@D)/* ./$(dir_exceptions)/exception_dump_parser.py
|
||||
|
||||
$(dir_build)/main.bin: $(dir_build)/main.elf
|
||||
@ -135,7 +121,7 @@ $(dir_build)/svcGetCFWInfopatch.h: $(dir_patches)/svcGetCFWInfo.s
|
||||
|
||||
$(dir_build)/injector.h: $(dir_injector)/Makefile
|
||||
@mkdir -p "$(@D)"
|
||||
@$(MAKE) -C $(dir_injector) DEV=$(DEV)
|
||||
@$(MAKE) -C $(dir_injector)
|
||||
@bin2c -o $@ -n injector $(@D)/injector.cxi
|
||||
|
||||
$(dir_build)/loader.h: $(dir_loader)/Makefile
|
||||
@ -156,7 +142,7 @@ $(dir_build)/arm11_exceptions.h: $(dir_arm11_exceptions)/Makefile
|
||||
@bin2c -o $@ -n arm11_exceptions $(@D)/arm11_exceptions.bin
|
||||
|
||||
$(dir_build)/memory.o $(dir_build)/strings.o: CFLAGS += -O3
|
||||
$(dir_build)/config.o: CFLAGS += -DCONFIG_TITLE="$(title)"
|
||||
$(dir_build)/config.o: CFLAGS += -DCONFIG_TITLE="\"$(name) $(revision) configuration\""
|
||||
$(dir_build)/patches.o: CFLAGS += -DREVISION=\"$(revision)\" -DCOMMIT_HASH="0x$(commit)"
|
||||
|
||||
$(dir_build)/%.o: $(dir_source)/%.c $(bundled)
|
||||
|
@ -14,7 +14,7 @@ To use it, you will need a console capable of running homebrew software on the A
|
||||
First you need to clone the repository recursively with: `git clone --recursive https://github.com/AuroraWright/Luma3DS.git`
|
||||
To compile, you'll need [armips](https://github.com/Kingcom/armips), [bin2c](https://sourceforge.net/projects/bin2c/), and a recent build of [makerom](https://github.com/profi200/Project_CTR) added to your PATH.
|
||||
For your convenience, here are [Windows](http://www91.zippyshare.com/v/ePGpjk9r/file.html) and [Linux](https://mega.nz/#!uQ1T1IAD!Q91O0e12LXKiaXh_YjXD3D5m8_W3FuMI-hEa6KVMRDQ) builds of armips (thanks to who compiled them!).
|
||||
Finally just run `make` (for the regular version) or `make DEV=TRUE` (for the dev version) and everything should work!
|
||||
Finally just run `make` and everything should work!
|
||||
You can find the compiled files in the `out` folder.
|
||||
|
||||
---
|
||||
|
@ -30,10 +30,6 @@ LDFLAGS := -Xlinker --defsym="__start__=0x14000000" -specs=3dsx.specs $(ASFLAGS)
|
||||
objects = $(patsubst $(dir_source)/%.c, $(dir_build)/%.o, \
|
||||
$(call rwildcard, $(dir_source), *.s *.c))
|
||||
|
||||
ifeq ($(strip $(DEV)),TRUE)
|
||||
CFLAGS += -DDEV
|
||||
endif
|
||||
|
||||
.PHONY: all
|
||||
all: ../$(dir_build)/$(name).cxi
|
||||
|
||||
|
@ -582,10 +582,9 @@ void patchCode(u64 progId, u8 *code, u32 size)
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef DEV
|
||||
case 0x0004003000008A02LL: // ErrDisp
|
||||
{
|
||||
if(MULTICONFIG(DEVOPTIONS) == 0)
|
||||
if(MULTICONFIG(DEVOPTIONS) == 1)
|
||||
{
|
||||
static const u8 unitinfoCheckPattern1[] = {
|
||||
0x14, 0x00, 0xD0, 0xE5, 0xDB
|
||||
@ -616,7 +615,6 @@ void patchCode(u64 progId, u8 *code, u32 size)
|
||||
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
default:
|
||||
if(CONFIG(USELANGEMUANDCODE))
|
||||
|
@ -16,24 +16,21 @@ enum multiOptions
|
||||
{
|
||||
DEFAULTEMU = 0,
|
||||
BRIGHTNESS,
|
||||
SPLASH,
|
||||
PIN,
|
||||
NEWCPU
|
||||
#ifdef DEV
|
||||
, DEVOPTIONS
|
||||
#endif
|
||||
NEWCPU,
|
||||
DEVOPTIONS
|
||||
};
|
||||
|
||||
enum singleOptions
|
||||
{
|
||||
AUTOBOOTSYS = 0,
|
||||
USESYSFIRM,
|
||||
SDFIRMSANDMODULES,
|
||||
USELANGEMUANDCODE,
|
||||
PATCHVERSTRING,
|
||||
SHOWGBABOOT,
|
||||
PAYLOADSPLASH
|
||||
#ifdef DEV
|
||||
, PATCHACCESS
|
||||
#endif
|
||||
PATCHACCESS
|
||||
};
|
||||
|
||||
void patchCode(u64 progId, u8 *code, u32 size);
|
@ -68,22 +68,19 @@ void configMenu(bool oldPinStatus)
|
||||
{
|
||||
const char *multiOptionsText[] = { "Default EmuNAND: 1( ) 2( ) 3( ) 4( )",
|
||||
"Screen brightness: 4( ) 3( ) 2( ) 1( )",
|
||||
"Splash: Off( ) Before( ) After( ) payloads",
|
||||
"PIN lock: Off( ) 4( ) 6( ) 8( ) digits",
|
||||
"New 3DS CPU: Off( ) Clock( ) L2( ) Clock+L2( )"
|
||||
#ifdef DEV
|
||||
, "Dev. features: ErrDisp( ) UNITINFO( ) Off( )"
|
||||
#endif
|
||||
"New 3DS CPU: Off( ) Clock( ) L2( ) Clock+L2( )",
|
||||
"Dev. features: Off( ) ErrDisp( ) UNITINFO( )"
|
||||
};
|
||||
|
||||
const char *singleOptionsText[] = { "( ) Autoboot SysNAND",
|
||||
"( ) Use SysNAND FIRM if booting with R (A9LH)",
|
||||
"( ) Enable FIRMs and modules loading from SD",
|
||||
"( ) Enable region/language emu. and ext. .code",
|
||||
"( ) Show NAND or user string in System Settings",
|
||||
"( ) Show GBA boot screen in patched AGB_FIRM",
|
||||
"( ) Display splash screen before payloads"
|
||||
#ifdef DEV
|
||||
, "( ) Patch SVC/service/archive/ARM9 access"
|
||||
#endif
|
||||
"( ) Patch SVC/service/archive/ARM9 access"
|
||||
};
|
||||
|
||||
const char *optionsDescription[] = { "Select the default EmuNAND.\n\n"
|
||||
@ -92,6 +89,13 @@ void configMenu(bool oldPinStatus)
|
||||
|
||||
"Select the screen brightness.",
|
||||
|
||||
"Enable splash screen support.\n\n"
|
||||
"\t* 'After payloads' displays it\n"
|
||||
"before booting payloads.\n\n"
|
||||
"\t* 'Before payloads' displays it\n"
|
||||
"afterwards (intended for splashes\n"
|
||||
"that display button hints).",
|
||||
|
||||
"Activate a PIN lock.\n\n"
|
||||
"The PIN will be asked each time\n"
|
||||
"Luma3DS boots.\n\n"
|
||||
@ -103,18 +107,20 @@ void configMenu(bool oldPinStatus)
|
||||
"It will be always enabled.\n\n"
|
||||
"'Clock+L2' can cause issues with some\n"
|
||||
"games.",
|
||||
#ifdef DEV
|
||||
|
||||
"Select the developer features.\n\n"
|
||||
"\t* 'Off' disables exception handlers\n"
|
||||
"in FIRM.\n"
|
||||
"\t* 'ErrDisp' displays debug info\n"
|
||||
"on the 'An error has occurred' screen.\n"
|
||||
"\t* 'UNITINFO' makes the console be\n"
|
||||
"always detected as a development unit\n"
|
||||
"(which breaks online features and\n"
|
||||
"allows booting some developer\n"
|
||||
"software).\n"
|
||||
"\t* 'Off' disables exception handlers\n"
|
||||
"in FIRM.",
|
||||
#endif
|
||||
"software).\n\n"
|
||||
"Only change this if you know what you\n"
|
||||
"are doing!",
|
||||
|
||||
"If enabled SysNAND will be launched on\n"
|
||||
"boot. Otherwise, an EmuNAND will.\n\n"
|
||||
"Hold L on boot to switch NAND.\n\n"
|
||||
@ -132,6 +138,11 @@ void configMenu(bool oldPinStatus)
|
||||
"(Up/Right/Down/Left equal EmuNANDs\n"
|
||||
"1/2/3/4).",
|
||||
|
||||
"If enabled, you will be able to load\n"
|
||||
"FIRMs and system modules from the SD\n"
|
||||
"card.\n\n"
|
||||
"This isn't needed in most cases,",
|
||||
|
||||
"Enable overriding the region and\n"
|
||||
"language configuration and the usage\n"
|
||||
"of patched code binaries for specific\n"
|
||||
@ -154,16 +165,10 @@ void configMenu(bool oldPinStatus)
|
||||
"Show the GBA boot screen when booting\n"
|
||||
"GBA games.",
|
||||
|
||||
"If enabled, the splash screen will be\n"
|
||||
"displayed before booting payloads,\n"
|
||||
"otherwise it will be displayed\n"
|
||||
"afterwards.\n\n"
|
||||
"Intended for splash screens that\n"
|
||||
"display button hints."
|
||||
#ifdef DEV
|
||||
, "Disable SVC, service, archive and ARM9\n"
|
||||
"exheader access checks."
|
||||
#endif
|
||||
"Disable SVC, service, archive and ARM9\n"
|
||||
"exheader access checks.\n\n"
|
||||
"Only change this if you know what you\n"
|
||||
"are doing!",
|
||||
};
|
||||
|
||||
struct multiOption {
|
||||
@ -173,11 +178,10 @@ void configMenu(bool oldPinStatus)
|
||||
} multiOptions[] = {
|
||||
{ .posXs = {19, 24, 29, 34} },
|
||||
{ .posXs = {21, 26, 31, 36} },
|
||||
{ .posXs = {12, 22, 31, 0} },
|
||||
{ .posXs = {14, 19, 24, 29} },
|
||||
{ .posXs = {17, 26, 32, 44} }
|
||||
#ifdef DEV
|
||||
, { .posXs = {23, 35, 43, 0} }
|
||||
#endif
|
||||
{ .posXs = {17, 26, 32, 44} },
|
||||
{ .posXs = {19, 30, 42, 0} }
|
||||
};
|
||||
|
||||
//Calculate the amount of the various kinds of options and pre-select the first single one
|
||||
|
@ -30,7 +30,7 @@
|
||||
|
||||
#define CONFIG_PATH "/luma/config.bin"
|
||||
#define CONFIG_VERSIONMAJOR 1
|
||||
#define CONFIG_VERSIONMINOR 4
|
||||
#define CONFIG_VERSIONMINOR 5
|
||||
|
||||
#define BOOTCFG_NAND BOOTCONFIG(0, 7)
|
||||
#define BOOTCFG_FIRM BOOTCONFIG(3, 7)
|
||||
@ -42,24 +42,21 @@ enum multiOptions
|
||||
{
|
||||
DEFAULTEMU = 0,
|
||||
BRIGHTNESS,
|
||||
SPLASH,
|
||||
PIN,
|
||||
NEWCPU
|
||||
#ifdef DEV
|
||||
, DEVOPTIONS
|
||||
#endif
|
||||
NEWCPU,
|
||||
DEVOPTIONS
|
||||
};
|
||||
|
||||
enum singleOptions
|
||||
{
|
||||
AUTOBOOTSYS = 0,
|
||||
USESYSFIRM,
|
||||
SDFIRMSANDMODULES,
|
||||
USELANGEMUANDCODE,
|
||||
PATCHVERSTRING,
|
||||
SHOWGBABOOT,
|
||||
PAYLOADSPLASH
|
||||
#ifdef DEV
|
||||
, PATCHACCESS
|
||||
#endif
|
||||
PATCHACCESS
|
||||
};
|
||||
|
||||
typedef struct __attribute__((packed))
|
||||
|
@ -20,7 +20,6 @@
|
||||
* Notices displayed by works containing it.
|
||||
*/
|
||||
|
||||
#ifdef DEV
|
||||
#include "exceptions.h"
|
||||
#include "fs.h"
|
||||
#include "strings.h"
|
||||
@ -197,5 +196,4 @@ void detectAndProcessExceptionDumps(void)
|
||||
waitInput();
|
||||
mcuPowerOff();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
@ -20,7 +20,6 @@
|
||||
* Notices displayed by works containing it.
|
||||
*/
|
||||
|
||||
#ifdef DEV
|
||||
#pragma once
|
||||
|
||||
#include "types.h"
|
||||
@ -45,5 +44,4 @@ typedef struct __attribute__((packed))
|
||||
|
||||
void installArm9Handlers(void);
|
||||
void installArm11Handlers(u32 *exceptionsPage, u32 stackAddress, u32 codeSetOffset);
|
||||
void detectAndProcessExceptionDumps(void);
|
||||
#endif
|
||||
void detectAndProcessExceptionDumps(void);
|
232
source/firm.c
232
source/firm.c
@ -24,6 +24,7 @@
|
||||
#include "config.h"
|
||||
#include "utils.h"
|
||||
#include "fs.h"
|
||||
#include "exceptions.h"
|
||||
#include "patches.h"
|
||||
#include "memory.h"
|
||||
#include "strings.h"
|
||||
@ -36,10 +37,6 @@
|
||||
#include "pin.h"
|
||||
#include "../build/injector.h"
|
||||
|
||||
#ifdef DEV
|
||||
#include "exceptions.h"
|
||||
#endif
|
||||
|
||||
extern u16 launchedFirmTidLow[8]; //Defined in start.s
|
||||
|
||||
static firmHeader *firm = (firmHeader *)0x24000000;
|
||||
@ -73,10 +70,6 @@ void main(void)
|
||||
//Attempt to read the configuration file
|
||||
needConfig = readConfig() ? MODIFY_CONFIGURATION : CREATE_CONFIGURATION;
|
||||
|
||||
#ifdef DEV
|
||||
detectAndProcessExceptionDumps();
|
||||
#endif
|
||||
|
||||
//Determine if this is a firmlaunch boot
|
||||
if(launchedFirmTidLow[5] != 0)
|
||||
{
|
||||
@ -90,10 +83,6 @@ void main(void)
|
||||
nandType = (FirmwareSource)BOOTCFG_NAND;
|
||||
firmSource = (FirmwareSource)BOOTCFG_FIRM;
|
||||
isA9lh = BOOTCFG_A9LH != 0;
|
||||
|
||||
#ifdef DEV
|
||||
if(isA9lh) installArm9Handlers();
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -103,9 +92,7 @@ void main(void)
|
||||
//Determine if booting with A9LH
|
||||
isA9lh = !PDN_SPI_CNT;
|
||||
|
||||
#ifdef DEV
|
||||
if(isA9lh) installArm9Handlers();
|
||||
#endif
|
||||
if(isA9lh) detectAndProcessExceptionDumps();
|
||||
|
||||
//Get pressed buttons
|
||||
u32 pressed = HID_PAD;
|
||||
@ -137,8 +124,13 @@ void main(void)
|
||||
}
|
||||
}
|
||||
|
||||
if(needConfig == DONT_CONFIGURE)
|
||||
{
|
||||
if(MULTICONFIG(DEVOPTIONS) != 0 && isA9lh) installArm9Handlers();
|
||||
}
|
||||
|
||||
//Boot options aren't being forced
|
||||
if(needConfig != DONT_CONFIGURE)
|
||||
else
|
||||
{
|
||||
bool pinExists = MULTICONFIG(PIN) != 0 && verifyPin();
|
||||
|
||||
@ -153,6 +145,8 @@ void main(void)
|
||||
pressed = HID_PAD;
|
||||
}
|
||||
|
||||
if(MULTICONFIG(DEVOPTIONS) != 0 && isA9lh) installArm9Handlers();
|
||||
|
||||
if(isA9lh && !CFG_BOOTENV && pressed == SAFE_MODE)
|
||||
{
|
||||
nandType = FIRMWARE_SYSNAND;
|
||||
@ -170,7 +164,7 @@ void main(void)
|
||||
}
|
||||
else
|
||||
{
|
||||
if(CONFIG(PAYLOADSPLASH) && loadSplash()) pressed = HID_PAD;
|
||||
if(MULTICONFIG(SPLASH) == 1 && loadSplash()) pressed = HID_PAD;
|
||||
|
||||
/* If L and R/A/Select or one of the single payload buttons are pressed,
|
||||
chainload an external payload */
|
||||
@ -179,7 +173,7 @@ void main(void)
|
||||
|
||||
if(shouldLoadPayload) loadPayload(pressed);
|
||||
|
||||
if(!CONFIG(PAYLOADSPLASH)) loadSplash();
|
||||
if(MULTICONFIG(SPLASH) == 2) loadSplash();
|
||||
|
||||
//Determine if the user chose to use the SysNAND FIRM as default for a R boot
|
||||
bool useSysAsDefault = isA9lh ? CONFIG(USESYSFIRM) : false;
|
||||
@ -246,7 +240,8 @@ void main(void)
|
||||
writeConfig(needConfig, configTemp);
|
||||
}
|
||||
|
||||
u32 firmVersion = loadFirm(&firmType, firmSource);
|
||||
bool loadFromSd = CONFIG(SDFIRMSANDMODULES);
|
||||
u32 firmVersion = loadFirm(&firmType, firmSource, loadFromSd);
|
||||
|
||||
switch(firmType)
|
||||
{
|
||||
@ -263,11 +258,10 @@ void main(void)
|
||||
break;
|
||||
}
|
||||
|
||||
launchFirm(firmType);
|
||||
launchFirm(firmType, loadFromSd);
|
||||
}
|
||||
|
||||
#ifdef DEV
|
||||
static inline u32 loadFirm(FirmwareType *firmType, FirmwareSource firmSource)
|
||||
static inline u32 loadFirm(FirmwareType *firmType, FirmwareSource firmSource, bool loadFromSd)
|
||||
{
|
||||
section = firm->section;
|
||||
|
||||
@ -287,7 +281,7 @@ static inline u32 loadFirm(FirmwareType *firmType, FirmwareSource firmSource)
|
||||
//Load FIRM from CTRNAND
|
||||
u32 firmVersion = firmRead(firm, (u32)*firmType);
|
||||
|
||||
bool loadFromSd = false;
|
||||
bool mustLoadFromSd = false;
|
||||
|
||||
if(!isN3DS && *firmType == NATIVE_FIRM)
|
||||
{
|
||||
@ -303,84 +297,39 @@ static inline u32 loadFirm(FirmwareType *firmType, FirmwareSource firmSource)
|
||||
}
|
||||
|
||||
//We can't boot a 3.x/4.x NATIVE_FIRM, load one from SD
|
||||
else if(firmVersion < 0x25) loadFromSd = true;
|
||||
else if(firmVersion < 0x25) mustLoadFromSd = true;
|
||||
}
|
||||
|
||||
u32 firmSize = fileRead(firm, *firmType == NATIVE_FIRM1X2X ? firmwareFiles[0] : firmwareFiles[(u32)*firmType], 0x400000);
|
||||
|
||||
if(firmSize > 0)
|
||||
if(loadFromSd || mustLoadFromSd)
|
||||
{
|
||||
if(memcmp(firm, "FIRM", 4) != 0)
|
||||
u32 firmSize = fileRead(firm, *firmType == NATIVE_FIRM1X2X ? firmwareFiles[0] : firmwareFiles[(u32)*firmType], 0x400000);
|
||||
|
||||
if(firmSize > 0)
|
||||
{
|
||||
u8 cetk[0xA50];
|
||||
if(memcmp(firm, "FIRM", 4) != 0)
|
||||
{
|
||||
u8 cetk[0xA50];
|
||||
|
||||
if(fileRead(cetk, *firmType == NATIVE_FIRM1X2X ? cetkFiles[0] : cetkFiles[(u32)*firmType], sizeof(cetk)))
|
||||
decryptNusFirm(cetk, (u8 *)firm, firmSize);
|
||||
if(fileRead(cetk, *firmType == NATIVE_FIRM1X2X ? cetkFiles[0] : cetkFiles[(u32)*firmType], sizeof(cetk)))
|
||||
decryptNusFirm(cetk, (u8 *)firm, firmSize);
|
||||
}
|
||||
|
||||
//Check that the SD FIRM is right for the console from the ARM9 section address
|
||||
if((section[3].offset ? section[3].address : section[2].address) != (isN3DS ? (u8 *)0x8006000 : (u8 *)0x8006800))
|
||||
error("The firmware.bin in /luma is not valid for your\nconsole, or corrupted");
|
||||
|
||||
firmVersion = 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
//Check that the SD FIRM is right for the console from the ARM9 section address
|
||||
if((section[3].offset ? section[3].address : section[2].address) != (isN3DS ? (u8 *)0x8006000 : (u8 *)0x8006800))
|
||||
error("The firmware.bin in /luma is not valid for your\nconsole, or corrupted");
|
||||
|
||||
firmVersion = 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
if(firmVersion != 0xFFFFFFFF)
|
||||
{
|
||||
if(loadFromSd) error("An old unsupported FIRM has been detected.\nCopy a valid firmware.bin in /luma to boot");
|
||||
if(mustLoadFromSd) error("An old unsupported FIRM has been detected.\nCopy a firmware.bin in /luma to boot");
|
||||
decryptExeFs((u8 *)firm);
|
||||
}
|
||||
|
||||
return firmVersion;
|
||||
}
|
||||
#else
|
||||
static inline u32 loadFirm(FirmwareType *firmType, FirmwareSource firmSource)
|
||||
{
|
||||
section = firm->section;
|
||||
|
||||
//Load FIRM from CTRNAND
|
||||
u32 firmVersion = firmRead(firm, (u32)*firmType);
|
||||
|
||||
if(!isN3DS && *firmType == NATIVE_FIRM)
|
||||
{
|
||||
if(firmVersion < 0x18)
|
||||
{
|
||||
//We can't boot < 3.x EmuNANDs
|
||||
if(firmSource != FIRMWARE_SYSNAND)
|
||||
error("An old unsupported EmuNAND has been detected.\nLuma3DS is unable to boot it");
|
||||
|
||||
if(BOOTCFG_SAFEMODE != 0) error("SAFE_MODE is not supported on 1.x/2.x FIRM");
|
||||
|
||||
*firmType = NATIVE_FIRM1X2X;
|
||||
}
|
||||
|
||||
//We can't boot a 3.x/4.x NATIVE_FIRM, load one from SD
|
||||
else if(firmVersion < 0x25)
|
||||
{
|
||||
u32 firmSize = fileRead(firm, "/luma/firmware.bin", 0x400000);
|
||||
|
||||
if(firmSize > 0)
|
||||
{
|
||||
if(memcmp(firm, "FIRM", 4) != 0)
|
||||
{
|
||||
u8 cetk[0xA50];
|
||||
|
||||
if(fileRead(cetk, "/luma/cetk", sizeof(cetk)))
|
||||
decryptNusFirm(cetk, (u8 *)firm, firmSize);
|
||||
}
|
||||
|
||||
if(section[2].address != (u8 *)0x8006800) firmVersion = 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
if(firmVersion != 0xFFFFFFFF) error("An old unsupported FIRM has been detected.\nCopy a valid firmware.bin in /luma to boot");
|
||||
}
|
||||
}
|
||||
|
||||
if(firmVersion != 0xFFFFFFFF) decryptExeFs((u8 *)firm);
|
||||
|
||||
return firmVersion;
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline void patchNativeFirm(u32 firmVersion, FirmwareSource nandType, u32 emuHeader, bool isA9lh)
|
||||
{
|
||||
@ -402,19 +351,12 @@ static inline void patchNativeFirm(u32 firmVersion, FirmwareSource nandType, u32
|
||||
process9MemAddr;
|
||||
u8 *process9Offset = getProcess9(arm9Section + 0x15000, section[2].size - 0x15000, &process9Size, &process9MemAddr);
|
||||
|
||||
#ifdef DEV
|
||||
//Find Kernel11 SVC table and handler, exceptions page and free space locations
|
||||
u32 baseK11VA;
|
||||
u8 *freeK11Space;
|
||||
u32 *arm11SvcHandler,
|
||||
*arm11ExceptionsPage,
|
||||
*arm11SvcTable = getKernel11Info(arm11Section1, section[1].size, &baseK11VA, &freeK11Space, &arm11SvcHandler, &arm11ExceptionsPage);
|
||||
#else
|
||||
//Find Kernel11 SVC table and free space locations
|
||||
u32 baseK11VA;
|
||||
u8 *freeK11Space;
|
||||
u32 *arm11SvcTable = getKernel11Info(arm11Section1, section[1].size, &baseK11VA, &freeK11Space);
|
||||
#endif
|
||||
|
||||
//Apply signature patches
|
||||
patchSignatureChecks(process9Offset, process9Size);
|
||||
@ -444,27 +386,22 @@ static inline void patchNativeFirm(u32 firmVersion, FirmwareSource nandType, u32
|
||||
|
||||
implementSvcGetCFWInfo(arm11Section1, arm11SvcTable, baseK11VA, &freeK11Space);
|
||||
|
||||
#ifdef DEV
|
||||
//Apply UNITINFO patch
|
||||
if(MULTICONFIG(DEVOPTIONS) == 1) patchUnitInfoValueSet(arm9Section, section[2].size);
|
||||
if(MULTICONFIG(DEVOPTIONS) == 2) patchUnitInfoValueSet(arm9Section, section[2].size);
|
||||
|
||||
if(isA9lh && MULTICONFIG(DEVOPTIONS) != 2)
|
||||
if(isA9lh && MULTICONFIG(DEVOPTIONS) != 0)
|
||||
{
|
||||
//Install ARM11 exception handlers
|
||||
u32 codeSetOffset;
|
||||
u32 stackAddress = getInfoForArm11ExceptionHandlers(arm11Section1, section[1].size, &codeSetOffset);
|
||||
//ARM11 exception handlers
|
||||
u32 codeSetOffset,
|
||||
stackAddress = getInfoForArm11ExceptionHandlers(arm11Section1, section[1].size, &codeSetOffset);
|
||||
installArm11Handlers(arm11ExceptionsPage, stackAddress, codeSetOffset);
|
||||
patchSvcBreak11(arm11Section1, arm11SvcTable);
|
||||
patchKernel11Panic(arm11Section1, section[1].size);
|
||||
|
||||
//Kernel9/Process9 debugging
|
||||
//ARM9 exception handlers
|
||||
patchArm9ExceptionHandlersInstall(arm9Section, section[2].size);
|
||||
patchSvcBreak9(arm9Section, section[2].size, (u32)section[2].address);
|
||||
patchKernel9Panic(arm9Section, section[2].size);
|
||||
|
||||
//Stub svcBreak11 with "bkpt 65535"
|
||||
patchSvcBreak11(arm11Section1, arm11SvcTable);
|
||||
|
||||
//Stub kernel11Panic with "bkpt 65534"
|
||||
patchKernel11Panic(arm11Section1, section[1].size);
|
||||
}
|
||||
|
||||
if(CONFIG(PATCHACCESS))
|
||||
@ -473,7 +410,6 @@ static inline void patchNativeFirm(u32 firmVersion, FirmwareSource nandType, u32
|
||||
patchK11ModuleChecks(arm11Section1, section[1].size, &freeK11Space);
|
||||
patchP9AccessChecks(process9Offset, process9Size);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void patchLegacyFirm(FirmwareType firmType)
|
||||
@ -489,10 +425,8 @@ static inline void patchLegacyFirm(FirmwareType firmType)
|
||||
|
||||
applyLegacyFirmPatches((u8 *)firm, firmType);
|
||||
|
||||
#ifdef DEV
|
||||
//Apply UNITINFO patch
|
||||
if(MULTICONFIG(DEVOPTIONS) == 1) patchUnitInfoValueSet(arm9Section, section[3].size);
|
||||
#endif
|
||||
if(MULTICONFIG(DEVOPTIONS) == 2) patchUnitInfoValueSet(arm9Section, section[3].size);
|
||||
}
|
||||
|
||||
static inline void patch1x2xNativeAndSafeFirm(void)
|
||||
@ -509,18 +443,15 @@ static inline void patch1x2xNativeAndSafeFirm(void)
|
||||
}
|
||||
else patchOldFirmWrites(arm9Section, section[2].size);
|
||||
|
||||
#ifdef DEV
|
||||
if(MULTICONFIG(DEVOPTIONS) != 2)
|
||||
if(MULTICONFIG(DEVOPTIONS) != 0)
|
||||
{
|
||||
//Kernel9/Process9 debugging
|
||||
//ARM9 exception handlers
|
||||
patchArm9ExceptionHandlersInstall(arm9Section, section[2].size);
|
||||
patchSvcBreak9(arm9Section, section[2].size, (u32)section[2].address);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef DEV
|
||||
static inline void copySection0AndInjectSystemModules(FirmwareType firmType)
|
||||
static inline void copySection0AndInjectSystemModules(FirmwareType firmType, bool loadFromSd)
|
||||
{
|
||||
u32 srcModuleSize,
|
||||
dstModuleSize;
|
||||
@ -531,15 +462,22 @@ static inline void copySection0AndInjectSystemModules(FirmwareType firmType)
|
||||
srcModuleSize = *(u32 *)(src + 0x104) * 0x200;
|
||||
const char *moduleName = (char *)(src + 0x200);
|
||||
|
||||
char fileName[30] = "/luma/sysmodules/";
|
||||
const char *ext = ".cxi";
|
||||
u32 fileSize;
|
||||
|
||||
//Read modules from files if they exist
|
||||
concatenateStrings(fileName, moduleName);
|
||||
concatenateStrings(fileName, ext);
|
||||
if(loadFromSd)
|
||||
{
|
||||
char fileName[30] = "/luma/sysmodules/";
|
||||
const char *ext = ".cxi";
|
||||
|
||||
u32 fileSize = fileRead(dst, fileName, 2 * srcModuleSize);
|
||||
if(fileSize) dstModuleSize = fileSize;
|
||||
//Read modules from files if they exist
|
||||
concatenateStrings(fileName, moduleName);
|
||||
concatenateStrings(fileName, ext);
|
||||
|
||||
fileSize = fileRead(dst, fileName, 2 * srcModuleSize);
|
||||
}
|
||||
else fileSize = 0;
|
||||
|
||||
if(fileSize > 0) dstModuleSize = fileSize;
|
||||
else
|
||||
{
|
||||
const void *module;
|
||||
@ -559,57 +497,17 @@ static inline void copySection0AndInjectSystemModules(FirmwareType firmType)
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
static inline void copySection0AndInjectSystemModules(void)
|
||||
|
||||
static inline void launchFirm(FirmwareType firmType, bool loadFromSd)
|
||||
{
|
||||
u32 srcModuleSize,
|
||||
dstModuleSize;
|
||||
|
||||
for(u8 *src = (u8 *)firm + section[0].offset, *srcEnd = src + section[0].size, *dst = section[0].address;
|
||||
src < srcEnd; src += srcModuleSize, dst += dstModuleSize)
|
||||
{
|
||||
srcModuleSize = *(u32 *)(src + 0x104) * 0x200;
|
||||
const char *moduleName = (const char *)(src + 0x200);
|
||||
|
||||
const void *module;
|
||||
|
||||
if(memcmp(moduleName, "loader", 6) == 0)
|
||||
{
|
||||
module = injector;
|
||||
dstModuleSize = injector_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
module = src;
|
||||
dstModuleSize = srcModuleSize;
|
||||
}
|
||||
|
||||
memcpy(dst, module, dstModuleSize);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline void launchFirm(FirmwareType firmType)
|
||||
{
|
||||
#ifdef DEV
|
||||
//Allow module injection and/or inject 3ds_injector on new NATIVE_FIRMs and LGY FIRMs
|
||||
u32 sectionNum;
|
||||
if(firmType != SAFE_FIRM && firmType != NATIVE_FIRM1X2X)
|
||||
if(firmType == NATIVE_FIRM || (loadFromSd && firmType != SAFE_FIRM && firmType != NATIVE_FIRM1X2X))
|
||||
{
|
||||
copySection0AndInjectSystemModules(firmType);
|
||||
copySection0AndInjectSystemModules(firmType, loadFromSd);
|
||||
sectionNum = 1;
|
||||
}
|
||||
else sectionNum = 0;
|
||||
#else
|
||||
//If we're booting NATIVE_FIRM, section0 needs to be copied separately to inject 3ds_injector
|
||||
u32 sectionNum;
|
||||
if(firmType == NATIVE_FIRM)
|
||||
{
|
||||
copySection0AndInjectSystemModules();
|
||||
sectionNum = 1;
|
||||
}
|
||||
else sectionNum = 0;
|
||||
#endif
|
||||
|
||||
//Copy FIRM sections to respective memory locations
|
||||
for(; sectionNum < 4 && section[sectionNum].size != 0; sectionNum++)
|
||||
|
@ -47,15 +47,9 @@ typedef struct firmHeader {
|
||||
firmSectionHeader section[4];
|
||||
} firmHeader;
|
||||
|
||||
static inline u32 loadFirm(FirmwareType *firmType, FirmwareSource firmSource);
|
||||
static inline u32 loadFirm(FirmwareType *firmType, FirmwareSource firmSource, bool loadFromSd);
|
||||
static inline void patchNativeFirm(u32 firmVersion, FirmwareSource nandType, u32 emuHeader, bool isA9lh);
|
||||
static inline void patchLegacyFirm(FirmwareType firmType);
|
||||
static inline void patch1x2xNativeAndSafeFirm(void);
|
||||
|
||||
#ifdef DEV
|
||||
static inline void copySection0AndInjectSystemModules(FirmwareType firmType);
|
||||
#else
|
||||
static inline void copySection0AndInjectSystemModules(void);
|
||||
#endif
|
||||
|
||||
static inline void launchFirm(FirmwareType firmType);
|
||||
static inline void copySection0AndInjectSystemModules(FirmwareType firmType, bool loadFromSd);
|
||||
static inline void launchFirm(FirmwareType firmType, bool loadFromSd);
|
@ -196,7 +196,6 @@ u32 firmRead(void *dest, u32 firmType)
|
||||
return firmVersion;
|
||||
}
|
||||
|
||||
#ifdef DEV
|
||||
void findDumpFile(const char *path, char *fileName)
|
||||
{
|
||||
DIR dir;
|
||||
@ -216,5 +215,4 @@ void findDumpFile(const char *path, char *fileName)
|
||||
}
|
||||
|
||||
f_closedir(&dir);
|
||||
}
|
||||
#endif
|
||||
}
|
@ -35,7 +35,4 @@ bool fileWrite(const void *buffer, const char *path, u32 size);
|
||||
void fileDelete(const char *path);
|
||||
void loadPayload(u32 pressed);
|
||||
u32 firmRead(void *dest, u32 firmType);
|
||||
|
||||
#ifdef DEV
|
||||
void findDumpFile(const char *path, char *fileName);
|
||||
#endif
|
||||
void findDumpFile(const char *path, char *fileName);
|
@ -29,10 +29,7 @@
|
||||
#include "config.h"
|
||||
#include "../build/rebootpatch.h"
|
||||
#include "../build/svcGetCFWInfopatch.h"
|
||||
|
||||
#ifdef DEV
|
||||
#include "../build/k11modulespatch.h"
|
||||
#endif
|
||||
|
||||
u8 *getProcess9(u8 *pos, u32 size, u32 *process9Size, u32 *process9MemAddr)
|
||||
{
|
||||
@ -45,7 +42,6 @@ u8 *getProcess9(u8 *pos, u32 size, u32 *process9Size, u32 *process9MemAddr)
|
||||
return off - 0x204 + (*(u32 *)(off - 0x64) * 0x200) + 0x200;
|
||||
}
|
||||
|
||||
#ifdef DEV
|
||||
u32 *getKernel11Info(u8 *pos, u32 size, u32 *baseK11VA, u8 **freeK11Space, u32 **arm11SvcHandler, u32 **arm11ExceptionsPage)
|
||||
{
|
||||
const u8 pattern[] = {0x00, 0xB0, 0x9C, 0xE5};
|
||||
@ -65,26 +61,6 @@ u32 *getKernel11Info(u8 *pos, u32 size, u32 *baseK11VA, u8 **freeK11Space, u32 *
|
||||
|
||||
return arm11SvcTable;
|
||||
}
|
||||
#else
|
||||
u32 *getKernel11Info(u8 *pos, u32 size, u32 *baseK11VA, u8 **freeK11Space)
|
||||
{
|
||||
const u8 pattern[] = {0x00, 0xB0, 0x9C, 0xE5};
|
||||
|
||||
u32 *arm11ExceptionsPage = (u32 *)memsearch(pos, pattern, size, sizeof(pattern)) - 0xB;
|
||||
|
||||
u32 svcOffset = (-((arm11ExceptionsPage[2] & 0xFFFFFF) << 2) & (0xFFFFFF << 2)) - 8; //Branch offset + 8 for prefetch
|
||||
u32 pointedInstructionVA = 0xFFFF0008 - svcOffset;
|
||||
*baseK11VA = pointedInstructionVA & 0xFFFF0000; //This assumes that the pointed instruction has an offset < 0x10000, iirc that's always the case
|
||||
u32 *arm11SvcTable = (u32 *)(pos + *(u32 *)(pos + pointedInstructionVA - *baseK11VA + 8) - *baseK11VA); //SVC handler address
|
||||
while(*arm11SvcTable) arm11SvcTable++; //Look for SVC0 (NULL)
|
||||
|
||||
const u8 pattern2[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
|
||||
|
||||
*freeK11Space = memsearch(pos, pattern2, size, sizeof(pattern2)) + 1;
|
||||
|
||||
return arm11SvcTable;
|
||||
}
|
||||
#endif
|
||||
|
||||
void patchSignatureChecks(u8 *pos, u32 size)
|
||||
{
|
||||
@ -186,11 +162,7 @@ void implementSvcGetCFWInfo(u8 *pos, u32 *arm11SvcTable, u32 baseK11VA, u8 **fre
|
||||
}
|
||||
else isRelease = rev[4] == 0;
|
||||
|
||||
#ifdef DEV
|
||||
info->flags = 1 /* dev build */ | ((isRelease ? 1 : 0) << 1) /* is release */;
|
||||
#else
|
||||
info->flags = 0 /* regular build */ | ((isRelease ? 1 : 0) << 1) /* is release */;
|
||||
#endif
|
||||
info->flags = isRelease ? 1 : 0;
|
||||
|
||||
arm11SvcTable[0x2E] = baseK11VA + *freeK11Space - pos; //Stubbed svc
|
||||
*freeK11Space += svcGetCFWInfo_size;
|
||||
@ -246,7 +218,6 @@ void applyLegacyFirmPatches(u8 *pos, FirmwareType firmType)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEV
|
||||
void patchArm9ExceptionHandlersInstall(u8 *pos, u32 size)
|
||||
{
|
||||
const u8 pattern[] = {0x03, 0xA0, 0xE3, 0x18};
|
||||
@ -372,5 +343,4 @@ void patchUnitInfoValueSet(u8 *pos, u32 size)
|
||||
|
||||
off[0] = isDevUnit ? 0 : 1;
|
||||
off[3] = 0xE3;
|
||||
}
|
||||
#endif
|
||||
}
|
@ -51,18 +51,10 @@ typedef struct __attribute__((packed))
|
||||
u32 config;
|
||||
} CFWInfo;
|
||||
|
||||
#ifdef DEV
|
||||
extern bool isDevUnit;
|
||||
#endif
|
||||
|
||||
u8 *getProcess9(u8 *pos, u32 size, u32 *process9Size, u32 *process9MemAddr);
|
||||
|
||||
#ifdef DEV
|
||||
u32 *getKernel11Info(u8 *pos, u32 size, u32 *baseK11VA, u8 **freeK11Space, u32 **arm11SvcHandler, u32 **arm11ExceptionsPage);
|
||||
#else
|
||||
u32 *getKernel11Info(u8 *pos, u32 size, u32 *baseK11VA, u8 **freeK11Space);
|
||||
#endif
|
||||
|
||||
void patchSignatureChecks(u8 *pos, u32 size);
|
||||
void patchTitleInstallMinVersionCheck(u8 *pos, u32 size);
|
||||
void patchFirmlaunches(u8 *pos, u32 size, u32 process9MemAddr);
|
||||
@ -71,8 +63,6 @@ void patchOldFirmWrites(u8 *pos, u32 size);
|
||||
void reimplementSvcBackdoor(u8 *pos, u32 *arm11SvcTable, u32 baseK11VA, u8 **freeK11Space);
|
||||
void implementSvcGetCFWInfo(u8 *pos, u32 *arm11SvcTable, u32 baseK11VA, u8 **freeK11Space);
|
||||
void applyLegacyFirmPatches(u8 *pos, FirmwareType firmType);
|
||||
|
||||
#ifdef DEV
|
||||
void patchArm9ExceptionHandlersInstall(u8 *pos, u32 size);
|
||||
u32 getInfoForArm11ExceptionHandlers(u8 *pos, u32 size, u32 *codeSetOffset);
|
||||
void patchSvcBreak9(u8 *pos, u32 size, u32 kernel9Address);
|
||||
@ -82,5 +72,4 @@ void patchKernel11Panic(u8 *pos, u32 size);
|
||||
void patchP9AccessChecks(u8 *pos, u32 size);
|
||||
void patchArm11SvcAccessChecks(u32 *arm11SvcHandler);
|
||||
void patchK11ModuleChecks(u8 *pos, u32 size, u8 **freeK11Space);
|
||||
void patchUnitInfoValueSet(u8 *pos, u32 size);
|
||||
#endif
|
||||
void patchUnitInfoValueSet(u8 *pos, u32 size);
|
Reference in New Issue
Block a user