diff --git a/Makefile.common b/Makefile.common index 5394c2c1a9..bd1188034b 100644 --- a/Makefile.common +++ b/Makefile.common @@ -2377,10 +2377,10 @@ endif ifeq ($(WANT_IOSUHAX), 1) DEFINES += -DHAVE_IOSUHAX - INCLUDE_DIRS += -I$(DEPS_DIR)/libiosuhax - OBJ += $(DEPS_DIR)/libiosuhax/iosuhax.o \ - $(DEPS_DIR)/libiosuhax/iosuhax_devoptab.o \ - $(DEPS_DIR)/libiosuhax/iosuhax_disc_interface.o + INCLUDE_DIRS += -I$(DEPS_DIR)/libiosuhax/include + OBJ += $(DEPS_DIR)/libiosuhax/source/iosuhax.o \ + $(DEPS_DIR)/libiosuhax/source/iosuhax_devoptab.o \ + $(DEPS_DIR)/libiosuhax/source/iosuhax_disc_interface.o endif ifeq ($(WANT_LIBFAT), 1) diff --git a/Makefile.wiiu b/Makefile.wiiu index 55a0dd93cc..c565db262c 100644 --- a/Makefile.wiiu +++ b/Makefile.wiiu @@ -102,7 +102,7 @@ endif INCDIRS += -Ilibretro-common/include/compat/zlib # for stb, libfat, iosuhax - INCDIRS += -Ideps -Ideps/libfat/include -Ideps/libiosuhax + INCDIRS += -Ideps -Ideps/libfat/include -Ideps/libiosuhax/include # pad_functions uses wiiu/input.h INCDIRS += -Iinput/include INCDIRS += -Ideps/SPIRV-Cross diff --git a/deps/libiosuhax/.github/workflows/push_image.yml b/deps/libiosuhax/.github/workflows/push_image.yml new file mode 100644 index 0000000000..9cd7bbdb42 --- /dev/null +++ b/deps/libiosuhax/.github/workflows/push_image.yml @@ -0,0 +1,25 @@ +name: Publish Docker Image +on: + push: + branches: + - master +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@master + - name: Get release version + id: get_release_tag + run: | + echo RELEASE_VERSION=$(echo $(date '+%Y%m%d')) >> $GITHUB_ENV + echo REPOSITORY_NAME=$(echo "$GITHUB_REPOSITORY" | awk -F / '{print $2}' | sed -e "s/:refs//" | tr '[:upper:]' '[:lower:]') >> $GITHUB_ENV + echo REPOSITORY_OWNER=$(echo "$GITHUB_REPOSITORY" | awk -F / '{print $1}' | sed 's/[^a-zA-Z0-9]//g' | tr '[:upper:]' '[:lower:]') >> $GITHUB_ENV + - name: Publish to Registry + uses: elgohr/Publish-Docker-Github-Action@master + with: + name: ${{ env.REPOSITORY_OWNER }}/${{ env.REPOSITORY_NAME }} + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + snapshot: true + cache: true + tags: "latest, ${{ env.RELEASE_VERSION }}" \ No newline at end of file diff --git a/deps/libiosuhax/.gitignore b/deps/libiosuhax/.gitignore new file mode 100644 index 0000000000..0955c90e6e --- /dev/null +++ b/deps/libiosuhax/.gitignore @@ -0,0 +1,5 @@ +/*.a +/build +*.bz2 +release/ +lib/ diff --git a/deps/libiosuhax/.travis.yml b/deps/libiosuhax/.travis.yml new file mode 100644 index 0000000000..ff1f980eaa --- /dev/null +++ b/deps/libiosuhax/.travis.yml @@ -0,0 +1,29 @@ +language: cpp + +os: linux +sudo: false +dist: trusty + +env: + global: + - DEVKITPRO=/opt/devkitpro + - DEVKITPPC=/opt/devkitpro/devkitPPC + +cache: + directories: + - "$HOME/.local" + - "$DEVKITPRO" + +addons: + apt: + packages: + - p7zip-full + +before_install: + - mkdir -p "${DEVKITPRO}" + - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then wget https://github.com/devkitPro/pacman/releases/download/devkitpro-pacman-1.0.1/devkitpro-pacman.deb -O /tmp/devkitpro-pacman.deb; fi + - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo dpkg -i /tmp/devkitpro-pacman.deb; fi + - yes | sudo dkp-pacman -Syu devkitPPC --needed + +script: + - make && make install \ No newline at end of file diff --git a/deps/libiosuhax/Dockerfile b/deps/libiosuhax/Dockerfile new file mode 100644 index 0000000000..27aa8936e8 --- /dev/null +++ b/deps/libiosuhax/Dockerfile @@ -0,0 +1,9 @@ +FROM wiiuenv/devkitppc:20210101 + +WORKDIR tmp_build +COPY . . +RUN make clean && make && mkdir -p /artifacts/wut/usr && cp -r lib /artifacts/wut/usr && cp -r include /artifacts/wut/usr +WORKDIR /artifacts + +FROM scratch +COPY --from=0 /artifacts /artifacts \ No newline at end of file diff --git a/deps/libiosuhax/Makefile b/deps/libiosuhax/Makefile new file mode 100644 index 0000000000..03af789f3d --- /dev/null +++ b/deps/libiosuhax/Makefile @@ -0,0 +1,157 @@ +#------------------------------------------------------------------------------- +.SUFFIXES: +#------------------------------------------------------------------------------- + +ifeq ($(strip $(DEVKITPRO)),) +$(error "Please set DEVKITPRO in your environment. export DEVKITPRO=/devkitpro") +endif + +TOPDIR ?= $(CURDIR) + +include $(DEVKITPRO)/wut/share/wut_rules + +export VER_MAJOR := 1 +export VER_MINOR := 0 +export VER_PATCH := 0 + +VERSION := $(VER_MAJOR).$(VER_MINOR).$(VER_PATCH) + +#------------------------------------------------------------------------------- +# TARGET is the name of the output +# BUILD is the directory where object files & intermediate files will be placed +# SOURCES is a list of directories containing source code +# DATA is a list of directories containing data files +# INCLUDES is a list of directories containing header files +#------------------------------------------------------------------------------- +TARGET := $(notdir $(CURDIR)) +BUILD := build +SOURCES := source +DATA := data +INCLUDES := source \ + include \ + +#--------------------------------------------------------------------------------- +# options for code generation +#--------------------------------------------------------------------------------- +CFLAGS := -Wall -Werror -save-temps \ + -ffunction-sections -fdata-sections \ + $(MACHDEP) \ + $(BUILD_CFLAGS) + +CFLAGS += $(INCLUDE) -D__WIIU__ -D__WUT__ + +CXXFLAGS := $(CFLAGS) -std=gnu++17 + +ASFLAGS := $(MACHDEP) + +LDFLAGS = $(ARCH) -Wl,--gc-sections + + +LIBS := + +#--------------------------------------------------------------------------------- +# list of directories containing libraries, this must be the top level containing +# include and lib +#--------------------------------------------------------------------------------- +LIBDIRS := $(PORTLIBS) $(WUT_ROOT) + +#--------------------------------------------------------------------------------- +# no real need to edit anything past this point unless you need to add additional +# rules for different file extensions +#--------------------------------------------------------------------------------- +ifneq ($(BUILD),$(notdir $(CURDIR))) +#--------------------------------------------------------------------------------- + +export TOPDIR := $(CURDIR) + +export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ + $(foreach dir,$(DATA),$(CURDIR)/$(dir)) + +CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) +CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) +SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) +DEFFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.def))) +BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) + +#--------------------------------------------------------------------------------- +# use CXX for linking C++ projects, CC for standard C +#--------------------------------------------------------------------------------- +ifeq ($(strip $(CPPFILES)),) +#--------------------------------------------------------------------------------- + export LD := $(CC) +#--------------------------------------------------------------------------------- +else +#--------------------------------------------------------------------------------- + export LD := $(CXX) +#--------------------------------------------------------------------------------- +endif +#--------------------------------------------------------------------------------- + +export OFILES_BIN := $(addsuffix .o,$(BINFILES)) +export OFILES_SRC := $(DEFFILES:.def=.o) $(SFILES:.s=.o) $(CFILES:.c=.o) $(CPPFILES:.cpp=.o) +export OFILES := $(OFILES_BIN) $(OFILES_SRC) +export HFILES := $(addsuffix .h,$(subst .,_,$(BINFILES))) + +export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ + $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ + -I. + +.PHONY: all dist-bin dist-src dist install clean + +#--------------------------------------------------------------------------------- +all: lib/libiosuhax.a + +dist-bin: all + @tar --exclude=*~ -cjf libiosuhax-$(VERSION).tar.bz2 include lib + +dist-src: + @tar --exclude=*~ -cjf libiosuhax-src-$(VERSION).tar.bz2 include source Makefile + +dist: dist-src dist-bin + +install: dist-bin + mkdir -p $(DESTDIR)$(DEVKITPRO)/wut/usr + bzip2 -cd libiosuhax-$(VERSION).tar.bz2 | tar -xf - -C $(DESTDIR)$(DEVKITPRO)/wut/usr + +lib: + @[ -d $@ ] || mkdir -p $@ + +release: + @[ -d $@ ] || mkdir -p $@ + +lib/libiosuhax.a :$(SOURCES) $(INCLUDES) | lib release + @$(MAKE) BUILD=release OUTPUT=$(CURDIR)/$@ \ + BUILD_CFLAGS="-DNDEBUG=1 -O2 -s" \ + DEPSDIR=$(CURDIR)/release \ + --no-print-directory -C release \ + -f $(CURDIR)/Makefile + +#--------------------------------------------------------------------------------- +clean: + @echo clean ... + @rm -rf release lib + +#--------------------------------------------------------------------------------- +else + +DEPENDS := $(OFILES:.o=.d) + +#--------------------------------------------------------------------------------- +# main targets +#--------------------------------------------------------------------------------- +$(OUTPUT) : $(OFILES) + +$(OFILES_SRC) : $(HFILES) + +#--------------------------------------------------------------------------------- +%_bin.h %.bin.o : %.bin +#--------------------------------------------------------------------------------- + @echo $(notdir $<) + @$(bin2o) + + +-include $(DEPENDS) + +#--------------------------------------------------------------------------------------- +endif +#--------------------------------------------------------------------------------------- diff --git a/deps/libiosuhax/README.md b/deps/libiosuhax/README.md new file mode 100644 index 0000000000..1fc1235092 --- /dev/null +++ b/deps/libiosuhax/README.md @@ -0,0 +1,10 @@ +[![Build Status](https://travis-ci.org/dimok789/libiosuhax.svg)](https://travis-ci.org/dimok789/libiosuhax) +# libiosuhax +A PPC library to access IOSUHAX from PPC and a devoptab for any device or path. +It's only compatible to RPX-Files. + +## Building +Make you to have [wut](https://github.com/devkitPro/wut/) installed and use the following command for build: +``` +make install +``` diff --git a/deps/libiosuhax/iosuhax.h b/deps/libiosuhax/include/iosuhax.h similarity index 96% rename from deps/libiosuhax/iosuhax.h rename to deps/libiosuhax/include/iosuhax.h index 25b7367cad..9b2350b7fd 100644 --- a/deps/libiosuhax/iosuhax.h +++ b/deps/libiosuhax/include/iosuhax.h @@ -1,109 +1,112 @@ -/*************************************************************************** - * Copyright (C) 2016 - * by Dimok - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event will the authors be held liable for any - * damages arising from the use of this software. - * - * Permission is granted to anyone to use this software for any - * purpose, including commercial applications, and to alter it and - * redistribute it freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you - * must not claim that you wrote the original software. If you use - * this software in a product, an acknowledgment in the product - * documentation would be appreciated but is not required. - * - * 2. Altered source versions must be plainly marked as such, and - * must not be misrepresented as being the original software. - * - * 3. This notice may not be removed or altered from any source - * distribution. - ***************************************************************************/ -#ifndef _LIB_IOSUHAX_H_ -#define _LIB_IOSUHAX_H_ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#define IOS_ERROR_UNKNOWN_VALUE 0xFFFFFFD6 -#define IOS_ERROR_INVALID_ARG 0xFFFFFFE3 -#define IOS_ERROR_INVALID_SIZE 0xFFFFFFE9 -#define IOS_ERROR_UNKNOWN 0xFFFFFFF7 -#define IOS_ERROR_NOEXISTS 0xFFFFFFFA - -typedef struct -{ - uint32_t flag; - uint32_t permission; - uint32_t owner_id; - uint32_t group_id; - uint32_t size; // size in bytes - uint32_t physsize; // physical size on disk in bytes - uint32_t unk[3]; - uint32_t id; - uint32_t ctime; - uint32_t mtime; - uint32_t unk2[0x0D]; -}fileStat_s; - -typedef struct -{ - fileStat_s stat; - char name[0x100]; -}directoryEntry_s; - -#define DIR_ENTRY_IS_DIRECTORY 0x80000000 - -#define FSA_MOUNTFLAGS_BINDMOUNT (1 << 0) -#define FSA_MOUNTFLAGS_GLOBAL (1 << 1) - -int IOSUHAX_Open(const char *dev); // if dev == NULL the default path /dev/iosuhax will be used -int IOSUHAX_Close(void); - -int IOSUHAX_memwrite(uint32_t address, const uint8_t * buffer, uint32_t size); // IOSU external input -int IOSUHAX_memread(uint32_t address, uint8_t * out_buffer, uint32_t size); // IOSU external output -int IOSUHAX_memcpy(uint32_t dst, uint32_t src, uint32_t size); // IOSU internal memcpy only - -int IOSUHAX_SVC(uint32_t svc_id, uint32_t * args, uint32_t arg_cnt); - -int IOSUHAX_FSA_Open(); -int IOSUHAX_FSA_Close(int fsaFd); - -int IOSUHAX_FSA_Mount(int fsaFd, const char* device_path, const char* volume_path, uint32_t flags, const char* arg_string, int arg_string_len); -int IOSUHAX_FSA_Unmount(int fsaFd, const char* path, uint32_t flags); -int IOSUHAX_FSA_FlushVolume(int fsaFd, const char* volume_path); - -int IOSUHAX_FSA_GetDeviceInfo(int fsaFd, const char* device_path, int type, uint32_t* out_data); - -int IOSUHAX_FSA_MakeDir(int fsaFd, const char* path, uint32_t flags); -int IOSUHAX_FSA_OpenDir(int fsaFd, const char* path, int* outHandle); -int IOSUHAX_FSA_ReadDir(int fsaFd, int handle, directoryEntry_s* out_data); -int IOSUHAX_FSA_RewindDir(int fsaFd, int dirHandle); -int IOSUHAX_FSA_CloseDir(int fsaFd, int handle); -int IOSUHAX_FSA_ChangeDir(int fsaFd, const char *path); - -int IOSUHAX_FSA_OpenFile(int fsaFd, const char* path, const char* mode, int* outHandle); -int IOSUHAX_FSA_ReadFile(int fsaFd, void* data, uint32_t size, uint32_t cnt, int fileHandle, uint32_t flags); -int IOSUHAX_FSA_WriteFile(int fsaFd, const void* data, uint32_t size, uint32_t cnt, int fileHandle, uint32_t flags); -int IOSUHAX_FSA_StatFile(int fsaFd, int fileHandle, fileStat_s* out_data); -int IOSUHAX_FSA_CloseFile(int fsaFd, int fileHandle); -int IOSUHAX_FSA_SetFilePos(int fsaFd, int fileHandle, uint32_t position); -int IOSUHAX_FSA_GetStat(int fsaFd, const char *path, fileStat_s* out_data); -int IOSUHAX_FSA_Remove(int fsaFd, const char *path); -int IOSUHAX_FSA_ChangeMode(int fsaFd, const char* path, int mode); - -int IOSUHAX_FSA_RawOpen(int fsaFd, const char* device_path, int* outHandle); -int IOSUHAX_FSA_RawRead(int fsaFd, void* data, uint32_t block_size, uint32_t block_cnt, uint64_t sector_offset, int device_handle); -int IOSUHAX_FSA_RawWrite(int fsaFd, const void* data, uint32_t block_size, uint32_t block_cnt, uint64_t sector_offset, int device_handle); -int IOSUHAX_FSA_RawClose(int fsaFd, int device_handle); - -#ifdef __cplusplus -} -#endif - -#endif +/*************************************************************************** + * Copyright (C) 2016 + * by Dimok + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any + * damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for any + * purpose, including commercial applications, and to alter it and + * redistribute it freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you + * must not claim that you wrote the original software. If you use + * this software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and + * must not be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + ***************************************************************************/ +#ifndef _LIB_IOSUHAX_H_ +#define _LIB_IOSUHAX_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define IOS_ERROR_UNKNOWN_VALUE 0xFFFFFFD6 +#define IOS_ERROR_INVALID_ARG 0xFFFFFFE3 +#define IOS_ERROR_INVALID_SIZE 0xFFFFFFE9 +#define IOS_ERROR_UNKNOWN 0xFFFFFFF7 +#define IOS_ERROR_NOEXISTS 0xFFFFFFFA + +typedef struct +{ + uint32_t flag; + uint32_t permission; + uint32_t owner_id; + uint32_t group_id; + uint32_t size; // size in bytes + uint32_t physsize; // physical size on disk in bytes + uint32_t unk[3]; + uint32_t id; + uint32_t ctime; + uint32_t mtime; + uint32_t unk2[0x0D]; +}fileStat_s; + +typedef struct +{ + fileStat_s stat; + char name[0x100]; +}directoryEntry_s; + +#define DIR_ENTRY_IS_DIRECTORY 0x80000000 + +#define FSA_MOUNTFLAGS_BINDMOUNT (1 << 0) +#define FSA_MOUNTFLAGS_GLOBAL (1 << 1) + +int IOSUHAX_Open(const char *dev); // if dev == NULL the default path /dev/iosuhax will be used +int IOSUHAX_Close(void); + +int IOSUHAX_memwrite(uint32_t address, const uint8_t * buffer, uint32_t size); // IOSU external input +int IOSUHAX_memread(uint32_t address, uint8_t * out_buffer, uint32_t size); // IOSU external output +int IOSUHAX_memcpy(uint32_t dst, uint32_t src, uint32_t size); // IOSU internal memcpy only + +int IOSUHAX_kern_write32(uint32_t address, uint32_t value); +int IOSUHAX_kern_read32(uint32_t address, uint32_t* out_buffer, uint32_t count); + +int IOSUHAX_SVC(uint32_t svc_id, uint32_t * args, uint32_t arg_cnt); + +int IOSUHAX_FSA_Open(); +int IOSUHAX_FSA_Close(int fsaFd); + +int IOSUHAX_FSA_Mount(int fsaFd, const char* device_path, const char* volume_path, uint32_t flags, const char* arg_string, int arg_string_len); +int IOSUHAX_FSA_Unmount(int fsaFd, const char* path, uint32_t flags); +int IOSUHAX_FSA_FlushVolume(int fsaFd, const char* volume_path); + +int IOSUHAX_FSA_GetDeviceInfo(int fsaFd, const char* device_path, int type, uint32_t* out_data); + +int IOSUHAX_FSA_MakeDir(int fsaFd, const char* path, uint32_t flags); +int IOSUHAX_FSA_OpenDir(int fsaFd, const char* path, int* outHandle); +int IOSUHAX_FSA_ReadDir(int fsaFd, int handle, directoryEntry_s* out_data); +int IOSUHAX_FSA_RewindDir(int fsaFd, int dirHandle); +int IOSUHAX_FSA_CloseDir(int fsaFd, int handle); +int IOSUHAX_FSA_ChangeDir(int fsaFd, const char *path); + +int IOSUHAX_FSA_OpenFile(int fsaFd, const char* path, const char* mode, int* outHandle); +int IOSUHAX_FSA_ReadFile(int fsaFd, void* data, uint32_t size, uint32_t cnt, int fileHandle, uint32_t flags); +int IOSUHAX_FSA_WriteFile(int fsaFd, const void* data, uint32_t size, uint32_t cnt, int fileHandle, uint32_t flags); +int IOSUHAX_FSA_StatFile(int fsaFd, int fileHandle, fileStat_s* out_data); +int IOSUHAX_FSA_CloseFile(int fsaFd, int fileHandle); +int IOSUHAX_FSA_SetFilePos(int fsaFd, int fileHandle, uint32_t position); +int IOSUHAX_FSA_GetStat(int fsaFd, const char *path, fileStat_s* out_data); +int IOSUHAX_FSA_Remove(int fsaFd, const char *path); +int IOSUHAX_FSA_ChangeMode(int fsaFd, const char* path, int mode); + +int IOSUHAX_FSA_RawOpen(int fsaFd, const char* device_path, int* outHandle); +int IOSUHAX_FSA_RawRead(int fsaFd, void* data, uint32_t block_size, uint32_t block_cnt, uint64_t sector_offset, int device_handle); +int IOSUHAX_FSA_RawWrite(int fsaFd, const void* data, uint32_t block_size, uint32_t block_cnt, uint64_t sector_offset, int device_handle); +int IOSUHAX_FSA_RawClose(int fsaFd, int device_handle); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/deps/libiosuhax/iosuhax_devoptab.h b/deps/libiosuhax/include/iosuhax_devoptab.h similarity index 97% rename from deps/libiosuhax/iosuhax_devoptab.h rename to deps/libiosuhax/include/iosuhax_devoptab.h index 2c7d5d227c..18847a683c 100644 --- a/deps/libiosuhax/iosuhax_devoptab.h +++ b/deps/libiosuhax/include/iosuhax_devoptab.h @@ -1,42 +1,42 @@ -/*************************************************************************** - * Copyright (C) 2015 - * by Dimok - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event will the authors be held liable for any - * damages arising from the use of this software. - * - * Permission is granted to anyone to use this software for any - * purpose, including commercial applications, and to alter it and - * redistribute it freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you - * must not claim that you wrote the original software. If you use - * this software in a product, an acknowledgment in the product - * documentation would be appreciated but is not required. - * - * 2. Altered source versions must be plainly marked as such, and - * must not be misrepresented as being the original software. - * - * 3. This notice may not be removed or altered from any source - * distribution. - ***************************************************************************/ -#ifndef __IOSUHAX_DEVOPTAB_H_ -#define __IOSUHAX_DEVOPTAB_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -//! virtual name example: sd or odd (for sd:/ or odd:/ access) -//! fsaFd: fd received by IOSUHAX_FSA_Open(); -//! dev_path: (optional) if a device should be mounted to the mount_path. If NULL no IOSUHAX_FSA_Mount is not executed. -//! mount_path: path to map to virtual device name -int mount_fs(const char *virt_name, int fsaFd, const char *dev_path, const char *mount_path); -int unmount_fs(const char *virt_name); - -#ifdef __cplusplus -} -#endif - -#endif // __IOSUHAX_DEVOPTAB_H_ +/*************************************************************************** + * Copyright (C) 2015 + * by Dimok + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any + * damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for any + * purpose, including commercial applications, and to alter it and + * redistribute it freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you + * must not claim that you wrote the original software. If you use + * this software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and + * must not be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + ***************************************************************************/ +#ifndef __IOSUHAX_DEVOPTAB_H_ +#define __IOSUHAX_DEVOPTAB_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +//! virtual name example: sd or odd (for sd:/ or odd:/ access) +//! fsaFd: fd received by IOSUHAX_FSA_Open(); +//! dev_path: (optional) if a device should be mounted to the mount_path. If NULL no IOSUHAX_FSA_Mount is not executed. +//! mount_path: path to map to virtual device name +int mount_fs(const char *virt_name, int fsaFd, const char *dev_path, const char *mount_path); +int unmount_fs(const char *virt_name); + +#ifdef __cplusplus +} +#endif + +#endif // __IOSUHAX_DEVOPTAB_H_ diff --git a/deps/libiosuhax/iosuhax_disc_interface.h b/deps/libiosuhax/include/iosuhax_disc_interface.h similarity index 97% rename from deps/libiosuhax/iosuhax_disc_interface.h rename to deps/libiosuhax/include/iosuhax_disc_interface.h index 0ce479547b..c5b703b7bc 100644 --- a/deps/libiosuhax/iosuhax_disc_interface.h +++ b/deps/libiosuhax/include/iosuhax_disc_interface.h @@ -1,73 +1,73 @@ -/*************************************************************************** - * Copyright (C) 2016 - * by Dimok - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event will the authors be held liable for any - * damages arising from the use of this software. - * - * Permission is granted to anyone to use this software for any - * purpose, including commercial applications, and to alter it and - * redistribute it freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you - * must not claim that you wrote the original software. If you use - * this software in a product, an acknowledgment in the product - * documentation would be appreciated but is not required. - * - * 2. Altered source versions must be plainly marked as such, and - * must not be misrepresented as being the original software. - * - * 3. This notice may not be removed or altered from any source - * distribution. - ***************************************************************************/ -#ifndef _IOSUHAX_DISC_INTERFACE_H_ -#define _IOSUHAX_DISC_INTERFACE_H_ - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#define DEVICE_TYPE_WII_U_SD (('W'<<24)|('U'<<16)|('S'<<8)|'D') -#define DEVICE_TYPE_WII_U_USB (('W'<<24)|('U'<<16)|('S'<<8)|'B') -#define FEATURE_WII_U_SD 0x00001000 -#define FEATURE_WII_U_USB 0x00002000 - -#ifndef OGC_DISC_IO_INCLUDE -typedef uint32_t sec_t; - -#define FEATURE_MEDIUM_CANREAD 0x00000001 -#define FEATURE_MEDIUM_CANWRITE 0x00000002 - -typedef bool (* FN_MEDIUM_STARTUP)(void) ; -typedef bool (* FN_MEDIUM_ISINSERTED)(void) ; -typedef bool (* FN_MEDIUM_READSECTORS)(uint32_t sector, uint32_t numSectors, void* buffer) ; -typedef bool (* FN_MEDIUM_WRITESECTORS)(uint32_t sector, uint32_t numSectors, const void* buffer) ; -typedef bool (* FN_MEDIUM_CLEARSTATUS)(void) ; -typedef bool (* FN_MEDIUM_SHUTDOWN)(void) ; - -struct DISC_INTERFACE_STRUCT { - unsigned long ioType ; - unsigned long features ; - FN_MEDIUM_STARTUP startup ; - FN_MEDIUM_ISINSERTED isInserted ; - FN_MEDIUM_READSECTORS readSectors ; - FN_MEDIUM_WRITESECTORS writeSectors ; - FN_MEDIUM_CLEARSTATUS clearStatus ; - FN_MEDIUM_SHUTDOWN shutdown ; -} ; - -typedef struct DISC_INTERFACE_STRUCT DISC_INTERFACE ; -#endif - -extern const DISC_INTERFACE IOSUHAX_sdio_disc_interface; -extern const DISC_INTERFACE IOSUHAX_usb_disc_interface; - -#ifdef __cplusplus -} -#endif - -#endif +/*************************************************************************** + * Copyright (C) 2016 + * by Dimok + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any + * damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for any + * purpose, including commercial applications, and to alter it and + * redistribute it freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you + * must not claim that you wrote the original software. If you use + * this software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and + * must not be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + ***************************************************************************/ +#ifndef _IOSUHAX_DISC_INTERFACE_H_ +#define _IOSUHAX_DISC_INTERFACE_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define DEVICE_TYPE_WII_U_SD (('W'<<24)|('U'<<16)|('S'<<8)|'D') +#define DEVICE_TYPE_WII_U_USB (('W'<<24)|('U'<<16)|('S'<<8)|'B') +#define FEATURE_WII_U_SD 0x00001000 +#define FEATURE_WII_U_USB 0x00002000 + +#ifndef OGC_DISC_IO_INCLUDE +typedef uint32_t sec_t; + +#define FEATURE_MEDIUM_CANREAD 0x00000001 +#define FEATURE_MEDIUM_CANWRITE 0x00000002 + +typedef bool (* FN_MEDIUM_STARTUP)(void) ; +typedef bool (* FN_MEDIUM_ISINSERTED)(void) ; +typedef bool (* FN_MEDIUM_READSECTORS)(uint32_t sector, uint32_t numSectors, void* buffer) ; +typedef bool (* FN_MEDIUM_WRITESECTORS)(uint32_t sector, uint32_t numSectors, const void* buffer) ; +typedef bool (* FN_MEDIUM_CLEARSTATUS)(void) ; +typedef bool (* FN_MEDIUM_SHUTDOWN)(void) ; + +struct DISC_INTERFACE_STRUCT { + unsigned long ioType ; + unsigned long features ; + FN_MEDIUM_STARTUP startup ; + FN_MEDIUM_ISINSERTED isInserted ; + FN_MEDIUM_READSECTORS readSectors ; + FN_MEDIUM_WRITESECTORS writeSectors ; + FN_MEDIUM_CLEARSTATUS clearStatus ; + FN_MEDIUM_SHUTDOWN shutdown ; +} ; + +typedef struct DISC_INTERFACE_STRUCT DISC_INTERFACE ; +#endif + +extern const DISC_INTERFACE IOSUHAX_sdio_disc_interface; +extern const DISC_INTERFACE IOSUHAX_usb_disc_interface; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/deps/libiosuhax/os_functions.h b/deps/libiosuhax/os_functions.h deleted file mode 100644 index 6135236344..0000000000 --- a/deps/libiosuhax/os_functions.h +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef __OS_FUNCTIONS_H_ -#define __OS_FUNCTIONS_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#define OS_MUTEX_SIZE 44 - -// RetroArch mod: use existing headers; prevents conflicts in griffin -#include -#include -#if 0 - -#ifndef __WUT__ -//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -//! Mutex functions -//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -extern void (* OSInitMutex)(void* mutex); -extern void (* OSLockMutex)(void* mutex); -extern void (* OSUnlockMutex)(void* mutex); - -//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -//! IOS function -//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -extern int (*IOS_Ioctl)(int fd, unsigned int request, void *input_buffer,unsigned int input_buffer_len, void *output_buffer, unsigned int output_buffer_len); -extern int (*IOS_Open)(char *path, unsigned int mode); -extern int (*IOS_Close)(int fd); -#else -//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -//! Mutex functions -//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -extern void OSInitMutex(void* mutex); -extern void OSLockMutex(void* mutex); -extern void OSUnlockMutex(void* mutex); - -//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -//! IOS function -//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -extern int IOS_Ioctl(int fd, unsigned int request, void *input_buffer,unsigned int input_buffer_len, void *output_buffer, unsigned int output_buffer_len); -extern int IOS_Open(char *path, unsigned int mode); -extern int IOS_Close(int fd); -#endif // __WUT__ - -#ifdef __cplusplus -} -#endif - -#endif // 0 - -#endif // __OS_FUNCTIONS_H_ diff --git a/deps/libiosuhax/iosuhax.c b/deps/libiosuhax/source/iosuhax.c similarity index 78% rename from deps/libiosuhax/iosuhax.c rename to deps/libiosuhax/source/iosuhax.c index 34a842ce73..bf6032850d 100644 --- a/deps/libiosuhax/iosuhax.c +++ b/deps/libiosuhax/source/iosuhax.c @@ -1,1029 +1,956 @@ -/*************************************************************************** - * Copyright (C) 2016 - * by Dimok - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event will the authors be held liable for any - * damages arising from the use of this software. - * - * Permission is granted to anyone to use this software for any - * purpose, including commercial applications, and to alter it and - * redistribute it freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you - * must not claim that you wrote the original software. If you use - * this software in a product, an acknowledgment in the product - * documentation would be appreciated but is not required. - * - * 2. Altered source versions must be plainly marked as such, and - * must not be misrepresented as being the original software. - * - * 3. This notice may not be removed or altered from any source - * distribution. - ***************************************************************************/ -#include -#include -#include "os_functions.h" -#include "iosuhax.h" - -#define IOSUHAX_MAGIC_WORD 0x4E696365 - -#define IOCTL_MEM_WRITE 0x00 -#define IOCTL_MEM_READ 0x01 -#define IOCTL_SVC 0x02 -#define IOCTL_MEMCPY 0x04 -#define IOCTL_REPEATED_WRITE 0x05 -#define IOCTL_KERN_READ32 0x06 -#define IOCTL_KERN_WRITE32 0x07 - -#define IOCTL_FSA_OPEN 0x40 -#define IOCTL_FSA_CLOSE 0x41 -#define IOCTL_FSA_MOUNT 0x42 -#define IOCTL_FSA_UNMOUNT 0x43 -#define IOCTL_FSA_GETDEVICEINFO 0x44 -#define IOCTL_FSA_OPENDIR 0x45 -#define IOCTL_FSA_READDIR 0x46 -#define IOCTL_FSA_CLOSEDIR 0x47 -#define IOCTL_FSA_MAKEDIR 0x48 -#define IOCTL_FSA_OPENFILE 0x49 -#define IOCTL_FSA_READFILE 0x4A -#define IOCTL_FSA_WRITEFILE 0x4B -#define IOCTL_FSA_STATFILE 0x4C -#define IOCTL_FSA_CLOSEFILE 0x4D -#define IOCTL_FSA_SETFILEPOS 0x4E -#define IOCTL_FSA_GETSTAT 0x4F -#define IOCTL_FSA_REMOVE 0x50 -#define IOCTL_FSA_REWINDDIR 0x51 -#define IOCTL_FSA_CHDIR 0x52 -#define IOCTL_FSA_RENAME 0x53 -#define IOCTL_FSA_RAW_OPEN 0x54 -#define IOCTL_FSA_RAW_READ 0x55 -#define IOCTL_FSA_RAW_WRITE 0x56 -#define IOCTL_FSA_RAW_CLOSE 0x57 -#define IOCTL_FSA_CHANGEMODE 0x58 -#define IOCTL_FSA_FLUSHVOLUME 0x59 -#define IOCTL_CHECK_IF_IOSUHAX 0x5B - -static int iosuhaxHandle = -1; - -int IOSUHAX_Open(const char *dev) -{ - if(iosuhaxHandle >= 0) - return iosuhaxHandle; - - iosuhaxHandle = IOS_Open((char*)(dev ? dev : "/dev/iosuhax"), 0); - if(iosuhaxHandle >= 0 && dev) /* make sure device is actually iosuhax */ - { - unsigned int res = 0; - IOS_Ioctl(iosuhaxHandle, IOCTL_CHECK_IF_IOSUHAX, (void*)0, 0, &res, 4); - if(res != IOSUHAX_MAGIC_WORD) - { - IOS_Close(iosuhaxHandle); - iosuhaxHandle = -1; - } - } - - return iosuhaxHandle; -} - -int IOSUHAX_Close(void) -{ - if(iosuhaxHandle < 0) - return 0; - - int res = IOS_Close(iosuhaxHandle); - iosuhaxHandle = -1; - return res; -} - -int IOSUHAX_memwrite(uint32_t address, const uint8_t * buffer, uint32_t size) -{ - if(iosuhaxHandle < 0) - return iosuhaxHandle; - - if(!buffer) - return -1; - - uint32_t *io_buf = (uint32_t*)memalign(0x20, size + 4); - if(!io_buf) - return -2; - - io_buf[0] = address; - memcpy(io_buf + 1, buffer, size); - - int res = IOS_Ioctl(iosuhaxHandle, IOCTL_MEM_WRITE, io_buf, size + 4, 0, 0); - - free(io_buf); - return res; -} - -int IOSUHAX_memread(uint32_t address, uint8_t * out_buffer, uint32_t size) -{ - if(iosuhaxHandle < 0) - return iosuhaxHandle; - - if(!out_buffer || !size) - return -1; - - return IOS_Ioctl(iosuhaxHandle, IOCTL_MEM_READ, &address, sizeof(address), out_buffer, size); -} - -int IOSUHAX_memcpy(uint32_t dst, uint32_t src, uint32_t size) -{ - if(iosuhaxHandle < 0) - return iosuhaxHandle; - - if(!dst || !src || !size) - return -1; - - uint32_t io_buf[3]; - io_buf[0] = dst; - io_buf[1] = src; - io_buf[2] = size; - - return IOS_Ioctl(iosuhaxHandle, IOCTL_MEMCPY, io_buf, sizeof(io_buf), 0, 0); -} - -int IOSUHAX_SVC(uint32_t svc_id, uint32_t * args, uint32_t arg_cnt) -{ - if(iosuhaxHandle < 0) - return iosuhaxHandle; - - uint32_t arguments[9]; - arguments[0] = svc_id; - - if(args && arg_cnt) - { - if(arg_cnt > 8) - arg_cnt = 8; - - memcpy(arguments + 1, args, arg_cnt * 4); - } - - int result; - int ret = IOS_Ioctl(iosuhaxHandle, IOCTL_SVC, arguments, (1 + arg_cnt) * 4, &result, sizeof(result)); - if(ret < 0) - return ret; - - return result; -} - -int IOSUHAX_FSA_Open(void) -{ - if(iosuhaxHandle < 0) - return iosuhaxHandle; - - int fsaFd; - - int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_OPEN, 0, 0, &fsaFd, sizeof(fsaFd)); - if(res < 0) - return res; - - return fsaFd; -} - -int IOSUHAX_FSA_Close(int fsaFd) -{ - if(iosuhaxHandle < 0) - return iosuhaxHandle; - - int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_CLOSE, &fsaFd, sizeof(fsaFd), &fsaFd, sizeof(fsaFd)); - if(res < 0) - return res; - - return fsaFd; -} - -int IOSUHAX_FSA_Mount(int fsaFd, const char* device_path, const char* volume_path, uint32_t flags, const char* arg_string, int arg_string_len) -{ - if(iosuhaxHandle < 0) - return iosuhaxHandle; - - if(!device_path || !volume_path || !arg_string) - return -1; - - const int input_cnt = 6; - - int io_buf_size = (sizeof(uint32_t) * input_cnt) + strlen(device_path) + strlen(volume_path) + arg_string_len + 3; - - uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); - if(!io_buf) - return -2; - - memset(io_buf, 0, io_buf_size); - io_buf[0] = fsaFd; - io_buf[1] = sizeof(uint32_t) * input_cnt; - io_buf[2] = io_buf[1] + strlen(device_path) + 1; - io_buf[3] = flags; - io_buf[4] = arg_string_len ? ( io_buf[2] + strlen(volume_path) + 1) : 0; - io_buf[5] = arg_string_len; - - strcpy(((char*)io_buf) + io_buf[1], device_path); - strcpy(((char*)io_buf) + io_buf[2], volume_path); - - if(arg_string_len) - memcpy(((char*)io_buf) + io_buf[4], arg_string, arg_string_len); - - int mountRes; - - int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_MOUNT, io_buf, io_buf_size, &mountRes, sizeof(mountRes)); - if(res < 0) - { - free(io_buf); - return res; - } - - free(io_buf); - return mountRes; -} - -int IOSUHAX_FSA_Unmount(int fsaFd, const char* path, uint32_t flags) -{ - if(iosuhaxHandle < 0) - return iosuhaxHandle; - - if(!path) - return -1; - - const int input_cnt = 3; - - int io_buf_size = sizeof(uint32_t) * input_cnt + strlen(path) + 1; - - uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); - if(!io_buf) - return -2; - - io_buf[0] = fsaFd; - io_buf[1] = sizeof(uint32_t) * input_cnt; - io_buf[2] = flags; - strcpy(((char*)io_buf) + io_buf[1], path); - - int result; - - int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_UNMOUNT, io_buf, io_buf_size, &result, sizeof(result)); - if(res < 0) - { - free(io_buf); - return res; - } - - free(io_buf); - return result; -} - -int IOSUHAX_FSA_FlushVolume(int fsaFd, const char *volume_path) -{ - if(iosuhaxHandle < 0) - return iosuhaxHandle; - - if(!volume_path) - return -1; - - const int input_cnt = 2; - - int io_buf_size = sizeof(uint32_t) * input_cnt + strlen(volume_path) + 1; - - uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); - if(!io_buf) - return -2; - - io_buf[0] = fsaFd; - io_buf[1] = sizeof(uint32_t) * input_cnt; - strcpy(((char*)io_buf) + io_buf[1], volume_path); - - int result; - - int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_FLUSHVOLUME, io_buf, io_buf_size, &result, sizeof(result)); - if(res < 0) - { - free(io_buf); - return res; - } - - free(io_buf); - return result; -} - -int IOSUHAX_FSA_GetDeviceInfo(int fsaFd, const char* device_path, int type, uint32_t* out_data) -{ - if(iosuhaxHandle < 0) - return iosuhaxHandle; - - if(!device_path || !out_data) - return -1; - - const int input_cnt = 3; - - int io_buf_size = sizeof(uint32_t) * input_cnt + strlen(device_path) + 1; - - uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); - if(!io_buf) - return -2; - - io_buf[0] = fsaFd; - io_buf[1] = sizeof(uint32_t) * input_cnt; - io_buf[2] = type; - strcpy(((char*)io_buf) + io_buf[1], device_path); - - uint32_t out_buf[1 + 0x64 / 4]; - - int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_GETDEVICEINFO, io_buf, io_buf_size, out_buf, sizeof(out_buf)); - if(res < 0) - { - free(io_buf); - return res; - } - - memcpy(out_data, out_buf + 1, 0x64); - free(io_buf); - return out_buf[0]; -} - -int IOSUHAX_FSA_MakeDir(int fsaFd, const char* path, uint32_t flags) -{ - if(iosuhaxHandle < 0) - return iosuhaxHandle; - - if(!path) - return -1; - - const int input_cnt = 3; - - int io_buf_size = sizeof(uint32_t) * input_cnt + strlen(path) + 1; - - uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); - if(!io_buf) - return -2; - - io_buf[0] = fsaFd; - io_buf[1] = sizeof(uint32_t) * input_cnt; - io_buf[2] = flags; - strcpy(((char*)io_buf) + io_buf[1], path); - - int result; - int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_MAKEDIR, io_buf, io_buf_size, &result, sizeof(result)); - if(res < 0) - { - free(io_buf); - return res; - } - - free(io_buf); - return result; -} - -int IOSUHAX_FSA_OpenDir(int fsaFd, const char* path, int* outHandle) -{ - if(iosuhaxHandle < 0) - return iosuhaxHandle; - - if(!path) - return -1; - - const int input_cnt = 2; - - int io_buf_size = sizeof(uint32_t) * input_cnt + strlen(path) + 1; - - uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); - if(!io_buf) - return -2; - - io_buf[0] = fsaFd; - io_buf[1] = sizeof(uint32_t) * input_cnt; - strcpy(((char*)io_buf) + io_buf[1], path); - - int result_vec[2]; - - int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_OPENDIR, io_buf, io_buf_size, result_vec, sizeof(result_vec)); - if(res < 0) - { - free(io_buf); - return res; - } - - *outHandle = result_vec[1]; - free(io_buf); - return result_vec[0]; -} - -int IOSUHAX_FSA_ReadDir(int fsaFd, int handle, directoryEntry_s* out_data) -{ - if(iosuhaxHandle < 0) - return iosuhaxHandle; - - if(!out_data) - return -1; - - const int input_cnt = 2; - - int io_buf_size = sizeof(uint32_t) * input_cnt; - - uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); - if(!io_buf) - return -2; - - io_buf[0] = fsaFd; - io_buf[1] = handle; - - int result_vec_size = 4 + sizeof(directoryEntry_s); - uint8_t *result_vec = (uint8_t*) memalign(0x20, result_vec_size); - if(!result_vec) - { - free(io_buf); - return -2; - } - - int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_READDIR, io_buf, io_buf_size, result_vec, result_vec_size); - if(res < 0) - { - free(result_vec); - free(io_buf); - return res; - } - - int result = *(int*)result_vec; - memcpy(out_data, result_vec + 4, sizeof(directoryEntry_s)); - free(io_buf); - free(result_vec); - return result; -} - -int IOSUHAX_FSA_RewindDir(int fsaFd, int dirHandle) -{ - if(iosuhaxHandle < 0) - return iosuhaxHandle; - - const int input_cnt = 2; - - int io_buf_size = sizeof(uint32_t) * input_cnt; - - uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); - if(!io_buf) - return -2; - - io_buf[0] = fsaFd; - io_buf[1] = dirHandle; - - int result; - - int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_REWINDDIR, io_buf, io_buf_size, &result, sizeof(result)); - if(res < 0) - { - free(io_buf); - return res; - } - - free(io_buf); - return result; -} - -int IOSUHAX_FSA_CloseDir(int fsaFd, int handle) -{ - if(iosuhaxHandle < 0) - return iosuhaxHandle; - - const int input_cnt = 2; - - int io_buf_size = sizeof(uint32_t) * input_cnt; - - uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); - if(!io_buf) - return -2; - - io_buf[0] = fsaFd; - io_buf[1] = handle; - - int result; - - int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_CLOSEDIR, io_buf, io_buf_size, &result, sizeof(result)); - if(res < 0) - { - free(io_buf); - return res; - } - - free(io_buf); - return result; -} - -int IOSUHAX_FSA_ChangeDir(int fsaFd, const char *path) -{ - if(iosuhaxHandle < 0) - return iosuhaxHandle; - - if(!path) - return -1; - - const int input_cnt = 2; - - int io_buf_size = sizeof(uint32_t) * input_cnt + strlen(path) + 1; - - uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); - if(!io_buf) - return -2; - - io_buf[0] = fsaFd; - io_buf[1] = sizeof(uint32_t) * input_cnt; - strcpy(((char*)io_buf) + io_buf[1], path); - - int result; - - int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_CHDIR, io_buf, io_buf_size, &result, sizeof(result)); - if(res < 0) - { - free(io_buf); - return res; - } - - free(io_buf); - return result; -} - -int IOSUHAX_FSA_OpenFile(int fsaFd, const char* path, const char* mode, int* outHandle) -{ - if(iosuhaxHandle < 0) - return iosuhaxHandle; - - if(!path || !mode || !outHandle) - return -1; - - const int input_cnt = 3; - - int io_buf_size = sizeof(uint32_t) * input_cnt + strlen(path) + strlen(mode) + 2; - - uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); - if(!io_buf) - return -2; - - io_buf[0] = fsaFd; - io_buf[1] = sizeof(uint32_t) * input_cnt; - io_buf[2] = io_buf[1] + strlen(path) + 1; - strcpy(((char*)io_buf) + io_buf[1], path); - strcpy(((char*)io_buf) + io_buf[2], mode); - - int result_vec[2]; - - int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_OPENFILE, io_buf, io_buf_size, result_vec, sizeof(result_vec)); - if(res < 0) - { - free(io_buf); - return res; - } - - *outHandle = result_vec[1]; - free(io_buf); - return result_vec[0]; -} - -int IOSUHAX_FSA_ReadFile(int fsaFd, void* data, uint32_t size, uint32_t cnt, int fileHandle, uint32_t flags) -{ - if(iosuhaxHandle < 0) - return iosuhaxHandle; - - if(!data) - return -1; - - const int input_cnt = 5; - - int io_buf_size = sizeof(uint32_t) * input_cnt; - - uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); - if(!io_buf) - return -2; - - io_buf[0] = fsaFd; - io_buf[1] = size; - io_buf[2] = cnt; - io_buf[3] = fileHandle; - io_buf[4] = flags; - - int out_buf_size = ((size * cnt + 0x40) + 0x3F) & ~0x3F; - - uint32_t *out_buffer = (uint32_t*)memalign(0x40, out_buf_size); - if(!out_buffer) - { - free(io_buf); - return -2; - } - - int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_READFILE, io_buf, io_buf_size, out_buffer, out_buf_size); - if(res < 0) - { - free(out_buffer); - free(io_buf); - return res; - } - - /* ! data is put to offset 0x40 to align the buffer output */ - memcpy(data, ((uint8_t*)out_buffer) + 0x40, size * cnt); - - int result = out_buffer[0]; - - free(out_buffer); - free(io_buf); - return result; -} - -int IOSUHAX_FSA_WriteFile(int fsaFd, const void* data, uint32_t size, uint32_t cnt, int fileHandle, uint32_t flags) -{ - if(iosuhaxHandle < 0) - return iosuhaxHandle; - - if(!data) - return -1; - - const int input_cnt = 5; - - int io_buf_size = ((sizeof(uint32_t) * input_cnt + size * cnt + 0x40) + 0x3F) & ~0x3F; - - uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); - if(!io_buf) - return -2; - - io_buf[0] = fsaFd; - io_buf[1] = size; - io_buf[2] = cnt; - io_buf[3] = fileHandle; - io_buf[4] = flags; - - /* ! data is put to offset 0x40 to align the buffer input */ - memcpy(((uint8_t*)io_buf) + 0x40, data, size * cnt); - - int result; - int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_WRITEFILE, io_buf, io_buf_size, &result, sizeof(result)); - if(res < 0) - { - free(io_buf); - return res; - } - free(io_buf); - return result; -} - -int IOSUHAX_FSA_StatFile(int fsaFd, int fileHandle, fileStat_s* out_data) -{ - if(iosuhaxHandle < 0) - return iosuhaxHandle; - - if(!out_data) - return -1; - - const int input_cnt = 2; - - int io_buf_size = sizeof(uint32_t) * input_cnt; - - uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); - if(!io_buf) - return -2; - - io_buf[0] = fsaFd; - io_buf[1] = fileHandle; - - int out_buf_size = 4 + sizeof(fileStat_s); - uint32_t *out_buffer = (uint32_t*)memalign(0x20, out_buf_size); - if(!out_buffer) - { - free(io_buf); - return -2; - } - - int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_STATFILE, io_buf, io_buf_size, out_buffer, out_buf_size); - if(res < 0) - { - free(io_buf); - free(out_buffer); - return res; - } - - int result = out_buffer[0]; - memcpy(out_data, out_buffer + 1, sizeof(fileStat_s)); - - free(io_buf); - free(out_buffer); - return result; -} - -int IOSUHAX_FSA_CloseFile(int fsaFd, int fileHandle) -{ - if(iosuhaxHandle < 0) - return iosuhaxHandle; - - const int input_cnt = 2; - - int io_buf_size = sizeof(uint32_t) * input_cnt; - - uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); - if(!io_buf) - return -2; - - io_buf[0] = fsaFd; - io_buf[1] = fileHandle; - - int result; - - int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_CLOSEFILE, io_buf, io_buf_size, &result, sizeof(result)); - if(res < 0) - { - free(io_buf); - return res; - } - - free(io_buf); - return result; -} - -int IOSUHAX_FSA_SetFilePos(int fsaFd, int fileHandle, uint32_t position) -{ - if(iosuhaxHandle < 0) - return iosuhaxHandle; - - const int input_cnt = 3; - - int io_buf_size = sizeof(uint32_t) * input_cnt; - - uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); - if(!io_buf) - return -2; - - io_buf[0] = fsaFd; - io_buf[1] = fileHandle; - io_buf[2] = position; - - int result; - - int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_SETFILEPOS, io_buf, io_buf_size, &result, sizeof(result)); - if(res < 0) - { - free(io_buf); - return res; - } - - free(io_buf); - return result; -} - -int IOSUHAX_FSA_GetStat(int fsaFd, const char *path, fileStat_s* out_data) -{ - if(iosuhaxHandle < 0) - return iosuhaxHandle; - - if(!path || !out_data) - return -1; - - const int input_cnt = 2; - - int io_buf_size = sizeof(uint32_t) * input_cnt + strlen(path) + 1; - - uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); - if(!io_buf) - return -2; - - io_buf[0] = fsaFd; - io_buf[1] = sizeof(uint32_t) * input_cnt; - strcpy(((char*)io_buf) + io_buf[1], path); - - int out_buf_size = 4 + sizeof(fileStat_s); - uint32_t *out_buffer = (uint32_t*)memalign(0x20, out_buf_size); - if(!out_buffer) - { - free(io_buf); - return -2; - } - - int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_GETSTAT, io_buf, io_buf_size, out_buffer, out_buf_size); - if(res < 0) - { - free(io_buf); - free(out_buffer); - return res; - } - - int result = out_buffer[0]; - memcpy(out_data, out_buffer + 1, sizeof(fileStat_s)); - - free(io_buf); - free(out_buffer); - return result; -} - -int IOSUHAX_FSA_Remove(int fsaFd, const char *path) -{ - if(iosuhaxHandle < 0) - return iosuhaxHandle; - - if(!path) - return -1; - - const int input_cnt = 2; - - int io_buf_size = sizeof(uint32_t) * input_cnt + strlen(path) + 1; - - uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); - if(!io_buf) - return -2; - - io_buf[0] = fsaFd; - io_buf[1] = sizeof(uint32_t) * input_cnt; - strcpy(((char*)io_buf) + io_buf[1], path); - - int result; - - int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_REMOVE, io_buf, io_buf_size, &result, sizeof(result)); - if(res < 0) - { - free(io_buf); - return res; - } - - free(io_buf); - return result; -} - -int IOSUHAX_FSA_ChangeMode(int fsaFd, const char* path, int mode) -{ - if(iosuhaxHandle < 0) - return iosuhaxHandle; - - if(!path) - return -1; - - const int input_cnt = 3; - - int io_buf_size = sizeof(uint32_t) * input_cnt + strlen(path) + 1; - - uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); - if(!io_buf) - return -2; - - io_buf[0] = fsaFd; - io_buf[1] = sizeof(uint32_t) * input_cnt; - io_buf[2] = mode; - strcpy(((char*)io_buf) + io_buf[1], path); - - int result; - - int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_CHANGEMODE, io_buf, io_buf_size, &result, sizeof(result)); - if(res < 0) - { - free(io_buf); - return res; - } - - free(io_buf); - return result; -} - -int IOSUHAX_FSA_RawOpen(int fsaFd, const char* device_path, int* outHandle) -{ - if(iosuhaxHandle < 0) - return iosuhaxHandle; - - if(!device_path && !outHandle) - return -1; - - const int input_cnt = 2; - - int io_buf_size = sizeof(uint32_t) * input_cnt + strlen(device_path) + 1; - - uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); - if(!io_buf) - return -2; - - io_buf[0] = fsaFd; - io_buf[1] = sizeof(uint32_t) * input_cnt; - strcpy(((char*)io_buf) + io_buf[1], device_path); - - int result_vec[2]; - - int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_RAW_OPEN, io_buf, io_buf_size, result_vec, sizeof(result_vec)); - if(res < 0) - { - free(io_buf); - return res; - } - - if(outHandle) - *outHandle = result_vec[1]; - - free(io_buf); - return result_vec[0]; -} - -int IOSUHAX_FSA_RawRead(int fsaFd, void* data, uint32_t block_size, uint32_t block_cnt, uint64_t sector_offset, int device_handle) -{ - if(iosuhaxHandle < 0) - return iosuhaxHandle; - - if(!data) - return -1; - - const int input_cnt = 6; - - int io_buf_size = sizeof(uint32_t) * input_cnt; - - uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); - if(!io_buf) - return -2; - - io_buf[0] = fsaFd; - io_buf[1] = block_size; - io_buf[2] = block_cnt; - io_buf[3] = (sector_offset >> 32) & 0xFFFFFFFF; - io_buf[4] = sector_offset & 0xFFFFFFFF; - io_buf[5] = device_handle; - - int out_buf_size = ((block_size * block_cnt + 0x40) + 0x3F) & ~0x3F; - - uint32_t *out_buffer = (uint32_t*)memalign(0x40, out_buf_size); - if(!out_buffer) - { - free(io_buf); - return -2; - } - - int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_RAW_READ, io_buf, io_buf_size, out_buffer, out_buf_size); - if(res < 0) - { - free(out_buffer); - free(io_buf); - return res; - } - - /* ! data is put to offset 0x40 to align the buffer output */ - memcpy(data, ((uint8_t*)out_buffer) + 0x40, block_size * block_cnt); - - int result = out_buffer[0]; - - free(out_buffer); - free(io_buf); - return result; -} - -int IOSUHAX_FSA_RawWrite(int fsaFd, const void* data, uint32_t block_size, uint32_t block_cnt, uint64_t sector_offset, int device_handle) -{ - if(iosuhaxHandle < 0) - return iosuhaxHandle; - - if(!data) - return -1; - - const int input_cnt = 6; - - int io_buf_size = ((sizeof(uint32_t) * input_cnt + block_size * block_cnt + 0x40) + 0x3F) & ~0x3F; - - uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); - if(!io_buf) - return -2; - - io_buf[0] = fsaFd; - io_buf[1] = block_size; - io_buf[2] = block_cnt; - io_buf[3] = (sector_offset >> 32) & 0xFFFFFFFF; - io_buf[4] = sector_offset & 0xFFFFFFFF; - io_buf[5] = device_handle; - - /* ! data is put to offset 0x40 to align the buffer input */ - memcpy(((uint8_t*)io_buf) + 0x40, data, block_size * block_cnt); - - int result; - - int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_RAW_WRITE, io_buf, io_buf_size, &result, sizeof(result)); - if(res < 0) - { - free(io_buf); - return res; - } - - free(io_buf); - return result; -} - - -int IOSUHAX_FSA_RawClose(int fsaFd, int device_handle) -{ - if(iosuhaxHandle < 0) - return iosuhaxHandle; - - const int input_cnt = 2; - - int io_buf_size = sizeof(uint32_t) * input_cnt; - - uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); - if(!io_buf) - return -2; - - io_buf[0] = fsaFd; - io_buf[1] = device_handle; - - int result; - - int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_RAW_CLOSE, io_buf, io_buf_size, &result, sizeof(result)); - if(res < 0) - { - free(io_buf); - return res; - } - - free(io_buf); - return result; -} +/*************************************************************************** + * Copyright (C) 2016 + * by Dimok + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any + * damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for any + * purpose, including commercial applications, and to alter it and + * redistribute it freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you + * must not claim that you wrote the original software. If you use + * this software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and + * must not be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + ***************************************************************************/ +#include +#include +#include "os_functions.h" +#include "iosuhax.h" + +#define IOSUHAX_MAGIC_WORD 0x4E696365 + +#define IOCTL_MEM_WRITE 0x00 +#define IOCTL_MEM_READ 0x01 +#define IOCTL_SVC 0x02 +#define IOCTL_MEMCPY 0x04 +#define IOCTL_REPEATED_WRITE 0x05 +#define IOCTL_KERN_READ32 0x06 +#define IOCTL_KERN_WRITE32 0x07 + +#define IOCTL_FSA_OPEN 0x40 +#define IOCTL_FSA_CLOSE 0x41 +#define IOCTL_FSA_MOUNT 0x42 +#define IOCTL_FSA_UNMOUNT 0x43 +#define IOCTL_FSA_GETDEVICEINFO 0x44 +#define IOCTL_FSA_OPENDIR 0x45 +#define IOCTL_FSA_READDIR 0x46 +#define IOCTL_FSA_CLOSEDIR 0x47 +#define IOCTL_FSA_MAKEDIR 0x48 +#define IOCTL_FSA_OPENFILE 0x49 +#define IOCTL_FSA_READFILE 0x4A +#define IOCTL_FSA_WRITEFILE 0x4B +#define IOCTL_FSA_STATFILE 0x4C +#define IOCTL_FSA_CLOSEFILE 0x4D +#define IOCTL_FSA_SETFILEPOS 0x4E +#define IOCTL_FSA_GETSTAT 0x4F +#define IOCTL_FSA_REMOVE 0x50 +#define IOCTL_FSA_REWINDDIR 0x51 +#define IOCTL_FSA_CHDIR 0x52 +#define IOCTL_FSA_RENAME 0x53 +#define IOCTL_FSA_RAW_OPEN 0x54 +#define IOCTL_FSA_RAW_READ 0x55 +#define IOCTL_FSA_RAW_WRITE 0x56 +#define IOCTL_FSA_RAW_CLOSE 0x57 +#define IOCTL_FSA_CHANGEMODE 0x58 +#define IOCTL_FSA_FLUSHVOLUME 0x59 +#define IOCTL_CHECK_IF_IOSUHAX 0x5B + +static int iosuhaxHandle = -1; + +#define ALIGN(align) __attribute__((aligned(align))) +#define ROUNDUP(x, align) (((x) + ((align) - 1)) & ~((align) - 1)) + +int IOSUHAX_Open(const char *dev) +{ + if(iosuhaxHandle >= 0) + return iosuhaxHandle; + + iosuhaxHandle = IOS_Open((char*)(dev ? dev : "/dev/iosuhax"), 0); + if(iosuhaxHandle >= 0 && dev) //make sure device is actually iosuhax + { + ALIGN(0x20) int res[0x20 >> 2]; + *res = 0; + + IOS_Ioctl(iosuhaxHandle, IOCTL_CHECK_IF_IOSUHAX, (void*)0, 0, res, 4); + if(*res != IOSUHAX_MAGIC_WORD) + { + IOS_Close(iosuhaxHandle); + iosuhaxHandle = -1; + } + } + + return iosuhaxHandle; +} + +int IOSUHAX_Close(void) +{ + if(iosuhaxHandle < 0) + return 0; + + int res = IOS_Close(iosuhaxHandle); + iosuhaxHandle = -1; + return res; +} + +int IOSUHAX_memwrite(uint32_t address, const uint8_t * buffer, uint32_t size) +{ + if(iosuhaxHandle < 0) + return iosuhaxHandle; + + uint32_t *io_buf = (uint32_t*)memalign(0x20, ROUNDUP(size + 4, 0x20)); + if(!io_buf) + return -2; + + io_buf[0] = address; + memcpy(io_buf + 1, buffer, size); + + int res = IOS_Ioctl(iosuhaxHandle, IOCTL_MEM_WRITE, io_buf, size + 4, 0, 0); + + free(io_buf); + return res; +} + +int IOSUHAX_memread(uint32_t address, uint8_t * out_buffer, uint32_t size) +{ + if(iosuhaxHandle < 0) + return iosuhaxHandle; + + ALIGN(0x20) int io_buf[0x20 >> 2]; + io_buf[0] = address; + + void* tmp_buf = NULL; + + if(((uintptr_t)out_buffer & 0x1F) || (size & 0x1F)) + { + tmp_buf = (uint32_t*)memalign(0x20, ROUNDUP(size, 0x20)); + if(!tmp_buf) + return -2; + } + + int res = IOS_Ioctl(iosuhaxHandle, IOCTL_MEM_READ, io_buf, sizeof(address), tmp_buf ? tmp_buf : out_buffer, size); + + if(res >= 0 && tmp_buf) + memcpy(out_buffer, tmp_buf, size); + + free(tmp_buf); + return res; +} + +int IOSUHAX_memcpy(uint32_t dst, uint32_t src, uint32_t size) +{ + if(iosuhaxHandle < 0) + return iosuhaxHandle; + + ALIGN(0x20) uint32_t io_buf[0x20 >> 2]; + io_buf[0] = dst; + io_buf[1] = src; + io_buf[2] = size; + + return IOS_Ioctl(iosuhaxHandle, IOCTL_MEMCPY, io_buf, 3 * sizeof(uint32_t), 0, 0); +} + +int IOSUHAX_kern_write32(uint32_t address, uint32_t value) +{ + if(iosuhaxHandle < 0) + return iosuhaxHandle; + + ALIGN(0x20) uint32_t io_buf[0x20 >> 2]; + io_buf[0] = address; + io_buf[1] = value; + + return IOS_Ioctl(iosuhaxHandle, IOCTL_KERN_WRITE32, io_buf, 2 * sizeof(uint32_t), 0, 0); +} + +int IOSUHAX_kern_read32(uint32_t address, uint32_t* out_buffer, uint32_t count) +{ + if(iosuhaxHandle < 0) + return iosuhaxHandle; + + ALIGN(0x20) uint32_t io_buf[0x20 >> 2]; + io_buf[0] = address; + + void* tmp_buf = NULL; + + if(((uintptr_t)out_buffer & 0x1F) || ((count * 4) & 0x1F)) + { + tmp_buf = (uint32_t*)memalign(0x20, ROUNDUP((count * 4), 0x20)); + if(!tmp_buf) + return -2; + } + + int res = IOS_Ioctl(iosuhaxHandle, IOCTL_KERN_READ32, io_buf, sizeof(address), tmp_buf ? tmp_buf : out_buffer, count * 4); + + if(res >= 0 && tmp_buf) + memcpy(out_buffer, tmp_buf, count * 4); + + free(tmp_buf); + return res; +} + +int IOSUHAX_SVC(uint32_t svc_id, uint32_t * args, uint32_t arg_cnt) +{ + if(iosuhaxHandle < 0) + return iosuhaxHandle; + + ALIGN(0x20) uint32_t arguments[0x40 >> 2]; + arguments[0] = svc_id; + + if(args && arg_cnt) + { + if(arg_cnt > 8) + arg_cnt = 8; + + memcpy(arguments + 1, args, arg_cnt * 4); + } + + ALIGN(0x20) int result[0x20 >> 2]; + int ret = IOS_Ioctl(iosuhaxHandle, IOCTL_SVC, arguments, (1 + arg_cnt) * 4, result, 4); + if(ret < 0) + return ret; + + return *result; +} + +int IOSUHAX_FSA_Open(void) +{ + if(iosuhaxHandle < 0) + return iosuhaxHandle; + + ALIGN(0x20) int io_buf[0x20 >> 2]; + + int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_OPEN, 0, 0, io_buf, sizeof(int)); + if(res < 0) + return res; + + return io_buf[0]; +} + +int IOSUHAX_FSA_Close(int fsaFd) +{ + if(iosuhaxHandle < 0) + return iosuhaxHandle; + + ALIGN(0x20) int io_buf[0x20 >> 2]; + io_buf[0] = fsaFd; + + int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_CLOSE, io_buf, sizeof(fsaFd), io_buf, sizeof(fsaFd)); + if(res < 0) + return res; + + return io_buf[0]; +} + +int IOSUHAX_FSA_Mount(int fsaFd, const char* device_path, const char* volume_path, uint32_t flags, const char* arg_string, int arg_string_len) +{ + if(iosuhaxHandle < 0) + return iosuhaxHandle; + + const int input_cnt = 6; + + int io_buf_size = (sizeof(uint32_t) * input_cnt) + strlen(device_path) + strlen(volume_path) + arg_string_len + 3; + + ALIGN(0x20) int io_buf[ROUNDUP(io_buf_size, 0x20) >> 2]; + memset(io_buf, 0, io_buf_size); + + io_buf[0] = fsaFd; + io_buf[1] = sizeof(uint32_t) * input_cnt; + io_buf[2] = io_buf[1] + strlen(device_path) + 1; + io_buf[3] = flags; + io_buf[4] = arg_string_len ? ( io_buf[2] + strlen(volume_path) + 1) : 0; + io_buf[5] = arg_string_len; + + strcpy(((char*)io_buf) + io_buf[1], device_path); + strcpy(((char*)io_buf) + io_buf[2], volume_path); + + if(arg_string_len) + memcpy(((char*)io_buf) + io_buf[4], arg_string, arg_string_len); + + int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_MOUNT, io_buf, io_buf_size, io_buf, 4); + if(res < 0) + return res; + + return io_buf[0]; +} + +int IOSUHAX_FSA_Unmount(int fsaFd, const char* path, uint32_t flags) +{ + if(iosuhaxHandle < 0) + return iosuhaxHandle; + + const int input_cnt = 3; + + int io_buf_size = sizeof(uint32_t) * input_cnt + strlen(path) + 1; + + ALIGN(0x20) int io_buf[ROUNDUP(io_buf_size, 0x20) >> 2]; + + io_buf[0] = fsaFd; + io_buf[1] = sizeof(uint32_t) * input_cnt; + io_buf[2] = flags; + strcpy(((char*)io_buf) + io_buf[1], path); + + int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_UNMOUNT, io_buf, io_buf_size, io_buf, 4); + if(res < 0) + return res; + + return io_buf[0]; +} + +int IOSUHAX_FSA_FlushVolume(int fsaFd, const char *volume_path) +{ + if(iosuhaxHandle < 0) + return iosuhaxHandle; + + const int input_cnt = 2; + + int io_buf_size = sizeof(uint32_t) * input_cnt + strlen(volume_path) + 1; + + ALIGN(0x20) int io_buf[ROUNDUP(io_buf_size, 0x20) >> 2]; + + io_buf[0] = fsaFd; + io_buf[1] = sizeof(uint32_t) * input_cnt; + strcpy(((char*)io_buf) + io_buf[1], volume_path); + + int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_FLUSHVOLUME, io_buf, io_buf_size, io_buf, 4); + if(res < 0) + return res; + + return io_buf[0]; +} + +int IOSUHAX_FSA_GetDeviceInfo(int fsaFd, const char* device_path, int type, uint32_t* out_data) +{ + if(iosuhaxHandle < 0) + return iosuhaxHandle; + + const int input_cnt = 3; + + int io_buf_size = sizeof(uint32_t) * input_cnt + strlen(device_path) + 1; + + uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); + if(!io_buf) + return -2; + + io_buf[0] = fsaFd; + io_buf[1] = sizeof(uint32_t) * input_cnt; + io_buf[2] = type; + strcpy(((char*)io_buf) + io_buf[1], device_path); + + uint32_t out_buf[1 + 0x64 / 4]; + + int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_GETDEVICEINFO, io_buf, io_buf_size, out_buf, sizeof(out_buf)); + if(res < 0) + { + free(io_buf); + return res; + } + + memcpy(out_data, out_buf + 1, 0x64); + free(io_buf); + return out_buf[0]; +} + +int IOSUHAX_FSA_MakeDir(int fsaFd, const char* path, uint32_t flags) +{ + if(iosuhaxHandle < 0) + return iosuhaxHandle; + + const int input_cnt = 3; + + int io_buf_size = sizeof(uint32_t) * input_cnt + strlen(path) + 1; + + uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); + if(!io_buf) + return -2; + + io_buf[0] = fsaFd; + io_buf[1] = sizeof(uint32_t) * input_cnt; + io_buf[2] = flags; + strcpy(((char*)io_buf) + io_buf[1], path); + + int result; + int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_MAKEDIR, io_buf, io_buf_size, &result, sizeof(result)); + if(res < 0) + { + free(io_buf); + return res; + } + + free(io_buf); + return result; +} + +int IOSUHAX_FSA_OpenDir(int fsaFd, const char* path, int* outHandle) +{ + if(iosuhaxHandle < 0) + return iosuhaxHandle; + + const int input_cnt = 2; + + int io_buf_size = sizeof(uint32_t) * input_cnt + strlen(path) + 1; + + uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); + if(!io_buf) + return -2; + + io_buf[0] = fsaFd; + io_buf[1] = sizeof(uint32_t) * input_cnt; + strcpy(((char*)io_buf) + io_buf[1], path); + + int result_vec[2]; + + int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_OPENDIR, io_buf, io_buf_size, result_vec, sizeof(result_vec)); + if(res < 0) + { + free(io_buf); + return res; + } + + *outHandle = result_vec[1]; + free(io_buf); + return result_vec[0]; +} + +int IOSUHAX_FSA_ReadDir(int fsaFd, int handle, directoryEntry_s* out_data) +{ + if(iosuhaxHandle < 0) + return iosuhaxHandle; + + const int input_cnt = 2; + + int io_buf_size = sizeof(uint32_t) * input_cnt; + + uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); + if(!io_buf) + return -2; + + io_buf[0] = fsaFd; + io_buf[1] = handle; + + int result_vec_size = 4 + sizeof(directoryEntry_s); + uint8_t *result_vec = (uint8_t*) memalign(0x20, result_vec_size); + if(!result_vec) + { + free(io_buf); + return -2; + } + + int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_READDIR, io_buf, io_buf_size, result_vec, result_vec_size); + if(res < 0) + { + free(result_vec); + free(io_buf); + return res; + } + + int result = *(int*)result_vec; + memcpy(out_data, result_vec + 4, sizeof(directoryEntry_s)); + free(io_buf); + free(result_vec); + return result; +} + +int IOSUHAX_FSA_RewindDir(int fsaFd, int dirHandle) +{ + if(iosuhaxHandle < 0) + return iosuhaxHandle; + + const int input_cnt = 2; + + int io_buf_size = sizeof(uint32_t) * input_cnt; + + uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); + if(!io_buf) + return -2; + + io_buf[0] = fsaFd; + io_buf[1] = dirHandle; + + int result; + + int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_REWINDDIR, io_buf, io_buf_size, &result, sizeof(result)); + if(res < 0) + { + free(io_buf); + return res; + } + + free(io_buf); + return result; +} + +int IOSUHAX_FSA_CloseDir(int fsaFd, int handle) +{ + if(iosuhaxHandle < 0) + return iosuhaxHandle; + + const int input_cnt = 2; + + int io_buf_size = sizeof(uint32_t) * input_cnt; + + uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); + if(!io_buf) + return -2; + + io_buf[0] = fsaFd; + io_buf[1] = handle; + + int result; + + int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_CLOSEDIR, io_buf, io_buf_size, &result, sizeof(result)); + if(res < 0) + { + free(io_buf); + return res; + } + + free(io_buf); + return result; +} + +int IOSUHAX_FSA_ChangeDir(int fsaFd, const char *path) +{ + if(iosuhaxHandle < 0) + return iosuhaxHandle; + + const int input_cnt = 2; + + int io_buf_size = sizeof(uint32_t) * input_cnt + strlen(path) + 1; + + uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); + if(!io_buf) + return -2; + + io_buf[0] = fsaFd; + io_buf[1] = sizeof(uint32_t) * input_cnt; + strcpy(((char*)io_buf) + io_buf[1], path); + + int result; + + int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_CHDIR, io_buf, io_buf_size, &result, sizeof(result)); + if(res < 0) + { + free(io_buf); + return res; + } + + free(io_buf); + return result; +} + +int IOSUHAX_FSA_OpenFile(int fsaFd, const char* path, const char* mode, int* outHandle) +{ + if(iosuhaxHandle < 0) + return iosuhaxHandle; + + const int input_cnt = 3; + + int io_buf_size = sizeof(uint32_t) * input_cnt + strlen(path) + strlen(mode) + 2; + + uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); + if(!io_buf) + return -2; + + io_buf[0] = fsaFd; + io_buf[1] = sizeof(uint32_t) * input_cnt; + io_buf[2] = io_buf[1] + strlen(path) + 1; + strcpy(((char*)io_buf) + io_buf[1], path); + strcpy(((char*)io_buf) + io_buf[2], mode); + + int result_vec[2]; + + int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_OPENFILE, io_buf, io_buf_size, result_vec, sizeof(result_vec)); + if(res < 0) + { + free(io_buf); + return res; + } + + *outHandle = result_vec[1]; + free(io_buf); + return result_vec[0]; +} + +int IOSUHAX_FSA_ReadFile(int fsaFd, void* data, uint32_t size, uint32_t cnt, int fileHandle, uint32_t flags) +{ + if(iosuhaxHandle < 0) + return iosuhaxHandle; + + const int input_cnt = 5; + + int io_buf_size = sizeof(uint32_t) * input_cnt; + + uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); + if(!io_buf) + return -2; + + io_buf[0] = fsaFd; + io_buf[1] = size; + io_buf[2] = cnt; + io_buf[3] = fileHandle; + io_buf[4] = flags; + + int out_buf_size = ((size * cnt + 0x40) + 0x3F) & ~0x3F; + + uint32_t *out_buffer = (uint32_t*)memalign(0x40, out_buf_size); + if(!out_buffer) + { + free(io_buf); + return -2; + } + + int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_READFILE, io_buf, io_buf_size, out_buffer, out_buf_size); + if(res < 0) + { + free(out_buffer); + free(io_buf); + return res; + } + + //! data is put to offset 0x40 to align the buffer output + memcpy(data, ((uint8_t*)out_buffer) + 0x40, size * cnt); + + int result = out_buffer[0]; + + free(out_buffer); + free(io_buf); + return result; +} + +int IOSUHAX_FSA_WriteFile(int fsaFd, const void* data, uint32_t size, uint32_t cnt, int fileHandle, uint32_t flags) +{ + if(iosuhaxHandle < 0) + return iosuhaxHandle; + + const int input_cnt = 5; + + int io_buf_size = ((sizeof(uint32_t) * input_cnt + size * cnt + 0x40) + 0x3F) & ~0x3F; + + uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); + if(!io_buf) + return -2; + + io_buf[0] = fsaFd; + io_buf[1] = size; + io_buf[2] = cnt; + io_buf[3] = fileHandle; + io_buf[4] = flags; + + //! data is put to offset 0x40 to align the buffer input + memcpy(((uint8_t*)io_buf) + 0x40, data, size * cnt); + + int result; + int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_WRITEFILE, io_buf, io_buf_size, &result, sizeof(result)); + if(res < 0) + { + free(io_buf); + return res; + } + free(io_buf); + return result; +} + +int IOSUHAX_FSA_StatFile(int fsaFd, int fileHandle, fileStat_s* out_data) +{ + if(iosuhaxHandle < 0) + return iosuhaxHandle; + + const int input_cnt = 2; + + int io_buf_size = sizeof(uint32_t) * input_cnt; + + uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); + if(!io_buf) + return -2; + + io_buf[0] = fsaFd; + io_buf[1] = fileHandle; + + int out_buf_size = 4 + sizeof(fileStat_s); + uint32_t *out_buffer = (uint32_t*)memalign(0x20, out_buf_size); + if(!out_buffer) + { + free(io_buf); + return -2; + } + + int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_STATFILE, io_buf, io_buf_size, out_buffer, out_buf_size); + if(res < 0) + { + free(io_buf); + free(out_buffer); + return res; + } + + int result = out_buffer[0]; + memcpy(out_data, out_buffer + 1, sizeof(fileStat_s)); + + free(io_buf); + free(out_buffer); + return result; +} + +int IOSUHAX_FSA_CloseFile(int fsaFd, int fileHandle) +{ + if(iosuhaxHandle < 0) + return iosuhaxHandle; + + const int input_cnt = 2; + + int io_buf_size = sizeof(uint32_t) * input_cnt; + + uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); + if(!io_buf) + return -2; + + io_buf[0] = fsaFd; + io_buf[1] = fileHandle; + + int result; + + int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_CLOSEFILE, io_buf, io_buf_size, &result, sizeof(result)); + if(res < 0) + { + free(io_buf); + return res; + } + + free(io_buf); + return result; +} + +int IOSUHAX_FSA_SetFilePos(int fsaFd, int fileHandle, uint32_t position) +{ + if(iosuhaxHandle < 0) + return iosuhaxHandle; + + const int input_cnt = 3; + + int io_buf_size = sizeof(uint32_t) * input_cnt; + + uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); + if(!io_buf) + return -2; + + io_buf[0] = fsaFd; + io_buf[1] = fileHandle; + io_buf[2] = position; + + int result; + + int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_SETFILEPOS, io_buf, io_buf_size, &result, sizeof(result)); + if(res < 0) + { + free(io_buf); + return res; + } + + free(io_buf); + return result; +} + +int IOSUHAX_FSA_GetStat(int fsaFd, const char *path, fileStat_s* out_data) +{ + if(iosuhaxHandle < 0) + return iosuhaxHandle; + + const int input_cnt = 2; + + int io_buf_size = sizeof(uint32_t) * input_cnt + strlen(path) + 1; + + uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); + if(!io_buf) + return -2; + + io_buf[0] = fsaFd; + io_buf[1] = sizeof(uint32_t) * input_cnt; + strcpy(((char*)io_buf) + io_buf[1], path); + + int out_buf_size = 4 + sizeof(fileStat_s); + uint32_t *out_buffer = (uint32_t*)memalign(0x20, out_buf_size); + if(!out_buffer) + { + free(io_buf); + return -2; + } + + int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_GETSTAT, io_buf, io_buf_size, out_buffer, out_buf_size); + if(res < 0) + { + free(io_buf); + free(out_buffer); + return res; + } + + int result = out_buffer[0]; + memcpy(out_data, out_buffer + 1, sizeof(fileStat_s)); + + free(io_buf); + free(out_buffer); + return result; +} + +int IOSUHAX_FSA_Remove(int fsaFd, const char *path) +{ + if(iosuhaxHandle < 0) + return iosuhaxHandle; + + const int input_cnt = 2; + + int io_buf_size = sizeof(uint32_t) * input_cnt + strlen(path) + 1; + + uint32_t *io_buf = (uint32_t*)memalign(0x20, ROUNDUP(io_buf_size, 0x20)); + if(!io_buf) + return -2; + + io_buf[0] = fsaFd; + io_buf[1] = sizeof(uint32_t) * input_cnt; + strcpy(((char*)io_buf) + io_buf[1], path); + + int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_REMOVE, io_buf, io_buf_size, io_buf, 4); + if(res >= 0) + res = io_buf[0]; + + free(io_buf); + return res; +} + +int IOSUHAX_FSA_ChangeMode(int fsaFd, const char* path, int mode) +{ + if(iosuhaxHandle < 0) + return iosuhaxHandle; + + const int input_cnt = 3; + + int io_buf_size = sizeof(uint32_t) * input_cnt + strlen(path) + 1; + + ALIGN(0x20) uint32_t io_buf[ROUNDUP(io_buf_size, 0x20) >> 2]; + + io_buf[0] = fsaFd; + io_buf[1] = sizeof(uint32_t) * input_cnt; + io_buf[2] = mode; + strcpy(((char*)io_buf) + io_buf[1], path); + + int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_CHANGEMODE, io_buf, io_buf_size, io_buf, 4); + if(res < 0) + return res; + + return io_buf[0]; +} + +int IOSUHAX_FSA_RawOpen(int fsaFd, const char* device_path, int* outHandle) +{ + if(iosuhaxHandle < 0) + return iosuhaxHandle; + + const int input_cnt = 2; + + int io_buf_size = sizeof(uint32_t) * input_cnt + strlen(device_path) + 1; + + ALIGN(0x20) uint32_t io_buf[ROUNDUP(io_buf_size, 0x20) >> 2]; + + io_buf[0] = fsaFd; + io_buf[1] = sizeof(uint32_t) * input_cnt; + strcpy(((char*)io_buf) + io_buf[1], device_path); + + int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_RAW_OPEN, io_buf, io_buf_size, io_buf, 2 * sizeof(int)); + if(res < 0) + return res; + + if(outHandle) + *outHandle = io_buf[1]; + + return io_buf[0]; +} + +int IOSUHAX_FSA_RawRead(int fsaFd, void* data, uint32_t block_size, uint32_t block_cnt, uint64_t sector_offset, int device_handle) +{ + if(iosuhaxHandle < 0) + return iosuhaxHandle; + + const int input_cnt = 6; + + int io_buf_size = 0x40 + block_size * block_cnt; + uint32_t *io_buf = (uint32_t*)memalign(0x40, ROUNDUP(io_buf_size, 0x40)); + + if(!io_buf) + return -2; + + io_buf[0] = fsaFd; + io_buf[1] = block_size; + io_buf[2] = block_cnt; + io_buf[3] = (sector_offset >> 32) & 0xFFFFFFFF; + io_buf[4] = sector_offset & 0xFFFFFFFF; + io_buf[5] = device_handle; + + int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_RAW_READ, io_buf, sizeof(uint32_t) * input_cnt, io_buf, io_buf_size); + if(res >= 0) + { + //! data is put to offset 0x40 to align the buffer output + memcpy(data, ((uint8_t*)io_buf) + 0x40, block_size * block_cnt); + + res = io_buf[0]; + } + + free(io_buf); + return res; +} + +int IOSUHAX_FSA_RawWrite(int fsaFd, const void* data, uint32_t block_size, uint32_t block_cnt, uint64_t sector_offset, int device_handle) +{ + if(iosuhaxHandle < 0) + return iosuhaxHandle; + + int io_buf_size = ROUNDUP(0x40 + block_size * block_cnt, 0x40); + + uint32_t *io_buf = (uint32_t*)memalign(0x40, io_buf_size); + if(!io_buf) + return -2; + + io_buf[0] = fsaFd; + io_buf[1] = block_size; + io_buf[2] = block_cnt; + io_buf[3] = (sector_offset >> 32) & 0xFFFFFFFF; + io_buf[4] = sector_offset & 0xFFFFFFFF; + io_buf[5] = device_handle; + + //! data is put to offset 0x40 to align the buffer input + memcpy(((uint8_t*)io_buf) + 0x40, data, block_size * block_cnt); + + int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_RAW_WRITE, io_buf, io_buf_size, io_buf, 4); + if(res >= 0) + res = io_buf[0]; + + free(io_buf); + return res; +} + + +int IOSUHAX_FSA_RawClose(int fsaFd, int device_handle) +{ + if(iosuhaxHandle < 0) + return iosuhaxHandle; + + const int input_cnt = 2; + + int io_buf_size = sizeof(uint32_t) * input_cnt; + + ALIGN(0x20) uint32_t io_buf[ROUNDUP(io_buf_size, 0x20) >> 2]; + + io_buf[0] = fsaFd; + io_buf[1] = device_handle; + + int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_RAW_CLOSE, io_buf, io_buf_size, io_buf, 4); + if(res < 0) + return res; + + return io_buf[0]; +} diff --git a/deps/libiosuhax/iosuhax_devoptab.c b/deps/libiosuhax/source/iosuhax_devoptab.c similarity index 84% rename from deps/libiosuhax/iosuhax_devoptab.c rename to deps/libiosuhax/source/iosuhax_devoptab.c index 4d59d6ae73..5e945f8ad4 100644 --- a/deps/libiosuhax/iosuhax_devoptab.c +++ b/deps/libiosuhax/source/iosuhax_devoptab.c @@ -1,1134 +1,993 @@ -/*************************************************************************** - * Copyright (C) 2015 - * by Dimok - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event will the authors be held liable for any - * damages arising from the use of this software. - * - * Permission is granted to anyone to use this software for any - * purpose, including commercial applications, and to alter it and - * redistribute it freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you - * must not claim that you wrote the original software. If you use - * this software in a product, an acknowledgment in the product - * documentation would be appreciated but is not required. - * - * 2. Altered source versions must be plainly marked as such, and - * must not be misrepresented as being the original software. - * - * 3. This notice may not be removed or altered from any source - * distribution. - ***************************************************************************/ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "os_functions.h" -#include "iosuhax.h" - -typedef struct _fs_dev_private_t { - char *mount_path; - int fsaFd; - int mounted; - void *pMutex; -} fs_dev_private_t; - -typedef struct _fs_dev_file_state_t { - fs_dev_private_t *dev; - int fd; /* File descriptor */ - int flags; /* Opening flags */ - int read; /* True if allowed to read from file */ - int write; /* True if allowed to write to file */ - int append; /* True if allowed to append to file */ - uint32_t pos; /* Current position within the file (in bytes) */ - uint32_t len; /* Total length of the file (in bytes) */ - struct _fs_dev_file_state_t *prevOpenFile; /* The previous entry in a double-linked FILO list of open files */ - struct _fs_dev_file_state_t *nextOpenFile; /* The next entry in a double-linked FILO list of open files */ -} fs_dev_file_state_t; - -typedef struct _fs_dev_dir_entry_t { - fs_dev_private_t *dev; - int dirHandle; -} fs_dev_dir_entry_t; - -static fs_dev_private_t *fs_dev_get_device_data(const char *path) -{ - const devoptab_t *devoptab = NULL; - char name[128] = {0}; - int i; - - if(!path) - return NULL; - - /* Get the device name from the path */ - strncpy(name, path, 127); - strtok(name, ":/"); - - // Search the devoptab table for the specified device name - // NOTE: We do this manually due to a 'bug' in GetDeviceOpTab - // which ignores names with suffixes and causes names - // like "ntfs" and "ntfs1" to be seen as equals - for (i = 3; i < STD_MAX; i++) { - devoptab = devoptab_list[i]; - if (devoptab && devoptab->name) { - if (strcmp(name, devoptab->name) == 0) { - return (fs_dev_private_t *)devoptab->deviceData; - } - } - } - - return NULL; -} - -static char *fs_dev_real_path (const char *path, fs_dev_private_t *dev) -{ - /* Sanity check */ - if (!path || !dev) - return NULL; - - /* Move the path pointer to the start of the actual path */ - if (strchr(path, ':') != NULL) { - path = strchr(path, ':') + 1; - } - - int mount_len = strlen(dev->mount_path); - - char *new_name = (char*)malloc(mount_len + strlen(path) + 1); - if(new_name) { - strcpy(new_name, dev->mount_path); - strcpy(new_name + mount_len, path); - return new_name; - } - return new_name; -} - -static int fs_dev_open_r (struct _reent *r, void *fileStruct, const char *path, int flags, int mode) -{ - fs_dev_private_t *dev = fs_dev_get_device_data(path); - - if(!r) - return -1; - - if(!dev) { - r->_errno = ENODEV; - return -1; - } - - fs_dev_file_state_t *file = (fs_dev_file_state_t *)fileStruct; - if(!file) { - r->_errno = EINVAL; - return -1; - } - - file->dev = dev; - /* Determine which mode the file is opened for */ - file->flags = flags; - - const char *mode_str; - - if ((flags & 0x03) == O_RDONLY) { - file->read = 1; - file->write = 0; - file->append = 0; - mode_str = "r"; - } else if ((flags & 0x03) == O_WRONLY) { - file->read = 0; - file->write = 1; - file->append = (flags & O_APPEND); - mode_str = file->append ? "a" : "w"; - } else if ((flags & 0x03) == O_RDWR) { - file->read = 1; - file->write = 1; - file->append = (flags & O_APPEND); - mode_str = file->append ? "a+" : "r+"; - } else { - r->_errno = EACCES; - return -1; - } - - int fd = -1; - - OSLockMutex(dev->pMutex); - - char *real_path = fs_dev_real_path(path, dev); - if(!path) { - r->_errno = ENOMEM; - OSUnlockMutex(dev->pMutex); - return -1; - } - - int result = IOSUHAX_FSA_OpenFile(dev->fsaFd, real_path, mode_str, &fd); - - free(real_path); - - if(result == 0) - { - fileStat_s stats; - result = IOSUHAX_FSA_StatFile(dev->fsaFd, fd, &stats); - if(result != 0) { - IOSUHAX_FSA_CloseFile(dev->fsaFd, fd); - r->_errno = result; - OSUnlockMutex(dev->pMutex); - return -1; - } - file->fd = fd; - file->pos = 0; - file->len = stats.size; - OSUnlockMutex(dev->pMutex); - return (int)file; - } - - r->_errno = result; - OSUnlockMutex(dev->pMutex); - return -1; -} - -static int fs_dev_close_r (struct _reent *r, void *fd) -{ - fs_dev_file_state_t *file = (fs_dev_file_state_t *)fd; - - if(!r) - return -1; - - if(!file) { - r->_errno = EINVAL; - return -1; - } - - if(!file->dev) { - r->_errno = ENODEV; - return -1; - } - - OSLockMutex(file->dev->pMutex); - - int result = IOSUHAX_FSA_CloseFile(file->dev->fsaFd, file->fd); - - OSUnlockMutex(file->dev->pMutex); - - if(result < 0) - { - r->_errno = result; - return -1; - } - return 0; -} - -static off_t fs_dev_seek_r (struct _reent *r, void* fd, off_t pos, int dir) -{ - fs_dev_file_state_t *file = (fs_dev_file_state_t *)fd; - - if(!r) - return 0; - - if(!file) { - r->_errno = EINVAL; - return 0; - } - - if(!file->dev) { - r->_errno = ENODEV; - return 0; - } - - OSLockMutex(file->dev->pMutex); - - switch(dir) - { - case SEEK_SET: - file->pos = pos; - break; - case SEEK_CUR: - file->pos += pos; - break; - case SEEK_END: - file->pos = file->len + pos; - break; - default: - r->_errno = EINVAL; - return -1; - } - - int result = IOSUHAX_FSA_SetFilePos(file->dev->fsaFd, file->fd, file->pos); - - OSUnlockMutex(file->dev->pMutex); - - if(result == 0) - { - return file->pos; - } - - return result; -} - -static ssize_t fs_dev_write_r (struct _reent *r, void *fd, const char *ptr, size_t len) -{ - fs_dev_file_state_t *file = (fs_dev_file_state_t *)fd; - - if(!r) - return 0; - - if(!file) { - r->_errno = EINVAL; - return 0; - } - - if(!file->dev) { - r->_errno = ENODEV; - return 0; - } - - if(!file->write) - { - r->_errno = EACCES; - return 0; - } - - OSLockMutex(file->dev->pMutex); - - size_t done = 0; - - while(done < len) - { - size_t write_size = len - done; - - int result = IOSUHAX_FSA_WriteFile(file->dev->fsaFd, ptr + done, 0x01, write_size, file->fd, 0); - if(result < 0) - { - r->_errno = result; - break; - } - else if(result == 0) - { - if(write_size > 0) - done = 0; - break; - } - else - { - done += result; - file->pos += result; - } - } - - OSUnlockMutex(file->dev->pMutex); - return done; -} - -static ssize_t fs_dev_read_r (struct _reent *r, void *fd, char *ptr, size_t len) -{ - if(!r) - return 0; - - fs_dev_file_state_t *file = (fs_dev_file_state_t *)fd; - - if(!file) { - r->_errno = EINVAL; - return 0; - } - - if(!file->dev) { - r->_errno = ENODEV; - return 0; - } - - if(!file->read) - { - r->_errno = EACCES; - return 0; - } - - OSLockMutex(file->dev->pMutex); - - size_t done = 0; - - while(done < len) - { - size_t read_size = len - done; - - int result = IOSUHAX_FSA_ReadFile(file->dev->fsaFd, ptr + done, 0x01, read_size, file->fd, 0); - if(result < 0) - { - r->_errno = result; - done = 0; - break; - } - else if(result == 0) - { - /*! TODO: error on read_size > 0 */ - break; - } - else - { - done += result; - file->pos += result; - } - } - - OSUnlockMutex(file->dev->pMutex); - return done; -} - - -static int fs_dev_fstat_r (struct _reent *r, void *fd, struct stat *st) -{ - fs_dev_file_state_t *file = (fs_dev_file_state_t *)fd; - - if(!r) - return -1; - - if(!file) { - r->_errno = EINVAL; - return -1; - } - - if(!file->dev) { - r->_errno = ENODEV; - return -1; - } - - OSLockMutex(file->dev->pMutex); - - /* Zero out the stat buffer */ - memset(st, 0, sizeof(struct stat)); - - fileStat_s stats; - int result = IOSUHAX_FSA_StatFile(file->dev->fsaFd, (int)fd, &stats); - if(result != 0) { - r->_errno = result; - OSUnlockMutex(file->dev->pMutex); - return -1; - } - - st->st_mode = S_IFREG; - st->st_size = stats.size; - st->st_blocks = (stats.size + 511) >> 9; - st->st_nlink = 1; - - /* Fill in the generic entry stats */ - st->st_dev = stats.id; - st->st_uid = stats.owner_id; - st->st_gid = stats.group_id; - st->st_ino = stats.id; - st->st_atime = stats.mtime; - st->st_ctime = stats.ctime; - st->st_mtime = stats.mtime; - OSUnlockMutex(file->dev->pMutex); - return 0; -} - -static int fs_dev_ftruncate_r (struct _reent *r, void *fd, off_t len) -{ - fs_dev_file_state_t *file = (fs_dev_file_state_t *)fd; - - if(!r) - return -1; - - if(!file) { - r->_errno = EINVAL; - return -1; - } - - if(!file->dev) { - r->_errno = ENODEV; - return -1; - } - - r->_errno = ENOTSUP; - /* TODO */ - return -1; -} - -static int fs_dev_fsync_r (struct _reent *r, void *fd) -{ - fs_dev_file_state_t *file = (fs_dev_file_state_t *)fd; - - if(!r) - return -1; - - if(!file) { - r->_errno = EINVAL; - return -1; - } - - if(!file->dev) { - r->_errno = ENODEV; - return -1; - } - - r->_errno = ENOTSUP; - /* TODO */ - return -1; -} - -static int fs_dev_stat_r (struct _reent *r, const char *path, struct stat *st) -{ - fs_dev_private_t *dev = fs_dev_get_device_data(path); - - if(!r) - return -1; - - if(!dev) { - r->_errno = ENODEV; - return -1; - } - - OSLockMutex(dev->pMutex); - - // Zero out the stat buffer - memset(st, 0, sizeof(struct stat)); - - char *real_path = fs_dev_real_path(path, dev); - if(!real_path) { - r->_errno = ENOMEM; - OSUnlockMutex(dev->pMutex); - return -1; - } - - fileStat_s stats; - - int result = IOSUHAX_FSA_GetStat(dev->fsaFd, real_path, &stats); - - free(real_path); - - if(result < 0) { - r->_errno = result; - OSUnlockMutex(dev->pMutex); - return -1; - } - - // mark root also as directory - st->st_mode = ((stats.flag & 0x80000000) || (strlen(dev->mount_path) + 1 == strlen(real_path)))? S_IFDIR : S_IFREG; - st->st_nlink = 1; - st->st_size = stats.size; - st->st_blocks = (stats.size + 511) >> 9; - // Fill in the generic entry stats - st->st_dev = stats.id; - st->st_uid = stats.owner_id; - st->st_gid = stats.group_id; - st->st_ino = stats.id; - st->st_atime = stats.mtime; - st->st_ctime = stats.ctime; - st->st_mtime = stats.mtime; - - OSUnlockMutex(dev->pMutex); - - return 0; -} - -static int fs_dev_link_r (struct _reent *r, const char *existing, const char *newLink) -{ - if(!r) - return -1; - - r->_errno = ENOTSUP; - return -1; -} - -static int fs_dev_unlink_r (struct _reent *r, const char *name) -{ - fs_dev_private_t *dev = fs_dev_get_device_data(name); - - if(!r) - return -1; - - if(!dev) { - r->_errno = ENODEV; - return -1; - } - - OSLockMutex(dev->pMutex); - - char *real_path = fs_dev_real_path(name, dev); - if(!real_path) { - r->_errno = ENOMEM; - OSUnlockMutex(dev->pMutex); - return -1; - } - - int result = IOSUHAX_FSA_Remove(dev->fsaFd, real_path); - - free(real_path); - - OSUnlockMutex(dev->pMutex); - - if(result < 0) { - r->_errno = result; - return -1; - } - - return result; -} - -static int fs_dev_chdir_r (struct _reent *r, const char *name) -{ - fs_dev_private_t *dev = fs_dev_get_device_data(name); - - if(!r) - return -1; - - if(!dev) { - r->_errno = ENODEV; - return -1; - } - - OSLockMutex(dev->pMutex); - - char *real_path = fs_dev_real_path(name, dev); - if(!real_path) { - r->_errno = ENOMEM; - OSUnlockMutex(dev->pMutex); - return -1; - } - - int result = IOSUHAX_FSA_ChangeDir(dev->fsaFd, real_path); - - free(real_path); - - OSUnlockMutex(dev->pMutex); - - if(result < 0) { - r->_errno = result; - return -1; - } - - return 0; -} - -static int fs_dev_rename_r (struct _reent *r, const char *oldName, const char *newName) -{ - fs_dev_private_t *dev = fs_dev_get_device_data(oldName); - - if(!r) - return -1; - - if(!dev) { - r->_errno = ENODEV; - return -1; - } - - if(!newName) { - r->_errno = EINVAL; - return -1; - } - - OSLockMutex(dev->pMutex); - - char *real_oldpath = fs_dev_real_path(oldName, dev); - if(!real_oldpath) { - r->_errno = ENOMEM; - OSUnlockMutex(dev->pMutex); - return -1; - } - char *real_newpath = fs_dev_real_path(newName, dev); - if(!real_newpath) { - r->_errno = ENOMEM; - free(real_oldpath); - OSUnlockMutex(dev->pMutex); - return -1; - } - - //! TODO - int result = -ENOTSUP; - - free(real_oldpath); - free(real_newpath); - - OSUnlockMutex(dev->pMutex); - - if(result < 0) { - r->_errno = result; - return -1; - } - - return 0; - -} - -static int fs_dev_mkdir_r (struct _reent *r, const char *path, int mode) -{ - fs_dev_private_t *dev = fs_dev_get_device_data(path); - - if(!r) - return -1; - - if(!dev) { - r->_errno = ENODEV; - return -1; - } - - OSLockMutex(dev->pMutex); - - char *real_path = fs_dev_real_path(path, dev); - if(!real_path) { - r->_errno = ENOMEM; - OSUnlockMutex(dev->pMutex); - return -1; - } - - int result = IOSUHAX_FSA_MakeDir(dev->fsaFd, real_path, mode); - - free(real_path); - - OSUnlockMutex(dev->pMutex); - - if(result < 0) { - r->_errno = result; - return -1; - } - - return 0; -} - -static int fs_dev_chmod_r (struct _reent *r, const char *path, int mode) -{ - fs_dev_private_t *dev = fs_dev_get_device_data(path); - - if(!r) - return -1; - - if(!dev) { - r->_errno = ENODEV; - return -1; - } - - OSLockMutex(dev->pMutex); - - char *real_path = fs_dev_real_path(path, dev); - if(!real_path) { - r->_errno = ENOMEM; - OSUnlockMutex(dev->pMutex); - return -1; - } - - int result = IOSUHAX_FSA_ChangeMode(dev->fsaFd, real_path, mode); - - free(real_path); - - OSUnlockMutex(dev->pMutex); - - if(result < 0) { - r->_errno = result; - return -1; - } - - return 0; -} - -static int fs_dev_statvfs_r (struct _reent *r, const char *path, struct statvfs *buf) -{ - fs_dev_private_t *dev = fs_dev_get_device_data(path); - - if(!r) - return -1; - - if(!dev) { - r->_errno = ENODEV; - return -1; - } - - if(!buf) { - r->_errno = EINVAL; - return -1; - } - - OSLockMutex(dev->pMutex); - - // Zero out the stat buffer - memset(buf, 0, sizeof(struct statvfs)); - - char *real_path = fs_dev_real_path(path, dev); - if(!real_path) { - r->_errno = ENOMEM; - OSUnlockMutex(dev->pMutex); - return -1; - } - - uint64_t size; - - int result = IOSUHAX_FSA_GetDeviceInfo(dev->fsaFd, real_path, 0x00, (uint32_t*)&size); - - free(real_path); - - if(result < 0) { - r->_errno = result; - OSUnlockMutex(dev->pMutex); - return -1; - } - - // File system block size - buf->f_bsize = 512; - - // Fundamental file system block size - buf->f_frsize = 512; - - // Total number of blocks on file system in units of f_frsize - buf->f_blocks = size >> 9; // this is unknown - - // Free blocks available for all and for non-privileged processes - buf->f_bfree = buf->f_bavail = size >> 9; - - // Number of inodes at this point in time - buf->f_files = 0xffffffff; - - // Free inodes available for all and for non-privileged processes - buf->f_ffree = 0xffffffff; - - // File system id - buf->f_fsid = (int)dev; - - // Bit mask of f_flag values. - buf->f_flag = 0; - - // Maximum length of filenames - buf->f_namemax = 255; - - OSUnlockMutex(dev->pMutex); - - return 0; -} - -static DIR_ITER *fs_dev_diropen_r (struct _reent *r, DIR_ITER *dirState, const char *path) -{ - fs_dev_private_t *dev = fs_dev_get_device_data(path); - - if(!r) - return NULL; - - if(!dev) { - r->_errno = ENODEV; - return NULL; - } - - if(!dirState) { - r->_errno = EINVAL; - return NULL; - } - - fs_dev_dir_entry_t *dirIter = (fs_dev_dir_entry_t *)dirState->dirStruct; - - OSLockMutex(dev->pMutex); - - char *real_path = fs_dev_real_path(path, dev); - if(!real_path) { - r->_errno = ENOMEM; - OSUnlockMutex(dev->pMutex); - return NULL; - } - - int dirHandle; - - int result = IOSUHAX_FSA_OpenDir(dev->fsaFd, real_path, &dirHandle); - - free(real_path); - - OSUnlockMutex(dev->pMutex); - - if(result < 0) - { - r->_errno = result; - return NULL; - } - - dirIter->dev = dev; - dirIter->dirHandle = dirHandle; - - return dirState; -} - -static int fs_dev_dirclose_r (struct _reent *r, DIR_ITER *dirState) -{ - fs_dev_dir_entry_t *dirIter; - - if(!r) - return -1; - - if(!dirState) { - r->_errno = EINVAL; - return -1; - } - - dirIter = (fs_dev_dir_entry_t *)dirState->dirStruct; - - if(!dirIter->dev) { - r->_errno = ENODEV; - return -1; - } - - OSLockMutex(dirIter->dev->pMutex); - - int result = IOSUHAX_FSA_CloseDir(dirIter->dev->fsaFd, dirIter->dirHandle); - - OSUnlockMutex(dirIter->dev->pMutex); - - if(result < 0) - { - r->_errno = result; - return -1; - } - return 0; -} - -static int fs_dev_dirreset_r (struct _reent *r, DIR_ITER *dirState) -{ - fs_dev_dir_entry_t *dirIter; - - if(!r) - return -1; - - if(!dirState) { - r->_errno = EINVAL; - return -1; - } - - dirIter = (fs_dev_dir_entry_t *)dirState->dirStruct; - - if(!dirIter->dev) { - r->_errno = ENODEV; - return -1; - } - - OSLockMutex(dirIter->dev->pMutex); - - int result = IOSUHAX_FSA_RewindDir(dirIter->dev->fsaFd, dirIter->dirHandle); - - OSUnlockMutex(dirIter->dev->pMutex); - - if(result < 0) - { - r->_errno = result; - return -1; - } - return 0; -} - -static int fs_dev_dirnext_r (struct _reent *r, DIR_ITER *dirState, char *filename, struct stat *st) -{ - fs_dev_dir_entry_t *dirIter; - - if(!r) - return -1; - - if(!dirState) { - r->_errno = EINVAL; - return -1; - } - - dirIter = (fs_dev_dir_entry_t *)dirState->dirStruct; - - if(!dirIter->dev) { - r->_errno = ENODEV; - return -1; - } - - OSLockMutex(dirIter->dev->pMutex); - - directoryEntry_s * dir_entry = malloc(sizeof(directoryEntry_s)); - - int result = IOSUHAX_FSA_ReadDir(dirIter->dev->fsaFd, dirIter->dirHandle, dir_entry); - if(result < 0) - { - free(dir_entry); - r->_errno = result; - OSUnlockMutex(dirIter->dev->pMutex); - return -1; - } - - // Fetch the current entry - strcpy(filename, dir_entry->name); - - if(st) - { - memset(st, 0, sizeof(struct stat)); - st->st_mode = (dir_entry->stat.flag & 0x80000000) ? S_IFDIR : S_IFREG; - st->st_nlink = 1; - st->st_size = dir_entry->stat.size; - st->st_blocks = (dir_entry->stat.size + 511) >> 9; - st->st_dev = dir_entry->stat.id; - st->st_uid = dir_entry->stat.owner_id; - st->st_gid = dir_entry->stat.group_id; - st->st_ino = dir_entry->stat.id; - st->st_atime = dir_entry->stat.mtime; - st->st_ctime = dir_entry->stat.ctime; - st->st_mtime = dir_entry->stat.mtime; - } - - free(dir_entry); - OSUnlockMutex(dirIter->dev->pMutex); - return 0; -} - -// NTFS device driver devoptab -static const devoptab_t devops_fs = { - NULL, /* Device name */ - sizeof (fs_dev_file_state_t), - fs_dev_open_r, - fs_dev_close_r, - fs_dev_write_r, - fs_dev_read_r, - fs_dev_seek_r, - fs_dev_fstat_r, - fs_dev_stat_r, - fs_dev_link_r, - fs_dev_unlink_r, - fs_dev_chdir_r, - fs_dev_rename_r, - fs_dev_mkdir_r, - sizeof (fs_dev_dir_entry_t), - fs_dev_diropen_r, - fs_dev_dirreset_r, - fs_dev_dirnext_r, - fs_dev_dirclose_r, - fs_dev_statvfs_r, - fs_dev_ftruncate_r, - fs_dev_fsync_r, - fs_dev_chmod_r, - NULL, /* fs_dev_fchmod_r */ - NULL /* Device data */ -}; - -static int fs_dev_add_device (const char *name, const char *mount_path, int fsaFd, int isMounted) -{ - devoptab_t *dev = NULL; - char *devname = NULL; - char *devpath = NULL; - int i; - - // Sanity check - if (!name || !mount_path) { - errno = EINVAL; - return -1; - } - - // Allocate a devoptab for this device - dev = (devoptab_t *) malloc(sizeof(devoptab_t) + strlen(name) + 1); - if (!dev) { - errno = ENOMEM; - return -1; - } - - // Use the space allocated at the end of the devoptab for storing the device name - devname = (char*)(dev + 1); - strcpy(devname, name); - - // create private data - fs_dev_private_t *priv = (fs_dev_private_t *)malloc(sizeof(fs_dev_private_t) + strlen(mount_path) + 1); - if(!priv) { - free(dev); - errno = ENOMEM; - return -1; - } - - devpath = (char*)(priv+1); - strcpy(devpath, mount_path); - - // setup private data - priv->mount_path = devpath; - priv->fsaFd = fsaFd; - priv->mounted = isMounted; - priv->pMutex = malloc(OS_MUTEX_SIZE); - - if(!priv->pMutex) { - free(dev); - free(priv); - errno = ENOMEM; - return -1; - } - - OSInitMutex(priv->pMutex); - - // Setup the devoptab - memcpy(dev, &devops_fs, sizeof(devoptab_t)); - dev->name = devname; - dev->deviceData = priv; - - // Add the device to the devoptab table (if there is a free slot) - for (i = 3; i < STD_MAX; i++) { - if (devoptab_list[i] == devoptab_list[0]) { - devoptab_list[i] = dev; - return 0; - } - } - - // failure, free all memory - free(priv); - free(dev); - - // If we reach here then there are no free slots in the devoptab table for this device - errno = EADDRNOTAVAIL; - return -1; -} - -static int fs_dev_remove_device (const char *path) -{ - const devoptab_t *devoptab = NULL; - char name[128] = {0}; - int i; - - if(!path) - return -1; - - // Get the device name from the path - strncpy(name, path, 127); - strtok(name, ":/"); - - // Find and remove the specified device from the devoptab table - // NOTE: We do this manually due to a 'bug' in RemoveDevice - // which ignores names with suffixes and causes names - // like "ntfs" and "ntfs1" to be seen as equals - for (i = 3; i < STD_MAX; i++) { - devoptab = devoptab_list[i]; - if (devoptab && devoptab->name) { - if (strcmp(name, devoptab->name) == 0) { - devoptab_list[i] = devoptab_list[0]; - - if(devoptab->deviceData) - { - fs_dev_private_t *priv = (fs_dev_private_t *)devoptab->deviceData; - - if(priv->mounted) - IOSUHAX_FSA_Unmount(priv->fsaFd, priv->mount_path, 2); - - if(priv->pMutex) - free(priv->pMutex); - free(devoptab->deviceData); - } - - free((devoptab_t*)devoptab); - return 0; - } - } - } - - return -1; -} - -int mount_fs(const char *virt_name, int fsaFd, const char *dev_path, const char *mount_path) -{ - int isMounted = 0; - - if(dev_path) - { - isMounted = 1; - - int res = IOSUHAX_FSA_Mount(fsaFd, dev_path, mount_path, 2, 0, 0); - if(res != 0) - { - return res; - } - } - - return fs_dev_add_device(virt_name, mount_path, fsaFd, isMounted); -} - -int unmount_fs(const char *virt_name) -{ - return fs_dev_remove_device(virt_name); -} +/*************************************************************************** + * Copyright (C) 2015 + * by Dimok + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any + * damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for any + * purpose, including commercial applications, and to alter it and + * redistribute it freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you + * must not claim that you wrote the original software. If you use + * this software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and + * must not be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + ***************************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "os_functions.h" +#include "iosuhax.h" + +typedef struct _fs_dev_private_t { + char *mount_path; + int fsaFd; + int mounted; + void *pMutex; +} fs_dev_private_t; + +typedef struct _fs_dev_file_state_t { + fs_dev_private_t *dev; + int fd; /* File descriptor */ + int flags; /* Opening flags */ + int read; /* True if allowed to read from file */ + int write; /* True if allowed to write to file */ + int append; /* True if allowed to append to file */ + uint32_t pos; /* Current position within the file (in bytes) */ + uint32_t len; /* Total length of the file (in bytes) */ + struct _fs_dev_file_state_t *prevOpenFile; /* The previous entry in a double-linked FILO list of open files */ + struct _fs_dev_file_state_t *nextOpenFile; /* The next entry in a double-linked FILO list of open files */ +} fs_dev_file_state_t; + +typedef struct _fs_dev_dir_entry_t { + fs_dev_private_t *dev; + int dirHandle; +} fs_dev_dir_entry_t; + +static fs_dev_private_t *fs_dev_get_device_data(const char *path) +{ + const devoptab_t *devoptab = NULL; + char name[128] = {0}; + int i; + + // Get the device name from the path + strncpy(name, path, 127); + strtok(name, ":/"); + + // Search the devoptab table for the specified device name + // NOTE: We do this manually due to a 'bug' in GetDeviceOpTab + // which ignores names with suffixes and causes names + // like "ntfs" and "ntfs1" to be seen as equals + for (i = 3; i < STD_MAX; i++) { + devoptab = devoptab_list[i]; + if (devoptab && devoptab->name) { + if (strcmp(name, devoptab->name) == 0) { + return (fs_dev_private_t *)devoptab->deviceData; + } + } + } + + return NULL; +} + +static char *fs_dev_real_path (const char *path, fs_dev_private_t *dev) +{ + // Sanity check + if (!path) + return NULL; + + // Move the path pointer to the start of the actual path + if (strchr(path, ':') != NULL) { + path = strchr(path, ':') + 1; + } + + int mount_len = strlen(dev->mount_path); + + char *new_name = (char*)malloc(mount_len + strlen(path) + 1); + if(new_name) { + strcpy(new_name, dev->mount_path); + strcpy(new_name + mount_len, path); + return new_name; + } + return new_name; +} + +static int fs_dev_open_r (struct _reent *r, void *fileStruct, const char *path, int flags, int mode) +{ + fs_dev_private_t *dev = fs_dev_get_device_data(path); + if(!dev) { + r->_errno = ENODEV; + return -1; + } + + fs_dev_file_state_t *file = (fs_dev_file_state_t *)fileStruct; + + file->dev = dev; + // Determine which mode the file is opened for + file->flags = flags; + + const char *fsMode; + + // Map flags to open modes + if (flags == 0) { + file->read = 1; + file->write = 0; + file->append = 0; + fsMode = "r"; + } else if (flags == 2) { + file->read = 1; + file->write = 1; + file->append = 0; + fsMode = "r+"; + } else if (flags == 0x601) { + file->read = 0; + file->write = 1; + file->append = 0; + fsMode = "w"; + } else if(flags == 0x602) { + file->read = 1; + file->write = 1; + file->append = 0; + fsMode = "w+"; + } else if(flags == 0x209) { + file->read = 0; + file->write = 1; + file->append = 1; + fsMode = "a"; + } else if(flags == 0x20A) { + file->read = 1; + file->write = 1; + file->append = 1; + fsMode = "a+"; + } else { + r->_errno = EINVAL; + return -1; + } + + + int fd = -1; + + OSLockMutex(dev->pMutex); + + char *real_path = fs_dev_real_path(path, dev); + if(!path) { + r->_errno = ENOMEM; + OSUnlockMutex(dev->pMutex); + return -1; + } + + int result = IOSUHAX_FSA_OpenFile(dev->fsaFd, real_path, fsMode, &fd); + + free(real_path); + + if(result == 0) + { + fileStat_s stats; + result = IOSUHAX_FSA_StatFile(dev->fsaFd, fd, &stats); + if(result != 0) { + IOSUHAX_FSA_CloseFile(dev->fsaFd, fd); + r->_errno = result; + OSUnlockMutex(dev->pMutex); + return -1; + } + file->fd = fd; + file->pos = 0; + file->len = stats.size; + OSUnlockMutex(dev->pMutex); + return (int)file; + } + + r->_errno = result; + OSUnlockMutex(dev->pMutex); + return -1; +} + + +static int fs_dev_close_r (struct _reent *r, void *fd) +{ + fs_dev_file_state_t *file = (fs_dev_file_state_t *)fd; + if(!file->dev) { + r->_errno = ENODEV; + return -1; + } + + OSLockMutex(file->dev->pMutex); + + int result = IOSUHAX_FSA_CloseFile(file->dev->fsaFd, file->fd); + + OSUnlockMutex(file->dev->pMutex); + + if(result < 0) + { + r->_errno = result; + return -1; + } + return 0; +} + +static off_t fs_dev_seek_r (struct _reent *r, void *fd, off_t pos, int dir) +{ + fs_dev_file_state_t *file = (fs_dev_file_state_t *)fd; + if(!file->dev) { + r->_errno = ENODEV; + return 0; + } + + OSLockMutex(file->dev->pMutex); + + switch(dir) + { + case SEEK_SET: + file->pos = pos; + break; + case SEEK_CUR: + file->pos += pos; + break; + case SEEK_END: + file->pos = file->len + pos; + break; + default: + r->_errno = EINVAL; + return -1; + } + + int result = IOSUHAX_FSA_SetFilePos(file->dev->fsaFd, file->fd, file->pos); + + OSUnlockMutex(file->dev->pMutex); + + if(result == 0) + { + return file->pos; + } + + return result; +} + +static ssize_t fs_dev_write_r (struct _reent *r, void *fd, const char *ptr, size_t len) +{ + fs_dev_file_state_t *file = (fs_dev_file_state_t *)fd; + if(!file->dev) { + r->_errno = ENODEV; + return 0; + } + + if(!file->write) + { + r->_errno = EACCES; + return 0; + } + + OSLockMutex(file->dev->pMutex); + + size_t done = 0; + + while(done < len) + { + size_t write_size = len - done; + + int result = IOSUHAX_FSA_WriteFile(file->dev->fsaFd, ptr + done, 0x01, write_size, file->fd, 0); + if(result < 0) + { + r->_errno = result; + break; + } + else if(result == 0) + { + if(write_size > 0) + done = 0; + break; + } + else + { + done += result; + file->pos += result; + } + } + + OSUnlockMutex(file->dev->pMutex); + return done; +} + +static ssize_t fs_dev_read_r (struct _reent *r, void *fd, char *ptr, size_t len) +{ + fs_dev_file_state_t *file = (fs_dev_file_state_t *)fd; + if(!file->dev) { + r->_errno = ENODEV; + return 0; + } + + if(!file->read) + { + r->_errno = EACCES; + return 0; + } + + OSLockMutex(file->dev->pMutex); + + size_t done = 0; + + while(done < len) + { + size_t read_size = len - done; + + int result = IOSUHAX_FSA_ReadFile(file->dev->fsaFd, ptr + done, 0x01, read_size, file->fd, 0); + if(result < 0) + { + r->_errno = result; + done = 0; + break; + } + else if(result == 0) + { + //! TODO: error on read_size > 0 + break; + } + else + { + done += result; + file->pos += result; + } + } + + OSUnlockMutex(file->dev->pMutex); + return done; +} + + +static int fs_dev_fstat_r (struct _reent *r, void *fd, struct stat *st) +{ + fs_dev_file_state_t *file = (fs_dev_file_state_t *)fd; + if(!file->dev) { + r->_errno = ENODEV; + return -1; + } + + OSLockMutex(file->dev->pMutex); + + // Zero out the stat buffer + memset(st, 0, sizeof(struct stat)); + + fileStat_s stats; + int result = IOSUHAX_FSA_StatFile(file->dev->fsaFd, (int)fd, &stats); + if(result != 0) { + r->_errno = result; + OSUnlockMutex(file->dev->pMutex); + return -1; + } + + st->st_mode = S_IFREG; + st->st_size = stats.size; + st->st_blocks = (stats.size + 511) >> 9; + st->st_nlink = 1; + + // Fill in the generic entry stats + st->st_dev = stats.id; + st->st_uid = stats.owner_id; + st->st_gid = stats.group_id; + st->st_ino = stats.id; + st->st_atime = stats.mtime; + st->st_ctime = stats.ctime; + st->st_mtime = stats.mtime; + OSUnlockMutex(file->dev->pMutex); + return 0; +} + +static int fs_dev_ftruncate_r (struct _reent *r, void *fd, off_t len) +{ + fs_dev_file_state_t *file = (fs_dev_file_state_t *)fd; + if(!file->dev) { + r->_errno = ENODEV; + return -1; + } + + r->_errno = ENOTSUP; + // TODO + return -1; +} + +static int fs_dev_fsync_r (struct _reent *r, void *fd) +{ + fs_dev_file_state_t *file = (fs_dev_file_state_t *)fd; + if(!file->dev) { + r->_errno = ENODEV; + return -1; + } + + r->_errno = ENOTSUP; + // TODO + return -1; +} + +static int fs_dev_stat_r (struct _reent *r, const char *path, struct stat *st) +{ + fs_dev_private_t *dev = fs_dev_get_device_data(path); + if(!dev) { + r->_errno = ENODEV; + return -1; + } + + OSLockMutex(dev->pMutex); + + // Zero out the stat buffer + memset(st, 0, sizeof(struct stat)); + + char *real_path = fs_dev_real_path(path, dev); + if(!real_path) { + r->_errno = ENOMEM; + OSUnlockMutex(dev->pMutex); + return -1; + } + + fileStat_s stats; + + int result = IOSUHAX_FSA_GetStat(dev->fsaFd, real_path, &stats); + + free(real_path); + + if(result < 0) { + r->_errno = result; + OSUnlockMutex(dev->pMutex); + return -1; + } + + // mark root also as directory + st->st_mode = ((stats.flag & 0x80000000) || (strlen(dev->mount_path) + 1 == strlen(real_path)))? S_IFDIR : S_IFREG; + st->st_nlink = 1; + st->st_size = stats.size; + st->st_blocks = (stats.size + 511) >> 9; + // Fill in the generic entry stats + st->st_dev = stats.id; + st->st_uid = stats.owner_id; + st->st_gid = stats.group_id; + st->st_ino = stats.id; + st->st_atime = stats.mtime; + st->st_ctime = stats.ctime; + st->st_mtime = stats.mtime; + + OSUnlockMutex(dev->pMutex); + + return 0; +} + +static int fs_dev_link_r (struct _reent *r, const char *existing, const char *newLink) +{ + r->_errno = ENOTSUP; + return -1; +} + +static int fs_dev_unlink_r (struct _reent *r, const char *name) +{ + fs_dev_private_t *dev = fs_dev_get_device_data(name); + if(!dev) { + r->_errno = ENODEV; + return -1; + } + + OSLockMutex(dev->pMutex); + + char *real_path = fs_dev_real_path(name, dev); + if(!real_path) { + r->_errno = ENOMEM; + OSUnlockMutex(dev->pMutex); + return -1; + } + + int result = IOSUHAX_FSA_Remove(dev->fsaFd, real_path); + + free(real_path); + + OSUnlockMutex(dev->pMutex); + + if(result < 0) { + r->_errno = result; + return -1; + } + + return result; +} + +static int fs_dev_chdir_r (struct _reent *r, const char *name) +{ + fs_dev_private_t *dev = fs_dev_get_device_data(name); + if(!dev) { + r->_errno = ENODEV; + return -1; + } + + OSLockMutex(dev->pMutex); + + char *real_path = fs_dev_real_path(name, dev); + if(!real_path) { + r->_errno = ENOMEM; + OSUnlockMutex(dev->pMutex); + return -1; + } + + int result = IOSUHAX_FSA_ChangeDir(dev->fsaFd, real_path); + + free(real_path); + + OSUnlockMutex(dev->pMutex); + + if(result < 0) { + r->_errno = result; + return -1; + } + + return 0; +} + +static int fs_dev_rename_r (struct _reent *r, const char *oldName, const char *newName) +{ + fs_dev_private_t *dev = fs_dev_get_device_data(oldName); + if(!dev) { + r->_errno = ENODEV; + return -1; + } + + OSLockMutex(dev->pMutex); + + char *real_oldpath = fs_dev_real_path(oldName, dev); + if(!real_oldpath) { + r->_errno = ENOMEM; + OSUnlockMutex(dev->pMutex); + return -1; + } + char *real_newpath = fs_dev_real_path(newName, dev); + if(!real_newpath) { + r->_errno = ENOMEM; + free(real_oldpath); + OSUnlockMutex(dev->pMutex); + return -1; + } + + //! TODO + int result = -ENOTSUP; + + free(real_oldpath); + free(real_newpath); + + OSUnlockMutex(dev->pMutex); + + if(result < 0) { + r->_errno = result; + return -1; + } + + return 0; + +} + +static int fs_dev_mkdir_r (struct _reent *r, const char *path, int mode) +{ + fs_dev_private_t *dev = fs_dev_get_device_data(path); + if(!dev) { + r->_errno = ENODEV; + return -1; + } + + OSLockMutex(dev->pMutex); + + char *real_path = fs_dev_real_path(path, dev); + if(!real_path) { + r->_errno = ENOMEM; + OSUnlockMutex(dev->pMutex); + return -1; + } + + int result = IOSUHAX_FSA_MakeDir(dev->fsaFd, real_path, mode); + + free(real_path); + + OSUnlockMutex(dev->pMutex); + + if(result < 0) { + r->_errno = result; + return -1; + } + + return 0; +} + +static int fs_dev_chmod_r (struct _reent *r, const char *path, int mode) +{ + fs_dev_private_t *dev = fs_dev_get_device_data(path); + if(!dev) { + r->_errno = ENODEV; + return -1; + } + + OSLockMutex(dev->pMutex); + + char *real_path = fs_dev_real_path(path, dev); + if(!real_path) { + r->_errno = ENOMEM; + OSUnlockMutex(dev->pMutex); + return -1; + } + + int result = IOSUHAX_FSA_ChangeMode(dev->fsaFd, real_path, mode); + + free(real_path); + + OSUnlockMutex(dev->pMutex); + + if(result < 0) { + r->_errno = result; + return -1; + } + + return 0; +} + +static int fs_dev_statvfs_r (struct _reent *r, const char *path, struct statvfs *buf) +{ + fs_dev_private_t *dev = fs_dev_get_device_data(path); + if(!dev) { + r->_errno = ENODEV; + return -1; + } + + OSLockMutex(dev->pMutex); + + // Zero out the stat buffer + memset(buf, 0, sizeof(struct statvfs)); + + char *real_path = fs_dev_real_path(path, dev); + if(!real_path) { + r->_errno = ENOMEM; + OSUnlockMutex(dev->pMutex); + return -1; + } + + uint64_t size; + + int result = IOSUHAX_FSA_GetDeviceInfo(dev->fsaFd, real_path, 0x00, (uint32_t*)&size); + + free(real_path); + + if(result < 0) { + r->_errno = result; + OSUnlockMutex(dev->pMutex); + return -1; + } + + // File system block size + buf->f_bsize = 512; + + // Fundamental file system block size + buf->f_frsize = 512; + + // Total number of blocks on file system in units of f_frsize + buf->f_blocks = size >> 9; // this is unknown + + // Free blocks available for all and for non-privileged processes + buf->f_bfree = buf->f_bavail = size >> 9; + + // Number of inodes at this point in time + buf->f_files = 0xffffffff; + + // Free inodes available for all and for non-privileged processes + buf->f_ffree = 0xffffffff; + + // File system id + buf->f_fsid = (int)dev; + + // Bit mask of f_flag values. + buf->f_flag = 0; + + // Maximum length of filenames + buf->f_namemax = 255; + + OSUnlockMutex(dev->pMutex); + + return 0; +} + +static DIR_ITER *fs_dev_diropen_r (struct _reent *r, DIR_ITER *dirState, const char *path) +{ + fs_dev_private_t *dev = fs_dev_get_device_data(path); + if(!dev) { + r->_errno = ENODEV; + return NULL; + } + + fs_dev_dir_entry_t *dirIter = (fs_dev_dir_entry_t *)dirState->dirStruct; + + OSLockMutex(dev->pMutex); + + char *real_path = fs_dev_real_path(path, dev); + if(!real_path) { + r->_errno = ENOMEM; + OSUnlockMutex(dev->pMutex); + return NULL; + } + + int dirHandle; + + int result = IOSUHAX_FSA_OpenDir(dev->fsaFd, real_path, &dirHandle); + + free(real_path); + + OSUnlockMutex(dev->pMutex); + + if(result < 0) + { + r->_errno = result; + return NULL; + } + + dirIter->dev = dev; + dirIter->dirHandle = dirHandle; + + return dirState; +} + +static int fs_dev_dirclose_r (struct _reent *r, DIR_ITER *dirState) +{ + fs_dev_dir_entry_t *dirIter = (fs_dev_dir_entry_t *)dirState->dirStruct; + if(!dirIter->dev) { + r->_errno = ENODEV; + return -1; + } + + OSLockMutex(dirIter->dev->pMutex); + + int result = IOSUHAX_FSA_CloseDir(dirIter->dev->fsaFd, dirIter->dirHandle); + + OSUnlockMutex(dirIter->dev->pMutex); + + if(result < 0) + { + r->_errno = result; + return -1; + } + return 0; +} + +static int fs_dev_dirreset_r (struct _reent *r, DIR_ITER *dirState) +{ + fs_dev_dir_entry_t *dirIter = (fs_dev_dir_entry_t *)dirState->dirStruct; + if(!dirIter->dev) { + r->_errno = ENODEV; + return -1; + } + + OSLockMutex(dirIter->dev->pMutex); + + int result = IOSUHAX_FSA_RewindDir(dirIter->dev->fsaFd, dirIter->dirHandle); + + OSUnlockMutex(dirIter->dev->pMutex); + + if(result < 0) + { + r->_errno = result; + return -1; + } + return 0; +} + +static int fs_dev_dirnext_r (struct _reent *r, DIR_ITER *dirState, char *filename, struct stat *st) +{ + fs_dev_dir_entry_t *dirIter = (fs_dev_dir_entry_t *)dirState->dirStruct; + if(!dirIter->dev) { + r->_errno = ENODEV; + return -1; + } + + OSLockMutex(dirIter->dev->pMutex); + + directoryEntry_s * dir_entry = malloc(sizeof(directoryEntry_s)); + + int result = IOSUHAX_FSA_ReadDir(dirIter->dev->fsaFd, dirIter->dirHandle, dir_entry); + if(result < 0) + { + free(dir_entry); + r->_errno = result; + OSUnlockMutex(dirIter->dev->pMutex); + return -1; + } + + // Fetch the current entry + strcpy(filename, dir_entry->name); + + if(st) + { + memset(st, 0, sizeof(struct stat)); + st->st_mode = (dir_entry->stat.flag & 0x80000000) ? S_IFDIR : S_IFREG; + st->st_nlink = 1; + st->st_size = dir_entry->stat.size; + st->st_blocks = (dir_entry->stat.size + 511) >> 9; + st->st_dev = dir_entry->stat.id; + st->st_uid = dir_entry->stat.owner_id; + st->st_gid = dir_entry->stat.group_id; + st->st_ino = dir_entry->stat.id; + st->st_atime = dir_entry->stat.mtime; + st->st_ctime = dir_entry->stat.ctime; + st->st_mtime = dir_entry->stat.mtime; + } + + free(dir_entry); + OSUnlockMutex(dirIter->dev->pMutex); + return 0; +} + +// NTFS device driver devoptab +static const devoptab_t devops_fs = { + NULL, /* Device name */ + sizeof (fs_dev_file_state_t), + fs_dev_open_r, + fs_dev_close_r, + fs_dev_write_r, + fs_dev_read_r, + fs_dev_seek_r, + fs_dev_fstat_r, + fs_dev_stat_r, + fs_dev_link_r, + fs_dev_unlink_r, + fs_dev_chdir_r, + fs_dev_rename_r, + fs_dev_mkdir_r, + sizeof (fs_dev_dir_entry_t), + fs_dev_diropen_r, + fs_dev_dirreset_r, + fs_dev_dirnext_r, + fs_dev_dirclose_r, + fs_dev_statvfs_r, + fs_dev_ftruncate_r, + fs_dev_fsync_r, + fs_dev_chmod_r, + NULL, /* fs_dev_fchmod_r */ + NULL /* Device data */ +}; + +static int fs_dev_add_device (const char *name, const char *mount_path, int fsaFd, int isMounted) +{ + devoptab_t *dev = NULL; + char *devname = NULL; + char *devpath = NULL; + int i; + + // Sanity check + if (!name) { + errno = EINVAL; + return -1; + } + + // Allocate a devoptab for this device + dev = (devoptab_t *) malloc(sizeof(devoptab_t) + strlen(name) + 1); + if (!dev) { + errno = ENOMEM; + return -1; + } + + // Use the space allocated at the end of the devoptab for storing the device name + devname = (char*)(dev + 1); + strcpy(devname, name); + + // create private data + fs_dev_private_t *priv = (fs_dev_private_t *)malloc(sizeof(fs_dev_private_t) + strlen(mount_path) + 1); + if(!priv) { + free(dev); + errno = ENOMEM; + return -1; + } + + devpath = (char*)(priv+1); + strcpy(devpath, mount_path); + + // setup private data + priv->mount_path = devpath; + priv->fsaFd = fsaFd; + priv->mounted = isMounted; + priv->pMutex = malloc(OS_MUTEX_SIZE); + + if(!priv->pMutex) { + free(dev); + free(priv); + errno = ENOMEM; + return -1; + } + + OSInitMutex(priv->pMutex); + + // Setup the devoptab + memcpy(dev, &devops_fs, sizeof(devoptab_t)); + dev->name = devname; + dev->deviceData = priv; + + // Add the device to the devoptab table (if there is a free slot) + for (i = 3; i < STD_MAX; i++) { + if (devoptab_list[i] == devoptab_list[0]) { + devoptab_list[i] = dev; + return 0; + } + } + + // failure, free all memory + free(priv); + free(dev); + + // If we reach here then there are no free slots in the devoptab table for this device + errno = EADDRNOTAVAIL; + return -1; +} + +static int fs_dev_remove_device (const char *path) +{ + const devoptab_t *devoptab = NULL; + char name[128] = {0}; + int i; + + // Get the device name from the path + strncpy(name, path, 127); + strtok(name, ":/"); + + // Find and remove the specified device from the devoptab table + // NOTE: We do this manually due to a 'bug' in RemoveDevice + // which ignores names with suffixes and causes names + // like "ntfs" and "ntfs1" to be seen as equals + for (i = 3; i < STD_MAX; i++) { + devoptab = devoptab_list[i]; + if (devoptab && devoptab->name) { + if (strcmp(name, devoptab->name) == 0) { + devoptab_list[i] = devoptab_list[0]; + + if(devoptab->deviceData) + { + fs_dev_private_t *priv = (fs_dev_private_t *)devoptab->deviceData; + + if(priv->mounted) + IOSUHAX_FSA_Unmount(priv->fsaFd, priv->mount_path, 2); + + if(priv->pMutex) + free(priv->pMutex); + free(devoptab->deviceData); + } + + free((devoptab_t*)devoptab); + return 0; + } + } + } + + return -1; +} + +int mount_fs(const char *virt_name, int fsaFd, const char *dev_path, const char *mount_path) +{ + int isMounted = 0; + + if(dev_path) + { + isMounted = 1; + + int res = IOSUHAX_FSA_Mount(fsaFd, dev_path, mount_path, 2, 0, 0); + if(res != 0) + { + return res; + } + } + + return fs_dev_add_device(virt_name, mount_path, fsaFd, isMounted); +} + +int unmount_fs(const char *virt_name) +{ + return fs_dev_remove_device(virt_name); +} diff --git a/deps/libiosuhax/iosuhax_disc_interface.c b/deps/libiosuhax/source/iosuhax_disc_interface.c similarity index 92% rename from deps/libiosuhax/iosuhax_disc_interface.c rename to deps/libiosuhax/source/iosuhax_disc_interface.c index dd1291ec27..1160fc1924 100644 --- a/deps/libiosuhax/iosuhax_disc_interface.c +++ b/deps/libiosuhax/source/iosuhax_disc_interface.c @@ -1,262 +1,262 @@ -/*************************************************************************** - * Copyright (C) 2016 - * by Dimok - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event will the authors be held liable for any - * damages arising from the use of this software. - * - * Permission is granted to anyone to use this software for any - * purpose, including commercial applications, and to alter it and - * redistribute it freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you - * must not claim that you wrote the original software. If you use - * this software in a product, an acknowledgment in the product - * documentation would be appreciated but is not required. - * - * 2. Altered source versions must be plainly marked as such, and - * must not be misrepresented as being the original software. - * - * 3. This notice may not be removed or altered from any source - * distribution. - ***************************************************************************/ -#include -#include -#include "iosuhax.h" -#include "iosuhax_disc_interface.h" - -#define FSA_REF_SD 0x01 -#define FSA_REF_USB 0x02 - -static int initialized = 0; - -static int fsaFdSd = 0; -static int fsaFdUsb = 0; -static int sdioFd = 0; -static int usbFd = 0; - -static void IOSUHAX_disc_io_initialize(void) -{ - if(initialized == 0) - { - initialized = 1; - fsaFdSd = -1; - fsaFdUsb = -1; - sdioFd = -1; - usbFd = -1; - } -} - -static bool IOSUHAX_disc_io_fsa_open(int fsaFd) -{ - IOSUHAX_disc_io_initialize(); - - if(IOSUHAX_Open(NULL) < 0) - return false; - - if(fsaFd == FSA_REF_SD) - { - if(fsaFdSd < 0) - { - fsaFdSd = IOSUHAX_FSA_Open(); - } - - if(fsaFdSd >= 0) - return true; - } - else if(fsaFd == FSA_REF_USB) - { - if(fsaFdUsb < 0) - { - fsaFdUsb = IOSUHAX_FSA_Open(); - } - - if(fsaFdUsb >= 0) - return true; - } - - return false; -} - -static void IOSUHAX_disc_io_fsa_close(int fsaFd) -{ - if(fsaFd == FSA_REF_SD) - { - if(fsaFdSd >= 0) - { - IOSUHAX_FSA_Close(fsaFdSd); - fsaFdSd = -1; - } - } - else if(fsaFd == FSA_REF_USB) - { - if(fsaFdUsb >= 0) - { - IOSUHAX_FSA_Close(fsaFdUsb); - fsaFdUsb = -1; - } - } -} - -static bool IOSUHAX_sdio_startup(void) -{ - if(!IOSUHAX_disc_io_fsa_open(FSA_REF_SD)) - return false; - - if(sdioFd < 0) - { - int res = IOSUHAX_FSA_RawOpen(fsaFdSd, "/dev/sdcard01", &sdioFd); - if(res < 0) - { - IOSUHAX_disc_io_fsa_close(FSA_REF_SD); - sdioFd = -1; - } - } - - return (sdioFd >= 0); -} - -static bool IOSUHAX_sdio_isInserted(void) -{ - //! TODO: check for SD card inserted with IOSUHAX_FSA_GetDeviceInfo() - return initialized && (fsaFdSd >= 0) && (sdioFd >= 0); -} - -static bool IOSUHAX_sdio_clearStatus(void) -{ - return true; -} - -static bool IOSUHAX_sdio_shutdown(void) -{ - if(!IOSUHAX_sdio_isInserted()) - return false; - - IOSUHAX_FSA_RawClose(fsaFdSd, sdioFd); - IOSUHAX_disc_io_fsa_close(FSA_REF_SD); - sdioFd = -1; - return true; -} - -static bool IOSUHAX_sdio_readSectors(uint32_t sector, uint32_t numSectors, void* buffer) -{ - if(!IOSUHAX_sdio_isInserted() || !buffer) - return false; - - int res = IOSUHAX_FSA_RawRead(fsaFdSd, buffer, 512, numSectors, sector, sdioFd); - if(res < 0) - { - return false; - } - - return true; -} - -static bool IOSUHAX_sdio_writeSectors(uint32_t sector, uint32_t numSectors, const void* buffer) -{ - if(!IOSUHAX_sdio_isInserted() || !buffer) - return false; - - int res = IOSUHAX_FSA_RawWrite(fsaFdSd, buffer, 512, numSectors, sector, sdioFd); - if(res < 0) - { - return false; - } - - return true; -} - -const DISC_INTERFACE IOSUHAX_sdio_disc_interface = -{ - DEVICE_TYPE_WII_U_SD, - FEATURE_MEDIUM_CANREAD | FEATURE_MEDIUM_CANWRITE | FEATURE_WII_U_SD, - IOSUHAX_sdio_startup, - IOSUHAX_sdio_isInserted, - IOSUHAX_sdio_readSectors, - IOSUHAX_sdio_writeSectors, - IOSUHAX_sdio_clearStatus, - IOSUHAX_sdio_shutdown -}; - -static bool IOSUHAX_usb_startup(void) -{ - if(!IOSUHAX_disc_io_fsa_open(FSA_REF_USB)) - return false; - - if(usbFd < 0) - { - int res = IOSUHAX_FSA_RawOpen(fsaFdUsb, "/dev/usb01", &usbFd); - if(res < 0) - { - res = IOSUHAX_FSA_RawOpen(fsaFdUsb, "/dev/usb02", &usbFd); - if(res < 0) - { - IOSUHAX_disc_io_fsa_close(FSA_REF_USB); - usbFd = -1; - } - } - } - return (usbFd >= 0); -} - -static bool IOSUHAX_usb_isInserted(void) -{ - return initialized && (fsaFdUsb >= 0) && (usbFd >= 0); -} - -static bool IOSUHAX_usb_clearStatus(void) -{ - return true; -} - -static bool IOSUHAX_usb_shutdown(void) -{ - if(!IOSUHAX_usb_isInserted()) - return false; - - IOSUHAX_FSA_RawClose(fsaFdUsb, usbFd); - IOSUHAX_disc_io_fsa_close(FSA_REF_USB); - usbFd = -1; - return true; -} - -static bool IOSUHAX_usb_readSectors(uint32_t sector, uint32_t numSectors, void* buffer) -{ - if(!IOSUHAX_usb_isInserted() || !buffer) - return false; - - int res = IOSUHAX_FSA_RawRead(fsaFdUsb, buffer, 512, numSectors, sector, usbFd); - if(res < 0) - { - return false; - } - - return true; -} - -static bool IOSUHAX_usb_writeSectors(uint32_t sector, uint32_t numSectors, const void* buffer) -{ - if(!IOSUHAX_usb_isInserted() || !buffer) - return false; - - int res = IOSUHAX_FSA_RawWrite(fsaFdUsb, buffer, 512, numSectors, sector, usbFd); - if(res < 0) - { - return false; - } - - return true; -} - -const DISC_INTERFACE IOSUHAX_usb_disc_interface = -{ - DEVICE_TYPE_WII_U_USB, - FEATURE_MEDIUM_CANREAD | FEATURE_MEDIUM_CANWRITE | FEATURE_WII_U_USB, - IOSUHAX_usb_startup, - IOSUHAX_usb_isInserted, - IOSUHAX_usb_readSectors, - IOSUHAX_usb_writeSectors, - IOSUHAX_usb_clearStatus, - IOSUHAX_usb_shutdown -}; +/*************************************************************************** + * Copyright (C) 2016 + * by Dimok + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any + * damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for any + * purpose, including commercial applications, and to alter it and + * redistribute it freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you + * must not claim that you wrote the original software. If you use + * this software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and + * must not be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + ***************************************************************************/ +#include +#include +#include "iosuhax.h" +#include "iosuhax_disc_interface.h" + +#define FSA_REF_SD 0x01 +#define FSA_REF_USB 0x02 + +static int initialized = 0; + +static int fsaFdSd = 0; +static int fsaFdUsb = 0; +static int sdioFd = 0; +static int usbFd = 0; + +static void IOSUHAX_disc_io_initialize(void) +{ + if(initialized == 0) + { + initialized = 1; + fsaFdSd = -1; + fsaFdUsb = -1; + sdioFd = -1; + usbFd = -1; + } +} + +static bool IOSUHAX_disc_io_fsa_open(int fsaFd) +{ + IOSUHAX_disc_io_initialize(); + + if(IOSUHAX_Open(NULL) < 0) + return false; + + if(fsaFd == FSA_REF_SD) + { + if(fsaFdSd < 0) + { + fsaFdSd = IOSUHAX_FSA_Open(); + } + + if(fsaFdSd >= 0) + return true; + } + else if(fsaFd == FSA_REF_USB) + { + if(fsaFdUsb < 0) + { + fsaFdUsb = IOSUHAX_FSA_Open(); + } + + if(fsaFdUsb >= 0) + return true; + } + + return false; +} + +static void IOSUHAX_disc_io_fsa_close(int fsaFd) +{ + if(fsaFd == FSA_REF_SD) + { + if(fsaFdSd >= 0) + { + IOSUHAX_FSA_Close(fsaFdSd); + fsaFdSd = -1; + } + } + else if(fsaFd == FSA_REF_USB) + { + if(fsaFdUsb >= 0) + { + IOSUHAX_FSA_Close(fsaFdUsb); + fsaFdUsb = -1; + } + } +} + +static bool IOSUHAX_sdio_startup(void) +{ + if(!IOSUHAX_disc_io_fsa_open(FSA_REF_SD)) + return false; + + if(sdioFd < 0) + { + int res = IOSUHAX_FSA_RawOpen(fsaFdSd, "/dev/sdcard01", &sdioFd); + if(res < 0) + { + IOSUHAX_disc_io_fsa_close(FSA_REF_SD); + sdioFd = -1; + } + } + + return (sdioFd >= 0); +} + +static bool IOSUHAX_sdio_isInserted(void) +{ + //! TODO: check for SD card inserted with IOSUHAX_FSA_GetDeviceInfo() + return initialized && (fsaFdSd >= 0) && (sdioFd >= 0); +} + +static bool IOSUHAX_sdio_clearStatus(void) +{ + return true; +} + +static bool IOSUHAX_sdio_shutdown(void) +{ + if(!IOSUHAX_sdio_isInserted()) + return false; + + IOSUHAX_FSA_RawClose(fsaFdSd, sdioFd); + IOSUHAX_disc_io_fsa_close(FSA_REF_SD); + sdioFd = -1; + return true; +} + +static bool IOSUHAX_sdio_readSectors(uint32_t sector, uint32_t numSectors, void* buffer) +{ + if(!IOSUHAX_sdio_isInserted()) + return false; + + int res = IOSUHAX_FSA_RawRead(fsaFdSd, buffer, 512, numSectors, sector, sdioFd); + if(res < 0) + { + return false; + } + + return true; +} + +static bool IOSUHAX_sdio_writeSectors(uint32_t sector, uint32_t numSectors, const void* buffer) +{ + if(!IOSUHAX_sdio_isInserted()) + return false; + + int res = IOSUHAX_FSA_RawWrite(fsaFdSd, buffer, 512, numSectors, sector, sdioFd); + if(res < 0) + { + return false; + } + + return true; +} + +const DISC_INTERFACE IOSUHAX_sdio_disc_interface = +{ + DEVICE_TYPE_WII_U_SD, + FEATURE_MEDIUM_CANREAD | FEATURE_MEDIUM_CANWRITE | FEATURE_WII_U_SD, + IOSUHAX_sdio_startup, + IOSUHAX_sdio_isInserted, + IOSUHAX_sdio_readSectors, + IOSUHAX_sdio_writeSectors, + IOSUHAX_sdio_clearStatus, + IOSUHAX_sdio_shutdown +}; + +static bool IOSUHAX_usb_startup(void) +{ + if(!IOSUHAX_disc_io_fsa_open(FSA_REF_USB)) + return false; + + if(usbFd < 0) + { + int res = IOSUHAX_FSA_RawOpen(fsaFdUsb, "/dev/usb01", &usbFd); + if(res < 0) + { + res = IOSUHAX_FSA_RawOpen(fsaFdUsb, "/dev/usb02", &usbFd); + if(res < 0) + { + IOSUHAX_disc_io_fsa_close(FSA_REF_USB); + usbFd = -1; + } + } + } + return (usbFd >= 0); +} + +static bool IOSUHAX_usb_isInserted(void) +{ + return initialized && (fsaFdUsb >= 0) && (usbFd >= 0); +} + +static bool IOSUHAX_usb_clearStatus(void) +{ + return true; +} + +static bool IOSUHAX_usb_shutdown(void) +{ + if(!IOSUHAX_usb_isInserted()) + return false; + + IOSUHAX_FSA_RawClose(fsaFdUsb, usbFd); + IOSUHAX_disc_io_fsa_close(FSA_REF_USB); + usbFd = -1; + return true; +} + +static bool IOSUHAX_usb_readSectors(uint32_t sector, uint32_t numSectors, void* buffer) +{ + if(!IOSUHAX_usb_isInserted()) + return false; + + int res = IOSUHAX_FSA_RawRead(fsaFdUsb, buffer, 512, numSectors, sector, usbFd); + if(res < 0) + { + return false; + } + + return true; +} + +static bool IOSUHAX_usb_writeSectors(uint32_t sector, uint32_t numSectors, const void* buffer) +{ + if(!IOSUHAX_usb_isInserted()) + return false; + + int res = IOSUHAX_FSA_RawWrite(fsaFdUsb, buffer, 512, numSectors, sector, usbFd); + if(res < 0) + { + return false; + } + + return true; +} + +const DISC_INTERFACE IOSUHAX_usb_disc_interface = +{ + DEVICE_TYPE_WII_U_USB, + FEATURE_MEDIUM_CANREAD | FEATURE_MEDIUM_CANWRITE | FEATURE_WII_U_USB, + IOSUHAX_usb_startup, + IOSUHAX_usb_isInserted, + IOSUHAX_usb_readSectors, + IOSUHAX_usb_writeSectors, + IOSUHAX_usb_clearStatus, + IOSUHAX_usb_shutdown +}; diff --git a/deps/libiosuhax/source/os_functions.h b/deps/libiosuhax/source/os_functions.h new file mode 100644 index 0000000000..a9d9d00317 --- /dev/null +++ b/deps/libiosuhax/source/os_functions.h @@ -0,0 +1,28 @@ +#ifndef __OS_FUNCTIONS_H_ +#define __OS_FUNCTIONS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#define OS_MUTEX_SIZE 44 + +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +//! Mutex functions +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +extern void OSInitMutex(void* mutex); +extern void OSLockMutex(void* mutex); +extern void OSUnlockMutex(void* mutex); + +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +//! IOS function +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +extern int IOS_Ioctl(int fd, unsigned int request, void *input_buffer,unsigned int input_buffer_len, void *output_buffer, unsigned int output_buffer_len); +extern int IOS_Open(char *path, unsigned int mode); +extern int IOS_Close(int fd); + +#ifdef __cplusplus +} +#endif + +#endif // __OS_FUNCTIONS_H_ diff --git a/griffin/griffin.c b/griffin/griffin.c index a187296e3b..0b880cba5c 100644 --- a/griffin/griffin.c +++ b/griffin/griffin.c @@ -1515,9 +1515,9 @@ DEPENDENCIES #endif #ifdef WANT_IOSUHAX -#include "../deps/libiosuhax/iosuhax.c" -#include "../deps/libiosuhax/iosuhax_devoptab.c" -#include "../deps/libiosuhax/iosuhax_disc_interface.c" +#include "../deps/libiosuhax/source/iosuhax.c" +#include "../deps/libiosuhax/source/iosuhax_devoptab.c" +#include "../deps/libiosuhax/source/iosuhax_disc_interface.c" #endif /*============================================================