Compare commits

..

45 Commits
v3.8 ... v3.13

Author SHA1 Message Date
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
Aurora
a437e533f5 Slightly improved the reboot patch, added emuNAND patch improvements from CakesFW, made the emuNAND patch completely version-independent
Should work as-is with future firmwares!
2016-03-21 03:21:22 +01:00
Aurora
6b88953517 Moved D9 launching fix to the loader 2016-03-20 22:03:43 +01:00
Aurora
9b9f784c26 Fixed intermittent splash from CakeBrah, made splash last slightly longer, added shutdown on error, slimmed down FatFs, added error on missing emuNAND, changed folder to "aurei", changed the dat name to "AuReiNand.dat", propered the built-in screen init of the chainloader, remade the look of the 3dsx
(First luma-powered CFW!)
2016-03-20 17:38:45 +01:00
Aurora
6dfb33191f Minor changes 2016-03-17 04:51:07 +01:00
Aurora
078fce4b3d Better here 2016-03-17 00:37:43 +01:00
Aurora
dcb09a9472 Added dual emuNAND support, multi-payload loader with built-in screen init (inspired by arm9select, thanks Fix94) 2016-03-17 00:15:38 +01:00
Aurora
8ce395caa5 Switch to Normmatt's iodelay
Seems to be more reliable in all conditions
2016-03-16 04:01:38 +01:00
Aurora
e9410c86b1 Added RedNAND support (untested) 2016-03-14 14:51:30 +01:00
Aurora
42885560ed Some clean-up 2016-03-13 17:01:00 +01:00
Aurora
796e4dd060 Forgot this 2016-03-13 04:03:07 +01:00
Aurora
9468582d83 Clean-up, fixed mistake
GCC, why no u warn me of strict aliasing
2016-03-12 15:48:20 +01:00
Aurora
6707a36ffe Minor changes 2016-03-10 16:06:44 +01:00
Aurora
09cc7c903c Oops #2 2016-03-10 04:25:38 +01:00
Aurora
9be7481c14 Minor formatting updates 2016-03-10 03:06:44 +01:00
Aurora
9f68ce0d70 Oops 2016-03-10 01:59:25 +01:00
Aurora
4748c0292c Added bottom screen splash image support
As suggested by Apache Thunder
2016-03-10 01:31:39 +01:00
Aurora
c3ebce1666 Crush loader warnings 2016-03-09 15:09:46 +01:00
Aurora
b1a428f6bc Disable splash screen when forcing boot options 2016-03-09 14:59:20 +01:00
Aurora
3e0b928db0 Not needed 2016-03-08 15:45:04 +01:00
55 changed files with 1235 additions and 859 deletions

2
.gitignore vendored
View File

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

View File

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

View File

