/* based on blsug.h * by Alex Chadwick * * Copyright (C) 2014, Alex Chadwick * Modified by Maschell, 2018 * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #ifndef WUPS_H_ #define WUPS_H_ #include #include #include #include #include #include #include #ifdef __cplusplus extern "C" { #endif #define WUPS_SECTION(x) __attribute__((__section__ (".wups." x))) #define DECL_FUNCTION(res, name, ...) \ res (* real_ ## name)(__VA_ARGS__) __attribute__((section(".data"))); \ res my_ ## name(__VA_ARGS__) typedef enum wups_loader_library_type_t { WUPS_LOADER_LIBRARY_AVM, WUPS_LOADER_LIBRARY_CAMERA, WUPS_LOADER_LIBRARY_COREINIT, WUPS_LOADER_LIBRARY_DC, WUPS_LOADER_LIBRARY_DMAE, WUPS_LOADER_LIBRARY_DRMAPP, WUPS_LOADER_LIBRARY_ERREULA, WUPS_LOADER_LIBRARY_GX2, WUPS_LOADER_LIBRARY_H264, WUPS_LOADER_LIBRARY_LZMA920, WUPS_LOADER_LIBRARY_MIC, WUPS_LOADER_LIBRARY_NFC, WUPS_LOADER_LIBRARY_NIO_PROF, WUPS_LOADER_LIBRARY_NLIBCURL, WUPS_LOADER_LIBRARY_NLIBNSS, WUPS_LOADER_LIBRARY_NLIBNSS2, WUPS_LOADER_LIBRARY_NN_AC, WUPS_LOADER_LIBRARY_NN_ACP, WUPS_LOADER_LIBRARY_NN_ACT, WUPS_LOADER_LIBRARY_NN_AOC, WUPS_LOADER_LIBRARY_NN_BOSS, WUPS_LOADER_LIBRARY_NN_CCR, WUPS_LOADER_LIBRARY_NN_CMPT, WUPS_LOADER_LIBRARY_NN_DLP, WUPS_LOADER_LIBRARY_NN_EC, WUPS_LOADER_LIBRARY_NN_FP, WUPS_LOADER_LIBRARY_NN_HAI, WUPS_LOADER_LIBRARY_NN_HPAD, WUPS_LOADER_LIBRARY_NN_IDBE, WUPS_LOADER_LIBRARY_NN_NDM, WUPS_LOADER_LIBRARY_NN_NETS2, WUPS_LOADER_LIBRARY_NN_NFP, WUPS_LOADER_LIBRARY_NN_NIM, WUPS_LOADER_LIBRARY_NN_OLV, WUPS_LOADER_LIBRARY_NN_PDM, WUPS_LOADER_LIBRARY_NN_SAVE, WUPS_LOADER_LIBRARY_NN_SL, WUPS_LOADER_LIBRARY_NN_SPM, WUPS_LOADER_LIBRARY_NN_TEMP, WUPS_LOADER_LIBRARY_NN_UDS, WUPS_LOADER_LIBRARY_NN_VCTL, WUPS_LOADER_LIBRARY_NSYSCCR, WUPS_LOADER_LIBRARY_NSYSHID, WUPS_LOADER_LIBRARY_NSYSKBD, WUPS_LOADER_LIBRARY_NSYSNET, WUPS_LOADER_LIBRARY_NSYSUHS, WUPS_LOADER_LIBRARY_NSYSUVD, WUPS_LOADER_LIBRARY_NTAG, WUPS_LOADER_LIBRARY_PADSCORE, WUPS_LOADER_LIBRARY_PROC_UI, WUPS_LOADER_LIBRARY_SND_CORE, WUPS_LOADER_LIBRARY_SND_USER, WUPS_LOADER_LIBRARY_SNDCORE2, WUPS_LOADER_LIBRARY_SNDUSER2, WUPS_LOADER_LIBRARY_SWKBD, WUPS_LOADER_LIBRARY_SYSAPP, WUPS_LOADER_LIBRARY_TCL, WUPS_LOADER_LIBRARY_TVE, WUPS_LOADER_LIBRARY_UAC, WUPS_LOADER_LIBRARY_UAC_RPL, WUPS_LOADER_LIBRARY_USB_MIC, WUPS_LOADER_LIBRARY_UVC, WUPS_LOADER_LIBRARY_UVD, WUPS_LOADER_LIBRARY_VPAD, WUPS_LOADER_LIBRARY_VPADBASE, WUPS_LOADER_LIBRARY_ZLIB125, } wups_loader_library_type_t; typedef enum wups_loader_hook_type_t { WUPS_LOADER_HOOK_INIT_FUNCTION } wups_loader_hook_type_t; typedef struct wups_loader_hook_t { wups_loader_hook_type_t type; const void *target; /*Address of our own, new function (my_XXX)*/ } wups_loader_hook_t; #define WUPS_HOOK_INIT(original_func) \ extern const wups_loader_hook_t wups_hooks_init_ ## original_func \ WUPS_SECTION("hooks"); \ const wups_loader_hook_t wups_hooks_init_ ## original_func = { \ .type = WUPS_LOADER_HOOK_INIT_FUNCTION, \ .target = (const void*)&(original_func) \ } #define WUPS_SDUSB_MOUNTED_NONE 0 #define WUPS_SDUSB_MOUNTED_FAKE (1<<0) #define WUPS_SDUSB_MOUNTED_OS_SD (1<<1) #define WUPS_SDUSB_LIBIOSU_LOADED (1<<2) #define WUPS_SD_MOUNTED_LIBFAT (1<<3) #define WUPS_USB_MOUNTED_LIBFAT (1<<4) #define WUPS_USB_MOUNTED_LIBNTFS (1<<5) #define WUPS_SD_MOUNTED (WUPS_SDUSB_MOUNTED_OS_SD | WUPS_SD_MOUNTED_LIBFAT) #define WUPS_USB_MOUNTED (WUPS_USB_MOUNTED_LIBFAT) typedef struct wups_loader_init_args_t { int device_mounted; struct { const void * open_repl; const void * close_repl; const void * write_repl; const void * read_repl; const void * lseek_repl; const void * stat_repl; const void * fstat_repl; const void * opendir_repl; const void * closedir_repl; const void * readdir_repl; } fs_wrapper; } wups_loader_init_args_t; #ifdef __cplusplus #define EXTERN_C_START extern "C" { #define EXTERN_C_END } #else #define EXTERN_C_START #define EXTERN_C_END #endif #define INITIALIZE(my_args) \ void init(wups_loader_init_args_t*);\ void myInit(wups_loader_init_args_t*);\ WUPS_HOOK_INIT(init); \ static void * new_open_ptr __attribute__((section(".data"))) = NULL; \ static void * new_close_ptr __attribute__((section(".data"))) = NULL; \ static void * new_write_ptr __attribute__((section(".data"))) = NULL; \ static void * new_read_ptr __attribute__((section(".data"))) = NULL; \ static void * new_lseek_ptr __attribute__((section(".data"))) = NULL; \ static void * new_stat_ptr __attribute__((section(".data"))) = NULL; \ static void * new_fstat_ptr __attribute__((section(".data"))) = NULL; \ static void * new_opendir_ptr __attribute__((section(".data"))) = NULL; \ static void * new_closedir_ptr __attribute__((section(".data"))) = NULL; \ static void * new_readdir_ptr __attribute__((section(".data"))) = NULL; \ void init(wups_loader_init_args_t* args){ \ if(args != NULL){\ new_open_ptr = (void*) args->fs_wrapper.open_repl; \ new_close_ptr = (void*) args->fs_wrapper.close_repl; \ new_write_ptr = (void*) args->fs_wrapper.write_repl; \ new_read_ptr = (void*) args->fs_wrapper.read_repl; \ new_lseek_ptr = (void*) args->fs_wrapper.lseek_repl; \ new_stat_ptr = (void*) args->fs_wrapper.stat_repl; \ new_fstat_ptr = (void*) args->fs_wrapper.fstat_repl; \ new_opendir_ptr = (void*) args->fs_wrapper.opendir_repl; \ new_closedir_ptr = (void*) args->fs_wrapper.closedir_repl; \ new_readdir_ptr = (void*) args->fs_wrapper.readdir_repl; \ }\ myInit(args);\ } \ \ EXTERN_C_START \ \ int __real_open(const char *pathname, int flags);\ int __wrap_open(const char *pathname, int flags){\ if(new_open_ptr == NULL) return __real_open(pathname,flags); \ return ( (int (*)(const char *,int))((unsigned int*)new_open_ptr) )(pathname,flags);\ }\ int __real_close(int fd);\ int __wrap_close(int fd){\ if(new_close_ptr == NULL) return __real_close(fd); \ return ( (int (*)(int))((unsigned int*)new_close_ptr) )(fd);\ }\ ssize_t __real_write(int fd, const void *buf, size_t count);\ ssize_t __wrap_write(int fd, const void *buf, size_t count){\ if(new_write_ptr == NULL) return __real_write(fd,buf,count); \ return ( (ssize_t (*)(int, const void *, size_t))((unsigned int*)new_write_ptr) )(fd,buf,count);\ }\ ssize_t __real_read(int fd, const void *buf, size_t count);\ ssize_t __wrap_read(int fd, const void *buf, size_t count){\ if(new_read_ptr == NULL) return __real_read(fd,buf,count); \ return ( (ssize_t (*)(int, const void *, size_t))((unsigned int*)new_read_ptr) )(fd,buf,count);\ }\ off_t __real_lseek(int fd, off_t offset, int whence);\ off_t __wrap_lseek(int fd, off_t offset, int whence){\ if(new_lseek_ptr == NULL) return __real_lseek(fd, offset, whence); \ return ( (off_t (*)(int, off_t, int))((unsigned int*)new_lseek_ptr) )(fd, offset, whence);\ }\ int __real_stat(const char *pathname, struct stat *statbuf);\ int __wrap_stat(const char *pathname, struct stat *statbuf){\ if(new_stat_ptr == NULL) return __real_stat(pathname,statbuf); \ return ( (int (*)(const char *, struct stat *))((unsigned int*)new_stat_ptr) )(pathname,statbuf);\ }\ int __real_fstat(int fd, struct stat *statbuf);\ int __wrap_fstat(int fd, struct stat *statbuf){\ if(new_fstat_ptr == NULL) return __real_fstat(fd,statbuf); \ return ( (int (*)(int, struct stat *))((unsigned int*)new_fstat_ptr) )(fd,statbuf);\ }\ DIR* __real_opendir(const char * arg);\ DIR* __wrap_opendir(const char * arg){\ if(new_opendir_ptr == NULL) return __real_opendir(arg); \ return ( (DIR* (*)(const char *))((unsigned int*)new_opendir_ptr) )(arg);\ }\ int __real_closedir(DIR *dirp);\ int __wrap_closedir(DIR *dirp){\ if(new_closedir_ptr == NULL) return __real_closedir(dirp); \ return ( (int (*)(DIR *))((unsigned int*)new_closedir_ptr) )(dirp);\ }\ struct dirent * __real_readdir(DIR *dirp);\ struct dirent * __wrap_readdir(DIR *dirp){\ if(new_readdir_ptr == NULL) return __real_readdir(dirp); \ return ( (struct dirent * (*)(DIR *))((unsigned int*)new_readdir_ptr) )(dirp);\ }\ \ EXTERN_C_END\ void myInit(wups_loader_init_args_t* my_args) typedef enum wups_loader_entry_type_t { WUPS_LOADER_ENTRY_FUNCTION, WUPS_LOADER_ENTRY_FUNCTION_MANDATORY, WUPS_LOADER_ENTRY_EXPORT } wups_loader_entry_type_t; typedef struct wups_loader_entry_t { wups_loader_entry_type_t type; struct { const char *name; /* Name of the function that will be replaced */ const wups_loader_library_type_t library; /**/ const char *my_function_name; /* Function name of your own, new function (my_XXX) */ const void *call_addr; /* Function name of function, to call the real function.(real_XXX) */ const void *target; /*Address of our own, new function (my_XXX)*/ } _function; } wups_loader_entry_t; #define WUPS_MUST_REPLACE(x, lib, function_name) WUPS_MUST_REPLACE_EX(real_ ## x, lib, my_ ## x, function_name); #define WUPS_MUST_REPLACE_EX(original_func, rpl_type, replace_func, replace_function_name) \ extern const wups_loader_entry_t wups_load_ ## replace_func \ WUPS_SECTION("load"); \ const wups_loader_entry_t wups_load_ ## replace_func = { \ .type = WUPS_LOADER_ENTRY_FUNCTION_MANDATORY, \ ._function = { \ .name = #replace_function_name, \ .library = rpl_type, \ .my_function_name = #replace_func, \ .call_addr = (const void*)&(original_func), \ .target = (const void*)&(replace_func) \ } \ } #define WUPS_META(id, value) \ extern const char wups_meta_ ## id [] WUPS_SECTION("meta"); \ const char wups_meta_ ## id [] = #id "=" value #define WUPS_MODULE_NAME(x) WUPS_META(name, x); WUPS_META(wups, "0.1") #define WUPS_MODULE_AUTHOR(x) WUPS_META(author, x) #define WUPS_MODULE_VERSION(x) WUPS_META(version, x) #define WUPS_MODULE_LICENSE(x) WUPS_META(license, x) #ifdef __cplusplus } #endif #endif /* WUPS_WUPS_H_ */