wiiu-nanddumper-payload/ios_mcp/source/fsa.c

438 lines
8.9 KiB
C

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "svc.h"
#include "imports.h"
#include "fsa.h"
static void* allocIobuf()
{
void* ptr = svcAlloc(0xCAFF, 0x828);
memset(ptr, 0x00, 0x828);
return ptr;
}
static void freeIobuf(void* ptr)
{
svcFree(0xCAFF, ptr);
}
int FSA_Mount(int fd, char* device_path, char* volume_path, u32 flags, char* arg_string, int arg_string_len)
{
u8* iobuf = allocIobuf();
u8* inbuf8 = iobuf;
u8* outbuf8 = &iobuf[0x520];
iovec_s* iovec = (iovec_s*)&iobuf[0x7C0];
u32* inbuf = (u32*)inbuf8;
u32* outbuf = (u32*)outbuf8;
strncpy((char*)&inbuf8[0x04], device_path, 0x27F);
strncpy((char*)&inbuf8[0x284], volume_path, 0x27F);
inbuf[0x504 / 4] = (u32)flags;
inbuf[0x508 / 4] = (u32)arg_string_len;
iovec[0].ptr = inbuf;
iovec[0].len = 0x520;
iovec[1].ptr = arg_string;
iovec[1].len = arg_string_len;
iovec[2].ptr = outbuf;
iovec[2].len = 0x293;
int ret = svcIoctlv(fd, 0x01, 2, 1, iovec);
freeIobuf(iobuf);
return ret;
}
int FSA_Unmount(int fd, char* path, u32 flags)
{
u8* iobuf = allocIobuf();
u32* inbuf = (u32*)iobuf;
u32* outbuf = (u32*)&iobuf[0x520];
strncpy((char*)&inbuf[0x01], path, 0x27F);
inbuf[0x284 / 4] = flags;
int ret = svcIoctl(fd, 0x02, inbuf, 0x520, outbuf, 0x293);
freeIobuf(iobuf);
return ret;
}
int FSA_MakeDir(int fd, char* path, u32 flags)
{
u8* iobuf = allocIobuf();
u32* inbuf = (u32*)iobuf;
u32* outbuf = (u32*)&iobuf[0x520];
strncpy((char*)&inbuf[0x01], path, 0x27F);
inbuf[0x284 / 4] = flags;
int ret = svcIoctl(fd, 0x07, inbuf, 0x520, outbuf, 0x293);
freeIobuf(iobuf);
return ret;
}
int FSA_OpenDir(int fd, char* path, int* outHandle)
{
u8* iobuf = allocIobuf();
u32* inbuf = (u32*)iobuf;
u32* outbuf = (u32*)&iobuf[0x520];
strncpy((char*)&inbuf[0x01], path, 0x27F);
int ret = svcIoctl(fd, 0x0A, inbuf, 0x520, outbuf, 0x293);
if(outHandle) *outHandle = outbuf[1];
freeIobuf(iobuf);
return ret;
}
int FSA_ReadDir(int fd, int handle, directoryEntry_s* out_data)
{
u8* iobuf = allocIobuf();
u32* inbuf = (u32*)iobuf;
u32* outbuf = (u32*)&iobuf[0x520];
inbuf[1] = handle;
int ret = svcIoctl(fd, 0x0B, inbuf, 0x520, outbuf, 0x293);
if(out_data) memcpy(out_data, &outbuf[1], sizeof(directoryEntry_s));
freeIobuf(iobuf);
return ret;
}
int FSA_RewindDir(int fd, int handle)
{
u8* iobuf = allocIobuf();
u32* inbuf = (u32*)iobuf;
u32* outbuf = (u32*)&iobuf[0x520];
inbuf[1] = handle;
int ret = svcIoctl(fd, 0x0C, inbuf, 0x520, outbuf, 0x293);
freeIobuf(iobuf);
return ret;
}
int FSA_CloseDir(int fd, int handle)
{
u8* iobuf = allocIobuf();
u32* inbuf = (u32*)iobuf;
u32* outbuf = (u32*)&iobuf[0x520];
inbuf[1] = handle;
int ret = svcIoctl(fd, 0x0D, inbuf, 0x520, outbuf, 0x293);
freeIobuf(iobuf);
return ret;
}
int FSA_ChangeDir(int fd, char* path)
{
u8* iobuf = allocIobuf();
u32* inbuf = (u32*)iobuf;
u32* outbuf = (u32*)&iobuf[0x520];
strncpy((char*)&inbuf[0x01], path, 0x27F);
int ret = svcIoctl(fd, 0x05, inbuf, 0x520, outbuf, 0x293);
freeIobuf(iobuf);
return ret;
}
int FSA_OpenFile(int fd, char* path, char* mode, int* outHandle)
{
u8* iobuf = allocIobuf();
u32* inbuf = (u32*)iobuf;
u32* outbuf = (u32*)&iobuf[0x520];
strncpy((char*)&inbuf[0x01], path, 0x27F);
strncpy((char*)&inbuf[0xA1], mode, 0x10);
int ret = svcIoctl(fd, 0x0E, inbuf, 0x520, outbuf, 0x293);
if(outHandle) *outHandle = outbuf[1];
freeIobuf(iobuf);
return ret;
}
int _FSA_ReadWriteFile(int fd, void* data, u32 size, u32 cnt, int fileHandle, u32 flags, bool read)
{
u8* iobuf = allocIobuf();
u8* inbuf8 = iobuf;
u8* outbuf8 = &iobuf[0x520];
iovec_s* iovec = (iovec_s*)&iobuf[0x7C0];
u32* inbuf = (u32*)inbuf8;
u32* outbuf = (u32*)outbuf8;
inbuf[0x08 / 4] = size;
inbuf[0x0C / 4] = cnt;
inbuf[0x14 / 4] = fileHandle;
inbuf[0x18 / 4] = flags;
iovec[0].ptr = inbuf;
iovec[0].len = 0x520;
iovec[1].ptr = data;
iovec[1].len = size * cnt;
iovec[2].ptr = outbuf;
iovec[2].len = 0x293;
int ret;
if(read) ret = svcIoctlv(fd, 0x0F, 1, 2, iovec);
else ret = svcIoctlv(fd, 0x10, 2, 1, iovec);
freeIobuf(iobuf);
return ret;
}
int FSA_ReadFile(int fd, void* data, u32 size, u32 cnt, int fileHandle, u32 flags)
{
return _FSA_ReadWriteFile(fd, data, size, cnt, fileHandle, flags, true);
}
int FSA_WriteFile(int fd, void* data, u32 size, u32 cnt, int fileHandle, u32 flags)
{
return _FSA_ReadWriteFile(fd, data, size, cnt, fileHandle, flags, false);
}
int FSA_StatFile(int fd, int handle, fileStat_s* out_data)
{
u8* iobuf = allocIobuf();
u32* inbuf = (u32*)iobuf;
u32* outbuf = (u32*)&iobuf[0x520];
inbuf[1] = handle;
int ret = svcIoctl(fd, 0x14, inbuf, 0x520, outbuf, 0x293);
if(out_data) memcpy(out_data, &outbuf[1], sizeof(fileStat_s));
freeIobuf(iobuf);
return ret;
}
int FSA_CloseFile(int fd, int fileHandle)
{
u8* iobuf = allocIobuf();
u32* inbuf = (u32*)iobuf;
u32* outbuf = (u32*)&iobuf[0x520];
inbuf[1] = fileHandle;
int ret = svcIoctl(fd, 0x15, inbuf, 0x520, outbuf, 0x293);
freeIobuf(iobuf);
return ret;
}
int FSA_SetPosFile(int fd, int fileHandle, u32 position)
{
u8* iobuf = allocIobuf();
u32* inbuf = (u32*)iobuf;
u32* outbuf = (u32*)&iobuf[0x520];
inbuf[1] = fileHandle;
inbuf[2] = position;
int ret = svcIoctl(fd, 0x12, inbuf, 0x520, outbuf, 0x293);
freeIobuf(iobuf);
return ret;
}
int FSA_GetStat(int fd, char *path, fileStat_s* out_data)
{
u8* iobuf = allocIobuf();
u32* inbuf = (u32*)iobuf;
u32* outbuf = (u32*)&iobuf[0x520];
strncpy((char*)&inbuf[0x01], path, 0x27F);
inbuf[0x284/4] = 5;
int ret = svcIoctl(fd, 0x18, inbuf, 0x520, outbuf, 0x293);
if(out_data) memcpy(out_data, &outbuf[1], sizeof(fileStat_s));
freeIobuf(iobuf);
return ret;
}
int FSA_Remove(int fd, char *path)
{
u8* iobuf = allocIobuf();
u32* inbuf = (u32*)iobuf;
u32* outbuf = (u32*)&iobuf[0x520];
strncpy((char*)&inbuf[0x01], path, 0x27F);
int ret = svcIoctl(fd, 0x08, inbuf, 0x520, outbuf, 0x293);
freeIobuf(iobuf);
return ret;
}
int FSA_ChangeMode(int fd, char *path, int mode)
{
u8* iobuf = allocIobuf();
u32* inbuf = (u32*)iobuf;
u32* outbuf = (u32*)&iobuf[0x520];
strncpy((char*)&inbuf[0x01], path, 0x27F);
inbuf[0x284/4] = mode;
inbuf[0x288/4] = 0x777; // mask
int ret = svcIoctl(fd, 0x20, inbuf, 0x520, outbuf, 0x293);
freeIobuf(iobuf);
return ret;
}
// type 4 :
// 0x08 : device size in sectors (u64)
// 0x10 : device sector size (u32)
int FSA_GetDeviceInfo(int fd, char* device_path, int type, u32* out_data)
{
u8* iobuf = allocIobuf();
u32* inbuf = (u32*)iobuf;
u32* outbuf = (u32*)&iobuf[0x520];
strncpy((char*)&inbuf[0x01], device_path, 0x27F);
inbuf[0x284 / 4] = type;
int ret = svcIoctl(fd, 0x18, inbuf, 0x520, outbuf, 0x293);
int size = 0;
switch(type)
{
case 0: case 1: case 7:
size = 0x8;
break;
case 2:
size = 0x4;
break;
case 3:
size = 0x1E;
break;
case 4:
size = 0x28;
break;
case 5:
size = 0x64;
break;
case 6: case 8:
size = 0x14;
break;
}
memcpy(out_data, &outbuf[1], size);
freeIobuf(iobuf);
return ret;
}
int FSA_RawOpen(int fd, char* device_path, int* outHandle)
{
u8* iobuf = allocIobuf();
u32* inbuf = (u32*)iobuf;
u32* outbuf = (u32*)&iobuf[0x520];
strncpy((char*)&inbuf[0x01], device_path, 0x27F);
int ret = svcIoctl(fd, 0x6A, inbuf, 0x520, outbuf, 0x293);
if(outHandle) *outHandle = outbuf[1];
freeIobuf(iobuf);
return ret;
}
int FSA_RawClose(int fd, int device_handle)
{
u8* iobuf = allocIobuf();
u32* inbuf = (u32*)iobuf;
u32* outbuf = (u32*)&iobuf[0x520];
inbuf[1] = device_handle;
int ret = svcIoctl(fd, 0x6D, inbuf, 0x520, outbuf, 0x293);
freeIobuf(iobuf);
return ret;
}
// offset in blocks of 0x1000 bytes
int FSA_RawRead(int fd, void* data, u32 size_bytes, u32 cnt, u64 blocks_offset, int device_handle)
{
u8* iobuf = allocIobuf();
u8* inbuf8 = iobuf;
u8* outbuf8 = &iobuf[0x520];
iovec_s* iovec = (iovec_s*)&iobuf[0x7C0];
u32* inbuf = (u32*)inbuf8;
u32* outbuf = (u32*)outbuf8;
// note : offset_bytes = blocks_offset * size_bytes
inbuf[0x08 / 4] = (blocks_offset >> 32);
inbuf[0x0C / 4] = (blocks_offset & 0xFFFFFFFF);
inbuf[0x10 / 4] = cnt;
inbuf[0x14 / 4] = size_bytes;
inbuf[0x18 / 4] = device_handle;
iovec[0].ptr = inbuf;
iovec[0].len = 0x520;
iovec[1].ptr = data;
iovec[1].len = size_bytes * cnt;
iovec[2].ptr = outbuf;
iovec[2].len = 0x293;
int ret = svcIoctlv(fd, 0x6B, 1, 2, iovec);
freeIobuf(iobuf);
return ret;
}
int FSA_RawWrite(int fd, void* data, u32 size_bytes, u32 cnt, u64 blocks_offset, int device_handle)
{
u8* iobuf = allocIobuf();
u8* inbuf8 = iobuf;
u8* outbuf8 = &iobuf[0x520];
iovec_s* iovec = (iovec_s*)&iobuf[0x7C0];
u32* inbuf = (u32*)inbuf8;
u32* outbuf = (u32*)outbuf8;
inbuf[0x08 / 4] = (blocks_offset >> 32);
inbuf[0x0C / 4] = (blocks_offset & 0xFFFFFFFF);
inbuf[0x10 / 4] = cnt;
inbuf[0x14 / 4] = size_bytes;
inbuf[0x18 / 4] = device_handle;
iovec[0].ptr = inbuf;
iovec[0].len = 0x520;
iovec[1].ptr = data;
iovec[1].len = size_bytes * cnt;
iovec[2].ptr = outbuf;
iovec[2].len = 0x293;
int ret = svcIoctlv(fd, 0x6C, 2, 1, iovec);
freeIobuf(iobuf);
return ret;
}