├── .gitignore ├── .gitmodules ├── .vscode └── c_cpp_properties.json ├── LICENSE ├── Makefile ├── README.md ├── build.sh ├── inject_libnx.json ├── kip1converter.py ├── kip1patch.py └── source ├── fs_types.h ├── main.c ├── twili.c └── twili.h /.gitignore: -------------------------------------------------------------------------------- 1 | *.kip 2 | *.data 3 | *.elf 4 | build 5 | libnx-patched/*~ 6 | libnx-patched/*.o 7 | libnx-patched/*.bz2 8 | libnx-patched/*.nro 9 | libnx-patched/*.nso 10 | libnx-patched/*.elf 11 | libnx-patched/*.npdm 12 | libnx-patched/*.pfs0 13 | libnx-patched/Thumbs.db 14 | libnx-patched/.*/ 15 | libnx-patched/debug/ 16 | libnx-patched/release/ 17 | libnx-patched/lib/ 18 | libnx-patched/docs/ 19 | .vscode/ipch -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "libnx-patched"] 2 | path = libnx-patched 3 | url = https://github.com/jakibaki/libnx 4 | -------------------------------------------------------------------------------- /.vscode/c_cpp_properties.json: -------------------------------------------------------------------------------- 1 | { 2 | "configurations": [ 3 | { 4 | "name": "Linux", 5 | "includePath": [ 6 | "${workspaceFolder}/**", 7 | "/opt/devkitpro/**", 8 | "${workspaceFolder}/libnx-patched/" 9 | ], 10 | "defines": [], 11 | "compilerPath": "/usr/bin/clang", 12 | "cStandard": "c11", 13 | "cppStandard": "c++17", 14 | "intelliSenseMode": "clang-x64" 15 | } 16 | ], 17 | "version": 4 18 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | , 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .SUFFIXES: 2 | 3 | ifeq ($(strip $(DEVKITPRO)),) 4 | $(error "Please set DEVKITPRO in your environment. export DEVKITPRO=/devkitpro") 5 | endif 6 | 7 | TOPDIR ?= $(CURDIR) 8 | # thanks to layoff for the "how to" on how to include custom libnx 9 | LNXPATCHED := $(TOPDIR)/libnx-patched/nx 10 | include $(LNXPATCHED)/switch_rules 11 | 12 | TARGET := inject_libnx 13 | BUILD := build 14 | SOURCES := source 15 | DATA := data 16 | INCLUDES := include 17 | EXEFS_SRC := exefs_src 18 | 19 | ARCH := -march=armv8-a -mtune=cortex-a57 -mtp=soft -fPIE 20 | 21 | CFLAGS := -g -Wall -Wextra -O2 -ffunction-sections -fno-asynchronous-unwind-tables \ 22 | $(ARCH) $(DEFINES) 23 | 24 | CFLAGS += $(INCLUDE) -D__SWITCH__ 25 | 26 | CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11 27 | 28 | ASFLAGS := -g $(ARCH) 29 | LDFLAGS = -specs=$(LNXPATCHED)/switch.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) 30 | 31 | LIBS := -lnx 32 | 33 | LIBDIRS := $(PORTLIBS) $(LNXPATCHED) 34 | 35 | ifneq ($(BUILD),$(notdir $(CURDIR))) 36 | 37 | export OUTPUT := $(CURDIR)/$(TARGET) 38 | export TOPDIR := $(CURDIR) 39 | 40 | export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ 41 | $(foreach dir,$(DATA),$(CURDIR)/$(dir)) 42 | 43 | export DEPSDIR := $(CURDIR)/$(BUILD) 44 | 45 | CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) 46 | CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) 47 | SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) 48 | BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) 49 | 50 | ifeq ($(strip $(CPPFILES)),) 51 | export LD := $(CC) 52 | else 53 | export LD := $(CXX) 54 | endif 55 | 56 | export OFILES_BIN := $(addsuffix .o,$(BINFILES)) 57 | export OFILES_SRC := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) 58 | export OFILES := $(OFILES_BIN) $(OFILES_SRC) 59 | export HFILES_BIN := $(addsuffix .h,$(subst .,_,$(BINFILES))) 60 | 61 | export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ 62 | $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ 63 | -I$(CURDIR)/$(BUILD) 64 | 65 | export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) 66 | 67 | export BUILD_EXEFS_SRC := $(TOPDIR)/$(EXEFS_SRC) 68 | 69 | ifeq ($(strip $(CONFIG_JSON)),) 70 | jsons := $(wildcard *.json) 71 | ifneq (,$(findstring $(TARGET).json,$(jsons))) 72 | export APP_JSON := $(TOPDIR)/$(TARGET).json 73 | else 74 | ifneq (,$(findstring config.json,$(jsons))) 75 | export APP_JSON := $(TOPDIR)/config.json 76 | endif 77 | endif 78 | else 79 | export APP_JSON := $(TOPDIR)/$(CONFIG_JSON) 80 | endif 81 | 82 | .PHONY: $(BUILD) clean all 83 | 84 | all: $(BUILD) 85 | 86 | $(BUILD): 87 | @[ -d $@ ] || mkdir -p $@ 88 | @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile 89 | 90 | clean: 91 | @echo clean ... 92 | @rm -fr $(BUILD) $(TARGET).elf $(TARGET).kip 93 | 94 | else 95 | .PHONY: all 96 | 97 | DEPENDS := $(OFILES:.o=.d) 98 | 99 | all : $(OUTPUT).kip 100 | 101 | $(OUTPUT).kip : $(OUTPUT).elf 102 | 103 | $(OUTPUT).elf : $(OFILES) 104 | 105 | $(OFILES_SRC) : $(HFILES_BIN) 106 | 107 | %.bin.o %_bin.h : %.bin 108 | @echo $(notdir $<) 109 | @$(bin2o) 110 | 111 | -include $(DEPENDS) 112 | 113 | endif 114 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | This is a poc for injecting full libnx into nintendo kips. 2 | 3 | Right now this just hooks the fs-sdmmc-access-function and logs usage to a twili named-pipe. 4 | 5 | Needs fullsvcperms until I figure out how to patch the kip-perms (should be trivial) 6 | 7 | MD5 of the needed fs.kip is `bfd1c91eda3f3e17f946da6698ccd9c6` 7.0(.1) exfat decompressed. -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | 5 | make clean 6 | make 7 | hactool -t kip inject_libnx.kip --uncompressed inject_libnx_unpacked.kip 8 | python3 kip1converter.py inject_libnx_unpacked.kip out.data 9 | python3 kip1patch.py FS_6.1_exfat_uncomp.kip out.kip -------------------------------------------------------------------------------- /inject_libnx.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "fatalfs", 3 | "title_id": "0x4200000000000ABC", 4 | "main_thread_stack_size": "0x0001A0000", 5 | "main_thread_priority": 49, 6 | "default_cpu_id": 3, 7 | "process_category": 1, 8 | "kernel_capabilities": { 9 | "handle_table_size": 128, 10 | "syscalls": { 11 | "svcSetHeapSize": "0x01", 12 | "svcSetMemoryPermission": "0x02", 13 | "svcSetMemoryAttribute": "0x03", 14 | "svcMapMemory": "0x04", 15 | "svcUnmapMemory": "0x05", 16 | "svcQueryMemory": "0x06", 17 | "svcExitProcess": "0x07", 18 | "svcCreateThread": "0x08", 19 | "svcStartThread": "0x09", 20 | "svcExitThread": "0x0a", 21 | "svcSleepThread": "0x0b", 22 | "svcGetThreadPriority": "0x0c", 23 | "svcSetThreadPriority": "0x0d", 24 | "svcGetThreadCoreMask": "0x0e", 25 | "svcSetThreadCoreMask": "0x0f", 26 | "svcGetCurrentProcessorNumber": "0x10", 27 | "svcSignalEvent": "0x11", 28 | "svcClearEvent": "0x12", 29 | "svcMapSharedMemory": "0x13", 30 | "svcUnmapSharedMemory": "0x14", 31 | "svcCreateTransferMemory": "0x15", 32 | "svcCloseHandle": "0x16", 33 | "svcResetSignal": "0x17", 34 | "svcWaitSynchronization": "0x18", 35 | "svcCancelSynchronization": "0x19", 36 | "svcArbitrateLock": "0x1a", 37 | "svcArbitrateUnlock": "0x1b", 38 | "svcWaitProcessWideKeyAtomic": "0x1c", 39 | "svcSignalProcessWideKey": "0x1d", 40 | "svcGetSystemTick": "0x1e", 41 | "svcConnectToNamedPort": "0x1f", 42 | "svcSendSyncRequestLight": "0x20", 43 | "svcSendSyncRequest": "0x21", 44 | "svcSendSyncRequestWithUserBuffer": "0x22", 45 | "svcSendAsyncRequestWithUserBuffer": "0x23", 46 | "svcGetProcessId": "0x24", 47 | "svcGetThreadId": "0x25", 48 | "svcBreak": "0x26", 49 | "svcOutputDebugString": "0x27", 50 | "svcReturnFromException": "0x28", 51 | "svcGetInfo": "0x29", 52 | "svcWaitForAddress": "0x34", 53 | "svcSignalToAddress": "0x35", 54 | "svcCreateSession": "0x40", 55 | "svcAcceptSession": "0x41", 56 | "svcReplyAndReceiveLight": "0x42", 57 | "svcReplyAndReceive": "0x43", 58 | "svcReplyAndReceiveWithUserBuffer": "0x44", 59 | "svcCreateEvent": "0x45", 60 | "svcDebugActiveProcess": "0x60", 61 | "svcGetDebugEvent": "0x63", 62 | "svcGetThreadList": "0x66", 63 | "svcGetDebugThreadContext": "0x67", 64 | "svcQueryDebugProcessMemory": "0x69", 65 | "svcReadDebugProcessMemory": "0x6a", 66 | "svcGetDebugThreadParam": "0x6d" 67 | } 68 | } 69 | } -------------------------------------------------------------------------------- /kip1converter.py: -------------------------------------------------------------------------------- 1 | from struct import pack, unpack 2 | from sys import argv 3 | from pwn import context, asm 4 | context.arch = 'aarch64' 5 | # https://github.com/Gallopsled/pwntools/tree/dev3 6 | 7 | TEXT_OFFSET = 0x100000 8 | 9 | 10 | f = open(argv[1], "rb") 11 | 12 | header_start = f.read(0x20) 13 | 14 | 15 | section_names = [".text", ".rodata", ".data", ".bss"] 16 | 17 | sections = [] 18 | for i in range(6): 19 | section_bytes = f.read(0x10) 20 | section = {} 21 | 22 | if i < len(section_names): 23 | section["Name"] = section_names[i] 24 | 25 | section["OutOffset"], section["DecompressedSize"], section["CompressedSize"], section["Attribute"] = unpack( 26 | "IIII", section_bytes) 27 | sections.append(section) 28 | print(section) 29 | 30 | f.seek(0x100) 31 | #discard kernel caps... 32 | 33 | for i in range(3): 34 | section = sections[i] 35 | section["Buffer"] = f.read(section["DecompressedSize"]) 36 | print(f.read()) 37 | 38 | f.close() 39 | 40 | 41 | f = open(argv[2], "wb") 42 | for i in range(3): 43 | section = sections[i] 44 | f.seek(section["OutOffset"]) 45 | f.write(section["Buffer"]) 46 | f.seek(TEXT_OFFSET-1) 47 | f.write(b'\0') -------------------------------------------------------------------------------- /kip1patch.py: -------------------------------------------------------------------------------- 1 | from struct import pack, unpack 2 | from sys import argv 3 | from pwn import context, asm 4 | context.arch = 'aarch64' 5 | # https://github.com/Gallopsled/pwntools/tree/dev3 6 | 7 | APPLY_CUSTOM_TEXT = True 8 | 9 | TEXT_OFFSET = 0x100000 10 | 11 | if not APPLY_CUSTOM_TEXT: 12 | TEXT_OFFSET = 0 13 | 14 | 15 | # secmon_panic: 16 | # needs exo patched to call the panic call for the amos extension instead of the iram stuff and fullsvcperm enabled in hekate 17 | # results in switch rebooting instantly (into rcm if autorcm is enabled) when called 18 | panic_smc = """ 19 | MOVZ X0, #0x201 20 | MOVK X0, #0xF000, LSL #16 21 | MOVZ X1, #0xF00 22 | SVC #0x7F 23 | """ 24 | 25 | 26 | patches = [ 27 | # 3.0.0 fat32: 28 | # rtld_relocate_modules need to make meminfo.perm != 5 branch always happen else the switch won't boot 29 | # you can imagine how annoying finding out that *that* was the issue was 30 | # this one matches 3.0 fs 31 | #('B #0xA4', TEXT_OFFSET + 0x4d0), 32 | # hook the sdmmc-handler in fs 33 | #('B #0xFFFFFFFFFFE6E87C', TEXT_OFFSET + 0x91790) 34 | 35 | # 7.0.1 exfat: 36 | #('B #0xA8', TEXT_OFFSET + 0x5a8), 37 | #('B #0xFFFFFFFFFFD992DC', TEXT_OFFSET + 0x166d30) 38 | 39 | # 6.1 exfat: 40 | 41 | # sdmmc_wrapper_read 42 | ('B #0xFFFFFFFFFFDAC36C', TEXT_OFFSET + 0x0153ca0), 43 | 44 | ('B #0x98', TEXT_OFFSET + 0x05b0) 45 | ] 46 | 47 | 48 | if not APPLY_CUSTOM_TEXT: 49 | print("WARNING WARNING!!! Not applying the custom text section!!!") 50 | 51 | if len(argv) != 3: 52 | print("Usage: python3 kip1patch.py FS_in.kip FS_out.kip\nThe kip HAS to be uncompressed with kip1decomp first") 53 | exit(-1) 54 | 55 | custom_text = open("out.data", "rb").read() 56 | if len(custom_text) != TEXT_OFFSET and APPLY_CUSTOM_TEXT: 57 | print("PANIC: custom_text is not the correct size") 58 | exit(-1) 59 | 60 | 61 | f = open(argv[1], "rb") 62 | 63 | header_start = f.read(0x20) 64 | 65 | 66 | section_names = [".text", ".rodata", ".data", ".bss"] 67 | 68 | sections = [] 69 | for i in range(6): 70 | section_bytes = f.read(0x10) 71 | section = {} 72 | 73 | if i < len(section_names): 74 | section["Name"] = section_names[i] 75 | 76 | section["OutOffset"], section["DecompressedSize"], section["CompressedSize"], section["Attribute"] = unpack( 77 | "IIII", section_bytes) 78 | sections.append(section) 79 | print(section) 80 | 81 | kernel_caps = [] 82 | for i in range(0x20): 83 | val, = unpack("I", f.read(4)) 84 | kernel_caps.append(val) 85 | 86 | 87 | for i in range(6): 88 | section = sections[i] 89 | section["Buffer"] = f.read(section["CompressedSize"]) 90 | if APPLY_CUSTOM_TEXT: 91 | if i == 0: 92 | section["CompressedSize"] += TEXT_OFFSET 93 | section["DecompressedSize"] += TEXT_OFFSET 94 | elif i <= 3: 95 | section["OutOffset"] += TEXT_OFFSET 96 | 97 | f.close() 98 | 99 | if APPLY_CUSTOM_TEXT: 100 | sections[0]["Buffer"] = custom_text + sections[0]["Buffer"] 101 | 102 | sections[0]["Buffer"] = sections[0]["Buffer"][:4] + \ 103 | pack("I", 0) + sections[0]["Buffer"][8:] 104 | 105 | 106 | for instr, offset in patches: 107 | buf = sections[0]["Buffer"] 108 | patch = asm(instr) 109 | out_buf = buf[:offset] + patch + buf[offset + len(patch):] 110 | sections[0]["Buffer"] = out_buf 111 | 112 | 113 | f = open(argv[2], "wb") 114 | 115 | f.write(header_start) 116 | 117 | for section in sections: 118 | section_header = pack( 119 | "IIII", section["OutOffset"], section["DecompressedSize"], section["CompressedSize"], section["Attribute"]) 120 | f.write(section_header) 121 | 122 | for i in range(0x20): 123 | f.write(pack("I", kernel_caps[i])) 124 | 125 | for section in sections: 126 | f.write(section["Buffer"]) 127 | 128 | f.close() 129 | -------------------------------------------------------------------------------- /source/fs_types.h: -------------------------------------------------------------------------------- 1 | // Many thanks to m4xw for this!z 2 | 3 | typedef unsigned char undefined; 4 | 5 | typedef unsigned char byte; 6 | typedef unsigned int dword; 7 | typedef long long longlong; 8 | typedef unsigned long long qword; 9 | typedef unsigned int uint; 10 | typedef unsigned long long ulonglong; 11 | typedef unsigned char undefined1; 12 | typedef unsigned short undefined2; 13 | typedef unsigned int undefined4; 14 | typedef unsigned long long undefined8; 15 | typedef unsigned short word; 16 | typedef void* pointer64; 17 | 18 | typedef struct struct_mmc_obj2_t struct_mmc_obj2_t, *Pstruct_mmc_obj2_t; 19 | 20 | struct struct_mmc_obj2_t { 21 | pointer64 vtab; 22 | pointer64 parent; 23 | pointer64 obj3; 24 | pointer64 field_18; 25 | qword field_20; 26 | byte field_28; 27 | qword field_29; 28 | byte field_31; 29 | byte field_32; 30 | byte field_33; 31 | byte field_34; 32 | byte field_35; 33 | byte field_36; 34 | byte field_37; 35 | byte field_38; 36 | byte field_39; 37 | byte field_3A; 38 | byte field_3B; 39 | byte field_3C; 40 | byte field_3D; 41 | byte field_3E; 42 | byte field_3F; 43 | byte field_40; 44 | byte field_41; 45 | byte field_42; 46 | byte field_43; 47 | byte field_44; 48 | byte field_45; 49 | byte field_46; 50 | byte field_47; 51 | byte field_48; 52 | byte field_49; 53 | byte field_4A; 54 | byte field_4B; 55 | byte field_4C; 56 | byte field_4D; 57 | byte field_4E; 58 | byte field_4F; 59 | byte field_50; 60 | byte field_51; 61 | byte field_52; 62 | byte field_53; 63 | byte field_54; 64 | byte field_55; 65 | byte field_56; 66 | byte field_57; 67 | byte field_58; 68 | byte field_59; 69 | byte field_5A; 70 | byte field_5B; 71 | byte field_5C; 72 | byte field_5D; 73 | byte field_5E; 74 | byte field_5F; 75 | byte field_60; 76 | byte field_61; 77 | byte field_62; 78 | byte field_63; 79 | byte field_64; 80 | byte field_65; 81 | byte field_66; 82 | byte field_67; 83 | byte field_68; 84 | byte field_69; 85 | byte field_6A; 86 | byte field_6B; 87 | byte field_6C; 88 | byte field_6D; 89 | byte field_6E; 90 | undefined field_0x6f; 91 | qword field_70; 92 | qword field_78; 93 | qword field_80; 94 | byte field_88; 95 | undefined field_0x89; 96 | undefined field_0x8a; 97 | undefined field_0x8b; 98 | undefined field_0x8c; 99 | undefined field_0x8d; 100 | undefined field_0x8e; 101 | undefined field_0x8f; 102 | qword field_90; 103 | qword field_98; 104 | qword field_A0; 105 | byte anonymous_18; 106 | word anonymous_19; 107 | byte field_AB; 108 | byte field_AC; 109 | byte field_AD; 110 | byte field_AE; 111 | byte field_AF; 112 | byte field_B0; 113 | byte field_B1; 114 | byte field_B2; 115 | byte field_B3; 116 | byte field_B4; 117 | byte field_B5; 118 | byte field_B6; 119 | byte field_B7; 120 | byte field_B8; 121 | byte field_B9; 122 | byte field_BA; 123 | byte field_BB; 124 | byte field_BC; 125 | byte field_BD; 126 | byte field_BE; 127 | byte field_BF; 128 | qword field_C0; 129 | byte anonymous_20; 130 | byte anonymous_21; 131 | byte field_23A; 132 | byte field_23B; 133 | byte field_23C; 134 | byte field_23D; 135 | byte field_23E; 136 | byte field_23F; 137 | byte field_240; 138 | byte field_241; 139 | byte field_242; 140 | byte field_243; 141 | byte field_244; 142 | byte field_245; 143 | byte field_246; 144 | byte field_247; 145 | byte field_248; 146 | byte field_249; 147 | byte field_24A; 148 | byte field_24B; 149 | byte field_24C; 150 | byte field_24D; 151 | byte field_24E; 152 | byte field_24F; 153 | byte field_250; 154 | byte field_251; 155 | byte field_252; 156 | byte field_253; 157 | byte field_254; 158 | byte field_255; 159 | byte field_256; 160 | byte field_257; 161 | byte anonymous_22; 162 | byte anonymous_23; 163 | byte field_25A; 164 | byte field_25B; 165 | byte field_25C; 166 | byte field_25D; 167 | byte field_25E; 168 | byte field_25F; 169 | byte field_260; 170 | byte field_261; 171 | byte field_262; 172 | byte field_263; 173 | byte field_264; 174 | byte field_265; 175 | byte field_266; 176 | byte field_267; 177 | byte mutex; 178 | byte field_269; 179 | byte field_26A; 180 | byte field_26B; 181 | byte field_26C; 182 | byte field_26D; 183 | byte field_26E; 184 | byte field_26F; 185 | byte field_270; 186 | byte field_271; 187 | byte field_272; 188 | byte field_273; 189 | byte field_274; 190 | byte field_275; 191 | byte field_276; 192 | byte field_277; 193 | byte anonymous_24; 194 | byte anonymous_25; 195 | byte field_27A; 196 | byte field_27B; 197 | byte field_27C; 198 | byte field_27D; 199 | byte field_27E; 200 | byte field_27F; 201 | byte field_280; 202 | byte field_281; 203 | byte field_282; 204 | byte field_283; 205 | byte field_284; 206 | byte field_285; 207 | byte field_286; 208 | byte field_287; 209 | byte field_288; 210 | byte field_289; 211 | byte field_28A; 212 | byte field_28B; 213 | byte field_28C; 214 | byte field_28D; 215 | byte field_28E; 216 | byte field_28F; 217 | qword field_290; 218 | byte field_298; 219 | byte field_299; 220 | byte field_29A; 221 | byte field_29B; 222 | byte field_29C; 223 | byte field_29D; 224 | byte field_29E; 225 | byte field_29F; 226 | byte field_2A0; 227 | byte field_2A1; 228 | byte field_2A2; 229 | byte field_2A3; 230 | byte field_2A4; 231 | byte field_2A5; 232 | byte field_2A6; 233 | byte field_2A7; 234 | byte field_2A8; 235 | byte field_2A9; 236 | byte field_2AA; 237 | byte field_2AB; 238 | byte field_2AC; 239 | byte field_2AD; 240 | byte field_2AE; 241 | byte field_2AF; 242 | byte field_2B0; 243 | byte field_2B1; 244 | byte field_2B2; 245 | byte field_2B3; 246 | byte field_2B4; 247 | byte field_2B5; 248 | byte field_2B6; 249 | byte field_2B7; 250 | byte anonymous_28; 251 | word anonymous_29; 252 | byte field_14B; 253 | byte field_14C; 254 | byte field_14D; 255 | byte field_14E; 256 | byte field_14F; 257 | byte field_150; 258 | byte field_151; 259 | byte field_152; 260 | byte field_153; 261 | byte field_154; 262 | byte field_155; 263 | byte field_156; 264 | byte field_157; 265 | qword field_158; 266 | byte field_160; 267 | byte field_161; 268 | byte field_162; 269 | byte field_163; 270 | byte field_164; 271 | byte field_165; 272 | byte field_166; 273 | byte field_167; 274 | byte anonymous_30; 275 | byte anonymous_31; 276 | undefined field_0x16a; 277 | undefined field_0x16b; 278 | undefined field_0x16c; 279 | undefined field_0x16d; 280 | undefined field_0x16e; 281 | undefined field_0x16f; 282 | undefined field_0x170; 283 | undefined field_0x171; 284 | undefined field_0x172; 285 | undefined field_0x173; 286 | undefined field_0x174; 287 | undefined field_0x175; 288 | undefined field_0x176; 289 | undefined field_0x177; 290 | undefined field_0x178; 291 | undefined field_0x179; 292 | undefined field_0x17a; 293 | undefined field_0x17b; 294 | undefined field_0x17c; 295 | undefined field_0x17d; 296 | undefined field_0x17e; 297 | undefined field_0x17f; 298 | undefined field_0x180; 299 | undefined field_0x181; 300 | undefined field_0x182; 301 | undefined field_0x183; 302 | undefined field_0x184; 303 | undefined field_0x185; 304 | undefined field_0x186; 305 | undefined field_0x187; 306 | byte anonymous_32; 307 | byte anonymous_33; 308 | undefined field_0x18a; 309 | undefined field_0x18b; 310 | undefined field_0x18c; 311 | undefined field_0x18d; 312 | undefined field_0x18e; 313 | undefined field_0x18f; 314 | undefined field_0x190; 315 | undefined field_0x191; 316 | undefined field_0x192; 317 | undefined field_0x193; 318 | undefined field_0x194; 319 | undefined field_0x195; 320 | undefined field_0x196; 321 | undefined field_0x197; 322 | undefined field_0x198; 323 | undefined field_0x199; 324 | undefined field_0x19a; 325 | undefined field_0x19b; 326 | undefined field_0x19c; 327 | undefined field_0x19d; 328 | undefined field_0x19e; 329 | undefined field_0x19f; 330 | undefined field_0x1a0; 331 | undefined field_0x1a1; 332 | undefined field_0x1a2; 333 | undefined field_0x1a3; 334 | undefined field_0x1a4; 335 | undefined field_0x1a5; 336 | undefined field_0x1a6; 337 | undefined field_0x1a7; 338 | byte anonymous_34; 339 | byte anonymous_35; 340 | undefined field_0x1aa; 341 | undefined field_0x1ab; 342 | undefined field_0x1ac; 343 | undefined field_0x1ad; 344 | undefined field_0x1ae; 345 | undefined field_0x1af; 346 | undefined field_0x1b0; 347 | undefined field_0x1b1; 348 | undefined field_0x1b2; 349 | undefined field_0x1b3; 350 | undefined field_0x1b4; 351 | undefined field_0x1b5; 352 | undefined field_0x1b6; 353 | undefined field_0x1b7; 354 | undefined field_0x1b8; 355 | undefined field_0x1b9; 356 | undefined field_0x1ba; 357 | undefined field_0x1bb; 358 | undefined field_0x1bc; 359 | undefined field_0x1bd; 360 | undefined field_0x1be; 361 | undefined field_0x1bf; 362 | undefined field_0x1c0; 363 | undefined field_0x1c1; 364 | undefined field_0x1c2; 365 | undefined field_0x1c3; 366 | undefined field_0x1c4; 367 | undefined field_0x1c5; 368 | undefined field_0x1c6; 369 | undefined field_0x1c7; 370 | byte anonymous_36; 371 | byte anonymous_37; 372 | undefined field_0x1ca; 373 | undefined field_0x1cb; 374 | undefined field_0x1cc; 375 | undefined field_0x1cd; 376 | undefined field_0x1ce; 377 | undefined field_0x1cf; 378 | undefined field_0x1d0; 379 | undefined field_0x1d1; 380 | undefined field_0x1d2; 381 | undefined field_0x1d3; 382 | undefined field_0x1d4; 383 | undefined field_0x1d5; 384 | undefined field_0x1d6; 385 | undefined field_0x1d7; 386 | undefined field_0x1d8; 387 | undefined field_0x1d9; 388 | undefined field_0x1da; 389 | undefined field_0x1db; 390 | undefined field_0x1dc; 391 | undefined field_0x1dd; 392 | undefined field_0x1de; 393 | undefined field_0x1df; 394 | undefined field_0x1e0; 395 | undefined field_0x1e1; 396 | undefined field_0x1e2; 397 | undefined field_0x1e3; 398 | undefined field_0x1e4; 399 | undefined field_0x1e5; 400 | undefined field_0x1e6; 401 | undefined field_0x1e7; 402 | byte anonymous_38; 403 | byte anonymous_39; 404 | undefined field_0x1ea; 405 | undefined field_0x1eb; 406 | undefined field_0x1ec; 407 | undefined field_0x1ed; 408 | undefined field_0x1ee; 409 | undefined field_0x1ef; 410 | undefined field_0x1f0; 411 | undefined field_0x1f1; 412 | undefined field_0x1f2; 413 | undefined field_0x1f3; 414 | undefined field_0x1f4; 415 | undefined field_0x1f5; 416 | undefined field_0x1f6; 417 | undefined field_0x1f7; 418 | undefined field_0x1f8; 419 | undefined field_0x1f9; 420 | undefined field_0x1fa; 421 | undefined field_0x1fb; 422 | undefined field_0x1fc; 423 | undefined field_0x1fd; 424 | undefined field_0x1fe; 425 | undefined field_0x1ff; 426 | undefined field_0x200; 427 | undefined field_0x201; 428 | undefined field_0x202; 429 | undefined field_0x203; 430 | undefined field_0x204; 431 | undefined field_0x205; 432 | undefined field_0x206; 433 | undefined field_0x207; 434 | byte anonymous_40; 435 | byte anonymous_41; 436 | undefined field_0x20a; 437 | undefined field_0x20b; 438 | undefined field_0x20c; 439 | undefined field_0x20d; 440 | undefined field_0x20e; 441 | undefined field_0x20f; 442 | undefined field_0x210; 443 | undefined field_0x211; 444 | undefined field_0x212; 445 | undefined field_0x213; 446 | undefined field_0x214; 447 | undefined field_0x215; 448 | undefined field_0x216; 449 | undefined field_0x217; 450 | undefined field_0x218; 451 | undefined field_0x219; 452 | undefined field_0x21a; 453 | undefined field_0x21b; 454 | undefined field_0x21c; 455 | undefined field_0x21d; 456 | undefined field_0x21e; 457 | undefined field_0x21f; 458 | undefined field_0x220; 459 | undefined field_0x221; 460 | undefined field_0x222; 461 | undefined field_0x223; 462 | undefined field_0x224; 463 | undefined field_0x225; 464 | undefined field_0x226; 465 | undefined field_0x227; 466 | dword anonymous_42; 467 | byte anonymous_43; 468 | undefined field_0x22d; 469 | undefined field_0x22e; 470 | undefined field_0x22f; 471 | }; 472 | -------------------------------------------------------------------------------- /source/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "twili.h" 6 | 7 | #include "fs_types.h" 8 | 9 | #define INJECTED_SIZE 0x100000 10 | 11 | #define HEAP_SIZE 0x80000 //0x000540000 12 | 13 | // we aren't an applet 14 | u32 __nx_applet_type = AppletType_None; 15 | 16 | // setup a fake heap (we don't need the heap anyway) 17 | char fake_heap[HEAP_SIZE]; 18 | 19 | // we override libnx internals to do a minimal init 20 | void __libnx_initheap(void) 21 | { 22 | extern char *fake_heap_start; 23 | extern char *fake_heap_end; 24 | 25 | // setup newlib fake heap 26 | fake_heap_start = fake_heap; 27 | fake_heap_end = fake_heap + HEAP_SIZE; 28 | } 29 | 30 | void __appInit(void) 31 | { 32 | } 33 | 34 | void __appExit(void) 35 | { 36 | } 37 | 38 | // Useful for debugging in very early boot-stages 39 | // Relies on a patched smcAmsIramCopy in exo which just calls panic instead 40 | // If this gets called it will instantly reboot the switch (into rcm if autorcm is enabled) 41 | void panic() 42 | { 43 | SecmonArgs args = {0}; 44 | args.X[0] = 0xF0000201; 45 | args.X[1] = 0xF00; 46 | 47 | svcCallSecureMonitor(&args); 48 | } 49 | 50 | bool is_inited = false; 51 | 52 | typedef struct_mmc_obj2_t *(*__mmc_get_gc_vtab2)(); 53 | typedef struct_mmc_obj2_t *(*__mmc_get_sd_vtab2)(); 54 | typedef struct_mmc_obj2_t *(*__mmc_get_nand_vtab2)(); 55 | 56 | typedef ulonglong (*__vtab_rw_handler)(struct_mmc_obj2_t *, ulonglong, uint, void *, longlong, int); 57 | 58 | __mmc_get_gc_vtab2 mmc_get_gc_vtab2; 59 | __mmc_get_sd_vtab2 mmc_get_sd_vtab2; 60 | __mmc_get_nand_vtab2 mmc_get_nand_vtab2; 61 | 62 | ulonglong sdmmc_wrapper_read(void *buf, longlong buf_size, int mmc_id, uint sector, 63 | ulonglong num_sectors) 64 | { 65 | struct_mmc_obj2_t *this; 66 | ulonglong read_res; 67 | 68 | switch (mmc_id) 69 | { 70 | case 0: 71 | this = (*mmc_get_nand_vtab2)(); 72 | break; 73 | case 1: 74 | this = (*mmc_get_sd_vtab2)(); 75 | break; 76 | case 2: 77 | this = (*mmc_get_gc_vtab2)(); 78 | break; 79 | default: 80 | fatalSimple(0xffd); 81 | } 82 | 83 | if (this != NULL) 84 | { 85 | read_res = (**(__vtab_rw_handler *)(this->vtab + 0x30))(this, (ulonglong)sector, num_sectors, buf, buf_size, 1); 86 | return read_res; 87 | } 88 | fatalSimple(0xffa); 89 | } 90 | 91 | void populate_function_pointers() 92 | { 93 | MemoryInfo meminfo; 94 | u32 pageinfo; 95 | // Gets start of our .text section 96 | svcQueryMemory(&meminfo, &pageinfo, (u64)&populate_function_pointers); 97 | 98 | // hardcoded to 7.0 exfat fs 99 | //__fs_sleep = (__fs_sleep_func)meminfo.addr + INJECTED_SIZE + 0x1620d0; 100 | //__fs_controller_action = (__fs_controller_action_func)meminfo.addr + INJECTED_SIZE + 0x166590; 101 | 102 | // hardcoded to 6.1 exfat fs 103 | 104 | mmc_get_gc_vtab2 = (__mmc_get_gc_vtab2)((intptr_t)meminfo.addr + INJECTED_SIZE + 0x15ee80); 105 | mmc_get_sd_vtab2 = (__mmc_get_sd_vtab2)((intptr_t)meminfo.addr + INJECTED_SIZE + 0x15ebf0); 106 | mmc_get_nand_vtab2 = (__mmc_get_nand_vtab2)((intptr_t)meminfo.addr + INJECTED_SIZE + 0x15b090); 107 | } 108 | 109 | void thread_main(void* arg) 110 | { 111 | (void) arg; 112 | 113 | svcSleepThread(10e+9L); 114 | 115 | Result rc; 116 | 117 | rc = smInitialize(); 118 | if (R_FAILED(rc)) 119 | fatalSimple(rc); 120 | 121 | rc = setsysInitialize(); 122 | if (R_SUCCEEDED(rc)) 123 | { 124 | SetSysFirmwareVersion fw; 125 | rc = setsysGetFirmwareVersion(&fw); 126 | if (R_SUCCEEDED(rc)) 127 | hosversionSet(MAKEHOSVERSION(fw.major, fw.minor, fw.micro)); 128 | setsysExit(); 129 | } 130 | 131 | rc = fsInitialize(); 132 | if (R_FAILED(rc)) 133 | fatalSimple(rc); 134 | 135 | rc = fsdevMountSdmc(); 136 | if (R_FAILED(rc)) 137 | fatalSimple(rc); 138 | 139 | //twiliInitialize(); 140 | 141 | is_inited = true; 142 | } 143 | 144 | Thread our_thread; 145 | void __injected_init() 146 | { 147 | populate_function_pointers(); 148 | threadCreate(&our_thread, thread_main, NULL, 0x1000, 0x3f, 3); 149 | threadStart(&our_thread); 150 | } -------------------------------------------------------------------------------- /source/twili.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2018, misson20000 3 | 4 | Permission to use, copy, modify, and/or distribute this software for any purpose 5 | with or without fee is hereby granted, provided that the above copyright notice 6 | and this permission notice appear in all copies. 7 | 8 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 9 | REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND 10 | FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 11 | INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS 12 | OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 13 | TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF 14 | THIS SOFTWARE. 15 | */ 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | #include "twili.h" 23 | 24 | static Service g_twiliSrv; 25 | static u64 g_twiliRefCnt; 26 | 27 | static Result twiliOpenPipe(Service *srv_out, int id) { 28 | IpcCommand c; 29 | ipcInitialize(&c); 30 | 31 | struct { 32 | u64 magic; 33 | u64 cmd_id; 34 | } *raw; 35 | 36 | ipcSendPid(&c); 37 | raw = ipcPrepareHeader(&c, sizeof(*raw)); 38 | 39 | raw->magic = SFCI_MAGIC; 40 | raw->cmd_id = id; 41 | 42 | Result rc = serviceIpcDispatch(&g_twiliSrv); 43 | if(R_SUCCEEDED(rc)) { 44 | IpcParsedCommand r; 45 | ipcParse(&r); 46 | 47 | struct { 48 | u64 magic; 49 | u64 result; 50 | } *resp = r.Raw; 51 | 52 | rc = resp->result; 53 | 54 | if(R_SUCCEEDED(rc)) { 55 | serviceCreate(srv_out, r.Handles[0]); 56 | } 57 | } 58 | 59 | return rc; 60 | } 61 | 62 | static Service g_twiliPipeStdin; 63 | static Service g_twiliPipeStdout; 64 | static Service g_twiliPipeStderr; 65 | static Service g_twiliLogPipe; 66 | 67 | static ssize_t twiliWrite(Service *pipe, struct _reent *r, void *fd, const char *ptr, size_t len) { 68 | IpcCommand c; 69 | ipcInitialize(&c); 70 | 71 | struct { 72 | u64 magic; 73 | u64 cmd_id; 74 | } *raw; 75 | 76 | ipcAddSendBuffer(&c, ptr, len, 0); 77 | raw = ipcPrepareHeader(&c, sizeof(*raw)); 78 | 79 | raw->magic = SFCI_MAGIC; 80 | raw->cmd_id = 1; 81 | 82 | Result rc = serviceIpcDispatch(pipe); 83 | if(R_SUCCEEDED(rc)) { 84 | IpcParsedCommand r; 85 | ipcParse(&r); 86 | 87 | struct { 88 | u64 magic; 89 | u64 result; 90 | } *resp = r.Raw; 91 | 92 | rc = resp->result; 93 | } 94 | 95 | if(R_SUCCEEDED(rc)) { 96 | return len; 97 | } else { 98 | if(r == NULL) { 99 | errno = EIO; 100 | } else { 101 | r->_errno = EIO; 102 | } 103 | return -1; 104 | } 105 | } 106 | 107 | Result twiliWriteNamedPipe(Service *pipe, const char *ptr, size_t len) { 108 | twiliWrite(pipe, NULL, NULL, ptr, len); 109 | } 110 | 111 | static ssize_t twiliRead(Service *pipe, struct _reent *r, void *fd, char *ptr, size_t len) { 112 | IpcCommand c; 113 | ipcInitialize(&c); 114 | 115 | struct { 116 | u64 magic; 117 | u64 cmd_id; 118 | } *raw; 119 | 120 | ipcAddRecvBuffer(&c, ptr, len, 0); 121 | raw = ipcPrepareHeader(&c, sizeof(*raw)); 122 | 123 | raw->magic = SFCI_MAGIC; 124 | raw->cmd_id = 0; 125 | 126 | Result rc = serviceIpcDispatch(pipe); 127 | if(R_SUCCEEDED(rc)) { 128 | IpcParsedCommand r; 129 | ipcParse(&r); 130 | 131 | struct { 132 | u64 magic; 133 | u64 result; 134 | u64 size; 135 | } *resp = r.Raw; 136 | 137 | rc = resp->result; 138 | 139 | if(R_SUCCEEDED(rc)) { 140 | return resp->size; 141 | } 142 | } 143 | 144 | if(r == NULL) { 145 | errno = EIO; 146 | } else { 147 | r->_errno = EIO; 148 | } 149 | return -1; 150 | } 151 | 152 | static ssize_t twiliReadStdin(struct _reent *r, void *fd, char *ptr, size_t len) { 153 | return twiliRead(&g_twiliPipeStdin, r, fd, ptr, len); 154 | } 155 | 156 | static ssize_t twiliWriteStdout(struct _reent *r, void *fd, const char *ptr, size_t len) { 157 | return twiliWrite(&g_twiliPipeStdout, r, fd, ptr, len); 158 | } 159 | 160 | static ssize_t twiliWriteStderr(struct _reent *r, void *fd, const char *ptr, size_t len) { 161 | return twiliWrite(&g_twiliPipeStderr, r, fd, ptr, len); 162 | } 163 | 164 | static ssize_t twiliWriteLogger(struct _reent *r, void *fd, const char *ptr, size_t len) { 165 | return twiliWrite(&g_twiliLogPipe, r, fd, ptr, len); 166 | } 167 | 168 | 169 | static const inline devoptab_t twiliMakeDotab(const char *name, ssize_t (*write_r)(struct _reent *r, void *fd, const char *ptr, size_t len), ssize_t (*read_r)(struct _reent *r, void *fd, char *ptr, size_t len)) { 170 | devoptab_t ret = { 171 | .name = name, 172 | .structSize = 0, 173 | .open_r = NULL, 174 | .close_r = NULL, 175 | .write_r = write_r, 176 | .read_r = read_r, 177 | .seek_r = NULL, 178 | .fstat_r = NULL, 179 | .deviceData = NULL 180 | }; 181 | return ret; 182 | } 183 | 184 | Result twiliCreateNamedOutputPipe(Service *srv_out, const char* name, size_t len) { 185 | IpcCommand c; 186 | ipcInitialize(&c); 187 | 188 | struct { 189 | u64 magic; 190 | u64 cmd_id; 191 | } *raw; 192 | 193 | ipcAddSendBuffer(&c, name, len, 0); 194 | raw = ipcPrepareHeader(&c, sizeof(*raw)); 195 | 196 | raw->magic = SFCI_MAGIC; 197 | raw->cmd_id = 10; 198 | 199 | Result rc = serviceIpcDispatch(&g_twiliSrv); 200 | if(R_SUCCEEDED(rc)) { 201 | IpcParsedCommand r; 202 | ipcParse(&r); 203 | 204 | struct { 205 | u64 magic; 206 | u64 result; 207 | } *resp = r.Raw; 208 | 209 | rc = resp->result; 210 | 211 | if(R_SUCCEEDED(rc)) { 212 | serviceCreate(srv_out, r.Handles[0]); 213 | } 214 | } 215 | return rc; 216 | } 217 | 218 | Result twiliInitialize(void) { 219 | Result r = 0; 220 | 221 | atomicIncrement64(&g_twiliRefCnt); 222 | 223 | if(!serviceIsActive(&g_twiliSrv)) { 224 | r = smGetService(&g_twiliSrv, "twili"); 225 | 226 | twiliCreateNamedOutputPipe(&g_twiliLogPipe, "fs-log", 6); 227 | 228 | if(R_SUCCEEDED(r)) { 229 | r = twiliOpenPipe(&g_twiliPipeStdin, 0); 230 | } 231 | 232 | if(R_SUCCEEDED(r)) { 233 | //static devoptab_t dotab_twili_stdin; 234 | static devoptab_t dotab_twili_stdout; 235 | static devoptab_t dotab_twili_stderr; 236 | //dotab_twili_stdin = twiliMakeDotab("twili-in", 237 | // NULL, twiliReadStdin); 238 | dotab_twili_stdout = twiliMakeDotab("twili-out", 239 | twiliWriteLogger, NULL); 240 | dotab_twili_stderr = twiliMakeDotab("twili-err", 241 | twiliWriteLogger, NULL); 242 | 243 | //devoptab_list[STD_IN] = &dotab_twili_stdin; 244 | devoptab_list[STD_OUT] = &dotab_twili_stdout; 245 | devoptab_list[STD_ERR] = &dotab_twili_stderr; 246 | } 247 | } 248 | 249 | if(R_FAILED(r)) { 250 | twiliExit(); 251 | } 252 | 253 | return r; 254 | } 255 | 256 | void twiliExit(void) { 257 | serviceClose(&g_twiliPipeStderr); 258 | serviceClose(&g_twiliPipeStdout); 259 | serviceClose(&g_twiliPipeStdin); 260 | serviceClose(&g_twiliSrv); 261 | } 262 | -------------------------------------------------------------------------------- /source/twili.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2018, misson20000 3 | 4 | Permission to use, copy, modify, and/or distribute this software for any purpose 5 | with or without fee is hereby granted, provided that the above copyright notice 6 | and this permission notice appear in all copies. 7 | 8 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 9 | REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND 10 | FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 11 | INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS 12 | OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 13 | TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF 14 | THIS SOFTWARE. 15 | */ 16 | 17 | #pragma once 18 | 19 | #ifdef __cplusplus 20 | extern "C" { 21 | #endif 22 | Result twiliWriteNamedPipe(Service *pipe, const char *ptr, size_t len); 23 | Result twiliCreateNamedOutputPipe(Service *srv_out, const char* name, size_t len); 24 | Result twiliInitialize(void); 25 | void twiliExit(void); 26 | 27 | #ifdef __cplusplus 28 | } 29 | #endif 30 | --------------------------------------------------------------------------------