Compare commits
19 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a437e533f5 | ||
|
|
6b88953517 | ||
|
|
9b9f784c26 | ||
|
|
6dfb33191f | ||
|
|
078fce4b3d | ||
|
|
dcb09a9472 | ||
|
|
8ce395caa5 | ||
|
|
e9410c86b1 | ||
|
|
42885560ed | ||
|
|
796e4dd060 | ||
|
|
9468582d83 | ||
|
|
6707a36ffe | ||
|
|
09cc7c903c | ||
|
|
9be7481c14 | ||
|
|
9f68ce0d70 | ||
|
|
4748c0292c | ||
|
|
c3ebce1666 | ||
|
|
b1a428f6bc | ||
|
|
3e0b928db0 |
33
Makefile
33
Makefile
@@ -12,7 +12,7 @@ ifneq ($(PYTHON_VER_MAJOR), 3)
|
|||||||
PYTHON3 := py -3
|
PYTHON3 := py -3
|
||||||
endif
|
endif
|
||||||
|
|
||||||
name := ReiNand
|
name := AuReiNand
|
||||||
|
|
||||||
dir_source := source
|
dir_source := source
|
||||||
dir_data := data
|
dir_data := data
|
||||||
@@ -26,7 +26,7 @@ dir_loader := loader
|
|||||||
|
|
||||||
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, \
|
||||||
@@ -43,28 +43,29 @@ launcher: $(dir_out)/$(name).dat
|
|||||||
a9lh: $(dir_out)/arm9loaderhax.bin
|
a9lh: $(dir_out)/arm9loaderhax.bin
|
||||||
|
|
||||||
.PHONY: emunand
|
.PHONY: emunand
|
||||||
emunand: $(dir_out)/rei/emunand/emunand.bin
|
emunand: $(dir_out)/aurei/emunand/emunand.bin
|
||||||
|
|
||||||
.PHONY: reboot
|
.PHONY: reboot
|
||||||
reboot: $(dir_out)/rei/reboot/reboot.bin
|
reboot: $(dir_out)/aurei/reboot/reboot.bin
|
||||||
|
|
||||||
.PHONY: ninjhax
|
.PHONY: ninjhax
|
||||||
ninjhax: $(dir_out)/3ds/$(name)
|
ninjhax: $(dir_out)/3ds/$(name)
|
||||||
|
|
||||||
.PHONY: loader
|
.PHONY: loader
|
||||||
loader: $(dir_out)/rei/loader.bin
|
loader: $(dir_out)/aurei/loader.bin
|
||||||
|
|
||||||
.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)/$(name).dat: $(dir_build)/main.bin $(dir_out)/aurei
|
||||||
@$(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)/aurei
|
||||||
@cp -av $(dir_build)/main.bin $@
|
@cp -av $(dir_build)/main.bin $@
|
||||||
|
|
||||||
$(dir_out)/3ds/$(name):
|
$(dir_out)/3ds/$(name):
|
||||||
@@ -73,21 +74,21 @@ $(dir_out)/3ds/$(name):
|
|||||||
@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)/aurei:
|
||||||
@mkdir -p "$(dir_out)/rei"
|
@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 $<
|
@armips $<
|
||||||
@mkdir -p "$(dir_out)/rei/emunand"
|
@mkdir -p "$(dir_out)/aurei/emunand"
|
||||||
@mv emunand.bin $@
|
@mv emunand.bin $@
|
||||||
|
|
||||||
$(dir_out)/rei/reboot/reboot.bin: $(dir_reboot)/rebootCode.s
|
$(dir_out)/aurei/reboot/reboot.bin: $(dir_reboot)/rebootCode.s
|
||||||
@armips $<
|
@armips $<
|
||||||
@mkdir -p "$(dir_out)/rei/reboot"
|
@mkdir -p "$(dir_out)/aurei/reboot"
|
||||||
@mv reboot.bin $@
|
@mv reboot.bin $@
|
||||||
|
|
||||||
$(dir_out)/rei/loader.bin: $(dir_out)/rei $(dir_loader)/Makefile
|
$(dir_out)/aurei/loader.bin: $(dir_out)/aurei $(dir_loader)/Makefile
|
||||||
@cd $(dir_loader) && make
|
@$(MAKE) -C $(dir_loader)
|
||||||
@mv $(dir_loader)/loader.bin $@
|
@mv $(dir_loader)/loader.bin $@
|
||||||
|
|
||||||
$(dir_build)/main.bin: $(dir_build)/main.elf
|
$(dir_build)/main.bin: $(dir_build)/main.elf
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
BIN
icon.png
BIN
icon.png
Binary file not shown.
|
Before Width: | Height: | Size: 6.1 KiB After Width: | Height: | Size: 3.1 KiB |
@@ -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
14
loader/source/buttons.h
Normal 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)
|
||||||
@@ -69,7 +69,7 @@ DRESULT disk_read (
|
|||||||
DRESULT disk_write (
|
DRESULT disk_write (
|
||||||
__attribute__((unused))
|
__attribute__((unused))
|
||||||
BYTE pdrv, /* Physical drive nmuber to identify the drive */
|
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 */
|
DWORD sector, /* Sector address in LBA */
|
||||||
UINT count /* Number of sectors to write */
|
UINT count /* Number of sectors to write */
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -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 */
|
||||||
|
|||||||
@@ -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
|
|
||||||
@@ -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
|
|
||||||
@@ -6,4 +6,4 @@
|
|||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
void waitcycles(u32 us);
|
void ioDelay(u32 us);
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
98
loader/source/i2c.c
Normal file
98
loader/source/i2c.c
Normal 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
18
loader/source/i2c.h
Normal 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);
|
||||||
@@ -1,19 +1,43 @@
|
|||||||
|
#include "types.h"
|
||||||
|
#include "buttons.h"
|
||||||
|
#include "screeninit.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")){
|
||||||
|
//Determine if screen was already inited
|
||||||
|
if(*(vu8 *)0x10141200 == 0x1) initLCD();
|
||||||
|
((void (*)())PAYLOAD_ADDRESS)();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
111
loader/source/screeninit.c
Normal file
111
loader/source/screeninit.c
Normal 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);
|
||||||
|
}
|
||||||
5
loader/source/screeninit.h
Normal file
5
loader/source/screeninit.h
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "types.h"
|
||||||
|
|
||||||
|
void initLCD(void);
|
||||||
@@ -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
20
loader/source/types.h
Normal 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;
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -54,10 +54,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 +67,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 +76,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 +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;
|
int i;
|
||||||
if(mode & AES_INPUT_BE)
|
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;
|
u32 *ctr32 = (u32 *)ctr;
|
||||||
int i;
|
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_AESBLKCNT = blockCount << 16;
|
||||||
*REG_AESCNT |= AES_CNT_START;
|
*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 |
|
*REG_AESCNT = mode |
|
||||||
AES_CNT_INPUT_ORDER | AES_CNT_OUTPUT_ORDER |
|
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)
|
//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--);
|
||||||
|
|||||||
@@ -1,56 +1,53 @@
|
|||||||
// From http://github.com/b1l1s/ctr
|
// From http://github.com/b1l1s/ctr
|
||||||
|
|
||||||
#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)
|
||||||
#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_DECRYPT_MODE (4u << 27)
|
||||||
#define AES_CBC_ENCRYPT_MODE (5u << 27)
|
#define AES_CBC_ENCRYPT_MODE (5u << 27)
|
||||||
#define AES_ECB_DECRYPT_MODE (6u << 27)
|
#define AES_ECB_DECRYPT_MODE (6u << 27)
|
||||||
#define AES_ECB_ENCRYPT_MODE (7u << 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_START 0x80000000
|
||||||
#define AES_CNT_INPUT_ORDER 0x02000000
|
#define AES_CNT_INPUT_ORDER 0x02000000
|
||||||
#define AES_CNT_OUTPUT_ORDER 0x01000000
|
#define AES_CNT_OUTPUT_ORDER 0x01000000
|
||||||
#define AES_CNT_INPUT_ENDIAN 0x00800000
|
#define AES_CNT_INPUT_ENDIAN 0x00800000
|
||||||
#define AES_CNT_OUTPUT_ENDIAN 0x00400000
|
#define AES_CNT_OUTPUT_ENDIAN 0x00400000
|
||||||
#define AES_CNT_FLUSH_READ 0x00000800
|
#define AES_CNT_FLUSH_READ 0x00000800
|
||||||
#define AES_CNT_FLUSH_WRITE 0x00000400
|
#define AES_CNT_FLUSH_WRITE 0x00000400
|
||||||
|
|
||||||
#define AES_INPUT_BE (AES_CNT_INPUT_ENDIAN)
|
#define AES_INPUT_BE (AES_CNT_INPUT_ENDIAN)
|
||||||
#define AES_INPUT_LE 0
|
#define AES_INPUT_LE 0
|
||||||
#define AES_INPUT_NORMAL (AES_CNT_INPUT_ORDER)
|
#define AES_INPUT_NORMAL (AES_CNT_INPUT_ORDER)
|
||||||
#define AES_INPUT_REVERSED 0
|
#define AES_INPUT_REVERSED 0
|
||||||
|
|
||||||
#define AES_BLOCK_SIZE 0x10
|
#define AES_BLOCK_SIZE 0x10
|
||||||
|
|
||||||
#define AES_KEYCNT_WRITE (1 << 0x7)
|
#define AES_KEYCNT_WRITE (1 << 0x7)
|
||||||
#define AES_KEYNORMAL 0
|
#define AES_KEYNORMAL 0
|
||||||
#define AES_KEYX 1
|
#define AES_KEYX 1
|
||||||
#define AES_KEYY 2
|
#define AES_KEYY 2
|
||||||
|
|
||||||
//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 decArm9Bin(u8 *armHdr, u32 mode);
|
||||||
void setKeyXs(u8 *armHdr);
|
void setKeyXs(u8 *armHdr);
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -8,36 +8,41 @@
|
|||||||
#include "fs.h"
|
#include "fs.h"
|
||||||
#include "memory.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
|
//Clear ARM11 entry offset
|
||||||
*arm11 = 0;
|
*arm11 = 0;
|
||||||
|
|
||||||
//Shutdown LCDs
|
//Shutdown LCDs
|
||||||
*(vu32*)0x10202A44 = 0;
|
*(vu32 *)0x10202A44 = 0;
|
||||||
*(vu32*)0x10202244 = 0;
|
*(vu32 *)0x10202244 = 0;
|
||||||
*(vu32*)0x10202014 = 0;
|
*(vu32 *)0x10202014 = 0;
|
||||||
|
|
||||||
//Wait for the ARM11 entrypoint to be set
|
//Wait for the entry to be set
|
||||||
while(!*arm11);
|
while(!*arm11);
|
||||||
//Jump to it
|
//Jump to it
|
||||||
((void (*)())*arm11)();
|
((void (*)())*arm11)();
|
||||||
}
|
}
|
||||||
|
|
||||||
void clearScreen(void){
|
static 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;
|
//Don't delay boot if no splash image is on the SD
|
||||||
clearScreen();
|
if(fileRead(fb->top_left, "/aurei/splash.bin", 0x46500) +
|
||||||
if(!fileRead(fb->top_left, "/rei/splash.bin", 0x46500)) return;
|
fileRead(fb->bottom, "/aurei/splashbottom.bin", 0x38400)){
|
||||||
u64 i = 0xFFFFFF; while(--i) __asm("mov r0, r0"); //Less Ghetto sleep func
|
u64 i = 0x1300000; while(--i) __asm("mov r0, r0"); //Less Ghetto sleep func
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -4,18 +4,9 @@
|
|||||||
* Copyright (c) 2015 All Rights Reserved
|
* Copyright (c) 2015 All Rights Reserved
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef DRAW_INC
|
#pragma once
|
||||||
#define DRAW_INC
|
|
||||||
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
struct fb {
|
|
||||||
u8 *top_left;
|
|
||||||
u8 *top_right;
|
|
||||||
u8 *bottom;
|
|
||||||
};
|
|
||||||
|
|
||||||
void loadSplash(void);
|
void loadSplash(void);
|
||||||
void shutdownLCD(void);
|
void __attribute__((naked)) shutdownLCD(void);
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -8,14 +8,24 @@
|
|||||||
#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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -53,3 +63,11 @@ void getMPU(void *pos, u32 *off, u32 size){
|
|||||||
|
|
||||||
*off = (u32)memsearch(pos, pattern, size, 4);
|
*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;
|
||||||
|
}
|
||||||
@@ -4,16 +4,14 @@
|
|||||||
* Copyright (c) 2015 All Rights Reserved
|
* Copyright (c) 2015 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);
|
void getSDMMC(void *pos, u32 *off, 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 *off, u32 size);
|
||||||
|
void getEmuCode(void *pos, u32 *off, u32 size);
|
||||||
#endif
|
|
||||||
@@ -69,7 +69,7 @@ DRESULT disk_read (
|
|||||||
DRESULT disk_write (
|
DRESULT disk_write (
|
||||||
__attribute__((unused))
|
__attribute__((unused))
|
||||||
BYTE pdrv, /* Physical drive nmuber to identify the drive */
|
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 */
|
DWORD sector, /* Sector address in LBA */
|
||||||
UINT count /* Number of sectors to write */
|
UINT count /* Number of sectors to write */
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -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 */
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
/ and optional writing functions as well. */
|
/ 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.
|
/* This option defines minimization level to remove some basic API functions.
|
||||||
/
|
/
|
||||||
/ 0: All basic functions are enabled.
|
/ 0: All basic functions are enabled.
|
||||||
|
|||||||
@@ -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
|
|
||||||
@@ -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
|
|
||||||
@@ -6,4 +6,4 @@
|
|||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
void waitcycles(u32 us);
|
void ioDelay(u32 us);
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
117
source/firm.c
117
source/firm.c
@@ -13,26 +13,26 @@
|
|||||||
#include "draw.h"
|
#include "draw.h"
|
||||||
#include "loader.h"
|
#include "loader.h"
|
||||||
|
|
||||||
firmHeader *firmLocation = (firmHeader *)0x24000000;
|
static firmHeader *const firmLocation = (firmHeader *)0x24000000;
|
||||||
firmSectionHeader *section;
|
static const firmSectionHeader *section;
|
||||||
u32 firmSize = 0,
|
static u32 firmSize = 0,
|
||||||
mode = 1,
|
mode = 1,
|
||||||
console = 1,
|
console = 1,
|
||||||
emuNAND = 0,
|
emuNAND = 0,
|
||||||
a9lhSetup = 0,
|
a9lhSetup = 0,
|
||||||
updatedSys = 0,
|
updatedSys = 0,
|
||||||
usePatchedFirm = 0;
|
usePatchedFirm = 0;
|
||||||
u16 pressed;
|
static u16 pressed;
|
||||||
char *firmPathPatched = NULL;
|
static const 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;
|
u32 overrideConfig = 0;
|
||||||
const char lastConfigPath[] = "rei/lastbootcfg";
|
const char lastConfigPath[] = "aurei/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;
|
||||||
@@ -41,10 +41,10 @@ void setupCFW(void){
|
|||||||
pressed = HID_PAD;
|
pressed = HID_PAD;
|
||||||
|
|
||||||
//Determine if A9LH is installed
|
//Determine if A9LH is installed
|
||||||
if(a9lhBoot || fileExists("/rei/installeda9lh")){
|
if(a9lhBoot || fileExists("/aurei/installeda9lh")){
|
||||||
a9lhSetup = 1;
|
a9lhSetup = 1;
|
||||||
//Check flag for > 9.2 SysNAND
|
//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
|
//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);
|
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 = tempConfig & 0x1;
|
||||||
overrideConfig = 1;
|
overrideConfig = 1;
|
||||||
//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 = tempConfig & 0x1;
|
||||||
emuNAND = (tempConfig >> 1) & 0x1;
|
emuNAND = (tempConfig >> 1) & 0x1;
|
||||||
overrideConfig = 1;
|
overrideConfig = 1;
|
||||||
@@ -69,6 +69,9 @@ void setupCFW(void){
|
|||||||
//If L and R are pressed, chainload an external payload
|
//If L and R are pressed, chainload an external payload
|
||||||
if(a9lhBoot && (pressed & BUTTON_L1R1) == BUTTON_L1R1) loadPayload();
|
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
|
/* If L is pressed, and on an updated SysNAND setup the SAFE MODE combo
|
||||||
is not pressed, boot 9.0 FIRM */
|
is not pressed, boot 9.0 FIRM */
|
||||||
if((pressed & BUTTON_L1) && !(updatedSys && pressed == SAFEMODE)) mode = 0;
|
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
|
/* 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 */
|
or R is pressed on a > 9.2 SysNAND, boot emuNAND */
|
||||||
if((updatedSys && (!mode || ((pressed & BUTTON_R1) && pressed != SAFEMODE))) ||
|
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
|
//Write the current boot options on A9LH
|
||||||
if(a9lhBoot){
|
if(a9lhBoot){
|
||||||
@@ -85,13 +92,14 @@ void setupCFW(void){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(mode) firmPathPatched = emuNAND ? "/rei/patched_firmware_emu.bin" :
|
if(mode) firmPathPatched = emuNAND ? (emuNAND == 1 ? "/aurei/patched_firmware_emu.bin" :
|
||||||
"/rei/patched_firmware_sys.bin";
|
"/aurei/patched_firmware_em2.bin") :
|
||||||
|
"/aurei/patched_firmware_sys.bin";
|
||||||
|
|
||||||
//Skip decrypting and patching FIRM
|
//Skip decrypting and patching FIRM
|
||||||
if(fileExists("/rei/usepatchedfw")){
|
if(fileExists("/aurei/usepatchedfw")){
|
||||||
//Only needed with this flag
|
//Only needed with this flag
|
||||||
if(!mode) firmPathPatched = "/rei/patched_firmware90.bin";
|
if(!mode) firmPathPatched = "/aurei/patched_firmware90.bin";
|
||||||
if(fileExists(firmPathPatched)) usePatchedFirm = 1;
|
if(fileExists(firmPathPatched)) usePatchedFirm = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -110,7 +118,7 @@ u32 loadFirm(void){
|
|||||||
//Load FIRM from SD
|
//Load FIRM from SD
|
||||||
else{
|
else{
|
||||||
const char *path = usePatchedFirm ? firmPathPatched :
|
const char *path = usePatchedFirm ? firmPathPatched :
|
||||||
(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) return 0;
|
||||||
fileRead((u8 *)firmLocation, path, firmSize);
|
fileRead((u8 *)firmLocation, path, firmSize);
|
||||||
@@ -128,24 +136,21 @@ u32 loadFirm(void){
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Nand redirection
|
//Nand redirection
|
||||||
u32 loadEmu(void){
|
static u32 loadEmu(void){
|
||||||
|
|
||||||
u32 emuOffset = 0,
|
u32 emuOffset = 1,
|
||||||
emuHeader = 0,
|
emuHeader = 1,
|
||||||
emuRead = 0,
|
emuRead,
|
||||||
emuWrite = 0,
|
emuWrite,
|
||||||
sdmmcOffset = 0,
|
sdmmcOffset,
|
||||||
mpuOffset = 0,
|
mpuOffset,
|
||||||
emuCodeOffset = 0;
|
emuCodeOffset;
|
||||||
|
|
||||||
//Read emunand code from SD
|
//Read emunand code from SD
|
||||||
const char path[] = "/rei/emunand/emunand.bin";
|
const char path[] = "/aurei/emunand/emunand.bin";
|
||||||
u32 size = fileSize(path);
|
u32 size = fileSize(path);
|
||||||
if(!size) return 0;
|
if(!size) return 0;
|
||||||
if(!console || !mode) nandRedir[5] = 0xA4;
|
getEmuCode(firmLocation, &emuCodeOffset, firmSize);
|
||||||
//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);
|
fileRead((u8 *)emuCodeOffset, path, size);
|
||||||
|
|
||||||
//Find and patch emunand related offsets
|
//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_offset = (u32 *)memsearch((void *)emuCodeOffset, "NAND", size, 4);
|
||||||
u32 *pos_header = (u32 *)memsearch((void *)emuCodeOffset, "NCSD", size, 4);
|
u32 *pos_header = (u32 *)memsearch((void *)emuCodeOffset, "NCSD", size, 4);
|
||||||
getSDMMC(firmLocation, &sdmmcOffset, firmSize);
|
getSDMMC(firmLocation, &sdmmcOffset, firmSize);
|
||||||
getEmunandSect(&emuOffset, &emuHeader);
|
getEmunandSect(&emuOffset, &emuHeader, emuNAND);
|
||||||
getEmuRW(firmLocation, firmSize, &emuRead, &emuWrite);
|
getEmuRW(firmLocation, firmSize, &emuRead, &emuWrite);
|
||||||
getMPU(firmLocation, &mpuOffset, firmSize);
|
getMPU(firmLocation, &mpuOffset, firmSize);
|
||||||
*pos_sdmmc = sdmmcOffset;
|
*pos_sdmmc = sdmmcOffset;
|
||||||
*pos_offset = emuOffset;
|
*pos_offset = emuOffset;
|
||||||
*pos_header = emuHeader;
|
*pos_header = emuHeader;
|
||||||
|
|
||||||
//Patch emuNAND code in memory for O3DS and 9.0 N3DS
|
//No emuNAND detected
|
||||||
if(!console || !mode){
|
if(!*pos_header) return 0;
|
||||||
void *pos_instr = memsearch((void *)emuCodeOffset, "\xA6\x01\x08\x30", size, 4);
|
|
||||||
memcpy(pos_instr, emuInstr, sizeof(emuInstr));
|
//Calculate offset for the hooks
|
||||||
}
|
*(u32 *)(nandRedir + 4) = emuCodeOffset - (u32)firmLocation -
|
||||||
|
section[2].offset + (u32)section[2].address;
|
||||||
|
|
||||||
//Add emunand hooks
|
//Add emunand hooks
|
||||||
memcpy((void *)emuRead, nandRedir, sizeof(nandRedir));
|
memcpy((void *)emuRead, nandRedir, sizeof(nandRedir));
|
||||||
@@ -194,26 +200,24 @@ u32 patchFirm(void){
|
|||||||
}
|
}
|
||||||
|
|
||||||
//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
|
//Patch FIRM reboots, not on 9.0 FIRM as it breaks firmlaunchhax
|
||||||
if(mode){
|
if(mode){
|
||||||
u32 rebootOffset = 0,
|
u32 rebootOffset,
|
||||||
fOpenOffset = 0;
|
fOpenOffset;
|
||||||
|
|
||||||
//Read reboot code from SD
|
//Read reboot code from SD
|
||||||
const char path[] = "/rei/reboot/reboot.bin";
|
const char path[] = "/aurei/reboot/reboot.bin";
|
||||||
u32 size = fileSize(path);
|
u32 size = fileSize(path);
|
||||||
if(!size) return 0;
|
if(!size) return 0;
|
||||||
getReboot(firmLocation, firmSize, &rebootOffset);
|
getReboot(firmLocation, firmSize, &rebootOffset);
|
||||||
@@ -227,7 +231,8 @@ u32 patchFirm(void){
|
|||||||
//Patch path for emuNAND-patched FIRM
|
//Patch path for emuNAND-patched FIRM
|
||||||
if(emuNAND){
|
if(emuNAND){
|
||||||
void *pos_path = memsearch((void *)rebootOffset, L"sy", size, 4);
|
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,7 +253,7 @@ void launchFirm(void){
|
|||||||
memcpy(section[2].address, (u8 *)firmLocation + section[2].offset, section[2].size);
|
memcpy(section[2].address, (u8 *)firmLocation + section[2].offset, section[2].size);
|
||||||
|
|
||||||
//Run ARM11 screen stuff
|
//Run ARM11 screen stuff
|
||||||
vu32 *arm11 = (vu32 *)0x1FFFFFF8;
|
vu32 *const arm11 = (u32 *)0x1FFFFFF8;
|
||||||
*arm11 = (u32)shutdownLCD;
|
*arm11 = (u32)shutdownLCD;
|
||||||
while(*arm11);
|
while(*arm11);
|
||||||
|
|
||||||
|
|||||||
@@ -4,22 +4,41 @@
|
|||||||
* Copyright (c) 2015 All Rights Reserved
|
* Copyright (c) 2015 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 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_R1 (1 << 8)
|
||||||
#define BUTTON_L1 (1 << 9)
|
#define BUTTON_L1 (1 << 9)
|
||||||
#define BUTTON_L1R1 (BUTTON_R1 | BUTTON_L1)
|
#define BUTTON_L1R1 (BUTTON_R1 | BUTTON_L1)
|
||||||
#define BUTTON_A 1
|
#define BUTTON_A 1
|
||||||
|
#define BUTTON_B (1 << 1)
|
||||||
#define SAFEMODE (BUTTON_L1R1 | BUTTON_A | (1 << 6))
|
#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);
|
void setupCFW(void);
|
||||||
u32 loadFirm(void);
|
u32 loadFirm(void);
|
||||||
u32 patchFirm(void);
|
u32 patchFirm(void);
|
||||||
void launchFirm(void);
|
void launchFirm(void);
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -52,7 +52,7 @@ 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;
|
||||||
|
|
||||||
|
|||||||
@@ -2,8 +2,7 @@
|
|||||||
* fs.h
|
* fs.h
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef FS_INC
|
#pragma once
|
||||||
#define FS_INC
|
|
||||||
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
@@ -12,5 +11,3 @@ 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);
|
||||||
|
|
||||||
#endif
|
|
||||||
98
source/i2c.c
Normal file
98
source/i2c.c
Normal 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
18
source/i2c.h
Normal 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);
|
||||||
@@ -8,7 +8,7 @@
|
|||||||
#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))
|
fileRead((u8 *)PAYLOAD_ADDRESS, "aurei/loader.bin", 0))
|
||||||
((void (*)())PAYLOAD_ADDRESS)();
|
((void (*)())PAYLOAD_ADDRESS)();
|
||||||
}
|
}
|
||||||
@@ -2,11 +2,8 @@
|
|||||||
* loader.h
|
* loader.h
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef LOADER_INC
|
#pragma once
|
||||||
#define LOADER_INC
|
|
||||||
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
void loadPayload(void);
|
void loadPayload(void);
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -8,16 +8,16 @@
|
|||||||
|
|
||||||
#include "fs.h"
|
#include "fs.h"
|
||||||
#include "firm.h"
|
#include "firm.h"
|
||||||
#include "draw.h"
|
#include "i2c.h"
|
||||||
|
|
||||||
void main(){
|
void main(void){
|
||||||
mountSD();
|
mountSD();
|
||||||
setupCFW();
|
setupCFW();
|
||||||
}
|
|
||||||
|
|
||||||
void startCFW(){
|
|
||||||
loadSplash();
|
|
||||||
if(!loadFirm()) return;
|
if(!loadFirm()) return;
|
||||||
if(!patchFirm()) return;
|
if(!patchFirm()) return;
|
||||||
launchFirm();
|
launchFirm();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void shutdown(void){
|
||||||
|
i2cWriteRegister(I2C_DEV_MCU, 0x20, 1);
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
|||||||
@@ -4,14 +4,12 @@
|
|||||||
* Copyright (c) 2015 All Rights Reserved
|
* Copyright (c) 2015 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
|
|
||||||
@@ -17,7 +17,8 @@ const u8 mpu[0x2C] = { //MPU shit
|
|||||||
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};
|
||||||
|
|||||||
@@ -4,8 +4,7 @@
|
|||||||
* Copyright (c) 2015 All Rights Reserved
|
* Copyright (c) 2015 All Rights Reserved
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef PATCHES_INC
|
#pragma once
|
||||||
#define PATCHES_INC
|
|
||||||
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
@@ -26,5 +25,3 @@ void getSignatures(void *pos, u32 size, u32 *off, u32 *off2);
|
|||||||
void getReboot(void *pos, u32 size, u32 *off);
|
void getReboot(void *pos, u32 size, u32 *off);
|
||||||
void getfOpen(void *pos, u32 size, u32 *off);
|
void getfOpen(void *pos, u32 size, u32 *off);
|
||||||
void getFIRMWrite(void *pos, u32 size, u32 *off);
|
void getFIRMWrite(void *pos, u32 size, u32 *off);
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -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,7 @@ _start:
|
|||||||
|
|
||||||
bl main
|
bl main
|
||||||
|
|
||||||
@ Set cache settings
|
bl shutdown
|
||||||
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
|
||||||
|
|||||||
@@ -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
|
|
||||||
Reference in New Issue
Block a user