diff --git a/.gitignore b/.gitignore index 0debc25..45b1e96 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,5 @@ /loader/build /menu/build /server/logs/*.txt +/build +/*.elf diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..b9edc03 --- /dev/null +++ b/Makefile @@ -0,0 +1,182 @@ +#--------------------------------------------------------------------------------- +# Clear the implicit built in rules +#--------------------------------------------------------------------------------- +.SUFFIXES: +#--------------------------------------------------------------------------------- +ifeq ($(strip $(DEVKITPPC)),) +$(error "Please set DEVKITPPC in your environment. export DEVKITPPC=devkitPPC") +endif +export PORTLIBS := ../../portlibs/ppc +export PATH := $(DEVKITPPC)/bin:$(PORTLIBS)/bin:$(PATH) +export LIBOGC_INC := $(DEVKITPRO)/libogc/include +export LIBOGC_LIB := $(DEVKITPRO)/libogc/lib/wii + +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 := loadiine +BUILD := build +BUILD_DBG := $(TARGET)_dbg +SOURCES := src \ + src/fs \ + src/kernel \ + src/loader \ + src/menu \ + src/utils +DATA := data +INCLUDES := + +#--------------------------------------------------------------------------------- +# options for code generation +#--------------------------------------------------------------------------------- +CFLAGS := -Os -nostdinc -nostdlib -Wall -x c -std=gnu99 -nostdlib \ + -fno-builtin -ffreestanding -mrvl -mcpu=750 -meabi -mhard-float \ + -fshort-wchar -msdata=none -memb -ffunction-sections -fdata-sections \ + -Wno-unknown-pragmas -Wno-strict-aliasing $(INCLUDE) + +ASFLAGS := -mregnames +LDFLAGS := -nostartfiles -nostdlib + +#--------------------------------------------------------------------------------- +# move loader to another location - THANKS CREDIAR - 0x81330000 for HBC +#--------------------------------------------------------------------------------- +#LDFLAGS = -g $(MACHDEP) -Wl,-Map,$(notdir $@).map +#LDFLAGS = -g $(MACHDEP) -Wl,-Map,$(notdir $@).map -Wl,--section-start,.init=0x80003f00 +Q := @ +MAKEFLAGS += --no-print-directory +#--------------------------------------------------------------------------------- +# any extra libraries we wish to link with the project +#--------------------------------------------------------------------------------- +LIBS := -lgcc + +#--------------------------------------------------------------------------------- +# list of directories containing libraries, this must be the top level containing +# include and lib +#--------------------------------------------------------------------------------- +LIBDIRS := $(CURDIR) \ + $(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)/*.*))) +PNGFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.png))) + +#--------------------------------------------------------------------------------- +# 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): + @[ -d $@ ] || mkdir -p $@ + @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile + +#--------------------------------------------------------------------------------- +clean: + @echo clean ... + @rm -fr $(BUILD) $(OUTPUT).elf $(OUTPUT).bin $(BUILD_DBG).elf + +#--------------------------------------------------------------------------------- +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 $@ + +#--------------------------------------------------------------------------------- +%.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 $(@) + +-include $(DEPENDS) + +#--------------------------------------------------------------------------------- +endif +#--------------------------------------------------------------------------------- diff --git a/fs/Makefile b/fs/Makefile deleted file mode 100755 index 6f824d0..0000000 --- a/fs/Makefile +++ /dev/null @@ -1,68 +0,0 @@ - -PATH := $(DEVKITPPC)/bin:$(PATH) - -PREFIX ?= powerpc-eabi- -LD := $(PREFIX)ld -AS := $(PREFIX)as -CC := $(PREFIX)gcc -OBJDUMP ?= $(PREFIX)objdump -OBJCOPY ?= $(PREFIX)objcopy - -SFLAGS := -mgekko -mregnames - -# -O2: optimise lots -# -Wall: generate lots of warnings -# -x c: compile as C code -# -std=gnu99: use the C99 standard with GNU extensions -# -ffreestanding: we don't have libc; don't expect we do -# -mrvl: enable wii/gamecube compilation -# -mcpu=750: enable processor specific compilation -# -meabi: enable eabi specific compilation -# -mhard-float: enable hardware floating point instructions -# -fshort-wchar: use 16 bit whcar_t type in keeping with Wii executables -# -msdata-none: do not use r2 or r13 as small data areas -# -memb: enable embedded application specific compilation -# -ffunction-sections: split up functions so linker can garbage collect -# -fdata-sections: split up data so linker can garbage collect -CFLAGS := -Os -nostdinc -nostdlib -Wall -x c -std=gnu99 -nostdlib \ - -ffreestanding \ - -mrvl -mcpu=750 -meabi -mhard-float -fshort-wchar \ - -msdata=none -memb -ffunction-sections -fdata-sections \ - -Wno-unknown-pragmas -Wno-strict-aliasing \ - -SRC := $(wildcard *.S) $(wildcard *.c) -OBJ := $(patsubst %.S,%.o,$(patsubst %.c,%.o,$(SRC))) - -# Simulate an order only dependency -BUILD_REQ := $(filter-out $(wildcard build),build) -BIN_REQ := $(filter-out $(wildcard bin),bin) - -all: build/fs532.elf copy - -../installer/fs%.h: build/fs%.text.bin build/fs%.magic.bin $(BIN_REQ) - xxd -i build/fs$*.magic.bin | sed "s/unsigned/static const unsigned/g;s/fs$*/fs/g" > $@ - xxd -i build/fs$*.text.bin | sed "s/unsigned/static const unsigned/g;s/fs$*/fs/g" >> $@ - -build/fs%.text.bin: build/fs%.elf $(BUILD_REQ) - $(OBJCOPY) -j .text -O binary $< $@ -build/fs%.magic.bin: build/fs%.elf $(BUILD_REQ) - $(OBJCOPY) -j .magic -O binary $< $@ - -build/fs%.elf: fs%.ld $(OBJ) $(BUILD_REQ) - $(LD) -o $@ -T $< $(OBJ) -s -L"$(DEVKITPPC)/lib/gcc/powerpc-eabi/4.8.2" -lgcc - -build/%.o: %.c $(BUILD_REQ) - $(CC) -c $(CFLAGS) -o $@ $+ -build/%.o: %.S $(BUILD_REQ) - $(AS) $(SFLAGS) -o $@ $+ - -bin: - mkdir $@ -build: - mkdir $@ - -copy: - cp build/fs532.elf ../installer/bin/ - -clean: - rm -rf $(wildcard build) $(wildcard bin) $(wildcard ../installer/fs532.h) diff --git a/fs/utils.c b/fs/utils.c deleted file mode 100755 index 5d0231a..0000000 --- a/fs/utils.c +++ /dev/null @@ -1,164 +0,0 @@ -#include "fs.h" - -static int recvwait(int sock, void *buffer, int len); -static int recvbyte(int sock); -static int sendwait(int sock, const void *buffer, int len); - -#define CHECK_ERROR(cond) if (cond) { goto error; } - -int fs_connect(int *psock) { - extern unsigned int server_ip; - struct sockaddr_in addr; - int sock, ret; - - // No ip means that we don't have any server running, so no logs - if (server_ip == 0) { - *psock = -1; - return 0; - } - - socket_lib_init(); - - sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); - CHECK_ERROR(sock == -1); - - addr.sin_family = AF_INET; - addr.sin_port = 7332; - addr.sin_addr.s_addr = server_ip; - - ret = connect(sock, (void *)&addr, sizeof(addr)); - CHECK_ERROR(ret < 0); - - ret = recvbyte(sock); - CHECK_ERROR(ret < 0); - - *psock = sock; - return 0; - -error: - if (sock != -1) - socketclose(sock); - - *psock = -1; - return -1; -} - -void fs_disconnect(int sock) { - CHECK_ERROR(sock == -1); - - char byte = BYTE_DISCONNECT; - sendwait(sock, &byte, 1); - - socketclose(sock); -error: - return; -} - -int fs_mount_sd(int sock, void* pClient, void* pCmd) { - while (bss.lock) GX2WaitForVsync(); - bss.lock = 1; - - int is_mounted = 0; - char buffer[1]; - - if (sock != -1) { - buffer[0] = BYTE_MOUNT_SD; - sendwait(sock, buffer, 1); - } - - // mount sdcard - FSMountSource mountSrc; - char mountPath[FS_MAX_MOUNTPATH_SIZE]; - int status = FSGetMountSource(pClient, pCmd, FS_SOURCETYPE_EXTERNAL, &mountSrc, FS_RET_NO_ERROR); - if (status == FS_STATUS_OK) - { - status = FSMount(pClient, pCmd, &mountSrc, mountPath, sizeof(mountPath), FS_RET_UNSUPPORTED_CMD); - if (status == FS_STATUS_OK) - { - // set as mounted - is_mounted = 1; - } - } - - if (sock != -1) { - buffer[0] = is_mounted ? BYTE_MOUNT_SD_OK : BYTE_MOUNT_SD_BAD; - sendwait(sock, buffer, 1); - } - - bss.lock = 0; - return is_mounted; -} - -void log_string(int sock, const char* str, char flag_byte) { - if(sock == -1) { - return; - } - while (bss.lock) GX2WaitForVsync(); - bss.lock = 1; - - int i; - int len_str = 0; - while (str[len_str++]); - - // - { - char buffer[1 + 4 + len_str]; - buffer[0] = flag_byte; - *(int *)(buffer + 1) = len_str; - for (i = 0; i < len_str; i++) - buffer[5 + i] = str[i]; - - buffer[5 + i] = 0; - - sendwait(sock, buffer, 1 + 4 + len_str); - } - - bss.lock = 0; -} - -void log_byte(int sock, char byte) { - while (bss.lock) GX2WaitForVsync(); - bss.lock = 1; - - CHECK_ERROR(sock == -1); - - sendwait(sock, &byte, 1); - -error: - bss.lock = 0; -} - -static int recvwait(int sock, void *buffer, int len) { - int ret; - while (len > 0) { - ret = recv(sock, buffer, len, 0); - CHECK_ERROR(ret < 0); - len -= ret; - buffer += ret; - } - return 0; -error: - return ret; -} - -static int recvbyte(int sock) { - unsigned char buffer[1]; - int ret; - - ret = recvwait(sock, buffer, 1); - if (ret < 0) return ret; - return buffer[0]; -} - -static int sendwait(int sock, const void *buffer, int len) { - int ret; - while (len > 0) { - ret = send(sock, buffer, len, 0); - CHECK_ERROR(ret < 0); - len -= ret; - buffer += ret; - } - return 0; -error: - return ret; -} diff --git a/installer/Makefile b/installer/Makefile index adb2d04..7c26b99 100644 --- a/installer/Makefile +++ b/installer/Makefile @@ -1,5 +1,6 @@ PATH := $(DEVKITPPC)/bin:$(PATH) CC=powerpc-eabi-gcc +AS=powerpc-eabi-as CFLAGS=-std=gnu99 -nostdinc -fno-builtin -c LD=powerpc-eabi-ld LDFLAGS=-Ttext 1800000 --oformat binary @@ -10,37 +11,28 @@ build := $(root)/bin www_loadiine :=$(root)/../../www/loadiine framework:=$(root)/../../../framework -all: clean setup menu loader fs main532 print_stats +all: clean setup main main532 print_stats setup: mkdir -p $(root)/bin/ -menu: - cd ../menu/ && make - -loader: - cd ../loader/ && make - -fs: - cd ../fs/ && make +main: + cd ../ && make clean + cd ../ && make main532: $(CC) $(CFLAGS) -DVER=532 $(project)/launcher.c + $(AS) -mregnames -o kernel_patches.o $(project)/kernel_patches.S #-Wa,-a,-ad cp -r $(root)/*.o $(build) rm $(root)/*.o $(LD) $(LDFLAGS) -s -o $(build)/code532.bin $(build)/launcher.o `find $(build) -name "*.o" ! -name "launcher.o"` - cp -rf $(build)/*.elf $(www_loadiine) - cp -rf $(build)/*.elf ../www/ + cp -rf ../*.elf $(www_loadiine) + cp -rf ../*.elf ../www/ clean: - make -C ../menu/ clean - make -C ../loader/ clean - make -C ../fs/ clean rm -rf $(build) print_stats: @echo - @echo "code size : menu =>" `$(OBJDUMP) -h $(build)/menu532.elf | awk '/.text|rodata/ { sum+=strtonum("0x"$$3) } END {print sum}'` / 5120 - @echo "code size : loader =>" `$(OBJDUMP) -h $(build)/loader532.elf | awk '/.text/ { sum+=strtonum("0x"$$3) } END {print sum}'` / 5120 - @echo "code size : fs =>" `$(OBJDUMP) -h $(build)/fs532.elf | awk '/.text|rodata|magic/ { sum+=strtonum("0x"$$3) } END {print sum}'` / 16364 + @echo "code size : loadiine =>" `$(OBJDUMP) -h ../loadiine.elf | awk '/.kernel_code|.text|.menu_code|.rodata|.fs_magic|.loader_magic|.bss/ { sum+=strtonum("0x"$$3) } END {print sum}'` / 7530312 diff --git a/installer/kernel_patches.S b/installer/kernel_patches.S new file mode 100644 index 0000000..950c411 --- /dev/null +++ b/installer/kernel_patches.S @@ -0,0 +1,173 @@ + .globl Syscall_0x36 +Syscall_0x36: + mflr r0 + stwu r1, -0x10(r1) + stw r30, 0x4(r1) + stw r31, 0x8(r1) + mr r5, r0 + mr r6, r1 + li r0, 0x3600 + sc + nop + mr r0, r5 + mr r1, r6 + lwz r30, 0x04(r1) + lwz r31, 0x08(r1) + addi r1, r1, 0x10 + mtlr r0 + blr + + .globl KernelPatches +KernelPatches: + # store the old DBAT0 + mfdbatu r30, 0 + mfdbatl r31, 0 + + # setup DBAT0 for access to kernel code memory + lis r3, 0xFFF0 + ori r3, r3, 0x0002 + mtdbatu 0, r3 + lis r3, 0xFFF0 + ori r3, r3, 0x0032 + mtdbatl 0, r3 + + # memory barrier + eieio + isync + + # SaveAndResetDataBATs_And_SRs hook setup, but could be any BAT function though + # just chosen because its simple + lis r3, 0xFFF1 + ori r3, r3, 0xD744 + + # make the kernel setup our section in IBAT4 and + # jump to our function to restore the replaced instructions + lis r4, 0x3ce0 # lis r7, 0x2C80 + ori r4, r4, 0x2c80 + stw r4, 0x00(r3) + lis r4, 0x60e7 # ori r7, r7, 0x0013 + ori r4, r4, 0x0013 + stw r4, 0x04(r3) + lis r4, 0x7cf1 # mtspr 561, r7 + ori r4, r4, 0x8ba6 + stw r4, 0x08(r3) + lis r4, 0x3ce0 # lis r7, 0x0080 + ori r4, r4, 0x0080 + stw r4, 0x0C(r3) + lis r4, 0x60e7 # ori r7, r7, 0x00FF + ori r4, r4, 0x00ff + stw r4, 0x10(r3) + lis r4, 0x7cf0 # mtspr 560, r7 + ori r4, r4, 0x8ba6 + stw r4, 0x14(r3) + lis r4, 0x7c00 # eieio + ori r4, r4, 0x06ac + stw r4, 0x18(r3) + lis r4, 0x4c00 # isync + ori r4, r4, 0x012c + stw r4, 0x1C(r3) + lis r4, 0x48ae # ba 0x00AE1000 + ori r4, r4, 0x1002 + stw r4, 0x20(r3) + + # flush and invalidate the replaced instructions + lis r3, 0xFFF1 + ori r3, r3, 0xD740 + dcbf 0, r3 + icbi 0, r3 + + # write "nop" to some positions + lis r4, 0x6000 + + # nop on IBATU 4 set/reset + lis r3, 0xFFF1 + ori r3, r3, 0xD558 + stw r4, 0(r3) + dcbf 0, r3 + icbi 0, r3 + + lis r3, 0xFFF1 + ori r3, r3, 0xD73C + stw r4, 0(r3) + dcbf 0, r3 + icbi 0, r3 + + # nop on IBATL 4 set/reset + lis r3, 0xFFF1 + ori r3, r3, 0xD550 + stw r4, 0(r3) + dcbf 0, r3 + icbi 0, r3 + + # nop on remove of supervisor level from IBATU 4 + lis r3, 0xFFF0 + ori r3, r3, 0x6A14 + stw r4, 0(r3) + dcbf 0, r3 + icbi 0, r3 + + lis r3, 0xFFF0 + ori r3, r3, 0x6AA0 + stw r4, 0(r3) + dcbf 0, r3 + icbi 0, r3 + isync + + # setup IBAT4 for core 1 at this position (not really required but wont hurt) + # IBATL 4 + lis r3, 0x2C80 + ori r3, r3, 0x0013 + mtspr 561, r3 + + # IBATU 4 + lis r3, 0x0080 + ori r3, r3, 0x00FF + mtspr 560, r3 + + + # while we are at it, let's give IBATU0 kernel permissions, maybe it will come in handy + # write "nop" to some positions that set/reset IBATU0 + lis r4, 0x6000 + + lis r3, 0xFFF1 + ori r3, r3, 0xD518 + stw r4, 0(r3) + dcbf 0, r3 + icbi 0, r3 + + lis r3, 0xFFF1 + ori r3, r3, 0xD72C + stw r4, 0(r3) + dcbf 0, r3 + icbi 0, r3 + + # add code execution permission for supervisor to IBATU0 + # IBATU 0 + lis r3, 0x0100 + ori r3, r3, 0x00FF + mtibatu 0,r3 + + # Now lets hook the kernel function for result printing of PrepareTitle add jump to our function + # at location 0x00AE1058 + lis r3, 0xFFF1 + ori r3, r3, 0x8558 + lis r4, 0x48AE + ori r4, r4, 0x105A + stw r4, 0(r3) + eieio + isync + + # memory barrier + eieio + isync + + # restore DBAT 0 and return from interrupt + mtdbatu 0, r30 + mtdbatl 0, r31 + + # memory barrier + eieio + isync + + rfi + diff --git a/installer/launcher.c b/installer/launcher.c index dee9a45..88cef59 100755 --- a/installer/launcher.c +++ b/installer/launcher.c @@ -1,11 +1,14 @@ #include "launcher.h" #include "elf_abi.h" -#include "../common/common.h" +#include "../src/common/common.h" #include "../../libwiiu/src/coreinit.h" #include "../../libwiiu/src/vpad.h" #include "../../libwiiu/src/socket.h" #if VER == 532 + #define CODE_RW_BASE_OFFSET 0xBC000000 + #define DATA_RW_BASE_OFFSET 0 + // Function definitions #define SYSLaunchMiiStudio ((void (*)(void))0xDEAAEB8) #define _Exit ((void (*)(void))0x0101cd70) @@ -13,13 +16,6 @@ #define memcpy ((void * (*)(void * dest, const void * src, int num))0x1035a6c) #define DCFlushRange ((void (*)(const void *addr, uint length))0x1023ee8) #define ICInvalidateRange ((void (*)(const void *addr, uint length))0x1024010) - - // Install addresses - #define INSTALL_FS_ADDR 0x011df800 // where the fs functions are copied in memory - - // Install flags - #define INSTALL_FS_DONE_ADDR (INSTALL_FS_ADDR - 0x4) // Used to know if fs is already installed - #define INSTALL_FS_DONE_FLAG 0xCACACACA #endif #define PRINT_TEXT1(x, y, str) { OSScreenPutFontEx(1, x, y, str); } @@ -65,13 +61,7 @@ typedef struct { } file_struct_t; typedef struct { - unsigned char *data_menu; - unsigned char *data_loader; - unsigned char *data_fs; - int len_menu; - int len_loader; - int len_fs; - + unsigned char *data_elf; unsigned int coreinit_handle; /* function pointers */ void*(*memset)(void * dest, unsigned int value, unsigned int bytes); @@ -87,6 +77,7 @@ typedef struct { } private_data_t; /* Install functions */ +static void InstallMain(private_data_t *private_data); static void InstallMenu(private_data_t *private_data); static void InstallLoader(private_data_t *private_data); static void InstallFS(private_data_t *private_data); @@ -94,6 +85,12 @@ static void InstallFS(private_data_t *private_data); static int show_ip_selection_screen(unsigned int coreinit_handle, unsigned int *ip_address); static void curl_thread_callback(int argc, void *argv); +static void SetupKernelSyscall(unsigned int addr); + +/* assembly functions */ +extern void Syscall_0x36(void); +extern void KernelPatches(void); + /* ****************************************************************** */ /* ENTRY POINT */ /* ****************************************************************** */ @@ -211,32 +208,70 @@ void _start() /* Install our ELF files */ if(result){ - InstallMenu(&private_data); - InstallLoader(&private_data); - InstallFS(&private_data); /* patch server IP */ - *((volatile unsigned int *)(INSTALL_FS_ADDR + 0xC1000000)) = ip_address; + SERVER_IP = ip_address; /* Set GAME_LAUNCHED to 0 */ GAME_LAUNCHED = 0; GAME_RPX_LOADED = 0; + RPX_CHECK_NAME = 0xDEADBEAF; /* Set LOADIINE mode to smash bros initially */ LOADIINE_MODE = LOADIINE_MODE_SMASH_BROS; + /* Install our code now */ + InstallMain(&private_data); + + /* setup our own syscall and call it */ + SetupKernelSyscall((unsigned int)KernelPatches); + Syscall_0x36(); + + InstallMenu(&private_data); + InstallLoader(&private_data); + InstallFS(&private_data); } /* free memory allocated */ - if(private_data.data_menu) { - private_data.MEMFreeToDefaultHeap(private_data.data_menu); - } - if(private_data.data_loader) { - private_data.MEMFreeToDefaultHeap(private_data.data_loader); - } - if(private_data.data_fs) { - private_data.MEMFreeToDefaultHeap(private_data.data_fs); + if(private_data.data_elf) { + private_data.MEMFreeToDefaultHeap(private_data.data_elf); } } + _Exit(); } +/* ***************************************************************************** + * Base functions + * ****************************************************************************/ + +/* Write a 32-bit word with kernel permissions */ +static void kern_write(uint32_t addr, uint32_t value) +{ + asm volatile( + "li 3,1\n" + "li 4,0\n" + "mr 5,%1\n" + "li 6,0\n" + "li 7,0\n" + "lis 8,1\n" + "mr 9,%0\n" + "mr %1,1\n" + "li 0,0x3500\n" + "sc\n" + "nop\n" + "mr 1,%1\n" + : + : "r"(addr), "r"(value) + : "memory", "ctr", "lr", "0", "3", "4", "5", "6", "7", "8", "9", "10", + "11", "12" + ); +} + +#define KERN_SYSCALL_TBL_5 0xFFEAA0E0 // works with browser + +static void SetupKernelSyscall(unsigned int address) +{ + // Add syscall #0x36 + kern_write(KERN_SYSCALL_TBL_5 + (0x36 * 4), address); +} + /* IP selection screen implemented by Maschell */ static int show_ip_selection_screen(unsigned int coreinit_handle, unsigned int *ip_address) { @@ -486,12 +521,8 @@ static void curl_thread_callback(int argc, void *argv) while(*ptr != 0x2F) ptr--; - memcpy(ptr+1, "fs532.elf", 10); - private_data->len_fs = curl_download_file(private_data, curl, buf, &private_data->data_fs); - memcpy(ptr+1, "menu532.elf", 12); - private_data->len_menu = curl_download_file(private_data, curl, buf, &private_data->data_menu); - memcpy(ptr+1, "loader532.elf", 14); - private_data->len_loader = curl_download_file(private_data, curl, buf, &private_data->data_loader); + memcpy(ptr+1, "loadiine.elf", 13); + curl_download_file(private_data, curl, buf, &private_data->data_elf); /* Cleanup to gain back memory */ private_data->curl_easy_cleanup(curl); @@ -555,36 +586,86 @@ static unsigned int get_section(private_data_t *private_data, unsigned char *dat } /* ****************************************************************** */ -/* INSTALL MENU */ +/* INSTALL MAIN CODE */ /* ****************************************************************** */ -static void InstallMenu(private_data_t *private_data) +static void InstallMain(private_data_t *private_data) { + // get .kernel_code section + unsigned int kernel_code_addr = 0; + unsigned int kernel_code_len = 0; + unsigned int section_offset = get_section(private_data, private_data->data_elf, ".kernel_code", &kernel_code_len, &kernel_code_addr); + unsigned char *kernel_code = private_data->data_elf + section_offset; + + /* Copy kernel code section to memory */ + unsigned int cpy_addr = (CODE_RW_BASE_OFFSET + kernel_code_addr); + memcpy((void*)cpy_addr, kernel_code, kernel_code_len); + DCFlushRange((void*)cpy_addr, kernel_code_len); + ICInvalidateRange((void*)cpy_addr, kernel_code_len); + // get .text section - unsigned int menu_text_addr = 0; - unsigned int menu_text_len = 0; - unsigned int section_offset = get_section(private_data, private_data->data_menu, ELF_TEXT, &menu_text_len, &menu_text_addr); - unsigned char *menu_text = private_data->data_menu + section_offset; + unsigned int main_text_addr = 0; + unsigned int main_text_len = 0; + section_offset = get_section(private_data, private_data->data_elf, ELF_TEXT, &main_text_len, &main_text_addr); + unsigned char *main_text = private_data->data_elf + section_offset; + /* Copy main .text to memory */ + memcpy((void*)(CODE_RW_BASE_OFFSET + main_text_addr), main_text, main_text_len); + DCFlushRange((void*)(CODE_RW_BASE_OFFSET + main_text_addr), main_text_len); + ICInvalidateRange((void*)(CODE_RW_BASE_OFFSET + main_text_addr), main_text_len); // get the .rodata section - unsigned int menu_rodata_addr = 0; - unsigned int menu_rodata_len = 0; - section_offset = get_section(private_data, private_data->data_menu, ELF_RODATA, &menu_rodata_len, &menu_rodata_addr); - unsigned char *menu_rodata = private_data->data_menu + section_offset; - - /* Copy menu code to memory */ - memcpy((void*)0xC1000000 + menu_text_addr, menu_text, menu_text_len); - DCFlushRange((void*)(0xC1000000 + menu_text_addr), menu_text_len); - ICInvalidateRange((void*)(0xC1000000 + menu_text_addr), menu_text_len); - - /* Copy menu rodata to memory */ - memcpy((void*)0xC1000000 + menu_rodata_addr, menu_rodata, menu_rodata_len); - DCFlushRange((void*)(0xC1000000 + menu_rodata_addr), menu_rodata_len); - - /* Patch coreinit - on 5.3.2 coreinit.rpl starts at 0x101c400 */ - int jump_length = menu_text_addr - 0x0101c55c; // => jump to (101C55C + 1C0AA4) = 11DD000 which is the codehandler - *((volatile uint32_t *)(0xC1000000 + 0x0101c55c)) = 0x48000001 | jump_length; // 0x481c0aa5 => bl 0x1C0AA4 => write at 0x15C in coreinit file => end of the coreinit_start function - DCFlushRange((void*)(0xC1000000 + 0x0101c55c), 4); - ICInvalidateRange((void*)(0xC1000000 + 0x0101c55c), 4); + unsigned int main_rodata_addr = 0; + unsigned int main_rodata_len = 0; + section_offset = get_section(private_data, private_data->data_elf, ELF_RODATA, &main_rodata_len, &main_rodata_addr); + unsigned char *main_rodata = private_data->data_elf + section_offset; + /* Copy main rodata to memory */ + memcpy((void*)(DATA_RW_BASE_OFFSET + main_rodata_addr), main_rodata, main_rodata_len); + DCFlushRange((void*)(DATA_RW_BASE_OFFSET + main_rodata_addr), main_rodata_len); + + // get the .bss section + unsigned int main_bss_addr = 0; + unsigned int main_bss_len = 0; + section_offset = get_section(private_data, private_data->data_elf, ELF_BSS, &main_bss_len, &main_bss_addr); + // Copy main bss to memory + private_data->memset((void*)(DATA_RW_BASE_OFFSET + main_bss_addr), 0, main_bss_len); + DCFlushRange((void*)(DATA_RW_BASE_OFFSET + main_bss_addr), main_bss_len); +} + +/* ****************************************************************** */ +/* INSTALL MENU CODE */ +/* ****************************************************************** */ +static void InstallMenu(private_data_t *private_data) +{ + // get .menu_magic section + unsigned int menu_magic_addr = 0; + unsigned int menu_magic_len = 0; + unsigned int section_offset = get_section(private_data, private_data->data_elf, ".menu_magic", &menu_magic_len, &menu_magic_addr); + unsigned char *menu_magic = private_data->data_elf + section_offset; + + /* Get our functions */ + struct magic_t + { + const unsigned int repl_func; // our replacement function which is called + const unsigned int repl_addr; // address where to place the jump to the our function + const unsigned int call_type; // call type, e.g. 0x48000000 for branch and 0x48000001 for bl + } *magic = (struct magic_t *)menu_magic; + int magic_len = menu_magic_len / sizeof(struct magic_t); + + /* Replace loader instructions */ + /* Loop to replace instructions in loader code by a "bl"(jump) instruction to our replacement function */ + int i; + for (i = 0; i < magic_len; i ++) + { + unsigned int repl_func = magic[i].repl_func; + unsigned int repl_addr = magic[i].repl_addr; + unsigned int call_type = magic[i].call_type; + + // Install function hook only if needed + unsigned int jump_addr = repl_func & 0x03fffffc; // Compute jump length to jump from current instruction address to our function address + *((volatile uint32_t *)(0xC1000000 + repl_addr)) = call_type | jump_addr; // Replace the instruction in the loader by the jump to our function + // flush caches and invalidate instruction cache + DCFlushRange((void*)(0xC1000000 + repl_addr), 4); + ICInvalidateRange((void*)(0xC1000000 + repl_addr), 4); + } } /* ****************************************************************** */ @@ -593,45 +674,17 @@ static void InstallMenu(private_data_t *private_data) /* ****************************************************************** */ static void InstallLoader(private_data_t *private_data) { - // get .text section - unsigned int loader_text_addr = 0; - unsigned int loader_text_len = 0; - unsigned int section_offset = get_section(private_data, private_data->data_loader, ELF_TEXT, &loader_text_len, &loader_text_addr); - unsigned char *loader_text = private_data->data_loader + section_offset; // get .magic section unsigned int loader_magic_addr = 0; unsigned int loader_magic_len = 0; - section_offset = get_section(private_data, private_data->data_loader, ".magic", &loader_magic_len, &loader_magic_addr); - unsigned char *loader_magic = private_data->data_loader + section_offset; - - /* Patch to bypass SDK version tests */ - *((volatile uint32_t *)(0xC1000000 + 0x010095b4)) = 0x480000a0; // ble loc_1009654 (0x408100a0) => b loc_1009654 (0x480000a0) - *((volatile uint32_t *)(0xC1000000 + 0x01009658)) = 0x480000e8; // bge loc_1009740 (0x408100a0) => b loc_1009740 (0x480000e8) - DCFlushRange((void*)(0xC1000000 + 0x010095b4), 4); - ICInvalidateRange((void*)(0xC1000000 + 0x010095b4), 4); - DCFlushRange((void*)(0xC1000000 + 0x01009658), 4); - ICInvalidateRange((void*)(0xC1000000 + 0x01009658), 4); - - /* Copy loader code in memory */ - /* - virtual address 0xA0000000 is at physical address 0x10000000 (with read/write access) */ - /* - virtual address range 0x01xxxxxx starts at physical address 0x32000000 */ - /* - we want to copy the code at INSTALL_ADDR (0x011de000), this memory range is the for cafeOS app and libraries, but is write protected */ - /* - in order to have the rights to write into memory in this address range we need to use the 0xA0000000 virtual address range */ - /* - so start virtual address is : (0xA0000000 + (0x32000000 - 0x10000000 - 0x01000000)) = 0xC1000000 */ - memcpy((void*)(0xC1000000 + loader_text_addr), loader_text, loader_text_len); - // flush caches and invalidate instruction cache - DCFlushRange((void*)(0xC1000000 + loader_text_addr), loader_text_len); - ICInvalidateRange((void*)(0xC1000000 + loader_text_addr), loader_text_len); - - /* Copy original loader instructions in memory for when we want to restore the loader at his original state */ - // TODO: copy original instructions in order to restore them later to have a clean loader state - // we'll have to hook the "quit" function to restore the original instructions + unsigned int section_offset = get_section(private_data, private_data->data_elf, ".loader_magic", &loader_magic_len, &loader_magic_addr); + unsigned char *loader_magic = private_data->data_elf + section_offset; /* Get our functions */ struct magic_t { - const void * repl_func; // our replacement function which is called - const void * repl_addr; // address where to place the jump to the our function + const unsigned int repl_func; // our replacement function which is called + const unsigned int repl_addr; // address where to place the jump to the our function const unsigned int call_type; // call type, e.g. 0x48000000 for branch and 0x48000001 for bl } *magic = (struct magic_t *)loader_magic; int magic_len = loader_magic_len / sizeof(struct magic_t); @@ -641,18 +694,25 @@ static void InstallLoader(private_data_t *private_data) int i; for (i = 0; i < magic_len; i ++) { - unsigned int repl_func = (unsigned int)magic[i].repl_func; - unsigned int repl_addr = (unsigned int)magic[i].repl_addr; + unsigned int repl_func = magic[i].repl_func; + unsigned int repl_addr = magic[i].repl_addr; unsigned int call_type = magic[i].call_type; // Install function hook only if needed - int jump_addr = (repl_func - repl_addr) & 0x03fffffc; // Compute jump length to jump from current instruction address to our function address - *((volatile uint32_t *)(0xC1000000 + repl_addr)) = call_type | jump_addr; // Replace the instruction in the loader by the jump to our function + unsigned int jump_addr = repl_func & 0x03fffffc; // Compute jump length to jump from current instruction address to our function address + *((volatile uint32_t *)(0xC1000000 + repl_addr)) = call_type | jump_addr; // Replace the instruction in the loader by the jump to our function // flush caches and invalidate instruction cache DCFlushRange((void*)(0xC1000000 + repl_addr), 4); ICInvalidateRange((void*)(0xC1000000 + repl_addr), 4); } + /* Patch to bypass SDK version tests */ + *((volatile uint32_t *)(0xC1000000 + 0x010095b4)) = 0x480000a0; // ble loc_1009654 (0x408100a0) => b loc_1009654 (0x480000a0) + *((volatile uint32_t *)(0xC1000000 + 0x01009658)) = 0x480000e8; // bge loc_1009740 (0x408100a0) => b loc_1009740 (0x480000e8) + DCFlushRange((void*)(0xC1000000 + 0x010095b4), 4); + ICInvalidateRange((void*)(0xC1000000 + 0x010095b4), 4); + DCFlushRange((void*)(0xC1000000 + 0x01009658), 4); + ICInvalidateRange((void*)(0xC1000000 + 0x01009658), 4); } /* ****************************************************************** */ @@ -661,37 +721,27 @@ static void InstallLoader(private_data_t *private_data) /* ****************************************************************** */ static void InstallFS(private_data_t *private_data) { - /* Check if already installed */ - if (*(volatile unsigned int *)(INSTALL_FS_DONE_ADDR + 0xC1000000) == INSTALL_FS_DONE_FLAG) - return; - *(volatile unsigned int *)(INSTALL_FS_DONE_ADDR + 0xC1000000) = INSTALL_FS_DONE_FLAG; - - // get .text section - unsigned int fs_text_addr = 0; - unsigned int fs_text_len = 0; - unsigned int section_offset = get_section(private_data, private_data->data_fs, ELF_TEXT, &fs_text_len, &fs_text_addr); - unsigned char *fs_text = private_data->data_fs + section_offset; - // get .rodata section - unsigned int fs_rodata_addr = 0; - unsigned int fs_rodata_len = 0; - section_offset = get_section(private_data, private_data->data_fs, ELF_RODATA, &fs_rodata_len, &fs_rodata_addr); - unsigned char *fs_rodata = private_data->data_fs + section_offset; // get .magic section unsigned int fs_magic_addr = 0; unsigned int fs_magic_len = 0; - section_offset = get_section(private_data, private_data->data_fs, ".magic", &fs_magic_len, &fs_magic_addr); - unsigned char *fs_magic = private_data->data_fs + section_offset; - - /* Copy fs code section to memory */ - unsigned int cpy_addr = (0xC1000000 + fs_text_addr); - memcpy((void*)cpy_addr, fs_text, fs_text_len); - DCFlushRange((void*)cpy_addr, fs_text_len); - ICInvalidateRange((void*)cpy_addr, fs_text_len); + unsigned int section_offset = get_section(private_data, private_data->data_elf, ".fs_magic", &fs_magic_len, &fs_magic_addr); + unsigned char *fs_magic = private_data->data_elf + section_offset; + // copy the data of the magic for later patching / unpatching + memcpy((void*)(DATA_RW_BASE_OFFSET + fs_magic_addr), fs_magic, fs_magic_len); + DCFlushRange((void*)(DATA_RW_BASE_OFFSET + fs_magic_addr), fs_magic_len); + // get .magic section + unsigned int magicptr_addr = 0; + unsigned int magicptr_len = 0; + section_offset = get_section(private_data, private_data->data_elf, ".magicptr", &magicptr_len, &magicptr_addr); + unsigned char *magicptr = private_data->data_elf + section_offset; + // copy the data of the magic for later patching / unpatching + memcpy((void*)(0xC1000000 + magicptr_addr), magicptr, magicptr_len); + DCFlushRange((void*)(0xC1000000 + magicptr_addr), magicptr_len); - /* Copy fs rodata section to memory */ - cpy_addr = (0xC1000000 + fs_rodata_addr); - memcpy((void*)cpy_addr, fs_rodata, fs_rodata_len); - DCFlushRange((void*)cpy_addr, fs_rodata_len); + // get .magic section + unsigned int fs_method_calls_addr = 0; + unsigned int fs_method_calls_len = 0; + section_offset = get_section(private_data, private_data->data_elf, ".fs_method_calls", &fs_method_calls_len, &fs_method_calls_addr); /* ------------------------------------------------------------------------------------------------------------------------*/ /* patch the FS functions to branch to our functions */ @@ -700,32 +750,35 @@ static void InstallFS(private_data_t *private_data) void *real; void *replacement; void *call; + unsigned int orig_instr; } *magic = (struct magic_t *)fs_magic; unsigned int len = fs_magic_len / sizeof(struct magic_t); /* Patch branches to it. */ - volatile int *space = (volatile int *)(0xC1000000 + fs_text_addr + fs_text_len); + volatile unsigned int *space = (volatile unsigned int *)(CODE_RW_BASE_OFFSET + fs_method_calls_addr); while (len--) { - int real_addr = (int)magic[len].real; - int repl_addr = (int)magic[len].replacement; - int call_addr = (int)magic[len].call; + unsigned int real_addr = (unsigned int)magic[len].real; + unsigned int repl_addr = (unsigned int)magic[len].replacement; + unsigned int call_addr = (unsigned int)magic[len].call; + unsigned int orig_instr =(unsigned int)magic[len].orig_instr; // set pointer to the real function - *(volatile int *)(0xC1000000 + call_addr) = (int)space - 0xC1000000; + *(volatile unsigned int *)(0xC1000000 + call_addr) = (unsigned int)space - CODE_RW_BASE_OFFSET; // fill the pointer of the real function - *space = *(volatile int *)(0xC1000000 + real_addr); + *space = orig_instr; space++; // jump to real function skipping the "mflr r0" instruction *space = 0x48000002 | ((real_addr + 4) & 0x03fffffc); space++; - DCFlushRange((void*)space - 2, 8); - ICInvalidateRange((void*)space - 2, 8); + DCFlushRange((void*)(space - 2), 8); + ICInvalidateRange((void*)(space - 2), 8); + // the installation is done later on during Mii Maker start, only restore here original instruction to "fix" it all up until new patch // in the real function, replace the "mflr r0" instruction by a jump to the replacement function - *(volatile int *)(0xC1000000 + real_addr) = 0x48000002 | (repl_addr & 0x03fffffc); - DCFlushRange((int *)(0xC1000000 + real_addr), 4); - ICInvalidateRange((int *)(0xC1000000 + real_addr), 4); + *(volatile unsigned int *)(0xC1000000 + real_addr) = orig_instr; + DCFlushRange((unsigned int *)(0xC1000000 + real_addr), 4); + ICInvalidateRange((unsigned int *)(0xC1000000 + real_addr), 4); } } diff --git a/installer/launcher.h b/installer/launcher.h index c46e778..6020345 100755 --- a/installer/launcher.h +++ b/installer/launcher.h @@ -2,6 +2,6 @@ #define LAUNCHER_H /* Include base types */ -#include "../common/types.h" +#include "../src/common/types.h" #endif /* LAUNCHER_H */ diff --git a/loader/Makefile b/loader/Makefile deleted file mode 100755 index ce3dc3c..0000000 --- a/loader/Makefile +++ /dev/null @@ -1,76 +0,0 @@ - -PATH := $(DEVKITPPC)/bin:$(PATH) - -PREFIX ?= powerpc-eabi- -LD := $(PREFIX)ld -AS := $(PREFIX)as -CC := $(PREFIX)gcc -OBJDUMP ?= $(PREFIX)objdump -OBJCOPY ?= $(PREFIX)objcopy - -SFLAGS := -mgekko -mregnames - -# -O2: optimise lots -# -Wall: generate lots of warnings -# -x c: compile as C code -# -std=gnu99: use the C99 standard with GNU extensions -# -ffreestanding: we don't have libc; don't expect we do -# -mrvl: enable wii/gamecube compilation -# -mcpu=750: enable processor specific compilation -# -meabi: enable eabi specific compilation -# -mhard-float: enable hardware floating point instructions -# -fshort-wchar: use 16 bit whcar_t type in keeping with Wii executables -# -msdata-none: do not use r2 or r13 as small data areas -# -memb: enable embedded application specific compilation -# -ffunction-sections: split up functions so linker can garbage collect -# -fdata-sections: split up data so linker can garbage collect -#CFLAGS := -O2 -Wall -x c -std=gnu99 \ - -# optimizing to -Os gives still disc error on some games like mario kart 8 and mario maker (even though they dont work anyway) -# gotta check what else the compiler is optimizing (memory realignment?) -# so for now i reverted it as there is still enough space in payload -# adding it back in will give another 600 - 1000 bytes of space -# CFLAGS := -Os -nostdinc -nostdlib -Wall -x c -std=gnu99 -CFLAGS := -Os -nostdinc -nostdlib -Wall -x c -std=gnu99 \ - -ffreestanding \ - -mrvl -mcpu=750 -meabi -mhard-float -fshort-wchar \ - -msdata=none -memb -ffunction-sections -fdata-sections \ - -Wno-unknown-pragmas -Wno-strict-aliasing - -SRC := $(wildcard *.S) $(wildcard *.c) -OBJ := $(patsubst %.S,build/%.o,$(patsubst %.c,build/%.o,$(SRC))) - -# Simulate an order only dependency -BUILD_REQ := $(filter-out $(wildcard build),build) -BIN_REQ := $(filter-out $(wildcard bin),bin) - -all: build/loader532.elf copy - -bin/loader%.h: build/loader%.text.bin build/loader%.magic.bin $(BIN_REQ) - xxd -i build/loader$*.magic.bin | sed "s/unsigned/static const unsigned/g;s/loader$*/loader/g;s/build_//g" > $@ - xxd -i build/loader$*.text.bin | sed "s/unsigned/static const unsigned/g;s/loader$*/loader/g;s/build_//g" >> $@ - -build/loader%.text.bin: build/loader%.elf $(BUILD_REQ) - $(OBJCOPY) -j .text -O binary $< $@ -build/loader%.magic.bin: build/loader%.elf $(BUILD_REQ) - $(OBJCOPY) -j .magic -O binary $< $@ - -build/loader%.elf: loader%.ld $(OBJ) $(BUILD_REQ) -# $(LD) -T $< $(OBJ) - $(LD) -T $< $(OBJ) -s -L"$(DEVKITPPC)/lib/gcc/powerpc-eabi/4.8.2" -lgcc - -build/%.o: %.c $(BUILD_REQ) - $(CC) -c $(CFLAGS) -o $@ $< -build/%.o: %.S $(BUILD_REQ) - $(AS) $(SFLAGS) -o $@ $< - -bin: - mkdir $@ -build: - mkdir $@ - -copy: - cp build/loader532.elf ../installer/bin/ - -clean: - rm -rf $(wildcard build) $(wildcard bin) $(wildcard ../installer/loader532.h) diff --git a/loader/loader532.ld b/loader/loader532.ld deleted file mode 100755 index 0fc607d..0000000 --- a/loader/loader532.ld +++ /dev/null @@ -1,28 +0,0 @@ -OUTPUT(build/loader532.elf); - -SECTIONS { - .text 0x011de400 : { - *(.text._start); - *(.text*); - } - .magic : { - *(.magic*); - } - /DISCARD/ : { - *(*); - } -} - -/* Instructions addresses to replace by "bl 0x???????? - instr addr - original instruction => comment */ -/* This are the real functions that are used for our purpose */ -PROVIDE(LiWaitIopComplete = 0x0100FFA4); -PROVIDE(LiWaitIopCompleteWithInterrupts = 0x0100FE90); -PROVIDE(LiCheckAndHandleInterrupts = 0x010046B0); -PROVIDE(Loader_SysCallGetProcessIndex = 0x010000A8); -PROVIDE(LiLoadAsync = 0x0101005C); -PROVIDE(strncpy = 0x01010690); -PROVIDE(strnlen = 0x010106E0); - -/* This are just addresses to the real functions which we only need as reference */ -PROVIDE(addr_LiWaitOneChunk = 0x010007EC); -PROVIDE(addr_LiBounceOneChunk = 0x010003B0); \ No newline at end of file diff --git a/menu/Makefile b/menu/Makefile deleted file mode 100755 index 9bcf296..0000000 --- a/menu/Makefile +++ /dev/null @@ -1,66 +0,0 @@ - -PATH := $(DEVKITPPC)/bin:$(PATH) - -PREFIX ?= powerpc-eabi- -LD := $(PREFIX)ld -AS := $(PREFIX)as -CC := $(PREFIX)gcc -OBJDUMP ?= $(PREFIX)objdump -OBJCOPY ?= $(PREFIX)objcopy - -SFLAGS := -mgekko -mregnames - -# -O2: optimise lots -# -Wall: generate lots of warnings -# -x c: compile as C code -# -std=gnu99: use the C99 standard with GNU extensions -# -ffreestanding: we don't have libc; don't expect we do -# -mrvl: enable wii/gamecube compilation -# -mcpu=750: enable processor specific compilation -# -meabi: enable eabi specific compilation -# -mhard-float: enable hardware floating point instructions -# -fshort-wchar: use 16 bit whcar_t type in keeping with Wii executables -# -msdata-none: do not use r2 or r13 as small data areas -# -memb: enable embedded application specific compilation -# -ffunction-sections: split up functions so linker can garbage collect -# -fdata-sections: split up data so linker can garbage collect -CFLAGS := -Os -nostdinc -nostdlib -Wall -x c -std=gnu99 \ - -ffreestanding \ - -mrvl -mcpu=750 -meabi -mhard-float -fshort-wchar \ - -msdata=none -memb -ffunction-sections -fdata-sections \ - -Wno-unknown-pragmas -Wno-strict-aliasing - -SRC := $(wildcard *.S) $(wildcard *.c) -OBJ := $(patsubst %.S,build/%.o,$(patsubst %.c,build/%.o,$(SRC))) - -# Simulate an order only dependency -BUILD_REQ := $(filter-out $(wildcard build),build) -BIN_REQ := $(filter-out $(wildcard bin),bin) - -all: build/menu532.elf copy - -bin/menu%.h: build/menu%.text.bin $(BIN_REQ) - xxd -i $< | sed "s/unsigned/static const unsigned/g;s/menu$*/menu/g;s/build_//g" > $@ - -build/menu%.text.bin: build/menu%.elf $(BUILD_REQ) - $(OBJCOPY) -j .text -O binary $< $@ - -build/menu%.elf: menu%.ld $(OBJ) $(BUILD_REQ) - $(LD) -T $< $(OBJ) -s -L"$(DEVKITPPC)/lib/gcc/powerpc-eabi/4.8.2" -lgcc - -build/%.o: %.c $(BUILD_REQ) - $(CC) -c $(CFLAGS) -o $@ $< -build/%.o: %.S $(BUILD_REQ) - $(AS) $(SFLAGS) -o $@ $< - -bin: - mkdir $@ -build: - mkdir $@ - -copy: - cp build/menu532.elf ../installer/bin/ - -clean: - rm -rf $(wildcard build) $(wildcard bin) $(wildcard ../installer/menu532.h) - diff --git a/menu/menu532.ld b/menu/menu532.ld deleted file mode 100755 index 5cb1cde..0000000 --- a/menu/menu532.ld +++ /dev/null @@ -1,65 +0,0 @@ -OUTPUT(build/menu532.elf); - -SECTIONS { - .text 0x011dd000 : { - *(.text._start); - *(.text*); - } - .rodata : { - *(.rodata*); - } - /DISCARD/ : { - *(*); - } -} - -/* Main */ -PROVIDE(entry_point = 0x1005d180); - -/* System */ -PROVIDE(_Exit = 0x0101cd70); -PROVIDE(OSFatal = 0x1031368); -PROVIDE(DCFlushRange = 0x1023ee8); -PROVIDE(memset = 0x1035a54); -PROVIDE(memcpy = 0x1035a68); -PROVIDE(__gh_errno_ptr = 0x1040308); -PROVIDE(GX2WaitForVsync = 0x1151964); -PROVIDE(__os_snprintf = 0x102f09c); -PROVIDE(title_id = 0x100136D0); - -/* Alloc */ -PROVIDE(MEMAllocFromDefaultHeapEx = 0x1004e9c0); -PROVIDE(MEMAllocFromDefaultHeap = 0x100b4878); -PROVIDE(MEMFreeToDefaultHeap = 0x100b487c); - -/* Libs */ -PROVIDE(OSDynLoad_FindExport = 0x102b790); -PROVIDE(OSDynLoad_Acquire = 0x102a31c); - -/* Screen */ -PROVIDE(OSScreenInit = 0x0103a880); -PROVIDE(OSScreenGetBufferSizeEx = 0x0103a91c); -PROVIDE(OSScreenSetBufferEx = 0x0103a934); -PROVIDE(OSScreenClearBufferEx = 0x0103aa90); -PROVIDE(OSScreenFlipBuffersEx = 0x0103a9d0); -PROVIDE(OSScreenPutFontEx = 0x0103af14); - -/* VPAD */ -PROVIDE(VPADRead = 0x011293d0); - -/* FS Functions */ -PROVIDE(FSAddClient = 0x010689fc); -PROVIDE(FSInitCmdBlock = 0x01068c54); -PROVIDE(FSGetMountSource = 0x0106ec24); -PROVIDE(FSMount = 0x0106ed14); -PROVIDE(FSUnmount = 0x0106ed8c); -PROVIDE(FSOpenDir = 0x0106f690); -PROVIDE(FSReadDir = 0x0106f780); -PROVIDE(FSOpenFile = 0x106ef7c); -PROVIDE(FSReadFile = 0x106f108); -PROVIDE(FSChangeDir = 0x0106eefc); -PROVIDE(FSMakeDir = 0x0106f8e0); -PROVIDE(FSCloseDir = 0x0106f700); -PROVIDE(FSCloseFile = 0x106f088); -PROVIDE(FSGetStat = 0x0106fdc8); -PROVIDE(FSMakeDir = 0x0106f8e0); diff --git a/menu/util.h b/menu/util.h deleted file mode 100644 index f37ef27..0000000 --- a/menu/util.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef __UTIL_H_ -#define __UTIL_H_ - -int strcasecmp(const char *s1, const char *s2); -int strlen(const char* str); -//int strlcpy(char *s1, const char *s2, unsigned int max_size); -void qsort(void *ptr, unsigned int count, unsigned int size, int (*compare)(const void*,const void*)); - -#endif diff --git a/common/common.h b/src/common/common.h old mode 100755 new mode 100644 similarity index 93% rename from common/common.h rename to src/common/common.h index 640c207..4bb3016 --- a/common/common.h +++ b/src/common/common.h @@ -33,8 +33,8 @@ #define MEM_BASE ((void*)0xC0800000) #define MEM_SIZE (*(volatile unsigned int*)(MEM_BASE - 0x04)) #define MEM_OFFSET (*(volatile unsigned int*)(MEM_BASE - 0x08)) -#define MEM_AREA (*(volatile unsigned int*)(MEM_BASE - 0x0C)) -#define MEM_PART (*(volatile unsigned int*)(MEM_BASE - 0x10)) +#define SERVER_IP (*(volatile unsigned int*)(MEM_BASE - 0x0C)) +#define RPX_CHECK_NAME (*(volatile unsigned int*)(MEM_BASE - 0x10)) #define GAME_RPX_LOADED (*(volatile unsigned int*)(MEM_BASE - 0x14)) #define GAME_LAUNCHED (*(volatile unsigned int*)(MEM_BASE - 0x18)) #define LOADIINE_MODE (*(volatile unsigned int*)(MEM_BASE - 0x1C)) // loadiine operation mode (0 = smash bros, 1 = mii maker) @@ -50,7 +50,7 @@ /* RPX Name : from which app/game, our rpx is launched */ // 0xEFE00000 contains the rpx name, 0x63726F73 => cros (for smash brox : cross_f.rpx) // 0xEFE00000 contains the rpx name, 0x66666C5F => ffl_ (for mii maker : ffl_app.rpx) -#define RPX_CHECK_NAME ( (LOADIINE_MODE == LOADIINE_MODE_MII_MAKER) ? 0x66666C5F : 0x63726F73 ) +//#define RPX_CHECK_NAME ( (LOADIINE_MODE == LOADIINE_MODE_MII_MAKER) ? 0x66666C5F : 0x63726F73 ) /* Struct used to organize empty memory areas */ typedef struct _s_mem_area diff --git a/common/fs_defs.h b/src/common/fs_defs.h old mode 100755 new mode 100644 similarity index 100% rename from common/fs_defs.h rename to src/common/fs_defs.h diff --git a/src/common/kernel_defs.h b/src/common/kernel_defs.h new file mode 100644 index 0000000..9d1b5de --- /dev/null +++ b/src/common/kernel_defs.h @@ -0,0 +1,98 @@ +#ifndef __KERNEL_DEFS_H_ +#define __KERNEL_DEFS_H_ + +#include "types.h" +#include "fs_defs.h" + +// original structure in the kernel that is originally 0x1270 long +typedef struct +{ + uint32_t version_cos_xml; // version tag from cos.xml + uint64_t os_version; // os_version from app.xml + uint64_t title_id; // title_id tag from app.xml + uint32_t app_type; // app_type tag from app.xml + uint32_t cmdFlags; // unknown tag as it is always 0 (might be cmdFlags from cos.xml but i am not sure) + char rpx_name[0x1000]; // rpx name from cos.xml + uint32_t unknown2; // 0x050B8304 in mii maker and system menu (looks a bit like permissions complex that got masked!?) + uint32_t unknown3[63]; // those were all zeros, but its probably connected with unknown2 + uint32_t max_size; // max_size in cos.xml which defines the maximum amount of memory reserved for the app + uint32_t avail_size; // avail_size or codegen_size in cos.xml (seems to mostly be 0?) + uint32_t codegen_size; // codegen_size or avail_size in cos.xml (seems to mostly be 0?) + uint32_t codegen_core; // codegen_core in cos.xml (seems to mostly be 1?) + uint32_t max_codesize; // max_codesize in cos.xml + uint32_t overlay_arena; // overlay_arena in cos.xml + uint32_t unknown4[59]; // all zeros it seems + uint32_t default_stack0_size; // not sure because always 0 but very likely + uint32_t default_stack1_size; // not sure because always 0 but very likely + uint32_t default_stack2_size; // not sure because always 0 but very likely + uint32_t default_redzone0_size; // not sure because always 0 but very likely + uint32_t default_redzone1_size; // not sure because always 0 but very likely + uint32_t default_redzone2_size; // not sure because always 0 but very likely + uint32_t exception_stack0_size; // from cos.xml, 0x1000 on mii maker + uint32_t exception_stack1_size; // from cos.xml, 0x1000 on mii maker + uint32_t exception_stack2_size; // from cos.xml, 0x1000 on mii maker + uint32_t sdk_version; // from app.xml, 20909 (0x51AD) on mii maker + uint32_t title_version; // from app.xml, 0x32 on mii maker + /* + // --------------------------------------------------------------------------------------------------------------------------------------------- + // the next part might be changing from title to title?! I don't think its important but nice to know maybe.... + // --------------------------------------------------------------------------------------------------------------------------------------------- + char mlc[4]; // string "mlc" on mii maker and sysmenu + uint32_t unknown5[7]; // all zeros on mii maker and sysmenu + uint32_t unknown6_one; // 0x01 on mii maker and sysmenu + // --------------------------------------------------------------------------------------------------------------------------------------------- + char ACP[4]; // string "ACP" on mii maker and sysmenu + uint32_t unknown7[15]; // all zeros on mii maker and sysmenu + uint32_t unknown8_5; // 0x05 on mii maker and sysmenu + uint32_t unknown9_zero; // 0x00 on mii maker and sysmenu + uint32_t unknown10_ptr; // 0xFF23DD0C pointer on mii maker and sysmenu + // --------------------------------------------------------------------------------------------------------------------------------------------- + char UVD[4]; // string "UVD" on mii maker and sysmenu + uint32_t unknown11[15]; // all zeros on mii maker and sysmenu + uint32_t unknown12_5; // 0x05 on mii maker and sysmenu + uint32_t unknown13_zero; // 0x00 on mii maker and sysmenu + uint32_t unknown14_ptr; // 0xFF23EFC8 pointer on mii maker and sysmenu + // --------------------------------------------------------------------------------------------------------------------------------------------- + char SND[4]; // string "SND" on mii maker and sysmenu + uint32_t unknown15[15]; // all zeros on mii maker and sysmenu + uint32_t unknown16_5; // 0x05 on mii maker and sysmenu + uint32_t unknown17_zero; // 0x00 on mii maker and sysmenu + uint32_t unknown18_ptr; // 0xFF23F014 pointer on mii maker and sysmenu + // --------------------------------------------------------------------------------------------------------------------------------------------- + uint32_t unknown19; // 0x02 on miimaker, 0x0F on system menu + */ + // after that only zeros follow +} __attribute__((packed)) CosAppXmlInfo; + + +// Our own cos/app.xml struct which uses only uses as much memory as really needed, since many things are just zeros in the above structure +// This structure is only 0x64 bytes long + RPX name length (dynamic up to 0x1000 theoretically) +typedef struct +{ + uint32_t version_cos_xml; // version tag from cos.xml + uint64_t os_version; // os_version from app.xml + uint64_t title_id; // title_id tag from app.xml + uint32_t app_type; // app_type tag from app.xml + uint32_t cmdFlags; // unknown tag as it is always 0 (might be cmdFlags from cos.xml but i am not sure) + uint32_t max_size; // max_size in cos.xml which defines the maximum amount of memory reserved for the app + uint32_t avail_size; // avail_size or codegen_size in cos.xml (seems to mostly be 0?) + uint32_t codegen_size; // codegen_size or avail_size in cos.xml (seems to mostly be 0?) + uint32_t codegen_core; // codegen_core in cos.xml (seems to mostly be 1?) + uint32_t max_codesize; // max_codesize in cos.xml + uint32_t overlay_arena; // overlay_arena in cos.xml + uint32_t default_stack0_size; // not sure because always 0 but very likely + uint32_t default_stack1_size; // not sure because always 0 but very likely + uint32_t default_stack2_size; // not sure because always 0 but very likely + uint32_t default_redzone0_size; // not sure because always 0 but very likely + uint32_t default_redzone1_size; // not sure because always 0 but very likely + uint32_t default_redzone2_size; // not sure because always 0 but very likely + uint32_t exception_stack0_size; // from cos.xml, 0x1000 on mii maker + uint32_t exception_stack1_size; // from cos.xml, 0x1000 on mii maker + uint32_t exception_stack2_size; // from cos.xml, 0x1000 on mii maker + uint32_t sdk_version; // from app.xml, 20909 (0x51AD) on mii maker + uint32_t title_version; // from app.xml, 0x32 on mii maker + char rpx_name[FS_MAX_ENTNAME_SIZE]; // rpx name from cos.xml, length 256 as it can't get bigger from FS anyway +} __attribute__((packed)) ReducedCosAppXmlInfo; + + +#endif // __KERNEL_DEFS_H_ diff --git a/src/common/loader_defs.h b/src/common/loader_defs.h new file mode 100644 index 0000000..2880d33 --- /dev/null +++ b/src/common/loader_defs.h @@ -0,0 +1,20 @@ +#ifndef __LOADER_DEFS_H_ +#define __LOADER_DEFS_H_ + +#include "types.h" + +// struct holding the globals of the loader (there are actually more but we don't need others) +typedef struct _loader_globals_t +{ + int sgIsLoadingBuffer; + int sgFileType; + int sgProcId; + int sgGotBytes; + int sgFileOffset; + int sgBufferNumber; + int sgBounceError; + char sgLoadName[0x1000]; +} __attribute__((packed)) loader_globals_t; + + +#endif // __LOADER_DEFS_H_ diff --git a/common/types.h b/src/common/types.h old mode 100755 new mode 100644 similarity index 100% rename from common/types.h rename to src/common/types.h diff --git a/fs/fs.c b/src/fs/fs.c old mode 100755 new mode 100644 similarity index 86% rename from fs/fs.c rename to src/fs/fs.c index 3076863..edda3df --- a/fs/fs.c +++ b/src/fs/fs.c @@ -1,6 +1,9 @@ #include "fs.h" -#include "exception_handler.h" #include "../common/common.h" +#include "../utils/exception_handler.h" +#include "../utils/logger.h" +#include "../utils/strings.h" +#include "../utils/utils.h" #define USE_EXTRA_LOG_FUNCTIONS 0 @@ -13,42 +16,6 @@ int FSAddClientEx(void *r3, void *r4, void *r5); int FSDelClient(void *pClient); -/* Log functions */ -//static const struct { -// const int tag; -// const char *name; -//} tag_names[] = { -// { 1, "LOADER_Start" }, -// { 2, "LOADER_Entry" }, -// { 3, "LOADER_Prep" }, -// { 4, "LiLoadRPLBasics_in_1_load" }, -// { 5, "GetNextBounce_1" }, -// { 6, "GetNextBounce_2" }, -// { 7, "After_GetBounce" }, -// { 8, "GetNextBounce result end" }, -//}; -// -//static const char *get_name_for_tag(int tag) { -// int i = 0; -// for(i = 0; i < sizeof(tag_names) / sizeof(tag_names[0]); i++) -// if(tag == tag_names[i].tag) -// return tag_names[i].name; -// -// return "unknown"; -//} - -/* Common useful functions */ -static inline int toupper(int c) { - return (c >= 'a' && c <= 'z') ? (c - 0x20) : c; -} - -static int strlen(const char* path) { - int i = 0; - while (path[i]) - i++; - return i; -} - /* Client functions */ static int client_num_alloc(void *pClient) { int i; @@ -76,7 +43,7 @@ static int client_num(void *pClient) { return -1; } -static int is_gamefile(char *path) { +static int is_gamefile(const char *path) { // In case the path starts by "//" and not "/" (some games do that ... ...) if (path[0] == '/' && path[1] == '/') path = &path[1]; @@ -109,7 +76,7 @@ static int is_gamefile(char *path) { return 1; } -static int is_savefile(char *path) { +static int is_savefile(const char *path) { // In case the path starts by "//" and not "/" (some games do that ... ...) if (path[0] == '/' && path[1] == '/') @@ -141,7 +108,7 @@ static int is_savefile(char *path) { return 1; } -static void compute_new_path(char* new_path, char* path, int len, int is_save) { +static void compute_new_path(char* new_path, const char* path, int len, int is_save) { int i, n, path_offset = 0; // In case the path starts by "//" and not "/" (some games do that ... ...) @@ -153,9 +120,7 @@ static void compute_new_path(char* new_path, char* path, int len, int is_save) { path_offset = -1; if (!is_save) { - for (n = 0; n < sizeof(bss.mount_base) && bss.mount_base[n] != 0; n++) { - new_path[n] = bss.mount_base[n]; - } + n = strlcpy(new_path, bss.mount_base, sizeof(bss.mount_base)); // copy the content file path with slash at the beginning for (i = 0; i < (len - 12 - path_offset); i++) { @@ -170,8 +135,7 @@ static void compute_new_path(char* new_path, char* path, int len, int is_save) { new_path[n++] = '\0'; } else { - for (n = 0; n < sizeof(bss.save_base) && bss.save_base[n] != 0; n++) - new_path[n] = bss.save_base[n]; + n = strlcpy(new_path, bss.save_base, sizeof(bss.save_base)); new_path[n++] = '/'; // Create path for common and user dirs @@ -216,15 +180,17 @@ static int GetCurClient(void *pClient) { } return -1; } - -/* ***************************************************************************** - * Base functions - * ****************************************************************************/ - +#include "../common/kernel_defs.h" DECL(int, FSInit, void) { if ((int)bss_ptr == 0x0a000000) { - bss_ptr = memalign(sizeof(struct bss_t), 0x40); + // allocate memory for our stuff + void *mem_ptr = memalign(sizeof(struct bss_t), 0x40); + if(!mem_ptr) + return real_FSInit(); + + // copy pointer + bss_ptr = mem_ptr; memset(bss_ptr, 0, sizeof(struct bss_t)); // setup exceptions @@ -235,8 +201,8 @@ DECL(int, FSInit, void) { // create game save path prefix __os_snprintf(bss.save_base, sizeof(bss.save_base), "%s%s/%s", CAFE_OS_SD_PATH, SD_SAVES_PATH, GAME_DIR_NAME); - fs_connect(&bss.global_sock); - + logger_connect(&bss.global_sock); + // Call real FSInit int result = real_FSInit(); @@ -256,18 +222,20 @@ DECL(int, FSInit, void) { FSAddClientEx(pClient, 0, FS_RET_NO_ERROR); fs_mount_sd(bss.global_sock, pClient, pCmd); - + FSDelClient(pClient); MEMFreeToDefaultHeap(pCmd); MEMFreeToDefaultHeap(pClient); - + return result; } return real_FSInit(); } + DECL(int, FSShutdown, void) { if ((int)bss_ptr != 0x0a000000) { - fs_disconnect(bss.global_sock); + logger_disconnect(bss.global_sock); + bss.global_sock = -1; } return real_FSShutdown(); } @@ -279,7 +247,7 @@ DECL(int, FSAddClientEx, void *r3, void *r4, void *r5) { if (GAME_RPX_LOADED != 0) { int client = client_num_alloc(r3); if (client >= 0) { - if (fs_connect(&bss.socket_fs[client]) != 0) + if (logger_connect(&bss.socket_fs[client]) != 0) client_num_free(client); } } @@ -287,11 +255,12 @@ DECL(int, FSAddClientEx, void *r3, void *r4, void *r5) { return res; } + DECL(int, FSDelClient, void *pClient) { if ((int)bss_ptr != 0x0a000000) { int client = client_num(pClient); if (client >= 0) { - fs_disconnect(bss.socket_fs[client]); + logger_disconnect(bss.socket_fs[client]); client_num_free(client); } } @@ -304,7 +273,7 @@ DECL(int, FSDelClient, void *pClient) { /* ***************************************************************************** * Replacement functions * ****************************************************************************/ -DECL(int, FSGetStat, void *pClient, void *pCmd, char *path, void *stats, int error) { +DECL(int, FSGetStat, void *pClient, void *pCmd, const char *path, void *stats, int error) { int client = GetCurClient(pClient); if (client != -1) { // log @@ -326,7 +295,7 @@ DECL(int, FSGetStat, void *pClient, void *pCmd, char *path, void *stats, int err return real_FSGetStat(pClient, pCmd, path, stats, error); } -DECL(int, FSGetStatAsync, void *pClient, void *pCmd, char *path, void *stats, int error, FSAsyncParams *asyncParams) { +DECL(int, FSGetStatAsync, void *pClient, void *pCmd, const char *path, void *stats, int error, FSAsyncParams *asyncParams) { int client = GetCurClient(pClient); if (client != -1) { // log @@ -347,7 +316,8 @@ DECL(int, FSGetStatAsync, void *pClient, void *pCmd, char *path, void *stats, in return real_FSGetStatAsync(pClient, pCmd, path, stats, error, asyncParams); } -DECL(int, FSOpenFile, void *pClient, void *pCmd, char *path, char *mode, int *handle, int error) { +DECL(int, FSOpenFile, void *pClient, void *pCmd, const char *path, const char *mode, int *handle, int error) { +/* int client = GetCurClient(pClient); if (client != -1) { // log @@ -365,11 +335,11 @@ DECL(int, FSOpenFile, void *pClient, void *pCmd, char *path, char *mode, int *ha return real_FSOpenFile(pClient, pCmd, new_path, mode, handle, error); } } - +*/ return real_FSOpenFile(pClient, pCmd, path, mode, handle, error); } -DECL(int, FSOpenFileAsync, void *pClient, void *pCmd, char *path, char *mode, int *handle, int error, FSAsyncParams *asyncParams) { +DECL(int, FSOpenFileAsync, void *pClient, void *pCmd, const char *path, const char *mode, int *handle, int error, const FSAsyncParams *asyncParams) { int client = GetCurClient(pClient); if (client != -1) { // log @@ -389,7 +359,7 @@ DECL(int, FSOpenFileAsync, void *pClient, void *pCmd, char *path, char *mode, in return real_FSOpenFileAsync(pClient, pCmd, path, mode, handle, error, asyncParams); } -DECL(int, FSOpenDir, void *pClient, void* pCmd, char *path, int *handle, int error) { +DECL(int, FSOpenDir, void *pClient, void* pCmd, const char *path, int *handle, int error) { int client = GetCurClient(pClient); if (client != -1) { // log @@ -409,7 +379,7 @@ DECL(int, FSOpenDir, void *pClient, void* pCmd, char *path, int *handle, int err return real_FSOpenDir(pClient, pCmd, path, handle, error); } -DECL(int, FSOpenDirAsync, void *pClient, void* pCmd, char *path, int *handle, int error, FSAsyncParams *asyncParams) { +DECL(int, FSOpenDirAsync, void *pClient, void* pCmd, const char *path, int *handle, int error, FSAsyncParams *asyncParams) { int client = GetCurClient(pClient); if (client != -1) { // log @@ -449,7 +419,7 @@ DECL(int, FSChangeDir, void *pClient, void *pCmd, char *path, int error) { return real_FSChangeDir(pClient, pCmd, path, error); } -DECL(int, FSChangeDirAsync, void *pClient, void *pCmd, char *path, int error, FSAsyncParams *asyncParams) { +DECL(int, FSChangeDirAsync, void *pClient, void *pCmd, const char *path, int error, FSAsyncParams *asyncParams) { int client = GetCurClient(pClient); if (client != -1) { // log @@ -470,7 +440,7 @@ DECL(int, FSChangeDirAsync, void *pClient, void *pCmd, char *path, int error, FS } // only for saves on sdcard -DECL(int, FSMakeDir, void *pClient, void *pCmd, char *path, int error) { +DECL(int, FSMakeDir, void *pClient, void *pCmd, const char *path, int error) { int client = GetCurClient(pClient); if (client != -1) { // log @@ -493,7 +463,7 @@ DECL(int, FSMakeDir, void *pClient, void *pCmd, char *path, int error) { } // only for saves on sdcard -DECL(int, FSMakeDirAsync, void *pClient, void *pCmd, char *path, int error, FSAsyncParams *asyncParams) { +DECL(int, FSMakeDirAsync, void *pClient, void *pCmd, const char *path, int error, FSAsyncParams *asyncParams) { int client = GetCurClient(pClient); if (client != -1) { // log @@ -516,7 +486,7 @@ DECL(int, FSMakeDirAsync, void *pClient, void *pCmd, char *path, int error, FSAs } // only for saves on sdcard -DECL(int, FSRename, void *pClient, void *pCmd, char *oldPath, char *newPath, int error) { +DECL(int, FSRename, void *pClient, void *pCmd, const char *oldPath, const char *newPath, int error) { int client = GetCurClient(pClient); if (client != -1) { // log @@ -547,7 +517,7 @@ DECL(int, FSRename, void *pClient, void *pCmd, char *oldPath, char *newPath, int } // only for saves on sdcard -DECL(int, FSRenameAsync, void *pClient, void *pCmd, char *oldPath, char *newPath, int error, FSAsyncParams *asyncParams) { +DECL(int, FSRenameAsync, void *pClient, void *pCmd, const char *oldPath, const char *newPath, int error, FSAsyncParams *asyncParams) { int client = GetCurClient(pClient); if (client != -1) { // log @@ -578,7 +548,7 @@ DECL(int, FSRenameAsync, void *pClient, void *pCmd, char *oldPath, char *newPath } // only for saves on sdcard -DECL(int, FSRemove, void *pClient, void *pCmd, char *path, int error) { +DECL(int, FSRemove, void *pClient, void *pCmd, const char *path, int error) { int client = GetCurClient(pClient); if (client != -1) { // log @@ -601,7 +571,7 @@ DECL(int, FSRemove, void *pClient, void *pCmd, char *path, int error) { } // only for saves on sdcard -DECL(int, FSRemoveAsync, void *pClient, void *pCmd, char *path, int error, FSAsyncParams *asyncParams) { +DECL(int, FSRemoveAsync, void *pClient, void *pCmd, const char *path, int error, FSAsyncParams *asyncParams) { int client = GetCurClient(pClient); if (client != -1) { // log @@ -623,7 +593,7 @@ DECL(int, FSRemoveAsync, void *pClient, void *pCmd, char *path, int error, FSAsy return real_FSRemoveAsync(pClient, pCmd, path, error, asyncParams); } -DECL(int, FSFlushQuota, void *pClient, void *pCmd, char* path, int error) { +DECL(int, FSFlushQuota, void *pClient, void *pCmd, const char* path, int error) { int client = GetCurClient(pClient); if (client != -1) { // log @@ -647,7 +617,7 @@ DECL(int, FSFlushQuota, void *pClient, void *pCmd, char* path, int error) { } return real_FSFlushQuota(pClient, pCmd, path, error); } -DECL(int, FSFlushQuotaAsync, void *pClient, void *pCmd, char *path, int error, FSAsyncParams *asyncParams) { +DECL(int, FSFlushQuotaAsync, void *pClient, void *pCmd, const char *path, int error, FSAsyncParams *asyncParams) { int client = GetCurClient(pClient); if (client != -1) { // log @@ -672,7 +642,7 @@ DECL(int, FSFlushQuotaAsync, void *pClient, void *pCmd, char *path, int error, F return real_FSFlushQuotaAsync(pClient, pCmd, path, error, asyncParams); } -DECL(int, FSGetFreeSpaceSize, void *pClient, void *pCmd, char *path, uint64_t *returnedFreeSize, int error) { +DECL(int, FSGetFreeSpaceSize, void *pClient, void *pCmd, const char *path, uint64_t *returnedFreeSize, int error) { int client = GetCurClient(pClient); if (client != -1) { // log @@ -696,7 +666,7 @@ DECL(int, FSGetFreeSpaceSize, void *pClient, void *pCmd, char *path, uint64_t *r } return real_FSGetFreeSpaceSize(pClient, pCmd, path, returnedFreeSize, error); } -DECL(int, FSGetFreeSpaceSizeAsync, void *pClient, void *pCmd, char *path, uint64_t *returnedFreeSize, int error, FSAsyncParams *asyncParams) { +DECL(int, FSGetFreeSpaceSizeAsync, void *pClient, void *pCmd, const char *path, uint64_t *returnedFreeSize, int error, FSAsyncParams *asyncParams) { int client = GetCurClient(pClient); if (client != -1) { // log @@ -721,7 +691,7 @@ DECL(int, FSGetFreeSpaceSizeAsync, void *pClient, void *pCmd, char *path, uint64 return real_FSGetFreeSpaceSizeAsync(pClient, pCmd, path, returnedFreeSize, error, asyncParams); } -DECL(int, FSRollbackQuota, void *pClient, void *pCmd, char *path, int error) { +DECL(int, FSRollbackQuota, void *pClient, void *pCmd, const char *path, int error) { int client = GetCurClient(pClient); if (client != -1) { // log @@ -744,7 +714,7 @@ DECL(int, FSRollbackQuota, void *pClient, void *pCmd, char *path, int error) { } return real_FSRollbackQuota(pClient, pCmd, path, error); } -DECL(int, FSRollbackQuotaAsync, void *pClient, void *pCmd, char *path, int error, FSAsyncParams *asyncParams) { +DECL(int, FSRollbackQuotaAsync, void *pClient, void *pCmd, const char *path, int error, FSAsyncParams *asyncParams) { int client = GetCurClient(pClient); if (client != -1) { // log @@ -903,17 +873,7 @@ static int CheckAndLoadRPL(const char *rpl) { } // compare name string case insensitive and without ".rpl" extension - int found = 1; - for (int x = 0; x < len; x++) - { - if (toupper(rpl_entry->name[x]) != toupper(rpl[x])) - { - found = 0; - break; - } - } - - if (found) + if (strncasecmp(rpl_entry->name, rpl, len) == 0) return LoadRPLToMemory(rpl_entry); } while((rpl_entry = rpl_entry->next) != 0); @@ -1068,47 +1028,47 @@ DECL(int, FSGetVolumeState_log, void *pClient) { } #endif - /* ***************************************************************************** * Creates function pointer array * ****************************************************************************/ -#define MAKE_MAGIC(x) { x, my_ ## x, &real_ ## x } +#define MAKE_MAGIC(x, orig_instr) { x, my_ ## x, &real_ ## x, orig_instr } -struct magic_t { +const struct fs_magic_t { const void *real; const void *replacement; const void *call; -} methods[] __attribute__((section(".magic"))) = { + const unsigned int orig_instr; +} fs_methods[] __attribute__((section(".fs_magic"))) = { // Common FS functions - MAKE_MAGIC(FSInit), - MAKE_MAGIC(FSShutdown), - MAKE_MAGIC(FSAddClientEx), - MAKE_MAGIC(FSDelClient), + MAKE_MAGIC(FSInit, 0x7C0802A6), + MAKE_MAGIC(FSShutdown, 0x4E800020), + MAKE_MAGIC(FSAddClientEx, 0x9421FFD8), + MAKE_MAGIC(FSDelClient, 0x7C0802A6), // Replacement functions - MAKE_MAGIC(FSGetStat), - MAKE_MAGIC(FSGetStatAsync), - MAKE_MAGIC(FSOpenFile), - MAKE_MAGIC(FSOpenFileAsync), - MAKE_MAGIC(FSOpenDir), - MAKE_MAGIC(FSOpenDirAsync), - MAKE_MAGIC(FSChangeDir), - MAKE_MAGIC(FSChangeDirAsync), - MAKE_MAGIC(FSMakeDir), - MAKE_MAGIC(FSMakeDirAsync), - MAKE_MAGIC(FSRename), - MAKE_MAGIC(FSRenameAsync), - MAKE_MAGIC(FSRemove), - MAKE_MAGIC(FSRemoveAsync), - MAKE_MAGIC(FSFlushQuota), - MAKE_MAGIC(FSFlushQuotaAsync), - MAKE_MAGIC(FSGetFreeSpaceSize), - MAKE_MAGIC(FSGetFreeSpaceSizeAsync), - MAKE_MAGIC(FSRollbackQuota), - MAKE_MAGIC(FSRollbackQuotaAsync), + MAKE_MAGIC(FSGetStat, 0x9421FFD8), + MAKE_MAGIC(FSGetStatAsync, 0x7D094378), + MAKE_MAGIC(FSOpenFile, 0x9421FFD0), + MAKE_MAGIC(FSOpenFileAsync, 0x7C0802A6), + MAKE_MAGIC(FSOpenDir, 0x9421FFD8), + MAKE_MAGIC(FSOpenDirAsync, 0x9421FFE0), + MAKE_MAGIC(FSChangeDir, 0x7C0802A6), + MAKE_MAGIC(FSChangeDirAsync, 0x7C0802A6), + MAKE_MAGIC(FSMakeDir, 0x7C0802A6), + MAKE_MAGIC(FSMakeDirAsync, 0x7C0802A6), + MAKE_MAGIC(FSRename, 0x9421FFD8), + MAKE_MAGIC(FSRenameAsync, 0x9421FFE0), + MAKE_MAGIC(FSRemove, 0x7C0802A6), + MAKE_MAGIC(FSRemoveAsync, 0x7C0802A6), + MAKE_MAGIC(FSFlushQuota, 0x7C0802A6), + MAKE_MAGIC(FSFlushQuotaAsync, 0x7C0802A6), + MAKE_MAGIC(FSGetFreeSpaceSize, 0x9421FFD8), + MAKE_MAGIC(FSGetFreeSpaceSizeAsync, 0x7D094378), + MAKE_MAGIC(FSRollbackQuota, 0x7C0802A6), + MAKE_MAGIC(FSRollbackQuotaAsync, 0x7C0802A6), // Dynamic RPL loading functions - MAKE_MAGIC(OSDynLoad_Acquire), + MAKE_MAGIC(OSDynLoad_Acquire, 0x38A00000), #if (USE_EXTRA_LOG_FUNCTIONS == 1) MAKE_MAGIC(OSDynLoad_GetModuleName), MAKE_MAGIC(OSDynLoad_IsModuleLoaded), @@ -1135,3 +1095,29 @@ struct magic_t { MAKE_MAGIC(FSGetVolumeState_log), #endif }; + +/* a buffer to place all the replaced instructions and calls to the real functions */ +const unsigned char fs_methods_calls[sizeof(fs_methods)] __attribute__((section(".fs_method_calls"))); + +void PatchFsMethods(void) +{ + static uint8_t ucFsMethodsPatched = 0; + if(!ucFsMethodsPatched) + { + ucFsMethodsPatched = 1; + /* Patch branches to it. */ + int len = sizeof(fs_methods) / sizeof(struct fs_magic_t); + while (len--) { + unsigned int real_addr = (unsigned int)fs_methods[len].real; + unsigned int repl_addr = (unsigned int)fs_methods[len].replacement; + + unsigned int replace_instr = 0x48000002 | (repl_addr & 0x03fffffc); + + if(*(volatile unsigned int *)(0xC1000000 + real_addr) != replace_instr) { + // in the real function, replace the "mflr r0" instruction by a jump to the replacement function + *(volatile unsigned int *)(0xC1000000 + real_addr) = replace_instr; + FlushBlock((0xC1000000 + real_addr)); + } + } + } +} diff --git a/src/fs/fs.h b/src/fs/fs.h new file mode 100644 index 0000000..876a7c2 --- /dev/null +++ b/src/fs/fs.h @@ -0,0 +1,44 @@ +#ifndef _FS_H_ +#define _FS_H_ + +#include "../common/fs_defs.h" + +extern void GX2WaitForVsync(void); + +/* OS stuff */ +extern void DCFlushRange(const void *p, unsigned int s); + +/* SDCard functions */ +extern FSStatus FSGetMountSource(void *pClient, void *pCmd, FSSourceType type, FSMountSource *source, FSRetFlag errHandling); +extern FSStatus FSMount(void *pClient, void *pCmd, FSMountSource *source, char *target, uint bytes, FSRetFlag errHandling); +extern FSStatus FSReadFile(FSClient *pClient, FSCmdBlock *pCmd, void *buffer, int size, int count, int fd, FSFlag flag, FSRetFlag errHandling); +extern void FSInitCmdBlock(FSCmdBlock *pCmd); +extern FSStatus FSCloseFile(FSClient *pClient, FSCmdBlock *pCmd, int fd, int error); + +/* Async callback definition */ +typedef void (*FSAsyncCallback)(void *pClient, void *pCmd, int result, void *context); +typedef struct +{ + FSAsyncCallback userCallback; + void *userContext; + void *ioMsgQueue; +} FSAsyncParams; + +/* Forward declarations */ +#define MAX_CLIENT 32 + +struct bss_t { + int global_sock; + int socket_fs[MAX_CLIENT]; + void *pClient_fs[MAX_CLIENT]; + volatile int lock; + char mount_base[255]; + char save_base[255]; +}; + +#define bss_ptr (*(struct bss_t **)0x100000e4) +#define bss (*bss_ptr) + +void PatchFsMethods(void); + +#endif /* _FS_H */ diff --git a/src/kernel/kernel_functions.c b/src/kernel/kernel_functions.c new file mode 100644 index 0000000..5c997b4 --- /dev/null +++ b/src/kernel/kernel_functions.c @@ -0,0 +1,69 @@ +#include "../common/common.h" +#include "../common/kernel_defs.h" +#include "../utils/strings.h" + +/* our BSS struct */ +extern ReducedCosAppXmlInfo cosAppXmlInfoStruct; + +/* + * This function is a kernel hook function. It is called directly from kernel code at position 0xFFF18558. + */ +void my_PrepareTitle(CosAppXmlInfo *xmlKernelInfo) +{ + /* + * Setup a DBAT access for our 0xC0800000 area and our 0xBC000000 area which hold our variables like GAME_LAUNCHED and our BSS/rodata section + */ + register int dbatu0, dbatl0, dbatu1, dbatl1; + // save the original DBAT value + asm volatile("mfdbatu %0, 0" : "=r" (dbatu0)); + asm volatile("mfdbatl %0, 0" : "=r" (dbatl0)); + asm volatile("mfdbatu %0, 1" : "=r" (dbatu1)); + asm volatile("mfdbatl %0, 1" : "=r" (dbatl1)); + // write our own DBATs into the array + asm volatile("mtdbatu 0, %0" : : "r" (0xC0001FFF)); + asm volatile("mtdbatl 0, %0" : : "r" (0x30000012)); + asm volatile("mtdbatu 1, %0" : : "r" (0xB0801FFF)); + asm volatile("mtdbatl 1, %0" : : "r" (0x20800012)); + asm volatile("eieio; isync"); + + + //! TODO: add Smash Bros IDs for the check? + // check for Mii Maker ID (region independent check) + if(GAME_LAUNCHED && (xmlKernelInfo->title_id & 0xFFFFFFFFFFFFF0FF) == 0x000500101004A000) + { + //! Copy all data from the parsed XML info + strlcpy(xmlKernelInfo->rpx_name, cosAppXmlInfoStruct.rpx_name, sizeof(cosAppXmlInfoStruct.rpx_name)); + + xmlKernelInfo->version_cos_xml = cosAppXmlInfoStruct.version_cos_xml; + xmlKernelInfo->os_version = cosAppXmlInfoStruct.os_version; + xmlKernelInfo->title_id = cosAppXmlInfoStruct.title_id; + xmlKernelInfo->app_type = cosAppXmlInfoStruct.app_type; + xmlKernelInfo->cmdFlags = cosAppXmlInfoStruct.cmdFlags; + xmlKernelInfo->max_size = cosAppXmlInfoStruct.max_size; + xmlKernelInfo->avail_size = cosAppXmlInfoStruct.avail_size; + xmlKernelInfo->codegen_size = cosAppXmlInfoStruct.codegen_size; + xmlKernelInfo->codegen_core = cosAppXmlInfoStruct.codegen_core; + xmlKernelInfo->max_codesize = cosAppXmlInfoStruct.max_codesize; + xmlKernelInfo->overlay_arena = cosAppXmlInfoStruct.overlay_arena; + xmlKernelInfo->default_stack0_size = cosAppXmlInfoStruct.default_stack0_size; + xmlKernelInfo->default_stack1_size = cosAppXmlInfoStruct.default_stack1_size; + xmlKernelInfo->default_stack2_size = cosAppXmlInfoStruct.default_stack2_size; + xmlKernelInfo->default_redzone0_size = cosAppXmlInfoStruct.default_redzone0_size; + xmlKernelInfo->default_redzone1_size = cosAppXmlInfoStruct.default_redzone1_size; + xmlKernelInfo->default_redzone2_size = cosAppXmlInfoStruct.default_redzone2_size; + xmlKernelInfo->exception_stack0_size = cosAppXmlInfoStruct.exception_stack0_size; + xmlKernelInfo->exception_stack1_size = cosAppXmlInfoStruct.exception_stack1_size; + xmlKernelInfo->exception_stack2_size = cosAppXmlInfoStruct.exception_stack2_size; + xmlKernelInfo->sdk_version = cosAppXmlInfoStruct.sdk_version; + xmlKernelInfo->title_version = cosAppXmlInfoStruct.title_version; + } + + /* + * Restore original DBAT value + */ + asm volatile("mfdbatu %0, 0" : "=r" (dbatu0)); + asm volatile("mfdbatl %0, 0" : "=r" (dbatl0)); + asm volatile("mfdbatu %0, 1" : "=r" (dbatu1)); + asm volatile("mfdbatl %0, 1" : "=r" (dbatl1)); + asm volatile("eieio; isync"); +} diff --git a/src/kernel/kernel_hooks.S b/src/kernel/kernel_hooks.S new file mode 100644 index 0000000..6d38ba6 --- /dev/null +++ b/src/kernel/kernel_hooks.S @@ -0,0 +1,110 @@ + +.section ".kernel_code" + .globl SaveAndResetDataBATs_And_SRs_hook +SaveAndResetDataBATs_And_SRs_hook: + # restore the kernel instructions that we replaced + li r7, 1 + mtsr 0, r7 + mtsr 1, r7 + mtsr 2, r7 + mtsr 3, r7 + mtsr 4, r7 + mtsr 5, r7 + mtsr 6, r7 + mtsr 7, r7 + mtsr 8, r7 + mtsr 9, r7 + mtsr 10, r7 + mtsr 11, r7 + mtsr 12, r7 + mtsr 13, r7 + mtsr 14, r7 + mtsr 15, r4 + isync + + # call back the position in kernel after our patch + lis r7, 0xFFF1 + ori r7, r7, 0xD78C + mtctr r7 + bctr + +.extern my_PrepareTitle +.section ".kernel_code" + .globl my_PrepareTitle_hook +my_PrepareTitle_hook: + # store all registers on stack to avoid issues with the call to C functions + stwu r1, -0x90(r1) + # registers for our own usage + # only need r31 and rest is from tests before, just leaving it for later tests + stw r28, 0x20(r1) + stw r29, 0x24(r1) + stw r30, 0x28(r1) + stw r31, 0x2C(r1) + + stw r3, 0x30(r1) + stw r4, 0x34(r1) + stw r5, 0x38(r1) + stw r6, 0x3C(r1) + stw r7, 0x40(r1) + stw r8, 0x44(r1) + stw r9, 0x48(r1) + stw r10, 0x4C(r1) + stw r11, 0x50(r1) + stw r12, 0x54(r1) + stw r13, 0x58(r1) + stw r14, 0x5C(r1) + stw r15, 0x60(r1) + stw r16, 0x64(r1) + stw r17, 0x68(r1) + stw r18, 0x6C(r1) + stw r19, 0x70(r1) + stw r20, 0x74(r1) + stw r21, 0x78(r1) + stw r22, 0x7C(r1) + + # the cos.xml/app.xml structure is at the location 0x68 of r11 + # there are actually many places that can be hooked for it + # e.g. 0xFFF16130 and r27 points to this structure + addi r3, r11, 0x68 + bl my_PrepareTitle + + # setup CTR to jump back to kernel code + lis r31, 0xFFF1 + ori r31, r31, 0x855C + mtspr CTR, r31 + + # restore all original values of registers from stack + lwz r28, 0x20(r1) + lwz r29, 0x24(r1) + lwz r30, 0x28(r1) + lwz r31, 0x2C(r1) + + lwz r3, 0x30(r1) + lwz r4, 0x34(r1) + lwz r5, 0x38(r1) + lwz r6, 0x3C(r1) + lwz r7, 0x40(r1) + lwz r8, 0x44(r1) + lwz r9, 0x48(r1) + lwz r10, 0x4C(r1) + lwz r11, 0x50(r1) + lwz r12, 0x54(r1) + lwz r13, 0x58(r1) + lwz r14, 0x5C(r1) + lwz r15, 0x60(r1) + lwz r16, 0x64(r1) + lwz r17, 0x68(r1) + lwz r18, 0x6C(r1) + lwz r19, 0x70(r1) + lwz r20, 0x74(r1) + lwz r21, 0x78(r1) + lwz r22, 0x7C(r1) + + # restore the stack + addi r1, r1, 0x90 + + # restore original instruction that we replaced in the kernel + clrlwi r7, r12, 0 + + # jump back + bctr diff --git a/fs/fs532.ld b/src/link.ld old mode 100755 new mode 100644 similarity index 61% rename from fs/fs532.ld rename to src/link.ld index 6cd4488..0b36cd9 --- a/fs/fs532.ld +++ b/src/link.ld @@ -1,24 +1,42 @@ -OUTPUT(fs532.elf); +OUTPUT(loadiine.elf); SECTIONS { - .text 0x011df800 : { - server_ip = .; - . = . + 4; - *(.text._start); + .kernel_code 0x00AE1000 : { + *(.kernel_code*); + } + . = .; + .text : { *(.text*); - *(.magicptr*); } - .magic : { - *(.magic*); + .menu_magic : { + *(.menu_magic*); + } + .loader_magic : { + *(.loader_magic*); + } + .fs_method_calls : { + *(.fs_method_calls*); } + . = . + 0xBC000000; .rodata : { *(.rodata*); } + .bss : { + *(.bss*); + } + .fs_magic : { + *(.fs_magic*); + } + .magicptr 0x011DD000 : { + *(.magicptr*); + } /DISCARD/ : { *(*); } } +/******************************************************** FS ********************************************************/ +/* coreinit.rpl difference in addresses 0xFE3C00 */ /* FSA methods */ PROVIDE(FSAInit = 0x10608ac); PROVIDE(FSAShutdown = 0x1060974); @@ -29,6 +47,7 @@ PROVIDE(FSAOpenFile = 0x10621f8); /* FS base methods */ PROVIDE(FSInit = 0x10683c8); PROVIDE(FSShutdown = 0x1068538); +PROVIDE(FSAddClient = 0x010689fc); PROVIDE(FSAddClientEx = 0x10685fc); PROVIDE(FSDelClient = 0x1068a08); PROVIDE(FSInitCmdBlock = 0x01068c54); @@ -55,9 +74,11 @@ PROVIDE(FSGetFreeSpaceSizeAsync = 0x0106c008); PROVIDE(FSRollbackQuota = 0x0106fc48); PROVIDE(FSRollbackQuotaAsync = 0x0106bb50); -/* FS methods - Used by Dynamic RPL loading */ +/* FS methods - not replaced */ +PROVIDE(FSReadDir = 0x0106f780); PROVIDE(FSReadFile = 0x106f108); PROVIDE(FSCloseFile = 0x106f088); +PROVIDE(FSCloseDir = 0x0106f700); /* FS methods - log */ PROVIDE(FSCloseFile_log = 0x106f088); @@ -87,6 +108,7 @@ PROVIDE(FSGetVolumeState_log = 0x01068e20); /* FS methods for sd card */ PROVIDE(FSGetMountSource = 0x0106ec24); PROVIDE(FSMount = 0x0106ed14); +PROVIDE(FSUnmount = 0x0106ed8c); /* GX2 methods */ PROVIDE(GX2WaitForVsync = 0x1151964); @@ -98,9 +120,27 @@ PROVIDE(socketclose = 0x10c2314); PROVIDE(connect = 0x10c0828); PROVIDE(send = 0x10c16ac); PROVIDE(recv = 0x10c0aec); +PROVIDE(setsockopt = 0x10C2E0C); + +/* Standard library methods */ +PROVIDE(MEMAllocFromDefaultHeapEx = 0x1004e9c0); +PROVIDE(MEMAllocFromDefaultHeap = 0x100b4878); +PROVIDE(MEMFreeToDefaultHeap = 0x100b487c); + +/* Screen */ +PROVIDE(OSScreenInit = 0x0103a880); +PROVIDE(OSScreenGetBufferSizeEx = 0x0103a91c); +PROVIDE(OSScreenSetBufferEx = 0x0103a934); +PROVIDE(OSScreenClearBufferEx = 0x0103aa90); +PROVIDE(OSScreenFlipBuffersEx = 0x0103a9d0); +PROVIDE(OSScreenPutFontEx = 0x0103af14); + +/* OS data */ +PROVIDE(title_id = 0x100136D0); /* OS methods */ PROVIDE(OSDynLoad_Acquire = 0x0102A31C); +PROVIDE(OSDynLoad_FindExport = 0x102b790); PROVIDE(OSDynLoad_IsModuleLoaded = 0x0102A504); PROVIDE(OSDynLoad_GetModuleName = 0x0102B960); PROVIDE(__os_snprintf = 0x102f09c); @@ -108,12 +148,21 @@ PROVIDE(OSFatal = 0x1031368); PROVIDE(OSSetExceptionCallbackEx = 0x010443f8); PROVIDE(DCFlushRange = 0x1023ee8); -/* Standard library methods */ -PROVIDE(memcpy = 0x1035a68); -PROVIDE(memset = 0x1035a54); -PROVIDE(MEMAllocFromDefaultHeapEx = 0x1004e9c0); -PROVIDE(MEMAllocFromDefaultHeap = 0x100b4878); -PROVIDE(MEMFreeToDefaultHeap = 0x100b487c); +/* VPAD */ +PROVIDE(VPADRead = 0x011293d0); -/* OS data */ -PROVIDE(title_id = 0x100136D0); +/******************************************************** Menu ********************************************************/ +/* Mii Maker */ +PROVIDE(MiiMaker_main = 0x1005d180); + +/******************************************************* Loader *******************************************************/ +/* This are the real functions that are used for our purpose */ +PROVIDE(LiWaitIopComplete = 0x0100FFA4); +PROVIDE(LiWaitIopCompleteWithInterrupts = 0x0100FE90); +PROVIDE(LiCheckAndHandleInterrupts = 0x010046B0); +PROVIDE(Loader_SysCallGetProcessIndex = 0x010000A8); +PROVIDE(LiLoadAsync = 0x0101005C); + +/* This are just addresses to the real functions which we only need as reference */ +PROVIDE(addr_LiWaitOneChunk = 0x010007EC); +PROVIDE(addr_LiBounceOneChunk = 0x010003B0); \ No newline at end of file diff --git a/loader/loader.c b/src/loader/loader.c old mode 100755 new mode 100644 similarity index 89% rename from loader/loader.c rename to src/loader/loader.c index 6c1e92d..059ea8c --- a/loader/loader.c +++ b/src/loader/loader.c @@ -1,26 +1,10 @@ #include "loader.h" #include "../common/common.h" +#include "../common/loader_defs.h" +#include "../utils/strings.h" #define REPLACE_LIBOUNCEONECHUNK 0 -// struct holding the globals of the loader (there are actually more but we don't need others) -typedef struct _loader_globals_t -{ - int sgIsLoadingBuffer; - int sgFileType; - int sgProcId; - int sgGotBytes; - int sgFileOffset; - int sgBufferNumber; - int sgBounceError; - char sgLoadName[0x1000]; -} __attribute__((packed)) loader_globals_t; - -/* Common useful functions */ -static inline int toupper(int c) { - return (c >= 'a' && c <= 'z') ? (c - 0x20) : c; -} - // Comment (Dimok): // we don't need to replace this function as i never seen it fail actually // it doesn't even fail when fileOffset is above the actually RPX/RPL fileSize @@ -119,6 +103,7 @@ static int LiWaitOneChunk(unsigned int * iRemainingBytes, const char *filename, result = LiWaitIopComplete(0x2160EC0, &remaining_bytes); } + // Comment (Dimok): // time measurement at this position for logger -> we don't need it right now except maybe for debugging //unsigned long long systemTime2 = Loader_GetSystemTime(); @@ -127,7 +112,7 @@ static int LiWaitOneChunk(unsigned int * iRemainingBytes, const char *filename, // Start of our function intrusion: // After IOSU is done writing the data into the 0xF6000000/0xF6400000 address, // we overwrite it with our data before setting the global flag for IsLoadingBuffer to 0 - // Do this only if we are in Smash Bros or Mii Maker and the game was launched by our method + // Do this only if we are in the game that was launched by our method if (*(volatile unsigned int*)0xEFE00000 == RPX_CHECK_NAME && (GAME_LAUNCHED == 1)) { s_rpx_rpl *rpl_struct = (s_rpx_rpl*)(RPX_RPL_ARRAY); @@ -149,13 +134,8 @@ static int LiWaitOneChunk(unsigned int * iRemainingBytes, const char *filename, if ((len != len2) && (len != (len2 - 4))) continue; - for (int x = 0; x < len; x++) - { - if (toupper(rpl_struct->name[x]) != toupper(filename[x])) - { - found = 0; - break; - } + if(strncasecmp(filename, rpl_struct->name, len) != 0) { + found = 0; } } @@ -205,7 +185,9 @@ static int LiWaitOneChunk(unsigned int * iRemainingBytes, const char *filename, { GAME_RPX_LOADED = 0; GAME_LAUNCHED = 0; + RPX_CHECK_NAME = 0xDEADBEAF; } + // end of our little intrusion into this function //------------------------------------------------------------------------------------------------------------------ @@ -234,17 +216,17 @@ static int LiWaitOneChunk(unsigned int * iRemainingBytes, const char *filename, } // this macro generates the the magic entry -#define MAKE_MAGIC(x, call_type) { x, addr_ ## x, call_type} +#define MAKE_MAGIC(x, call_type) { x, addr_ ## x, call_type } // A kind of magic used to store : // - replace instruction address // - replace instruction -struct magic_t { +const struct magic_t { const void * repl_func; // our replacement function which is called const void * repl_addr; // address where to place the jump to the our function const unsigned int call_type; // call type, e.g. 0x48000000 for branch and 0x48000001 for branch link -} const methods[] __attribute__((section(".magic"))) = { +} loader_methods[] __attribute__((section(".loader_magic"))) = { #if REPLACE_LIBOUNCEONECHUNK - MAKE_MAGIC(LiBounceOneChunk, 0x48000000), // simple branch to our function as we replace it completely and don't want LR to be replaced by bl + MAKE_MAGIC(LiBounceOneChunk, 0x48000002), // simple branch to our function as we replace it completely and don't want LR to be replaced by bl #endif - MAKE_MAGIC(LiWaitOneChunk, 0x48000000), // simple branch to our function as we replace it completely and don't want LR to be replaced by bl + MAKE_MAGIC(LiWaitOneChunk, 0x48000002), // simple branch to our function as we replace it completely and don't want LR to be replaced by bl }; diff --git a/loader/loader.h b/src/loader/loader.h old mode 100755 new mode 100644 similarity index 88% rename from loader/loader.h rename to src/loader/loader.h index 3a1f97b..4d4bb8f --- a/loader/loader.h +++ b/src/loader/loader.h @@ -8,9 +8,6 @@ extern int LiLoadAsync(const char *filename, unsigned int address, unsigned int extern int LiWaitIopComplete(int unknown_syscall_arg_r3, int * remaining_bytes); extern int LiWaitIopCompleteWithInterrupts(int unknown_syscall_arg_r3, int * remaining_bytes); -extern int strncpy(char *dst, const char *src, int max_len); -extern int strnlen(const char *src, int max_len); - /* This are just addresses to the real functions which we only need as reference */ extern int addr_LiBounceOneChunk(const char * filename, int fileType, int procId, int * hunkBytes, int fileOffset, int bufferNumber, int * dst_address); extern int addr_LiWaitOneChunk(unsigned int * iRemainingBytes, const char *filename, int fileType); diff --git a/menu/menu.c b/src/menu/menu.c old mode 100755 new mode 100644 similarity index 90% rename from menu/menu.c rename to src/menu/menu.c index 39199ce..0f1c07c --- a/menu/menu.c +++ b/src/menu/menu.c @@ -1,5 +1,7 @@ #include "menu.h" -#include "util.h" +#include "../utils/strings.h" +#include "../utils/utils.h" +#include "../utils/xml.h" #include "../common/common.h" /* Utils for the display */ @@ -7,16 +9,22 @@ #define PRINT_TEXT2(x, y, _fmt, ...) { __os_snprintf(msg, 80, _fmt, __VA_ARGS__); OSScreenPutFontEx(1, x, y, msg); } #define BTN_PRESSED (BUTTON_LEFT | BUTTON_RIGHT | BUTTON_UP | BUTTON_DOWN | BUTTON_A | BUTTON_B | BUTTON_X) +/* Function prototype to patch FS methods */ +void PatchFsMethods(void); + /* Static function definitions */ static int IsRPX(FSDirEntry *dir_entry); -static int Copy_RPX_RPL(FSClient *pClient, FSCmdBlock *pCmd, FSDirEntry *dir_entry, char *path, int path_index, int is_rpx, int entry_index); +static int Copy_RPX_RPL(FSClient *pClient, FSCmdBlock *pCmd, FSDirEntry *dir_entry, char *path, int is_rpx, int entry_index); static void CreateGameSaveDir(FSClient *pClient, FSCmdBlock *pCmd, const char *dir_entry, char* mount_path); static void GenerateMemoryAreasTable(); static void AddMemoryArea(int start, int end, int cur_index); static int game_name_cmp(const void *game1, const void *game2); +/* global variable for CosAppXml struct that is forced to bss section */ +ReducedCosAppXmlInfo cosAppXmlInfoStruct __attribute__((section(".bss"))); + /* Entry point */ -int _start(int argc, char *argv[]) { +int Menu_Main(int argc, char *argv[]) { /* ****************************************************************** */ /* MENU CHECK */ /* ****************************************************************** */ @@ -44,7 +52,7 @@ int _start(int argc, char *argv[]) { int(*SYSRelaunchTitle)(uint argc, char* argv) = 0; OSDynLoad_FindExport(sysapp_handle, 0, "SYSRelaunchTitle", &SYSRelaunchTitle); - + int(*SYSLaunchMenu)() = 0; OSDynLoad_FindExport(sysapp_handle, 0, "SYSLaunchMenu", &SYSLaunchMenu); @@ -66,6 +74,11 @@ int _start(int argc, char *argv[]) { for(j = 0; j < MAX_GAME_COUNT; j++) game_dir[j] = NULL; + /* ****************************************************************** */ + /* Patch FS Functions */ + /* ****************************************************************** */ + PatchFsMethods(); + /* ****************************************************************** */ /* Init Screen */ /* ****************************************************************** */ @@ -110,6 +123,8 @@ int _start(int argc, char *argv[]) { if (pClient && pCmd) { + // Do an FSInit first + FSInit(); // Add client to FS. FSAddClient(pClient, FS_RET_NO_ERROR); @@ -139,7 +154,7 @@ int _start(int argc, char *argv[]) { while (FSReadDir(pClient, pCmd, game_dh, &dir_entry, FS_RET_ALL_ERROR) == FS_STATUS_OK && game_count < MAX_GAME_COUNT) { // allocate string length + 0 termination bytes - int name_len = strlen(dir_entry.name); + int name_len = strnlen(dir_entry.name, 0x1000); game_dir[game_count] = (char *)malloc(name_len + 1); if(!game_dir[game_count]) continue; @@ -167,6 +182,9 @@ int _start(int argc, char *argv[]) { uint8_t ready = 0; int error; + //*(volatile unsigned int *)0xBD900000 = 0xDEADBEAF; + //*(volatile unsigned int *)0xBD900004 = 0xDEADBABE; + // sort game name pointers by name case insensitive qsort(game_dir, game_count, sizeof(char*), game_name_cmp); @@ -235,9 +253,7 @@ int _start(int argc, char *argv[]) { // Create game folder path char *cur_game_dir = game_dir[game_sel]; - int len = 0; - while (cur_game_dir[len]) - len++; + int len = strnlen(cur_game_dir, 0x1000); // initialize the RPL/RPX table first entry to zero + 1 byte for name zero termination // just in case no RPL/RPX are found, though it wont boot then anyway @@ -262,12 +278,12 @@ int _start(int argc, char *argv[]) { if (is_rpx) { - is_okay = Copy_RPX_RPL(pClient, pCmd, &dir_entry, path, path_index, 1, cur_entry++); + is_okay = Copy_RPX_RPL(pClient, pCmd, &dir_entry, path, 1, cur_entry++); CreateGameSaveDir(pClient, pCmd, game_dir[game_sel], mount_path); } else { - is_okay = Copy_RPX_RPL(pClient, pCmd, &dir_entry, path, path_index, 0, cur_entry++); + is_okay = Copy_RPX_RPL(pClient, pCmd, &dir_entry, path, 0, cur_entry++); } if (is_okay == 0) break; @@ -282,6 +298,10 @@ int _start(int argc, char *argv[]) { // Close dir FSCloseDir(pClient, pCmd, game_dh, FS_RET_NO_ERROR); + + if(ready){ + LoadXmlParameters(&cosAppXmlInfoStruct, pClient, pCmd, path, path_index); + } } } } @@ -379,7 +399,7 @@ static int IsRPX(FSDirEntry *dir_entry) return -1; } -static void Add_RPX_RPL_Entry(const char *name, int size, int is_rpx, int entry_index){ +static void Add_RPX_RPL_Entry(const char *name, int size, int is_rpx, int entry_index, s_mem_area* area){ // fill rpx/rpl entry s_rpx_rpl * rpx_rpl_data = (s_rpx_rpl *)(RPX_RPL_ARRAY); // get to last entry @@ -389,48 +409,38 @@ static void Add_RPX_RPL_Entry(const char *name, int size, int is_rpx, int entry_ // setup next entry on the previous one (only if it is not the first entry) if(entry_index > 0) { - rpx_rpl_data->next = (s_rpx_rpl *)( ((unsigned int)rpx_rpl_data) + sizeof(s_rpx_rpl) + strlen(rpx_rpl_data->name) + 1 ); + rpx_rpl_data->next = (s_rpx_rpl *)( ((unsigned int)rpx_rpl_data) + sizeof(s_rpx_rpl) + strnlen(rpx_rpl_data->name, 0x1000) + 1 ); rpx_rpl_data = rpx_rpl_data->next; } // setup current entry - rpx_rpl_data->area = (s_mem_area*)(MEM_AREA_ARRAY); + rpx_rpl_data->area = area; rpx_rpl_data->size = size; rpx_rpl_data->offset = 0; rpx_rpl_data->is_rpx = is_rpx; rpx_rpl_data->next = 0; // copy string length + 0 termination - memcpy(rpx_rpl_data->name, name, strlen(name) + 1); + memcpy(rpx_rpl_data->name, name, strnlen(name, 0x1000) + 1); } /* Copy_RPX_RPL */ -static int Copy_RPX_RPL(FSClient *pClient, FSCmdBlock *pCmd, FSDirEntry *dir_entry, char *path, int path_index, int is_rpx, int entry_index) +static int Copy_RPX_RPL(FSClient *pClient, FSCmdBlock *pCmd, FSDirEntry *dir_entry, char *path, int is_rpx, int entry_index) { // Open rpl file int fd = 0; - char buf_mode[3] = {'r', '\0' }; char* path_game = (char*)malloc(FS_MAX_MOUNTPATH_SIZE); if (!path_game) return 0; - // Copy path - memcpy(path_game, path, FS_MAX_MOUNTPATH_SIZE); - - // Get rpx/rpl filename length - int len = strlen(dir_entry->name); - // Concatenate rpl filename - path_game[path_index++] = '/'; - memcpy(&(path_game[path_index]), dir_entry->name, len); - path_index += len; - path_game[path_index++] = '\0'; + __os_snprintf(path_game, FS_MAX_MOUNTPATH_SIZE, "%s/%s", path, dir_entry->name); // For RPLs : if(!is_rpx) { // fill rpl entry - Add_RPX_RPL_Entry(dir_entry->name, 0, is_rpx, entry_index); + Add_RPX_RPL_Entry(dir_entry->name, 0, is_rpx, entry_index, (s_mem_area*)(MEM_AREA_ARRAY)); // free path free(path_game); @@ -438,7 +448,7 @@ static int Copy_RPX_RPL(FSClient *pClient, FSCmdBlock *pCmd, FSDirEntry *dir_ent } // For RPX : load file from sdcard and fill memory with the rpx data - if (FSOpenFile(pClient, pCmd, path_game, buf_mode, &fd, FS_RET_ALL_ERROR) == FS_STATUS_OK) + if (FSOpenFile(pClient, pCmd, path_game, "r", &fd, FS_RET_ALL_ERROR) == FS_STATUS_OK) { int cur_size = 0; int ret = 0; @@ -448,6 +458,7 @@ static int Copy_RPX_RPL(FSClient *pClient, FSCmdBlock *pCmd, FSDirEntry *dir_ent // Get current memory area limits s_mem_area* mem_area = (s_mem_area*)(MEM_AREA_ARRAY); + s_mem_area* mem_area_rpl = mem_area; int mem_area_addr_start = mem_area->address; int mem_area_addr_end = mem_area->address + mem_area->size; int mem_area_offset = 0; @@ -472,8 +483,12 @@ static int Copy_RPX_RPL(FSClient *pClient, FSCmdBlock *pCmd, FSDirEntry *dir_ent cur_size += ret; } + if(is_rpx) { + RPX_CHECK_NAME = *(unsigned int*)dir_entry->name; + } + // fill rpx entry - Add_RPX_RPL_Entry(dir_entry->name, cur_size, is_rpx, entry_index); + Add_RPX_RPL_Entry(dir_entry->name, cur_size, is_rpx, entry_index, mem_area_rpl); // close file and free memory FSCloseFile(pClient, pCmd, fd, FS_RET_NO_ERROR); @@ -644,7 +659,7 @@ static void GenerateMemoryAreasTable() {0xB8000000 + 0x01030800, 0xB8000000 + 0x013F69A0}, // 3864 kB {0xB8000000 + 0x008EEC30, 0xB8000000 + 0x00B06E98}, // 2144 kB {0xB8000000 + 0x053B966C, 0xB8000000 + 0x058943C4}, // 4971 kB - {0xB8000000 + 0x04ADE370, 0xB8000000 + 0x0520EAB8}, // 7361 kB + {0xB8000000 + 0x04ADE370, 0xB8000000 + 0x0520EAB8}, // 7361 kB {0, 0} }; // total : 66mB + 25mB @@ -679,5 +694,19 @@ static int game_name_cmp(const void *game1, const void *game2) const char *game_name_1 = *((const char **)game1); const char *game_name_2 = *((const char **)game2); // compare strings case insensitive - return strcasecmp(game_name_1, game_name_2); + return strncasecmp(game_name_1, game_name_2, FS_MAX_FULLPATH_SIZE); } + +// this macro generates the the magic entry +#define MAKE_MAGIC(x, y, call_type) { x, y, call_type } +// A kind of magic used to store : +// - replace instruction address +// - replace instruction +const struct magic_t { + const void * repl_func; // our replacement function which is called + const unsigned int repl_addr; // address where to place the jump to the our function + const unsigned int call_type; // call type, e.g. 0x48000000 for branch and 0x48000001 for branch link +} menu_methods[] __attribute__((section(".menu_magic"))) = { + /* Patch coreinit - on 5.3.2 coreinit.rpl starts at 0x101c400 */ + { Menu_Main, 0x0101c55c, 0x48000003 }, // bla Branch Link Adress +}; diff --git a/menu/menu.h b/src/menu/menu.h old mode 100755 new mode 100644 similarity index 78% rename from menu/menu.h rename to src/menu/menu.h index 536ade3..7a86320 --- a/menu/menu.h +++ b/src/menu/menu.h @@ -10,29 +10,15 @@ #define MAX_GAME_ON_PAGE 11 /* Main */ -extern int (* const entry_point)(int argc, char *argv[]); -#define main (*entry_point) +extern int (* const MiiMaker_main)(int argc, char *argv[]); +#define main (*MiiMaker_main) /* System */ extern void _Exit (void); extern void OSFatal(char* msg); extern void DCFlushRange(const void *addr, uint length); -extern void *memset(void *dst, int val, int bytes); -extern void *memcpy(void *dst, const void *src, int bytes); -extern int *__gh_errno_ptr(void); -#define errno (*__gh_errno_ptr()) -extern void GX2WaitForVsync(void); -extern int __os_snprintf(char* s, int n, const char * format, ...); -extern const long long title_id; - -/* Alloc */ -extern void *(* const MEMAllocFromDefaultHeapEx)(int size, int align); -extern void *(* const MEMAllocFromDefaultHeap)(int size); -extern void *(* const MEMFreeToDefaultHeap)(void *ptr); -#define memalign (*MEMAllocFromDefaultHeapEx) -#define malloc (*MEMAllocFromDefaultHeap) -#define free (*MEMFreeToDefaultHeap) +extern void GX2WaitForVsync(void); /* Libs */ extern int OSDynLoad_Acquire(char* rpl, uint *handle); @@ -50,6 +36,7 @@ extern uint OSScreenPutFontEx(uint bufferNum, uint posX, uint posY, const void * extern int VPADRead(int controller, VPADData *buffer, uint num, int *error); /* FS Functions */ +extern FSStatus FSInit(void); extern FSStatus FSAddClient(FSClient *pClient, FSRetFlag errHandling); extern void FSInitCmdBlock(FSCmdBlock *pCmd); extern FSStatus FSGetMountSource(FSClient *pClient, FSCmdBlock *pCmd, FSSourceType type, FSMountSource *source, FSRetFlag errHandling); diff --git a/fs/exception_handler.c b/src/utils/exception_handler.c similarity index 100% rename from fs/exception_handler.c rename to src/utils/exception_handler.c diff --git a/fs/exception_handler.h b/src/utils/exception_handler.h similarity index 100% rename from fs/exception_handler.h rename to src/utils/exception_handler.h diff --git a/src/utils/logger.c b/src/utils/logger.c new file mode 100644 index 0000000..6d1201b --- /dev/null +++ b/src/utils/logger.c @@ -0,0 +1,93 @@ +#include "../common/common.h" +#include "../fs/fs.h" +#include "logger.h" +#include "socket.h" + +#define CHECK_ERROR(cond) if (cond) { goto error; } + +int logger_connect(int *psock) { + struct sockaddr_in addr; + int sock, ret; + + // No ip means that we don't have any server running, so no logs + if (SERVER_IP == 0) { + *psock = -1; + return 0; + } + + socket_lib_init(); + + sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + CHECK_ERROR(sock == -1); + + addr.sin_family = AF_INET; + addr.sin_port = 7332; + addr.sin_addr.s_addr = SERVER_IP; + + ret = connect(sock, (void *)&addr, sizeof(addr)); + CHECK_ERROR(ret < 0); + + int enable = 1; + setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char*)&enable, sizeof(enable)); + + ret = recvbyte(sock); + CHECK_ERROR(ret < 0); + + *psock = sock; + return 0; + +error: + if (sock != -1) + socketclose(sock); + + *psock = -1; + return -1; +} + +void logger_disconnect(int sock) { + CHECK_ERROR(sock == -1); + + char byte = BYTE_DISCONNECT; + sendwait(sock, &byte, 1); + + socketclose(sock); +error: + return; +} + +void log_string(int sock, const char* str, char flag_byte) { + if(sock == -1) { + return; + } + while (bss.lock) GX2WaitForVsync(); + bss.lock = 1; + + int i; + int len_str = 0; + while (str[len_str++]); + + // + { + char buffer[1 + 4 + len_str]; + buffer[0] = flag_byte; + *(int *)(buffer + 1) = len_str; + for (i = 0; i < len_str; i++) + buffer[5 + i] = str[i]; + + buffer[5 + i] = 0; + + sendwait(sock, buffer, 1 + 4 + len_str); + } + + bss.lock = 0; +} + +void log_byte(int sock, char byte) { + while (bss.lock) GX2WaitForVsync(); + bss.lock = 1; + + if(sock != -1) { + sendwait(sock, &byte, 1); + } + bss.lock = 0; +} diff --git a/fs/fs.h b/src/utils/logger.h old mode 100755 new mode 100644 similarity index 51% rename from fs/fs.h rename to src/utils/logger.h index 672ad86..593ca97 --- a/fs/fs.h +++ b/src/utils/logger.h @@ -1,81 +1,5 @@ -#ifndef _FS_H_ -#define _FS_H_ - -#include "../common/fs_defs.h" - -/* mem functions */ -void *memcpy(void *dst, const void *src, int bytes); -void *memset(void *dst, int val, int bytes); -extern void *(* const MEMAllocFromDefaultHeapEx)(int size, int align); -extern void *(* const MEMAllocFromDefaultHeap)(int size); -extern void (* const MEMFreeToDefaultHeap)(void *p); -#define memalign (*MEMAllocFromDefaultHeapEx) - -/* socket.h */ -#define AF_INET 2 -#define SOCK_STREAM 1 -#define IPPROTO_TCP 6 - -extern void socket_lib_init(); -extern int socket(int domain, int type, int protocol); -extern int socketclose(int socket); -extern int connect(int socket, void *addr, int addrlen); -extern int send(int socket, const void *buffer, int size, int flags); -extern int recv(int socket, void *buffer, int size, int flags); - -extern void GX2WaitForVsync(void); - - -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]; -}; - -/* OS stuff */ -extern const long long title_id; -extern void DCFlushRange(const void *p, unsigned int s); - -/* SDCard functions */ -extern FSStatus FSGetMountSource(void *pClient, void *pCmd, FSSourceType type, FSMountSource *source, FSRetFlag errHandling); -extern FSStatus FSMount(void *pClient, void *pCmd, FSMountSource *source, char *target, uint bytes, FSRetFlag errHandling); -extern FSStatus FSReadFile(FSClient *pClient, FSCmdBlock *pCmd, void *buffer, int size, int count, int fd, FSFlag flag, FSRetFlag errHandling); -extern void FSInitCmdBlock(FSCmdBlock *pCmd); -extern FSStatus FSCloseFile(FSClient *pClient, FSCmdBlock *pCmd, int fd, int error); - -/* Async callback definition */ -typedef void (*FSAsyncCallback)(void *pClient, void *pCmd, int result, void *context); -typedef struct -{ - FSAsyncCallback userCallback; - void *userContext; - void *ioMsgQueue; -} FSAsyncParams; - -/* Forward declarations */ -#define MAX_CLIENT 32 - -struct bss_t { - int global_sock; - int socket_fs[MAX_CLIENT]; - void *pClient_fs[MAX_CLIENT]; - volatile int lock; - char mount_base[255]; - char save_base[255]; -}; - -#define bss_ptr (*(struct bss_t **)0x100000e4) -#define bss (*bss_ptr) - -int fs_connect(int *socket); -void fs_disconnect(int socket); -int fs_mount_sd(int sock, void* pClient, void* pCmd); -void log_string(int sock, const char* str, char byte); -void log_byte(int sock, char byte); +#ifndef __LOGGER_H_ +#define __LOGGER_H_ /* Communication bytes with the server */ // Com @@ -141,4 +65,11 @@ void log_byte(int sock, char byte); #define BYTE_CREATE_THREAD 0x60 -#endif /* _FS_H */ + +int logger_connect(int *socket); +void logger_disconnect(int socket); +void log_string(int sock, const char* str, char byte); +void log_byte(int sock, char byte); + + +#endif diff --git a/src/utils/socket.c b/src/utils/socket.c new file mode 100644 index 0000000..1cd0bbb --- /dev/null +++ b/src/utils/socket.c @@ -0,0 +1,38 @@ +#include "socket.h" + +int recvwait(int sock, void *buffer, int len) { + int ret; + while (len > 0) { + ret = recv(sock, buffer, len, 0); + if(ret < 0) + return ret; + + len -= ret; + buffer += ret; + } + return len; +} + +int recvbyte(int sock) { + unsigned char buffer[1]; + int ret; + + ret = recvwait(sock, buffer, 1); + if (ret < 0) + return ret; + + return buffer[0]; +} + +int sendwait(int sock, const void *buffer, int len) { + int ret; + while (len > 0) { + ret = send(sock, buffer, len, 0); + if(ret < 0) + return ret; + + len -= ret; + buffer += ret; + } + return len; +} diff --git a/src/utils/socket.h b/src/utils/socket.h new file mode 100644 index 0000000..b6ef41c --- /dev/null +++ b/src/utils/socket.h @@ -0,0 +1,33 @@ +#ifndef __SOCKET_H_ +#define __SOCKET_H_ + +/* socket.h */ +#define AF_INET 2 +#define SOCK_STREAM 1 +#define IPPROTO_TCP 6 +#define TCP_NODELAY 0x2004 + +extern void socket_lib_init(); +extern int socket(int domain, int type, int protocol); +extern int socketclose(int socket); +extern int connect(int socket, void *addr, int addrlen); +extern int send(int socket, const void *buffer, int size, int flags); +extern int recv(int socket, void *buffer, int size, int flags); +extern int setsockopt(int fd, int level, int optname, void *optval, int optlen); + +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]; +}; + +int recvwait(int sock, void *buffer, int len); +int recvbyte(int sock); +int sendwait(int sock, const void *buffer, int len); + + +#endif diff --git a/src/utils/strings.c b/src/utils/strings.c new file mode 100644 index 0000000..3aba907 --- /dev/null +++ b/src/utils/strings.c @@ -0,0 +1,169 @@ +#include "strings.h" + +void* memcpy(void *dst, const void *src, unsigned int len) +{ + const unsigned char *src_ptr = (const unsigned char *)src; + unsigned char *dst_ptr = (unsigned char *)dst; + + while(len) + { + *dst_ptr++ = *src_ptr++; + --len; + } + return dst; +} + +void* memset(void *dst, int val, unsigned int bytes) +{ + unsigned char *dst_ptr = (unsigned char *)dst; + unsigned int i = 0; + while(i < bytes) + { + dst_ptr[i] = val; + ++i; + } + return dst; +} + +int memcmp(const void * ptr1, const void * ptr2, unsigned int num) +{ + const unsigned char *ptr1_cpy = (const unsigned char *)ptr1; + const unsigned char *ptr2_cpy = (const unsigned char *)ptr2; + + while(num) + { + int diff = (int)*ptr1_cpy - (int)*ptr2_cpy; + if(diff != 0) { + return diff; + } + ptr1_cpy++; + ptr2_cpy++; + --num; + } + return 0; +} + +int strnlen(const char* str, unsigned int max_len) { + unsigned int i = 0; + while (str[i] && (i < max_len)) { + i++; + } + return i; +} + +int strlen(const char* str) { + unsigned int i = 0; + while (str[i]) { + i++; + } + return i; +} + +int strlcpy(char *s1, const char *s2, unsigned int max_size) +{ + if(!s1 || !s2 || !max_size) + return 0; + + unsigned int len = 0; + while(s2[len] && (len < (max_size-1))) + { + s1[len] = s2[len]; + len++; + } + s1[len] = 0; + return len; +} + +int strncpy(char *dst, const char *src, unsigned int max_size) +{ + return strlcpy(dst, src, max_size); // this is not correct, but mostly we need a terminating zero +} + + +int strncasecmp(const char *s1, const char *s2, unsigned int max_len) { + if(!s1 || !s2) { + return -1; + } + + unsigned int len = 0; + while(*s1 && *s2 && len < max_len) + { + int diff = toupper(*s1) - toupper(*s2); + if(diff != 0) { + return diff; + } + + s1++; + s2++; + len++; + } + + if(len == max_len) { + return 0; + } + + int diff = toupper(*s1) - toupper(*s2); + if(diff != 0) { + return diff; + } + return 0; +} + + +const char *strcasestr(const char *str, const char *pattern) +{ + if(!str || !pattern) { + return 0; + } + + int len = strnlen(pattern, 0x1000); + + while(*str) + { + if(strncasecmp(str, pattern, len) == 0) { + return str; + } + str++; + } + return 0; +} + +int64_t strtoll(const char *str, char **end, int base) +{ + int64_t value = 0; + int sign = 1; + + // skip initial spaces only + while(*str == ' ') + str++; + + if(*str == '-') { + sign = -1; + str++; + } + + while(*str) + { + if(base == 16 && toupper(*str) == 'X') { + str++; + continue; + } + + if(!(*str >= '0' && *str <= '9') && !(base == 16 && toupper(*str) >= 'A' && toupper(*str) <= 'F')) + break; + + value *= base; + + if(toupper(*str) >= 'A' && toupper(*str) <= 'F') + value += toupper(*str) - 'A' + 10; + else + value += *str - '0'; + + str++; + } + + if(end) + *end = (char*) str; + + return value * sign; +} diff --git a/src/utils/strings.h b/src/utils/strings.h new file mode 100644 index 0000000..de6f3f7 --- /dev/null +++ b/src/utils/strings.h @@ -0,0 +1,26 @@ +#ifndef __STRINGS_H_ +#define __STRINGS_H_ + +#include "../common/types.h" + +static inline int toupper(int c) { + return (c >= 'a' && c <= 'z') ? (c - 0x20) : c; +} + +void* memcpy(void *dst, const void *src, unsigned int len); +void* memset(void *dst, int val, unsigned int len); +int memcmp (const void * ptr1, const void * ptr2, unsigned int num); + +/* string functions */ +int strncasecmp(const char *s1, const char *s2, unsigned int max_len); +int strncpy(char *dst, const char *src, unsigned int max_size); +int strlcpy(char *s1, const char *s2, unsigned int max_size); +int strnlen(const char* str, unsigned int max_size); +int strlen(const char* str); +const char *strcasestr(const char *str, const char *pattern); +int64_t strtoll(const char *str, char **end, int base); + +/* functions from OS, don't put standard functions here without any prefix marking it as an OS function */ +extern int __os_snprintf(char* s, int n, const char * format, ...); + +#endif // __STRINGS_H_ diff --git a/menu/util.c b/src/utils/utils.c similarity index 60% rename from menu/util.c rename to src/utils/utils.c index faafb65..2d925e8 100644 --- a/menu/util.c +++ b/src/utils/utils.c @@ -1,54 +1,41 @@ -#include "util.h" - -static inline int toupper(int c) { - return (c >= 'a' && c <= 'z') ? (c - 0x20) : c; -} - -int strlen(const char* str) { - int i = 0; - while (str[i]) - i++; - return i; -} - -/* not used yet, maybe later -int strlcpy(char *s1, const char *s2, unsigned int max_size) -{ - if(!s1 || !s2 || !max_size) - return 0; - - int len = 0; - while(s2[len] && (len < (max_size-1))) - { - s1[len] = s2[len]; - len++; - } - s1[len] = 0; - return len; -} -*/ -int strcasecmp(const char *s1, const char *s2) { - if(!s1 || !s2) { - return -1; +#include "../common/common.h" +#include "../fs/fs.h" +#include "socket.h" +#include "logger.h" +#include "utils.h" + +int fs_mount_sd(int sock, void* pClient, void* pCmd) { + int is_mounted = 0; + char buffer[1]; + + if (sock != -1) { + buffer[0] = BYTE_MOUNT_SD; + sendwait(sock, buffer, 1); } - while(*s1 && *s2) + // mount sdcard + FSMountSource mountSrc; + char mountPath[FS_MAX_MOUNTPATH_SIZE]; + int status = FSGetMountSource(pClient, pCmd, FS_SOURCETYPE_EXTERNAL, &mountSrc, FS_RET_NO_ERROR); + if (status == FS_STATUS_OK) { - int diff = toupper(*s1) - toupper(*s2); - if(diff != 0) { - return diff; + status = FSMount(pClient, pCmd, &mountSrc, mountPath, sizeof(mountPath), FS_RET_UNSUPPORTED_CMD); + if (status == FS_STATUS_OK) + { + // set as mounted + is_mounted = 1; } - - s1++; - s2++; } - int diff = toupper(*s1) - toupper(*s2); - if(diff != 0) { - return diff; + + if (sock != -1) { + buffer[0] = is_mounted ? BYTE_MOUNT_SD_OK : BYTE_MOUNT_SD_BAD; + sendwait(sock, buffer, 1); } - return 0; + + return is_mounted; } + static void swap(void *e1, void *e2, unsigned int length) { unsigned char tmp; diff --git a/src/utils/utils.h b/src/utils/utils.h new file mode 100644 index 0000000..d0ba475 --- /dev/null +++ b/src/utils/utils.h @@ -0,0 +1,31 @@ +#ifndef __UTILS_H_ +#define __UTILS_H_ + +#include "../common/types.h" + +#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" \ + ); + + +/* Alloc */ +extern void *(* const MEMAllocFromDefaultHeapEx)(int size, int align); +extern void *(* const MEMAllocFromDefaultHeap)(int size); +extern void *(* const MEMFreeToDefaultHeap)(void *ptr); + +#define memalign (*MEMAllocFromDefaultHeapEx) +#define malloc (*MEMAllocFromDefaultHeap) +#define free (*MEMFreeToDefaultHeap) + +extern const uint64_t title_id; + +int fs_mount_sd(int sock, void* pClient, void* pCmd); +void qsort(void *ptr, unsigned int count, unsigned int size, int (*compare)(const void*,const void*)); + +#endif // __UTILS_H_ diff --git a/src/utils/xml.c b/src/utils/xml.c new file mode 100644 index 0000000..d06cd97 --- /dev/null +++ b/src/utils/xml.c @@ -0,0 +1,258 @@ +#include "../Common/fs_defs.h" +#include "../Common/kernel_defs.h" +#include "../menu/menu.h" +#include "utils.h" +#include "strings.h" +#include "logger.h" + +#define XML_BUFFER_SIZE 8192 + +char * XML_GetNodeText(const char *xml_part, const char * nodename, char * output, int output_size) +{ + // create '<' + nodename + char buffer[strlen(nodename) + 3]; + buffer[0] = '<'; + strlcpy(&buffer[1], nodename, sizeof(buffer)); + + const char *start = strcasestr(xml_part, buffer); + if(!start) + return 0; + + // find closing tag + while(*start && *start != '>') + start++; + // skip '>' + if(*start == '>') + start++; + + // create 'version_cos_xml = 18; // default for most games + xmlInfo->os_version = 0x000500101000400A; // default for most games + xmlInfo->title_id = title_id; // use mii maker ID + xmlInfo->app_type = 0x80000000; // default for most games + xmlInfo->cmdFlags = 0; // default for most games + strlcpy(xmlInfo->rpx_name, "ffl_app.rpx", sizeof(xmlInfo->rpx_name)); + xmlInfo->max_size = 0x40000000; // default for most games + xmlInfo->avail_size = 0; // default for most games + xmlInfo->codegen_size = 0; // default for most games + xmlInfo->codegen_core = 1; // default for most games + xmlInfo->max_codesize = 0x03000000; // i think this is the best for most games + xmlInfo->overlay_arena = 0; // only very few have that set to 1 + xmlInfo->exception_stack0_size = 0x1000; // default for most games + xmlInfo->exception_stack1_size = 0x1000; // default for most games + xmlInfo->exception_stack2_size = 0x1000; // default for most games + xmlInfo->sdk_version = 20909; // game dependent, lets take the one from mii maker + xmlInfo->title_version = 0; // game dependent, we say its 0 + //-------------------------------------------------------------------------------------------- + + int fd = 0; + char* path_copy = (char*)malloc(FS_MAX_MOUNTPATH_SIZE); + if (!path_copy) + return -1; + + char* xmlData = (char*)malloc(XML_BUFFER_SIZE); + if(!xmlData) { + free(path_copy); + return -2; + } + + char* xmlNodeData = (char*)malloc(XML_BUFFER_SIZE); + if(!xmlNodeData) { + free(xmlData); + free(path_copy); + return -3; + } + + memset(xmlData, 0, XML_BUFFER_SIZE); + + // create path + __os_snprintf(path_copy, FS_MAX_MOUNTPATH_SIZE, "%s/cos.xml", path); + + if (FSOpenFile(pClient, pCmd, path_copy, "r", &fd, FS_RET_ALL_ERROR) == FS_STATUS_OK) + { + // read first up to XML_BUFFER_SIZE available bytes and close file + int result = FSReadFile(pClient, pCmd, xmlData, 0x1, XML_BUFFER_SIZE, fd, 0, FS_RET_ALL_ERROR); + FSCloseFile(pClient, pCmd, fd, FS_RET_NO_ERROR); + // lets start parsing + if(result > 0) + { + // ensure 0 termination + xmlData[XML_BUFFER_SIZE-1] = 0; + + + if(XML_GetNodeText(xmlData, "version", xmlNodeData, XML_BUFFER_SIZE)) + { + unsigned int value = strtoll(xmlNodeData, 0, 10); + xmlInfo->version_cos_xml = value; + } + if(XML_GetNodeText(xmlData, "cmdFlags", xmlNodeData, XML_BUFFER_SIZE)) + { + unsigned int value = strtoll(xmlNodeData, 0, 10); + xmlInfo->cmdFlags = value; + } + if(XML_GetNodeText(xmlData, "argstr", xmlNodeData, XML_BUFFER_SIZE)) + { + strlcpy(xmlInfo->rpx_name, xmlNodeData, sizeof(xmlInfo->rpx_name)); + } + if(XML_GetNodeText(xmlData, "avail_size", xmlNodeData, XML_BUFFER_SIZE)) + { + unsigned int value = strtoll(xmlNodeData, 0, 16); + xmlInfo->avail_size = value; + } + if(XML_GetNodeText(xmlData, "codegen_size", xmlNodeData, XML_BUFFER_SIZE)) + { + unsigned int value = strtoll(xmlNodeData, 0, 16); + xmlInfo->codegen_size = value; + } + if(XML_GetNodeText(xmlData, "codegen_core", xmlNodeData, XML_BUFFER_SIZE)) + { + unsigned int value = strtoll(xmlNodeData, 0, 16); + xmlInfo->codegen_core = value; + } + if(XML_GetNodeText(xmlData, "max_size", xmlNodeData, XML_BUFFER_SIZE)) + { + unsigned int value = strtoll(xmlNodeData, 0, 16); + xmlInfo->max_size = value; + } + if(XML_GetNodeText(xmlData, "max_codesize", xmlNodeData, XML_BUFFER_SIZE)) + { + unsigned int value = strtoll(xmlNodeData, 0, 16); + xmlInfo->max_codesize = value; + } + if(XML_GetNodeText(xmlData, "overlay_arena", xmlNodeData, XML_BUFFER_SIZE)) + { + unsigned int value = strtoll(xmlNodeData, 0, 16); + xmlInfo->overlay_arena = value; + } + if(XML_GetNodeText(xmlData, "default_stack0_size", xmlNodeData, XML_BUFFER_SIZE)) + { + unsigned int value = strtoll(xmlNodeData, 0, 16); + xmlInfo->default_stack0_size = value; + } + if(XML_GetNodeText(xmlData, "default_stack1_size", xmlNodeData, XML_BUFFER_SIZE)) + { + unsigned int value = strtoll(xmlNodeData, 0, 16); + xmlInfo->default_stack1_size = value; + } + if(XML_GetNodeText(xmlData, "default_stack2_size", xmlNodeData, XML_BUFFER_SIZE)) + { + unsigned int value = strtoll(xmlNodeData, 0, 16); + xmlInfo->default_stack2_size = value; + } + if(XML_GetNodeText(xmlData, "default_redzone0_size", xmlNodeData, XML_BUFFER_SIZE)) + { + unsigned int value = strtoll(xmlNodeData, 0, 16); + xmlInfo->default_redzone0_size = value; + } + if(XML_GetNodeText(xmlData, "default_redzone1_size", xmlNodeData, XML_BUFFER_SIZE)) + { + unsigned int value = strtoll(xmlNodeData, 0, 16); + xmlInfo->default_redzone1_size = value; + } + if(XML_GetNodeText(xmlData, "default_redzone2_size", xmlNodeData, XML_BUFFER_SIZE)) + { + unsigned int value = strtoll(xmlNodeData, 0, 16); + xmlInfo->default_redzone2_size = value; + } + if(XML_GetNodeText(xmlData, "exception_stack0_size", xmlNodeData, XML_BUFFER_SIZE)) + { + unsigned int value = strtoll(xmlNodeData, 0, 16); + xmlInfo->exception_stack0_size = value; + } + if(XML_GetNodeText(xmlData, "exception_stack1_size", xmlNodeData, XML_BUFFER_SIZE)) + { + unsigned int value = strtoll(xmlNodeData, 0, 16); + xmlInfo->exception_stack0_size = value; + } + if(XML_GetNodeText(xmlData, "exception_stack2_size", xmlNodeData, XML_BUFFER_SIZE)) + { + unsigned int value = strtoll(xmlNodeData, 0, 16); + xmlInfo->exception_stack0_size = value; + } + } + } + + // reset buffer + memset(xmlData, 0, XML_BUFFER_SIZE); + + // create path + __os_snprintf(path_copy, FS_MAX_MOUNTPATH_SIZE, "%s/app.xml", path); + + if (FSOpenFile(pClient, pCmd, path_copy, "r", &fd, FS_RET_ALL_ERROR) == FS_STATUS_OK) + { + // read first up to XML_BUFFER_SIZE available bytes and close file + int result = FSReadFile(pClient, pCmd, xmlData, 0x1, XML_BUFFER_SIZE, fd, 0, FS_RET_ALL_ERROR); + FSCloseFile(pClient, pCmd, fd, FS_RET_NO_ERROR); + // lets start parsing + if(result > 0) + { + // ensure 0 termination + xmlData[XML_BUFFER_SIZE-1] = 0; + + //-------------------------------------------------------------------------------------------- + // version tag is still unknown where it is used + //-------------------------------------------------------------------------------------------- + if(XML_GetNodeText(xmlData, "os_version", xmlNodeData, XML_BUFFER_SIZE)) + { + uint64_t value = strtoll(xmlNodeData, 0, 16); + xmlInfo->os_version = value; + } + if(XML_GetNodeText(xmlData, "title_id", xmlNodeData, XML_BUFFER_SIZE)) + { + uint64_t value = strtoll(xmlNodeData, 0, 16); + xmlInfo->title_id = value; + + } + if(XML_GetNodeText(xmlData, "title_version", xmlNodeData, XML_BUFFER_SIZE)) + { + uint32_t value = strtoll(xmlNodeData, 0, 16); + xmlInfo->title_version = value; + } + if(XML_GetNodeText(xmlData, "sdk_version", xmlNodeData, XML_BUFFER_SIZE)) + { + uint32_t value = strtoll(xmlNodeData, 0, 10); + xmlInfo->sdk_version = value; + } + if(XML_GetNodeText(xmlData, "app_type", xmlNodeData, XML_BUFFER_SIZE)) + { + uint32_t value = strtoll(xmlNodeData, 0, 16); + xmlInfo->app_type = value; + } + //-------------------------------------------------------------------------------------------- + // group_id tag is still unknown where it is used + //-------------------------------------------------------------------------------------------- + } + } + + free(xmlData); + free(xmlNodeData); + free(path_copy); + + return 0; +} diff --git a/src/utils/xml.h b/src/utils/xml.h new file mode 100644 index 0000000..ae61620 --- /dev/null +++ b/src/utils/xml.h @@ -0,0 +1,9 @@ +#ifndef __XML_H_ +#define __XML_H_ + +#include "../common/kernel_defs.h" + +char * XML_GetNodeText(const char *xml_part, const char * nodename, char * output, int output_size); +int LoadXmlParameters(ReducedCosAppXmlInfo * xmlInfo, FSClient *pClient, FSCmdBlock *pCmd, const char *path, int path_index); + +#endif // __XML_H_ diff --git a/www/fs532.elf b/www/fs532.elf deleted file mode 100755 index 57daa02..0000000 Binary files a/www/fs532.elf and /dev/null differ diff --git a/www/loader532.elf b/www/loader532.elf deleted file mode 100755 index 8781c65..0000000 Binary files a/www/loader532.elf and /dev/null differ diff --git a/www/loadiine.elf b/www/loadiine.elf new file mode 100644 index 0000000..5d73216 Binary files /dev/null and b/www/loadiine.elf differ diff --git a/www/loadiine_dbg.elf b/www/loadiine_dbg.elf new file mode 100644 index 0000000..d9c6e6c Binary files /dev/null and b/www/loadiine_dbg.elf differ diff --git a/www/menu532.elf b/www/menu532.elf deleted file mode 100755 index 3fc3d00..0000000 Binary files a/www/menu532.elf and /dev/null differ