Implement fs:REG

This commit is contained in:
TuxSH 2019-03-10 22:18:28 +01:00 committed by fincs
parent 550793b262
commit dacacfa403
3 changed files with 191 additions and 0 deletions

View File

@ -40,6 +40,7 @@ extern "C" {
#include <3ds/services/csnd.h>
#include <3ds/services/dsp.h>
#include <3ds/services/fs.h>
#include <3ds/services/fsreg.h>
#include <3ds/services/frd.h>
#include <3ds/services/gspgpu.h>
#include <3ds/services/gsplcd.h>

View File

@ -0,0 +1,63 @@
/**
* @file fsReg.h
* @brief Filesystem registry service
*/
#pragma once
#include <3ds/exheader.h>
#include <3ds/services/fs.h>
/// Initializes fs:REG.
Result fsRegInit(void);
/// Exits fs:REG.
void fsRegExit(void);
/**
* @brief Gets the current fs:REG session handle.
* @return The current fs:REG session handle.
*/
Handle *fsRegGetSessionHandle(void);
/**
* @brief Registers a program's storage information.
* @param pid The Process ID of the program.
* @param programHandle The program handle.
* @param programInfo Information about the program.
* @param storageInfo Storage information to register.
*/
Result FSREG_Register(u32 pid, u64 programHandle, const FS_ProgramInfo *programInfo, const ExHeader_Arm11StorageInfo *storageInfo);
/**
* @brief Unregisters a program's storage information.
* @param pid The Process ID of the program.
*/
Result FSREG_Unregister(u32 pid);
/**
* @brief Retrives the exheader information set(s) (SCI+ACI) about a program.
* @param exheaderInfos[out] Pointer to the output exheader information set(s).
* @param maxNumEntries The maximum number of entries.
* @param programHandle The program handle.
*/
Result FSREG_GetProgramInfo(ExHeader_Info *exheaderInfos, u32 maxNumEntries, u64 programHandle);
/**
* @brief Loads a program.
* @param programHandle[out] Pointer to the output the program handle to.
* @param programInfo Information about the program to load.
*/
Result FSREG_LoadProgram(u64 *programHandle, const FS_ProgramInfo *programInfo);
/**
* @brief Unloads a program.
* @param programHandle The program handle.
*/
Result FSREG_UnloadProgram(u64 programHandle);
/**
* @brief Checks if a program has been loaded by fs:REG.
* @param programHandle The program handle.
*/
Result FSREG_CheckHostLoadId(u64 programHandle);

View File

@ -0,0 +1,127 @@
#include <string.h>
#include <3ds/result.h>
#include <3ds/synchronization.h>
#include <3ds/result.h>
#include <3ds/services/fsreg.h>
#include <3ds/svc.h>
#include <3ds/srv.h>
#include <3ds/ipc.h>
static Handle fsRegHandle;
static int fsRegRefCount;
Result fsRegInit(void)
{
Result ret = 0;
if (AtomicPostIncrement(&fsRegRefCount)) return 0;
ret = srvGetServiceHandle(&fsRegHandle, "fs:REG");
if (R_FAILED(ret)) AtomicDecrement(&fsRegRefCount);
return ret;
}
void fsRegExit(void)
{
if (AtomicDecrement(&fsRegRefCount)) return;
svcCloseHandle(fsRegHandle);
}
Handle *fsRegGetSessionHandle(void)
{
return &fsRegHandle;
}
Result FSREG_Register(u32 pid, u64 programHandle, const FS_ProgramInfo *programInfo, const ExHeader_Arm11StorageInfo *storageInfo)
{
u32 *cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = IPC_MakeHeader(0x401, 0xF, 0); // 0x40103C0
cmdbuf[1] = pid;
cmdbuf[2] = (u32)programHandle;
cmdbuf[3] = (u32)(programHandle >> 32);
memcpy(&cmdbuf[4], programInfo, sizeof(FS_ProgramInfo));
memcpy(&cmdbuf[8], storageInfo, sizeof(ExHeader_Arm11StorageInfo));
Result ret = 0;
if(R_FAILED(ret = svcSendSyncRequest(fsRegHandle))) return ret;
return cmdbuf[1];
}
Result FSREG_Unregister(u32 pid)
{
u32 *cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = IPC_MakeHeader(0x402, 1, 0); // 0x4020040
cmdbuf[1] = pid;
Result ret = 0;
if(R_FAILED(ret = svcSendSyncRequest(fsRegHandle))) return ret;
return cmdbuf[1];
}
Result FSREG_GetProgramInfo(ExHeader_Info *exheaderInfos, u32 maxNumEntries, u64 programHandle)
{
u32 *cmdbuf = getThreadCommandBuffer();
u32 *staticbufs = getThreadStaticBuffers();
cmdbuf[0] = IPC_MakeHeader(0x403, 3, 0); // 0x40300C0
cmdbuf[1] = maxNumEntries;
cmdbuf[2] = (u32)programHandle;
cmdbuf[3] = (u32)(programHandle >> 32);
u32 staticbufscpy[2] = {staticbufs[0], staticbufs[1]};
staticbufs[0] = IPC_Desc_StaticBuffer(maxNumEntries * sizeof(ExHeader_Info), 0);
staticbufs[1] = (u32)exheaderInfos;
Result ret = svcSendSyncRequest(fsRegHandle);
staticbufs[0] = staticbufscpy[0];
staticbufs[1] = staticbufscpy[1];
return R_FAILED(ret) ? ret : cmdbuf[1];
}
Result FSREG_LoadProgram(u64 *programHandle, const FS_ProgramInfo *programInfo)
{
u32 *cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = IPC_MakeHeader(0x404, 4, 0); // 0x4040100
memcpy(&cmdbuf[1], programInfo, sizeof(FS_ProgramInfo));
Result ret = 0;
if(R_FAILED(ret = svcSendSyncRequest(fsRegHandle))) return ret;
*programHandle = ((u64)cmdbuf[3] << 32) | cmdbuf[2];
return cmdbuf[1];
}
Result FSREG_UnloadProgram(u64 programHandle)
{
u32 *cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = IPC_MakeHeader(0x405, 2, 0); // 0x4050080
cmdbuf[1] = (u32)programHandle;
cmdbuf[2] = (u32)(programHandle >> 32);
Result ret = 0;
if(R_FAILED(ret = svcSendSyncRequest(fsRegHandle))) return ret;
return cmdbuf[1];
}
Result FSREG_CheckHostLoadId(u64 programHandle)
{
u32 *cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = IPC_MakeHeader(0x406, 2, 0); // 0x4060080
cmdbuf[1] = (u32)programHandle;
cmdbuf[2] = (u32)(programHandle >> 32);
Result ret = 0;
if(R_FAILED(ret = svcSendSyncRequest(fsRegHandle))) return ret;
return cmdbuf[1];
}