Compare commits

..

19 Commits
v3.8 ... v3.11

Author SHA1 Message Date
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
51 changed files with 724 additions and 638 deletions

View File

@@ -12,7 +12,7 @@ ifneq ($(PYTHON_VER_MAJOR), 3)
PYTHON3 := py -3
endif
name := ReiNand
name := AuReiNand
dir_source := source
dir_data := data
@@ -26,7 +26,7 @@ dir_loader := loader
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
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, \
$(patsubst $(dir_source)/%.c, $(dir_build)/%.o, \
@@ -43,28 +43,29 @@ launcher: $(dir_out)/$(name).dat
a9lh: $(dir_out)/arm9loaderhax.bin
.PHONY: emunand
emunand: $(dir_out)/rei/emunand/emunand.bin
emunand: $(dir_out)/aurei/emunand/emunand.bin
.PHONY: reboot
reboot: $(dir_out)/rei/reboot/reboot.bin
reboot: $(dir_out)/aurei/reboot/reboot.bin
.PHONY: ninjhax
ninjhax: $(dir_out)/3ds/$(name)
.PHONY: loader
loader: $(dir_out)/rei/loader.bin
loader: $(dir_out)/aurei/loader.bin
.PHONY: clean
clean:
@$(MAKE) $(FLAGS) -C $(dir_mset) 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)/$(name).dat: $(dir_build)/main.bin $(dir_out)/aurei
@$(MAKE) $(FLAGS) -C $(dir_mset) launcher
dd if=$(dir_build)/main.bin of=$@ bs=512 seek=144
$(dir_out)/arm9loaderhax.bin: $(dir_build)/main.bin $(dir_out)/rei
$(dir_out)/arm9loaderhax.bin: $(dir_build)/main.bin $(dir_out)/aurei
@cp -av $(dir_build)/main.bin $@
$(dir_out)/3ds/$(name):
@@ -73,21 +74,21 @@ $(dir_out)/3ds/$(name):
@mv $(dir_out)/$(name).3dsx $@
@mv $(dir_out)/$(name).smdh $@
$(dir_out)/rei:
@mkdir -p "$(dir_out)/rei"
$(dir_out)/aurei:
@mkdir -p "$(dir_out)/aurei"
$(dir_out)/rei/emunand/emunand.bin: $(dir_emu)/emuCode.s
$(dir_out)/aurei/emunand/emunand.bin: $(dir_emu)/emuCode.s
@armips $<
@mkdir -p "$(dir_out)/rei/emunand"
@mkdir -p "$(dir_out)/aurei/emunand"
@mv emunand.bin $@
$(dir_out)/rei/reboot/reboot.bin: $(dir_reboot)/rebootCode.s
$(dir_out)/aurei/reboot/reboot.bin: $(dir_reboot)/rebootCode.s
@armips $<
@mkdir -p "$(dir_out)/rei/reboot"
@mkdir -p "$(dir_out)/aurei/reboot"
@mv reboot.bin $@
$(dir_out)/rei/loader.bin: $(dir_out)/rei $(dir_loader)/Makefile
@cd $(dir_loader) && make
$(dir_out)/aurei/loader.bin: $(dir_out)/aurei $(dir_loader)/Makefile
@$(MAKE) -C $(dir_loader)
@mv $(dir_loader)/loader.bin $@
$(dir_build)/main.bin: $(dir_build)/main.elf

View File

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

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
CFLAGS := -g -Wall -O2\
-march=armv5te -mtune=arm946e-s -fomit-frame-pointer\
-ffast-math -std=c99\
-march=armv5te -mtune=arm946e-s\
-ffast-math -Wno-main -std=c99\
$(ARCH)
CFLAGS += $(INCLUDE) -DARM9
@@ -105,7 +105,7 @@ $(BUILD):
#---------------------------------------------------------------------------------
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