@@ -3,7 +3,7 @@
**Compiling:** **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! 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 See https://github.com/Reisyukaku/ReiNand and http://gbatemp.net/threads/reinand-mod-o3ds-n3ds-sysnand.411110
The FIRMs you need are here: The FIRMs you need are [HERE](http://www99.zippyshare.com/v/kEIiQl0x/file.html).
http://www99.zippyshare.com/v/kEIiQl0x/file.html
**Credits:** **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.

BIN
icon.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.1 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

@@ -32,8 +32,8 @@ INCLUDES := include source/fatfs source/fatfs/sdmmc
ARCH := -mthumb -mthumb-interwork ARCH := -mthumb -mthumb-interwork
CFLAGS := -g -Wall -O2\ CFLAGS := -g -Wall -O2\
-march=armv5te -mtune=arm946e-s -fomit-frame-pointer\ -march=armv5te -mtune=arm946e-s\
-ffast-math -std=c99\ -ffast-math -Wno-main -std=c99\
$(ARCH) $(ARCH)
CFLAGS += $(INCLUDE) -DARM9 CFLAGS += $(INCLUDE) -DARM9
@@ -105,7 +105,7 @@ $(BUILD):
#--------------------------------------------------------------------------------- #---------------------------------------------------------------------------------
clean: clean:
@echo clean ... @echo clean ...
@rm -fr $(BUILD) $(OUTPUT).elf arm9loaderhax.bin @rm -fr $(BUILD) $(OUTPUT).elf
#--------------------------------------------------------------------------------- #---------------------------------------------------------------------------------

14
loader/source/buttons.h Normal file
View File

@@ -0,0 +1,14 @@
#pragma once
#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)

View File

@@ -811,7 +811,7 @@ FRESULT sync_fs ( /* FR_OK: successful, FR_DISK_ERR: failed */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* Hidden API for hacks and disk tools */ /* Hidden API for hacks and disk tools */
DWORD clust2sect ( /* !=0: Sector number, 0: Failed - invalid cluster# */ static DWORD clust2sect ( /* !=0: Sector number, 0: Failed - invalid cluster# */
FATFS* fs, /* File system object */ FATFS* fs, /* File system object */
DWORD clst /* Cluster# to be converted */ DWORD clst /* Cluster# to be converted */
) )
@@ -829,7 +829,7 @@ DWORD clust2sect ( /* !=0: Sector number, 0: Failed - invalid cluster# */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* Hidden API for hacks and disk tools */ /* Hidden API for hacks and disk tools */
DWORD get_fat ( /* 0xFFFFFFFF:Disk error, 1:Internal error, 2..0x0FFFFFFF:Cluster status */ static DWORD get_fat ( /* 0xFFFFFFFF:Disk error, 1:Internal error, 2..0x0FFFFFFF:Cluster status */
FATFS* fs, /* File system object */ FATFS* fs, /* File system object */
DWORD clst /* FAT index number (cluster number) to get the value */ DWORD clst /* FAT index number (cluster number) to get the value */
) )
@@ -884,7 +884,7 @@ DWORD get_fat ( /* 0xFFFFFFFF:Disk error, 1:Internal error, 2..0x0FFFFFFF:Cluste
/* Hidden API for hacks and disk tools */ /* Hidden API for hacks and disk tools */
#if !_FS_READONLY #if !_FS_READONLY
FRESULT put_fat ( static FRESULT put_fat (
FATFS* fs, /* File system object */ FATFS* fs, /* File system object */
DWORD clst, /* FAT index number (cluster number) to be changed */ DWORD clst, /* FAT index number (cluster number) to be changed */
DWORD val /* New value to be set to the entry */ DWORD val /* New value to be set to the entry */
@@ -1314,7 +1314,7 @@ int cmp_lfn ( /* 1:Matched, 0:Not matched */
} }
#if _FS_MINIMIZE <= 1 || _USE_LABEL || _FS_RPATH >= 2
static static
int pick_lfn ( /* 1:Succeeded, 0:Buffer overflow */ int pick_lfn ( /* 1:Succeeded, 0:Buffer overflow */
WCHAR* lfnbuf, /* Pointer to the Unicode-LFN buffer */ WCHAR* lfnbuf, /* Pointer to the Unicode-LFN buffer */
@@ -1345,6 +1345,7 @@ int pick_lfn ( /* 1:Succeeded, 0:Buffer overflow */
return 1; return 1;
} }
#endif
#if !_FS_READONLY #if !_FS_READONLY
@@ -1385,7 +1386,7 @@ void fit_lfn (
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* Create numbered name */ /* Create numbered name */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
#if _USE_LFN #if _USE_LFN && !_FS_READONLY
static static
void gen_numname ( void gen_numname (
BYTE* dst, /* Pointer to the buffer to store numbered SFN */ BYTE* dst, /* Pointer to the buffer to store numbered SFN */

View File

@@ -1,151 +0,0 @@
/*------------------------------------------------------------------------*/
/* Sample code of OS dependent controls for FatFs */
/* (C)ChaN, 2014 */
/*------------------------------------------------------------------------*/
#include "../ff.h"
#if _FS_REENTRANT
/*------------------------------------------------------------------------*/
/* Create a Synchronization Object */
/*------------------------------------------------------------------------*/
/* This function is called in f_mount() function to create a new
/ synchronization object, such as semaphore and mutex. When a 0 is returned,
/ the f_mount() function fails with FR_INT_ERR.
*/
int ff_cre_syncobj ( /* !=0:Function succeeded, ==0:Could not create due to any error */
BYTE vol, /* Corresponding logical drive being processed */
_SYNC_t *sobj /* Pointer to return the created sync object */
)
{
int ret;
*sobj = CreateMutex(NULL, FALSE, NULL); /* Win32 */
ret = (int)(*sobj != INVALID_HANDLE_VALUE);
// *sobj = SyncObjects[vol]; /* uITRON (give a static created sync object) */
// ret = 1; /* The initial value of the semaphore must be 1. */
// *sobj = OSMutexCreate(0, &err); /* uC/OS-II */
// ret = (int)(err == OS_NO_ERR);
// *sobj = xSemaphoreCreateMutex(); /* FreeRTOS */
// ret = (int)(*sobj != NULL);
return ret;
}
/*------------------------------------------------------------------------*/
/* Delete a Synchronization Object */
/*------------------------------------------------------------------------*/
/* This function is called in f_mount() function to delete a synchronization
/ object that created with ff_cre_syncobj function. When a 0 is returned,
/ the f_mount() function fails with FR_INT_ERR.
*/
int ff_del_syncobj ( /* !=0:Function succeeded, ==0:Could not delete due to any error */
_SYNC_t sobj /* Sync object tied to the logical drive to be deleted */
)
{
int ret;
ret = CloseHandle(sobj); /* Win32 */
// ret = 1; /* uITRON (nothing to do) */
// OSMutexDel(sobj, OS_DEL_ALWAYS, &err); /* uC/OS-II */
// ret = (int)(err == OS_NO_ERR);
// vSemaphoreDelete(sobj); /* FreeRTOS */
// ret = 1;
return ret;
}
/*------------------------------------------------------------------------*/
/* Request Grant to Access the Volume */
/*------------------------------------------------------------------------*/
/* This function is called on entering file functions to lock the volume.
/ When a 0 is returned, the file function fails with FR_TIMEOUT.
*/
int ff_req_grant ( /* 1:Got a grant to access the volume, 0:Could not get a grant */
_SYNC_t sobj /* Sync object to wait */
)
{
int ret;
ret = (int)(WaitForSingleObject(sobj, _FS_TIMEOUT) == WAIT_OBJECT_0); /* Win32 */
// ret = (int)(wai_sem(sobj) == E_OK); /* uITRON */
// OSMutexPend(sobj, _FS_TIMEOUT, &err)); /* uC/OS-II */
// ret = (int)(err == OS_NO_ERR);
// ret = (int)(xSemaphoreTake(sobj, _FS_TIMEOUT) == pdTRUE); /* FreeRTOS */
return ret;
}
/*------------------------------------------------------------------------*/
/* Release Grant to Access the Volume */
/*------------------------------------------------------------------------*/
/* This function is called on leaving file functions to unlock the volume.
*/
void ff_rel_grant (
_SYNC_t sobj /* Sync object to be signaled */
)
{
ReleaseMutex(sobj); /* Win32 */
// sig_sem(sobj); /* uITRON */
// OSMutexPost(sobj); /* uC/OS-II */
// xSemaphoreGive(sobj); /* FreeRTOS */
}
#endif
#if _USE_LFN == 3 /* LFN with a working buffer on the heap */
/*------------------------------------------------------------------------*/
/* Allocate a memory block */
/*------------------------------------------------------------------------*/
/* If a NULL is returned, the file function fails with FR_NOT_ENOUGH_CORE.
*/
void* ff_memalloc ( /* Returns pointer to the allocated memory block */
UINT msize /* Number of bytes to allocate */
)
{
return malloc(msize); /* Allocate a new memory block with POSIX API */
}
/*------------------------------------------------------------------------*/
/* Free a memory block */
/*------------------------------------------------------------------------*/
void ff_memfree (
void* mblock /* Pointer to the memory block to free */
)
{
free(mblock); /* Discard the memory block with POSIX API */
}
#endif

View File

@@ -1,15 +1,4 @@
#pragma once #pragma once
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h> #include <stdbool.h>
#include "../../types.h"
#define u8 uint8_t
#define u16 uint16_t
#define u32 uint32_t
#define u64 uint64_t
#define vu8 volatile u8
#define vu16 volatile u16
#define vu32 volatile u32
#define vu64 volatile u64

View File

@@ -6,4 +6,4 @@
#include "common.h" #include "common.h"
void waitcycles(u32 us); void ioDelay(u32 us);

View File

@@ -1,15 +1,17 @@
.arm // Copyright 2014 Normmatt
.global waitcycles // Licensed under GPLv2 or any later version
.type waitcycles STT_FUNC // Refer to the license.txt file included.
@waitcycles ( u32 us ) .arm
waitcycles: .global ioDelay
PUSH {R0-R2,LR} .type ioDelay STT_FUNC
STR R0, [SP,#4]
waitcycles_loop: @ioDelay ( u32 us )
LDR R3, [SP,#4] ioDelay:
SUBS R2, R3, #1 ldr r1, =0x18000000 @ VRAM
STR R2, [SP,#4] 1:
CMP R3, #0 @ Loop doing uncached reads from VRAM to make loop timing more reliable
BNE waitcycles_loop ldr r2, [r1]
POP {R0-R2,PC} subs r0, #1
bgt 1b
bx lr

View File

@@ -2,8 +2,6 @@
// Licensed under GPLv2 or any later version // Licensed under GPLv2 or any later version
// Refer to the license.txt file included. // Refer to the license.txt file included.
#include "common.h"
#include "sdmmc.h" #include "sdmmc.h"
#include "delay.h" #include "delay.h"
@@ -286,7 +284,7 @@ static void InitSD()
static int Nand_Init() static int Nand_Init()
{ {
inittarget(&handleNAND); inittarget(&handleNAND);
waitcycles(0xF000); ioDelay(0xF000);
sdmmc_send_command(&handleNAND,0,0); sdmmc_send_command(&handleNAND,0,0);
@@ -337,7 +335,7 @@ static int SD_Init()
{ {
inittarget(&handleSD); inittarget(&handleSD);
waitcycles(1u << 18); //Card needs a little bit of time to be detected, it seems ioDelay(1u << 18); //Card needs a little bit of time to be detected, it seems
//If not inserted //If not inserted
if (!(*((vu16*)0x1000601c) & TMIO_STAT0_SIGSTATE)) return -1; if (!(*((vu16*)0x1000601c) & TMIO_STAT0_SIGSTATE)) return -1;

View File

@@ -125,4 +125,3 @@ mmcdevice *getMMCDevice(int drive);
u32 sdmmc_nand_readsectors(u32 sector_no, u32 numsectors, vu8 *out); u32 sdmmc_nand_readsectors(u32 sector_no, u32 numsectors, vu8 *out);
u32 sdmmc_nand_writesectors(u32 sector_no, u32 numsectors, vu8 *in); u32 sdmmc_nand_writesectors(u32 sector_no, u32 numsectors, vu8 *in);

View File

@@ -1,19 +1,39 @@
#include "types.h"
#include "buttons.h"
#include "fatfs/ff.h" #include "fatfs/ff.h"
#define PAYLOAD_ADDRESS 0x23F00000 #define PAYLOAD_ADDRESS 0x23F00000
int main() static u32 loadPayload(const char *path){
{
FATFS fs;
FIL payload; FIL payload;
unsigned int br; unsigned int br;
if(f_open(&payload, path, FA_READ) == FR_OK)
f_mount(&fs, "0:", 1);
if(f_open(&payload, "rei/arm9payload.bin", FA_READ) == FR_OK)
{ {
f_read(&payload, (void *)PAYLOAD_ADDRESS, f_size(&payload), &br); f_read(&payload, (void *)PAYLOAD_ADDRESS, f_size(&payload), &br);
((void (*)())PAYLOAD_ADDRESS)(); f_close(&payload);
}
return 1; return 1;
}
return 0;
}
void main(void){
FATFS fs;
f_mount(&fs, "0:", 1);
//Get pressed buttons
u16 pressed = HID_PAD;
if(((pressed & BUTTON_B) && loadPayload("/aurei/payloads/b.bin")) ||
((pressed & BUTTON_X) && loadPayload("/aurei/payloads/x.bin")) ||
((pressed & BUTTON_Y) && loadPayload("/aurei/payloads/y.bin")) ||
((pressed & BUTTON_SELECT) && loadPayload("/aurei/payloads/select.bin")) ||
((pressed & BUTTON_START) && loadPayload("/aurei/payloads/start.bin")) ||
((pressed & BUTTON_RIGHT) && loadPayload("/aurei/payloads/right.bin")) ||
((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"))
((void (*)())PAYLOAD_ADDRESS)();
} }

View File

@@ -2,6 +2,9 @@
.align 4 .align 4
.global _start .global _start
_start: _start:
@ Fix payloads like Decrypt9
mov r0, #0x5
mcr p15, 0, r0, c3, c0, 0 @ data bufferable
@ Flush caches @ Flush caches
mov r0, #0 mov r0, #0

20
loader/source/types.h Normal file
View File

@@ -0,0 +1,20 @@
/*
* types.h
* by Reisyukaku
* Copyright (c) 2015 All Rights Reserved
*/
#pragma once
#include <stdint.h>
#include <stdlib.h>
//Common data types
typedef uint8_t u8;
typedef uint16_t u16;
typedef uint32_t u32;
typedef uint64_t u64;
typedef volatile u8 vu8;
typedef volatile u16 vu16;
typedef volatile u32 vu32;
typedef volatile u64 vu64;

View File

@@ -1,9 +1,6 @@
.nds .arm.little
sdmmc equ 0x434D4453 ;dummy .create "emunand.bin", 0
.create "emunand.bin", 0x0801A5C0
.org 0x0801A5C0
.arm .arm
nand_sd: nand_sd:
; Original code that still needs to be executed. ; Original code that still needs to be executed.
@@ -15,7 +12,7 @@ nand_sd:
; If we're already trying to access the SD, return. ; If we're already trying to access the SD, return.
ldr r2, [r0, #4] ldr r2, [r0, #4]
ldr r1, =sdmmc ldr r1, [sdmmc]
cmp r2, r1 cmp r2, r1
beq nand_sd_ret beq nand_sd_ret
@@ -23,12 +20,10 @@ nand_sd:
ldr r2, [r0, #8] ; Get sector to read ldr r2, [r0, #8] ; Get sector to read
cmp r2, #0 ; For GW compatibility, see if we're trying to read the ncsd header (sector 0) cmp r2, #0 ; For GW compatibility, see if we're trying to read the ncsd header (sector 0)
ldr r3, =nand_offset ldr r3, [nand_offset]
ldr r3, [r3]
add r2, r3 ; Add the offset to the NAND in the SD. add r2, r3 ; Add the offset to the NAND in the SD.
ldreq r3, =ncsd_header_offset ldreq r3, [ncsd_header_offset]
ldreq r3, [r3]
addeq r2, r3 ; If we're reading the ncsd header, add the offset of that sector. addeq r2, r3 ; If we're reading the ncsd header, add the offset of that sector.
str r2, [r0, #8] ; Store sector to read str r2, [r0, #8] ; Store sector to read
@@ -45,6 +40,7 @@ nand_sd:
add r0, #4 add r0, #4
bx r0 bx r0
.pool .pool
sdmmc: .ascii "SDMC"
nand_offset: .ascii "NAND" ; for rednand this should be 1 nand_offset: .ascii "NAND" ; for rednand this should be 1
ncsd_header_offset: .ascii "NCSD" ; depends on nand manufacturer + emunand type (GW/RED) ncsd_header_offset: .ascii "NCSD" ; depends on nand manufacturer + emunand type (GW/RED)
.close .close

View File

@@ -1,12 +1,11 @@
.nds .arm.little
.create "reboot.bin", 0
byteswritten equ 0x2000E000 byteswritten equ 0x2000E000
externalFirm equ 0x2000A000
kernelCode equ 0x080F0000 kernelCode equ 0x080F0000
buffer equ 0x24000000 buffer equ 0x24000000
fileOpen equ 0x4E45504F ;dummy fileOpen equ 0x4E45504F ;dummy
.create "reboot.bin", 0
.arm .arm
//Code jumps here right after the sprintf call //Code jumps here right after the sprintf call
process9Reboot: process9Reboot:
@@ -34,18 +33,16 @@ process9Reboot:
ldreq r1, =(FileName - OpenFirm - 12) ldreq r1, =(FileName - OpenFirm - 12)
addeq r1, pc addeq r1, pc
addne r1, sp, #0x3A8-0x70 addne r1, sp, #0x3A8-0x70
ldr r0, =externalFirm
moveq r2, #1 moveq r2, #1
movne r2, #0 movne r2, #0
str r2, [r0] str r2, [externalFirm]
mov r2, #1 mov r2, #1
add r0, r7, #8 add r0, r7, #8
ldr r6, =fileOpen ldr r6, =fileOpen
blx r6 blx r6
SeekFirm: SeekFirm:
ldr r0, =externalFirm ldr r0, [externalFirm]
ldr r0, [r0]
cmp r0, #1 cmp r0, #1
moveq r0, r7 moveq r0, r7
ldreq r1, =byteswritten ldreq r1, =byteswritten
@@ -99,9 +96,12 @@ Memcpy:
BX LR BX LR
FileName: FileName:
.dcw "sdmc:/rei/patched_firmware_sys.bin" .dcw "sdmc:/aurei/patched_firmware_sys.bin"
.word 0x0 .word 0x0
externalFirm:
.word 0x2000A000
.pool .pool
// Kernel Code // Kernel Code

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 "crypto.h"
#include "memory.h" #include "memory.h"
@@ -54,10 +60,10 @@ __asm__\
} }
#endif /*__thumb__*/ #endif /*__thumb__*/
void aes_setkey(u8 keyslot, const void* key, u32 keyType, u32 mode) static void aes_setkey(u8 keyslot, const void *key, u32 keyType, u32 mode)
{ {
if(keyslot <= 0x03) return; // Ignore TWL keys for now if(keyslot <= 0x03) return; // Ignore TWL keys for now
u32 * key32 = (u32 *)key; u32 *key32 = (u32 *)key;
*REG_AESCNT = (*REG_AESCNT & ~(AES_CNT_INPUT_ENDIAN | AES_CNT_INPUT_ORDER)) | mode; *REG_AESCNT = (*REG_AESCNT & ~(AES_CNT_INPUT_ENDIAN | AES_CNT_INPUT_ORDER)) | mode;
*REG_AESKEYCNT = (*REG_AESKEYCNT >> 6 << 6) | keyslot | AES_KEYCNT_WRITE; *REG_AESKEYCNT = (*REG_AESKEYCNT >> 6 << 6) | keyslot | AES_KEYCNT_WRITE;
@@ -67,7 +73,7 @@ void aes_setkey(u8 keyslot, const void* key, u32 keyType, u32 mode)
REG_AESKEYFIFO[keyType] = key32[3]; REG_AESKEYFIFO[keyType] = key32[3];
} }
void aes_use_keyslot(u8 keyslot) static void aes_use_keyslot(u8 keyslot)
{ {
if(keyslot > 0x3F) if(keyslot > 0x3F)
return; return;
@@ -76,7 +82,7 @@ void aes_use_keyslot(u8 keyslot)
*REG_AESCNT = *REG_AESCNT | 0x04000000; /* mystery bit */ *REG_AESCNT = *REG_AESCNT | 0x04000000; /* mystery bit */
} }
void aes_setiv(const void* iv, u32 mode) static void aes_setiv(const void *iv, u32 mode)
{ {
const u32 *iv32 = (const u32 *)iv; const u32 *iv32 = (const u32 *)iv;
*REG_AESCNT = (*REG_AESCNT & ~(AES_CNT_INPUT_ENDIAN | AES_CNT_INPUT_ORDER)) | mode; *REG_AESCNT = (*REG_AESCNT & ~(AES_CNT_INPUT_ENDIAN | AES_CNT_INPUT_ORDER)) | mode;
@@ -98,9 +104,9 @@ void aes_setiv(const void* iv, u32 mode)
} }
} }
void aes_advctr(void *ctr, u32 val, u32 mode) static void aes_advctr(void *ctr, u32 val, u32 mode)
{ {
u32 *ctr32 = (u32*)ctr; u32 *ctr32 = (u32 *)ctr;
int i; int i;
if(mode & AES_INPUT_BE) if(mode & AES_INPUT_BE)
@@ -125,7 +131,7 @@ void aes_advctr(void *ctr, u32 val, u32 mode)
} }
} }
void aes_change_ctrmode(void *ctr, u32 fromMode, u32 toMode) static void aes_change_ctrmode(void *ctr, u32 fromMode, u32 toMode)
{ {
u32 *ctr32 = (u32 *)ctr; u32 *ctr32 = (u32 *)ctr;
int i; int i;
@@ -147,7 +153,7 @@ void aes_change_ctrmode(void *ctr, u32 fromMode, u32 toMode)
} }
} }
void aes_batch(void *dst, const void *src, u32 blockCount) static void aes_batch(void *dst, const void *src, u32 blockCount)
{ {
*REG_AESBLKCNT = blockCount << 16; *REG_AESBLKCNT = blockCount << 16;
*REG_AESCNT |= AES_CNT_START; *REG_AESCNT |= AES_CNT_START;
@@ -180,7 +186,7 @@ void aes_batch(void *dst, const void *src, u32 blockCount)
} }
} }
void aes(void *dst, const void *src, u32 blockCount, void *iv, u32 mode, u32 ivMode) static void aes(void *dst, const void *src, u32 blockCount, void *iv, u32 mode, u32 ivMode)
{ {
*REG_AESCNT = mode | *REG_AESCNT = mode |
AES_CNT_INPUT_ORDER | AES_CNT_OUTPUT_ORDER | AES_CNT_INPUT_ORDER | AES_CNT_OUTPUT_ORDER |
@@ -228,12 +234,12 @@ void aes(void *dst, const void *src, u32 blockCount, void *iv, u32 mode, u32 ivM
****************************************************************/ ****************************************************************/
//Nand key#2 (0x12C10) //Nand key#2 (0x12C10)
const u8 key2[0x10] = { static const u8 key2[0x10] = {
0x42, 0x3F, 0x81, 0x7A, 0x23, 0x52, 0x58, 0x31, 0x6E, 0x75, 0x8E, 0x3A, 0x39, 0x43, 0x2E, 0xD0 0x42, 0x3F, 0x81, 0x7A, 0x23, 0x52, 0x58, 0x31, 0x6E, 0x75, 0x8E, 0x3A, 0x39, 0x43, 0x2E, 0xD0
}; };
//Get Nand CTR key //Get Nand CTR key
void getNandCTR(u8 *buf, u32 console){ static void getNandCTR(u8 *buf, u32 console){
u8 *addr = (console ? (u8 *)0x080D8BBC : (u8 *)0x080D797C) + 0x0F; u8 *addr = (console ? (u8 *)0x080D8BBC : (u8 *)0x080D797C) + 0x0F;
for(u8 keyLen = 0x10; keyLen; keyLen--) for(u8 keyLen = 0x10; keyLen; keyLen--)
*(buf++) = *(addr--); *(buf++) = *(addr--);
@@ -243,14 +249,16 @@ void getNandCTR(u8 *buf, u32 console){
void nandFirm0(u8 *outbuf, u32 size, u32 console){ void nandFirm0(u8 *outbuf, u32 size, u32 console){
u8 CTR[0x10]; u8 CTR[0x10];
getNandCTR(CTR, console); getNandCTR(CTR, console);
aes_advctr(CTR, 0x0B130000/0x10, AES_INPUT_BE | AES_INPUT_NORMAL);
sdmmc_nand_readsectors(0x0B130000 / 0x200, size / 0x200, outbuf); sdmmc_nand_readsectors(0x0B130000 / 0x200, size / 0x200, outbuf);
aes_advctr(CTR, 0x0B130000/0x10, AES_INPUT_BE | AES_INPUT_NORMAL);
aes_use_keyslot(0x06); aes_use_keyslot(0x06);
aes(outbuf, outbuf, size / AES_BLOCK_SIZE, CTR, AES_CTR_MODE, AES_INPUT_BE | AES_INPUT_NORMAL); aes(outbuf, outbuf, size / AES_BLOCK_SIZE, CTR, AES_CTR_MODE, AES_INPUT_BE | AES_INPUT_NORMAL);
} }
//Decrypts the N3DS arm9bin //Decrypts the N3DS arm9bin
void decArm9Bin(u8 *armHdr, u32 mode){ void decryptArm9Bin(u8 *arm9Section, u32 mode){
//Firm keys //Firm keys
u8 keyY[0x10]; u8 keyY[0x10];
@@ -258,11 +266,11 @@ void decArm9Bin(u8 *armHdr, u32 mode){
u8 slot = mode ? 0x16 : 0x15; u8 slot = mode ? 0x16 : 0x15;
//Setup keys needed for arm9bin decryption //Setup keys needed for arm9bin decryption
memcpy(keyY, armHdr+0x10, 0x10); memcpy(keyY, arm9Section+0x10, 0x10);
memcpy(CTR, armHdr+0x20, 0x10); memcpy(CTR, arm9Section+0x20, 0x10);
u32 size = 0; u32 size = 0;
//http://stackoverflow.com/questions/12791077/atoi-implementation-in-c //http://stackoverflow.com/questions/12791077/atoi-implementation-in-c
for(u8 *tmp = armHdr+0x30; *tmp; tmp++) for(u8 *tmp = arm9Section+0x30; *tmp; tmp++)
size = (size<<3)+(size<<1)+(*tmp)-'0'; size = (size<<3)+(size<<1)+(*tmp)-'0';
if(mode){ if(mode){
@@ -271,7 +279,7 @@ void decArm9Bin(u8 *armHdr, u32 mode){
//Set 0x11 to key2 for the arm9bin and misc keys //Set 0x11 to key2 for the arm9bin and misc keys
aes_setkey(0x11, key2, AES_KEYNORMAL, AES_INPUT_BE | AES_INPUT_NORMAL); aes_setkey(0x11, key2, AES_KEYNORMAL, AES_INPUT_BE | AES_INPUT_NORMAL);
aes_use_keyslot(0x11); 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); aes_setkey(slot, keyX, AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL);
} }
@@ -280,13 +288,13 @@ void decArm9Bin(u8 *armHdr, u32 mode){
aes_use_keyslot(slot); aes_use_keyslot(slot);
//Decrypt arm9bin //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 //Sets the N3DS 9.6 KeyXs
void setKeyXs(u8 *armHdr){ void setKeyXs(u8 *arm9Section){
u8 *keyData = armHdr+0x89814; u8 *keyData = arm9Section+0x89814;
u8 *decKey = keyData+0x10; u8 *decKey = keyData+0x10;
//Set keys 0x19..0x1F keyXs //Set keys 0x19..0x1F keyXs

View File

@@ -1,22 +1,27 @@
// 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
*/
#ifndef CRYPTO_INC #pragma once
#define CRYPTO_INC
#include "types.h" #include "types.h"
/**************************AES****************************/ /**************************AES****************************/
#define REG_AESCNT ((volatile u32*)0x10009000) #define REG_AESCNT ((vu32 *)0x10009000)
#define REG_AESBLKCNT ((volatile u32*)0x10009004) #define REG_AESBLKCNT ((vu32 *)0x10009004)
#define REG_AESWRFIFO ((volatile u32*)0x10009008) #define REG_AESWRFIFO ((vu32 *)0x10009008)
#define REG_AESRDFIFO ((volatile u32*)0x1000900C) #define REG_AESRDFIFO ((vu32 *)0x1000900C)
#define REG_AESKEYSEL ((volatile u8 *)0x10009010) #define REG_AESKEYSEL ((vu8 *)0x10009010)
#define REG_AESKEYCNT ((volatile u8 *)0x10009011) #define REG_AESKEYCNT ((vu8 *)0x10009011)
#define REG_AESCTR ((volatile u32*)0x10009020) #define REG_AESCTR ((vu32 *)0x10009020)
#define REG_AESKEYFIFO ((volatile u32*)0x10009100) #define REG_AESKEYFIFO ((vu32 *)0x10009100)
#define REG_AESKEYXFIFO ((volatile u32*)0x10009104) #define REG_AESKEYXFIFO ((vu32 *)0x10009104)
#define REG_AESKEYYFIFO ((volatile u32*)0x10009108) #define REG_AESKEYYFIFO ((vu32 *)0x10009108)
#define AES_CCM_DECRYPT_MODE (0u << 27) #define AES_CCM_DECRYPT_MODE (0u << 27)
#define AES_CCM_ENCRYPT_MODE (1u << 27) #define AES_CCM_ENCRYPT_MODE (1u << 27)
@@ -50,7 +55,5 @@
//NAND/FIRM stuff //NAND/FIRM stuff
void nandFirm0(u8 *outbuf, u32 size, u32 console); void nandFirm0(u8 *outbuf, u32 size, u32 console);
void decArm9Bin(u8 *armHdr, u32 mode); void decryptArm9Bin(u8 *arm9Section, u32 mode);
void setKeyXs(u8 *armHdr); void setKeyXs(u8 *arm9Section);
#endif

View File

@@ -1,43 +1,82 @@
/* /*
* draw.c * draw.c
* by Reisyukaku * by Reisyukaku / Aurora Wright
* Copyright (c) 2015 All Rights Reserved * Code to print to the screen by mid-kid @CakesFW
*
* Copyright (c) 2016 All Rights Reserved
*/ */
#include "draw.h" #include "draw.h"
#include "fs.h" #include "fs.h"
#include "memory.h" #include "memory.h"
#include "font.h"
static struct fb *fb = (struct fb *)0x23FFFE00; #define SCREEN_TOP_WIDTH 400
#define SCREEN_TOP_HEIGHT 240
void shutdownLCD(void){ static const struct fb {
u8 *top_left;
u8 *top_right;
u8 *bottom;
} *const fb = (struct fb *)0x23FFFE00;
vu32 *arm11 = (vu32 *)0x1FFFFFF8; static int strlen(const char *string){
char *stringEnd = (char *)string;
//Clear ARM11 entry offset while(*stringEnd) stringEnd++;
*arm11 = 0; return stringEnd - string;
//Shutdown LCDs
*(vu32*)0x10202A44 = 0;
*(vu32*)0x10202244 = 0;
*(vu32*)0x10202014 = 0;
//Wait for the ARM11 entrypoint to be set
while(!*arm11);
//Jump to it
((void (*)())*arm11)();
} }
void clearScreen(void){ void clearScreens(void){
memset(fb->top_left, 0, 0x46500); memset32(fb->top_left, 0, 0x46500);
memset(fb->top_right, 0, 0x46500); memset32(fb->top_right, 0, 0x46500);
memset(fb->bottom, 0, 0x38400); memset32(fb->bottom, 0, 0x38400);
} }
void loadSplash(void){ void loadSplash(void){
//Check if it's a no-screen-init A9LH boot via PDN_GPU_CNT clearScreens();
if(*(u8 *)0x10141200 == 0x1) return;
clearScreen(); //Don't delay boot if no splash image is on the SD
if(!fileRead(fb->top_left, "/rei/splash.bin", 0x46500)) return; if(fileRead(fb->top_left, "/aurei/splash.bin", 0x46500) +
u64 i = 0xFFFFFF; while(--i) __asm("mov r0, r0"); //Less Ghetto sleep func 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,21 +1,19 @@
/* /*
* draw.h * draw.h
* by Reisyukaku * by Reisyukaku / Aurora Wright
* Copyright (c) 2015 All Rights Reserved * Code to print to the screen by mid-kid @CakesFW
*
* Copyright (c) 2016 All Rights Reserved
*/ */
#ifndef DRAW_INC #pragma once
#define DRAW_INC
#include "types.h" #include "types.h"
struct fb { #define SPACING_VERT 10
u8 *top_left; #define SPACING_HORIZ 8
u8 *top_right;
u8 *bottom;
};
void loadSplash(void); void loadSplash(void);
void shutdownLCD(void); void clearScreens(void);
void drawCharacter(char character, int pos_x, int pos_y, u32 color);
#endif int drawString(const char *string, int pos_x, int pos_y, u32 color);

View File

@@ -1,42 +1,40 @@
/* /*
* emunand.c * emunand.c
* by Reisyukaku * by Reisyukaku / Aurora Wright
* Copyright (c) 2015 All Rights Reserved * Copyright (c) 2016 All Rights Reserved
*/ */
#include "emunand.h" #include "emunand.h"
#include "memory.h" #include "memory.h"
#include "fatfs/sdmmc/sdmmc.h" #include "fatfs/sdmmc/sdmmc.h"
static u8 *temp = (u8 *)0x24300000; void getEmunandSect(u32 *off, u32 *head, u32 emuNAND){
u8 *const temp = (u8 *)0x24300000;
void getEmunandSect(u32 *off, u32 *head){
u32 nandSize = getMMCDevice(0)->total_size; u32 nandSize = getMMCDevice(0)->total_size;
if(sdmmc_sdcard_readsectors(nandSize, 1, temp) == 0){ u32 nandOffset = emuNAND == 1 ? 0 :
(nandSize > 0x200000 ? 0x400000 : 0x200000);
if(sdmmc_sdcard_readsectors(nandOffset + nandSize, 1, temp) == 0){
if(*(u32 *)(temp + 0x100) == NCSD_MAGIC){ if(*(u32 *)(temp + 0x100) == NCSD_MAGIC){
*off = 0; *off = nandOffset;
*head = nandSize; *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;
} }
} }
void getSDMMC(void *pos, u32 *off, u32 size){ u32 getSDMMC(void *pos, u32 size){
//Look for struct code //Look for struct code
const unsigned char pattern[] = {0x21, 0x20, 0x18, 0x20}; const unsigned char pattern[] = {0x21, 0x20, 0x18, 0x20};
*off = (u32)memsearch(pos, pattern, size, 4) - 1; const u8 *off = (u8 *)memsearch(pos, pattern, size, 4) - 1;
//Get DCD values return *(u32 *)(off+0x0A) + *(u32 *)(off+0x0E);
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;
} }
void getEmuRW(void *pos, u32 size, u32 *readOff, u32 *writeOff){ void getEmuRW(void *pos, u32 size, u32 *readOff, u32 *writeOff){
@@ -47,9 +45,16 @@ void getEmuRW(void *pos, u32 size, u32 *readOff, u32 *writeOff){
*readOff = (u32)memsearch((void *)(*writeOff - 0x1000), pattern, 0x1000, 4) - 6; *readOff = (u32)memsearch((void *)(*writeOff - 0x1000), pattern, 0x1000, 4) - 6;
} }
void getMPU(void *pos, u32 *off, u32 size){ void *getMPU(void *pos, u32 size){
//Look for MPU pattern //Look for MPU pattern
const unsigned char pattern[] = {0x03, 0x00, 0x24, 0x00}; const unsigned char pattern[] = {0x03, 0x00, 0x24, 0x00};
*off = (u32)memsearch(pos, pattern, size, 4); return memsearch(pos, pattern, size, 4);
}
void *getEmuCode(void *pos, u32 size, u8 *proc9Offset){
const unsigned char pattern[] = {0x00, 0xFF, 0xFF, 0xFF};
//Looking for the last free space before Process9
return (u8 *)memsearch(pos, pattern, size - (size - (u32)(proc9Offset - (u8 *)pos)), 4) + 0xD;
} }

View File

@@ -1,19 +1,17 @@
/* /*
* emunand.h * emunand.h
* by Reisyukaku * by Reisyukaku / Aurora Wright
* Copyright (c) 2015 All Rights Reserved * Copyright (c) 2016 All Rights Reserved
*/ */
#ifndef EMUNAND_INC #pragma once
#define EMUNAND_INC
#include "types.h" #include "types.h"
#define NCSD_MAGIC (0x4453434E) #define NCSD_MAGIC (0x4453434E)
void getEmunandSect(u32 *off, u32 *head); 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 getEmuRW(void *pos, u32 size, u32 *readOff, u32 *writeOff);
void getMPU(void *pos, u32 *off, u32 size); void *getMPU(void *pos, u32 size);
void *getEmuCode(void *pos, u32 size, u8 *proc9Offset);
#endif

View File

@@ -811,7 +811,7 @@ FRESULT sync_fs ( /* FR_OK: successful, FR_DISK_ERR: failed */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* Hidden API for hacks and disk tools */ /* Hidden API for hacks and disk tools */
DWORD clust2sect ( /* !=0: Sector number, 0: Failed - invalid cluster# */ static DWORD clust2sect ( /* !=0: Sector number, 0: Failed - invalid cluster# */
FATFS* fs, /* File system object */ FATFS* fs, /* File system object */
DWORD clst /* Cluster# to be converted */ DWORD clst /* Cluster# to be converted */
) )
@@ -829,7 +829,7 @@ DWORD clust2sect ( /* !=0: Sector number, 0: Failed - invalid cluster# */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* Hidden API for hacks and disk tools */ /* Hidden API for hacks and disk tools */
DWORD get_fat ( /* 0xFFFFFFFF:Disk error, 1:Internal error, 2..0x0FFFFFFF:Cluster status */ static DWORD get_fat ( /* 0xFFFFFFFF:Disk error, 1:Internal error, 2..0x0FFFFFFF:Cluster status */
FATFS* fs, /* File system object */ FATFS* fs, /* File system object */
DWORD clst /* FAT index number (cluster number) to get the value */ DWORD clst /* FAT index number (cluster number) to get the value */
) )
@@ -884,7 +884,7 @@ DWORD get_fat ( /* 0xFFFFFFFF:Disk error, 1:Internal error, 2..0x0FFFFFFF:Cluste
/* Hidden API for hacks and disk tools */ /* Hidden API for hacks and disk tools */
#if !_FS_READONLY #if !_FS_READONLY
FRESULT put_fat ( static FRESULT put_fat (
FATFS* fs, /* File system object */ FATFS* fs, /* File system object */
DWORD clst, /* FAT index number (cluster number) to be changed */ DWORD clst, /* FAT index number (cluster number) to be changed */
DWORD val /* New value to be set to the entry */ DWORD val /* New value to be set to the entry */
@@ -1314,7 +1314,7 @@ int cmp_lfn ( /* 1:Matched, 0:Not matched */
} }
#if _FS_MINIMIZE <= 1 || _USE_LABEL || _FS_RPATH >= 2
static static
int pick_lfn ( /* 1:Succeeded, 0:Buffer overflow */ int pick_lfn ( /* 1:Succeeded, 0:Buffer overflow */
WCHAR* lfnbuf, /* Pointer to the Unicode-LFN buffer */ WCHAR* lfnbuf, /* Pointer to the Unicode-LFN buffer */
@@ -1345,6 +1345,7 @@ int pick_lfn ( /* 1:Succeeded, 0:Buffer overflow */
return 1; return 1;
} }
#endif
#if !_FS_READONLY #if !_FS_READONLY
@@ -1385,7 +1386,7 @@ void fit_lfn (
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* Create numbered name */ /* Create numbered name */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
#if _USE_LFN #if _USE_LFN && !_FS_READONLY
static static
void gen_numname ( void gen_numname (
BYTE* dst, /* Pointer to the buffer to store numbered SFN */ BYTE* dst, /* Pointer to the buffer to store numbered SFN */

View File

@@ -1,151 +0,0 @@
/*------------------------------------------------------------------------*/
/* Sample code of OS dependent controls for FatFs */
/* (C)ChaN, 2014 */
/*------------------------------------------------------------------------*/
#include "../ff.h"
#if _FS_REENTRANT
/*------------------------------------------------------------------------*/
/* Create a Synchronization Object */
/*------------------------------------------------------------------------*/
/* This function is called in f_mount() function to create a new
/ synchronization object, such as semaphore and mutex. When a 0 is returned,
/ the f_mount() function fails with FR_INT_ERR.
*/
int ff_cre_syncobj ( /* !=0:Function succeeded, ==0:Could not create due to any error */
BYTE vol, /* Corresponding logical drive being processed */
_SYNC_t *sobj /* Pointer to return the created sync object */
)
{
int ret;
*sobj = CreateMutex(NULL, FALSE, NULL); /* Win32 */
ret = (int)(*sobj != INVALID_HANDLE_VALUE);
// *sobj = SyncObjects[vol]; /* uITRON (give a static created sync object) */
// ret = 1; /* The initial value of the semaphore must be 1. */
// *sobj = OSMutexCreate(0, &err); /* uC/OS-II */
// ret = (int)(err == OS_NO_ERR);
// *sobj = xSemaphoreCreateMutex(); /* FreeRTOS */
// ret = (int)(*sobj != NULL);
return ret;
}
/*------------------------------------------------------------------------*/
/* Delete a Synchronization Object */
/*------------------------------------------------------------------------*/
/* This function is called in f_mount() function to delete a synchronization
/ object that created with ff_cre_syncobj function. When a 0 is returned,
/ the f_mount() function fails with FR_INT_ERR.
*/
int ff_del_syncobj ( /* !=0:Function succeeded, ==0:Could not delete due to any error */
_SYNC_t sobj /* Sync object tied to the logical drive to be deleted */
)
{
int ret;
ret = CloseHandle(sobj); /* Win32 */
// ret = 1; /* uITRON (nothing to do) */
// OSMutexDel(sobj, OS_DEL_ALWAYS, &err); /* uC/OS-II */
// ret = (int)(err == OS_NO_ERR);
// vSemaphoreDelete(sobj); /* FreeRTOS */
// ret = 1;
return ret;
}
/*------------------------------------------------------------------------*/
/* Request Grant to Access the Volume */
/*------------------------------------------------------------------------*/
/* This function is called on entering file functions to lock the volume.
/ When a 0 is returned, the file function fails with FR_TIMEOUT.
*/
int ff_req_grant ( /* 1:Got a grant to access the volume, 0:Could not get a grant */
_SYNC_t sobj /* Sync object to wait */
)
{
int ret;
ret = (int)(WaitForSingleObject(sobj, _FS_TIMEOUT) == WAIT_OBJECT_0); /* Win32 */
// ret = (int)(wai_sem(sobj) == E_OK); /* uITRON */
// OSMutexPend(sobj, _FS_TIMEOUT, &err)); /* uC/OS-II */
// ret = (int)(err == OS_NO_ERR);
// ret = (int)(xSemaphoreTake(sobj, _FS_TIMEOUT) == pdTRUE); /* FreeRTOS */
return ret;
}
/*------------------------------------------------------------------------*/
/* Release Grant to Access the Volume */
/*------------------------------------------------------------------------*/
/* This function is called on leaving file functions to unlock the volume.
*/
void ff_rel_grant (
_SYNC_t sobj /* Sync object to be signaled */
)
{
ReleaseMutex(sobj); /* Win32 */
// sig_sem(sobj); /* uITRON */
// OSMutexPost(sobj); /* uC/OS-II */
// xSemaphoreGive(sobj); /* FreeRTOS */
}
#endif
#if _USE_LFN == 3 /* LFN with a working buffer on the heap */
/*------------------------------------------------------------------------*/
/* Allocate a memory block */
/*------------------------------------------------------------------------*/
/* If a NULL is returned, the file function fails with FR_NOT_ENOUGH_CORE.
*/
void* ff_memalloc ( /* Returns pointer to the allocated memory block */
UINT msize /* Number of bytes to allocate */
)
{
return malloc(msize); /* Allocate a new memory block with POSIX API */
}
/*------------------------------------------------------------------------*/
/* Free a memory block */
/*------------------------------------------------------------------------*/
void ff_memfree (
void* mblock /* Pointer to the memory block to free */
)
{
free(mblock); /* Discard the memory block with POSIX API */
}
#endif

View File

@@ -1,15 +1,4 @@
#pragma once #pragma once
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h> #include <stdbool.h>
#include "../../types.h"
#define u8 uint8_t
#define u16 uint16_t
#define u32 uint32_t
#define u64 uint64_t
#define vu8 volatile u8
#define vu16 volatile u16
#define vu32 volatile u32
#define vu64 volatile u64

View File

@@ -6,4 +6,4 @@
#include "common.h" #include "common.h"
void waitcycles(u32 us); void ioDelay(u32 us);

View File

@@ -1,15 +1,17 @@
.arm // Copyright 2014 Normmatt
.global waitcycles // Licensed under GPLv2 or any later version
.type waitcycles STT_FUNC // Refer to the license.txt file included.
@waitcycles ( u32 us ) .arm
waitcycles: .global ioDelay
PUSH {R0-R2,LR} .type ioDelay STT_FUNC
STR R0, [SP,#4]
waitcycles_loop: @ioDelay ( u32 us )
LDR R3, [SP,#4] ioDelay:
SUBS R2, R3, #1 ldr r1, =0x18000000 @ VRAM
STR R2, [SP,#4] 1:
CMP R3, #0 @ Loop doing uncached reads from VRAM to make loop timing more reliable
BNE waitcycles_loop ldr r2, [r1]
POP {R0-R2,PC} subs r0, #1
bgt 1b
bx lr

View File

@@ -2,8 +2,6 @@
// Licensed under GPLv2 or any later version // Licensed under GPLv2 or any later version
// Refer to the license.txt file included. // Refer to the license.txt file included.
#include "common.h"
#include "sdmmc.h" #include "sdmmc.h"
#include "delay.h" #include "delay.h"
@@ -286,7 +284,7 @@ static void InitSD()
static int Nand_Init() static int Nand_Init()
{ {
inittarget(&handleNAND); inittarget(&handleNAND);
waitcycles(0xF000); ioDelay(0xF000);
sdmmc_send_command(&handleNAND,0,0); sdmmc_send_command(&handleNAND,0,0);
@@ -337,7 +335,7 @@ static int SD_Init()
{ {
inittarget(&handleSD); inittarget(&handleSD);
waitcycles(1u << 18); //Card needs a little bit of time to be detected, it seems ioDelay(1u << 18); //Card needs a little bit of time to be detected, it seems
//If not inserted //If not inserted
if (!(*((vu16*)0x1000601c) & TMIO_STAT0_SIGSTATE)) return -1; if (!(*((vu16*)0x1000601c) & TMIO_STAT0_SIGSTATE)) return -1;

View File

@@ -125,4 +125,3 @@ mmcdevice *getMMCDevice(int drive);
u32 sdmmc_nand_readsectors(u32 sector_no, u32 numsectors, vu8 *out); u32 sdmmc_nand_readsectors(u32 sector_no, u32 numsectors, vu8 *out);
u32 sdmmc_nand_writesectors(u32 sector_no, u32 numsectors, vu8 *in); u32 sdmmc_nand_writesectors(u32 sector_no, u32 numsectors, vu8 *in);

View File

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

View File

@@ -1,25 +1,36 @@
/* /*
* firm.h * firm.h
* by Reisyukaku * by Reisyukaku / Aurora Wright
* Copyright (c) 2015 All Rights Reserved * Copyright (c) 2016 All Rights Reserved
*/ */
#ifndef FIRM_INC #pragma once
#define FIRM_INC
#include "types.h" #include "types.h"
#define PDN_MPCORE_CFG (*(u8*)0x10140FFC) #define PDN_MPCORE_CFG (*(vu8 *)0x10140FFC)
#define HID_PAD ((~*(u16*)0x10146000) & 0xFFF) #define PDN_SPI_CNT (*(vu8 *)0x101401C0)
#define BUTTON_R1 (1 << 8) #define CFG_BOOTENV (*(vu8 *)0x10010000)
#define BUTTON_L1 (1 << 9)
#define BUTTON_L1R1 (BUTTON_R1 | BUTTON_L1) //FIRM Header layout
#define BUTTON_A 1 typedef struct firmSectionHeader {
#define SAFEMODE (BUTTON_L1R1 | BUTTON_A | (1 << 6)) u32 offset;
u8 *address;
u32 size;
u32 procType;
u8 hash[0x20];
} firmSectionHeader;
typedef struct firmHeader {
u32 magic;
u32 reserved1;
u8 *arm11Entry;
u8 *arm9Entry;
u8 reserved2[0x30];
firmSectionHeader section[4];
} firmHeader;
void setupCFW(void); void setupCFW(void);
u32 loadFirm(void); void loadFirm(void);
u32 patchFirm(void); void patchFirm(void);
void launchFirm(void); void launchFirm(void);
#endif

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 * fs.c
* by Reisyukaku / Aurora Wright
* Copyright (c) 2016 All Rights Reserved
*/ */
#include "fs.h" #include "fs.h"
@@ -52,10 +54,14 @@ u32 fileSize(const char *path){
u32 fileExists(const char *path){ u32 fileExists(const char *path){
FIL fp; FIL fp;
u8 exists = 0; u32 exists = 0;
if(f_open(&fp, path, FA_READ) == FR_OK) exists = 1; if(f_open(&fp, path, FA_READ) == FR_OK) exists = 1;
f_close(&fp); f_close(&fp);
return exists; return exists;
} }
void fileDelete(const char *path){
f_unlink(path);
}

View File

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

98
source/i2c.c Normal file
View File

@@ -0,0 +1,98 @@
#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;
}

18
source/i2c.h Normal file
View File

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

View File

@@ -1,12 +1,11 @@
/* /*
* loader.h * loader.h
* by Aurora Wright
* Copyright (c) 2016 All Rights Reserved
*/ */
#ifndef LOADER_INC #pragma once
#define LOADER_INC
#include "types.h" #include "types.h"
void loadPayload(void); void loadPayload(void);
#endif

View File

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

View File

@@ -1,7 +1,7 @@
/* /*
* memory.c * memory.c
* by Reisyukaku * by Reisyukaku / Aurora Wright
* Copyright (c) 2015 All Rights Reserved * Copyright (c) 2016 All Rights Reserved
*/ */
#include "memory.h" #include "memory.h"
@@ -19,6 +19,12 @@ void memset(void *dest, int filler, u32 size){
destc[i] = (u8)filler; destc[i] = (u8)filler;
} }
void memset32(void *dest, u32 filler, u32 size){
u32 *dest32 = (u32 *)dest;
for (u32 i = 0; i < size / 4; i++)
dest32[i] = filler;
}
int memcmp(const void *buf1, const void *buf2, u32 size){ int memcmp(const void *buf1, const void *buf2, u32 size){
const u8 *buf1c = (const u8 *)buf1; const u8 *buf1c = (const u8 *)buf1;
const u8 *buf2c = (const u8 *)buf2; const u8 *buf2c = (const u8 *)buf2;

View File

@@ -1,17 +1,15 @@
/* /*
* memory.h * memory.h
* by Reisyukaku * by Reisyukaku / Aurora Wright
* Copyright (c) 2015 All Rights Reserved * Copyright (c) 2016 All Rights Reserved
*/ */
#ifndef MEMORY_INC #pragma once
#define MEMORY_INC
#include "types.h" #include "types.h"
void memcpy(void *dest, const void *src, u32 size); void memcpy(void *dest, const void *src, u32 size);
void memset(void *dest, int filler, u32 size); void memset(void *dest, int filler, u32 size);
void memset32(void *dest, u32 filler, u32 size);
int memcmp(const void *buf1, const void *buf2, u32 size); int memcmp(const void *buf1, const void *buf2, u32 size);
void *memsearch(void *start_pos, const void *search, u32 size, u32 size_search); void *memsearch(void *start_pos, const void *search, u32 size, u32 size_search);
#endif

View File

@@ -1,7 +1,7 @@
/* /*
* patches.c * patches.c
* by Reisyukaku * by Reisyukaku / Aurora Wright
* Copyright (c) 2015 All Rights Reserved * Copyright (c) 2016 All Rights Reserved
*/ */
#include "patches.h" #include "patches.h"
@@ -11,25 +11,28 @@
* Patches * Patches
**************************************************/ **************************************************/
const u8 mpu[0x2C] = { //MPU shit const u8 mpu[0x2C] = {
0x03, 0x00, 0x36, 0x00, 0x00, 0x00, 0x10, 0x10, 0x01, 0x00, 0x00, 0x01, 0x03, 0x00, 0x36, 0x00, 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, 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 0x01, 0x01, 0x01, 0x01, 0x03, 0x06, 0x1C, 0x00, 0x00, 0x00, 0x02, 0x08
}; };
u8 nandRedir[0x08] = {0x00, 0x4C, 0xA0, 0x47, 0xC0, 0xA5, 0x01, 0x08}; //Branch to emunand function //Branch to emunand function. To be filled in
u8 nandRedir[0x08] = {0x00, 0x4C, 0xA0, 0x47, 0x00, 0x00, 0x00, 0x00};
const u8 sigPat1[2] = {0x00, 0x20}; const u8 sigPat1[2] = {0x00, 0x20};
const u8 sigPat2[4] = {0x00, 0x20, 0x70, 0x47}; const u8 sigPat2[4] = {0x00, 0x20, 0x70, 0x47};
const u8 FIRMblock[4] = {0x00, 0x20, 0xC0, 0x46}; const u8 writeBlock[4] = {0x00, 0x20, 0xC0, 0x46};
const u8 emuInstr[5] = {0xA5, 0x01, 0x08, 0x30, 0xA5};
/************************************************** /**************************************************
* Functions * Functions
**************************************************/ **************************************************/
u8 *getProc9(void *pos, u32 size){
return (u8 *)memsearch(pos, "ess9", size, 4);
}
void getSignatures(void *pos, u32 size, u32 *off, u32 *off2){ void getSignatures(void *pos, u32 size, u32 *off, u32 *off2){
//Look for signature checks //Look for signature checks
const unsigned char pattern[] = {0xC0, 0x1C, 0x76, 0xE7}; const unsigned char pattern[] = {0xC0, 0x1C, 0x76, 0xE7};
@@ -39,26 +42,29 @@ void getSignatures(void *pos, u32 size, u32 *off, u32 *off2){
*off2 = (u32)memsearch(pos, pattern2, size, 4) - 1; *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 //Look for FIRM reboot code
const unsigned char pattern[] = {0xDE, 0x1F, 0x8D, 0xE2}; 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){ u32 getfOpen(void *pos, u32 size, u8 *proc9Offset){
//Offset Process9 code gets loaded to in memory (defined in ExHeader)
u32 p9MemAddr = *(u32 *)(proc9Offset + 0xC);
//Start of Process9 .code section (start of NCCH + ExeFS offset + ExeFS header size)
u32 p9CodeOff = (u32)(proc9Offset - 0x204) + (*(u32 *)(proc9Offset - 0x64) * 0x200) + 0x200;
//Calculate fOpen //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}; const unsigned char pattern[] = {0xB0, 0x04, 0x98, 0x0D};
*off = (u32)memsearch(pos, pattern, size, 4) - 2 - p9off + p9addr; return (u32)memsearch(pos, pattern, size, 4) - 2 - p9CodeOff + p9MemAddr;
} }
void getFIRMWrite(void *pos, u32 size, u32 *off){ void *getFirmWrite(void *pos, u32 size){
//Look for FIRM writing code //Look for FIRM writing code
u8 *firmwrite = (u8 *)memsearch(pos, "exe:", size, 4); u8 *firmwrite = (u8 *)memsearch(pos, "exe:", size, 4);
const unsigned char pattern[] = {0x00, 0x28, 0x01, 0xDA}; const unsigned char pattern[] = {0x00, 0x28, 0x01, 0xDA};
*off = (u32)memsearch(firmwrite - 0x100, pattern, 0x100, 4); return memsearch(firmwrite - 0x100, pattern, 0x100, 4);
} }

View File

@@ -1,11 +1,10 @@
/* /*
* patches.h * patches.h
* by Reisyukaku * by Reisyukaku / Aurora Wright
* Copyright (c) 2015 All Rights Reserved * Copyright (c) 2016 All Rights Reserved
*/ */
#ifndef PATCHES_INC #pragma once
#define PATCHES_INC
#include "types.h" #include "types.h"
@@ -16,15 +15,13 @@ const u8 mpu[0x2C];
u8 nandRedir[0x08]; u8 nandRedir[0x08];
const u8 sigPat1[2]; const u8 sigPat1[2];
const u8 sigPat2[4]; const u8 sigPat2[4];
const u8 FIRMblock[4]; const u8 writeBlock[4];
const u8 emuInstr[5];
/************************************************** /**************************************************
* Functions * Functions
**************************************************/ **************************************************/
u8 *getProc9(void *pos, u32 size);
void getSignatures(void *pos, u32 size, u32 *off, u32 *off2); void getSignatures(void *pos, u32 size, u32 *off, u32 *off2);
void getReboot(void *pos, u32 size, u32 *off); void *getReboot(void *pos, u32 size);
void getfOpen(void *pos, u32 size, u32 *off); u32 getfOpen(void *pos, u32 size, u8 *proc9Offset);
void getFIRMWrite(void *pos, u32 size, u32 *off); void *getFirmWrite(void *pos, u32 size);
#endif

152
source/screeninit.c Normal file
View File

@@ -0,0 +1,152 @@
/*
* 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"
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 = 0x45;
*(vu32 *)0x10202A40 = 0x45;
*(vu32 *)0x10202244 = 0x1023E;
*(vu32 *)0x10202A44 = 0x1023E;
// Top screen
*(vu32 *)0x10400400 = 0x000001c2;
*(vu32 *)0x10400404 = 0x000000d1;
*(vu32 *)0x10400408 = 0x000001c1;
*(vu32 *)0x1040040c = 0x000001c1;
*(vu32 *)0x10400410 = 0x00000000;
*(vu32 *)0x10400414 = 0x000000cf;
*(vu32 *)0x10400418 = 0x000000d1;
*(vu32 *)0x1040041c = 0x01c501c1;
*(vu32 *)0x10400420 = 0x00010000;
*(vu32 *)0x10400424 = 0x0000019d;
*(vu32 *)0x10400428 = 0x00000002;
*(vu32 *)0x1040042c = 0x00000192;
*(vu32 *)0x10400430 = 0x00000192;
*(vu32 *)0x10400434 = 0x00000192;
*(vu32 *)0x10400438 = 0x00000001;
*(vu32 *)0x1040043c = 0x00000002;
*(vu32 *)0x10400440 = 0x01960192;
*(vu32 *)0x10400444 = 0x00000000;
*(vu32 *)0x10400448 = 0x00000000;
*(vu32 *)0x1040045C = 0x00f00190;
*(vu32 *)0x10400460 = 0x01c100d1;
*(vu32 *)0x10400464 = 0x01920002;
*(vu32 *)0x10400468 = 0x18300000;
*(vu32 *)0x10400470 = 0x80341;
*(vu32 *)0x10400474 = 0x00010501;
*(vu32 *)0x10400478 = 0;
*(vu32 *)0x10400490 = 0x000002D0;
*(vu32 *)0x1040049C = 0x00000000;
// Disco register
for(vu32 i = 0; i < 256; i++)
*(vu32 *)0x10400484 = 0x10101 * i;
// Bottom screen
*(vu32 *)0x10400500 = 0x000001c2;
*(vu32 *)0x10400504 = 0x000000d1;
*(vu32 *)0x10400508 = 0x000001c1;
*(vu32 *)0x1040050c = 0x000001c1;
*(vu32 *)0x10400510 = 0x000000cd;
*(vu32 *)0x10400514 = 0x000000cf;
*(vu32 *)0x10400518 = 0x000000d1;
*(vu32 *)0x1040051c = 0x01c501c1;
*(vu32 *)0x10400520 = 0x00010000;
*(vu32 *)0x10400524 = 0x0000019d;
*(vu32 *)0x10400528 = 0x00000052;
*(vu32 *)0x1040052c = 0x00000192;
*(vu32 *)0x10400530 = 0x00000192;
*(vu32 *)0x10400534 = 0x0000004f;
*(vu32 *)0x10400538 = 0x00000050;
*(vu32 *)0x1040053c = 0x00000052;
*(vu32 *)0x10400540 = 0x01980194;
*(vu32 *)0x10400544 = 0x00000000;
*(vu32 *)0x10400548 = 0x00000011;
*(vu32 *)0x1040055C = 0x00f00140;
*(vu32 *)0x10400560 = 0x01c100d1;
*(vu32 *)0x10400564 = 0x01920052;
*(vu32 *)0x10400568 = 0x18300000 + 0x46500;
*(vu32 *)0x10400570 = 0x80301;
*(vu32 *)0x10400574 = 0x00010501;
*(vu32 *)0x10400578 = 0;
*(vu32 *)0x10400590 = 0x000002D0;
*(vu32 *)0x1040059C = 0x00000000;
// Disco register
for(vu32 i = 0; i < 256; i++)
*(vu32 *)0x10400584 = 0x10101 * i;
// Enable backlight
i2cWriteRegister(I2C_DEV_MCU, 0x22, 0x2A);
*(vu32 *)0x10400468 = 0x18300000;
*(vu32 *)0x1040046c = 0x18300000;
*(vu32 *)0x10400494 = 0x18300000;
*(vu32 *)0x10400498 = 0x18300000;
*(vu32 *)0x10400568 = 0x18346500;
*(vu32 *)0x1040056c = 0x18346500;
//Set CakeBrah framebuffers
*((vu32 *)0x23FFFE00) = 0x18300000;
*((vu32 *)0x23FFFE04) = 0x18300000;
*((vu32 *)0x23FFFE08) = 0x18346500;
//Clear ARM11 entry offset
*arm11 = 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);
}
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

@@ -10,7 +10,7 @@ _start:
mcr p15, 0, r0, c5, c0, 2 @ write data access mcr p15, 0, r0, c5, c0, 2 @ write data access
mcr p15, 0, r0, c5, c0, 3 @ write instruction access mcr p15, 0, r0, c5, c0, 3 @ write instruction access
@ Set MPU permissions @ Set MPU permissions and cache settings
ldr r0, =0xFFFF001D @ ffff0000 32k ldr r0, =0xFFFF001D @ ffff0000 32k
ldr r1, =0x01FF801D @ 01ff8000 32k ldr r1, =0x01FF801D @ 01ff8000 32k
ldr r2, =0x08000027 @ 08000000 1M ldr r2, =0x08000027 @ 08000000 1M
@@ -27,6 +27,10 @@ _start:
mcr p15, 0, r5, c6, c5, 0 mcr p15, 0, r5, c6, c5, 0
mcr p15, 0, r6, c6, c6, 0 mcr p15, 0, r6, c6, c6, 0
mcr p15, 0, r7, c6, c7, 0 mcr p15, 0, r7, c6, c7, 0
mov r0, #0x25
mcr p15, 0, r0, c2, c0, 0 @ data cacheable
mcr p15, 0, r0, c2, c0, 1 @ instruction cacheable
mcr p15, 0, r0, c3, c0, 0 @ data bufferable
@ Enable caches @ Enable caches
mrc p15, 0, r0, c1, c0, 0 @ read control register mrc p15, 0, r0, c1, c0, 0 @ read control register
@@ -48,15 +52,5 @@ _start:
bl main bl main
@ Set cache settings
mov r0, #0x25
mov r1, #0x25
mov r2, #0x25
mcr p15, 0, r0, c3, c0, 0 @ Write bufferable 0, 2, 5
mcr p15, 0, r1, c2, c0, 0 @ Data cacheable 0, 2, 5
mcr p15, 0, r2, c2, c0, 1 @ Inst cacheable 0, 2, 5
bl startCFW
.die: .die:
b .die b .die

View File

@@ -4,8 +4,7 @@
* Copyright (c) 2015 All Rights Reserved * Copyright (c) 2015 All Rights Reserved
*/ */
#ifndef TYPES_INC #pragma once
#define TYPES_INC
#include <stdint.h> #include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
@@ -15,27 +14,7 @@ typedef uint8_t u8;
typedef uint16_t u16; typedef uint16_t u16;
typedef uint32_t u32; typedef uint32_t u32;
typedef uint64_t u64; typedef uint64_t u64;
typedef volatile uint8_t vu8; typedef volatile u8 vu8;
typedef volatile uint16_t vu16; typedef volatile u16 vu16;
typedef volatile uint32_t vu32; typedef volatile u32 vu32;
typedef volatile uint64_t vu64; typedef volatile u64 vu64;
//FIRM Header layout
typedef struct firmSectionHeader {
u32 offset;
u8 *address;
u32 size;
u32 procType;
u8 hash[0x20];
} firmSectionHeader;
typedef struct firmHeader {
u32 magic;
u32 reserved1;
u8 *arm11Entry;
u8 *arm9Entry;
u8 reserved2[0x30];
firmSectionHeader section[4];
} firmHeader;
#endif

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((u8 *)&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((u8 *)&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);