Add DLP patches to allow .cia reading from sd card

This commit is contained in:
Maschell 2024-07-14 17:14:56 +02:00
parent 1aea6f3474
commit e578a26442
13 changed files with 450 additions and 5 deletions

2
.gitignore vendored
View File

@ -8,3 +8,5 @@ cmake-build-debug/
.idea/
CMakeLists.txt
cmake-build-debug-mocha-builder/
source/ios_net/ios_net.bin
source/ios_net/ios_net.bin.h

View File

@ -96,16 +96,20 @@ $(BUILD): $(CURDIR)/source/ios_kernel/ios_kernel.bin.h
@[ -d $@ ] || mkdir -p $@
@$(MAKE) -j1 --no-print-directory -C $(CURDIR)/source/ios_fs -f $(CURDIR)/source/ios_fs/Makefile
@$(MAKE) -j1 --no-print-directory -C $(CURDIR)/source/ios_mcp -f $(CURDIR)/source/ios_mcp/Makefile
@$(MAKE) -j1 --no-print-directory -C $(CURDIR)/source/ios_net -f $(CURDIR)/source/ios_mcp/Makefile
@$(MAKE) -j1 --no-print-directory -C $(CURDIR)/source/ios_usb -f $(CURDIR)/source/ios_usb/Makefile
@$(MAKE) -j1 --no-print-directory -C $(CURDIR)/source/ios_kernel -f $(CURDIR)/source/ios_kernel/Makefile
@$(MAKE) -j1 --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
$(CURDIR)/source/ios_kernel/ios_kernel.bin.h: $(CURDIR)/source/ios_usb/ios_usb.bin.h $(CURDIR)/source/ios_mcp/ios_mcp.bin.h $(CURDIR)/source/ios_fs/ios_fs.bin.h
$(CURDIR)/source/ios_kernel/ios_kernel.bin.h: $(CURDIR)/source/ios_usb/ios_usb.bin.h $(CURDIR)/source/ios_net/ios_net.bin.h $(CURDIR)/source/ios_mcp/ios_mcp.bin.h $(CURDIR)/source/ios_fs/ios_fs.bin.h
@$(MAKE) -j1 --no-print-directory -C $(CURDIR)/source/ios_kernel -f $(CURDIR)/source/ios_kernel/Makefile
$(CURDIR)/source/ios_usb/ios_usb.bin.h:
@$(MAKE) -j1 --no-print-directory -C $(CURDIR)/source/ios_usb -f $(CURDIR)/source/ios_usb/Makefile
$(CURDIR)/source/ios_net/ios_net.bin.h:
@$(MAKE) -j1 --no-print-directory -C $(CURDIR)/source/ios_net -f $(CURDIR)/source/ios_net/Makefile
$(CURDIR)/source/ios_mcp/ios_mcp.bin.h:
@$(MAKE) -j1 --no-print-directory -C $(CURDIR)/source/ios_mcp -f $(CURDIR)/source/ios_mcp/Makefile
@ -117,6 +121,7 @@ clean:
@rm -fr $(BUILD) $(TARGET).rpx $(TARGET).elf
@$(MAKE) --no-print-directory -C $(CURDIR)/source/ios_kernel -f $(CURDIR)/source/ios_kernel/Makefile clean
@$(MAKE) --no-print-directory -C $(CURDIR)/source/ios_usb -f $(CURDIR)/source/ios_usb/Makefile clean
@$(MAKE) --no-print-directory -C $(CURDIR)/source/ios_net -f $(CURDIR)/source/ios_net/Makefile clean
@$(MAKE) --no-print-directory -C $(CURDIR)/source/ios_mcp -f $(CURDIR)/source/ios_mcp/Makefile clean
@$(MAKE) --no-print-directory -C $(CURDIR)/source/ios_fs -f $(CURDIR)/source/ios_fs/Makefile clean

View File

