MochaPayload/source/ios_kernel/source/fsa.c
2020-04-28 15:07:52 +02:00

238 lines
5.7 KiB
C

/***************************************************************************
* Copyright (C) 2016
* by Dimok
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any
* damages arising from the use of this software.
*
* Permission is granted to anyone to use this software for any
* purpose, including commercial applications, and to alter it and
* redistribute it freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you
* must not claim that you wrote the original software. If you use
* this software in a product, an acknowledgment in the product
* documentation would be appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and
* must not be misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source
* distribution.
***************************************************************************/
#include "types.h"
#include "utils.h"
#define svcAlloc ((void *(*)(u32 heapid, u32 size))0x081234E4)
#define svcAllocAlign ((void *(*)(u32 heapid, u32 size, u32 align))0x08123464)
#define svcFree ((void *(*)(u32 heapid, void *ptr))0x08123830)
#define svcOpen ((int (*)(const char* name, int mode))0x0812940C)
#define svcClose ((int (*)(int fd))0x08129368)
#define svcIoctl ((int (*)(int fd, u32 request, void* input_buffer, u32 input_buffer_len, void* output_buffer, u32 output_buffer_len))0x081290E0)
#define svcIoctlv ((int (*)(int fd, u32 request, u32 vector_count_in, u32 vector_count_out, iovec_s* vector))0x0812903C)
typedef struct
{
void* ptr;
u32 len;
u32 unk;
}iovec_s;
static void* allocIobuf()
{
void* ptr = svcAlloc(0xCAFF, 0x828);
kernel_memset(ptr, 0x00, 0x828);
return ptr;
}
static void freeIobuf(void* ptr)
{
svcFree(0xCAFF, ptr);
}
static int IOS_Open(const char * dev, int mode)
{
// put string into a good location
char* devStr = (char*)svcAlloc(0xCAFF, 0x20);
if(!devStr)
return -3;
kernel_strncpy(devStr, dev, 0x20);
int res = svcOpen(devStr, 0);
svcFree(0xCAFF, devStr);
return res;
}
static int FSA_Open(void)
{
return IOS_Open("/dev/fsa", 0);
}
static int FSA_Close(int fd)
{
return svcClose(fd);
}
static int FSA_RawOpen(int fd, const char* device_path, int* outHandle)
{
u8* iobuf = allocIobuf();
u32* inbuf = (u32*)iobuf;
u32* outbuf = (u32*)&iobuf[0x520];
kernel_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;
}
static 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;
}
static 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;
}
static 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;
}
int FSA_SDReadRawSectors(void *buffer, u32 sector, u32 num_sectors)
{
int fsa = FSA_Open();
if(fsa < 0)
return fsa;
int fd;
int res = FSA_RawOpen(fsa, "/dev/sdcard01", &fd);
if(res < 0)
{
FSA_Close(fsa);
return res;
}
void *buf = svcAllocAlign(0xCAFF, num_sectors << 9, 0x40);
if(!buf)
{
FSA_RawClose(fsa, fd);
FSA_Close(fsa);
return -2;
}
res = FSA_RawRead(fsa, buf, 0x200, num_sectors, sector, fd);
kernel_memcpy(buffer, buf, num_sectors << 9);
svcFree(0xCAFF, buf);
FSA_RawClose(fsa, fd);
FSA_Close(fsa);
return res;
}
int FSA_SDWriteRawSectors(const void *buffer, u32 sector, u32 num_sectors)
{
int fsa = FSA_Open();
if(fsa < 0)
return fsa;
int fd;
int res = FSA_RawOpen(fsa, "/dev/sdcard01", &fd);
if(res < 0)
{
FSA_Close(fsa);
return res;
}
void *buf = svcAllocAlign(0xCAFF, num_sectors << 9, 0x40);
if(!buf)
{
FSA_RawClose(fsa, fd);
FSA_Close(fsa);
return -2;
}
kernel_memcpy(buf, buffer, num_sectors << 9);
res = FSA_RawWrite(fsa, buf, 0x200, num_sectors, sector, fd);
svcFree(0xCAFF, buf);
FSA_RawClose(fsa, fd);
FSA_Close(fsa);
return res;
}