diff --git a/Makefile b/Makefile index 4253850..5061d35 100644 --- a/Makefile +++ b/Makefile @@ -6,14 +6,17 @@ endif export TARGET := $(notdir $(CURDIR)) -ENTRY9 := 0x08000054 +ENTRY9 := 0x080000D4 ENTRY11 := 0x1FF89040 -SECTION0_ADR := 0x08000040 +SECTION0_ADR := 0x080000C0 SECTION0_TYPE := 0 SECTION0_FILE := arm9/$(TARGET)9.bin -SECTION1_ADR := 0x1FF89000 -SECTION1_TYPE := 1 -SECTION1_FILE := arm11/$(TARGET)11.bin +SECTION1_ADR := 0x07FFFE8C +SECTION1_TYPE := 0 +SECTION1_FILE := superhax/superhax.bin +SECTION2_ADR := 0x1FF89000 +SECTION2_TYPE := 1 +SECTION2_FILE := arm11/$(TARGET)11.bin export VERS_STRING := $(shell git describe --tags --match v[0-9]* --abbrev=8 | sed 's/-[0-9]*-g/-/i') @@ -21,45 +24,57 @@ export VERS_MINOR := $(shell echo "$(VERS_STRING)" | sed 's/.*\.\([0-9]*\).*/\1/') -.PHONY: checkarm9 checkarm11 clean release +.PHONY: checkarm9 checksuperhax checkarm11 clean release #--------------------------------------------------------------------------------- # main targets #--------------------------------------------------------------------------------- -all: checkarm9 checkarm11 $(TARGET).firm +all: checkarm9 checksuperhax checkarm11 $(TARGET).firm #--------------------------------------------------------------------------------- checkarm9: @$(MAKE) -j4 --no-print-directory -C arm9 #--------------------------------------------------------------------------------- +checksuperhax: + @$(MAKE) --no-print-directory -C superhax + +#--------------------------------------------------------------------------------- checkarm11: @$(MAKE) -j4 --no-print-directory -C arm11 #--------------------------------------------------------------------------------- -$(TARGET).firm: arm9/$(TARGET)9.bin arm11/$(TARGET)11.bin +$(TARGET).firm: arm9/$(TARGET)9.bin superhax/superhax.bin arm11/$(TARGET)11.bin firm_builder $(TARGET).firm $(ENTRY9) $(ENTRY11) $(SECTION0_ADR) $(SECTION0_TYPE) \ - $(SECTION0_FILE) $(SECTION1_ADR) $(SECTION1_TYPE) $(SECTION1_FILE) + $(SECTION0_FILE) $(SECTION1_ADR) $(SECTION1_TYPE) $(SECTION1_FILE) $(SECTION2_ADR) \ + $(SECTION2_TYPE) $(SECTION2_FILE) #--------------------------------------------------------------------------------- arm9/$(TARGET)9.bin: @$(MAKE) -j4 --no-print-directory -C arm9 #--------------------------------------------------------------------------------- +superhax/superhax.bin: + @$(MAKE) --no-print-directory -C superhax + +#--------------------------------------------------------------------------------- arm11/$(TARGET)11.bin: @$(MAKE) -j4 --no-print-directory -C arm11 #--------------------------------------------------------------------------------- clean: @$(MAKE) --no-print-directory -C arm9 clean + @$(MAKE) --no-print-directory -C superhax clean @$(MAKE) --no-print-directory -C arm11 clean rm -f $(TARGET).firm *.7z release: clean @$(MAKE) -j4 --no-print-directory -C arm9 NO_DEBUG=1 + @$(MAKE) --no-print-directory -C superhax NO_DEBUG=1 @$(MAKE) -j4 --no-print-directory -C arm11 NO_DEBUG=1 firm_builder $(TARGET).firm $(ENTRY9) $(ENTRY11) $(SECTION0_ADR) $(SECTION0_TYPE) \ - $(SECTION0_FILE) $(SECTION1_ADR) $(SECTION1_TYPE) $(SECTION1_FILE) + $(SECTION0_FILE) $(SECTION1_ADR) $(SECTION1_TYPE) $(SECTION1_FILE) $(SECTION2_ADR) \ + $(SECTION2_TYPE) $(SECTION2_FILE) @bash signFirm.sh @7z a -mx -m0=ARM -m1=LZMA $(TARGET)$(VERS_STRING).7z $(TARGET).firm @7z u -mx -m0=PPMD $(TARGET)$(VERS_STRING).7z LICENSE.txt README.md diff --git a/arm9/arm9.ld b/arm9/arm9.ld index ee72576..69ebea4 100644 --- a/arm9/arm9.ld +++ b/arm9/arm9.ld @@ -13,7 +13,7 @@ { /* =========== CODE section =========== */ - PROVIDE(__start__ = 0x08000040); + PROVIDE(__start__ = 0x080000C0); . = __start__; .text ALIGN(4) : diff --git a/source/arm9/main.c b/source/arm9/main.c index 8e76da6..807db59 100644 --- a/source/arm9/main.c +++ b/source/arm9/main.c @@ -19,6 +19,7 @@ #include "types.h" #include "mem_map.h" #include "arm9/debug.h" +#include "arm9/hardware/cfg9.h" #include "arm.h" #include "arm9/firm.h" @@ -31,6 +32,12 @@ { debugHashCodeRoData(); + while(!(REG_CFG9_SYSPROT9 & 1) || !(REG_CFG9_SYSPROT11 & 1)) + { + REG_CFG9_SYSPROT9 = 1; + REG_CFG9_SYSPROT11 = 1; + } + while(!g_startFirmLaunch) __wfi(); // TODO: Proper argc/v passing needs to be implemented. diff --git a/superhax/Makefile b/superhax/Makefile new file mode 100644 index 0000000..c284eb3 --- /dev/null +++ b/superhax/Makefile @@ -0,0 +1,157 @@ +#--------------------------------------------------------------------------------- +.SUFFIXES: +#--------------------------------------------------------------------------------- + +ifeq ($(strip $(DEVKITARM)),) +$(error "Please set DEVKITARM in your environment. export DEVKITARM=devkitARM") +endif + +TOPDIR ?= $(CURDIR) +include $(DEVKITARM)/base_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 +#--------------------------------------------------------------------------------- +#TARGET := $(notdir $(CURDIR)) +BUILD := build +SOURCES := . +DATA := +INCLUDES := ../include +DEFINES := -DARM9 -D_3DS +LDNAME := superhax.ld + +ifneq ($(strip $(NO_DEBUG)),) + DEFINES += -DNDEBUG +endif + +#--------------------------------------------------------------------------------- +# options for code generation +#--------------------------------------------------------------------------------- +ARCH := -march=armv5te -mtune=arm946e-s -mfloat-abi=soft -mtp=soft -marm -mthumb-interwork + +CFLAGS := $(ARCH) -std=c11 -O2 -g -flto -fstrict-aliasing -mword-relocations -fomit-frame-pointer \ + -ffast-math -ffunction-sections -Wall -Wextra + +CFLAGS += $(INCLUDE) $(DEFINES) + +CXXFLAGS := $(ARCH) -std=c11 -O2 -g -flto -fno-rtti -fno-exceptions -fstrict-aliasing \ + -mword-relocations -fomit-frame-pointer -ffast-math -ffunction-sections -Wall -Wextra + +CXXFLAGS += $(INCLUDE) $(DEFINES) + +ASFLAGS := $(ARCH) -g -flto $(INCLUDE) $(DEFINES) +LDFLAGS = $(ARCH) -g -flto -Wl,--use-blx,--gc-sections,-Map,$(notdir $*.map) -nostartfiles -T ../$(LDNAME) + +LIBS := + +#--------------------------------------------------------------------------------- +# list of directories containing libraries, this must be the top level containing +# include and lib +#--------------------------------------------------------------------------------- +LIBDIRS := + + +#--------------------------------------------------------------------------------- +# 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)/superhax +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_SOURCES := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) + +export OFILES_BIN := $(addsuffix .o,$(BINFILES)) + +export OFILES := $(OFILES_BIN) $(OFILES_SOURCES) + +export HFILES := $(addsuffix .h,$(subst .,_,$(BINFILES))) + +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) + +.PHONY: $(BUILD) clean all + +#--------------------------------------------------------------------------------- +all: $(BUILD) + +$(BUILD): + @[ -d $@ ] || mkdir -p $@ + @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile + +#--------------------------------------------------------------------------------- +clean: + @echo clean ... + @rm -fr $(BUILD) $(OUTPUT).bin $(OUTPUT).elf + + +#--------------------------------------------------------------------------------- +else + +DEPENDS := $(OFILES:.o=.d) + +#--------------------------------------------------------------------------------- +# main targets +#--------------------------------------------------------------------------------- +$(OUTPUT).bin : $(OUTPUT).elf + @$(OBJCOPY) -O binary $< $@ + @echo built ... $(notdir $@) + +$(OFILES_SOURCES) : $(HFILES) + +$(OUTPUT).elf : $(OFILES) + +#--------------------------------------------------------------------------------- +# you need a rule like this for each extension you use as binary data +#--------------------------------------------------------------------------------- +%.bin.o %_bin.h : %.bin +#--------------------------------------------------------------------------------- + @echo $(notdir $<) + @$(bin2o) + +#--------------------------------------------------------------------------------- +%.elf: +#--------------------------------------------------------------------------------- + @echo linking $(notdir $@) + @$(LD) $(LDFLAGS) $(OFILES) $(LIBPATHS) $(LIBS) -o $@ + @$(NM) -CSn $@ > $(notdir $*.lst) + + +-include $(DEPENDS) + +#--------------------------------------------------------------------------------------- +endif +#--------------------------------------------------------------------------------------- diff --git a/superhax/superhax.ld b/superhax/superhax.ld new file mode 100644 index 0000000..465d55d --- /dev/null +++ b/superhax/superhax.ld @@ -0,0 +1,23 @@ +OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_vectors) + +PHDRS +{ + code PT_LOAD FLAGS(5) /* Read | Execute */; +} + +SECTIONS +{ + /* =========== CODE section =========== */ + + PROVIDE(__start__ = 0x07FFFE8C); + . = __start__; + + .text ALIGN(4) : + { + /* .init */ + KEEP( *(.crt0) ) + . = ALIGN(4); + } : code = 0xFF +} diff --git a/superhax/superhax.s b/superhax/superhax.s new file mode 100644 index 0000000..b76deb5 --- /dev/null +++ b/superhax/superhax.s @@ -0,0 +1,91 @@ +/* + * This file is part of fastboot 3DS + * Copyright (C) 2018 derrek, profi200 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 . + */ + +.arm +.cpu arm946e-s +.fpu softvfp + +.global _vectors + +.type _vectors %function +.type irqHandlerHook %function +.type hook1 %function +.type hook2 %function + +.section ".crt0", "ax" + + + +.skip 372, 0 @ Pad to 512 bytes + +_vectors: + @ These vectors are copied over the existing ones in ARM9 memory + @ at address 0x08000000. The next IRQ (MMC?) will then branch to + @ our hook function instead of the regular IRQ handler. + ldr pc, irqFuncPtr + irqFuncPtr: .word irqHandlerHook + b . + .word 0 + b . + .word 0 + b . + .word 0 + b . + .word 0 + b . + .word 0 + + +irqHandlerHook: + @ Overwrites 2 debug function pointers left in boot9 which are + @ called before boot9 jumps to the FIRM entrypoint. It also + @ restores the original IRQ vector before jumping to boot9's + @ IRQ handler. The second function skips the bootrom lock code. + stmfd sp!, {r0-r5, r12, lr} @ Prelogue of boot9 IRQ handler (yes, they save too many regs). + adr r0, hook1 + adr r1, hook2 + ldr r3, =0xFFFF0C78 @ boot9 IRQ handler + ldr r2, =0xFFF00058 @ DTCM function pointers + str r3, irqFuncPtr @ Restore IRQ vector + strd r0, r1, [r2] @ Overwrite function pointers + add pc, r3, #4 @ Branch to real IRQ handler skipping prelogue + + +hook1: + @ Overwrites a debug function pointer from boot11 called just + @ before the final jump to the entrypoint. This is a race + @ condition because boot1 will overwrite it itself while we are + @ messing with it. This also copies a tiny function to AXIWRAM start. + @ This function skips the bootrom lock wait code. + ldr r0, =0x1FFE802C @ boot11 function pointer + ldr r1, =0x1FF80000 + ldr r2, hook2 + str r2, [r1] @ Copy hook2 to AXIWRAM start + str r1, [r0] @ Overwrite pointer + hook1_lp: @ Loop until pointer changes (race) + ldr r2, [r0] + cmp r2, r1 + beq hook1_lp + str r1, [r0] @ Overwrite pointer again + bx lr + + +hook2: + bx r0 + +.pool