@@ -69,7 +69,7 @@ DRESULT disk_read (
DRESULT disk_write (
__attribute__((unused))
BYTE pdrv, /* Physical drive nmuber to identify the drive */
const BYTE *buff, /* Data to be written */
const BYTE *buff, /* Data to be written */
DWORD sector, /* Sector address in LBA */
UINT count /* Number of sectors to write */
)

View File

@@ -811,7 +811,7 @@ FRESULT sync_fs ( /* FR_OK: successful, FR_DISK_ERR: failed */
/*-----------------------------------------------------------------------*/
/* 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 */
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 */
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 */
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 */
#if !_FS_READONLY
FRESULT put_fat (
static FRESULT put_fat (
FATFS* fs, /* File system object */
DWORD clst, /* FAT index number (cluster number) to be changed */
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
int pick_lfn ( /* 1:Succeeded, 0:Buffer overflow */
WCHAR* lfnbuf, /* Pointer to the Unicode-LFN buffer */
@@ -1345,6 +1345,7 @@ int pick_lfn ( /* 1:Succeeded, 0:Buffer overflow */
return 1;
}
#endif
#if !_FS_READONLY
@@ -1385,7 +1386,7 @@ void fit_lfn (
/*-----------------------------------------------------------------------*/
/* Create numbered name */
/*-----------------------------------------------------------------------*/
#if _USE_LFN
#if _USE_LFN && !_FS_READONLY
static
void gen_numname (
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
#include <stdint.h>
#include <stddef.h>
#include <stdbool.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
#include "../../types.h"

View File

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

View File

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

View File

@@ -2,8 +2,6 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include "common.h"
#include "sdmmc.h"
#include "delay.h"
@@ -286,7 +284,7 @@ static void InitSD()
static int Nand_Init()
{
inittarget(&handleNAND);
waitcycles(0xF000);
ioDelay(0xF000);
sdmmc_send_command(&handleNAND,0,0);
@@ -337,7 +335,7 @@ static int SD_Init()
{
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 (!(*((vu16*)0x1000601c) & TMIO_STAT0_SIGSTATE)) return -1;

View File

@@ -124,5 +124,4 @@ u32 sdmmc_sdcard_writesectors(u32 sector_no, u32 numsectors, vu8 *in);
mmcdevice *getMMCDevice(int drive);
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);

98
loader/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
loader/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,19 +1,43 @@
#include "types.h"
#include "buttons.h"
#include "screeninit.h"
#include "fatfs/ff.h"
#define PAYLOAD_ADDRESS 0x23F00000
int main()
{
FATFS fs;
static u32 loadPayload(const char *path){
FIL payload;
unsigned int br;
f_mount(&fs, "0:", 1);
if(f_open(&payload, "rei/arm9payload.bin", FA_READ) == FR_OK)
if(f_open(&payload, path, FA_READ) == FR_OK)
{
f_read(&payload, (void *)PAYLOAD_ADDRESS, f_size(&payload), &br);
((void (*)())PAYLOAD_ADDRESS)();
f_read(&payload, (void*)PAYLOAD_ADDRESS, f_size(&payload), &br);
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")){
//Determine if screen was already inited
if(*(vu8 *)0x10141200 == 0x1) initLCD();
((void (*)())PAYLOAD_ADDRESS)();
}
}

111
loader/source/screeninit.c Normal file
View File

@@ -0,0 +1,111 @@
#include "screeninit.h"
#include "i2c.h"
void initLCD(void){
vu32 *const arm11 = (vu32 *)0x1FFFFFF8;
void __attribute__((naked)) ARM11(void){
__asm(".word 0xF10C01C0");
*(vu32 *)0x10141200 = 0x1007F;
*(vu32 *)0x10202014 = 0x00000001;
*(vu32 *)0x1020200C &= 0xFFFEFFFE;
*(vu32 *)0x10202240 = 0x39;
*(vu32 *)0x10202A40 = 0x39;
*(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)();
}
*arm11 = (u32)ARM11;
while(*arm11);
}

View File

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

View File

@@ -2,6 +2,9 @@
.align 4
.global _start
_start:
@ Fix payloads like Decrypt9
mov r0, #0x5
mcr p15, 0, r0, c3, c0, 0 @ data bufferable
@ Flush caches
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,12 +1,11 @@
.nds
.create "reboot.bin", 0
.arm.little
byteswritten equ 0x2000E000
externalFirm equ 0x2000A000
kernelCode equ 0x080F0000
buffer equ 0x24000000
fileOpen equ 0x4E45504F ;dummy
.create "reboot.bin", 0
.arm
//Code jumps here right after the sprintf call
process9Reboot:
@@ -34,18 +33,16 @@ process9Reboot:
ldreq r1, =(FileName - OpenFirm - 12)
addeq r1, pc
addne r1, sp, #0x3A8-0x70
ldr r0, =externalFirm
moveq r2, #1
movne r2, #0
str r2, [r0]
str r2, [externalFirm]
mov r2, #1
add r0, r7, #8
ldr r6, =fileOpen
blx r6
SeekFirm:
ldr r0, =externalFirm
ldr r0, [r0]
ldr r0, [externalFirm]
cmp r0, #1
moveq r0, r7
ldreq r1, =byteswritten
@@ -97,11 +94,14 @@ Memcpy:
LDMFD SP!, {R0-R4}
MOV LR, R12
BX LR
FileName:
.dcw "sdmc:/rei/patched_firmware_sys.bin"
.dcw "sdmc:/aurei/patched_firmware_sys.bin"
.word 0x0
externalFirm:
.word 0x2000A000
.pool
// Kernel Code

View File

@@ -54,10 +54,10 @@ __asm__\
}
#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
u32 * key32 = (u32 *)key;
u32 *key32 = (u32 *)key;
*REG_AESCNT = (*REG_AESCNT & ~(AES_CNT_INPUT_ENDIAN | AES_CNT_INPUT_ORDER)) | mode;
*REG_AESKEYCNT = (*REG_AESKEYCNT >> 6 << 6) | keyslot | AES_KEYCNT_WRITE;
@@ -67,7 +67,7 @@ void aes_setkey(u8 keyslot, const void* key, u32 keyType, u32 mode)
REG_AESKEYFIFO[keyType] = key32[3];
}
void aes_use_keyslot(u8 keyslot)
static void aes_use_keyslot(u8 keyslot)
{
if(keyslot > 0x3F)
return;
@@ -76,7 +76,7 @@ void aes_use_keyslot(u8 keyslot)
*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;
*REG_AESCNT = (*REG_AESCNT & ~(AES_CNT_INPUT_ENDIAN | AES_CNT_INPUT_ORDER)) | mode;
@@ -98,9 +98,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;
if(mode & AES_INPUT_BE)
@@ -125,7 +125,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;
int i;
@@ -147,7 +147,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_AESCNT |= AES_CNT_START;
@@ -180,7 +180,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 |
AES_CNT_INPUT_ORDER | AES_CNT_OUTPUT_ORDER |
@@ -228,12 +228,12 @@ void aes(void *dst, const void *src, u32 blockCount, void *iv, u32 mode, u32 ivM
****************************************************************/
//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
};
//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;
for(u8 keyLen = 0x10; keyLen; keyLen--)
*(buf++) = *(addr--);

View File

@@ -1,56 +1,53 @@
// From http://github.com/b1l1s/ctr
#ifndef CRYPTO_INC
#define CRYPTO_INC
#pragma once
#include "types.h"
/**************************AES****************************/
#define REG_AESCNT ((volatile u32*)0x10009000)
#define REG_AESBLKCNT ((volatile u32*)0x10009004)
#define REG_AESWRFIFO ((volatile u32*)0x10009008)
#define REG_AESRDFIFO ((volatile u32*)0x1000900C)
#define REG_AESKEYSEL ((volatile u8 *)0x10009010)
#define REG_AESKEYCNT ((volatile u8 *)0x10009011)
#define REG_AESCTR ((volatile u32*)0x10009020)
#define REG_AESCNT ((vu32 *)0x10009000)
#define REG_AESBLKCNT ((vu32 *)0x10009004)
#define REG_AESWRFIFO ((vu32 *)0x10009008)
#define REG_AESRDFIFO ((vu32 *)0x1000900C)
#define REG_AESKEYSEL ((vu8 *)0x10009010)
#define REG_AESKEYCNT ((vu8 *)0x10009011)
#define REG_AESCTR ((vu32 *)0x10009020)
#define REG_AESKEYFIFO ((volatile u32*)0x10009100)
#define REG_AESKEYXFIFO ((volatile u32*)0x10009104)
#define REG_AESKEYYFIFO ((volatile u32*)0x10009108)
#define REG_AESKEYFIFO ((vu32 *)0x10009100)
#define REG_AESKEYXFIFO ((vu32 *)0x10009104)
#define REG_AESKEYYFIFO ((vu32 *)0x10009108)
#define AES_CCM_DECRYPT_MODE (0u << 27)
#define AES_CCM_ENCRYPT_MODE (1u << 27)
#define AES_CTR_MODE (2u << 27)
#define AES_CTR_MODE (2u << 27)
#define AES_CTR_MODE (2u << 27)
#define AES_CTR_MODE (2u << 27)
#define AES_CBC_DECRYPT_MODE (4u << 27)
#define AES_CBC_ENCRYPT_MODE (5u << 27)
#define AES_ECB_DECRYPT_MODE (6u << 27)
#define AES_ECB_ENCRYPT_MODE (7u << 27)
#define AES_ALL_MODES (7u << 27)
#define AES_ALL_MODES (7u << 27)
#define AES_CNT_START 0x80000000
#define AES_CNT_INPUT_ORDER 0x02000000
#define AES_CNT_START 0x80000000
#define AES_CNT_INPUT_ORDER 0x02000000
#define AES_CNT_OUTPUT_ORDER 0x01000000
#define AES_CNT_INPUT_ENDIAN 0x00800000
#define AES_CNT_OUTPUT_ENDIAN 0x00400000
#define AES_CNT_FLUSH_READ 0x00000800
#define AES_CNT_FLUSH_WRITE 0x00000400
#define AES_CNT_FLUSH_READ 0x00000800
#define AES_CNT_FLUSH_WRITE 0x00000400
#define AES_INPUT_BE (AES_CNT_INPUT_ENDIAN)
#define AES_INPUT_LE 0
#define AES_INPUT_NORMAL (AES_CNT_INPUT_ORDER)
#define AES_INPUT_REVERSED 0
#define AES_INPUT_BE (AES_CNT_INPUT_ENDIAN)
#define AES_INPUT_LE 0
#define AES_INPUT_NORMAL (AES_CNT_INPUT_ORDER)
#define AES_INPUT_REVERSED 0
#define AES_BLOCK_SIZE 0x10
#define AES_BLOCK_SIZE 0x10
#define AES_KEYCNT_WRITE (1 << 0x7)
#define AES_KEYNORMAL 0
#define AES_KEYX 1
#define AES_KEYY 2
#define AES_KEYCNT_WRITE (1 << 0x7)
#define AES_KEYNORMAL 0
#define AES_KEYX 1
#define AES_KEYY 2
//NAND/FIRM stuff
void nandFirm0(u8 *outbuf, u32 size, u32 console);
void decArm9Bin(u8 *armHdr, u32 mode);
void setKeyXs(u8 *armHdr);
#endif
void setKeyXs(u8 *armHdr);

View File

@@ -8,36 +8,41 @@
#include "fs.h"
#include "memory.h"
static struct fb *fb = (struct fb *)0x23FFFE00;
static const struct fb {
u8 *top_left;
u8 *top_right;
u8 *bottom;
} *const fb = (struct fb *)0x23FFFE00;
void shutdownLCD(void){
void __attribute__((naked)) shutdownLCD(void){
vu32 *arm11 = (vu32 *)0x1FFFFFF8;
vu32 *const arm11 = (u32 *)0x1FFFFFF8;
//Clear ARM11 entry offset
*arm11 = 0;
//Shutdown LCDs
*(vu32*)0x10202A44 = 0;
*(vu32*)0x10202244 = 0;
*(vu32*)0x10202014 = 0;
*(vu32 *)0x10202A44 = 0;
*(vu32 *)0x10202244 = 0;
*(vu32 *)0x10202014 = 0;
//Wait for the ARM11 entrypoint to be set
//Wait for the entry to be set
while(!*arm11);
//Jump to it
((void (*)())*arm11)();
}
void clearScreen(void){
memset(fb->top_left, 0, 0x46500);
memset(fb->top_right, 0, 0x46500);
memset(fb->bottom, 0, 0x38400);
static void clearScreens(void){
memset32(fb->top_left, 0, 0x46500);
memset32(fb->top_right, 0, 0x46500);
memset32(fb->bottom, 0, 0x38400);
}
void loadSplash(void){
//Check if it's a no-screen-init A9LH boot via PDN_GPU_CNT
if(*(u8 *)0x10141200 == 0x1) return;
clearScreen();
if(!fileRead(fb->top_left, "/rei/splash.bin", 0x46500)) return;
u64 i = 0xFFFFFF; while(--i) __asm("mov r0, r0"); //Less Ghetto sleep func
clearScreens();
//Don't delay boot if no splash image is on the SD
if(fileRead(fb->top_left, "/aurei/splash.bin", 0x46500) +
fileRead(fb->bottom, "/aurei/splashbottom.bin", 0x38400)){
u64 i = 0x1300000; while(--i) __asm("mov r0, r0"); //Less Ghetto sleep func
}
}

View File

@@ -4,18 +4,9 @@
* Copyright (c) 2015 All Rights Reserved
*/
#ifndef DRAW_INC
#define DRAW_INC
#pragma once
#include "types.h"
struct fb {
u8 *top_left;
u8 *top_right;
u8 *bottom;
};
void loadSplash(void);
void shutdownLCD(void);
#endif
void __attribute__((naked)) shutdownLCD(void);

View File

@@ -8,14 +8,24 @@
#include "memory.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;
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){
*off = 0;
*head = nandSize;
*off = nandOffset;
*head = nandOffset + nandSize;
}
//Fallback to the first emuNAND if there's no second one
else if(emuNAND == 2) getEmunandSect(off, head, 1);
//Check if a RedNAND is present
else if(sdmmc_sdcard_readsectors(1, 1, temp) == 0){
if(*(u32 *)(temp + 0x100) != NCSD_MAGIC)
*head = 0;
}
}
}
@@ -52,4 +62,12 @@ void getMPU(void *pos, u32 *off, u32 size){
const unsigned char pattern[] = {0x03, 0x00, 0x24, 0x00};
*off = (u32)memsearch(pos, pattern, size, 4);
}
void getEmuCode(void *pos, u32 *off, u32 size){
u8 *proc9 = (u8 *)memsearch(pos, "ess9", size, 4);
const unsigned char pattern[] = {0x00, 0xFF, 0xFF, 0xFF};
//Looking for the last spot before Process9
*off = (u32)memsearch(pos, pattern, size - (size - (u32)(proc9 - (u8 *)pos)), 4) + 0xD;
}

View File

@@ -4,16 +4,14 @@
* Copyright (c) 2015 All Rights Reserved
*/
#ifndef EMUNAND_INC
#define EMUNAND_INC
#pragma once
#include "types.h"
#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);
void getEmuRW(void *pos, u32 size, u32 *readOff, u32 *writeOff);
void getMPU(void *pos, u32 *off, u32 size);
#endif
void getEmuCode(void *pos, u32 *off, u32 size);

View File

@@ -69,7 +69,7 @@ DRESULT disk_read (
DRESULT disk_write (
__attribute__((unused))
BYTE pdrv, /* Physical drive nmuber to identify the drive */
const BYTE *buff, /* Data to be written */
const BYTE *buff, /* Data to be written */
DWORD sector, /* Sector address in LBA */
UINT count /* Number of sectors to write */
)

View File

@@ -811,7 +811,7 @@ FRESULT sync_fs ( /* FR_OK: successful, FR_DISK_ERR: failed */
/*-----------------------------------------------------------------------*/
/* 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 */
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 */
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 */
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 */
#if !_FS_READONLY
FRESULT put_fat (
static FRESULT put_fat (
FATFS* fs, /* File system object */
DWORD clst, /* FAT index number (cluster number) to be changed */
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
int pick_lfn ( /* 1:Succeeded, 0:Buffer overflow */
WCHAR* lfnbuf, /* Pointer to the Unicode-LFN buffer */
@@ -1345,6 +1345,7 @@ int pick_lfn ( /* 1:Succeeded, 0:Buffer overflow */
return 1;
}
#endif
#if !_FS_READONLY
@@ -1385,7 +1386,7 @@ void fit_lfn (
/*-----------------------------------------------------------------------*/
/* Create numbered name */
/*-----------------------------------------------------------------------*/
#if _USE_LFN
#if _USE_LFN && !_FS_READONLY
static
void gen_numname (
BYTE* dst, /* Pointer to the buffer to store numbered SFN */

View File

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

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
#include <stdint.h>
#include <stddef.h>
#include <stdbool.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
#include "../../types.h"

View File

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

View File

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

View File

@@ -2,8 +2,6 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include "common.h"
#include "sdmmc.h"
#include "delay.h"
@@ -286,7 +284,7 @@ static void InitSD()
static int Nand_Init()
{
inittarget(&handleNAND);
waitcycles(0xF000);
ioDelay(0xF000);
sdmmc_send_command(&handleNAND,0,0);
@@ -337,7 +335,7 @@ static int SD_Init()
{
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 (!(*((vu16*)0x1000601c) & TMIO_STAT0_SIGSTATE)) return -1;

View File

@@ -124,5 +124,4 @@ u32 sdmmc_sdcard_writesectors(u32 sector_no, u32 numsectors, vu8 *in);
mmcdevice *getMMCDevice(int drive);
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

@@ -13,26 +13,26 @@
#include "draw.h"
#include "loader.h"
firmHeader *firmLocation = (firmHeader *)0x24000000;
firmSectionHeader *section;
u32 firmSize = 0,
mode = 1,
console = 1,
emuNAND = 0,
a9lhSetup = 0,
updatedSys = 0,
usePatchedFirm = 0;
u16 pressed;
char *firmPathPatched = NULL;
static firmHeader *const firmLocation = (firmHeader *)0x24000000;
static const firmSectionHeader *section;
static u32 firmSize = 0,
mode = 1,
console = 1,
emuNAND = 0,
a9lhSetup = 0,
updatedSys = 0,
usePatchedFirm = 0;
static u16 pressed;
static const char *firmPathPatched = NULL;
void setupCFW(void){
//Determine if booting with A9LH via PDN_SPI_CNT
u8 a9lhBoot = (*(u8 *)0x101401C0 == 0x0) ? 1 : 0;
//Retrieve the last booted FIRM via CFG_BOOTENV
u8 previousFirm = *(u8 *)0x10010000;
//Determine if booting with A9LH
u32 a9lhBoot = (PDN_SPI_CNT == 0x0) ? 1 : 0;
//Retrieve the last booted FIRM
u8 previousFirm = CFG_BOOTENV;
u32 overrideConfig = 0;
const char lastConfigPath[] = "rei/lastbootcfg";
const char lastConfigPath[] = "aurei/lastbootcfg";
//Detect the console being used
if(PDN_MPCORE_CFG == 1) console = 0;
@@ -41,10 +41,10 @@ void setupCFW(void){
pressed = HID_PAD;
//Determine if A9LH is installed
if(a9lhBoot || fileExists("/rei/installeda9lh")){
if(a9lhBoot || fileExists("/aurei/installeda9lh")){
a9lhSetup = 1;
//Check flag for > 9.2 SysNAND
if(fileExists("/rei/updatedsysnand")) updatedSys = 1;
if(fileExists("/aurei/updatedsysnand")) updatedSys = 1;
}
//If booting with A9LH and it's a MCU reboot, try to force boot options
@@ -53,11 +53,11 @@ void setupCFW(void){
fileRead(&tempConfig, lastConfigPath, 1);
//Always force a sysNAND boot when quitting AGB_FIRM
if(previousFirm == 0x7) {
if(previousFirm == 0x7){
if(!updatedSys) mode = tempConfig & 0x1;
overrideConfig = 1;
//Else, force the last used boot options unless A is pressed
} else if(!(pressed & BUTTON_A)) {
} else if(!(pressed & BUTTON_A)){
mode = tempConfig & 0x1;
emuNAND = (tempConfig >> 1) & 0x1;
overrideConfig = 1;
@@ -69,6 +69,9 @@ void setupCFW(void){
//If L and R are pressed, chainload an external payload
if(a9lhBoot && (pressed & BUTTON_L1R1) == BUTTON_L1R1) loadPayload();
//Check if it's a no-screen-init A9LH boot
if(PDN_GPU_CNT != 0x1) loadSplash();
/* If L is pressed, and on an updated SysNAND setup the SAFE MODE combo
is not pressed, boot 9.0 FIRM */
if((pressed & BUTTON_L1) && !(updatedSys && pressed == SAFEMODE)) mode = 0;
@@ -76,7 +79,11 @@ void setupCFW(void){
/* If L or R aren't pressed on a 9.0/9.2 SysNAND, or the 9.0 FIRM is selected
or R is pressed on a > 9.2 SysNAND, boot emuNAND */
if((updatedSys && (!mode || ((pressed & BUTTON_R1) && pressed != SAFEMODE))) ||
(!updatedSys && mode && !(pressed & BUTTON_R1))) emuNAND = 1;
(!updatedSys && mode && !(pressed & BUTTON_R1))){
//If not 9.0 FIRM and B is pressed, attempt booting the second emuNAND
if(mode && (pressed & BUTTON_B)) emuNAND = 2;
else emuNAND = 1;
}
//Write the current boot options on A9LH
if(a9lhBoot){
@@ -85,13 +92,14 @@ void setupCFW(void){
}
}
if(mode) firmPathPatched = emuNAND ? "/rei/patched_firmware_emu.bin" :
"/rei/patched_firmware_sys.bin";
if(mode) firmPathPatched = emuNAND ? (emuNAND == 1 ? "/aurei/patched_firmware_emu.bin" :
"/aurei/patched_firmware_em2.bin") :
"/aurei/patched_firmware_sys.bin";
//Skip decrypting and patching FIRM
if(fileExists("/rei/usepatchedfw")){
if(fileExists("/aurei/usepatchedfw")){
//Only needed with this flag
if(!mode) firmPathPatched = "/rei/patched_firmware90.bin";
if(!mode) firmPathPatched = "/aurei/patched_firmware90.bin";
if(fileExists(firmPathPatched)) usePatchedFirm = 1;
}
}
@@ -110,7 +118,7 @@ u32 loadFirm(void){
//Load FIRM from SD
else{
const char *path = usePatchedFirm ? firmPathPatched :
(mode ? "/rei/firmware.bin" : "/rei/firmware90.bin");
(mode ? "/aurei/firmware.bin" : "/aurei/firmware90.bin");
firmSize = fileSize(path);
if(!firmSize) return 0;
fileRead((u8 *)firmLocation, path, firmSize);
@@ -128,24 +136,21 @@ u32 loadFirm(void){
}
//Nand redirection
u32 loadEmu(void){
static u32 loadEmu(void){
u32 emuOffset = 0,
emuHeader = 0,
emuRead = 0,
emuWrite = 0,
sdmmcOffset = 0,
mpuOffset = 0,
emuCodeOffset = 0;
u32 emuOffset = 1,
emuHeader = 1,
emuRead,
emuWrite,
sdmmcOffset,
mpuOffset,
emuCodeOffset;
//Read emunand code from SD
const char path[] = "/rei/emunand/emunand.bin";
const char path[] = "/aurei/emunand/emunand.bin";
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;
getEmuCode(firmLocation, &emuCodeOffset, firmSize);
fileRead((u8 *)emuCodeOffset, path, size);
//Find and patch emunand related offsets
@@ -153,18 +158,19 @@ u32 loadEmu(void){
u32 *pos_offset = (u32 *)memsearch((void *)emuCodeOffset, "NAND", size, 4);
u32 *pos_header = (u32 *)memsearch((void *)emuCodeOffset, "NCSD", size, 4);
getSDMMC(firmLocation, &sdmmcOffset, firmSize);
getEmunandSect(&emuOffset, &emuHeader);
getEmunandSect(&emuOffset, &emuHeader, emuNAND);
getEmuRW(firmLocation, firmSize, &emuRead, &emuWrite);
getMPU(firmLocation, &mpuOffset, firmSize);
*pos_sdmmc = sdmmcOffset;
*pos_offset = emuOffset;
*pos_header = emuHeader;
//Patch emuNAND code in memory for O3DS and 9.0 N3DS
if(!console || !mode){
void *pos_instr = memsearch((void *)emuCodeOffset, "\xA6\x01\x08\x30", size, 4);
memcpy(pos_instr, emuInstr, sizeof(emuInstr));
}
//No emuNAND detected
if(!*pos_header) return 0;
//Calculate offset for the hooks
*(u32 *)(nandRedir + 4) = emuCodeOffset - (u32)firmLocation -
section[2].offset + (u32)section[2].address;
//Add emunand hooks
memcpy((void *)emuRead, nandRedir, sizeof(nandRedir));
@@ -194,26 +200,24 @@ u32 patchFirm(void){
}
//Disable signature checks
u32 sigOffset = 0,
sigOffset2 = 0;
u32 sigOffset,
sigOffset2;
getSignatures(firmLocation, firmSize, &sigOffset, &sigOffset2);
memcpy((void *)sigOffset, sigPat1, sizeof(sigPat1));
memcpy((void *)sigOffset2, sigPat2, sizeof(sigPat2));
//Patch ARM9 entrypoint on N3DS to skip arm9loader
if(console){
u32 *arm9 = (u32 *)&firmLocation->arm9Entry;
*arm9 = 0x801B01C;
}
if(console)
firmLocation->arm9Entry = (u8 *)0x801B01C;
//Patch FIRM reboots, not on 9.0 FIRM as it breaks firmlaunchhax
if(mode){
u32 rebootOffset = 0,
fOpenOffset = 0;
u32 rebootOffset,
fOpenOffset;
//Read reboot code from SD
const char path[] = "/rei/reboot/reboot.bin";
const char path[] = "/aurei/reboot/reboot.bin";
u32 size = fileSize(path);
if(!size) return 0;
getReboot(firmLocation, firmSize, &rebootOffset);
@@ -227,7 +231,8 @@ u32 patchFirm(void){
//Patch path for emuNAND-patched FIRM
if(emuNAND){
void *pos_path = memsearch((void *)rebootOffset, L"sy", size, 4);
memcpy(pos_path, L"emu", 5);
const wchar_t *path = emuNAND == 1 ? L"emu" : L"em2";
memcpy(pos_path, path, 5);
}
}
@@ -248,13 +253,13 @@ void launchFirm(void){
memcpy(section[2].address, (u8 *)firmLocation + section[2].offset, section[2].size);
//Run ARM11 screen stuff
vu32 *arm11 = (vu32 *)0x1FFFFFF8;
vu32 *const arm11 = (u32 *)0x1FFFFFF8;
*arm11 = (u32)shutdownLCD;
while(*arm11);
//Set ARM11 kernel
*arm11 = (u32)firmLocation->arm11Entry;
//Final jump to arm9 binary
((void (*)())firmLocation->arm9Entry)();
}

View File

@@ -4,22 +4,41 @@
* Copyright (c) 2015 All Rights Reserved
*/
#ifndef FIRM_INC
#define FIRM_INC
#pragma once
#include "types.h"
#define PDN_MPCORE_CFG (*(u8*)0x10140FFC)
#define HID_PAD ((~*(u16*)0x10146000) & 0xFFF)
#define PDN_MPCORE_CFG (*(vu8 *)0x10140FFC)
#define HID_PAD ((~*(vu16 *)0x10146000) & 0xFFF)
#define PDN_SPI_CNT (*(vu8 *)0x101401C0)
#define CFG_BOOTENV (*(vu8 *)0x10010000)
#define PDN_GPU_CNT (*(vu8 *)0x10141200)
#define BUTTON_R1 (1 << 8)
#define BUTTON_L1 (1 << 9)
#define BUTTON_L1R1 (BUTTON_R1 | BUTTON_L1)
#define BUTTON_A 1
#define BUTTON_B (1 << 1)
#define SAFEMODE (BUTTON_L1R1 | BUTTON_A | (1 << 6))
//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;
void setupCFW(void);
u32 loadFirm(void);
u32 patchFirm(void);
void launchFirm(void);
#endif
void launchFirm(void);

View File

@@ -52,7 +52,7 @@ u32 fileSize(const char *path){
u32 fileExists(const char *path){
FIL fp;
u8 exists = 0;
u32 exists = 0;
if(f_open(&fp, path, FA_READ) == FR_OK) exists = 1;

View File

@@ -2,8 +2,7 @@
* fs.h
*/
#ifndef FS_INC
#define FS_INC
#pragma once
#include "types.h"
@@ -11,6 +10,4 @@ u32 mountSD(void);
u32 fileRead(u8 *dest, const char *path, u32 size);
u32 fileWrite(const u8 *buffer, const char *path, u32 size);
u32 fileSize(const char *path);
u32 fileExists(const char *path);
#endif
u32 fileExists(const char *path);

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

@@ -8,7 +8,7 @@
#define PAYLOAD_ADDRESS 0x24F00000
void loadPayload(void){
if(fileExists("rei/arm9payload.bin") &&
fileRead((u8 *)PAYLOAD_ADDRESS, "rei/loader.bin", 0))
if(fileExists("aurei/payloads/default.bin") &&
fileRead((u8 *)PAYLOAD_ADDRESS, "aurei/loader.bin", 0))
((void (*)())PAYLOAD_ADDRESS)();
}

View File

@@ -2,11 +2,8 @@
* loader.h
*/
#ifndef LOADER_INC
#define LOADER_INC
#pragma once
#include "types.h"
void loadPayload(void);
#endif
void loadPayload(void);

View File

@@ -8,16 +8,16 @@
#include "fs.h"
#include "firm.h"
#include "draw.h"
#include "i2c.h"
void main(){
void main(void){
mountSD();
setupCFW();
}
void startCFW(){
loadSplash();
if(!loadFirm()) return;
if(!patchFirm()) return;
launchFirm();
}
void shutdown(void){
i2cWriteRegister(I2C_DEV_MCU, 0x20, 1);
}

View File

@@ -19,6 +19,12 @@ void memset(void *dest, int filler, u32 size){
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){
const u8 *buf1c = (const u8 *)buf1;
const u8 *buf2c = (const u8 *)buf2;

View File

@@ -4,14 +4,12 @@
* Copyright (c) 2015 All Rights Reserved
*/
#ifndef MEMORY_INC
#define MEMORY_INC
#pragma once
#include "types.h"
void memcpy(void *dest, const void *src, 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);
void *memsearch(void *start_pos, const void *search, u32 size, u32 size_search);
#endif
void *memsearch(void *start_pos, const void *search, u32 size, u32 size_search);

View File

@@ -17,7 +17,8 @@ const u8 mpu[0x2C] = { //MPU shit
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 sigPat2[4] = {0x00, 0x20, 0x70, 0x47};

View File

@@ -4,8 +4,7 @@
* Copyright (c) 2015 All Rights Reserved
*/
#ifndef PATCHES_INC
#define PATCHES_INC
#pragma once
#include "types.h"
@@ -25,6 +24,4 @@ const u8 emuInstr[5];
void getSignatures(void *pos, u32 size, u32 *off, u32 *off2);
void getReboot(void *pos, u32 size, u32 *off);
void getfOpen(void *pos, u32 size, u32 *off);
void getFIRMWrite(void *pos, u32 size, u32 *off);
#endif
void getFIRMWrite(void *pos, u32 size, u32 *off);

View File

@@ -10,7 +10,7 @@ _start:
mcr p15, 0, r0, c5, c0, 2 @ write data 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 r1, =0x01FF801D @ 01ff8000 32k
ldr r2, =0x08000027 @ 08000000 1M
@@ -27,6 +27,10 @@ _start:
mcr p15, 0, r5, c6, c5, 0
mcr p15, 0, r6, c6, c6, 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
mrc p15, 0, r0, c1, c0, 0 @ read control register
@@ -48,15 +52,7 @@ _start:
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
bl shutdown
.die:
b .die

View File

@@ -4,8 +4,7 @@
* Copyright (c) 2015 All Rights Reserved
*/
#ifndef TYPES_INC
#define TYPES_INC
#pragma once
#include <stdint.h>
#include <stdlib.h>
@@ -15,27 +14,7 @@ typedef uint8_t u8;
typedef uint16_t u16;
typedef uint32_t u32;
typedef uint64_t u64;
typedef volatile uint8_t vu8;
typedef volatile uint16_t vu16;
typedef volatile uint32_t vu32;
typedef volatile uint64_t 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
typedef volatile u8 vu8;
typedef volatile u16 vu16;
typedef volatile u32 vu32;
typedef volatile u64 vu64;