Compare commits

...

33 Commits
v3.11 ... 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
Aurora
39a9eb5ccb Explicitly block Safe Mode access on A9LH
Prevents bricking
2016-03-24 17:05:19 +01:00
Aurora
c413b6d07f Simplified button stuff 2016-03-24 16:11:53 +01:00
Aurora
85a59264c9 Comment 2016-03-24 02:40:43 +01:00
Aurora
7f96e47b4f Updated sysNAND (A9LH) & SAFE_MODE FIRM update = brick 2016-03-24 02:26:04 +01:00
Aurora
02b5c69802 New way of launching payloads (L+R/up/down/right/left/START/SELECT/B/X/Y) 2016-03-24 01:57:56 +01:00
Aurora
b5eb108393 Increased the screen-init brightness 2016-03-24 00:11:02 +01:00
Aurora
0a9cd09cc3 Reorganized folder layout, cleaned Makefile (we do not need Python) 2016-03-23 20:29:19 +01:00
Aurora
af451b4997 Update submodules 2016-03-23 17:51:21 +01:00
Aurora
a5f8ccc3ea Fixed loader.bin not cleared after compiling 2016-03-23 17:09:52 +01:00
Aurora
28cdcfed9c Updated ReadMe 2016-03-23 17:00:18 +01:00
Aurora
ea3e45d40a Move clearScreens calls and screen-init checks 2016-03-23 16:14:28 +01:00
Aurora
8daf3ebe3f Detect emuNAND first 2016-03-23 15:52:21 +01:00
Aurora
7ad55ed61e Chainloading works from CakeBrah too, by now 2016-03-23 15:26:52 +01:00
Aurora
96e46b2234 Remove unneeded casts 2016-03-23 15:16:40 +01:00
Aurora
094b88b6aa Forgot this 2016-03-23 15:03:14 +01:00
Aurora
03a6e343db Merge emunand.bin, reboot.bin and loader.bin in the main executable
Less SD accesses, more noob-proof
2016-03-23 15:00:28 +01:00
Aurora
b42f9ffb41 Warn that Updated SysNAND does not work if not using A9LH 2016-03-23 04:56:02 +01:00
Aurora
39280e397a Fix typo 2016-03-23 04:27:07 +01:00
Aurora
887707ea87 Better errors 2016-03-23 04:06:21 +01:00
Aurora
279f39bc13 Added error messages, moved emunand and reboot.bin to aurei/patches 2016-03-23 03:46:44 +01:00
Aurora
b7b734bad1 Added configuration menu (thanks to Cakes for the screen printing code - no more flags!), auto-delete of patched FIRMs when switching to/from A9LH or the CFW gets updated, moved screen init from the loader, general reorganization 2016-03-23 02:46:41 +01:00
Aurora
d01d9b53f2 No need to search for the Process9 .code, calculate it (one memsearch less) 2016-03-21 20:27:01 +01:00
Aurora
c542bc5cf3 More readable this way 2016-03-21 19:20:26 +01:00
Aurora
1f5b824c27 Clean-up, optimized the SDMMC struct searching function, lots of useless casts removed, Process9 only gets searched once 2016-03-21 19:14:32 +01:00
Aurora
cb84a6c7ea Added interrupts disabling to the deinit function
Did not cause any issues, but it is better this way
2016-03-21 04:58:20 +01:00
Aurora
61564e5fcf Check for emuNAND earlier 2016-03-21 04:39:00 +01:00
36 changed files with 779 additions and 483 deletions

2
.gitignore vendored
View File

@@ -1,6 +1,4 @@
out
CakeHax
CakeBrah
build
loader/build
*.bin

View File

