mirror of
https://github.com/yellows8/dsi.git
synced 2025-06-18 11:15:34 -04:00
Finally fixed 4swordshax by loading a heavily stripped down payload (minitwlpayload, ~5.4KB) from dataPub:/, which is itself based off nds-hb-menu's ARM7 bootloader.
This commit is contained in:
parent
8bad190f45
commit
20fe8d68ca
7
.gitignore
vendored
Normal file
7
.gitignore
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
build/
|
||||
exploits/generictwlpayload/**/*.bin
|
||||
exploits/minitwlpayload/**/*.bin
|
||||
*~
|
||||
*.elf
|
||||
*.dat
|
||||
*.lz
|
@ -1,9 +1,9 @@
|
||||
This is the *source* for DSi exploits/etc for DSiWare savedata. This repo is originally from 2011. These DSiWare exploits were already released in binary-only form(2011). The only exception is 4swordshax from 2011, which wasn't publicly available [until](https://github.com/yellows8/3ds_dsiwarehax_installer) 2016 since it wasn't usable on DSi without(?) a nandmod(this is the only DSiWareHax that triggers in about 1-second after app boot before any gfx is displayed). There's currently no known way to successfully load the payload from 4swordshax, hence it will just display a red sub-screen on failure.
|
||||
This is the *source* for DSi exploits/etc for DSiWare savedata. This repo is originally from 2011. These DSiWare exploits were already released in binary-only form(2011). The only exception is 4swordshax from 2011, which wasn't publicly available [until](https://github.com/yellows8/3ds_dsiwarehax_installer) 2016 since it wasn't usable on DSi without(?) a nandmod(this is the only DSiWareHax that triggers in about 1-second after app boot before any gfx is displayed).
|
||||
|
||||
If you want a prebuilt binary for generictwlpayload(it can't be completely built from this repo), check the released exploit saveimages(for example [here](https://github.com/yellows8/3ds_dsiwarehax_installer)).
|
||||
|
||||
Credits:
|
||||
* See repo description text.
|
||||
* polarssl
|
||||
* This uses code from/based on libnds/bootmii-MINI.
|
||||
* This uses code from/based on libnds/bootmii-MINI/nds-hb-menu.
|
||||
* ...
|
||||
|
@ -15,6 +15,7 @@
|
||||
#define REGION_EUR 56
|
||||
|
||||
#define REG_BASE 0x04000000
|
||||
#define PAYLOAD_ADDR 0x02200000
|
||||
|
||||
#define FS_InitCtx 0x20102d4
|
||||
#define FS_Open 0x2010b1c
|
||||
@ -43,7 +44,7 @@ _start:
|
||||
@ 4swords has two savefiles, savedata/all.dat and savedata/backup.dat. When loading one fails,(in this case larger than normal filesize) it will fallback to loading the other savefile. It will then continue without error as long as loading one of the saves worked.(it will stop loading the save *after* it reads the save into memory with the filesize, when the filesize is too large. by then it's too late to stop haxx, it seems even if *both* saves were corrupted the attacked heap stuff below would still be used & exploited before their "corrupted save" delete+recreate code executes.)
|
||||
|
||||
.word 0, 0
|
||||
.word HEAPCTX_ADR @ Adr of the next word. Starting with that adr, we overwrite a class with a vtable, but that class doesn't matter since it seems to be only used before loading the save.
|
||||
.word HEAPCTX_ADR @ Adr of the next word. Starting with that adr, we overwrite a class with a vtable, but that class does not matter since it seems to be only used before loading the save.
|
||||
.word 0 @ Without this padding, the title will overwrite heapctx+0x34 with a vtable ptr after the savedata was loaded.
|
||||
.word 0 @ Without this here, the title would overwrite heapctx+0x24+12 with a vtable ptr.
|
||||
.word HEAPCTX_ADR+4 @ This is actually a ptr to the heapctx.
|
||||
@ -88,18 +89,17 @@ mov r2, #1
|
||||
ldr r4, =FS_Open
|
||||
blx r4
|
||||
cmp r0, #0
|
||||
beq gfxdisp
|
||||
bne success
|
||||
|
||||
mov r6, #0x1f
|
||||
bl gfxdisp
|
||||
1: b 1b
|
||||
|
||||
success:
|
||||
mov r0, sp
|
||||
mov r3, #0x0020
|
||||
lsl r3, #4
|
||||
add r3, #0x20
|
||||
lsl r3, #16 @ 0x02200000
|
||||
mov r7, r3
|
||||
mov r1, r3
|
||||
mov r2, #0xd4
|
||||
lsl r2, #8
|
||||
add r2, #4 @ 0xd404
|
||||
ldr r1, =PAYLOAD_ADDR
|
||||
mov r7, r1
|
||||
ldr r2, =PAYLOAD_SIZE
|
||||
ldr r4, =FS_Read
|
||||
blx r4
|
||||
|
||||
@ -111,8 +111,10 @@ blx DC_FlushAll
|
||||
blx DC_InvalidateAll
|
||||
blx IC_InvalidateAll
|
||||
|
||||
mov r1, r7
|
||||
bx r1
|
||||
push {r7}
|
||||
ldr r6, =0x3af3
|
||||
bl gfxdisp
|
||||
pop {pc}
|
||||
|
||||
gfxdisp:
|
||||
ldr r7, =REG_BASE
|
||||
@ -149,12 +151,10 @@ mov r1, #0x84
|
||||
strb r1, [r0,#0x02]
|
||||
|
||||
ldr r4, =0x05000000 @ engine A palette
|
||||
mov r1, #0x1f
|
||||
str r1, [r4]
|
||||
str r6, [r4]
|
||||
ldr r5, =0x400
|
||||
str r1, [r4, r5] @ engine B palette
|
||||
code_end:
|
||||
b code_end
|
||||
str r6, [r4, r5] @ engine B palette
|
||||
bx lr
|
||||
|
||||
.pool
|
||||
.align 2
|
||||
@ -203,12 +203,5 @@ IC_InvalidateAll: @ From libnds.
|
||||
bx lr
|
||||
|
||||
payloadpath:
|
||||
#if REGCODE==REGION_USA
|
||||
.string "nand:/title/00030004/4B513945/data/banner.new"
|
||||
#elif REGCODE==REGION_EUR
|
||||
.string "nand:/title/00030004/4B513956/data/banner.new"
|
||||
#endif
|
||||
.string "dataPub:/savedata/payload.dat"
|
||||
.align 2
|
||||
|
||||
.space (_start + 0x1c00) - .
|
||||
|
||||
|
@ -20,18 +20,21 @@ endif
|
||||
all: all.dat
|
||||
|
||||
clean:
|
||||
rm -f $(HAXNAME).elf all.dat $(TID)$(REGCODE)hax_crypt.sav.$(HAXVER) $(HAXNAME)_crypt.ban.$(HAXVER) $(TID)$(REGCODE).tmd.sha1 $(TID)$(REGCODE)hax.savedata.sha1 $(HAXNAME).banner.sha1
|
||||
@make clean -C ../minitwlpayload
|
||||
rm -f $(HAXNAME).elf all.dat ../minitwlpayload/payload.dat $(TID)$(REGCODE)hax_crypt.sav.$(HAXVER) $(HAXNAME)_crypt.ban.$(HAXVER) $(TID)$(REGCODE).tmd.sha1 $(TID)$(REGCODE)hax.savedata.sha1 $(HAXNAME).banner.sha1
|
||||
|
||||
all.dat: $(HAXNAME).elf
|
||||
arm-none-eabi-objcopy -O binary $(HAXNAME).elf all.dat
|
||||
cp $(TID)$(REGCODE)in.savedata $(TID)$(REGCODE)hax.savedata
|
||||
sudo mount -o loop $(TID)$(REGCODE)hax.savedata $(HAXNAME)
|
||||
sudo cp ./all.dat $(HAXNAME)/savedata/all.dat
|
||||
sudo cp ../minitwlpayload/payload.dat $(HAXNAME)/savedata/payload.dat
|
||||
sudo umount $(HAXNAME)
|
||||
cp ../generictwlpayload/generictwlpayload.bin $(TID)$(REGCODE)hax.banner_new
|
||||
cp $(TID)$(REGCODE)hax.savedata public.sav
|
||||
../dumprawsav/dumprawsav --insav=$(CURDIR)/$(TID)$(REGCODE)hax.savedata --inban=$(CURDIR)/$(HAXNAME).banner --cryptsav=$(CURDIR)/$(TID)$(REGCODE)hax_crypt.sav.$(HAXVER) --cryptban=$(CURDIR)/$(HAXNAME)_crypt.ban.$(HAXVER) --hashsav=$(TID)$(REGCODE)hax.savedata.sha1 --hashban=$(HAXNAME).banner.sha1
|
||||
|
||||
$(HAXNAME).elf: $(HAXNAME).s
|
||||
arm-none-eabi-gcc -x assembler-with-cpp -nostartfiles -nostdlib -DREGCODE=$(REGCODE) $(HAXNAME).s -o $(HAXNAME).elf
|
||||
$(HAXNAME).elf: $(HAXNAME).s ../minitwlpayload/payload.dat
|
||||
arm-none-eabi-gcc -x assembler-with-cpp -nostartfiles -nostdlib -DREGCODE=$(REGCODE) -DPAYLOAD_SIZE=`stat -L -c %s ../minitwlpayload/payload.dat` $(HAXNAME).s -o $(HAXNAME).elf
|
||||
|
||||
../minitwlpayload/payload.dat:
|
||||
@make -C ../minitwlpayload
|
||||
|
168
exploits/minitwlpayload/Makefile
Normal file
168
exploits/minitwlpayload/Makefile
Normal file
@ -0,0 +1,168 @@
|
||||
#---------------------------------------------------------------------------------
|
||||
.SUFFIXES:
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
ifeq ($(strip $(DEVKITARM)),)
|
||||
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
|
||||
endif
|
||||
|
||||
include $(DEVKITARM)/ds_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
|
||||
# INCLUDES is a list of directories containing extra header files
|
||||
# DATA is a list of directories containing binary files embedded using bin2o
|
||||
# GRAPHICS is a list of directories containing image files to be converted with grit
|
||||
#---------------------------------------------------------------------------------
|
||||
TARGET := payload
|
||||
BUILD := build
|
||||
SOURCES := source
|
||||
INCLUDES := include build
|
||||
DATA := data
|
||||
GRAPHICS := gfx
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# options for code generation
|
||||
#---------------------------------------------------------------------------------
|
||||
ARCH := -mthumb -mthumb-interwork
|
||||
|
||||
CFLAGS := -g -Wall -Os\
|
||||
-march=armv5te -mtune=arm946e-s -fomit-frame-pointer -ffunction-sections -save-temps \
|
||||
-ffast-math \
|
||||
$(ARCH)
|
||||
|
||||
CFLAGS += $(INCLUDE) -DARM9 $(DEFINES)
|
||||
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions
|
||||
|
||||
ASFLAGS := -g $(ARCH) $(DEFINES)
|
||||
LDFLAGS = -nostartfiles -T../stub.ld -g $(ARCH) -Wl,-Map,$(notdir $*.map) -Wl,--gc-sections,--use-blx
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# any extra libraries we wish to link with the project (order is important)
|
||||
#---------------------------------------------------------------------------------
|
||||
LIBS :=
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# list of directories containing libraries, this must be the top level containing
|
||||
# include and lib
|
||||
#---------------------------------------------------------------------------------
|
||||
LIBDIRS := $(LIBNDS)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# 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 VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
|
||||
$(foreach dir,$(DATA),$(CURDIR)/$(dir)) \
|
||||
$(foreach dir,$(GRAPHICS),$(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)))
|
||||
PNGFILES := $(foreach dir,$(GRAPHICS),$(notdir $(wildcard $(dir)/*.png)))
|
||||
BINFILES := ndsloader.bin
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# 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)) \
|
||||
$(PNGFILES:.png=.o) \
|
||||
$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
|
||||
|
||||
export INCLUDE := $(foreach dir,$(INCLUDES),-iquote $(CURDIR)/$(dir)) \
|
||||
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
|
||||
-I$(CURDIR)/$(BUILD)
|
||||
|
||||
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
|
||||
|
||||
icons := $(wildcard *.bmp)
|
||||
|
||||
ifneq (,$(findstring $(TARGET).bmp,$(icons)))
|
||||
export GAME_ICON := $(CURDIR)/$(TARGET).bmp
|
||||
else
|
||||
ifneq (,$(findstring icon.bmp,$(icons)))
|
||||
export GAME_ICON := $(CURDIR)/icon.bmp
|
||||
endif
|
||||
endif
|
||||
|
||||
.PHONY: all bootloader $(BUILD) clean
|
||||
|
||||
all: bootloader $(BUILD)
|
||||
|
||||
bootloader: $(DATA)
|
||||
@make -C bootloader
|
||||
|
||||
$(DATA):
|
||||
@mkdir -p $@
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
$(BUILD):
|
||||
@[ -d $@ ] || mkdir -p $@
|
||||
@make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
clean:
|
||||
@echo clean ...
|
||||
@make clean -C bootloader
|
||||
@rm -fr $(BUILD) $(DATA) $(TARGET).elf $(TARGET).dat
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
else
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# main targets
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
$(OUTPUT).dat : $(OUTPUT).elf
|
||||
@$(OBJCOPY) -O binary $< $@
|
||||
@echo built ... $(notdir $@)
|
||||
|
||||
$(OUTPUT).elf : $(OFILES)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
%.bin.o : %.bin
|
||||
#---------------------------------------------------------------------------------
|
||||
@echo $(notdir $<)
|
||||
$(bin2o)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
%.nds.o : %.nds
|
||||
#---------------------------------------------------------------------------------
|
||||
@echo $(notdir $<)
|
||||
$(bin2o)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# This rule creates assembly source files using grit
|
||||
# grit takes an image file and a .grit describing how the file is to be processed
|
||||
# add additional rules like this for each image extension
|
||||
# you use in the graphics folders
|
||||
#---------------------------------------------------------------------------------
|
||||
%.s %.h : %.png %.grit
|
||||
#---------------------------------------------------------------------------------
|
||||
grit $< -fts -o$*
|
||||
|
||||
-include $(DEPSDIR)/*.d
|
||||
|
||||
#---------------------------------------------------------------------------------------
|
||||
endif
|
||||
#---------------------------------------------------------------------------------------
|
114
exploits/minitwlpayload/bootloader/Makefile
Normal file
114
exploits/minitwlpayload/bootloader/Makefile
Normal file
@ -0,0 +1,114 @@
|
||||
#---------------------------------------------------------------------------------
|
||||
.SUFFIXES:
|
||||
#---------------------------------------------------------------------------------
|
||||
ifeq ($(strip $(DEVKITARM)),)
|
||||
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM)
|
||||
endif
|
||||
|
||||
-include $(DEVKITARM)/ds_rules
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# BUILD is the directory where object files & intermediate files will be placed
|
||||
# SOURCES is a list of directories containing source code
|
||||
# INCLUDES is a list of directories containing extra header files
|
||||
#---------------------------------------------------------------------------------
|
||||
TARGET := ndsloader
|
||||
BUILD := build
|
||||
SOURCES := source source/patches
|
||||
INCLUDES := build
|
||||
SPECS := specs
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# options for code generation
|
||||
#---------------------------------------------------------------------------------
|
||||
ARCH := -mthumb -mthumb-interwork
|
||||
|
||||
CFLAGS := -g -Wall -Os\
|
||||
-mcpu=arm7tdmi -mtune=arm7tdmi -fomit-frame-pointer -ffunction-sections -save-temps\
|
||||
-ffast-math \
|
||||
$(ARCH)
|
||||
|
||||
CFLAGS += $(INCLUDE) -DARM7
|
||||
|
||||
ASFLAGS := -g $(ARCH)
|
||||
LDFLAGS = -nostartfiles -T $(TOPDIR)/load.ld -g $(ARCH) -Wl,-Map,$(TARGET).map -Wl,--gc-sections
|
||||
|
||||
LIBS :=
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# list of directories containing libraries, this must be the top level containing
|
||||
# include and lib
|
||||
#---------------------------------------------------------------------------------
|
||||
LIBDIRS := $(LIBNDS)
|
||||
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# 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 TOPDIR := $(CURDIR)
|
||||
export LOADBIN := $(CURDIR)/../data/$(TARGET).bin
|
||||
export LOADELF := $(CURDIR)/$(TARGET).elf
|
||||
export DEPSDIR := $(CURDIR)/$(BUILD)
|
||||
|
||||
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir))
|
||||
|
||||
export CC := $(PREFIX)gcc
|
||||
export CXX := $(PREFIX)g++
|
||||
export AR := $(PREFIX)ar
|
||||
export OBJCOPY := $(PREFIX)objcopy
|
||||
|
||||
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
|
||||
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
|
||||
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
|
||||
|
||||
export OFILES := $(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)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# use CC for linking standard C
|
||||
#---------------------------------------------------------------------------------
|
||||
export LD := $(CC)
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
.PHONY: $(BUILD) clean
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
$(BUILD):
|
||||
@[ -d $@ ] || mkdir -p $@
|
||||
@$(MAKE) -C $(BUILD) -f $(CURDIR)/Makefile
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
clean:
|
||||
@echo clean ...
|
||||
@rm -fr $(BUILD) $(LOADBIN) $(LOADELF)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
else
|
||||
|
||||
DEPENDS := $(OFILES:.o=.d)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# main targets
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
$(LOADBIN) : $(LOADELF)
|
||||
@$(OBJCOPY) -O binary $< $@
|
||||
@echo built ... $(notdir $@)
|
||||
|
||||
$(LOADELF) : $(OFILES)
|
||||
@echo linking $(notdir $@)
|
||||
@$(LD) $(LDFLAGS) $(OFILES) $(LIBPATHS) $(LIBS) -o $@
|
||||
|
||||
-include $(DEPENDS)
|
||||
#---------------------------------------------------------------------------------------
|
||||
endif
|
||||
#---------------------------------------------------------------------------------------
|
198
exploits/minitwlpayload/bootloader/load.ld
Normal file
198
exploits/minitwlpayload/bootloader/load.ld
Normal file
@ -0,0 +1,198 @@
|
||||
OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
|
||||
OUTPUT_ARCH(arm)
|
||||
ENTRY(_start)
|
||||
|
||||
MEMORY {
|
||||
|
||||
vram : ORIGIN = 0x06000000, LENGTH = 128K
|
||||
}
|
||||
|
||||
__vram_start = ORIGIN(vram);
|
||||
__vram_top = ORIGIN(vram)+ LENGTH(vram);
|
||||
__sp_irq = __vram_top - 0x60;
|
||||
__sp_svc = __sp_irq - 0x100;
|
||||
__sp_usr = __sp_svc - 0x100;
|
||||
|
||||
__irq_flags = __vram_top - 8;
|
||||
__irq_vector = __vram_top - 4;
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.init :
|
||||
{
|
||||
__text_start = . ;
|
||||
KEEP (*(.init))
|
||||
. = ALIGN(4); /* REQUIRED. LD is flaky without it. */
|
||||
} >vram = 0xff
|
||||
|
||||
.plt :
|
||||
{
|
||||
*(.plt)
|
||||
} >vram = 0xff
|
||||
|
||||
.text : /* ALIGN (4): */
|
||||
{
|
||||
|
||||
*(.text*)
|
||||
*(.stub)
|
||||
/* .gnu.warning sections are handled specially by elf32.em. */
|
||||
*(.gnu.warning)
|
||||
*(.gnu.linkonce.t*)
|
||||
*(.glue_7)
|
||||
*(.glue_7t)
|
||||
. = ALIGN(4); /* REQUIRED. LD is flaky without it. */
|
||||
} >vram = 0xff
|
||||
|
||||
.fini :
|
||||
{
|
||||
KEEP (*(.fini))
|
||||
} >vram =0xff
|
||||
|
||||
__text_end = . ;
|
||||
|
||||
.rodata :
|
||||
{
|
||||
*(.rodata)
|
||||
*all.rodata*(*)
|
||||
*(.roda)
|
||||
*(.rodata.*)
|
||||
*(.gnu.linkonce.r*)
|
||||
SORT(CONSTRUCTORS)
|
||||
. = ALIGN(4); /* REQUIRED. LD is flaky without it. */
|
||||
} >vram = 0xff
|
||||
|
||||
.ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >vram
|
||||
__exidx_start = .;
|
||||
.ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) } >vram
|
||||
__exidx_end = .;
|
||||
|
||||
/* Ensure the __preinit_array_start label is properly aligned. We
|
||||
could instead move the label definition inside the section, but
|
||||
the linker would then create the section even if it turns out to
|
||||
be empty, which isn't pretty. */
|
||||
. = ALIGN(32 / 8);
|
||||
PROVIDE (__preinit_array_start = .);
|
||||
.preinit_array : { KEEP (*(.preinit_array)) } >vram = 0xff
|
||||
PROVIDE (__preinit_array_end = .);
|
||||
PROVIDE (__init_array_start = .);
|
||||
.init_array : { KEEP (*(.init_array)) } >vram = 0xff
|
||||
PROVIDE (__init_array_end = .);
|
||||
PROVIDE (__fini_array_start = .);
|
||||
.fini_array : { KEEP (*(.fini_array)) } >vram = 0xff
|
||||
PROVIDE (__fini_array_end = .);
|
||||
|
||||
.ctors :
|
||||
{
|
||||
/* gcc uses crtbegin.o to find the start of the constructors, so
|
||||
we make sure it is first. Because this is a wildcard, it
|
||||
doesn't matter if the user does not actually link against
|
||||
crtbegin.o; the linker won't look for a file to match a
|
||||
wildcard. The wildcard also means that it doesn't matter which
|
||||
directory crtbegin.o is in. */
|
||||
KEEP (*crtbegin.o(.ctors))
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
|
||||
KEEP (*(SORT(.ctors.*)))
|
||||
KEEP (*(.ctors))
|
||||
. = ALIGN(4); /* REQUIRED. LD is flaky without it. */
|
||||
} >vram = 0xff
|
||||
|
||||
.dtors :
|
||||
{
|
||||
KEEP (*crtbegin.o(.dtors))
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
|
||||
KEEP (*(SORT(.dtors.*)))
|
||||
KEEP (*(.dtors))
|
||||
. = ALIGN(4); /* REQUIRED. LD is flaky without it. */
|
||||
} >vram = 0xff
|
||||
|
||||
.eh_frame :
|
||||
{
|
||||
KEEP (*(.eh_frame))
|
||||
. = ALIGN(4); /* REQUIRED. LD is flaky without it. */
|
||||
} >vram = 0xff
|
||||
|
||||
.gcc_except_table :
|
||||
{
|
||||
*(.gcc_except_table)
|
||||
. = ALIGN(4); /* REQUIRED. LD is flaky without it. */
|
||||
} >vram = 0xff
|
||||
.jcr : { KEEP (*(.jcr)) } >vram = 0
|
||||
.got : { *(.got.plt) *(.got) } >vram = 0
|
||||
|
||||
|
||||
.vram ALIGN(4) :
|
||||
{
|
||||
__vram_start = ABSOLUTE(.) ;
|
||||
*(.vram)
|
||||
*vram.*(.text)
|
||||
. = ALIGN(4); /* REQUIRED. LD is flaky without it. */
|
||||
__vram_end = ABSOLUTE(.) ;
|
||||
} >vram = 0xff
|
||||
|
||||
|
||||
.data ALIGN(4) : {
|
||||
__data_start = ABSOLUTE(.);
|
||||
*(.data)
|
||||
*(.data.*)
|
||||
*(.gnu.linkonce.d*)
|
||||
CONSTRUCTORS
|
||||
. = ALIGN(4);
|
||||
__data_end = ABSOLUTE(.) ;
|
||||
} >vram = 0xff
|
||||
|
||||
|
||||
|
||||
.bss ALIGN(4) :
|
||||
{
|
||||
__bss_start = ABSOLUTE(.);
|
||||
__bss_start__ = ABSOLUTE(.);
|
||||
*(.dynbss)
|
||||
*(.gnu.linkonce.b*)
|
||||
*(.bss*)
|
||||
*(COMMON)
|
||||
. = ALIGN(4); /* REQUIRED. LD is flaky without it. */
|
||||
} >vram
|
||||
|
||||
__bss_end = . ;
|
||||
__bss_end__ = . ;
|
||||
|
||||
_end = . ;
|
||||
__end__ = . ;
|
||||
PROVIDE (end = _end);
|
||||
|
||||
/* Stabs debugging sections. */
|
||||
.stab 0 : { *(.stab) }
|
||||
.stabstr 0 : { *(.stabstr) }
|
||||
.stab.excl 0 : { *(.stab.excl) }
|
||||
.stab.exclstr 0 : { *(.stab.exclstr) }
|
||||
.stab.index 0 : { *(.stab.index) }
|
||||
.stab.indexstr 0 : { *(.stab.indexstr) }
|
||||
.comment 0 : { *(.comment) }
|
||||
/* DWARF debug sections.
|
||||
Symbols in the DWARF debugging sections are relative to the beginning
|
||||
of the section so we begin them at 0. */
|
||||
/* DWARF 1 */
|
||||
.debug 0 : { *(.debug) }
|
||||
.line 0 : { *(.line) }
|
||||
/* GNU DWARF 1 extensions */
|
||||
.debug_srcinfo 0 : { *(.debug_srcinfo) }
|
||||
.debug_sfnames 0 : { *(.debug_sfnames) }
|
||||
/* DWARF 1.1 and DWARF 2 */
|
||||
.debug_aranges 0 : { *(.debug_aranges) }
|
||||
.debug_pubnames 0 : { *(.debug_pubnames) }
|
||||
/* DWARF 2 */
|
||||
.debug_info 0 : { *(.debug_info) }
|
||||
.debug_abbrev 0 : { *(.debug_abbrev) }
|
||||
.debug_line 0 : { *(.debug_line) }
|
||||
.debug_frame 0 : { *(.debug_frame) }
|
||||
.debug_str 0 : { *(.debug_str) }
|
||||
.debug_loc 0 : { *(.debug_loc) }
|
||||
.debug_macinfo 0 : { *(.debug_macinfo) }
|
||||
/* SGI/MIPS DWARF 2 extensions */
|
||||
.debug_weaknames 0 : { *(.debug_weaknames) }
|
||||
.debug_funcnames 0 : { *(.debug_funcnames) }
|
||||
.debug_typenames 0 : { *(.debug_typenames) }
|
||||
.debug_varnames 0 : { *(.debug_varnames) }
|
||||
.stack 0x80000 : { _stack = .; *(.stack) }
|
||||
/* These must appear regardless of . */
|
||||
}
|
60
exploits/minitwlpayload/bootloader/source/arm7clear.s
Normal file
60
exploits/minitwlpayload/bootloader/source/arm7clear.s
Normal file
@ -0,0 +1,60 @@
|
||||
/*-----------------------------------------------------------------
|
||||
|
||||
Copyright (C) 2005 Michael "Chishm" Chisholm
|
||||
|
||||
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 2
|
||||
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, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
If you use this code, please give due credit and email me about your
|
||||
project at chishm@hotmail.com
|
||||
------------------------------------------------------------------*/
|
||||
|
||||
.arm
|
||||
.global arm7clearRAM
|
||||
.type arm7clearRAM STT_FUNC
|
||||
arm7clearRAM:
|
||||
|
||||
push {r0-r9}
|
||||
// clear exclusive IWRAM
|
||||
// 0380:0000 to 0380:FFFF, total 64KiB
|
||||
mov r0, #0
|
||||
mov r1, #0
|
||||
mov r2, #0
|
||||
mov r3, #0
|
||||
mov r4, #0
|
||||
mov r5, #0
|
||||
mov r6, #0
|
||||
mov r7, #0
|
||||
mov r8, #0x03800000
|
||||
sub r8, #0x00008000
|
||||
mov r9, #0x03800000
|
||||
orr r9, r9, #0x10000
|
||||
clear_IWRAM_loop:
|
||||
stmia r8!, {r0, r1, r2, r3, r4, r5, r6, r7}
|
||||
cmp r8, r9
|
||||
blt clear_IWRAM_loop
|
||||
|
||||
// clear most of EWRAM - except after RAM end - 0xc000, which has the bootstub
|
||||
mov r8, #0x02000000
|
||||
mov r9, #0x03000000
|
||||
sub r9, #0x0000c000
|
||||
clear_EWRAM_loop:
|
||||
stmia r8!, {r0, r1, r2, r3, r4, r5, r6, r7}
|
||||
cmp r8, r9
|
||||
blt clear_EWRAM_loop
|
||||
|
||||
pop {r0-r9}
|
||||
|
||||
bx lr
|
||||
|
114
exploits/minitwlpayload/bootloader/source/arm9clear.arm.c
Normal file
114
exploits/minitwlpayload/bootloader/source/arm9clear.arm.c
Normal file
@ -0,0 +1,114 @@
|
||||
#define ARM9
|
||||
#undef ARM7
|
||||
|
||||
#include <nds/ndstypes.h>
|
||||
#include <nds/dma.h>
|
||||
#include <nds/system.h>
|
||||
#include <nds/interrupts.h>
|
||||
#include <nds/timers.h>
|
||||
|
||||
#include <nds/memory.h>
|
||||
#include <nds/arm9/video.h>
|
||||
#include <nds/arm9/input.h>
|
||||
|
||||
#include "boot.h"
|
||||
|
||||
static inline void debug_color(int r, int g, int b)
|
||||
{
|
||||
u16 clr = RGB15(r,g,b);
|
||||
*(vu32*)0x05000000 = clr;
|
||||
*(vu32*)0x05000400 = clr;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
resetMemory2_ARM9
|
||||
Clears the ARM9's DMA channels and resets video memory
|
||||
Written by Darkain.
|
||||
Modified by Chishm:
|
||||
* Changed MultiNDS specific stuff
|
||||
--------------------------------------------------------------------------*/
|
||||
void __attribute__ ((long_call)) __attribute__((naked)) __attribute__((noreturn)) resetMemory2_ARM9 (void)
|
||||
{
|
||||
register int i, reg;
|
||||
if (*(vu32*)(0x02FFE000-4))
|
||||
debug_color(0,0,31); // blue
|
||||
else
|
||||
debug_color(31,15,15); // light red
|
||||
|
||||
//clear out ARM9 DMA channels
|
||||
/* --removed-- already done by other code
|
||||
for (i=0; i<4; i++) {
|
||||
DMA_CR(i) = 0;
|
||||
DMA_SRC(i) = 0;
|
||||
DMA_DEST(i) = 0;
|
||||
TIMER_CR(i) = 0;
|
||||
TIMER_DATA(i) = 0;
|
||||
for(reg=0; reg<0x1c; reg+=4)*((u32*)(0x04004104 + ((i*0x1c)+reg))) = 0;//Reset NDMA.
|
||||
}
|
||||
*/
|
||||
|
||||
VRAM_CR = (VRAM_CR & 0xffff0000) | 0x00008080 ;
|
||||
|
||||
u16 *mainregs = (u16*)0x04000000;
|
||||
u16 *subregs = (u16*)0x04001000;
|
||||
|
||||
for (i=0; i<43; i++) {
|
||||
mainregs[i] = 0;
|
||||
subregs[i] = 0;
|
||||
}
|
||||
|
||||
REG_DISPSTAT = 0;
|
||||
|
||||
VRAM_A_CR = 0;
|
||||
VRAM_B_CR = 0;
|
||||
// Don't mess with the ARM7's VRAM
|
||||
// VRAM_C_CR = 0;
|
||||
VRAM_D_CR = 0;
|
||||
VRAM_E_CR = 0;
|
||||
VRAM_F_CR = 0;
|
||||
VRAM_G_CR = 0;
|
||||
VRAM_H_CR = 0;
|
||||
VRAM_I_CR = 0;
|
||||
|
||||
/* --removed-- already done by other code
|
||||
REG_POWERCNT = 0x820F;
|
||||
|
||||
//set shared ram to ARM7
|
||||
WRAM_CR = 0x03;
|
||||
|
||||
REG_EXMEMCNT = 0xE880;
|
||||
*/
|
||||
|
||||
// Return to passme loop
|
||||
*((vu32*)0x02FFFE04) = (u32)0xE59FF018; // ldr pc, 0x02FFFE24
|
||||
*((vu32*)0x02FFFE24) = (u32)0x02FFFE04; // Set ARM9 Loop address
|
||||
|
||||
asm volatile(
|
||||
"\tbx %0\n"
|
||||
: : "r" (0x02FFFE04)
|
||||
);
|
||||
while(1);
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
startBinary_ARM9
|
||||
Jumps to the ARM9 NDS binary in sync with the display and ARM7
|
||||
Written by Darkain.
|
||||
Modified by Chishm:
|
||||
* Removed MultiNDS specific stuff
|
||||
--------------------------------------------------------------------------*/
|
||||
void __attribute__ ((long_call)) __attribute__((noreturn)) __attribute__((naked)) startBinary_ARM9 (void)
|
||||
{
|
||||
debug_color(15,15,31); // light blue
|
||||
REG_IME=0;
|
||||
REG_EXMEMCNT = 0xE880;
|
||||
// set ARM9 load address to 0 and wait for it to change again
|
||||
ARM9_START_FLAG = 0;
|
||||
while(REG_VCOUNT!=191);
|
||||
while(REG_VCOUNT==191);
|
||||
while ( ARM9_START_FLAG != 1 );
|
||||
VoidFn arm9code = *(VoidFn*)(0x2FFFE24);
|
||||
arm9code();
|
||||
while(1);
|
||||
}
|
||||
|
13
exploits/minitwlpayload/bootloader/source/bios.s
Normal file
13
exploits/minitwlpayload/bootloader/source/bios.s
Normal file
@ -0,0 +1,13 @@
|
||||
.text
|
||||
.align 4
|
||||
|
||||
.thumb
|
||||
|
||||
@---------------------------------------------------------------------------------
|
||||
.global swiDelay
|
||||
.thumb_func
|
||||
@---------------------------------------------------------------------------------
|
||||
swiDelay:
|
||||
@---------------------------------------------------------------------------------
|
||||
swi 0x03
|
||||
bx lr
|
293
exploits/minitwlpayload/bootloader/source/boot.c
Normal file
293
exploits/minitwlpayload/bootloader/source/boot.c
Normal file
@ -0,0 +1,293 @@
|
||||
/*-----------------------------------------------------------------
|
||||
boot.c
|
||||
|
||||
BootLoader
|
||||
Loads a file into memory and runs it
|
||||
|
||||
All resetMemory and startBinary functions are based
|
||||
on the MultiNDS loader by Darkain.
|
||||
Original source available at:
|
||||
http://cvs.sourceforge.net/viewcvs.py/ndslib/ndslib/examples/loader/boot/main.cpp
|
||||
|
||||
License:
|
||||
Copyright (C) 2005 Michael "Chishm" Chisholm
|
||||
|
||||
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 2
|
||||
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, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
If you use this code, please give due credit and email me about your
|
||||
project at chishm@hotmail.com
|
||||
|
||||
Helpful information:
|
||||
This code runs from VRAM bank C on ARM7
|
||||
------------------------------------------------------------------*/
|
||||
|
||||
#include <nds/ndstypes.h>
|
||||
#include <nds/dma.h>
|
||||
#include <nds/system.h>
|
||||
#include <nds/interrupts.h>
|
||||
#include <nds/timers.h>
|
||||
#define ARM9
|
||||
#undef ARM7
|
||||
#include <nds/memory.h>
|
||||
#include <nds/arm9/video.h>
|
||||
#include <nds/arm9/input.h>
|
||||
#undef ARM9
|
||||
#define ARM7
|
||||
#include <nds/arm7/audio.h>
|
||||
|
||||
#include "fat.h"
|
||||
#include "card.h"
|
||||
#include "boot.h"
|
||||
|
||||
void arm7clearRAM();
|
||||
|
||||
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
// Important things
|
||||
#define TEMP_MEM 0x02FFE000
|
||||
#define NDS_HEAD 0x02FFFE00
|
||||
#define TEMP_ARM9_START_ADDRESS (*(vu32*)0x02FFFFF4)
|
||||
|
||||
|
||||
const char* bootName = "BOOT.NDS";
|
||||
|
||||
extern unsigned long _start;
|
||||
extern unsigned long argStart;
|
||||
extern unsigned long argSize;
|
||||
|
||||
#ifdef USE_FIRMWARE_READ
|
||||
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
// Firmware stuff
|
||||
|
||||
#define FW_READ 0x03
|
||||
|
||||
void boot_readFirmware (uint32 address, uint8 * buffer, uint32 size) {
|
||||
uint32 index;
|
||||
|
||||
// Read command
|
||||
while (REG_SPICNT & SPI_BUSY);
|
||||
REG_SPICNT = SPI_ENABLE | SPI_CONTINUOUS | SPI_DEVICE_NVRAM;
|
||||
REG_SPIDATA = FW_READ;
|
||||
while (REG_SPICNT & SPI_BUSY);
|
||||
|
||||
// Set the address
|
||||
REG_SPIDATA = (address>>16) & 0xFF;
|
||||
while (REG_SPICNT & SPI_BUSY);
|
||||
REG_SPIDATA = (address>>8) & 0xFF;
|
||||
while (REG_SPICNT & SPI_BUSY);
|
||||
REG_SPIDATA = (address) & 0xFF;
|
||||
while (REG_SPICNT & SPI_BUSY);
|
||||
|
||||
for (index = 0; index < size; index++) {
|
||||
REG_SPIDATA = 0;
|
||||
while (REG_SPICNT & SPI_BUSY);
|
||||
buffer[index] = REG_SPIDATA & 0xFF;
|
||||
}
|
||||
REG_SPICNT = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static inline void copyLoop (u32* dest, const u32* src, u32 size) {
|
||||
size = (size +3) & ~3;
|
||||
do {
|
||||
*dest++ = *src++;
|
||||
} while (size -= 4);
|
||||
}
|
||||
|
||||
//#define resetCpu() __asm volatile("\tswi 0x000000\n");
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
passArgs_ARM7
|
||||
Copies the command line arguments to the end of the ARM9 binary,
|
||||
then sets a flag in memory for the loaded NDS to use
|
||||
--------------------------------------------------------------------------*/
|
||||
void passArgs_ARM7 (void) {
|
||||
u32 ARM9_DST = *((u32*)(NDS_HEAD + 0x028));
|
||||
u32 ARM9_LEN = *((u32*)(NDS_HEAD + 0x02C));
|
||||
u32* argSrc;
|
||||
u32* argDst;
|
||||
|
||||
if (!argStart || !argSize) return;
|
||||
|
||||
argSrc = (u32*)(argStart + (int)&_start);
|
||||
|
||||
argDst = (u32*)((ARM9_DST + ARM9_LEN + 3) & ~3); // Word aligned
|
||||
|
||||
copyLoop(argDst, argSrc, argSize);
|
||||
|
||||
__system_argv->argvMagic = ARGV_MAGIC;
|
||||
__system_argv->commandLine = (char*)argDst;
|
||||
__system_argv->length = argSize;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
resetMemory_ARM7
|
||||
Clears all of the NDS's RAM that is visible to the ARM7
|
||||
Written by Darkain.
|
||||
Modified by Chishm:
|
||||
* Added STMIA clear mem loop
|
||||
--------------------------------------------------------------------------*/
|
||||
void resetMemory_ARM7 (void)
|
||||
{
|
||||
int i,reg;
|
||||
#ifdef USE_FIRMWARE_READ
|
||||
u8 settings1, settings2;
|
||||
u32 settingsOffset = 0;
|
||||
#endif
|
||||
|
||||
REG_IME = 0;
|
||||
|
||||
for (i=0; i<16; i++) {
|
||||
SCHANNEL_CR(i) = 0;
|
||||
SCHANNEL_TIMER(i) = 0;
|
||||
SCHANNEL_SOURCE(i) = 0;
|
||||
SCHANNEL_LENGTH(i) = 0;
|
||||
}
|
||||
|
||||
REG_SOUNDCNT = 0;
|
||||
REG_SOUNDBIAS = 0x0200; //Fix bad sounds after soft reset
|
||||
for (i=0; i<0x20; i+=4) //Clear sound capture hw.
|
||||
*(vu32*)(0x04000508+i) = 0;
|
||||
|
||||
//clear out ARM7 DMA channels and timers
|
||||
for (i=0; i<4; i++) {
|
||||
DMA_CR(i) = 0;
|
||||
DMA_SRC(i) = 0;
|
||||
DMA_DEST(i) = 0;
|
||||
TIMER_CR(i) = 0;
|
||||
TIMER_DATA(i) = 0;
|
||||
for(reg=0; reg<0x1c; reg+=4)*((u32*)(0x04004104 + ((i*0x1c)+reg))) = 0;//Reset NDMA.
|
||||
}
|
||||
|
||||
arm7clearRAM();
|
||||
|
||||
REG_IE = 0;
|
||||
REG_IF = ~0;
|
||||
REG_AUXIE = 0;
|
||||
REG_AUXIF = ~0;
|
||||
(*(vu32*)(0x04000000-4)) = 0; //IRQ_HANDLER ARM7 version
|
||||
(*(vu32*)(0x04000000-8)) = ~0; //VBLANK_INTR_WAIT_FLAGS, ARM7 version
|
||||
REG_POWERCNT = 1; //turn off power to stuff
|
||||
|
||||
#ifdef USE_FIRMWARE_READ
|
||||
// Get settings location
|
||||
boot_readFirmware((u32)0x00020, (u8*)&settingsOffset, 0x2);
|
||||
settingsOffset *= 8;
|
||||
|
||||
// Reload DS Firmware settings
|
||||
boot_readFirmware(settingsOffset + 0x070, &settings1, 0x1);
|
||||
boot_readFirmware(settingsOffset + 0x170, &settings2, 0x1);
|
||||
|
||||
if ((settings1 & 0x7F) == ((settings2+1) & 0x7F)) {
|
||||
boot_readFirmware(settingsOffset + 0x000, (u8*)0x02FFFC80, 0x70);
|
||||
} else {
|
||||
boot_readFirmware(settingsOffset + 0x100, (u8*)0x02FFFC80, 0x70);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void loadBinary_ARM7 (u32 fileCluster)
|
||||
{
|
||||
u32 ndsHeader[0x170>>2];
|
||||
|
||||
// read NDS header
|
||||
fileRead ((char*)ndsHeader, fileCluster, 0, 0x170);
|
||||
// read ARM9 info from NDS header
|
||||
u32 ARM9_SRC = ndsHeader[0x020>>2];
|
||||
char* ARM9_DST = (char*)ndsHeader[0x028>>2];
|
||||
u32 ARM9_LEN = ndsHeader[0x02C>>2];
|
||||
// read ARM7 info from NDS header
|
||||
u32 ARM7_SRC = ndsHeader[0x030>>2];
|
||||
char* ARM7_DST = (char*)ndsHeader[0x038>>2];
|
||||
u32 ARM7_LEN = ndsHeader[0x03C>>2];
|
||||
|
||||
// Load binaries into memory
|
||||
fileRead(ARM9_DST, fileCluster, ARM9_SRC, ARM9_LEN);
|
||||
fileRead(ARM7_DST, fileCluster, ARM7_SRC, ARM7_LEN);
|
||||
|
||||
// first copy the header to its proper location, excluding
|
||||
// the ARM9 start address, so as not to start it
|
||||
TEMP_ARM9_START_ADDRESS = ndsHeader[0x024>>2]; // Store for later
|
||||
ndsHeader[0x024>>2] = 0;
|
||||
dmaCopyWords(3, (void*)ndsHeader, (void*)NDS_HEAD, 0x170);
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
startBinary_ARM7
|
||||
Jumps to the ARM7 NDS binary in sync with the display and ARM9
|
||||
Written by Darkain.
|
||||
Modified by Chishm:
|
||||
* Removed MultiNDS specific stuff
|
||||
--------------------------------------------------------------------------*/
|
||||
void startBinary_ARM7 (void) {
|
||||
REG_IME=0;
|
||||
while(REG_VCOUNT!=191);
|
||||
while(REG_VCOUNT==191);
|
||||
// copy NDS ARM9 start address into the header, starting ARM9
|
||||
*((vu32*)0x02FFFE24) = TEMP_ARM9_START_ADDRESS;
|
||||
ARM9_START_FLAG = 1;
|
||||
// Start ARM7
|
||||
VoidFn arm7code = *(VoidFn*)(0x2FFFE34);
|
||||
arm7code();
|
||||
}
|
||||
|
||||
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
// Main function
|
||||
|
||||
int main (void) {
|
||||
// Init card
|
||||
bool fs_success = FAT_InitFiles();
|
||||
u32 fileCluster = CLUSTER_FREE;
|
||||
if (fs_success)
|
||||
{
|
||||
// Get cluster of boot file
|
||||
fileCluster = getBootFileCluster("BOOT.NDS");
|
||||
fs_success = fileCluster != CLUSTER_FREE;
|
||||
}
|
||||
|
||||
// ARM9 clears its memory part 2
|
||||
// copy ARM9 function to RAM, and make the ARM9 jump to it
|
||||
*(vu32*)(TEMP_MEM-4) = fs_success;
|
||||
copyLoop((void*)TEMP_MEM, (void*)resetMemory2_ARM9, resetMemory2_ARM9_size);
|
||||
(*(vu32*)0x02FFFE24) = (u32)TEMP_MEM; // Make ARM9 jump to the function
|
||||
// Wait until the ARM9 has completed its task
|
||||
while ((*(vu32*)0x02FFFE24) == (u32)TEMP_MEM);
|
||||
|
||||
if (!fs_success)
|
||||
return -1;
|
||||
|
||||
// Get ARM7 to clear RAM
|
||||
resetMemory_ARM7();
|
||||
|
||||
// ARM9 enters a wait loop
|
||||
// copy ARM9 function to RAM, and make the ARM9 jump to it
|
||||
copyLoop((void*)TEMP_MEM, (void*)startBinary_ARM9, startBinary_ARM9_size);
|
||||
(*(vu32*)0x02FFFE24) = (u32)TEMP_MEM; // Make ARM9 jump to the function
|
||||
|
||||
// Load the NDS file
|
||||
loadBinary_ARM7(fileCluster);
|
||||
|
||||
// Pass command line arguments to loaded program
|
||||
passArgs_ARM7();
|
||||
|
||||
startBinary_ARM7();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
10
exploits/minitwlpayload/bootloader/source/boot.h
Normal file
10
exploits/minitwlpayload/bootloader/source/boot.h
Normal file
@ -0,0 +1,10 @@
|
||||
#ifndef _BOOT_H_
|
||||
#define _BOOT_H_
|
||||
|
||||
#define resetMemory2_ARM9_size 0x400
|
||||
void __attribute__ ((long_call)) __attribute__((naked)) __attribute__((noreturn)) resetMemory2_ARM9();
|
||||
#define startBinary_ARM9_size 0x100
|
||||
void __attribute__ ((long_call)) __attribute__((noreturn)) __attribute__((naked)) startBinary_ARM9 ();
|
||||
#define ARM9_START_FLAG (*(vu8*)0x02FFFDFB)
|
||||
|
||||
#endif // _BOOT_H_
|
49
exploits/minitwlpayload/bootloader/source/card.h
Normal file
49
exploits/minitwlpayload/bootloader/source/card.h
Normal file
@ -0,0 +1,49 @@
|
||||
/*-----------------------------------------------------------------
|
||||
|
||||
Copyright (C) 2005 Michael "Chishm" Chisholm
|
||||
|
||||
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 2
|
||||
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, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
If you use this code, please give due credit and email me about your
|
||||
project at chishm@hotmail.com
|
||||
------------------------------------------------------------------*/
|
||||
|
||||
#ifndef CARD_H
|
||||
#define CARD_H
|
||||
|
||||
#define BYTES_PER_SECTOR 512
|
||||
|
||||
void sdmmc_controller_init();
|
||||
int sdmmc_sdcard_init();
|
||||
int sdmmc_sdcard_readsectors(u32 sector_no, u32 numsectors, void *out);
|
||||
|
||||
static inline bool CARD_StartUp (void) {
|
||||
sdmmc_controller_init();
|
||||
return sdmmc_sdcard_init() == 0;
|
||||
}
|
||||
|
||||
static inline bool CARD_IsInserted (void) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool CARD_ReadSectors (u32 sector, int count, void *buffer) {
|
||||
return sdmmc_sdcard_readsectors(sector, count, buffer) == 0;
|
||||
}
|
||||
|
||||
static inline bool CARD_ReadSector (u32 sector, void *buffer) {
|
||||
return sdmmc_sdcard_readsectors(sector, 1, buffer) == 0;
|
||||
}
|
||||
|
||||
#endif // CARD_H
|
587
exploits/minitwlpayload/bootloader/source/fat.c
Normal file
587
exploits/minitwlpayload/bootloader/source/fat.c
Normal file
@ -0,0 +1,587 @@
|
||||
/*-----------------------------------------------------------------
|
||||
fat.c
|
||||
|
||||
NDS MP
|
||||
GBAMP NDS Firmware Hack Version 2.12
|
||||
An NDS aware firmware patch for the GBA Movie Player.
|
||||
By Michael Chisholm (Chishm)
|
||||
|
||||
Filesystem code based on GBAMP_CF.c by Chishm (me).
|
||||
|
||||
License:
|
||||
Copyright (C) 2005 Michael "Chishm" Chisholm
|
||||
|
||||
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 2
|
||||
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, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
If you use this code, please give due credit and email me about your
|
||||
project at chishm@hotmail.com
|
||||
------------------------------------------------------------------*/
|
||||
|
||||
#include "fat.h"
|
||||
#include "card.h"
|
||||
|
||||
|
||||
//---------------------------------------------------------------
|
||||
// FAT constants
|
||||
|
||||
#define FILE_LAST 0x00
|
||||
#define FILE_FREE 0xE5
|
||||
|
||||
#define ATTRIB_ARCH 0x20
|
||||
#define ATTRIB_DIR 0x10
|
||||
#define ATTRIB_LFN 0x0F
|
||||
#define ATTRIB_VOL 0x08
|
||||
#define ATTRIB_HID 0x02
|
||||
#define ATTRIB_SYS 0x04
|
||||
#define ATTRIB_RO 0x01
|
||||
|
||||
#define FAT16_ROOT_DIR_CLUSTER 0x00
|
||||
|
||||
// File Constants
|
||||
#ifndef EOF
|
||||
#define EOF -1
|
||||
#define SEEK_SET 0
|
||||
#define SEEK_CUR 1
|
||||
#define SEEK_END 2
|
||||
#endif
|
||||
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
// FAT constants
|
||||
#define CLUSTER_EOF_16 0xFFFF
|
||||
|
||||
#define ATTRIB_ARCH 0x20
|
||||
#define ATTRIB_DIR 0x10
|
||||
#define ATTRIB_LFN 0x0F
|
||||
#define ATTRIB_VOL 0x08
|
||||
#define ATTRIB_HID 0x02
|
||||
#define ATTRIB_SYS 0x04
|
||||
#define ATTRIB_RO 0x01
|
||||
|
||||
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
// Data Structures
|
||||
|
||||
#define __PACKED __attribute__ ((__packed__))
|
||||
|
||||
// Boot Sector - must be packed
|
||||
typedef struct
|
||||
{
|
||||
u8 jmpBoot[3];
|
||||
u8 OEMName[8];
|
||||
// BIOS Parameter Block
|
||||
u16 bytesPerSector;
|
||||
u8 sectorsPerCluster;
|
||||
u16 reservedSectors;
|
||||
u8 numFATs;
|
||||
u16 rootEntries;
|
||||
u16 numSectorsSmall;
|
||||
u8 mediaDesc;
|
||||
u16 sectorsPerFAT;
|
||||
u16 sectorsPerTrk;
|
||||
u16 numHeads;
|
||||
u32 numHiddenSectors;
|
||||
u32 numSectors;
|
||||
union // Different types of extended BIOS Parameter Block for FAT16 and FAT32
|
||||
{
|
||||
struct
|
||||
{
|
||||
// Ext BIOS Parameter Block for FAT16
|
||||
u8 driveNumber;
|
||||
u8 reserved1;
|
||||
u8 extBootSig;
|
||||
u32 volumeID;
|
||||
u8 volumeLabel[11];
|
||||
u8 fileSysType[8];
|
||||
// Bootcode
|
||||
u8 bootCode[448];
|
||||
} fat16;
|
||||
struct
|
||||
{
|
||||
// FAT32 extended block
|
||||
u32 sectorsPerFAT32;
|
||||
u16 extFlags;
|
||||
u16 fsVer;
|
||||
u32 rootClus;
|
||||
u16 fsInfo;
|
||||
u16 bkBootSec;
|
||||
u8 reserved[12];
|
||||
// Ext BIOS Parameter Block for FAT16
|
||||
u8 driveNumber;
|
||||
u8 reserved1;
|
||||
u8 extBootSig;
|
||||
u32 volumeID;
|
||||
u8 volumeLabel[11];
|
||||
u8 fileSysType[8];
|
||||
// Bootcode
|
||||
u8 bootCode[420];
|
||||
} fat32;
|
||||
} extBlock;
|
||||
|
||||
__PACKED u16 bootSig;
|
||||
|
||||
} __PACKED BOOT_SEC;
|
||||
|
||||
// Directory entry - must be packed
|
||||
typedef struct
|
||||
{
|
||||
u8 name[8];
|
||||
u8 ext[3];
|
||||
u8 attrib;
|
||||
u8 reserved;
|
||||
u8 cTime_ms;
|
||||
u16 cTime;
|
||||
u16 cDate;
|
||||
u16 aDate;
|
||||
u16 startClusterHigh;
|
||||
u16 mTime;
|
||||
u16 mDate;
|
||||
u16 startCluster;
|
||||
u32 fileSize;
|
||||
} __PACKED DIR_ENT;
|
||||
|
||||
// File information - no need to pack
|
||||
typedef struct
|
||||
{
|
||||
u32 firstCluster;
|
||||
u32 length;
|
||||
u32 curPos;
|
||||
u32 curClus; // Current cluster to read from
|
||||
int curSect; // Current sector within cluster
|
||||
int curByte; // Current byte within sector
|
||||
char readBuffer[512]; // Buffer used for unaligned reads
|
||||
u32 appClus; // Cluster to append to
|
||||
int appSect; // Sector within cluster for appending
|
||||
int appByte; // Byte within sector for appending
|
||||
bool read; // Can read from file
|
||||
bool write; // Can write to file
|
||||
bool append;// Can append to file
|
||||
bool inUse; // This file is open
|
||||
u32 dirEntSector; // The sector where the directory entry is stored
|
||||
int dirEntOffset; // The offset within the directory sector
|
||||
} FAT_FILE;
|
||||
|
||||
|
||||
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
// Global Variables
|
||||
|
||||
// _VARS_IN_RAM variables are stored in the largest section of WRAM
|
||||
// available: IWRAM on NDS ARM7, EWRAM on NDS ARM9 and GBA
|
||||
|
||||
// Locations on card
|
||||
int discRootDir;
|
||||
int discRootDirClus;
|
||||
int discFAT;
|
||||
int discSecPerFAT;
|
||||
int discNumSec;
|
||||
int discData;
|
||||
int discBytePerSec;
|
||||
int discSecPerClus;
|
||||
int discBytePerClus;
|
||||
|
||||
enum {FS_UNKNOWN, FS_FAT12, FS_FAT16, FS_FAT32} discFileSystem;
|
||||
|
||||
// Global sector buffer to save on stack space
|
||||
unsigned char globalBuffer[BYTES_PER_SECTOR];
|
||||
|
||||
|
||||
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
//FAT routines
|
||||
|
||||
u32 FAT_ClustToSect (u32 cluster) {
|
||||
return (((cluster-2) * discSecPerClus) + discData);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------
|
||||
FAT_NextCluster
|
||||
Internal function - gets the cluster linked from input cluster
|
||||
-----------------------------------------------------------------*/
|
||||
u32 FAT_NextCluster(u32 cluster)
|
||||
{
|
||||
u32 nextCluster = CLUSTER_FREE;
|
||||
u32 sector;
|
||||
int offset;
|
||||
|
||||
|
||||
switch (discFileSystem)
|
||||
{
|
||||
#ifdef SUPPORT_OLD_FAT
|
||||
case FS_UNKNOWN:
|
||||
nextCluster = CLUSTER_FREE;
|
||||
break;
|
||||
|
||||
case FS_FAT12:
|
||||
sector = discFAT + (((cluster * 3) / 2) / BYTES_PER_SECTOR);
|
||||
offset = ((cluster * 3) / 2) % BYTES_PER_SECTOR;
|
||||
CARD_ReadSector(sector, globalBuffer);
|
||||
nextCluster = ((u8*) globalBuffer)[offset];
|
||||
offset++;
|
||||
|
||||
if (offset >= BYTES_PER_SECTOR) {
|
||||
offset = 0;
|
||||
sector++;
|
||||
}
|
||||
|
||||
CARD_ReadSector(sector, globalBuffer);
|
||||
nextCluster |= (((u8*) globalBuffer)[offset]) << 8;
|
||||
|
||||
if (cluster & 0x01) {
|
||||
nextCluster = nextCluster >> 4;
|
||||
} else {
|
||||
nextCluster &= 0x0FFF;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case FS_FAT16:
|
||||
sector = discFAT + ((cluster << 1) / BYTES_PER_SECTOR);
|
||||
offset = cluster % (BYTES_PER_SECTOR >> 1);
|
||||
|
||||
CARD_ReadSector(sector, globalBuffer);
|
||||
// read the nextCluster value
|
||||
nextCluster = ((u16*)globalBuffer)[offset];
|
||||
|
||||
if (nextCluster >= 0xFFF7)
|
||||
{
|
||||
nextCluster = CLUSTER_EOF;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
case FS_FAT32:
|
||||
sector = discFAT + ((cluster << 2) / BYTES_PER_SECTOR);
|
||||
offset = cluster % (BYTES_PER_SECTOR >> 2);
|
||||
|
||||
CARD_ReadSector(sector, globalBuffer);
|
||||
// read the nextCluster value
|
||||
nextCluster = (((u32*)globalBuffer)[offset]) & 0x0FFFFFFF;
|
||||
|
||||
if (nextCluster >= 0x0FFFFFF7)
|
||||
{
|
||||
nextCluster = CLUSTER_EOF;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
nextCluster = CLUSTER_FREE;
|
||||
break;
|
||||
}
|
||||
|
||||
return nextCluster;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------
|
||||
ucase
|
||||
Returns the uppercase version of the given char
|
||||
char IN: a character
|
||||
char return OUT: uppercase version of character
|
||||
-----------------------------------------------------------------*/
|
||||
char ucase (char character)
|
||||
{
|
||||
if ((character > 0x60) && (character < 0x7B))
|
||||
character = character - 0x20;
|
||||
return (character);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------
|
||||
FAT_InitFiles
|
||||
Reads the FAT information from the CF card.
|
||||
You need to call this before reading any files.
|
||||
bool return OUT: true if successful.
|
||||
-----------------------------------------------------------------*/
|
||||
bool FAT_InitFiles (void)
|
||||
{
|
||||
int i;
|
||||
int bootSector;
|
||||
BOOT_SEC* bootSec;
|
||||
|
||||
if (!CARD_StartUp())
|
||||
{
|
||||
return (false);
|
||||
}
|
||||
|
||||
// Read first sector of card
|
||||
if (!CARD_ReadSector (0, globalBuffer))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// Check if there is a FAT string, which indicates this is a boot sector
|
||||
if ((globalBuffer[0x36] == 'F') && (globalBuffer[0x37] == 'A') && (globalBuffer[0x38] == 'T'))
|
||||
{
|
||||
bootSector = 0;
|
||||
}
|
||||
// Check for FAT32
|
||||
else if ((globalBuffer[0x52] == 'F') && (globalBuffer[0x53] == 'A') && (globalBuffer[0x54] == 'T'))
|
||||
{
|
||||
bootSector = 0;
|
||||
}
|
||||
else // This is an MBR
|
||||
{
|
||||
// Find first valid partition from MBR
|
||||
// First check for an active partition
|
||||
for (i=0x1BE; (i < 0x1FE) && (globalBuffer[i] != 0x80); i+= 0x10);
|
||||
// If it didn't find an active partition, search for any valid partition
|
||||
if (i == 0x1FE)
|
||||
for (i=0x1BE; (i < 0x1FE) && (globalBuffer[i+0x04] == 0x00); i+= 0x10);
|
||||
|
||||
// Go to first valid partition
|
||||
if ( i != 0x1FE) // Make sure it found a partition
|
||||
{
|
||||
bootSector = globalBuffer[0x8 + i] + (globalBuffer[0x9 + i] << 8) + (globalBuffer[0xA + i] << 16) + ((globalBuffer[0xB + i] << 24) & 0x0F);
|
||||
} else {
|
||||
bootSector = 0; // No partition found, assume this is a MBR free disk
|
||||
}
|
||||
}
|
||||
|
||||
// Read in boot sector
|
||||
bootSec = (BOOT_SEC*) globalBuffer;
|
||||
CARD_ReadSector (bootSector, bootSec);
|
||||
|
||||
// Store required information about the file system
|
||||
if (bootSec->sectorsPerFAT != 0)
|
||||
{
|
||||
discSecPerFAT = bootSec->sectorsPerFAT;
|
||||
}
|
||||
else
|
||||
{
|
||||
discSecPerFAT = bootSec->extBlock.fat32.sectorsPerFAT32;
|
||||
}
|
||||
|
||||
if (bootSec->numSectorsSmall != 0)
|
||||
{
|
||||
discNumSec = bootSec->numSectorsSmall;
|
||||
}
|
||||
else
|
||||
{
|
||||
discNumSec = bootSec->numSectors;
|
||||
}
|
||||
|
||||
discBytePerSec = BYTES_PER_SECTOR; // Sector size is redefined to be 512 bytes
|
||||
discSecPerClus = bootSec->sectorsPerCluster * bootSec->bytesPerSector / BYTES_PER_SECTOR;
|
||||
discBytePerClus = discBytePerSec * discSecPerClus;
|
||||
discFAT = bootSector + bootSec->reservedSectors;
|
||||
|
||||
discRootDir = discFAT + (bootSec->numFATs * discSecPerFAT);
|
||||
discData = discRootDir + ((bootSec->rootEntries * sizeof(DIR_ENT)) / BYTES_PER_SECTOR);
|
||||
|
||||
if ((discNumSec - discData) / bootSec->sectorsPerCluster < 4085)
|
||||
{
|
||||
discFileSystem = FS_FAT12;
|
||||
}
|
||||
else if ((discNumSec - discData) / bootSec->sectorsPerCluster < 65525)
|
||||
{
|
||||
discFileSystem = FS_FAT16;
|
||||
}
|
||||
else
|
||||
{
|
||||
discFileSystem = FS_FAT32;
|
||||
}
|
||||
|
||||
if (discFileSystem != FS_FAT32)
|
||||
{
|
||||
discRootDirClus = FAT16_ROOT_DIR_CLUSTER;
|
||||
}
|
||||
else // Set up for the FAT32 way
|
||||
{
|
||||
discRootDirClus = bootSec->extBlock.fat32.rootClus;
|
||||
// Check if FAT mirroring is enabled
|
||||
if (!(bootSec->extBlock.fat32.extFlags & 0x80))
|
||||
{
|
||||
// Use the active FAT
|
||||
discFAT = discFAT + ( discSecPerFAT * (bootSec->extBlock.fat32.extFlags & 0x0F));
|
||||
}
|
||||
}
|
||||
|
||||
return (true);
|
||||
}
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------
|
||||
getBootFileCluster
|
||||
-----------------------------------------------------------------*/
|
||||
u32 getBootFileCluster (const char* bootName)
|
||||
{
|
||||
DIR_ENT dir;
|
||||
int firstSector = 0;
|
||||
bool notFound = false;
|
||||
bool found = false;
|
||||
// int maxSectors;
|
||||
u32 wrkDirCluster = discRootDirClus;
|
||||
u32 wrkDirSector = 0;
|
||||
int wrkDirOffset = 0;
|
||||
int nameOffset;
|
||||
|
||||
dir.startCluster = CLUSTER_FREE; // default to no file found
|
||||
dir.startClusterHigh = CLUSTER_FREE;
|
||||
|
||||
|
||||
// Check if fat has been initialised
|
||||
if (discBytePerSec == 0)
|
||||
{
|
||||
return (CLUSTER_FREE);
|
||||
}
|
||||
|
||||
char *ptr = (char*)bootName;
|
||||
while (*ptr != '.') ptr++;
|
||||
int namelen = ptr - bootName;
|
||||
|
||||
// maxSectors = (wrkDirCluster == FAT16_ROOT_DIR_CLUSTER ? (discData - discRootDir) : discSecPerClus);
|
||||
// Scan Dir for correct entry
|
||||
firstSector = discRootDir;
|
||||
CARD_ReadSector (firstSector + wrkDirSector, globalBuffer);
|
||||
found = false;
|
||||
notFound = false;
|
||||
wrkDirOffset = -1; // Start at entry zero, Compensating for increment
|
||||
while (!found && !notFound) {
|
||||
wrkDirOffset++;
|
||||
if (wrkDirOffset == BYTES_PER_SECTOR / sizeof (DIR_ENT))
|
||||
{
|
||||
wrkDirOffset = 0;
|
||||
wrkDirSector++;
|
||||
if ((wrkDirSector == discSecPerClus) && (wrkDirCluster != FAT16_ROOT_DIR_CLUSTER))
|
||||
{
|
||||
wrkDirSector = 0;
|
||||
wrkDirCluster = FAT_NextCluster(wrkDirCluster);
|
||||
if (wrkDirCluster == CLUSTER_EOF)
|
||||
{
|
||||
notFound = true;
|
||||
}
|
||||
firstSector = FAT_ClustToSect(wrkDirCluster);
|
||||
}
|
||||
else if ((wrkDirCluster == FAT16_ROOT_DIR_CLUSTER) && (wrkDirSector == (discData - discRootDir)))
|
||||
{
|
||||
notFound = true; // Got to end of root dir
|
||||
}
|
||||
CARD_ReadSector (firstSector + wrkDirSector, globalBuffer);
|
||||
}
|
||||
dir = ((DIR_ENT*) globalBuffer)[wrkDirOffset];
|
||||
found = true;
|
||||
if ((dir.attrib & ATTRIB_DIR) || (dir.attrib & ATTRIB_VOL))
|
||||
{
|
||||
found = false;
|
||||
}
|
||||
if(namelen<8 && dir.name[namelen]!=0x20) found = false;
|
||||
for (nameOffset = 0; nameOffset < namelen && found; nameOffset++)
|
||||
{
|
||||
if (ucase(dir.name[nameOffset]) != bootName[nameOffset])
|
||||
found = false;
|
||||
}
|
||||
for (nameOffset = 0; nameOffset < 3 && found; nameOffset++)
|
||||
{
|
||||
if (ucase(dir.ext[nameOffset]) != bootName[nameOffset+namelen+1])
|
||||
found = false;
|
||||
}
|
||||
if (dir.name[0] == FILE_LAST)
|
||||
{
|
||||
notFound = true;
|
||||
}
|
||||
}
|
||||
|
||||
// If no file is found, return CLUSTER_FREE
|
||||
if (notFound)
|
||||
{
|
||||
return CLUSTER_FREE;
|
||||
}
|
||||
|
||||
return (dir.startCluster | (dir.startClusterHigh << 16));
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------
|
||||
fileRead(buffer, cluster, startOffset, length)
|
||||
-----------------------------------------------------------------*/
|
||||
u32 fileRead (char* buffer, u32 cluster, u32 startOffset, u32 length)
|
||||
{
|
||||
int curByte;
|
||||
int curSect;
|
||||
|
||||
int dataPos = 0;
|
||||
int chunks;
|
||||
int beginBytes;
|
||||
|
||||
if (cluster == CLUSTER_FREE || cluster == CLUSTER_EOF)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Follow cluster list until desired one is found
|
||||
for (chunks = startOffset / discBytePerClus; chunks > 0; chunks--)
|
||||
{
|
||||
cluster = FAT_NextCluster (cluster);
|
||||
}
|
||||
|
||||
// Calculate the sector and byte of the current position,
|
||||
// and store them
|
||||
curSect = (startOffset % discBytePerClus) / BYTES_PER_SECTOR;
|
||||
curByte = startOffset % BYTES_PER_SECTOR;
|
||||
|
||||
// Load sector buffer for new position in file
|
||||
CARD_ReadSector( curSect + FAT_ClustToSect(cluster), globalBuffer);
|
||||
curSect++;
|
||||
|
||||
// Number of bytes needed to read to align with a sector
|
||||
beginBytes = (BYTES_PER_SECTOR < length + curByte ? (BYTES_PER_SECTOR - curByte) : length);
|
||||
|
||||
// Read first part from buffer, to align with sector boundary
|
||||
for (dataPos = 0 ; dataPos < beginBytes; dataPos++)
|
||||
{
|
||||
buffer[dataPos] = globalBuffer[curByte++];
|
||||
}
|
||||
|
||||
// Read in all the 512 byte chunks of the file directly, saving time
|
||||
for ( chunks = ((int)length - beginBytes) / BYTES_PER_SECTOR; chunks > 0;)
|
||||
{
|
||||
int sectorsToRead;
|
||||
|
||||
// Move to the next cluster if necessary
|
||||
if (curSect >= discSecPerClus)
|
||||
{
|
||||
curSect = 0;
|
||||
cluster = FAT_NextCluster (cluster);
|
||||
}
|
||||
|
||||
// Calculate how many sectors to read (read a maximum of discSecPerClus at a time)
|
||||
sectorsToRead = discSecPerClus - curSect;
|
||||
if(chunks < sectorsToRead)
|
||||
sectorsToRead = chunks;
|
||||
|
||||
// Read the sectors
|
||||
CARD_ReadSectors(curSect + FAT_ClustToSect(cluster), sectorsToRead, buffer + dataPos);
|
||||
chunks -= sectorsToRead;
|
||||
curSect += sectorsToRead;
|
||||
dataPos += BYTES_PER_SECTOR * sectorsToRead;
|
||||
}
|
||||
|
||||
// Take care of any bytes left over before end of read
|
||||
if (dataPos < length)
|
||||
{
|
||||
|
||||
// Update the read buffer
|
||||
curByte = 0;
|
||||
if (curSect >= discSecPerClus)
|
||||
{
|
||||
curSect = 0;
|
||||
cluster = FAT_NextCluster (cluster);
|
||||
}
|
||||
CARD_ReadSector( curSect + FAT_ClustToSect( cluster), globalBuffer);
|
||||
|
||||
// Read in last partial chunk
|
||||
for (; dataPos < length; dataPos++)
|
||||
{
|
||||
buffer[dataPos] = globalBuffer[curByte];
|
||||
curByte++;
|
||||
}
|
||||
}
|
||||
|
||||
return dataPos;
|
||||
}
|
46
exploits/minitwlpayload/bootloader/source/fat.h
Normal file
46
exploits/minitwlpayload/bootloader/source/fat.h
Normal file
@ -0,0 +1,46 @@
|
||||
/*-----------------------------------------------------------------
|
||||
fat.h
|
||||
|
||||
NDS MP
|
||||
GBAMP NDS Firmware Hack Version 2.12
|
||||
An NDS aware firmware patch for the GBA Movie Player.
|
||||
By Michael Chisholm (Chishm)
|
||||
|
||||
Filesystem code based on GBAMP_CF.c by Chishm (me).
|
||||
|
||||
License:
|
||||
Copyright (C) 2005 Michael "Chishm" Chisholm
|
||||
|
||||
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 2
|
||||
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, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
If you use this code, please give due credit and email me about your
|
||||
project at chishm@hotmail.com
|
||||
------------------------------------------------------------------*/
|
||||
|
||||
#ifndef FAT_H
|
||||
#define FAT_H
|
||||
|
||||
#include <nds/ndstypes.h>
|
||||
|
||||
#define CLUSTER_FREE 0x00000000
|
||||
#define CLUSTER_EOF 0x0FFFFFFF
|
||||
#define CLUSTER_FIRST 0x00000002
|
||||
|
||||
bool FAT_InitFiles (void);
|
||||
u32 getBootFileCluster (const char* bootName);
|
||||
u32 fileRead (char* buffer, u32 cluster, u32 startOffset, u32 length);
|
||||
u32 FAT_ClustToSect (u32 cluster);
|
||||
|
||||
#endif // FAT_H
|
132
exploits/minitwlpayload/bootloader/source/load_crt0.s
Normal file
132
exploits/minitwlpayload/bootloader/source/load_crt0.s
Normal file
@ -0,0 +1,132 @@
|
||||
/*-----------------------------------------------------------------
|
||||
|
||||
Copyright (C) 2005 Michael "Chishm" Chisholm
|
||||
|
||||
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 2
|
||||
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, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
If you use this code, please give due credit and email me about your
|
||||
project at chishm@hotmail.com
|
||||
------------------------------------------------------------------*/
|
||||
|
||||
@---------------------------------------------------------------------------------
|
||||
.section ".init"
|
||||
.global _start
|
||||
.global argStart
|
||||
.global argSize
|
||||
@---------------------------------------------------------------------------------
|
||||
.align 4
|
||||
.arm
|
||||
@---------------------------------------------------------------------------------
|
||||
_start:
|
||||
@---------------------------------------------------------------------------------
|
||||
b startUp
|
||||
|
||||
@ Used for passing arguments to the loaded app
|
||||
argStart:
|
||||
.word _end - _start
|
||||
argSize:
|
||||
.word 0x00000000
|
||||
|
||||
startUp:
|
||||
mov r0, #0x04000000
|
||||
mov r1, #0
|
||||
str r1, [r0,#0x208] @ REG_IME
|
||||
str r1, [r0,#0x210] @ REG_IE
|
||||
str r1, [r0,#0x218] @ REG_AUXIE
|
||||
|
||||
ldr r0, =0x02FFFDFB
|
||||
mov r1, #42
|
||||
strb r1, [r0]
|
||||
|
||||
mov r0, #0x12 @ Switch to IRQ Mode
|
||||
msr cpsr, r0
|
||||
ldr sp, =__sp_irq @ Set IRQ stack
|
||||
|
||||
mov r0, #0x13 @ Switch to SVC Mode
|
||||
msr cpsr, r0
|
||||
ldr sp, =__sp_svc @ Set SVC stack
|
||||
|
||||
mov r0, #0x1F @ Switch to System Mode
|
||||
msr cpsr, r0
|
||||
ldr sp, =__sp_usr @ Set user stack
|
||||
|
||||
ldr r0, =__bss_start @ Clear BSS section to 0x00
|
||||
ldr r1, =__bss_end
|
||||
sub r1, r1, r0
|
||||
bl ClearMem
|
||||
|
||||
mov r0, #0 @ int argc
|
||||
mov r1, #0 @ char *argv[]
|
||||
ldr r3, =main
|
||||
bl _blx_r3_stub @ jump to user code
|
||||
1: b 1b
|
||||
|
||||
@---------------------------------------------------------------------------------
|
||||
_blx_r3_stub:
|
||||
@---------------------------------------------------------------------------------
|
||||
bx r3
|
||||
|
||||
@---------------------------------------------------------------------------------
|
||||
@ Clear memory to 0x00 if length != 0
|
||||
@ r0 = Start Address
|
||||
@ r1 = Length
|
||||
@---------------------------------------------------------------------------------
|
||||
ClearMem:
|
||||
@---------------------------------------------------------------------------------
|
||||
mov r2, #3 @ Round down to nearest word boundary
|
||||
add r1, r1, r2 @ Shouldn't be needed
|
||||
bics r1, r1, r2 @ Clear 2 LSB (and set Z)
|
||||
bxeq lr @ Quit if copy size is 0
|
||||
|
||||
mov r2, #0
|
||||
ClrLoop:
|
||||
stmia r0!, {r2}
|
||||
subs r1, r1, #4
|
||||
bne ClrLoop
|
||||
bx lr
|
||||
|
||||
@---------------------------------------------------------------------------------
|
||||
@ Copy memory if length != 0
|
||||
@ r1 = Source Address
|
||||
@ r2 = Dest Address
|
||||
@ r4 = Dest Address + Length
|
||||
@---------------------------------------------------------------------------------
|
||||
CopyMemCheck:
|
||||
@---------------------------------------------------------------------------------
|
||||
sub r3, r4, r2 @ Is there any data to copy?
|
||||
@---------------------------------------------------------------------------------
|
||||
@ Copy memory
|
||||
@ r1 = Source Address
|
||||
@ r2 = Dest Address
|
||||
@ r3 = Length
|
||||
@---------------------------------------------------------------------------------
|
||||
CopyMem:
|
||||
@---------------------------------------------------------------------------------
|
||||
mov r0, #3 @ These commands are used in cases where
|
||||
add r3, r3, r0 @ the length is not a multiple of 4,
|
||||
bics r3, r3, r0 @ even though it should be.
|
||||
bxeq lr @ Length is zero, so exit
|
||||
CIDLoop:
|
||||
ldmia r1!, {r0}
|
||||
stmia r2!, {r0}
|
||||
subs r3, r3, #4
|
||||
bne CIDLoop
|
||||
bx lr
|
||||
|
||||
@---------------------------------------------------------------------------------
|
||||
.align
|
||||
.pool
|
||||
.end
|
||||
@---------------------------------------------------------------------------------
|
315
exploits/minitwlpayload/bootloader/source/sdmmc.c
Normal file
315
exploits/minitwlpayload/bootloader/source/sdmmc.c
Normal file
@ -0,0 +1,315 @@
|
||||
#include <nds.h>
|
||||
#include "sdmmc.h"
|
||||
|
||||
|
||||
static struct mmcdevice deviceSD;
|
||||
|
||||
/*mmcdevice *getMMCDevice(int drive) {
|
||||
if(drive==0) return &deviceNAND;
|
||||
return &deviceSD;
|
||||
}
|
||||
*/
|
||||
//---------------------------------------------------------------------------------
|
||||
int __attribute__((noinline)) geterror(struct mmcdevice *ctx) {
|
||||
//---------------------------------------------------------------------------------
|
||||
//if(ctx->error == 0x4) return -1;
|
||||
//else return 0;
|
||||
return (ctx->error << 29) >> 31;
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
void __attribute__((noinline)) setTarget(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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
void __attribute__((noinline)) sdmmc_send_command(struct mmcdevice *ctx, u32 cmd, u32 args) {
|
||||
//---------------------------------------------------------------------------------
|
||||
int i;
|
||||
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);
|
||||
|
||||
#ifdef DATA32_SUPPORT
|
||||
if (readdata)
|
||||
sdmmc_mask16(REG_SDDATACTL32, 0x1000, 0x800);
|
||||
if (writedata)
|
||||
sdmmc_mask16(REG_SDDATACTL32, 0x800, 0x1000);
|
||||
#else
|
||||
sdmmc_mask16(REG_SDDATACTL32,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;
|
||||
#ifdef DATA32_SUPPORT
|
||||
u32 *dataPtr32 = (u32*)ctx->data;
|
||||
#endif
|
||||
|
||||
bool useBuf = ( 0 != 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(i = 0; i<0x200; i+=4)
|
||||
*dataPtr32++ = sdmmc_read32(REG_SDFIFO32);
|
||||
} else {
|
||||
#endif
|
||||
for(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 (i = 0; i<0x200; i+=4)
|
||||
sdmmc_write32(REG_SDFIFO32,*dataPtr32++);
|
||||
#else
|
||||
for (i = 0; i<0x200; i+=2)
|
||||
sdmmc_write16(REG_SDFIFO,*dataPtr++);
|
||||
#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 sdmmc_cardinserted() {
|
||||
//---------------------------------------------------------------------------------
|
||||
return 1; //sdmmc_cardready;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
void sdmmc_controller_init() {
|
||||
//---------------------------------------------------------------------------------
|
||||
deviceSD.isSDHC = 0;
|
||||
deviceSD.SDOPT = 0;
|
||||
deviceSD.res = 0;
|
||||
deviceSD.initarg = 0;
|
||||
deviceSD.clk = 0x80;
|
||||
deviceSD.devicenumber = 0;
|
||||
|
||||
*(vu16*)(SDMMC_BASE + REG_SDDATACTL32) &= 0xF7FFu;
|
||||
*(vu16*)(SDMMC_BASE + REG_SDDATACTL32) &= 0xEFFFu;
|
||||
*(vu16*)(SDMMC_BASE + REG_SDDATACTL32) |= 0x402u;
|
||||
|
||||
*(vu16*)(SDMMC_BASE + REG_SDDATACTL) = (*(vu16*)(SDMMC_BASE + 0xd8) & 0xFFDD) | 2;
|
||||
|
||||
#ifdef DATA32_SUPPORT
|
||||
*(vu16*)(SDMMC_BASE + REG_SDDATACTL32) &= 0xFFFFu;
|
||||
*(vu16*)(SDMMC_BASE + REG_SDDATACTL) &= 0xFFDFu;
|
||||
*(vu16*)(SDMMC_BASE + REG_SDBLKLEN32) = 512;
|
||||
#else
|
||||
*(vu16*)(SDMMC_BASE + REG_SDDATACTL32) &= 0xFFFDu;
|
||||
*(vu16*)(SDMMC_BASE + REG_SDDATACTL) &= 0xFFDDu;
|
||||
*(vu16*)(SDMMC_BASE + REG_SDBLKLEN32) = 0;
|
||||
#endif
|
||||
*(vu16*)(SDMMC_BASE + REG_SDBLKCOUNT32) = 1; //SDBLKCOUNT32
|
||||
*(vu16*)(SDMMC_BASE + REG_SDRESET) &= 0xFFFEu; //SDRESET
|
||||
*(vu16*)(SDMMC_BASE + REG_SDRESET) |= 1u; //SDRESET
|
||||
*(vu16*)(SDMMC_BASE + REG_SDIRMASK0) |= TMIO_MASK_ALL;
|
||||
*(vu16*)(SDMMC_BASE + REG_SDIRMASK1) |= TMIO_MASK_ALL>>16;
|
||||
*(vu16*)(SDMMC_BASE + 0x0fc) |= 0xDBu; //SDCTL_RESERVED7
|
||||
*(vu16*)(SDMMC_BASE + 0x0fe) |= 0xDBu; //SDCTL_RESERVED8
|
||||
*(vu16*)(SDMMC_BASE + REG_SDPORTSEL) &= 0xFFFCu; //SDPORTSEL
|
||||
#ifdef DATA32_SUPPORT
|
||||
*(vu16*)(SDMMC_BASE + REG_SDCLKCTL) = 0x20;
|
||||
*(vu16*)(SDMMC_BASE + REG_SDOPT) = 0x40EE;
|
||||
#else
|
||||
*(vu16*)(SDMMC_BASE + REG_SDCLKCTL) = 0x40; //Nintendo sets this to 0x20
|
||||
*(vu16*)(SDMMC_BASE + REG_SDOPT) = 0x40EB; //Nintendo sets this to 0x40EE
|
||||
#endif
|
||||
*(vu16*)(SDMMC_BASE + REG_SDPORTSEL) &= 0xFFFCu; ////SDPORTSEL
|
||||
*(vu16*)(SDMMC_BASE + REG_SDBLKLEN) = 512; //SDBLKLEN
|
||||
*(vu16*)(SDMMC_BASE + REG_SDSTOP) = 0; //SDSTOP
|
||||
|
||||
setTarget(&deviceSD);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
static u32 calcSDSize(u8* csd, int type) {
|
||||
//---------------------------------------------------------------------------------
|
||||
u32 result = 0;
|
||||
if (type == -1) type = csd[14] >> 6;
|
||||
switch (type) {
|
||||
case 0:
|
||||
{
|
||||
u32 block_len = csd[9] & 0xf;
|
||||
block_len = 1 << block_len;
|
||||
u32 mult = (csd[4] >> 7) | ((csd[5] & 3) << 1);
|
||||
mult = 1 << (mult + 2);
|
||||
result = csd[8] & 3;
|
||||
result = (result << 8) | csd[7];
|
||||
result = (result << 2) | (csd[6] >> 6);
|
||||
result = (result + 1) * mult * block_len / 512;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
result = csd[7] & 0x3f;
|
||||
result = (result << 8) | csd[6];
|
||||
result = (result << 8) | csd[5];
|
||||
result = (result + 1) * 1024;
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
int sdmmc_sdcard_init() {
|
||||
//---------------------------------------------------------------------------------
|
||||
setTarget(&deviceSD);
|
||||
swiDelay(0xF000);
|
||||
sdmmc_send_command(&deviceSD,0,0);
|
||||
sdmmc_send_command(&deviceSD,0x10408,0x1AA);
|
||||
//u32 temp = (deviceSD.ret[0] == 0x1AA) << 0x1E;
|
||||
u32 temp = (deviceSD.error & 0x1) << 0x1E;
|
||||
|
||||
//int count = 0;
|
||||
u32 temp2 = 0;
|
||||
do {
|
||||
do {
|
||||
sdmmc_send_command(&deviceSD,0x10437,deviceSD.initarg << 0x10);
|
||||
sdmmc_send_command(&deviceSD,0x10769,0x00FF8000 | temp);
|
||||
temp2 = 1;
|
||||
} while ( !(deviceSD.error & 1) );
|
||||
|
||||
} while((deviceSD.ret[0] & 0x80000000) == 0);
|
||||
//do
|
||||
//{
|
||||
// sdmmc_send_command(&deviceSD,0x10437,deviceSD.initarg << 0x10);
|
||||
// sdmmc_send_command(&deviceSD,0x10769,0x00FF8000 | temp);
|
||||
//
|
||||
//}
|
||||
//while(!(deviceSD.ret[0] & 0x80000000));
|
||||
|
||||
if(!((deviceSD.ret[0] >> 30) & 1) || !temp)
|
||||
temp2 = 0;
|
||||
|
||||
deviceSD.isSDHC = temp2;
|
||||
//deviceSD.isSDHC = (deviceSD.ret[0] & 0x40000000);
|
||||
|
||||
sdmmc_send_command(&deviceSD,0x10602,0);
|
||||
if (deviceSD.error & 0x4) return -1;
|
||||
|
||||
sdmmc_send_command(&deviceSD,0x10403,0);
|
||||
if (deviceSD.error & 0x4) return -1;
|
||||
deviceSD.initarg = deviceSD.ret[0] >> 0x10;
|
||||
|
||||
sdmmc_send_command(&deviceSD,0x10609,deviceSD.initarg << 0x10);
|
||||
if (deviceSD.error & 0x4) return -1;
|
||||
|
||||
deviceSD.total_size = calcSDSize((u8*)&deviceSD.ret[0],-1);
|
||||
deviceSD.clk = 1;
|
||||
setckl(1);
|
||||
|
||||
sdmmc_send_command(&deviceSD,0x10507,deviceSD.initarg << 0x10);
|
||||
if (deviceSD.error & 0x4) return -1;
|
||||
|
||||
sdmmc_send_command(&deviceSD,0x10437,deviceSD.initarg << 0x10);
|
||||
if (deviceSD.error & 0x4) return -1;
|
||||
|
||||
deviceSD.SDOPT = 1;
|
||||
sdmmc_send_command(&deviceSD,0x10446,0x2);
|
||||
if (deviceSD.error & 0x4) return -1;
|
||||
|
||||
sdmmc_send_command(&deviceSD,0x1040D,deviceSD.initarg << 0x10);
|
||||
if (deviceSD.error & 0x4) return -1;
|
||||
|
||||
sdmmc_send_command(&deviceSD,0x10410,0x200);
|
||||
if (deviceSD.error & 0x4) return -1;
|
||||
deviceSD.clk |= 0x200;
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
int __attribute__((noinline)) sdmmc_sdcard_readsectors(u32 sector_no, u32 numsectors, void *out) {
|
||||
if (deviceSD.isSDHC == 0)
|
||||
sector_no <<= 9;
|
||||
setTarget(&deviceSD);
|
||||
sdmmc_write16(REG_SDSTOP,0x100);
|
||||
|
||||
#ifdef DATA32_SUPPORT
|
||||
sdmmc_write16(REG_SDBLKCOUNT32,numsectors);
|
||||
sdmmc_write16(REG_SDBLKLEN32,0x200);
|
||||
#endif
|
||||
|
||||
sdmmc_write16(REG_SDBLKCOUNT,numsectors);
|
||||
deviceSD.data = out;
|
||||
deviceSD.size = numsectors << 9;
|
||||
sdmmc_send_command(&deviceSD,0x33C12,sector_no);
|
||||
return geterror(&deviceSD);
|
||||
}
|
175
exploits/minitwlpayload/bootloader/source/sdmmc.h
Normal file
175
exploits/minitwlpayload/bootloader/source/sdmmc.h
Normal file
@ -0,0 +1,175 @@
|
||||
#ifndef __SDMMC_H__
|
||||
#define __SDMMC_H__
|
||||
|
||||
#include <nds/ndstypes.h>
|
||||
|
||||
#define SDMMC_BASE 0x04004800
|
||||
|
||||
|
||||
#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_SDRESP 0x0c
|
||||
#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_SDSTATUS0 0x1c
|
||||
#define REG_SDSTATUS1 0x1e
|
||||
|
||||
#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_SDDATACTL 0xd8
|
||||
#define REG_SDRESET 0xe0
|
||||
#define REG_SDPROTECTED 0xf6 //bit 0 determines if sd is protected or not?
|
||||
|
||||
#define REG_SDDATACTL32 0x100
|
||||
#define REG_SDBLKLEN32 0x104
|
||||
#define REG_SDBLKCOUNT32 0x108
|
||||
#define REG_SDFIFO32 0x10C
|
||||
|
||||
#define REG_CLK_AND_WAIT_CTL 0x138
|
||||
#define REG_RESET_SDIO 0x1e0
|
||||
//The below defines are from linux kernel drivers/mmc tmio_mmc.h.
|
||||
/* Definitions for values the CTRL_STATUS register can take. */
|
||||
#define TMIO_STAT0_CMDRESPEND 0x0001
|
||||
#define TMIO_STAT0_DATAEND 0x0004
|
||||
#define TMIO_STAT0_CARD_REMOVE 0x0008
|
||||
#define TMIO_STAT0_CARD_INSERT 0x0010
|
||||
#define TMIO_STAT0_SIGSTATE 0x0020
|
||||
#define TMIO_STAT0_WRPROTECT 0x0080
|
||||
#define TMIO_STAT0_CARD_REMOVE_A 0x0100
|
||||
#define TMIO_STAT0_CARD_INSERT_A 0x0200
|
||||
#define TMIO_STAT0_SIGSTATE_A 0x0400
|
||||
|
||||
#define TMIO_STAT1_CMD_IDX_ERR 0x0001
|
||||
#define TMIO_STAT1_CRCFAIL 0x0002
|
||||
#define TMIO_STAT1_STOPBIT_ERR 0x0004
|
||||
#define TMIO_STAT1_DATATIMEOUT 0x0008
|
||||
#define TMIO_STAT1_RXOVERFLOW 0x0010
|
||||
#define TMIO_STAT1_TXUNDERRUN 0x0020
|
||||
#define TMIO_STAT1_CMDTIMEOUT 0x0040
|
||||
#define TMIO_STAT1_RXRDY 0x0100
|
||||
#define TMIO_STAT1_TXRQ 0x0200
|
||||
#define TMIO_STAT1_ILL_FUNC 0x2000
|
||||
#define TMIO_STAT1_CMD_BUSY 0x4000
|
||||
#define TMIO_STAT1_ILL_ACCESS 0x8000
|
||||
|
||||
//Comes from TWLSDK mongoose.tef DWARF info
|
||||
#define SDMC_NORMAL 0x00000000
|
||||
#define SDMC_ERR_COMMAND 0x00000001
|
||||
#define SDMC_ERR_CRC 0x00000002
|
||||
#define SDMC_ERR_END 0x00000004
|
||||
#define SDMC_ERR_TIMEOUT 0x00000008
|
||||
#define SDMC_ERR_FIFO_OVF 0x00000010
|
||||
#define SDMC_ERR_FIFO_UDF 0x00000020
|
||||
#define SDMC_ERR_WP 0x00000040
|
||||
#define SDMC_ERR_ABORT 0x00000080
|
||||
#define SDMC_ERR_FPGA_TIMEOUT 0x00000100
|
||||
#define SDMC_ERR_PARAM 0x00000200
|
||||
#define SDMC_ERR_R1_STATUS 0x00000800
|
||||
#define SDMC_ERR_NUM_WR_SECTORS 0x00001000
|
||||
#define SDMC_ERR_RESET 0x00002000
|
||||
#define SDMC_ERR_ILA 0x00004000
|
||||
#define SDMC_ERR_INFO_DETECT 0x00008000
|
||||
|
||||
#define SDMC_STAT_ERR_UNKNOWN 0x00080000
|
||||
#define SDMC_STAT_ERR_CC 0x00100000
|
||||
#define SDMC_STAT_ERR_ECC_FAILED 0x00200000
|
||||
#define SDMC_STAT_ERR_CRC 0x00800000
|
||||
#define SDMC_STAT_ERR_OTHER 0xf9c70008
|
||||
|
||||
#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)
|
||||
|
||||
#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;
|
||||
|
||||
void sdmmc_controller_init();
|
||||
void sdmmc_initirq();
|
||||
int sdmmc_cardinserted();
|
||||
|
||||
int sdmmc_sdcard_init();
|
||||
int sdmmc_sdcard_readsectors(u32 sector_no, u32 numsectors, void *out);
|
||||
int sdmmc_sdcard_writesectors(u32 sector_no, u32 numsectors, void *in);
|
||||
|
||||
extern u32 sdmmc_cid[];
|
||||
extern int sdmmc_curdevice;
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
static inline u16 sdmmc_read16(u16 reg) {
|
||||
//---------------------------------------------------------------------------------
|
||||
return *(vu16*)(SDMMC_BASE + reg);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
static inline void sdmmc_write16(u16 reg, u16 val) {
|
||||
//---------------------------------------------------------------------------------
|
||||
*(vu16*)(SDMMC_BASE + reg) = val;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
static inline u32 sdmmc_read32(u16 reg) {
|
||||
//---------------------------------------------------------------------------------
|
||||
return *(vu32*)(SDMMC_BASE + reg);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
static inline void sdmmc_write32(u16 reg, u32 val) {
|
||||
//---------------------------------------------------------------------------------
|
||||
*(vu32*)(SDMMC_BASE + reg) = val;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
static inline void sdmmc_mask16(u16 reg, u16 clear, u16 set) {
|
||||
//---------------------------------------------------------------------------------
|
||||
u16 val = sdmmc_read16(reg);
|
||||
val &= ~clear;
|
||||
val |= set;
|
||||
sdmmc_write16(reg, val);
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
static inline void setckl(u32 data) {
|
||||
//---------------------------------------------------------------------------------
|
||||
sdmmc_mask16(REG_SDCLKCTL, 0x100, 0);
|
||||
sdmmc_mask16(REG_SDCLKCTL, 0x2FF, data & 0x2FF);
|
||||
sdmmc_mask16(REG_SDCLKCTL, 0x0, 0x100);
|
||||
}
|
||||
|
||||
#endif
|
142
exploits/minitwlpayload/source/common.h
Normal file
142
exploits/minitwlpayload/source/common.h
Normal file
@ -0,0 +1,142 @@
|
||||
#pragma once
|
||||
#include <nds.h>
|
||||
|
||||
#define NDSHEADER ((tNDSHeader *)0x02FFFE00)
|
||||
#define TWLNDSHEADER ((tTWLNDSHeader *)0x02FFE000)
|
||||
#define BOOTFLAG *((vu8*)0x02FFFDFB)
|
||||
|
||||
#define BOOTLDR_NDS 0x02300000
|
||||
#define BOOTLDR_NDSHEADER ((tNDSHeader *)BOOTLDR_NDS)
|
||||
#define BOOTLDR_TWLNDSHEADER ((tTWLNDSHeader *)BOOTLDR_NDS)
|
||||
|
||||
typedef struct sTWLNDSHeader {
|
||||
char gameTitle[12]; //!< 12 characters for the game title.
|
||||
char gameCode[4]; //!< 4 characters for the game code.
|
||||
char makercode[2]; //!< identifies the (commercial) developer.
|
||||
u8 unitCode; //!< identifies the required hardware.
|
||||
u8 deviceType; //!< type of device in the game card
|
||||
u8 deviceSize; //!< capacity of the device (1 << n Mbit)
|
||||
u8 reserved1[9];
|
||||
u8 romversion; //!< version of the ROM.
|
||||
u8 flags; //!< bit 2: auto-boot flag.
|
||||
|
||||
u32 arm9romOffset; //!< offset of the arm9 binary in the nds file.
|
||||
u32 arm9executeAddress; //!< adress that should be executed after the binary has been copied.
|
||||
u32 arm9destination; //!< destination address to where the arm9 binary should be copied.
|
||||
u32 arm9binarySize; //!< size of the arm9 binary.
|
||||
|
||||
u32 arm7romOffset; //!< offset of the arm7 binary in the nds file.
|
||||
u32 arm7executeAddress; //!< adress that should be executed after the binary has been copied.
|
||||
u32 arm7destination; //!< destination address to where the arm7 binary should be copied.
|
||||
u32 arm7binarySize; //!< size of the arm7 binary.
|
||||
|
||||
u32 filenameOffset; //!< File Name Table (FNT) offset.
|
||||
u32 filenameSize; //!< File Name Table (FNT) size.
|
||||
u32 fatOffset; //!< File Allocation Table (FAT) offset.
|
||||
u32 fatSize; //!< File Allocation Table (FAT) size.
|
||||
|
||||
u32 arm9overlaySource; //!< File arm9 overlay offset.
|
||||
u32 arm9overlaySize; //!< File arm9 overlay size.
|
||||
u32 arm7overlaySource; //!< File arm7 overlay offset.
|
||||
u32 arm7overlaySize; //!< File arm7 overlay size.
|
||||
|
||||
u32 cardControl13; //!< Port 40001A4h setting for normal commands (used in modes 1 and 3)
|
||||
u32 cardControlBF; //!< Port 40001A4h setting for KEY1 commands (used in mode 2)
|
||||
u32 bannerOffset; //!< offset to the banner with icon and titles etc.
|
||||
|
||||
u16 secureCRC16; //!< Secure Area Checksum, CRC-16.
|
||||
|
||||
u16 readTimeout; //!< Secure Area Loading Timeout.
|
||||
|
||||
u32 unknownRAM1; //!< ARM9 Auto Load List RAM Address (?)
|
||||
u32 unknownRAM2; //!< ARM7 Auto Load List RAM Address (?)
|
||||
|
||||
u32 bfPrime1; //!< Secure Area Disable part 1.
|
||||
u32 bfPrime2; //!< Secure Area Disable part 2.
|
||||
u32 romSize; //!< total size of the ROM.
|
||||
|
||||
u32 headerSize; //!< ROM header size.
|
||||
u32 zeros88[14];
|
||||
u8 gbaLogo[156]; //!< Nintendo logo needed for booting the game.
|
||||
u16 logoCRC16; //!< Nintendo Logo Checksum, CRC-16.
|
||||
u16 headerCRC16; //!< header checksum, CRC-16.
|
||||
|
||||
u32 debugRomSource; //!< debug ROM offset.
|
||||
u32 debugRomSize; //!< debug size.
|
||||
u32 debugRomDestination; //!< debug RAM destination.
|
||||
u32 offset_0x16C; //reserved?
|
||||
u8 debug_reserved[0x10];
|
||||
|
||||
u8 config_settings[52];
|
||||
u32 access_control;//0x1b4
|
||||
u32 scfg_ext_mask;
|
||||
u32 reserved_1bc;
|
||||
|
||||
u32 arm9iromOffset;
|
||||
u32 arm9ireserved;
|
||||
u32 arm9idestination;
|
||||
u32 arm9ibinarySize;
|
||||
|
||||
u32 arm7iromOffset;
|
||||
u32 arm7ititleparams;
|
||||
u32 arm7idestination;
|
||||
u32 arm7ibinarySize;
|
||||
|
||||
u32 digest_ntr_offset;
|
||||
u32 digest_ntr_size;
|
||||
u32 digest_twl_offset;
|
||||
u32 digest_twl_size;
|
||||
|
||||
u32 digest_sector_hashtable_offset;
|
||||
u32 digest_sector_hashtable_size;
|
||||
u32 digest_block_hashtable_offset;
|
||||
u32 digest_block_hashtable_size;
|
||||
|
||||
u32 digest_sector_size;
|
||||
u32 digest_block_sectorcount;
|
||||
|
||||
u8 reserved_208[24];
|
||||
|
||||
u32 modcrypt1_offset;
|
||||
u32 modcrypt1_size;
|
||||
u32 modcrypt2_offset;
|
||||
u32 modcrypt2_size;
|
||||
|
||||
u64 titleid;
|
||||
u32 publicsav_size;
|
||||
u32 privatesav_size;
|
||||
|
||||
u8 reserved_238[192];
|
||||
|
||||
u8 arm9_sec_hmac[20];//sha1 hmac /w encrypted secure area
|
||||
u8 arm7_hmac[20];
|
||||
u8 digest_master_hmac[20];
|
||||
u8 banner_hmac[20];
|
||||
u8 arm9i_hmac[20];
|
||||
u8 arm7i_hmac[20];
|
||||
|
||||
u8 reserved_378[40];
|
||||
u8 arm9_unsec_hmac[20];//without secure area
|
||||
|
||||
u8 reserved_3b4[2636];
|
||||
u8 reserved_debugargs[0x180];
|
||||
|
||||
u8 signature[0x80];
|
||||
|
||||
} __attribute__ ((__packed__)) tTWLNDSHeader;
|
||||
|
||||
typedef unsigned int size_t;
|
||||
void* memset(void* buffer, int val, size_t len);
|
||||
void* memcpy(void* a, const void* b, size_t len);
|
||||
void* memcpy16(void* a, const void* b, size_t len);
|
||||
void memset_addrs(void* start, void* end);
|
||||
void memcpy_addrs(void* start, void* end, void* dst);
|
||||
void memcpy16_addrs(void* start, void* end, void* dst);
|
||||
void* memcpy_arm9(u32 *a, u32 *b, size_t len);
|
||||
void* memset_arm9(u32 *buffer, int val, size_t len);
|
||||
|
||||
void memset_arm7(u32 *buffer, int val, size_t len);
|
||||
void memcpy_arm7(u32 *a, u32 *b, size_t len);
|
||||
void memcpy8_arm7(u8 *a, u8 *b, size_t len);
|
||||
void memset_addrs_arm7(u32 start, u32 end);
|
||||
void memset8_arm7(u8 *buffer, int val, size_t len);
|
126
exploits/minitwlpayload/source/exploit.c
Normal file
126
exploits/minitwlpayload/source/exploit.c
Normal file
@ -0,0 +1,126 @@
|
||||
#include "common.h"
|
||||
#include "ndsloader_bin.h"
|
||||
|
||||
static void resetArm9();
|
||||
static void bootstrapArm7();
|
||||
static void bootstrapArm7DSiSync();
|
||||
static int sendipcmsg(u32 channel, u32 data);
|
||||
|
||||
static inline void debug_color(int r, int g, int b)
|
||||
{
|
||||
u16 clr = RGB15(r,g,b);
|
||||
*(vu32*)0x05000000 = clr;
|
||||
*(vu32*)0x05000400 = clr;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
debug_color(31,15,0); // orange
|
||||
|
||||
resetArm9();
|
||||
bootstrapArm7();
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
void resetArm9()
|
||||
{
|
||||
int i, reg;
|
||||
|
||||
for(i=0; i<4; i++)
|
||||
{
|
||||
DMA_CR(i) = 0;//Reset DMA.
|
||||
DMA_SRC(i) = 0;
|
||||
DMA_DEST(i) = 0;
|
||||
TIMER_CR(i) = 0;//Reset timers.
|
||||
TIMER_DATA(i) = 0;
|
||||
for(reg=0; reg<0x1c; reg+=4)*((u32*)(0x04004104 + ((i*0x1c)+reg))) = 0;//Reset NDMA.
|
||||
}
|
||||
|
||||
VRAM_CR = 0;
|
||||
VRAM_EFG_CR = 0;
|
||||
VRAM_H_CR = 0;
|
||||
VRAM_I_CR = 0;
|
||||
|
||||
REG_POWERCNT = 0x820f;
|
||||
WRAM_CR = 0x03;
|
||||
REG_EXMEMCNT = 0xE880;
|
||||
}
|
||||
|
||||
int sendipcmsg(u32 chan, u32 data)
|
||||
{
|
||||
u32 dat = (chan & 0x1f) | (data<<6);
|
||||
|
||||
if(REG_IPC_FIFO_CR & (IPC_FIFO_SEND_FULL | IPC_FIFO_ERROR))return -1;
|
||||
REG_IPC_FIFO_TX = dat;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void bootstrapArm7()
|
||||
{
|
||||
REG_IME = 0;
|
||||
REG_IE = 0;
|
||||
REG_IF = ~0;
|
||||
|
||||
BOOTFLAG = 0;
|
||||
*((vu32*)0x02FFFE04) = (u32)0xE59FF018;
|
||||
*((vu32*)0x02FFFE24) = (u32)0x02FFFE04;
|
||||
NDSHEADER->arm7executeAddress = 0x06000000;
|
||||
|
||||
while(sendipcmsg(12, 0x10<<8)<0);
|
||||
debug_color(31,31,0); // yellow
|
||||
|
||||
bootstrapArm7DSiSync();
|
||||
while(IPC_GetSync()!=1);
|
||||
|
||||
debug_color(31,0,31); // magenta
|
||||
|
||||
VRAM_C_CR = VRAM_ENABLE | VRAM_C_LCD;
|
||||
memcpy16(VRAM_C, ndsloader_bin, ndsloader_bin_size);
|
||||
VRAM_C_CR = VRAM_ENABLE | VRAM_C_ARM7_0x06000000;
|
||||
|
||||
debug_color(0,15,0); // dark green
|
||||
|
||||
IPC_SendSync(1);
|
||||
|
||||
while(IPC_GetSync()==1);
|
||||
|
||||
IPC_SendSync(0);
|
||||
|
||||
debug_color(0,31,0); // green
|
||||
while (BOOTFLAG != 42);
|
||||
debug_color(15,31,15); // bright green
|
||||
|
||||
swiSoftReset();
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
void bootstrapArm7DSiSync()
|
||||
{
|
||||
vu16 *sync = (vu16*)0x02fffc24;
|
||||
vu16 temp;
|
||||
|
||||
sync[2] = 4;
|
||||
temp = sync[1];
|
||||
while (sync[1]==temp);
|
||||
sync[0]++;
|
||||
|
||||
sync[2] = 3; //When this is 3, Arm7 TWL SDK bootstub skips 7i bin loading, otherwise when 2 it loads the 7i bin.
|
||||
temp = sync[1];
|
||||
while (sync[1]==temp);
|
||||
sync[0]++;
|
||||
}
|
||||
|
||||
void* memcpy16(void* a, const void* b, size_t len)
|
||||
{
|
||||
vu16 *bufa = (vu16*)a;
|
||||
vu16 *bufb = (vu16*)b;
|
||||
while(len>0)
|
||||
{
|
||||
*bufa = *bufb;
|
||||
bufa++;
|
||||
bufb++;
|
||||
len-=2;
|
||||
}
|
||||
return a;
|
||||
}
|
56
exploits/minitwlpayload/source/start.s
Normal file
56
exploits/minitwlpayload/source/start.s
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
mini - a Free Software replacement for the Nintendo/BroadOn IOS.
|
||||
|
||||
ELF loader: system startup
|
||||
|
||||
Copyright (C) 2008, 2009 Hector Martin "marcan" <marcan@marcansoft.com>
|
||||
|
||||
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, version 2.
|
||||
|
||||
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, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
*/
|
||||
|
||||
//Modified for nzonehtmlhaxx by yellowstar6.
|
||||
//Stripped down by fincs.
|
||||
.arm
|
||||
|
||||
.arch armv5te
|
||||
.fpu softvfp
|
||||
|
||||
.section .init
|
||||
.global _start
|
||||
_start:
|
||||
@ clear BSS
|
||||
ldr r1, =__bss_start
|
||||
ldr r2, =__bss_end
|
||||
mov r3, #0
|
||||
bss_loop:
|
||||
@ check for the end
|
||||
cmp r1, r2
|
||||
beq done_bss
|
||||
@ clear the word and move on
|
||||
str r3, [r1]
|
||||
add r1, r1, #4
|
||||
b bss_loop
|
||||
|
||||
done_bss:
|
||||
ldr r0, =0x0000FFFF
|
||||
mcr p15, 0, r0, c5, c0, 0
|
||||
mcr p15, 0, r0, c5, c0, 1
|
||||
ldr r0, =0x33333333
|
||||
mcr p15, 0, r0, c5, c0, 2
|
||||
mcr p15, 0, r0, c5, c0, 3
|
||||
|
||||
@ take the plunge
|
||||
bl main
|
||||
1: b 1b @ Added by yellowstar6. This code should never be executed.
|
52
exploits/minitwlpayload/source/swiSoftReset.s
Normal file
52
exploits/minitwlpayload/source/swiSoftReset.s
Normal file
@ -0,0 +1,52 @@
|
||||
/*---------------------------------------------------------------------------------
|
||||
|
||||
Copyright (C) 2009
|
||||
Dave Murphy (WinterMute)
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any
|
||||
damages arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any
|
||||
purpose, including commercial applications, and to alter it and
|
||||
redistribute it freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you
|
||||
must not claim that you wrote the original software. If you use
|
||||
this software in a product, an acknowledgment in the product
|
||||
documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and
|
||||
must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
||||
|
||||
---------------------------------------------------------------------------------*/
|
||||
|
||||
.text
|
||||
.align 4
|
||||
|
||||
.arm
|
||||
@---------------------------------------------------------------------------------
|
||||
.global swiSoftReset
|
||||
.type swiSoftReset STT_FUNC
|
||||
@---------------------------------------------------------------------------------
|
||||
swiSoftReset:
|
||||
@---------------------------------------------------------------------------------
|
||||
.arch armv5te
|
||||
.cpu arm946e-s
|
||||
ldr r1, =0x00002078 @ disable TCM and protection unit
|
||||
mcr p15, 0, r1, c1, c0
|
||||
@ Disable cache
|
||||
mov r0, #0
|
||||
mcr p15, 0, r0, c7, c5, 0 @ Instruction cache
|
||||
mcr p15, 0, r0, c7, c6, 0 @ Data cache
|
||||
|
||||
@ Wait for write buffer to empty
|
||||
mcr p15, 0, r0, c7, c10, 4
|
||||
|
||||
ldr r0,=0x2FFFE24
|
||||
|
||||
ldr r0,[r0]
|
||||
bx r0
|
||||
|
||||
.pool
|
102
exploits/minitwlpayload/stub.ld
Normal file
102
exploits/minitwlpayload/stub.ld
Normal file
@ -0,0 +1,102 @@
|
||||
/*
|
||||
elfloader - a Free Software replacement for the Nintendo/BroadOn IOS.
|
||||
|
||||
Copyright (C) 2008, 2009 Hector Martin "marcan" <marcan@marcansoft.com>
|
||||
|
||||
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, version 2.
|
||||
|
||||
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, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
*/
|
||||
|
||||
/*Modified for nzoneurlstacksmash.*/
|
||||
|
||||
OUTPUT_FORMAT("elf32-littlearm")
|
||||
OUTPUT_ARCH(arm)
|
||||
EXTERN(_start)
|
||||
ENTRY(_start)
|
||||
|
||||
__base_addr = 0x02200000;
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
. = __base_addr;
|
||||
|
||||
__code_start = .;
|
||||
|
||||
.init :
|
||||
{
|
||||
*(.init)
|
||||
. = ALIGN(4);
|
||||
}
|
||||
|
||||
.got :
|
||||
{
|
||||
__got_start = .;
|
||||
*(.got.*)
|
||||
*(.got)
|
||||
. = ALIGN(4);
|
||||
__got_end = . ;
|
||||
}
|
||||
|
||||
.text :
|
||||
{
|
||||
*(.text.*)
|
||||
*(.gnu.warning)
|
||||
*(.gnu.linkonce.t*)
|
||||
*(.glue_7)
|
||||
*(.glue_7t)
|
||||
. = ALIGN(4);
|
||||
}
|
||||
|
||||
__text_end = . ;
|
||||
|
||||
.rodata :
|
||||
{
|
||||
*(.rodata)
|
||||
*all.rodata*(*)
|
||||
*(.roda)
|
||||
*(.rodata.*)
|
||||
*(.gnu.linkonce.r*)
|
||||
. = ALIGN(4);
|
||||
}
|
||||
|
||||
.data :
|
||||
{
|
||||
*(.data)
|
||||
*(.data.*)
|
||||
*(.gnu.linkonce.d*)
|
||||
. = ALIGN(4);
|
||||
}
|
||||
|
||||
.bss :
|
||||
{
|
||||
__bss_start = . ;
|
||||
*(.dynbss)
|
||||
*(.gnu.linkonce.b*)
|
||||
*(.bss*)
|
||||
*(.sbss*)
|
||||
*(COMMON)
|
||||
. = ALIGN(32);
|
||||
__bss_end = . ;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
__end = __bss_end ;
|
||||
__loader_size = __end - __code_start;
|
||||
|
||||
PROVIDE (__got_start = __got_start);
|
||||
PROVIDE (__got_end = __got_end);
|
||||
PROVIDE (__bss_start = __bss_start);
|
||||
PROVIDE (__bss_end = __bss_end);
|
||||
|
Loading…
Reference in New Issue
Block a user