@ -36,6 +36,7 @@ typedef struct __attribute__((packed)) {
#include "ios_fs/ios_fs.bin.h"
#include "ios_kernel/ios_kernel.bin.h"
#include "ios_mcp/ios_mcp.bin.h"
#include "ios_net/ios_net.bin.h"
#include "ios_usb/ios_usb.bin.h"
/* ROP CHAIN STARTS HERE (0x1015BD78) */
@ -316,11 +317,15 @@ static void uhs_exploit_init(int dev_uhs_0_handle) {
static_assert(sizeof(final_chain) < 0xF4148000 - 0xF4140000, "ios_kernel is too big");
memcpy((char *) (0xF4140000), ios_kernel, sizeof(ios_kernel));
static_assert(sizeof(ios_usb) < 0xF4160000 - 0xF4148000, "IOS_USB is too big");
static_assert(sizeof(ios_usb) < 0xF4149000 - 0xF4148000, "IOS_USB is too big");
payload_info_t *payloads = (payload_info_t *) 0xF4148000;
payloads->size = sizeof(ios_usb);
memcpy(payloads->data, ios_usb, payloads->size);
static_assert(sizeof(ios_net) < 0xF4160000 - 0xF4149000, "IOS_NET is too big");
payloads = (payload_info_t *) 0xF4149000;
payloads->size = sizeof(ios_net);
memcpy(payloads->data, ios_net, payloads->size);
static_assert(sizeof(ios_mcp) < 0xF4170000 - 0xF4160000, "IOS_MCP is too big");
payloads = (payload_info_t *) 0xF4160000;

View File

@ -23,9 +23,9 @@
***************************************************************************/
#include "../../ios_fs/ios_fs_syms.h"
#include "../../ios_mcp/ios_mcp_syms.h"
#include "../../ios_net/ios_net_syms.h"
#include "elf_patcher.h"
#include "ios_fs_patches.h"
#include "ios_mcp_patches.h"
#include "kernel_patches.h"
#include "types.h"
#include "utils.h"
@ -47,6 +47,7 @@ typedef struct {
#define mcp_text_phys(addr) ((u32) (addr) -0x05000000 + 0x081C0000)
#define mcp_rodata_phys(addr) ((u32) (addr) -0x05060000 + 0x08220000)
#define mcp_data_phys(addr) ((u32) (addr) -0x05074000 + 0x08234000)
#define net_phys(addr) ((u32) (addr))
#define fsa_phys(addr) ((u32) (addr))
#define kernel_phys(addr) ((u32) (addr))
#define net_phys(addr) ((u32) (addr))
@ -166,6 +167,53 @@ void instant_patches_setup(void) {
*(volatile u32 *) mcp_data_phys(0x050B817C) = *(volatile u32 *) 0x0017FFF0;
*(volatile u32 *) mcp_data_phys(0x050B8180) = *(volatile u32 *) 0x0017FFF4;
// Patch DLP region check by replacing result code with success
*(volatile u32 *) net_phys(0x1239DA7C) = 0;
// Patch DLP to ignore error for missing title archive
*(volatile u32 *) net_phys(0x1239E108) = 0xEA000000; // mov r0, r0
*(volatile u32 *) net_phys(0x1239E10C) = 0xEA000000; // mov r0, r0
*(volatile u32 *) net_phys(0x1239E110) = 0xEA000000; // mov r0, r0
// Patch DLP path from /vol/content/dlp/app to sd:/dlp/app
*(volatile u32 *) net_phys(0x12455368) = 0x2F766F6C; // /vol
*(volatile u32 *) net_phys(0x12455368 + 4) = 0x2F646C70; // /dlp
*(volatile u32 *) net_phys(0x12455368 + 8) = 0x5F5F7364; // __sd
*(volatile u32 *) net_phys(0x12455368 + 12) = 0x2F646C70; // /dlp
*(volatile u32 *) net_phys(0x12455368 + 16) = 0x2F617070; // /app
*(volatile u32 *) net_phys(0x12455368 + 20) = 0x00000000; //
// Patch DLP path from /vol/content/dlp/app to sd:/dlp/app
*(volatile u32 *) net_phys(0x12455490) = 0x2F766F6C; // /vol
*(volatile u32 *) net_phys(0x12455490 + 4) = 0x2F646C70; // /dlp
*(volatile u32 *) net_phys(0x12455490 + 8) = 0x5F5F7364; // __sd
*(volatile u32 *) net_phys(0x12455490 + 12) = 0x2F646C70; // /dlp
*(volatile u32 *) net_phys(0x12455490 + 16) = 0x2F617070; // /app
*(volatile u32 *) net_phys(0x12455490 + 20) = 0x00000000; //
// DLP: (un)mount sd card for .cia reading.
*(volatile u32 *) net_phys(0x1237f33c) = ARM_BL(0x1237f33c, DLP_FSAInit_patch);
*(volatile u32 *) net_phys(0x123a4448) = ARM_BL(0x123a4448, DLP_FSAInit_patch);
*(volatile u32 *) net_phys(0x1239de98) = ARM_BL(0x1239de98, DLP_FSAInit_patch);
*(volatile u32 *) net_phys(0x1237f310) = ARM_BL(0x1237f310, DLP_FSADeinit_patch);
*(volatile u32 *) net_phys(0x1239dfa0) = ARM_BL(0x1239dfa0, DLP_FSADeinit_patch);
*(volatile u32 *) net_phys(0x1239dfc0) = ARM_BL(0x1239dfc0, DLP_FSADeinit_patch);
*(volatile u32 *) net_phys(0x1239dfd8) = ARM_BL(0x1239dfd8, DLP_FSADeinit_patch);
*(volatile u32 *) net_phys(0x1239dfec) = ARM_BL(0x1239dfec, DLP_FSADeinit_patch);
*(volatile u32 *) net_phys(0x1239e020) = ARM_BL(0x1239e020, DLP_FSADeinit_patch);
*(volatile u32 *) net_phys(0x1239e094) = ARM_BL(0x1239e094, DLP_FSADeinit_patch);
*(volatile u32 *) net_phys(0x123a457c) = ARM_BL(0x123a457c, DLP_FSADeinit_patch);
// DLP debug:
/*
*(volatile u32 *) net_phys(0x123a449c) = ARM_BL(0x123a449c, DLP_FSA_OpenFile);
*(volatile u32 *) net_phys(0x1239ce08) = ARM_BL(0x1239ce08, DLP_FSA_OpenFile);
*(volatile u32 *) net_phys(0x1239cf68) = ARM_BL(0x1239cf68, DLP_FSA_OpenFile);
*(volatile u32 *) net_phys(0x1239defc) = ARM_BL(0x1239defc, DLP_FSA_OpenFile);
*(volatile u32 *) net_phys(0x1239debc) = ARM_BL(0x1239debc, DLP_GetChildTitleId);
*/
// Place the environment path at the end of our .text section.
for (int i = 0; i < ENVIRONMENT_PATH_LENGTH; i += 4) {
*(volatile u32 *) mcp_custom_text_phys(MCP_CUSTOM_TEXT_START + MCP_CUSTOM_TEXT_LENGTH - ENVIRONMENT_PATH_LENGTH + i) = *(volatile u32 *) (0x0017FEF0 + i);

View File

@ -0,0 +1,61 @@
#include "ios_net_patches.h"
#include "../../ios_net/ios_net_syms.h"
#include "elf_patcher.h"
#include "types.h"
#define NET_CODE_BASE_PHYS_ADDR (0)
u32 net_get_phys_code_base(void) {
return _text_start + NET_CODE_BASE_PHYS_ADDR;
}
void net_run_patches(u32 ios_elf_start) {
section_write(ios_elf_start, _text_start, (void *) net_get_phys_code_base(), _text_end - _text_start);
// Patch DLP region check by replacing result code with success
section_write_word(ios_elf_start, 0x1239DA7C, 0);
// Patch DLP to ignore error for missing title archive
section_write_word(ios_elf_start, 0x1239E108, 0xEA000000); // mov r0, r0
section_write_word(ios_elf_start, 0x1239E10C, 0xEA000000); // mov r0, r0
section_write_word(ios_elf_start, 0x1239E110, 0xEA000000); // mov r0, r0
// Patch DLP path from /vol/content/dlp/app to sd:/dlp/app
section_write_word(ios_elf_start, 0x12455368, 0x2F766F6C); // /vol
section_write_word(ios_elf_start, 0x12455368 + 4, 0x2F646C70); // /dlp
section_write_word(ios_elf_start, 0x12455368 + 8, 0x5F5F7364); // __sd
section_write_word(ios_elf_start, 0x12455368 + 12, 0x2F646C70); // /dlp
section_write_word(ios_elf_start, 0x12455368 + 16, 0x2F617070); // /app
section_write_word(ios_elf_start, 0x12455368 + 20, 0x00000000); //
// Patch DLP path from /vol/content/dlp/app to sd:/dlp/app
section_write_word(ios_elf_start, 0x12455490, 0x2F766F6C); // /vol
section_write_word(ios_elf_start, 0x12455490 + 4, 0x2F646C70); // /dlp
section_write_word(ios_elf_start, 0x12455490 + 8, 0x5F5F7364); // __sd
section_write_word(ios_elf_start, 0x12455490 + 12, 0x2F646C70); // /dlp
section_write_word(ios_elf_start, 0x12455490 + 16, 0x2F617070); // /app
section_write_word(ios_elf_start, 0x12455490 + 20, 0x00000000); //
// DLP: (un)mount sd card for .cia reading.
section_write_word(ios_elf_start, 0x1237f33c, ARM_BL(0x1237f33c, DLP_FSAInit_patch));
section_write_word(ios_elf_start, 0x123a4448, ARM_BL(0x123a4448, DLP_FSAInit_patch));
section_write_word(ios_elf_start, 0x1239de98, ARM_BL(0x1239de98, DLP_FSAInit_patch));
section_write_word(ios_elf_start, 0x1237f310, ARM_BL(0x1237f310, DLP_FSADeinit_patch));
section_write_word(ios_elf_start, 0x1239dfa0, ARM_BL(0x1239dfa0, DLP_FSADeinit_patch));
section_write_word(ios_elf_start, 0x1239dfc0, ARM_BL(0x1239dfc0, DLP_FSADeinit_patch));
section_write_word(ios_elf_start, 0x1239dfd8, ARM_BL(0x1239dfd8, DLP_FSADeinit_patch));
section_write_word(ios_elf_start, 0x1239dfec, ARM_BL(0x1239dfec, DLP_FSADeinit_patch));
section_write_word(ios_elf_start, 0x1239e020, ARM_BL(0x1239e020, DLP_FSADeinit_patch));
section_write_word(ios_elf_start, 0x1239e094, ARM_BL(0x1239e094, DLP_FSADeinit_patch));
section_write_word(ios_elf_start, 0x123a457c, ARM_BL(0x123a457c, DLP_FSADeinit_patch));
// DLP debug:
/*
section_write_word(ios_elf_start, 0x123a449c, ARM_BL(0x123a449c, DLP_FSA_OpenFile));
section_write_word(ios_elf_start, 0x1239ce08, ARM_BL(0x1239ce08, DLP_FSA_OpenFile));
section_write_word(ios_elf_start, 0x1239cf68, ARM_BL(0x1239cf68, DLP_FSA_OpenFile));
section_write_word(ios_elf_start, 0x1239defc, ARM_BL(0x1239defc, DLP_FSA_OpenFile));
section_write_word(ios_elf_start, 0x1239debc, ARM_BL(0x1239debc, DLP_GetChildTitleId));
*/
}

View File

@ -0,0 +1,10 @@
#ifndef _NET_PATCHES_H_
#define _NET_PATCHES_H_
#include "types.h"
u32 net_get_phys_code_base(void);
void net_run_patches(u32 ios_elf_start);
#endif

View File

@ -23,6 +23,7 @@
***************************************************************************/
#include "instant_patches.h"
#include "ios_mcp_patches.h"
#include "ios_net_patches.h"
#include "types.h"
#include "utils.h"
@ -90,6 +91,9 @@ int _main() {
payload_info_t *payloads = (payload_info_t *) 0x00148000;
kernel_memcpy((void *) USB_PHYS_CODE_BASE, payloads->data, payloads->size);
payloads = (payload_info_t *) 0x00149000;
kernel_memcpy((void *) net_get_phys_code_base(), payloads->data, payloads->size);
payloads = (payload_info_t *) 0x00160000;
kernel_memcpy((void *) mcp_get_phys_code_base(), payloads->data, payloads->size);

146
source/ios_net/Makefile Normal file
View File

@ -0,0 +1,146 @@
#-------------------------------------------------------------------------------
.SUFFIXES:
#-------------------------------------------------------------------------------
ifeq ($(strip $(DEVKITPRO)),)
$(error "Please set DEVKITPRO in your environment. export DEVKITPRO=<path to>/devkitpro")
endif
TOPDIR ?= $(CURDIR)
#---------------------------------------------------------------------------------
# iosu_rules
#---------------------------------------------------------------------------------
ifeq ($(strip $(DEVKITARM)),)
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>/devkitARM")
endif
include $(DEVKITARM)/base_rules
export OBJDUMP := $(PREFIX)objdump
MACHDEP = -DSTARBUCK -mbig-endian -mcpu=arm926ej-s -msoft-float -mfloat-abi=soft
%.elf:
@echo linking ... $(notdir $@)
$(SILENTCMD)$(LD) $(LDFLAGS) $(OFILES) $(LIBPATHS) $(LIBS) -o $@
#---------------------------------------------------------------------------------
#---------------------------------------------------------------------------------
# TARGET is the name of the output
# 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
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
CFLAGS := -Wall -std=gnu11 -Os $(MACHDEP) $(INCLUDE) -Wno-array-bounds -fno-builtin
ASFLAGS := $(MACHDEP)
LDFLAGS := -nostartfiles -nodefaultlibs -mbig-endian \
-Wl,-L $(TOPDIR) -Wl,-Map,$(notdir $*.map),-T $(TOPDIR)/link.ld
LIBS := -lgcc
#-------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level
# containing include and lib
#-------------------------------------------------------------------------------
LIBDIRS :=
#---------------------------------------------------------------------------------
# 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 TARGETNAME := $(TARGET)
export OUTPUT := $(CURDIR)/$(TARGET)
export TOPDIR := $(CURDIR)
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
export DEPSDIR := $(CURDIR)/$(BUILD)
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
export LD := $(CC)
export OFILES_BIN := $(addsuffix .o,$(BINFILES))
export OFILES_SRC := $(SFILES:.s=.o) $(CFILES:.c=.o)
export OFILES := $(OFILES_BIN) $(OFILES_SRC)
export HFILES_BIN := $(addsuffix .h,$(subst .,_,$(BINFILES)))
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
-I$(CURDIR)/$(BUILD)
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
.PHONY: $(BUILD) clean all
#---------------------------------------------------------------------------------
all: $(BUILD)
$(BUILD):
@[ -d $@ ] || mkdir -p $@
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
#---------------------------------------------------------------------------------
clean:
@echo clean ...
@rm -fr $(BUILD) $(TARGET).elf $(TARGET).bin $(TARGET).bin.h $(TARGET)_syms.h
#---------------------------------------------------------------------------------
else
DEPENDS := $(OFILES:.o=.d)
#---------------------------------------------------------------------------------
# main targets
#---------------------------------------------------------------------------------
all : $(OUTPUT).bin.h $(OUTPUT)_syms.h
$(OUTPUT).elf : $(OFILES)
$(OUTPUT).bin: $(OUTPUT).elf
@echo "built ... $(notdir $@)"
@$(OBJCOPY) -j .text -j .rodata -j .data -O binary $(OUTPUT).elf $@
$(OUTPUT).bin.h: $(OUTPUT).bin
@raw2c $<
@cp $(TARGETNAME).c $@
$(OUTPUT)_syms.h: $(OUTPUT).elf
@echo "#ifndef $(TARGETNAME)_SYMS_H" > $@
@echo "#define $(TARGETNAME)_SYMS_H" >> $@
@$(OBJDUMP) -EB -t -marm $(OUTPUT).elf | grep 'g F .text' | grep -v '.hidden' | awk '{print "#define " $$6 " 0x" $$1}' >> $@
@$(OBJDUMP) -EB -t -marm $(OUTPUT).elf | grep -e 'g .text' -e '_bss_' | awk '{print "#define " $$5 " 0x" $$1}' >> $@
@echo "#endif" >> $@
$(OFILES_SRC) : $(HFILES_BIN)
#-------------------------------------------------------------------------------
# you need a rule like this for each extension you use as binary data
#-------------------------------------------------------------------------------
%.bin.o %_bin.h : %.bin
#-------------------------------------------------------------------------------
@echo $(notdir $<)
@$(bin2o)
-include $(DEPENDS)
#---------------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------------

32
source/ios_net/imports.ld Normal file
View File

@ -0,0 +1,32 @@
/*PROVIDE(printf = 0x123ccff4); <- this one prints annoying timestamps*/
PROVIDE(printf = 0x123ccfbc);
PROVIDE(memcpy = 0x123e2a24);
PROVIDE(memset = 0x123e2ac0);
PROVIDE(strncpy = 0x123e3534);
PROVIDE(snprintf = 0x123e34cc);
PROVIDE(IOS_CreateThread = 0x123e4254);
PROVIDE(IOS_StartThread = 0x123e428c);
PROVIDE(IOS_GetThreadPriority = 0x123e42a4);
PROVIDE(IOS_CreateMessageQueue = 0x123e42b4);
PROVIDE(IOS_DestroyMessageQueue = 0x123e42bc);
PROVIDE(IOS_ReceiveMessage = 0x123e42d4);
PROVIDE(IOS_Alloc = 0x123e438c);
PROVIDE(IOS_AllocAligned = 0x123e4394);
PROVIDE(IOS_Free = 0x123e439c);
PROVIDE(IOS_Open = 0x123e43ec);
PROVIDE(IOS_Close = 0x123e43f4);
PROVIDE(IOS_Ioctl = 0x123e4414);
PROVIDE(IOS_Ioctlv = 0x123e441c);
PROVIDE(IOS_GetAbsTime64 = 0x123e433c);
PROVIDE(IOS_GetAbsTimeCalendar = 0x123e4334);
PROVIDE(IOS_CreateSemaphore = 0x123e450c);
PROVIDE(IOS_WaitSemaphore = 0x123e4514);
PROVIDE(IOS_SignalSemaphore = 0x123e451c);
PROVIDE(IOS_DestroySemaphore = 0x123e4524);
PROVIDE(FSA_Mount = 0x123cc44c);
PROVIDE(FSA_Unmount = 0x123cbfb4);
PROVIDE(FSA_OpenDir = 0x123c9f48);
PROVIDE(FSA_CloseDir = 0x123c97b0);

28
source/ios_net/link.ld Normal file
View File

@ -0,0 +1,28 @@
OUTPUT_ARCH(arm)
INCLUDE "imports.ld"
SECTIONS {
. = 0x12431900; /* real .text section is ending at 0x12431843, Hokaku is starting at 0x12432000 */
.text : {
_text_start = .;
*(.text*);
*(.rodata*);
*(.data*);
}
_text_end = .;
/* We don't need a .bss section for now. Keep Hokaku in mind when adding .bss section.
.bss : {
_bss_start = .;
*(.bss*);
}
_bss_end = .;*/
/DISCARD/ : {
*(*);
}
}
ASSERT((0x12431900 + SIZEOF(.text)) < 0x12432000, "ios_net text is too big");

View File

@ -0,0 +1,15 @@
#ifndef FSA_H
#define FSA_H
#include <stdint.h>
#define FSA_MOUNTFLAGS_BINDMOUNT (1 << 0)
#define FSA_MOUNTFLAGS_GLOBAL (1 << 1)
int FSA_Mount(int fd, char *device_path, char *volume_path, uint32_t flags, char *arg_string, int arg_string_len);
int FSA_Unmount(int fd, char *path, uint32_t flags);
int FSA_OpenDir(int fd, char *path, int *outHandle);
int FSA_CloseDir(int fd, int handle);
#endif

View File

@ -0,0 +1,47 @@
#pragma once
#include <stdint.h>
typedef struct {
void *vaddr;
uint32_t len;
uint32_t paddr;
} IOSVec_t;
typedef struct {
uint32_t year;
uint32_t month;
uint32_t day;
uint32_t hour;
uint32_t minute;
uint32_t second;
} CalendarTime_t;
#define IOS_HEAP_LOCAL 0xcafe
#define IOS_HEAP_SHARED 0xcaff
void *IOS_Alloc(uint32_t heap, uint32_t size);
void *IOS_AllocAligned(uint32_t heap, uint32_t size, uint32_t alignment);
void IOS_Free(uint32_t heap, void *ptr);
int IOS_Open(const char *device, int mode);
int IOS_Close(int fd);
int IOS_Ioctl(int fd, uint32_t request, void *input_buffer, uint32_t len_in, void *output_buffer, uint32_t len_out);
int IOS_Ioctlv(int fd, uint32_t request, uint32_t num_in, uint32_t num_out, IOSVec_t *vectors);
int IOS_GetAbsTime64(uint64_t *time);
int IOS_GetAbsTimeCalendar(CalendarTime_t *time);
int IOS_CreateSemaphore(int32_t maxCount, int32_t initialCount);
int IOS_WaitSemaphore(int id, uint32_t tryWait);
int IOS_SignalSemaphore(int id);
int IOS_DestroySemaphore(int id);

View File

@ -0,0 +1,42 @@
#include "fsa.h"
#include <stdio.h>
uint32_t DLP_FSAInit_patch(void *u1) {
int (*const real_DLP_FSAInit_patch)(void *) = (void *) 0x0123c0a1c;
int handle = real_DLP_FSAInit_patch(u1);
if (handle != -1) {
if (FSA_Mount(handle, "/dev/sdcard01", "/vol/dlp__sd", 0, 0, 0) == 0) {
printf("Mocha (DLP): Mounted sd card for handle (%08X).\n", handle);
} else {
printf("Mocha (DLP): Failed to mount sd card for handle (%08X).\n", handle);
}
} else {
printf("Mocha (DLP): Getting FSAClient failed. Could not mount sd card.\n");
}
return handle;
}
uint32_t DLP_FSADeinit_patch(int fsaHandle) {
uint32_t (*const real_NET_DLP_deinit_patch)(int) = (void *) 0x123c0948;
if (FSA_Unmount(fsaHandle, "/vol/dlp__sd", 0) == 0) {
printf("Mocha (DLP): Unmounted sd card for handle (%08X).\n", fsaHandle);
} else {
printf("Mocha (DLP): Failed to unmount sd card for handle (%08X).\n", fsaHandle);
}
return real_NET_DLP_deinit_patch(fsaHandle);
}
uint32_t DLP_FSA_OpenFile(int fd, char *path, char *mode, uint32_t *outhandle) {
int (*const real_DLP_FSA_OpenFile)(int, char *, char *, uint32_t *) = (void *) 0x123c9480;
int result = real_DLP_FSA_OpenFile(fd, path, mode, outhandle);
printf("DLP_FSA_OpenFile(%08X %s %s %p) returned %d \n", fd, path, mode, outhandle, result);
return result;
}
uint32_t DLP_GetChildTitleId(uint32_t *titleId, uint32_t uniqueId, int fsaHandle, const char *path, uint8_t childIndex) {
int (*const real_DLP_GetChildTitleId)(uint32_t * titleId, uint32_t uniqueId, int fsaHandle, const char *, uint8_t childIndex) = (void *) 0x1239bd38;
int result = real_DLP_GetChildTitleId(titleId, uniqueId, fsaHandle, path, childIndex);
printf("DLP_GetChildTitleId(%08X%08X unique %08X handle %08X path \"%s\" childindex %02X) returned %d \n", titleId[0], titleId[1], uniqueId, fsaHandle, path, childIndex, result);
return result;
}