@@ -4,25 +4,16 @@ CC := arm-none-eabi-gcc
AS := arm-none-eabi-as
LD := arm-none-eabi-ld
OC := arm-none-eabi-objcopy
OPENSSL := openssl
PYTHON3 := python
PYTHON_VER_MAJOR := $(word 2, $(subst ., , $(shell python --version 2>&1)))
ifneq ($(PYTHON_VER_MAJOR), 3)
PYTHON3 := py -3
endif
name := AuReiNand
dir_source := source
dir_data := data
dir_build := build
dir_mset := CakeHax
dir_out := out
dir_emu := emunand
dir_reboot := reboot
dir_ninjhax := CakeBrah
dir_patches := patches
dir_loader := loader
dir_mset := CakeHax
dir_ninjhax := CakeBrah
dir_build := build
dir_out := out
ASFLAGS := -mlittle-endian -mcpu=arm946e-s -march=armv5te
CFLAGS := -Wall -Wextra -MMD -MP -marm $(ASFLAGS) -fno-builtin -fshort-wchar -std=c11 -Wno-main -O2 -ffast-math
@@ -34,25 +25,19 @@ objects_cfw = $(patsubst $(dir_source)/%.s, $(dir_build)/%.o, \
.PHONY: all
all: launcher a9lh emunand reboot ninjhax loader
all: launcher a9lh ninjhax
.PHONY: launcher
launcher: $(dir_out)/$(name).dat
launcher: $(dir_out)/$(name).dat
.PHONY: a9lh
a9lh: $(dir_out)/arm9loaderhax.bin
.PHONY: emunand
emunand: $(dir_out)/aurei/emunand/emunand.bin
.PHONY: reboot
reboot: $(dir_out)/aurei/reboot/reboot.bin
.PHONY: ninjhax
ninjhax: $(dir_out)/3ds/$(name)
.PHONY: loader
loader: $(dir_out)/aurei/loader.bin
.PHONY: release
release: $(dir_out)/$(name).zip
.PHONY: clean
clean:
@@ -61,35 +46,36 @@ clean:
@rm -rf $(dir_out) $(dir_build)
@$(MAKE) -C $(dir_loader) clean
$(dir_out)/$(name).dat: $(dir_build)/main.bin $(dir_out)/aurei
@$(MAKE) $(FLAGS) -C $(dir_mset) launcher
dd if=$(dir_build)/main.bin of=$@ bs=512 seek=144
$(dir_out):
@mkdir -p "$(dir_out)/aurei/payloads"
$(dir_out)/arm9loaderhax.bin: $(dir_build)/main.bin $(dir_out)/aurei
$(dir_out)/$(name).dat: $(dir_build)/main.bin $(dir_out)
@$(MAKE) $(FLAGS) -C $(dir_mset) launcher
@dd if=$(dir_build)/main.bin of=$@ bs=512 seek=144
$(dir_out)/arm9loaderhax.bin: $(dir_build)/main.bin $(dir_out)
@cp -av $(dir_build)/main.bin $@
$(dir_out)/3ds/$(name):
$(dir_out)/3ds/$(name): $(dir_out)
@mkdir -p "$(dir_out)/3ds/$(name)"
@$(MAKE) $(FLAGS) -C $(dir_ninjhax)
@mv $(dir_out)/$(name).3dsx $@
@mv $(dir_out)/$(name).smdh $@
$(dir_out)/aurei:
@mkdir -p "$(dir_out)/aurei"
$(dir_out)/$(name).zip: launcher a9lh ninjhax
@cd $(dir_out) && zip -9 -r $(name) *
$(dir_out)/aurei/emunand/emunand.bin: $(dir_emu)/emuCode.s
$(dir_build)/patches.h: $(dir_patches)/emunand.s $(dir_patches)/reboot.s
@mkdir -p "$(dir_build)"
@armips $<
@mkdir -p "$(dir_out)/aurei/emunand"
@mv emunand.bin $@
@armips $(word 2,$^)
@mv emunand.bin reboot.bin $(dir_build)
@bin2c -o $@ -n emunand $(dir_build)/emunand.bin -n reboot $(dir_build)/reboot.bin
$(dir_out)/aurei/reboot/reboot.bin: $(dir_reboot)/rebootCode.s
@armips $<
@mkdir -p "$(dir_out)/aurei/reboot"
@mv reboot.bin $@
$(dir_out)/aurei/loader.bin: $(dir_out)/aurei $(dir_loader)/Makefile
$(dir_build)/loader.h: $(dir_loader)/Makefile
@$(MAKE) -C $(dir_loader)
@mv $(dir_loader)/loader.bin $@
@mv $(dir_loader)/loader.bin $(dir_build)
@bin2c -o $@ -n loader $(dir_build)/loader.bin
$(dir_build)/main.bin: $(dir_build)/main.elf
$(OC) -S -O binary $< $@
@@ -98,7 +84,7 @@ $(dir_build)/main.elf: $(objects_cfw)
# FatFs requires libgcc for __aeabi_uidiv
$(CC) -nostartfiles $(LDFLAGS) -T linker.ld $(OUTPUT_OPTION) $^
$(dir_build)/%.o: $(dir_source)/%.c
$(dir_build)/%.o: $(dir_source)/%.c $(dir_build)/patches.h $(dir_build)/loader.h
@mkdir -p "$(@D)"
$(COMPILE.c) $(OUTPUT_OPTION) $<

View File

@@ -3,7 +3,7 @@
**Compiling:**
You'll need armips added to your Path. [HERE](https://www.dropbox.com/s/ceuv2qeqp38lpah/armips.exe?dl=0) is a pre-compiled version.
You'll need armips and [bin2c](https://sourceforge.net/projects/bin2c/) added to your Path. [HERE](http://www91.zippyshare.com/v/ePGpjk9r/file.html) is a pre-compiled version of armips.
Lastly, just run Make and everything should work!
@@ -13,12 +13,20 @@ Copy everything in 'out' folder to SD root and run!
See https://github.com/Reisyukaku/ReiNand and http://gbatemp.net/threads/reinand-mod-o3ds-n3ds-sysnand.411110
The FIRMs you need are here:
http://www99.zippyshare.com/v/kEIiQl0x/file.html
The FIRMs you need are [HERE](http://www99.zippyshare.com/v/kEIiQl0x/file.html).
**Credits:**
Rei as this is 99% his code (this is no more than a mod)
Rei as this is mostly his code.
Everyone he credited on his GitHub :P
The offset to detect the console, and to calculate the O3DS NAND CTR are from Decrypt9.
tiniVi suggested me a way to detect a A9LH environment, and figured out screen deinit.
Delebile provided me with the FIRM writes blocking patch.
A skilled reverser gave me the new reboot patch.
The screen init code is from dark_samus, bil1s, Normmatt, delebile and everyone who contributed.
The code for printing to the screen is from CakesFW.

View File

@@ -2,13 +2,13 @@
#include "types.h"
#define HID_PAD ((~*(vu16 *)0x10146000) & 0xFFF)
#define BUTTON_B (1 << 1)
#define BUTTON_X (1 << 10)
#define BUTTON_Y (1 << 11)
#define BUTTON_SELECT (1 << 2)
#define BUTTON_START (1 << 3)
#define BUTTON_RIGHT (1 << 4)
#define BUTTON_LEFT (1 << 5)
#define BUTTON_UP (1 << 6)
#define BUTTON_DOWN (1 << 7)
#define HID_PAD (*(vu16 *)0x10146000 ^ 0xFFF)
#define BUTTON_B (1 << 1)
#define BUTTON_X (1 << 10)
#define BUTTON_Y (1 << 11)
#define BUTTON_SELECT (1 << 2)
#define BUTTON_START (1 << 3)
#define BUTTON_RIGHT (1 << 4)
#define BUTTON_LEFT (1 << 5)
#define BUTTON_UP (1 << 6)
#define BUTTON_DOWN (1 << 7)

View File

@@ -1,98 +0,0 @@
#include "i2c.h"
//-----------------------------------------------------------------------------
static const struct { u8 bus_id, reg_addr; } dev_data[] = {
{0, 0x4A}, {0, 0x7A}, {0, 0x78},
{1, 0x4A}, {1, 0x78}, {1, 0x2C},
{1, 0x2E}, {1, 0x40}, {1, 0x44},
{2, 0xD6}, {2, 0xD0}, {2, 0xD2},
{2, 0xA4}, {2, 0x9A}, {2, 0xA0},
};
static inline u8 i2cGetDeviceBusId(u8 device_id) {
return dev_data[device_id].bus_id;
}
static inline u8 i2cGetDeviceRegAddr(u8 device_id) {
return dev_data[device_id].reg_addr;
}
//-----------------------------------------------------------------------------
static vu8* reg_data_addrs[] = {
(vu8*)(I2C1_REG_OFF + I2C_REG_DATA),
(vu8*)(I2C2_REG_OFF + I2C_REG_DATA),
(vu8*)(I2C3_REG_OFF + I2C_REG_DATA),
};
static inline vu8* i2cGetDataReg(u8 bus_id) {
return reg_data_addrs[bus_id];
}
//-----------------------------------------------------------------------------
static vu8* reg_cnt_addrs[] = {
(vu8*)(I2C1_REG_OFF + I2C_REG_CNT),
(vu8*)(I2C2_REG_OFF + I2C_REG_CNT),
(vu8*)(I2C3_REG_OFF + I2C_REG_CNT),
};
static inline vu8* i2cGetCntReg(u8 bus_id) {
return reg_cnt_addrs[bus_id];
}
//-----------------------------------------------------------------------------
static inline void i2cWaitBusy(u8 bus_id) {
while (*i2cGetCntReg(bus_id) & 0x80);
}
static inline u32 i2cGetResult(u8 bus_id) {
i2cWaitBusy(bus_id);
return (*i2cGetCntReg(bus_id) >> 4) & 1;
}
static void i2cStop(u8 bus_id, u8 arg0) {
*i2cGetCntReg(bus_id) = (arg0 << 5) | 0xC0;
i2cWaitBusy(bus_id);
*i2cGetCntReg(bus_id) = 0xC5;
}
//-----------------------------------------------------------------------------
static u32 i2cSelectDevice(u8 bus_id, u8 dev_reg) {
i2cWaitBusy(bus_id);
*i2cGetDataReg(bus_id) = dev_reg;
*i2cGetCntReg(bus_id) = 0xC2;
return i2cGetResult(bus_id);
}
static u32 i2cSelectRegister(u8 bus_id, u8 reg) {
i2cWaitBusy(bus_id);
*i2cGetDataReg(bus_id) = reg;
*i2cGetCntReg(bus_id) = 0xC0;
return i2cGetResult(bus_id);
}
//-----------------------------------------------------------------------------
u32 i2cWriteRegister(u8 dev_id, u8 reg, u8 data) {
u8 bus_id = i2cGetDeviceBusId(dev_id);
u8 dev_addr = i2cGetDeviceRegAddr(dev_id);
for (int i = 0; i < 8; i++) {
if (i2cSelectDevice(bus_id, dev_addr) && i2cSelectRegister(bus_id, reg)) {
i2cWaitBusy(bus_id);
*i2cGetDataReg(bus_id) = data;
*i2cGetCntReg(bus_id) = 0xC1;
i2cStop(bus_id, 0);
if (i2cGetResult(bus_id))
return 1;
}
*i2cGetCntReg(bus_id) = 0xC5;
i2cWaitBusy(bus_id);
}
return 0;
}

View File

@@ -1,18 +0,0 @@
#pragma once
#include "types.h"
#define I2C1_REG_OFF 0x10161000
#define I2C2_REG_OFF 0x10144000
#define I2C3_REG_OFF 0x10148000
#define I2C_REG_DATA 0
#define I2C_REG_CNT 1
#define I2C_REG_CNTEX 2
#define I2C_REG_SCL 4
#define I2C_DEV_MCU 3
#define I2C_DEV_GYRO 10
#define I2C_DEV_IR 13
u32 i2cWriteRegister(u8 dev_id, u8 reg, u8 data);

View File

@@ -1,6 +1,5 @@
#include "types.h"
#include "buttons.h"
#include "screeninit.h"
#include "fatfs/ff.h"
#define PAYLOAD_ADDRESS 0x23F00000
@@ -10,7 +9,7 @@ static u32 loadPayload(const char *path){
unsigned int br;
if(f_open(&payload, path, FA_READ) == FR_OK)
{
f_read(&payload, (void*)PAYLOAD_ADDRESS, f_size(&payload), &br);
f_read(&payload, (void *)PAYLOAD_ADDRESS, f_size(&payload), &br);
f_close(&payload);
return 1;
@@ -35,9 +34,6 @@ void main(void){
((pressed & BUTTON_LEFT) && loadPayload("/aurei/payloads/left.bin")) ||
((pressed & BUTTON_UP) && loadPayload("/aurei/payloads/up.bin")) ||
((pressed & BUTTON_DOWN) && loadPayload("/aurei/payloads/down.bin")) ||
loadPayload("/aurei/payloads/default.bin")){
//Determine if screen was already inited
if(*(vu8 *)0x10141200 == 0x1) initLCD();
loadPayload("/aurei/payloads/default.bin"))
((void (*)())PAYLOAD_ADDRESS)();
}
}

View File

@@ -1,5 +0,0 @@
#pragma once
#include "types.h"
void initLCD(void);

21
source/buttons.h Normal file
View File

@@ -0,0 +1,21 @@
/*
* buttons.h
* by Aurora Wright
* Copyright (c) 2016 All Rights Reserved
*/
#pragma once
#include "types.h"
#define HID_PAD (*(vu16 *)0x10146000 ^ 0xFFF)
#define BUTTON_R1 (1 << 8)
#define BUTTON_L1 (1 << 9)
#define BUTTON_A 1
#define BUTTON_B (1 << 1)
#define BUTTON_UP (1 << 6)
#define BUTTON_DOWN (1 << 7)
#define BUTTON_START (1 << 3)
#define BUTTON_SELECT (1 << 2)
#define SAFE_MODE (BUTTON_R1 | BUTTON_L1 | BUTTON_A | BUTTON_UP)
#define PAYLOAD_BUTTONS ((BUTTON_L1 | BUTTON_A) ^ 0xFFF)

View File

@@ -1,4 +1,10 @@
// From http://github.com/b1l1s/ctr
/*
* crypto.c
* by Reisyukaku / Aurora Wright
* Crypto libs from http://github.com/b1l1s/ctr
*
* Copyright (c) 2016 All Rights Reserved
*/
#include "crypto.h"
#include "memory.h"
@@ -243,14 +249,16 @@ static void getNandCTR(u8 *buf, u32 console){
void nandFirm0(u8 *outbuf, u32 size, u32 console){
u8 CTR[0x10];
getNandCTR(CTR, console);
aes_advctr(CTR, 0x0B130000/0x10, AES_INPUT_BE | AES_INPUT_NORMAL);
sdmmc_nand_readsectors(0x0B130000 / 0x200, size / 0x200, outbuf);
aes_advctr(CTR, 0x0B130000/0x10, AES_INPUT_BE | AES_INPUT_NORMAL);
aes_use_keyslot(0x06);
aes(outbuf, outbuf, size / AES_BLOCK_SIZE, CTR, AES_CTR_MODE, AES_INPUT_BE | AES_INPUT_NORMAL);
}
//Decrypts the N3DS arm9bin
void decArm9Bin(u8 *armHdr, u32 mode){
void decryptArm9Bin(u8 *arm9Section, u32 mode){
//Firm keys
u8 keyY[0x10];
@@ -258,12 +266,12 @@ void decArm9Bin(u8 *armHdr, u32 mode){
u8 slot = mode ? 0x16 : 0x15;
//Setup keys needed for arm9bin decryption
memcpy(keyY, armHdr+0x10, 0x10);
memcpy(CTR, armHdr+0x20, 0x10);
memcpy(keyY, arm9Section + 0x10, 0x10);
memcpy(CTR, arm9Section + 0x20, 0x10);
u32 size = 0;
//http://stackoverflow.com/questions/12791077/atoi-implementation-in-c
for(u8 *tmp = armHdr+0x30; *tmp; tmp++)
size = (size<<3)+(size<<1)+(*tmp)-'0';
for(u8 *tmp = arm9Section + 0x30; *tmp; tmp++)
size = (size << 3) + (size << 1) + (*tmp) - '0';
if(mode){
u8 keyX[0x10];
@@ -271,7 +279,7 @@ void decArm9Bin(u8 *armHdr, u32 mode){
//Set 0x11 to key2 for the arm9bin and misc keys
aes_setkey(0x11, key2, AES_KEYNORMAL, AES_INPUT_BE | AES_INPUT_NORMAL);
aes_use_keyslot(0x11);
aes(keyX, armHdr+0x60, 1, NULL, AES_ECB_DECRYPT_MODE, 0);
aes(keyX, arm9Section + 0x60, 1, NULL, AES_ECB_DECRYPT_MODE, 0);
aes_setkey(slot, keyX, AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL);
}
@@ -280,14 +288,14 @@ void decArm9Bin(u8 *armHdr, u32 mode){
aes_use_keyslot(slot);
//Decrypt arm9bin
aes(armHdr+0x800, armHdr+0x800, size/AES_BLOCK_SIZE, CTR, AES_CTR_MODE, AES_INPUT_BE | AES_INPUT_NORMAL);
aes(arm9Section + 0x800, arm9Section + 0x800, size/AES_BLOCK_SIZE, CTR, AES_CTR_MODE, AES_INPUT_BE | AES_INPUT_NORMAL);
}
//Sets the N3DS 9.6 KeyXs
void setKeyXs(u8 *armHdr){
void setKeyXs(u8 *arm9Section){
u8 *keyData = armHdr+0x89814;
u8 *decKey = keyData+0x10;
u8 *keyData = arm9Section + 0x89814;
u8 *decKey = keyData + 0x10;
//Set keys 0x19..0x1F keyXs
aes_setkey(0x11, key2, AES_KEYNORMAL, AES_INPUT_BE | AES_INPUT_NORMAL);
@@ -295,6 +303,6 @@ void setKeyXs(u8 *armHdr){
for(u8 slot = 0x19; slot < 0x20; slot++){
aes(decKey, keyData, 1, NULL, AES_ECB_DECRYPT_MODE, 0);
aes_setkey(slot, decKey, AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL);
*(keyData+0xF) += 1;
*(keyData + 0xF) += 1;
}
}

View File

@@ -1,4 +1,10 @@
// From http://github.com/b1l1s/ctr
/*
* crypto.h
* by Reisyukaku / Aurora Wright
* Crypto libs from http://github.com/b1l1s/ctr
*
* Copyright (c) 2016 All Rights Reserved
*/
#pragma once
@@ -49,5 +55,5 @@
//NAND/FIRM stuff
void nandFirm0(u8 *outbuf, u32 size, u32 console);
void decArm9Bin(u8 *armHdr, u32 mode);
void setKeyXs(u8 *armHdr);
void decryptArm9Bin(u8 *arm9Section, u32 mode);
void setKeyXs(u8 *arm9Section);

View File

@@ -1,12 +1,18 @@
/*
* draw.c
* by Reisyukaku
* Copyright (c) 2015 All Rights Reserved
* by Reisyukaku / Aurora Wright
* Code to print to the screen by mid-kid @CakesFW
*
* Copyright (c) 2016 All Rights Reserved
*/
#include "draw.h"
#include "fs.h"
#include "memory.h"
#include "font.h"
#define SCREEN_TOP_WIDTH 400
#define SCREEN_TOP_HEIGHT 240
static const struct fb {
u8 *top_left;
@@ -14,25 +20,13 @@ static const struct fb {
u8 *bottom;
} *const fb = (struct fb *)0x23FFFE00;
void __attribute__((naked)) shutdownLCD(void){
vu32 *const arm11 = (u32 *)0x1FFFFFF8;
//Clear ARM11 entry offset
*arm11 = 0;
//Shutdown LCDs
*(vu32 *)0x10202A44 = 0;
*(vu32 *)0x10202244 = 0;
*(vu32 *)0x10202014 = 0;
//Wait for the entry to be set
while(!*arm11);
//Jump to it
((void (*)())*arm11)();
static int strlen(const char *string){
char *stringEnd = (char *)string;
while(*stringEnd) stringEnd++;
return stringEnd - string;
}
static void clearScreens(void){
void clearScreens(void){
memset32(fb->top_left, 0, 0x46500);
memset32(fb->top_right, 0, 0x46500);
memset32(fb->bottom, 0, 0x38400);
@@ -40,9 +34,49 @@ static void clearScreens(void){
void loadSplash(void){
clearScreens();
//Don't delay boot if no splash image is on the SD
if(fileRead(fb->top_left, "/aurei/splash.bin", 0x46500) +
fileRead(fb->bottom, "/aurei/splashbottom.bin", 0x38400)){
u64 i = 0x1300000; while(--i) __asm("mov r0, r0"); //Less Ghetto sleep func
}
}
void drawCharacter(char character, int pos_x, int pos_y, u32 color){
u8 *const select = fb->top_left;
for(int y = 0; y < 8; y++){
unsigned char char_pos = font[character * 8 + y];
for(int x = 7; x >= 0; x--){
int screen_pos = (pos_x * SCREEN_TOP_HEIGHT * 3 + (SCREEN_TOP_HEIGHT - y - pos_y - 1) * 3) + (7 - x) * 3 * SCREEN_TOP_HEIGHT;
if ((char_pos >> x) & 1) {
select[screen_pos] = color >> 16;
select[screen_pos + 1] = color >> 8;
select[screen_pos + 2] = color;
}
}
}
}
int drawString(const char *string, int pos_x, int pos_y, u32 color){
int length = strlen(string);
for(int i = 0, line_i = 0; i < length; i++, line_i++){
if(string[i] == '\n'){
pos_y += SPACING_VERT;
line_i = 0;
i++;
} else if(line_i >= (SCREEN_TOP_WIDTH - pos_x) / SPACING_HORIZ){
// Make sure we never get out of the screen.
pos_y += SPACING_VERT;
line_i = 2; // Little offset so we know the same string continues.
if(string[i] == ' ') i++; // Spaces at the start look weird
}
drawCharacter(string[i], pos_x + line_i * SPACING_HORIZ, pos_y, color);
}
return pos_y;
}

View File

@@ -1,12 +1,19 @@
/*
* draw.h
* by Reisyukaku
* Copyright (c) 2015 All Rights Reserved
* by Reisyukaku / Aurora Wright
* Code to print to the screen by mid-kid @CakesFW
*
* Copyright (c) 2016 All Rights Reserved
*/
#pragma once
#include "types.h"
#define SPACING_VERT 10
#define SPACING_HORIZ 8
void loadSplash(void);
void __attribute__((naked)) shutdownLCD(void);
void clearScreens(void);
void drawCharacter(char character, int pos_x, int pos_y, u32 color);
int drawString(const char *string, int pos_x, int pos_y, u32 color);

View File

@@ -1,7 +1,7 @@
/*
* emunand.c
* by Reisyukaku
* Copyright (c) 2015 All Rights Reserved
* by Reisyukaku / Aurora Wright
* Copyright (c) 2016 All Rights Reserved
*/
#include "emunand.h"
@@ -15,38 +15,30 @@ void getEmunandSect(u32 *off, u32 *head, u32 emuNAND){
u32 nandOffset = emuNAND == 1 ? 0 :
(nandSize > 0x200000 ? 0x400000 : 0x200000);
//Check for Gateway emuNAND
if(sdmmc_sdcard_readsectors(nandOffset + nandSize, 1, temp) == 0){
if(*(u32 *)(temp + 0x100) == NCSD_MAGIC){
*off = nandOffset;
*head = nandOffset + nandSize;
*off = nandOffset;
*head = nandOffset + nandSize;
}
//Fallback to the first emuNAND if there's no second one
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;
//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
else if(emuNAND == 2) getEmunandSect(off, head, 1);
}
}
}
void getSDMMC(void *pos, u32 *off, u32 size){
u32 getSDMMC(void *pos, u32 size){
//Look for struct code
const unsigned char pattern[] = {0x21, 0x20, 0x18, 0x20};
*off = (u32)memsearch(pos, pattern, size, 4) - 1;
//Get DCD values
u8 buf[4];
u32 addr = 0,
additive = 0,
p;
memcpy(buf, (void *)(*off+0x0A), 4);
for (p = 0; p < 4; p++) addr |= ((u32) buf[p]) << (8 * p);
memcpy(buf, (void *)(*off+0x0E), 4);
for (p = 0; p < 4; p++) additive |= ((u32) buf[p]) << (8 * p);
//Return result
*off = addr + additive;
const u8 *off = (u8 *)memsearch(pos, pattern, size, 4) - 1;
return *(u32 *)(off + 0x0A) + *(u32 *)(off + 0x0E);
}
void getEmuRW(void *pos, u32 size, u32 *readOff, u32 *writeOff){
@@ -57,17 +49,16 @@ void getEmuRW(void *pos, u32 size, u32 *readOff, u32 *writeOff){
*readOff = (u32)memsearch((void *)(*writeOff - 0x1000), pattern, 0x1000, 4) - 6;
}
void getMPU(void *pos, u32 *off, u32 size){
u32 *getMPU(void *pos, u32 size){
//Look for MPU pattern
const unsigned char pattern[] = {0x03, 0x00, 0x24, 0x00};
*off = (u32)memsearch(pos, pattern, size, 4);
return (u32 *)memsearch(pos, pattern, size, 4);
}
void getEmuCode(void *pos, u32 *off, u32 size){
u8 *proc9 = (u8 *)memsearch(pos, "ess9", size, 4);
void *getEmuCode(u8 *pos, u32 size, u8 *proc9Offset){
const unsigned char pattern[] = {0x00, 0xFF, 0xFF, 0xFF};
//Looking for the last spot before Process9
*off = (u32)memsearch(pos, pattern, size - (size - (u32)(proc9 - (u8 *)pos)), 4) + 0xD;
//Looking for the last free space before Process9
return (u8 *)memsearch(pos, pattern, size - (size - (u32)(proc9Offset - pos)), 4) + 0xD;
}

View File

@@ -1,7 +1,7 @@
/*
* emunand.h
* by Reisyukaku
* Copyright (c) 2015 All Rights Reserved
* by Reisyukaku / Aurora Wright
* Copyright (c) 2016 All Rights Reserved
*/
#pragma once
@@ -11,7 +11,7 @@
#define NCSD_MAGIC (0x4453434E)
void getEmunandSect(u32 *off, u32 *head, u32 emuNAND);
void getSDMMC(void *pos, u32 *off, u32 size);
u32 getSDMMC(void *pos, u32 size);
void getEmuRW(void *pos, u32 size, u32 *readOff, u32 *writeOff);
void getMPU(void *pos, u32 *off, u32 size);
void getEmuCode(void *pos, u32 *off, u32 size);
u32 *getMPU(void *pos, u32 size);
void *getEmuCode(u8 *pos, u32 size, u8 *proc9Offset);

View File

@@ -23,7 +23,7 @@
/ and optional writing functions as well. */
#define _FS_MINIMIZE 3
#define _FS_MINIMIZE 0
/* This option defines minimization level to remove some basic API functions.
/
/ 0: All basic functions are enabled.

View File

@@ -1,7 +1,7 @@
/*
* firm.c
* by Reisyukaku
* Copyright (c) 2015 All Rights Reserved
* by Reisyukaku / Aurora Wright
* Copyright (c) 2016 All Rights Reserved
*/
#include "firm.h"
@@ -11,19 +11,29 @@
#include "emunand.h"
#include "crypto.h"
#include "draw.h"
#include "screeninit.h"
#include "loader.h"
#include "utils.h"
#include "buttons.h"
#include "../build/patches.h"
//FIRM patches version
#define PATCH_VER 1
static firmHeader *const firmLocation = (firmHeader *)0x24000000;
static const firmSectionHeader *section;
static u32 firmSize = 0,
static u8 *arm9Section;
static const char *patchedFirms[] = { "/aurei/patched_firmware_sys.bin",
"/aurei/patched_firmware_emu.bin",
"/aurei/patched_firmware_em2.bin",
"/aurei/patched_firmware90.bin" };
static u32 firmSize,
mode = 1,
console = 1,
emuNAND = 0,
a9lhSetup = 0,
updatedSys = 0,
usePatchedFirm = 0;
static u16 pressed;
static const char *firmPathPatched = NULL;
usePatchedFirm = 0,
selectedFirm = 0;
void setupCFW(void){
@@ -31,81 +41,97 @@ void setupCFW(void){
u32 a9lhBoot = (PDN_SPI_CNT == 0x0) ? 1 : 0;
//Retrieve the last booted FIRM
u8 previousFirm = CFG_BOOTENV;
u32 overrideConfig = 0;
const char lastConfigPath[] = "aurei/lastbootcfg";
//Detect the console being used
if(PDN_MPCORE_CFG == 1) console = 0;
//Get pressed buttons
pressed = HID_PAD;
u16 pressed = HID_PAD;
u32 updatedSys = 0;
//Attempt to read the configuration file
const char configPath[] = "aurei/config.bin";
u16 config = 0;
u32 needConfig = fileRead(&config, configPath, 2) ? 1 : 2;
//Determine if A9LH is installed
if(a9lhBoot || fileExists("/aurei/installeda9lh")){
if(a9lhBoot || (config >> 2) & 0x1){
if(pressed == SAFE_MODE)
error("Using Safe Mode would brick you, or remove A9LH!");
a9lhSetup = 1;
//Check flag for > 9.2 SysNAND
if(fileExists("/aurei/updatedsysnand")) updatedSys = 1;
//Check setting for > 9.2 sysNAND
updatedSys = config & 0x1;
}
//If booting with A9LH and it's a MCU reboot, try to force boot options
if(a9lhBoot && previousFirm && fileExists(lastConfigPath)){
u8 tempConfig;
fileRead(&tempConfig, lastConfigPath, 1);
/* If booting with A9LH, it's a MCU reboot and a previous configuration exists,
try to force boot options */
if(a9lhBoot && previousFirm && needConfig == 1){
//Always force a sysNAND boot when quitting AGB_FIRM
if(previousFirm == 0x7){
if(!updatedSys) mode = tempConfig & 0x1;
overrideConfig = 1;
if(!updatedSys) mode = (config >> 8) & 0x1;
needConfig = 0;
//Else, force the last used boot options unless A is pressed
} else if(!(pressed & BUTTON_A)){
mode = tempConfig & 0x1;
emuNAND = (tempConfig >> 1) & 0x1;
overrideConfig = 1;
mode = (config >> 8) & 0x1;
emuNAND = (config >> 9) & 0x1;
needConfig = 0;
}
}
if(!overrideConfig){
if(needConfig){
//If L and R are pressed, chainload an external payload
if(a9lhBoot && (pressed & BUTTON_L1R1) == BUTTON_L1R1) loadPayload();
/* If L and one of the payload buttons are pressed, and if not using A9LH
the Safe Mode combo is not pressed, chainload an external payload */
if((pressed & BUTTON_L1) && (pressed & PAYLOAD_BUTTONS) &&
pressed != SAFE_MODE) loadPayload();
//Check if it's a no-screen-init A9LH boot
//If no configuration file exists or SELECT is held, load configuration menu
if(needConfig == 2 || (pressed & BUTTON_SELECT))
configureCFW(configPath);
//If screens are inited, load splash screen
if(PDN_GPU_CNT != 0x1) loadSplash();
/* If L is pressed, and on an updated SysNAND setup the SAFE MODE combo
is not pressed, boot 9.0 FIRM */
if((pressed & BUTTON_L1) && !(updatedSys && pressed == SAFEMODE)) mode = 0;
/* If L is pressed, boot 9.0 FIRM */
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
or R is pressed on a > 9.2 SysNAND, boot emuNAND */
if((updatedSys && (!mode || ((pressed & BUTTON_R1) && pressed != SAFEMODE))) ||
/* 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 */
if((updatedSys && (!mode || (pressed & BUTTON_R1))) ||
(!updatedSys && mode && !(pressed & BUTTON_R1))){
//If not 9.0 FIRM and B is pressed, attempt booting the second emuNAND
if(mode && (pressed & BUTTON_B)) emuNAND = 2;
else emuNAND = 1;
}
//Write the current boot options on A9LH
if(a9lhBoot){
u8 tempConfig = (mode | (emuNAND << 1)) & 0x3;
fileWrite(&tempConfig, lastConfigPath, 1);
/* If tha FIRM patches version is different or user switched to/from A9LH,
and "Use pre-patched FIRMs" is set, delete all patched FIRMs */
u16 bootConfig = (PATCH_VER << 11) | (a9lhSetup << 10);
if ((config >> 1) & 0x1 && bootConfig != (config & 0xFC00))
deleteFirms(patchedFirms, sizeof(patchedFirms) / sizeof(char *));
//We also need to remember the used boot mode on A9LH
if(a9lhBoot) bootConfig |= (mode << 8) | (emuNAND << 9);
//If the boot configuration is different from previously, overwrite it
if(bootConfig != (config & 0xFF00)){
//Preserve user settings (first byte)
u16 tempConfig = ((config & 0xFF) | bootConfig);
fileWrite(&tempConfig, configPath, 2);
}
}
if(mode) firmPathPatched = emuNAND ? (emuNAND == 1 ? "/aurei/patched_firmware_emu.bin" :
"/aurei/patched_firmware_em2.bin") :
"/aurei/patched_firmware_sys.bin";
if(mode) selectedFirm = emuNAND ? (emuNAND == 1 ? 2 : 3) : 1;
//Skip decrypting and patching FIRM
if(fileExists("/aurei/usepatchedfw")){
//Only needed with this flag
if(!mode) firmPathPatched = "/aurei/patched_firmware90.bin";
if(fileExists(firmPathPatched)) usePatchedFirm = 1;
if((config >> 1) & 0x1){
//Only needed with this setting
if(!mode) selectedFirm = 4;
if(fileExists(patchedFirms[selectedFirm - 1])) usePatchedFirm = 1;
}
}
//Load firm into FCRAM
u32 loadFirm(void){
//Load FIRM into FCRAM
void loadFirm(void){
//If not using an A9LH setup or the patched FIRM, load 9.0 FIRM from NAND
if(!usePatchedFirm && !a9lhSetup && !mode){
@@ -113,90 +139,117 @@ u32 loadFirm(void){
firmSize = console ? 0xF2000 : 0xE9000;
nandFirm0((u8 *)firmLocation, firmSize, console);
//Check for correct decryption
if(memcmp(firmLocation, "FIRM", 4) != 0) return 0;
if(memcmp(firmLocation, "FIRM", 4) != 0)
error("Couldn't decrypt NAND FIRM0 (O3DS not on 9.x?)");
}
//Load FIRM from SD
else{
const char *path = usePatchedFirm ? firmPathPatched :
const char *path = usePatchedFirm ? patchedFirms[selectedFirm - 1] :
(mode ? "/aurei/firmware.bin" : "/aurei/firmware90.bin");
firmSize = fileSize(path);
if(!firmSize) return 0;
fileRead((u8 *)firmLocation, path, firmSize);
if(!firmSize) error("aurei/firmware(90).bin doesn't exist");
fileRead(firmLocation, path, firmSize);
}
section = firmLocation->section;
//Check that the loaded FIRM matches the console
if((((u32)section[2].address >> 8) & 0xFF) != (console ? 0x60 : 0x68)) return 0;
if((((u32)section[2].address >> 8) & 0xFF) != (console ? 0x60 : 0x68))
error("aurei/firmware(90).bin doesn't match this\nconsole, or it's encrypted");
if(console && !usePatchedFirm)
decArm9Bin((u8 *)firmLocation + section[2].offset, mode);
arm9Section = (u8 *)firmLocation + section[2].offset;
return 1;
if(console && !usePatchedFirm) decryptArm9Bin(arm9Section, mode);
}
//Nand redirection
static u32 loadEmu(void){
//NAND redirection
static void loadEmu(u8 *proc9Offset){
u32 emuOffset = 1,
emuHeader = 1,
u32 emuOffset,
emuHeader = 0,
emuRead,
emuWrite,
sdmmcOffset,
mpuOffset,
emuCodeOffset;
emuWrite;
//Read emunand code from SD
const char path[] = "/aurei/emunand/emunand.bin";
u32 size = fileSize(path);
if(!size) return 0;
getEmuCode(firmLocation, &emuCodeOffset, firmSize);
fileRead((u8 *)emuCodeOffset, path, size);
//Find and patch emunand related offsets
u32 *pos_sdmmc = (u32 *)memsearch((void *)emuCodeOffset, "SDMC", size, 4);
u32 *pos_offset = (u32 *)memsearch((void *)emuCodeOffset, "NAND", size, 4);
u32 *pos_header = (u32 *)memsearch((void *)emuCodeOffset, "NCSD", size, 4);
getSDMMC(firmLocation, &sdmmcOffset, firmSize);
//Look for emuNAND
getEmunandSect(&emuOffset, &emuHeader, emuNAND);
getEmuRW(firmLocation, firmSize, &emuRead, &emuWrite);
getMPU(firmLocation, &mpuOffset, firmSize);
*pos_sdmmc = sdmmcOffset;
//No emuNAND detected
if(!emuHeader) error("No emuNAND has been detected");
//Copy emuNAND code
void *emuCodeOffset = getEmuCode(arm9Section, section[2].size, proc9Offset);
memcpy(emuCodeOffset, emunand, emunand_size);
//Add the data of the found emuNAND
u32 *pos_offset = (u32 *)memsearch(emuCodeOffset, "NAND", emunand_size, 4);
u32 *pos_header = (u32 *)memsearch(emuCodeOffset, "NCSD", emunand_size, 4);
*pos_offset = emuOffset;
*pos_header = emuHeader;
//No emuNAND detected
if(!*pos_header) return 0;
//Find and add the SDMMC struct
u32 *pos_sdmmc = (u32 *)memsearch(emuCodeOffset, "SDMC", emunand_size, 4);
*pos_sdmmc = getSDMMC(arm9Section, section[2].size);
//Calculate offset for the hooks
*(u32 *)(nandRedir + 4) = emuCodeOffset - (u32)firmLocation -
section[2].offset + (u32)section[2].address;
u32 branchOffset = (u32)emuCodeOffset - (u32)firmLocation -
section[2].offset + (u32)section[2].address;
//Add emunand hooks
memcpy((void *)emuRead, nandRedir, sizeof(nandRedir));
memcpy((void *)emuWrite, nandRedir, sizeof(nandRedir));
getEmuRW(arm9Section, section[2].size, &emuRead, &emuWrite);
*(u16 *)emuRead = nandRedir[0];
*((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
memcpy((void *)mpuOffset, mpu, sizeof(mpu));
return 1;
u32 *mpuOffset = getMPU(arm9Section, section[2].size);
*mpuOffset = mpuPatch[0];
*(mpuOffset + 6) = mpuPatch[1];
*(mpuOffset + 9) = mpuPatch[2];
}
//Patches
u32 patchFirm(void){
void patchFirm(void){
//Skip patching
if(usePatchedFirm) return 1;
if(usePatchedFirm) return;
//Apply emuNAND patches
if(emuNAND){
if(!loadEmu()) return 0;
if(mode || emuNAND){
//Find the Process9 NCCH location
u8 *proc9Offset = getProc9(arm9Section, section[2].size);
//Apply emuNAND patches
if(emuNAND) loadEmu(proc9Offset);
//Patch FIRM reboots, not on 9.0 FIRM as it breaks firmlaunchhax
if(mode){
//Calculate offset for the firmlaunch code
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);
//Put the fOpen offset in the right location
u32 *pos_fopen = (u32 *)memsearch(rebootOffset, "OPEN", reboot_size, 4);
*pos_fopen = fOpenOffset;
//Patch path for emuNAND-patched FIRM
if(emuNAND){
void *pos_path = memsearch(rebootOffset, L"sy", reboot_size, 4);
memcpy(pos_path, emuNAND == 1 ? L"emu" : L"em2", 5);
}
}
}
else if(a9lhSetup){
//Patch FIRM partitions writes on SysNAND to protect A9LH
u32 writeOffset = 0;
getFIRMWrite(firmLocation, firmSize, &writeOffset);
memcpy((void *)writeOffset, FIRMblock, sizeof(FIRMblock));
if(a9lhSetup && !emuNAND){
//Patch FIRM partitions writes on sysNAND to protect A9LH
u16 *writeOffset = getFirmWrite(arm9Section, section[2].size);
*writeOffset = writeBlock[0];
*(writeOffset + 1) = writeBlock[1];
}
//Disable signature checks
@@ -204,62 +257,35 @@ u32 patchFirm(void){
sigOffset2;
getSignatures(firmLocation, firmSize, &sigOffset, &sigOffset2);
memcpy((void *)sigOffset, sigPat1, sizeof(sigPat1));
memcpy((void *)sigOffset2, sigPat2, sizeof(sigPat2));
*(u16 *)sigOffset = sigPatch[0];
*(u16 *)sigOffset2 = sigPatch[0];
*((u16 *)sigOffset2 + 1) = sigPatch[1];
//Patch ARM9 entrypoint on N3DS to skip arm9loader
if(console)
firmLocation->arm9Entry = (u8 *)0x801B01C;
//Patch FIRM reboots, not on 9.0 FIRM as it breaks firmlaunchhax
if(mode){
u32 rebootOffset,
fOpenOffset;
//Read reboot code from SD
const char path[] = "/aurei/reboot/reboot.bin";
u32 size = fileSize(path);
if(!size) return 0;
getReboot(firmLocation, firmSize, &rebootOffset);
fileRead((u8 *)rebootOffset, path, size);
//Calculate the fOpen offset and put it in the right location
u32 *pos_fopen = (u32 *)memsearch((void *)rebootOffset, "OPEN", size, 4);
getfOpen(firmLocation, firmSize, &fOpenOffset);
*pos_fopen = fOpenOffset;
//Patch path for emuNAND-patched FIRM
if(emuNAND){
void *pos_path = memsearch((void *)rebootOffset, L"sy", size, 4);
const wchar_t *path = emuNAND == 1 ? L"emu" : L"em2";
memcpy(pos_path, path, 5);
}
}
//Write patched FIRM to SD if needed
if(firmPathPatched)
if(!fileWrite((u8 *)firmLocation, firmPathPatched, firmSize)) return 0;
return 1;
if(selectedFirm)
if(!fileWrite(firmLocation, patchedFirms[selectedFirm - 1], firmSize))
error("Couldn't write the patched FIRM (no free space?)");
}
void launchFirm(void){
if(console && mode) setKeyXs((u8 *)firmLocation + section[2].offset);
if(console && mode) setKeyXs(arm9Section);
//Copy firm partitions to respective memory locations
memcpy(section[0].address, (u8 *)firmLocation + section[0].offset, section[0].size);
memcpy(section[1].address, (u8 *)firmLocation + section[1].offset, section[1].size);
memcpy(section[2].address, (u8 *)firmLocation + section[2].offset, section[2].size);
memcpy(section[2].address, arm9Section, section[2].size);
//Run ARM11 screen stuff
vu32 *const arm11 = (u32 *)0x1FFFFFF8;
*arm11 = (u32)shutdownLCD;
while(*arm11);
//Fixes N3DS 3D
deinitScreens();
//Set ARM11 kernel
*arm11 = (u32)firmLocation->arm11Entry;
//Set ARM11 kernel entrypoint
*(vu32 *)0x1FFFFFF8 = (u32)firmLocation->arm11Entry;
//Final jump to arm9 binary
//Final jump to arm9 kernel
((void (*)())firmLocation->arm9Entry)();
}

View File

@@ -1,24 +1,16 @@
/*
* firm.h
* by Reisyukaku
* Copyright (c) 2015 All Rights Reserved
* by Reisyukaku / Aurora Wright
* Copyright (c) 2016 All Rights Reserved
*/
#pragma once
#include "types.h"
#define PDN_MPCORE_CFG (*(vu8 *)0x10140FFC)
#define HID_PAD ((~*(vu16 *)0x10146000) & 0xFFF)
#define PDN_SPI_CNT (*(vu8 *)0x101401C0)
#define CFG_BOOTENV (*(vu8 *)0x10010000)
#define PDN_GPU_CNT (*(vu8 *)0x10141200)
#define BUTTON_R1 (1 << 8)
#define BUTTON_L1 (1 << 9)
#define BUTTON_L1R1 (BUTTON_R1 | BUTTON_L1)
#define BUTTON_A 1
#define BUTTON_B (1 << 1)
#define SAFEMODE (BUTTON_L1R1 | BUTTON_A | (1 << 6))
#define PDN_MPCORE_CFG (*(vu8 *)0x10140FFC)
#define PDN_SPI_CNT (*(vu8 *)0x101401C0)
#define CFG_BOOTENV (*(vu8 *)0x10010000)
//FIRM Header layout
typedef struct firmSectionHeader {
@@ -39,6 +31,6 @@ typedef struct firmHeader {
} firmHeader;
void setupCFW(void);
u32 loadFirm(void);
u32 patchFirm(void);
void loadFirm(void);
void patchFirm(void);
void launchFirm(void);

144
source/font.h Normal file
View File

@@ -0,0 +1,144 @@
/*
This file was autogenerated by raw2c.
Visit http://www.devkitpro.org
*/
//---------------------------------------------------------------------------------
#ifndef _font_h_
#define _font_h_
//---------------------------------------------------------------------------------
static const unsigned char font[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x81, 0xa5, 0x81, 0xbd, 0x99, 0x81, 0x7e,
0x7e, 0xff, 0xdb, 0xff, 0xc3, 0xe7, 0xff, 0x7e, 0x6c, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10, 0x00,
0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x10, 0x00, 0x3c, 0x3c, 0x18, 0xff, 0xe7, 0x18, 0x3c, 0x00,
0x10, 0x38, 0x7c, 0xfe, 0xee, 0x10, 0x38, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x18, 0x00, 0x00,
0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff, 0x00, 0x3c, 0x66, 0x42, 0x42, 0x66, 0x3c, 0x00,
0xff, 0xc3, 0x99, 0xbd, 0xbd, 0x99, 0xc3, 0xff, 0x0f, 0x07, 0x0f, 0x7d, 0xcc, 0xcc, 0xcc, 0x78,
0x3c, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x08, 0x0c, 0x0a, 0x0a, 0x08, 0x78, 0xf0, 0x00,
0x18, 0x14, 0x1a, 0x16, 0x72, 0xe2, 0x0e, 0x1c, 0x10, 0x54, 0x38, 0xee, 0x38, 0x54, 0x10, 0x00,
0x80, 0xe0, 0xf8, 0xfe, 0xf8, 0xe0, 0x80, 0x00, 0x02, 0x0e, 0x3e, 0xfe, 0x3e, 0x0e, 0x02, 0x00,
0x18, 0x3c, 0x5a, 0x18, 0x5a, 0x3c, 0x18, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x00,
0x7f, 0xdb, 0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x00, 0x1c, 0x22, 0x38, 0x44, 0x44, 0x38, 0x88, 0x70,
0x00, 0x00, 0x00, 0x00, 0x7e, 0x7e, 0x7e, 0x00, 0x18, 0x3c, 0x5a, 0x18, 0x5a, 0x3c, 0x18, 0x7e,
0x18, 0x3c, 0x5a, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x5a, 0x3c, 0x18, 0x00,
0x00, 0x18, 0x0c, 0xfe, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x30, 0x60, 0xfe, 0x60, 0x30, 0x00, 0x00,
0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xfe, 0x00, 0x00, 0x00, 0x24, 0x42, 0xff, 0x42, 0x24, 0x00, 0x00,
0x00, 0x10, 0x38, 0x7c, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x7c, 0x38, 0x10, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x18, 0x18, 0x00, 0x18, 0x00,
0x6c, 0x24, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x6c, 0xfe, 0x6c, 0xfe, 0x6c, 0x6c, 0x00,
0x10, 0x7c, 0xd0, 0x7c, 0x16, 0xfc, 0x10, 0x00, 0x00, 0x66, 0xac, 0xd8, 0x36, 0x6a, 0xcc, 0x00,
0x38, 0x4c, 0x38, 0x78, 0xce, 0xcc, 0x7a, 0x00, 0x30, 0x10, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
0x18, 0x30, 0x60, 0x60, 0x60, 0x30, 0x18, 0x00, 0x60, 0x30, 0x18, 0x18, 0x18, 0x30, 0x60, 0x00,
0x00, 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00, 0x00, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x10, 0x20, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x02, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x00,
0x7c, 0xce, 0xde, 0xf6, 0xe6, 0xe6, 0x7c, 0x00, 0x18, 0x38, 0x78, 0x18, 0x18, 0x18, 0x7e, 0x00,
0x7c, 0xc6, 0x06, 0x1c, 0x70, 0xc6, 0xfe, 0x00, 0x7c, 0xc6, 0x06, 0x3c, 0x06, 0xc6, 0x7c, 0x00,
0x1c, 0x3c, 0x6c, 0xcc, 0xfe, 0x0c, 0x1e, 0x00, 0xfe, 0xc0, 0xfc, 0x06, 0x06, 0xc6, 0x7c, 0x00,
0x7c, 0xc6, 0xc0, 0xfc, 0xc6, 0xc6, 0x7c, 0x00, 0xfe, 0xc6, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x00,
0x7c, 0xc6, 0xc6, 0x7c, 0xc6, 0xc6, 0x7c, 0x00, 0x7c, 0xc6, 0xc6, 0x7e, 0x06, 0xc6, 0x7c, 0x00,
0x00, 0x30, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x30, 0x10, 0x20,
0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x7e, 0x00, 0x00,
0x60, 0x30, 0x18, 0x0c, 0x18, 0x30, 0x60, 0x00, 0x78, 0xcc, 0x0c, 0x18, 0x30, 0x00, 0x30, 0x00,
0x7c, 0x82, 0x9e, 0xa6, 0x9e, 0x80, 0x7c, 0x00, 0x7c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00,
0xfc, 0x66, 0x66, 0x7c, 0x66, 0x66, 0xfc, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 0x00,
0xfc, 0x66, 0x66, 0x66, 0x66, 0x66, 0xfc, 0x00, 0xfe, 0x62, 0x68, 0x78, 0x68, 0x62, 0xfe, 0x00,
0xfe, 0x62, 0x68, 0x78, 0x68, 0x60, 0xf0, 0x00, 0x7c, 0xc6, 0xc6, 0xc0, 0xce, 0xc6, 0x7e, 0x00,
0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00,
0x1e, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0x78, 0x00, 0xe6, 0x66, 0x6c, 0x78, 0x6c, 0x66, 0xe6, 0x00,
0xf0, 0x60, 0x60, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x82, 0xc6, 0xee, 0xfe, 0xd6, 0xc6, 0xc6, 0x00,
0xc6, 0xe6, 0xf6, 0xde, 0xce, 0xc6, 0xc6, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00,
0xfc, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xd6, 0xde, 0x7c, 0x06,
0xfc, 0x66, 0x66, 0x7c, 0x66, 0x66, 0xe6, 0x00, 0x7c, 0xc6, 0xc0, 0x7c, 0x06, 0xc6, 0x7c, 0x00,
0x7e, 0x5a, 0x5a, 0x18, 0x18, 0x18, 0x3c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00,
0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x10, 0x00, 0xc6, 0xc6, 0xd6, 0xfe, 0xee, 0xc6, 0x82, 0x00,
0xc6, 0x6c, 0x38, 0x38, 0x38, 0x6c, 0xc6, 0x00, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x3c, 0x00,
0xfe, 0xc6, 0x8c, 0x18, 0x32, 0x66, 0xfe, 0x00, 0x78, 0x60, 0x60, 0x60, 0x60, 0x60, 0x78, 0x00,
0xc0, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x02, 0x00, 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78, 0x00,
0x10, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
0x30, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x76, 0x00,
0xe0, 0x60, 0x60, 0x7c, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc6, 0x7c, 0x00,
0x1c, 0x0c, 0x0c, 0x7c, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0x7c, 0x00,
0x1c, 0x36, 0x30, 0x78, 0x30, 0x30, 0x78, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, 0x7c, 0x0c, 0x78,
0xe0, 0x60, 0x6c, 0x76, 0x66, 0x66, 0xe6, 0x00, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x3c, 0x00,
0x00, 0x0c, 0x00, 0x1c, 0x0c, 0x0c, 0xcc, 0x78, 0xe0, 0x60, 0x66, 0x6c, 0x78, 0x6c, 0xe6, 0x00,
0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0xcc, 0xfe, 0xd6, 0xd6, 0xd6, 0x00,
0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7c, 0x00,
0x00, 0x00, 0xdc, 0x66, 0x66, 0x7c, 0x60, 0xf0, 0x00, 0x00, 0x7c, 0xcc, 0xcc, 0x7c, 0x0c, 0x1e,
0x00, 0x00, 0xde, 0x76, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x7c, 0xc0, 0x7c, 0x06, 0x7c, 0x00,
0x10, 0x30, 0xfc, 0x30, 0x30, 0x34, 0x18, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00,
0x00, 0x00, 0xc6, 0xc6, 0x6c, 0x38, 0x10, 0x00, 0x00, 0x00, 0xc6, 0xd6, 0xd6, 0xfe, 0x6c, 0x00,
0x00, 0x00, 0xc6, 0x6c, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xf8,
0x00, 0x00, 0xfc, 0x98, 0x30, 0x64, 0xfc, 0x00, 0x0e, 0x18, 0x18, 0x30, 0x18, 0x18, 0x0e, 0x00,
0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00, 0xe0, 0x30, 0x30, 0x18, 0x30, 0x30, 0xe0, 0x00,
0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0x00,
0x7c, 0xc6, 0xc0, 0xc0, 0xc6, 0x7c, 0x18, 0x70, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00,
0x0e, 0x10, 0x7c, 0xc6, 0xfe, 0xc0, 0x7c, 0x00, 0x7c, 0x82, 0x38, 0x0c, 0x7c, 0xcc, 0x76, 0x00,
0xcc, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x76, 0x00, 0xe0, 0x10, 0x78, 0x0c, 0x7c, 0xcc, 0x76, 0x00,
0x30, 0x30, 0x78, 0x0c, 0x7c, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x7c, 0xc0, 0xc0, 0x7c, 0x18, 0x70,
0x7c, 0x82, 0x7c, 0xc6, 0xfe, 0xc0, 0x7c, 0x00, 0xc6, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0x7c, 0x00,
0xe0, 0x10, 0x7c, 0xc6, 0xfe, 0xc0, 0x7c, 0x00, 0x66, 0x00, 0x38, 0x18, 0x18, 0x18, 0x3c, 0x00,
0x7c, 0x82, 0x38, 0x18, 0x18, 0x18, 0x3c, 0x00, 0xe0, 0x10, 0x38, 0x18, 0x18, 0x18, 0x3c, 0x00,
0xc6, 0x00, 0x7c, 0xc6, 0xfe, 0xc6, 0xc6, 0x00, 0x38, 0x38, 0x7c, 0xc6, 0xfe, 0xc6, 0xc6, 0x00,
0x0e, 0x10, 0xfe, 0x60, 0x78, 0x60, 0xfe, 0x00, 0x00, 0x00, 0x7c, 0x12, 0x7e, 0xd0, 0x7e, 0x00,
0x7e, 0xc8, 0xc8, 0xfe, 0xc8, 0xc8, 0xce, 0x00, 0x7c, 0x82, 0x7c, 0xc6, 0xc6, 0xc6, 0x7c, 0x00,
0xc6, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0xe0, 0x10, 0x7c, 0xc6, 0xc6, 0xc6, 0x7c, 0x00,
0x7c, 0x82, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0xe0, 0x10, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00,
0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xf8, 0xc6, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00,
0xc6, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x18, 0x7c, 0xd6, 0xd0, 0xd6, 0x7c, 0x18, 0x00,
0x38, 0x6c, 0x60, 0xf0, 0x60, 0xf2, 0xdc, 0x00, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x7e, 0x18, 0x00,
0xf8, 0xcc, 0xf8, 0xc4, 0xcc, 0xde, 0xcc, 0x06, 0x0e, 0x1b, 0x18, 0x3c, 0x18, 0x18, 0xd8, 0x70,
0x0e, 0x10, 0x78, 0x0c, 0x7c, 0xcc, 0x76, 0x00, 0x0e, 0x10, 0x38, 0x18, 0x18, 0x18, 0x3c, 0x00,
0x0e, 0x10, 0x7c, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x0e, 0x10, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00,
0x66, 0x98, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x98, 0xe6, 0xf6, 0xde, 0xce, 0xc6, 0x00,
0x38, 0x0c, 0x3c, 0x34, 0x00, 0x7e, 0x00, 0x00, 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x7c, 0x00, 0x00,
0x30, 0x00, 0x30, 0x60, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xc0, 0xc0, 0x00, 0x00,
0x00, 0x00, 0x00, 0xfc, 0x0c, 0x0c, 0x00, 0x00, 0xc0, 0xc8, 0xd0, 0xfe, 0x46, 0x8c, 0x1e, 0x00,
0xc0, 0xc8, 0xd0, 0xec, 0x5c, 0xbe, 0x0c, 0x00, 0x18, 0x00, 0x18, 0x18, 0x3c, 0x3c, 0x18, 0x00,
0x00, 0x36, 0x6c, 0xd8, 0x6c, 0x36, 0x00, 0x00, 0x00, 0xd8, 0x6c, 0x36, 0x6c, 0xd8, 0x00, 0x00,
0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa,
0xdb, 0x77, 0xdb, 0xee, 0xdb, 0x77, 0xdb, 0xee, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18,
0x36, 0x36, 0x36, 0x36, 0xf6, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x36, 0x36, 0x36,
0x00, 0x00, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x36, 0x36, 0xf6, 0x06, 0xf6, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0xfe, 0x06, 0xf6, 0x36, 0x36, 0x36,
0x36, 0x36, 0xf6, 0x06, 0xfe, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36, 0xfe, 0x00, 0x00, 0x00,
0x18, 0x18, 0xf8, 0x18, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x18, 0x18,
0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18,
0x18, 0x18, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, 0x37, 0x36, 0x36, 0x36,
0x36, 0x36, 0x37, 0x30, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x30, 0x37, 0x36, 0x36, 0x36,
0x36, 0x36, 0xf7, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xf7, 0x36, 0x36, 0x36,
0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00,
0x36, 0x36, 0xf7, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x18, 0x18, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00,
0x36, 0x36, 0x36, 0x36, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x18, 0x18, 0x18,
0x00, 0x00, 0x00, 0x00, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x3f, 0x00, 0x00, 0x00,
0x18, 0x18, 0x1f, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18,
0x00, 0x00, 0x00, 0x00, 0x3f, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, 0x36, 0x36, 0x36,
0x18, 0x18, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x18, 0x18, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x74, 0xcc, 0xc8, 0xdc, 0x76, 0x00, 0x78, 0xcc, 0xd8, 0xcc, 0xc6, 0xc6, 0xdc, 0x40,
0xfe, 0x62, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x02, 0x7e, 0xec, 0x6c, 0x6c, 0x48, 0x00,
0xfe, 0x62, 0x30, 0x18, 0x30, 0x62, 0xfe, 0x00, 0x00, 0x00, 0x7e, 0xd0, 0xc8, 0xc8, 0x70, 0x00,
0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xf8, 0x80, 0x00, 0x00, 0x7e, 0xd8, 0x18, 0x18, 0x10, 0x00,
0x38, 0x10, 0x7c, 0xd6, 0xd6, 0x7c, 0x10, 0x38, 0x7c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x7c, 0x00,
0x7c, 0xc6, 0xc6, 0xc6, 0x6c, 0x28, 0xee, 0x00, 0x3c, 0x22, 0x18, 0x7c, 0xcc, 0xcc, 0x78, 0x00,
0x00, 0x00, 0x66, 0x99, 0x99, 0x66, 0x00, 0x00, 0x00, 0x06, 0x7c, 0x9e, 0xf2, 0x7c, 0xc0, 0x00,
0x00, 0x00, 0x7c, 0xc0, 0xf8, 0xc0, 0x7c, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00,
0x00, 0xfe, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x7e, 0x00,
0x30, 0x18, 0x0c, 0x18, 0x30, 0x00, 0x7c, 0x00, 0x18, 0x30, 0x60, 0x30, 0x18, 0x00, 0x7c, 0x00,
0x0e, 0x1b, 0x1b, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xd8, 0xd8, 0x70,
0x00, 0x18, 0x00, 0x7e, 0x00, 0x18, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00, 0x76, 0xdc, 0x00, 0x00,
0x38, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x0f, 0x0c, 0x0c, 0x0c, 0xec, 0x6c, 0x3c, 0x00,
0xd8, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x30, 0xc0, 0xf0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
const int font_size = sizeof(font);
//---------------------------------------------------------------------------------
#endif //_font_h_
//---------------------------------------------------------------------------------

View File

@@ -1,5 +1,7 @@
/*
* fs.c
* by Reisyukaku / Aurora Wright
* Copyright (c) 2016 All Rights Reserved
*/
#include "fs.h"
@@ -12,7 +14,7 @@ u32 mountSD(void){
return 1;
}
u32 fileRead(u8 *dest, const char *path, u32 size){
u32 fileRead(void *dest, const char *path, u32 size){
FRESULT fr;
FIL fp;
unsigned int br = 0;
@@ -27,7 +29,7 @@ u32 fileRead(u8 *dest, const char *path, u32 size){
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;
FIL fp;
unsigned int br = 0;
@@ -58,4 +60,8 @@ u32 fileExists(const char *path){
f_close(&fp);
return exists;
}
void fileDelete(const char *path){
f_unlink(path);
}

View File

@@ -1,5 +1,7 @@
/*
* fs.h
* by Reisyukaku / Aurora Wright
* Copyright (c) 2016 All Rights Reserved
*/
#pragma once
@@ -7,7 +9,8 @@
#include "types.h"
u32 mountSD(void);
u32 fileRead(u8 *dest, const char *path, u32 size);
u32 fileWrite(const u8 *buffer, const char *path, u32 size);
u32 fileRead(void *dest, const char *path, u32 size);
u32 fileWrite(const void *buffer, const char *path, u32 size);
u32 fileSize(const char *path);
u32 fileExists(const char *path);
u32 fileExists(const char *path);
void fileDelete(const char *path);

View File

@@ -1,14 +1,21 @@
/*
* loader.c
* by Aurora Wright
* Copyright (c) 2016 All Rights Reserved
*/
#include "loader.h"
#include "fs.h"
#include "memory.h"
#include "screeninit.h"
#include "../build/loader.h"
#define PAYLOAD_ADDRESS 0x24F00000
void loadPayload(void){
if(fileExists("aurei/payloads/default.bin") &&
fileRead((u8 *)PAYLOAD_ADDRESS, "aurei/loader.bin", 0))
if(fileExists("aurei/payloads/default.bin")){
initScreens();
memcpy((void *)PAYLOAD_ADDRESS, loader, loader_size);
((void (*)())PAYLOAD_ADDRESS)();
}
}

View File

@@ -1,5 +1,7 @@
/*
* loader.h
* by Aurora Wright
* Copyright (c) 2016 All Rights Reserved
*/
#pragma once

View File

@@ -1,23 +1,18 @@
/*
* main.c
* by Reisyukaku
* Copyright (c) 2015 All Rights Reserved
* by Reisyukaku / Aurora Wright
* Copyright (c) 2016 All Rights Reserved
*
* Minimalist CFW for N3DS
* Minimalist CFW for (N)3DS
*/
#include "fs.h"
#include "firm.h"
#include "i2c.h"
void main(void){
mountSD();
setupCFW();
if(!loadFirm()) return;
if(!patchFirm()) return;
loadFirm();
patchFirm();
launchFirm();
}
void shutdown(void){
i2cWriteRegister(I2C_DEV_MCU, 0x20, 1);
}

View File

@@ -1,7 +1,7 @@
/*
* memory.c
* by Reisyukaku
* Copyright (c) 2015 All Rights Reserved
* by Reisyukaku / Aurora Wright
* Copyright (c) 2016 All Rights Reserved
*/
#include "memory.h"
@@ -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){
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;
}
return NULL;
}

View File

@@ -1,7 +1,7 @@
/*
* memory.h
* by Reisyukaku
* Copyright (c) 2015 All Rights Reserved
* by Reisyukaku / Aurora Wright
* Copyright (c) 2016 All Rights Reserved
*/
#pragma once

View File

@@ -1,7 +1,7 @@
/*
* patches.c
* by Reisyukaku
* Copyright (c) 2015 All Rights Reserved
* by Reisyukaku / Aurora Wright
* Copyright (c) 2016 All Rights Reserved
*/
#include "patches.h"
@@ -11,26 +11,22 @@
* Patches
**************************************************/
const u8 mpu[0x2C] = { //MPU shit
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
};
const u32 mpuPatch[3] = {0x00360003, 0x00200603, 0x001C0603};
//Branch to emunand function. To be filled in
u8 nandRedir[0x08] = {0x00, 0x4C, 0xA0, 0x47, 0x00, 0x00, 0x00, 0x00};
const u16 nandRedir[2] = {0x4C00, 0x47A0};
const u8 sigPat1[2] = {0x00, 0x20};
const u8 sigPat2[4] = {0x00, 0x20, 0x70, 0x47};
const u16 sigPatch[2] = {0x2000, 0x4770};
const u8 FIRMblock[4] = {0x00, 0x20, 0xC0, 0x46};
const u8 emuInstr[5] = {0xA5, 0x01, 0x08, 0x30, 0xA5};
const u16 writeBlock[2] = {0x2000, 0x46C0};
/**************************************************
* Functions
**************************************************/
u8 *getProc9(void *pos, u32 size){
return (u8 *)memsearch(pos, "ess9", size, 4);
}
void getSignatures(void *pos, u32 size, u32 *off, u32 *off2){
//Look for signature checks
const unsigned char pattern[] = {0xC0, 0x1C, 0x76, 0xE7};
@@ -40,26 +36,27 @@ void getSignatures(void *pos, u32 size, u32 *off, u32 *off2){
*off2 = (u32)memsearch(pos, pattern2, size, 4) - 1;
}
void getReboot(void *pos, u32 size, u32 *off){
void *getReboot(void *pos, u32 size){
//Look for FIRM reboot code
const unsigned char pattern[] = {0xDE, 0x1F, 0x8D, 0xE2};
*off = (u32)memsearch(pos, pattern, size, 4) - 0x10;
return (u8 *)memsearch(pos, pattern, size, 4) - 0x10;
}
void getfOpen(void *pos, u32 size, u32 *off){
//Calculate fOpen
u32 p9addr = *(u32 *)((u8 *)memsearch(pos, "ess9", size, 4) + 0xC);
u32 p9off = (u32)memsearch(pos, "code", size, 4) + 0x1FF;
const unsigned char pattern[] = {0xB0, 0x04, 0x98, 0x0D};
u32 getfOpen(u8 *proc9Offset, void *rebootOffset){
//Offset Process9 code gets loaded to in memory (defined in ExHeader)
u32 p9MemAddr = *(u32 *)(proc9Offset + 0xC);
//Process9 code offset (start of NCCH + ExeFS offset + ExeFS header size)
u32 p9CodeOff = (u32)(proc9Offset - 0x204) + (*(u32 *)(proc9Offset - 0x64) * 0x200) + 0x200;
*off = (u32)memsearch(pos, pattern, size, 4) - 2 - p9off + p9addr;
//Firmlaunch function offset - offset in BLX opcode (A4-16 - ARM DDI 0100E) + 1
return (u32)rebootOffset + 9 - (-((*(u32 *)rebootOffset & 0x00FFFFFF) << 2) & 0xFFFFF) - p9CodeOff + p9MemAddr;
}
void getFIRMWrite(void *pos, u32 size, u32 *off){
u16 *getFirmWrite(void *pos, u32 size){
//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};
*off = (u32)memsearch(firmwrite - 0x100, pattern, 0x100, 4);
return (u16 *)memsearch(off - 0x100, pattern, 0x100, 4);
}

View File

@@ -1,7 +1,7 @@
/*
* patches.h
* by Reisyukaku
* Copyright (c) 2015 All Rights Reserved
* by Reisyukaku / Aurora Wright
* Copyright (c) 2016 All Rights Reserved
*/
#pragma once
@@ -11,17 +11,16 @@
/**************************************************
* Patches
**************************************************/
const u8 mpu[0x2C];
u8 nandRedir[0x08];
const u8 sigPat1[2];
const u8 sigPat2[4];
const u8 FIRMblock[4];
const u8 emuInstr[5];
const u32 mpuPatch[3];
const u16 nandRedir[2];
const u16 sigPatch[2];
const u16 writeBlock[2];
/**************************************************
* Functions
**************************************************/
u8 *getProc9(void *pos, u32 size);
void getSignatures(void *pos, u32 size, u32 *off, u32 *off2);
void getReboot(void *pos, u32 size, u32 *off);
void getfOpen(void *pos, u32 size, u32 *off);
void getFIRMWrite(void *pos, u32 size, u32 *off);
void *getReboot(void *pos, u32 size);
u32 getfOpen(u8 *proc9Offset, void *rebootOffset);
u16 *getFirmWrite(void *pos, u32 size);

View File

@@ -1,16 +1,53 @@
/*
* screeninit.c
* by Aurora Wright
* Screen init code by dark_samus, bil1s, Normmatt, delebile and others.
* Screen deinit code by tiniVi.
*
* Copyright (c) 2016 All Rights Reserved
*/
#include "screeninit.h"
#include "draw.h"
#include "i2c.h"
void initLCD(void){
vu32 *const arm11 = (vu32 *)0x1FFFFFF8;
static vu32 *const arm11 = (vu32 *)0x1FFFFFF8;
void deinitScreens(void){
void __attribute__((naked)) ARM11(void){
//Disable interrupts
__asm(".word 0xF10C01C0");
//Clear ARM11 entry offset
*arm11 = 0;
//Shutdown LCDs
*(vu32 *)0x10202A44 = 0;
*(vu32 *)0x10202244 = 0;
*(vu32 *)0x10202014 = 0;
//Wait for the entry to be set
while(!*arm11);
//Jump to it
((void (*)())*arm11)();
}
if(PDN_GPU_CNT != 0x1){
*arm11 = (u32)ARM11;
while(*arm11);
}
}
void initScreens(void){
void __attribute__((naked)) ARM11(void){
//Disable interrupts
__asm(".word 0xF10C01C0");
*(vu32 *)0x10141200 = 0x1007F;
*(vu32 *)0x10202014 = 0x00000001;
*(vu32 *)0x1020200C &= 0xFFFEFFFE;
*(vu32 *)0x10202240 = 0x39;
*(vu32 *)0x10202A40 = 0x39;
*(vu32 *)0x10202240 = 0x45;
*(vu32 *)0x10202A40 = 0x45;
*(vu32 *)0x10202244 = 0x1023E;
*(vu32 *)0x10202A44 = 0x1023E;
@@ -106,6 +143,10 @@ void initLCD(void){
((void (*)())*arm11)();
}
*arm11 = (u32)ARM11;
while(*arm11);
if(PDN_GPU_CNT == 0x1){
*arm11 = (u32)ARM11;
while(*arm11);
}
clearScreens();
}

17
source/screeninit.h Normal file
View File

@@ -0,0 +1,17 @@
/*
* screeninit.h
* by Aurora Wright
* Screen init code by dark_samus, bil1s, Normmatt, delebile and others.
* Screen deinit code by tiniVi.
*
* Copyright (c) 2016 All Rights Reserved
*/
#pragma once
#include "types.h"
#define PDN_GPU_CNT (*(vu8 *)0x10141200)
void deinitScreens(void);
void initScreens(void);

View File

@@ -52,7 +52,5 @@ _start:
bl main
bl shutdown
.die:
b .die

123
source/utils.c Normal file
View File

@@ -0,0 +1,123 @@
/*
* utils.c
* by Aurora Wright
* Copyright (c) 2016 All Rights Reserved
*/
#include "utils.h"
#include "screeninit.h"
#include "draw.h"
#include "fs.h"
#include "i2c.h"
#include "buttons.h"
//Number of options that can be configured
#define OPTIONS 3
#define COLOR_TITLE 0xFF9900
#define COLOR_WHITE 0xFFFFFF
#define COLOR_RED 0x0000FF
#define COLOR_BLACK 0x000000
struct options {
char *text[OPTIONS];
int pos_y[OPTIONS];
u32 enabled[OPTIONS];
u32 selected;
};
static u16 waitInput(void){
u32 pressedkey = 0;
u16 key;
//Wait for no keys to be pressed
while(HID_PAD);
do {
//Wait for a key to be pressed
while(!HID_PAD);
key = HID_PAD;
//Make sure it's pressed
for(u32 i = 0x13000; i; i--){
if (key != HID_PAD)
break;
if(i == 1) pressedkey = 1;
}
} while(!pressedkey);
return key;
}
void configureCFW(const char *configPath){
struct options options;
options.text[0] = "( ) Updated SysNAND mode (A9LH-only)";
options.text[1] = "( ) Use pre-patched FIRMs";
options.text[2] = "( ) Force A9LH detection";
initScreens();
drawString("AuReiNand configuration", 10, 10, COLOR_TITLE);
drawString("Press A to select, START to save and reboot", 10, 30, COLOR_WHITE);
//Read and parse the existing configuration
u16 tempConfig = 0;
fileRead(&tempConfig, configPath, 2);
for(u32 i = 0; i < OPTIONS; i++)
options.enabled[i] = (tempConfig >> i) & 0x1;
//Pre-select the first configuration option
options.selected = 0;
//Boring configuration menu
while(1){
u16 pressed = 0;
do{
for(u32 i = 0; i < OPTIONS; i++){
options.pos_y[i] = drawString(options.text[i], 10, !i ? 60 : options.pos_y[i - 1] + SPACING_VERT, options.selected == i ? COLOR_RED : COLOR_WHITE);
drawCharacter('x', 10 + SPACING_HORIZ, options.pos_y[i], options.enabled[i] ? (options.selected == i ? COLOR_RED : COLOR_WHITE) : COLOR_BLACK);
}
pressed = waitInput();
} while(!(pressed & (BUTTON_UP | BUTTON_DOWN | BUTTON_A | BUTTON_START)));
if(pressed == BUTTON_UP) options.selected = !options.selected ? OPTIONS - 1 : options.selected - 1;
else if(pressed == BUTTON_DOWN) options.selected = options.selected == OPTIONS - 1 ? 0 : options.selected + 1;
else if(pressed == BUTTON_A) options.enabled[options.selected] = !options.enabled[options.selected];
else if(pressed == BUTTON_START) break;
}
//Preserve the last-used boot options (second byte)
tempConfig &= 0xFF00;
//Parse and write the selected options
for(u32 i = 0; i < OPTIONS; i++)
tempConfig |= options.enabled[i] << i;
fileWrite(&tempConfig, configPath, 2);
//Reboot
i2cWriteRegister(I2C_DEV_MCU, 0x20, 1 << 2);
while(1);
}
void deleteFirms(const char *firmPaths[], u32 firms){
while(firms){
fileDelete(firmPaths[firms - 1]);
firms--;
}
}
void error(const char *message){
initScreens();
drawString("An error has occurred:", 10, 10, COLOR_RED);
int pos_y = drawString(message, 10, 30, COLOR_WHITE);
drawString("Press any button to shutdown", 10, pos_y + 2 * SPACING_VERT, COLOR_WHITE);
waitInput();
//Shutdown
i2cWriteRegister(I2C_DEV_MCU, 0x20, 1);
while(1);
}

13
source/utils.h Normal file
View File

@@ -0,0 +1,13 @@
/*
* utils.h
* by Aurora Wright
* Copyright (c) 2016 All Rights Reserved
*/
#pragma once
#include "types.h"
void configureCFW(const char *configPath);
void deleteFirms(const char *firmPaths[], u32 firms);
void error(const char *message);