ctrulib changes
This commit is contained in:
parent
74bbfb95d3
commit
e57abad52f
@ -1,166 +0,0 @@
|
|||||||
#include <3ds.h>
|
|
||||||
#include "fsldr.h"
|
|
||||||
#include "fsreg.h"
|
|
||||||
#include "srvsys.h"
|
|
||||||
|
|
||||||
#define SDK_VERSION 0x70200C8
|
|
||||||
|
|
||||||
static Handle fsldrHandle;
|
|
||||||
static int fsldrRefCount;
|
|
||||||
|
|
||||||
// MAKE SURE fsreg has been init before calling this
|
|
||||||
static Result fsldrPatchPermissions(void)
|
|
||||||
{
|
|
||||||
u32 pid;
|
|
||||||
Result res;
|
|
||||||
FS_ProgramInfo info;
|
|
||||||
ExHeader_Arm11StorageInfo storage = {0};
|
|
||||||
|
|
||||||
// SDMC access and NAND access flags
|
|
||||||
storage.fs_access_info = FSACCESS_NANDRW | FSACCESS_NANDRO_RO | FSACCESS_SDMC_RW;
|
|
||||||
info.programId = 0x0004013000001302LL; // loader PID
|
|
||||||
info.mediaType = MEDIATYPE_NAND;
|
|
||||||
|
|
||||||
if(R_SUCCEEDED(res = svcGetProcessId(&pid, CUR_PROCESS_HANDLE)))
|
|
||||||
res = FSREG_Register(pid, 0xFFFF000000000000LL, &info, &storage);
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
Result fsldrInit(void)
|
|
||||||
{
|
|
||||||
Result ret = 0;
|
|
||||||
|
|
||||||
if (AtomicPostIncrement(&fsldrRefCount)) return 0;
|
|
||||||
|
|
||||||
ret = srvSysGetServiceHandle(&fsldrHandle, "fs:LDR");
|
|
||||||
if (R_SUCCEEDED(ret))
|
|
||||||
{
|
|
||||||
fsldrPatchPermissions();
|
|
||||||
ret = FSLDR_InitializeWithSdkVersion(fsldrHandle, SDK_VERSION);
|
|
||||||
ret = FSLDR_SetPriority(0);
|
|
||||||
if (R_FAILED(ret)) svcBreak(USERBREAK_ASSERT);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
AtomicDecrement(&fsldrRefCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
void fsldrExit(void)
|
|
||||||
{
|
|
||||||
if (AtomicDecrement(&fsldrRefCount)) return;
|
|
||||||
svcCloseHandle(fsldrHandle);
|
|
||||||
}
|
|
||||||
|
|
||||||
Result FSLDR_InitializeWithSdkVersion(Handle session, u32 version)
|
|
||||||
{
|
|
||||||
u32 *cmdbuf = getThreadCommandBuffer();
|
|
||||||
|
|
||||||
cmdbuf[0] = IPC_MakeHeader(0x861,1,2); // 0x8610042
|
|
||||||
cmdbuf[1] = version;
|
|
||||||
cmdbuf[2] = 32;
|
|
||||||
|
|
||||||
Result ret = 0;
|
|
||||||
if(R_FAILED(ret = svcSendSyncRequest(session))) return ret;
|
|
||||||
|
|
||||||
return cmdbuf[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
Result FSLDR_SetPriority(u32 priority)
|
|
||||||
{
|
|
||||||
u32 *cmdbuf = getThreadCommandBuffer();
|
|
||||||
|
|
||||||
cmdbuf[0] = IPC_MakeHeader(0x862,1,0); // 0x8620040
|
|
||||||
cmdbuf[1] = priority;
|
|
||||||
|
|
||||||
Result ret = 0;
|
|
||||||
if(R_FAILED(ret = svcSendSyncRequest(fsldrHandle))) return ret;
|
|
||||||
|
|
||||||
return cmdbuf[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
Result FSLDR_OpenFileDirectly(Handle* out, FS_ArchiveID archiveId, FS_Path archivePath, FS_Path filePath, u32 openFlags, u32 attributes)
|
|
||||||
{
|
|
||||||
u32 *cmdbuf = getThreadCommandBuffer();
|
|
||||||
|
|
||||||
cmdbuf[0] = IPC_MakeHeader(0x803,8,4); // 0x8030204
|
|
||||||
cmdbuf[1] = 0;
|
|
||||||
cmdbuf[2] = archiveId;
|
|
||||||
cmdbuf[3] = archivePath.type;
|
|
||||||
cmdbuf[4] = archivePath.size;
|
|
||||||
cmdbuf[5] = filePath.type;
|
|
||||||
cmdbuf[6] = filePath.size;
|
|
||||||
cmdbuf[7] = openFlags;
|
|
||||||
cmdbuf[8] = attributes;
|
|
||||||
cmdbuf[9] = IPC_Desc_StaticBuffer(archivePath.size, 2);
|
|
||||||
cmdbuf[10] = (u32)archivePath.data;
|
|
||||||
cmdbuf[11] = IPC_Desc_StaticBuffer(filePath.size, 0);
|
|
||||||
cmdbuf[12] = (u32)filePath.data;
|
|
||||||
|
|
||||||
Result ret = 0;
|
|
||||||
if(R_FAILED(ret = svcSendSyncRequest(fsldrHandle))) return ret;
|
|
||||||
|
|
||||||
if(out) *out = cmdbuf[3];
|
|
||||||
|
|
||||||
return cmdbuf[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
Result FSLDR_OpenArchive(FS_Archive* archive, FS_ArchiveID id, FS_Path path)
|
|
||||||
{
|
|
||||||
if(!archive) return -2;
|
|
||||||
|
|
||||||
u32 *cmdbuf = getThreadCommandBuffer();
|
|
||||||
|
|
||||||
cmdbuf[0] = IPC_MakeHeader(0x80C,3,2); // 0x80C00C2
|
|
||||||
cmdbuf[1] = id;
|
|
||||||
cmdbuf[2] = path.type;
|
|
||||||
cmdbuf[3] = path.size;
|
|
||||||
cmdbuf[4] = IPC_Desc_StaticBuffer(path.size, 0);
|
|
||||||
cmdbuf[5] = (u32) path.data;
|
|
||||||
|
|
||||||
Result ret = 0;
|
|
||||||
if(R_FAILED(ret = svcSendSyncRequest(fsldrHandle))) return ret;
|
|
||||||
|
|
||||||
if(archive) *archive = cmdbuf[2] | ((u64) cmdbuf[3] << 32);
|
|
||||||
|
|
||||||
return cmdbuf[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
Result FSLDR_CloseArchive(FS_Archive archive)
|
|
||||||
{
|
|
||||||
if(!archive) return -2;
|
|
||||||
|
|
||||||
u32 *cmdbuf = getThreadCommandBuffer();
|
|
||||||
|
|
||||||
cmdbuf[0] = IPC_MakeHeader(0x80E,2,0); // 0x80E0080
|
|
||||||
cmdbuf[1] = (u32) archive;
|
|
||||||
cmdbuf[2] = (u32) (archive >> 32);
|
|
||||||
|
|
||||||
Result ret = 0;
|
|
||||||
if(R_FAILED(ret = svcSendSyncRequest(fsldrHandle))) return ret;
|
|
||||||
|
|
||||||
return cmdbuf[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
Result FSLDR_OpenDirectory(Handle* out, FS_Archive archive, FS_Path path)
|
|
||||||
{
|
|
||||||
u32 *cmdbuf = getThreadCommandBuffer();
|
|
||||||
|
|
||||||
cmdbuf[0] = IPC_MakeHeader(0x80B,4,2); // 0x80B0102
|
|
||||||
cmdbuf[1] = (u32) archive;
|
|
||||||
cmdbuf[2] = (u32) (archive >> 32);
|
|
||||||
cmdbuf[3] = path.type;
|
|
||||||
cmdbuf[4] = path.size;
|
|
||||||
cmdbuf[5] = IPC_Desc_StaticBuffer(path.size, 0);
|
|
||||||
cmdbuf[6] = (u32) path.data;
|
|
||||||
|
|
||||||
Result ret = 0;
|
|
||||||
if(R_FAILED(ret = svcSendSyncRequest(fsldrHandle))) return ret;
|
|
||||||
|
|
||||||
if(out) *out = cmdbuf[3];
|
|
||||||
|
|
||||||
return cmdbuf[1];
|
|
||||||
}
|
|
@ -1,12 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <3ds/types.h>
|
|
||||||
|
|
||||||
Result fsldrInit(void);
|
|
||||||
void fsldrExit(void);
|
|
||||||
Result FSLDR_InitializeWithSdkVersion(Handle session, u32 version);
|
|
||||||
Result FSLDR_SetPriority(u32 priority);
|
|
||||||
Result FSLDR_OpenFileDirectly(Handle* out, FS_ArchiveID archiveId, FS_Path archivePath, FS_Path filePath, u32 openFlags, u32 attributes);
|
|
||||||
Result FSLDR_OpenArchive(FS_Archive* archive, FS_ArchiveID id, FS_Path path);
|
|
||||||
Result FSLDR_CloseArchive(FS_Archive archive);
|
|
||||||
Result FSLDR_OpenDirectory(Handle* out, FS_Archive archive, FS_Path path);
|
|
@ -1,116 +0,0 @@
|
|||||||
#include <3ds.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include "fsreg.h"
|
|
||||||
#include "srvsys.h"
|
|
||||||
|
|
||||||
static Handle fsregHandle;
|
|
||||||
static int fsregRefCount;
|
|
||||||
|
|
||||||
Result fsregInit(void)
|
|
||||||
{
|
|
||||||
Result ret = 0;
|
|
||||||
|
|
||||||
if (AtomicPostIncrement(&fsregRefCount)) return 0;
|
|
||||||
|
|
||||||
ret = srvSysGetServiceHandle(&fsregHandle, "fs:REG");
|
|
||||||
|
|
||||||
if (R_FAILED(ret)) AtomicDecrement(&fsregRefCount);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
void fsregExit(void)
|
|
||||||
{
|
|
||||||
if (AtomicDecrement(&fsregRefCount)) return;
|
|
||||||
svcCloseHandle(fsregHandle);
|
|
||||||
}
|
|
||||||
|
|
||||||
Result FSREG_CheckHostLoadId(u64 prog_handle)
|
|
||||||
{
|
|
||||||
u32 *cmdbuf = getThreadCommandBuffer();
|
|
||||||
|
|
||||||
cmdbuf[0] = IPC_MakeHeader(0x406,2,0); // 0x4060080
|
|
||||||
cmdbuf[1] = (u32) (prog_handle);
|
|
||||||
cmdbuf[2] = (u32) (prog_handle >> 32);
|
|
||||||
|
|
||||||
Result ret = 0;
|
|
||||||
if(R_FAILED(ret = svcSendSyncRequest(fsregHandle))) return ret;
|
|
||||||
|
|
||||||
return cmdbuf[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
Result FSREG_LoadProgram(u64 *prog_handle, FS_ProgramInfo *title)
|
|
||||||
{
|
|
||||||
u32 *cmdbuf = getThreadCommandBuffer();
|
|
||||||
|
|
||||||
cmdbuf[0] = IPC_MakeHeader(0x404,4,0); // 0x4040100
|
|
||||||
memcpy(&cmdbuf[1], &title->programId, sizeof(u64));
|
|
||||||
*(u8 *)&cmdbuf[3] = title->mediaType;
|
|
||||||
memcpy(((u8 *)&cmdbuf[3])+1, &title->padding, 7);
|
|
||||||
|
|
||||||
Result ret = 0;
|
|
||||||
if(R_FAILED(ret = svcSendSyncRequest(fsregHandle))) return ret;
|
|
||||||
*prog_handle = *(u64 *)&cmdbuf[2];
|
|
||||||
|
|
||||||
return cmdbuf[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
Result FSREG_GetProgramInfo(ExHeader *exheader, u32 entry_count, u64 prog_handle)
|
|
||||||
{
|
|
||||||
u32 *cmdbuf = getThreadCommandBuffer();
|
|
||||||
|
|
||||||
cmdbuf[0] = IPC_MakeHeader(0x403,3,0); // 0x40300C0
|
|
||||||
cmdbuf[1] = entry_count;
|
|
||||||
*(u64 *)&cmdbuf[2] = prog_handle;
|
|
||||||
cmdbuf[64] = ((entry_count << 10) << 14) | 2;
|
|
||||||
cmdbuf[65] = (u32) exheader;
|
|
||||||
|
|
||||||
Result ret = 0;
|
|
||||||
if(R_FAILED(ret = svcSendSyncRequest(fsregHandle))) return ret;
|
|
||||||
|
|
||||||
return cmdbuf[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
Result FSREG_UnloadProgram(u64 prog_handle)
|
|
||||||
{
|
|
||||||
u32 *cmdbuf = getThreadCommandBuffer();
|
|
||||||
|
|
||||||
cmdbuf[0] = IPC_MakeHeader(0x405,2,0); // 0x4050080
|
|
||||||
cmdbuf[1] = (u32) (prog_handle);
|
|
||||||
cmdbuf[2] = (u32) (prog_handle >> 32);
|
|
||||||
|
|
||||||
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_Register(u32 pid, u64 prog_handle, FS_ProgramInfo *info, void *storageinfo)
|
|
||||||
{
|
|
||||||
u32 *cmdbuf = getThreadCommandBuffer();
|
|
||||||
|
|
||||||
cmdbuf[0] = IPC_MakeHeader(0x401,0xf,0); // 0x40103C0
|
|
||||||
cmdbuf[1] = pid;
|
|
||||||
*(u64 *)&cmdbuf[2] = prog_handle;
|
|
||||||
memcpy(&cmdbuf[4], &info->programId, sizeof(u64));
|
|
||||||
*(u8 *)&cmdbuf[6] = info->mediaType;
|
|
||||||
memcpy(((u8 *)&cmdbuf[6])+1, &info->padding, 7);
|
|
||||||
memcpy((u8 *)&cmdbuf[8], storageinfo, 32);
|
|
||||||
|
|
||||||
Result ret = 0;
|
|
||||||
if(R_FAILED(ret = svcSendSyncRequest(fsregHandle))) return ret;
|
|
||||||
|
|
||||||
return cmdbuf[1];
|
|
||||||
}
|
|
@ -1,13 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <3ds/types.h>
|
|
||||||
#include <3ds/exheader.h>
|
|
||||||
|
|
||||||
Result fsregInit(void);
|
|
||||||
void fsregExit(void);
|
|
||||||
Result FSREG_CheckHostLoadId(u64 prog_handle);
|
|
||||||
Result FSREG_LoadProgram(u64 *prog_handle, FS_ProgramInfo *title);
|
|
||||||
Result FSREG_GetProgramInfo(ExHeader *exheader, u32 entry_count, u64 prog_handle);
|
|
||||||
Result FSREG_UnloadProgram(u64 prog_handle);
|
|
||||||
Result FSREG_Unregister(u32 pid);
|
|
||||||
Result FSREG_Register(u32 pid, u64 prog_handle, FS_ProgramInfo *info, void *storageinfo);
|
|
@ -1,12 +1,11 @@
|
|||||||
#include <3ds.h>
|
#include <3ds.h>
|
||||||
#include "ifile.h"
|
#include "ifile.h"
|
||||||
#include "fsldr.h"
|
|
||||||
|
|
||||||
Result IFile_Open(IFile *file, FS_ArchiveID archiveId, FS_Path archivePath, FS_Path filePath, u32 flags)
|
Result IFile_Open(IFile *file, FS_ArchiveID archiveId, FS_Path archivePath, FS_Path filePath, u32 flags)
|
||||||
{
|
{
|
||||||
Result res;
|
Result res;
|
||||||
|
|
||||||
res = FSLDR_OpenFileDirectly(&file->handle, archiveId, archivePath, filePath, flags, 0);
|
res = FSUSER_OpenFileDirectly(&file->handle, archiveId, archivePath, filePath, flags, 0);
|
||||||
file->pos = 0;
|
file->pos = 0;
|
||||||
file->size = 0;
|
file->size = 0;
|
||||||
return res;
|
return res;
|
||||||
|
@ -2,10 +2,6 @@
|
|||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
#include "patcher.h"
|
#include "patcher.h"
|
||||||
#include "ifile.h"
|
#include "ifile.h"
|
||||||
#include "fsldr.h"
|
|
||||||
#include "fsreg.h"
|
|
||||||
#include "pxipm.h"
|
|
||||||
#include "srvsys.h"
|
|
||||||
|
|
||||||
#define MAX_SESSIONS 1
|
#define MAX_SESSIONS 1
|
||||||
#define HBLDR_3DSX_TID (*(vu64 *)0x1FF81100)
|
#define HBLDR_3DSX_TID (*(vu64 *)0x1FF81100)
|
||||||
@ -29,9 +25,29 @@ typedef struct
|
|||||||
static Handle g_handles[MAX_SESSIONS+2];
|
static Handle g_handles[MAX_SESSIONS+2];
|
||||||
static int g_active_handles;
|
static int g_active_handles;
|
||||||
static u64 g_cached_prog_handle;
|
static u64 g_cached_prog_handle;
|
||||||
static ExHeader g_exheader;
|
static ExHeader_Info g_exheader;
|
||||||
static char g_ret_buf[1024];
|
static char g_ret_buf[1024];
|
||||||
|
|
||||||
|
// MAKE SURE fsreg has been init before calling this
|
||||||
|
static Result fsldrPatchPermissions(void)
|
||||||
|
{
|
||||||
|
u32 pid;
|
||||||
|
Result res;
|
||||||
|
FS_ProgramInfo info;
|
||||||
|
ExHeader_Arm11StorageInfo storageInfo = {
|
||||||
|
.fs_access_info = FSACCESS_NANDRW | FSACCESS_NANDRO_RO | FSACCESS_SDMC_RW,
|
||||||
|
};
|
||||||
|
|
||||||
|
info.programId = 0x0004013000001302LL; // loader PID
|
||||||
|
info.mediaType = MEDIATYPE_NAND;
|
||||||
|
res = svcGetProcessId(&pid, CUR_PROCESS_HANDLE);
|
||||||
|
if (R_SUCCEEDED(res))
|
||||||
|
{
|
||||||
|
res = FSREG_Register(pid, 0xFFFF000000000000LL, &info, &storageInfo);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
static inline void loadCFWInfo(void)
|
static inline void loadCFWInfo(void)
|
||||||
{
|
{
|
||||||
s64 out;
|
s64 out;
|
||||||
@ -183,12 +199,9 @@ static Result load_code(u64 progid, prog_addrs_t *shared, u64 prog_handle, int i
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ExHeader_CodeSetInfo *csi = &g_exheader.info.sci.codeset_info;
|
ExHeader_CodeSetInfo *csi = &g_exheader.sci.codeset_info;
|
||||||
u16 progver = csi->flags.remaster_version;
|
|
||||||
|
|
||||||
// patch
|
patchCode(progid, csi->flags.remaster_version, (u8 *)shared->text_addr, shared->total_size << 12, csi->text.size, csi->rodata.size, csi->data.size, csi->rodata.address, csi->data.address);
|
||||||
patchCode(progid, progver, (u8 *)shared->text_addr, shared->total_size << 12,
|
|
||||||
csi->text.size, csi->rodata.size, csi->data.size, csi->rodata.address, csi->data.address);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -208,7 +221,7 @@ static Result HBLDR_Init(Handle *session)
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Result loader_GetProgramInfo(ExHeader *exheader, u64 prog_handle)
|
static Result loader_GetProgramInfo(ExHeader_Info *exheader, u64 prog_handle)
|
||||||
{
|
{
|
||||||
Result res;
|
Result res;
|
||||||
|
|
||||||
@ -237,13 +250,12 @@ static Result loader_GetProgramInfo(ExHeader *exheader, u64 prog_handle)
|
|||||||
svcGetSystemInfo(&nbSection0Modules, 26, 0);
|
svcGetSystemInfo(&nbSection0Modules, 26, 0);
|
||||||
|
|
||||||
// Force always having sdmc:/ and nand:/rw permission
|
// Force always having sdmc:/ and nand:/rw permission
|
||||||
exheader->info.aci.local_caps.storage_info.fs_access_info |= FSACCESS_SDMC_RW | FSACCESS_NANDRW;
|
exheader->aci.local_caps.storage_info.fs_access_info |= FSACCESS_NANDRW | FSACCESS_SDMC_RW;
|
||||||
exheader->access_descriptor.acli.local_caps.storage_info.fs_access_info |= FSACCESS_SDMC_RW | FSACCESS_NANDRW;;
|
|
||||||
|
|
||||||
// Tweak 3dsx placeholder title exheader
|
// Tweak 3dsx placeholder title exheader
|
||||||
if (nbSection0Modules == 6)
|
if (nbSection0Modules == 6)
|
||||||
{
|
{
|
||||||
if(exheader->info.aci.local_caps.title_id == HBLDR_3DSX_TID)
|
if(exheader->aci.local_caps.title_id == HBLDR_3DSX_TID)
|
||||||
{
|
{
|
||||||
Handle hbldr = 0;
|
Handle hbldr = 0;
|
||||||
res = HBLDR_Init(&hbldr);
|
res = HBLDR_Init(&hbldr);
|
||||||
@ -261,11 +273,10 @@ static Result loader_GetProgramInfo(ExHeader *exheader, u64 prog_handle)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 originalProgId = exheader->info.aci.local_caps.title_id;
|
u64 originalProgId = exheader->aci.local_caps.title_id;
|
||||||
if(CONFIG(PATCHGAMES) && loadTitleExheader(exheader->info.aci.local_caps.title_id, exheader))
|
if(CONFIG(PATCHGAMES) && loadTitleExheader(exheader->aci.local_caps.title_id, exheader))
|
||||||
{
|
{
|
||||||
exheader->info.aci.local_caps.title_id = originalProgId;
|
exheader->aci.local_caps.title_id = originalProgId;
|
||||||
exheader->access_descriptor.acli.local_caps.title_id = originalProgId;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -288,7 +299,7 @@ static Result loader_LoadProcess(Handle *process, u64 prog_handle)
|
|||||||
u64 progid;
|
u64 progid;
|
||||||
|
|
||||||
// make sure the cached info corrosponds to the current prog_handle
|
// make sure the cached info corrosponds to the current prog_handle
|
||||||
if (g_cached_prog_handle != prog_handle || g_exheader.info.aci.local_caps.title_id == HBLDR_3DSX_TID)
|
if (g_cached_prog_handle != prog_handle || g_exheader.aci.local_caps.title_id == HBLDR_3DSX_TID)
|
||||||
{
|
{
|
||||||
res = loader_GetProgramInfo(&g_exheader, prog_handle);
|
res = loader_GetProgramInfo(&g_exheader, prog_handle);
|
||||||
g_cached_prog_handle = prog_handle;
|
g_cached_prog_handle = prog_handle;
|
||||||
@ -303,7 +314,7 @@ static Result loader_LoadProcess(Handle *process, u64 prog_handle)
|
|||||||
flags = 0;
|
flags = 0;
|
||||||
for (count = 0; count < 28; count++)
|
for (count = 0; count < 28; count++)
|
||||||
{
|
{
|
||||||
desc = g_exheader.info.aci.kernel_caps.descriptors[count];
|
desc = g_exheader.aci.kernel_caps.descriptors[count];
|
||||||
if (0x1FE == desc >> 23)
|
if (0x1FE == desc >> 23)
|
||||||
{
|
{
|
||||||
flags = desc & 0xF00;
|
flags = desc & 0xF00;
|
||||||
@ -315,7 +326,9 @@ static Result loader_LoadProcess(Handle *process, u64 prog_handle)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// check for 3dsx process
|
// check for 3dsx process
|
||||||
progid = g_exheader.info.aci.local_caps.title_id;
|
progid = g_exheader.aci.local_caps.title_id;
|
||||||
|
ExHeader_CodeSetInfo *csi = &g_exheader.sci.codeset_info;
|
||||||
|
|
||||||
if (progid == HBLDR_3DSX_TID)
|
if (progid == HBLDR_3DSX_TID)
|
||||||
{
|
{
|
||||||
Handle hbldr = 0;
|
Handle hbldr = 0;
|
||||||
@ -327,11 +340,11 @@ static Result loader_LoadProcess(Handle *process, u64 prog_handle)
|
|||||||
}
|
}
|
||||||
u32* cmdbuf = getThreadCommandBuffer();
|
u32* cmdbuf = getThreadCommandBuffer();
|
||||||
cmdbuf[0] = IPC_MakeHeader(1,6,0);
|
cmdbuf[0] = IPC_MakeHeader(1,6,0);
|
||||||
cmdbuf[1] = g_exheader.info.sci.codeset_info.text.address;
|
cmdbuf[1] = csi->text.address;
|
||||||
cmdbuf[2] = flags & 0xF00;
|
cmdbuf[2] = flags & 0xF00;
|
||||||
cmdbuf[3] = progid;
|
cmdbuf[3] = progid;
|
||||||
cmdbuf[4] = progid>>32;
|
cmdbuf[4] = progid>>32;
|
||||||
memcpy(&cmdbuf[5], g_exheader.info.sci.codeset_info.name, 8);
|
memcpy(&cmdbuf[5], csi->name, 8);
|
||||||
res = svcSendSyncRequest(hbldr);
|
res = svcSendSyncRequest(hbldr);
|
||||||
svcCloseHandle(hbldr);
|
svcCloseHandle(hbldr);
|
||||||
if (R_SUCCEEDED(res))
|
if (R_SUCCEEDED(res))
|
||||||
@ -344,13 +357,12 @@ static Result loader_LoadProcess(Handle *process, u64 prog_handle)
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
codeset = (Handle)cmdbuf[3];
|
codeset = (Handle)cmdbuf[3];
|
||||||
res = svcCreateProcess(process, codeset, g_exheader.info.aci.kernel_caps.descriptors, count);
|
res = svcCreateProcess(process, codeset, g_exheader.aci.kernel_caps.descriptors, count);
|
||||||
svcCloseHandle(codeset);
|
svcCloseHandle(codeset);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
// allocate process memory
|
// allocate process memory
|
||||||
ExHeader_CodeSetInfo *csi = &g_exheader.info.sci.codeset_info;
|
|
||||||
vaddr.text_addr = csi->text.address;
|
vaddr.text_addr = csi->text.address;
|
||||||
vaddr.text_size = (csi->text.size + 4095) >> 12;
|
vaddr.text_size = (csi->text.size + 4095) >> 12;
|
||||||
vaddr.ro_addr = csi->rodata.address;
|
vaddr.ro_addr = csi->rodata.address;
|
||||||
@ -381,7 +393,7 @@ static Result loader_LoadProcess(Handle *process, u64 prog_handle)
|
|||||||
res = svcCreateCodeSet(&codeset, &codesetinfo, (void *)shared_addr.text_addr, (void *)shared_addr.ro_addr, (void *)shared_addr.data_addr);
|
res = svcCreateCodeSet(&codeset, &codesetinfo, (void *)shared_addr.text_addr, (void *)shared_addr.ro_addr, (void *)shared_addr.data_addr);
|
||||||
if (res >= 0)
|
if (res >= 0)
|
||||||
{
|
{
|
||||||
res = svcCreateProcess(process, codeset, g_exheader.info.aci.kernel_caps.descriptors, count);
|
res = svcCreateProcess(process, codeset, g_exheader.aci.kernel_caps.descriptors, count);
|
||||||
svcCloseHandle(codeset);
|
svcCloseHandle(codeset);
|
||||||
if (res >= 0)
|
if (res >= 0)
|
||||||
{
|
{
|
||||||
@ -517,7 +529,7 @@ static void handle_commands(void)
|
|||||||
case 4: // GetProgramInfo
|
case 4: // GetProgramInfo
|
||||||
{
|
{
|
||||||
prog_handle = *(u64 *)&cmdbuf[1];
|
prog_handle = *(u64 *)&cmdbuf[1];
|
||||||
if (prog_handle != g_cached_prog_handle || g_exheader.info.aci.local_caps.title_id == HBLDR_3DSX_TID)
|
if (prog_handle != g_cached_prog_handle || g_exheader.aci.local_caps.title_id == HBLDR_3DSX_TID)
|
||||||
{
|
{
|
||||||
res = loader_GetProgramInfo(&g_exheader, prog_handle);
|
res = loader_GetProgramInfo(&g_exheader, prog_handle);
|
||||||
if (res >= 0)
|
if (res >= 0)
|
||||||
@ -550,7 +562,7 @@ static Result should_terminate(int *term_request)
|
|||||||
u32 notid;
|
u32 notid;
|
||||||
Result ret;
|
Result ret;
|
||||||
|
|
||||||
ret = srvSysReceiveNotification(¬id);
|
ret = srvReceiveNotification(¬id);
|
||||||
if (R_FAILED(ret))
|
if (R_FAILED(ret))
|
||||||
{
|
{
|
||||||
return ret;
|
return ret;
|
||||||
@ -565,19 +577,36 @@ static Result should_terminate(int *term_request)
|
|||||||
// this is called before main
|
// this is called before main
|
||||||
void __appInit()
|
void __appInit()
|
||||||
{
|
{
|
||||||
srvSysInit();
|
Result res;
|
||||||
fsregInit();
|
for(res = 0xD88007FA; res == (Result)0xD88007FA; svcSleepThread(500 * 1000LL))
|
||||||
fsldrInit();
|
{
|
||||||
pxipmInit();
|
res = srvInit();
|
||||||
|
if(R_FAILED(res) && res != (Result)0xD88007FA)
|
||||||
|
svcBreak(USERBREAK_PANIC);
|
||||||
|
}
|
||||||
|
|
||||||
|
fsRegInit();
|
||||||
|
fsldrPatchPermissions();
|
||||||
|
|
||||||
|
//fsldrInit();
|
||||||
|
res = srvGetServiceHandle(fsGetSessionHandle(), "fs:LDR");
|
||||||
|
if (R_FAILED(res)) svcBreak(USERBREAK_PANIC);
|
||||||
|
res = FSUSER_InitializeWithSdkVersion(*fsGetSessionHandle(), 0x70200C8);
|
||||||
|
if (R_FAILED(res)) svcBreak(USERBREAK_PANIC);
|
||||||
|
res = FSUSER_SetPriority(0);
|
||||||
|
if (R_FAILED(res)) svcBreak(USERBREAK_PANIC);
|
||||||
|
|
||||||
|
pxiPmInit();
|
||||||
}
|
}
|
||||||
|
|
||||||
// this is called after main exits
|
// this is called after main exits
|
||||||
void __appExit()
|
void __appExit()
|
||||||
{
|
{
|
||||||
pxipmExit();
|
pxiPmExit();
|
||||||
fsldrExit();
|
//fsldrExit();
|
||||||
fsregExit();
|
svcCloseHandle(*fsGetSessionHandle());
|
||||||
srvSysExit();
|
fsRegExit();
|
||||||
|
srvExit();
|
||||||
}
|
}
|
||||||
|
|
||||||
// stubs for non-needed pre-main functions
|
// stubs for non-needed pre-main functions
|
||||||
@ -623,12 +652,12 @@ int main()
|
|||||||
srv_handle = &g_handles[1];
|
srv_handle = &g_handles[1];
|
||||||
notification_handle = &g_handles[0];
|
notification_handle = &g_handles[0];
|
||||||
|
|
||||||
if (R_FAILED(srvSysRegisterService(srv_handle, "Loader", MAX_SESSIONS)))
|
if (R_FAILED(srvRegisterService(srv_handle, "Loader", MAX_SESSIONS)))
|
||||||
{
|
{
|
||||||
svcBreak(USERBREAK_ASSERT);
|
svcBreak(USERBREAK_ASSERT);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (R_FAILED(srvSysEnableNotification(notification_handle)))
|
if (R_FAILED(srvEnableNotification(notification_handle)))
|
||||||
{
|
{
|
||||||
svcBreak(USERBREAK_ASSERT);
|
svcBreak(USERBREAK_ASSERT);
|
||||||
}
|
}
|
||||||
@ -717,7 +746,7 @@ int main()
|
|||||||
}
|
}
|
||||||
} while (!term_request || g_active_handles != 2);
|
} while (!term_request || g_active_handles != 2);
|
||||||
|
|
||||||
srvSysUnregisterService("Loader");
|
srvUnregisterService("Loader");
|
||||||
svcCloseHandle(*srv_handle);
|
svcCloseHandle(*srv_handle);
|
||||||
svcCloseHandle(*notification_handle);
|
svcCloseHandle(*notification_handle);
|
||||||
|
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
#include "patcher.h"
|
#include "patcher.h"
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
#include "strings.h"
|
#include "strings.h"
|
||||||
#include "fsldr.h"
|
|
||||||
#include "romfsredir.h"
|
#include "romfsredir.h"
|
||||||
|
|
||||||
static u32 patchMemory(u8 *start, u32 size, const void *pattern, u32 patSize, s32 offset, const void *replace, u32 repSize, u32 count)
|
static u32 patchMemory(u8 *start, u32 size, const void *pattern, u32 patSize, s32 offset, const void *replace, u32 repSize, u32 count)
|
||||||
@ -44,12 +43,12 @@ static bool dirCheck(FS_ArchiveID archiveId, const char *path)
|
|||||||
FS_Path dirPath = {PATH_ASCII, strnlen(path, 255) + 1, path},
|
FS_Path dirPath = {PATH_ASCII, strnlen(path, 255) + 1, path},
|
||||||
archivePath = {PATH_EMPTY, 1, (u8 *)""};
|
archivePath = {PATH_EMPTY, 1, (u8 *)""};
|
||||||
|
|
||||||
if(R_FAILED(FSLDR_OpenArchive(&archive, archiveId, archivePath))) ret = false;
|
if(R_FAILED(FSUSER_OpenArchive(&archive, archiveId, archivePath))) ret = false;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ret = R_SUCCEEDED(FSLDR_OpenDirectory(&handle, archive, dirPath));
|
ret = R_SUCCEEDED(FSUSER_OpenDirectory(&handle, archive, dirPath));
|
||||||
if(ret) FSDIR_Close(handle);
|
if(ret) FSDIR_Close(handle);
|
||||||
FSLDR_CloseArchive(archive);
|
FSUSER_CloseArchive(archive);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@ -356,7 +355,7 @@ error:
|
|||||||
while(true);
|
while(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool loadTitleExheader(u64 progId, ExHeader *exheader)
|
bool loadTitleExheader(u64 progId, ExHeader_Info *exheader)
|
||||||
{
|
{
|
||||||
/* Here we look for "/luma/titles/[u64 titleID in hex, uppercase]/exheader.bin"
|
/* Here we look for "/luma/titles/[u64 titleID in hex, uppercase]/exheader.bin"
|
||||||
If it exists it should be a decrypted exheader */
|
If it exists it should be a decrypted exheader */
|
||||||
@ -370,12 +369,12 @@ bool loadTitleExheader(u64 progId, ExHeader *exheader)
|
|||||||
|
|
||||||
u64 fileSize;
|
u64 fileSize;
|
||||||
|
|
||||||
if(R_FAILED(IFile_GetSize(&file, &fileSize)) || fileSize != sizeof(ExHeader)) goto error;
|
if(R_FAILED(IFile_GetSize(&file, &fileSize)) || fileSize != sizeof(ExHeader_Info) || fileSize != sizeof(ExHeader)) goto error;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
u64 total;
|
u64 total;
|
||||||
|
|
||||||
if(R_FAILED(IFile_Read(&file, &total, exheader, fileSize)) || total != fileSize) goto error;
|
if(R_FAILED(IFile_Read(&file, &total, exheader, sizeof(ExHeader_Info))) || total != sizeof(ExHeader_Info)) goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
IFile_Close(&file);
|
IFile_Close(&file);
|
||||||
|
@ -44,4 +44,4 @@ extern bool isN3DS, needToInitSd, isSdMode;
|
|||||||
void patchCode(u64 progId, u16 progVer, u8 *code, u32 size, u32 textSize, u32 roSize, u32 dataSize, u32 roAddress, u32 dataAddress);
|
void patchCode(u64 progId, u16 progVer, u8 *code, u32 size, u32 textSize, u32 roSize, u32 dataSize, u32 roAddress, u32 dataAddress);
|
||||||
Result fileOpen(IFile *file, FS_ArchiveID archiveId, const char *path, int flags);
|
Result fileOpen(IFile *file, FS_ArchiveID archiveId, const char *path, int flags);
|
||||||
bool loadTitleCodeSection(u64 progId, u8 *code, u32 size);
|
bool loadTitleCodeSection(u64 progId, u8 *code, u32 size);
|
||||||
bool loadTitleExheader(u64 progId, ExHeader *exheader);
|
bool loadTitleExheader(u64 progId, ExHeader_Info *exheader);
|
||||||
|
@ -1,74 +0,0 @@
|
|||||||
#include <3ds.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include "pxipm.h"
|
|
||||||
#include "srvsys.h"
|
|
||||||
|
|
||||||
static Handle pxipmHandle;
|
|
||||||
static int pxipmRefCount;
|
|
||||||
|
|
||||||
Result pxipmInit(void)
|
|
||||||
{
|
|
||||||
Result ret = 0;
|
|
||||||
|
|
||||||
if (AtomicPostIncrement(&pxipmRefCount)) return 0;
|
|
||||||
|
|
||||||
ret = srvSysGetServiceHandle(&pxipmHandle, "PxiPM");
|
|
||||||
|
|
||||||
if (R_FAILED(ret)) AtomicDecrement(&pxipmRefCount);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
void pxipmExit(void)
|
|
||||||
{
|
|
||||||
if (AtomicDecrement(&pxipmRefCount)) return;
|
|
||||||
svcCloseHandle(pxipmHandle);
|
|
||||||
}
|
|
||||||
|
|
||||||
Result PXIPM_RegisterProgram(u64 *prog_handle, FS_ProgramInfo *title, FS_ProgramInfo *update)
|
|
||||||
{
|
|
||||||
u32 *cmdbuf = getThreadCommandBuffer();
|
|
||||||
|
|
||||||
cmdbuf[0] = IPC_MakeHeader(0x2,8,0); // 0x20200
|
|
||||||
memcpy(&cmdbuf[1], &title->programId, sizeof(u64));
|
|
||||||
*(u8 *)&cmdbuf[3] = title->mediaType;
|
|
||||||
memcpy(((u8 *)&cmdbuf[3])+1, &title->padding, 7);
|
|
||||||
memcpy(&cmdbuf[5], &update->programId, sizeof(u64));
|
|
||||||
*(u8 *)&cmdbuf[7] = update->mediaType;
|
|
||||||
memcpy(((u8 *)&cmdbuf[7])+1, &update->padding, 7);
|
|
||||||
|
|
||||||
Result ret = 0;
|
|
||||||
if(R_FAILED(ret = svcSendSyncRequest(pxipmHandle))) return ret;
|
|
||||||
*prog_handle = *(u64*)&cmdbuf[2];
|
|
||||||
|
|
||||||
return cmdbuf[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
Result PXIPM_GetProgramInfo(ExHeader *exheader, u64 prog_handle)
|
|
||||||
{
|
|
||||||
u32 *cmdbuf = getThreadCommandBuffer();
|
|
||||||
|
|
||||||
cmdbuf[0] = IPC_MakeHeader(0x1,2,2); // 0x10082
|
|
||||||
cmdbuf[1] = (u32) (prog_handle);
|
|
||||||
cmdbuf[2] = (u32) (prog_handle >> 32);
|
|
||||||
cmdbuf[3] = (0x400 << 8) | 0x4;
|
|
||||||
cmdbuf[4] = (u32) exheader;
|
|
||||||
|
|
||||||
Result ret = 0;
|
|
||||||
if(R_FAILED(ret = svcSendSyncRequest(pxipmHandle))) return ret;
|
|
||||||
|
|
||||||
return cmdbuf[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
Result PXIPM_UnregisterProgram(u64 prog_handle)
|
|
||||||
{
|
|
||||||
u32 *cmdbuf = getThreadCommandBuffer();
|
|
||||||
|
|
||||||
cmdbuf[0] = IPC_MakeHeader(0x3,2,0); // 0x30080
|
|
||||||
cmdbuf[1] = (u32) (prog_handle);
|
|
||||||
cmdbuf[2] = (u32) (prog_handle >> 32);
|
|
||||||
|
|
||||||
Result ret = 0;
|
|
||||||
if(R_FAILED(ret = svcSendSyncRequest(pxipmHandle))) return ret;
|
|
||||||
|
|
||||||
return cmdbuf[1];
|
|
||||||
}
|
|
@ -1,10 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <3ds/types.h>
|
|
||||||
#include <3ds/exheader.h>
|
|
||||||
|
|
||||||
Result pxipmInit(void);
|
|
||||||
void pxipmExit(void);
|
|
||||||
Result PXIPM_RegisterProgram(u64 *prog_handle, FS_ProgramInfo *title, FS_ProgramInfo *update);
|
|
||||||
Result PXIPM_GetProgramInfo(ExHeader *exheader, u64 prog_handle);
|
|
||||||
Result PXIPM_UnregisterProgram(u64 prog_handle);
|
|
@ -1,154 +0,0 @@
|
|||||||
#include <3ds.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include "srvsys.h"
|
|
||||||
|
|
||||||
static Handle srvHandle;
|
|
||||||
static int srvRefCount;
|
|
||||||
static RecursiveLock initLock;
|
|
||||||
static int initLockinit = 0;
|
|
||||||
|
|
||||||
Result srvSysInit()
|
|
||||||
{
|
|
||||||
Result rc = 0;
|
|
||||||
|
|
||||||
if (!initLockinit)
|
|
||||||
{
|
|
||||||
RecursiveLock_Init(&initLock);
|
|
||||||
}
|
|
||||||
|
|
||||||
RecursiveLock_Lock(&initLock);
|
|
||||||
|
|
||||||
if (srvRefCount > 0)
|
|
||||||
{
|
|
||||||
RecursiveLock_Unlock(&initLock);
|
|
||||||
return MAKERESULT(RL_INFO, RS_NOP, 25, RD_ALREADY_INITIALIZED);
|
|
||||||
}
|
|
||||||
|
|
||||||
while (1)
|
|
||||||
{
|
|
||||||
rc = svcConnectToPort(&srvHandle, "srv:");
|
|
||||||
if (R_LEVEL(rc) != RL_PERMANENT ||
|
|
||||||
R_SUMMARY(rc) != RS_NOTFOUND ||
|
|
||||||
R_DESCRIPTION(rc) != RD_NOT_FOUND
|
|
||||||
) break;
|
|
||||||
svcSleepThread(500000);
|
|
||||||
}
|
|
||||||
if (R_SUCCEEDED(rc))
|
|
||||||
{
|
|
||||||
rc = srvSysRegisterClient();
|
|
||||||
srvRefCount++;
|
|
||||||
}
|
|
||||||
|
|
||||||
RecursiveLock_Unlock(&initLock);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
Result srvSysRegisterClient(void)
|
|
||||||
{
|
|
||||||
Result rc = 0;
|
|
||||||
u32* cmdbuf = getThreadCommandBuffer();
|
|
||||||
|
|
||||||
cmdbuf[0] = IPC_MakeHeader(0x1,0,2); // 0x10002
|
|
||||||
cmdbuf[1] = IPC_Desc_CurProcessHandle();
|
|
||||||
|
|
||||||
if(R_FAILED(rc = svcSendSyncRequest(srvHandle)))return rc;
|
|
||||||
|
|
||||||
return cmdbuf[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
Result srvSysExit()
|
|
||||||
{
|
|
||||||
Result rc;
|
|
||||||
RecursiveLock_Lock(&initLock);
|
|
||||||
|
|
||||||
if (srvRefCount > 1)
|
|
||||||
{
|
|
||||||
srvRefCount--;
|
|
||||||
RecursiveLock_Unlock(&initLock);
|
|
||||||
return MAKERESULT(RL_INFO, RS_NOP, 25, RD_BUSY);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (srvHandle != 0) svcCloseHandle(srvHandle);
|
|
||||||
else svcBreak(USERBREAK_ASSERT);
|
|
||||||
rc = (Result)srvHandle; // yeah, I think this is a benign bug
|
|
||||||
srvHandle = 0;
|
|
||||||
srvRefCount--;
|
|
||||||
RecursiveLock_Unlock(&initLock);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
Result srvSysGetServiceHandle(Handle* out, const char* name)
|
|
||||||
{
|
|
||||||
Result rc = 0;
|
|
||||||
u32* cmdbuf = getThreadCommandBuffer();
|
|
||||||
|
|
||||||
cmdbuf[0] = IPC_MakeHeader(0x5,4,0); // 0x50100
|
|
||||||
strncpy((char*) &cmdbuf[1], name,8);
|
|
||||||
cmdbuf[3] = strlen(name);
|
|
||||||
cmdbuf[4] = 0x0;
|
|
||||||
|
|
||||||
if(R_FAILED(rc = svcSendSyncRequest(srvHandle)))return rc;
|
|
||||||
|
|
||||||
if(out) *out = cmdbuf[3];
|
|
||||||
|
|
||||||
return cmdbuf[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
Result srvSysEnableNotification(Handle* semaphoreOut)
|
|
||||||
{
|
|
||||||
Result rc = 0;
|
|
||||||
u32* cmdbuf = getThreadCommandBuffer();
|
|
||||||
|
|
||||||
cmdbuf[0] = IPC_MakeHeader(0x2,0,0);
|
|
||||||
|
|
||||||
if(R_FAILED(rc = svcSendSyncRequest(srvHandle)))return rc;
|
|
||||||
|
|
||||||
if(semaphoreOut) *semaphoreOut = cmdbuf[3];
|
|
||||||
|
|
||||||
return cmdbuf[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
Result srvSysReceiveNotification(u32* notificationIdOut)
|
|
||||||
{
|
|
||||||
Result rc = 0;
|
|
||||||
u32* cmdbuf = getThreadCommandBuffer();
|
|
||||||
|
|
||||||
cmdbuf[0] = IPC_MakeHeader(0xB,0,0); // 0xB0000
|
|
||||||
|
|
||||||
if(R_FAILED(rc = svcSendSyncRequest(srvHandle)))return rc;
|
|
||||||
|
|
||||||
if(notificationIdOut) *notificationIdOut = cmdbuf[2];
|
|
||||||
|
|
||||||
return cmdbuf[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
Result srvSysRegisterService(Handle* out, const char* name, int maxSessions)
|
|
||||||
{
|
|
||||||
Result rc = 0;
|
|
||||||
u32* cmdbuf = getThreadCommandBuffer();
|
|
||||||
|
|
||||||
cmdbuf[0] = IPC_MakeHeader(0x3,4,0); // 0x30100
|
|
||||||
strncpy((char*) &cmdbuf[1], name,8);
|
|
||||||
cmdbuf[3] = strlen(name);
|
|
||||||
cmdbuf[4] = maxSessions;
|
|
||||||
|
|
||||||
if(R_FAILED(rc = svcSendSyncRequest(srvHandle)))return rc;
|
|
||||||
|
|
||||||
if(out) *out = cmdbuf[3];
|
|
||||||
|
|
||||||
return cmdbuf[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
Result srvSysUnregisterService(const char* name)
|
|
||||||
{
|
|
||||||
Result rc = 0;
|
|
||||||
u32* cmdbuf = getThreadCommandBuffer();
|
|
||||||
|
|
||||||
cmdbuf[0] = IPC_MakeHeader(0x4,3,0); // 0x400C0
|
|
||||||
strncpy((char*) &cmdbuf[1], name,8);
|
|
||||||
cmdbuf[3] = strlen(name);
|
|
||||||
|
|
||||||
if(R_FAILED(rc = svcSendSyncRequest(srvHandle)))return rc;
|
|
||||||
|
|
||||||
return cmdbuf[1];
|
|
||||||
}
|
|
@ -1,47 +0,0 @@
|
|||||||
/**
|
|
||||||
* @file srv.h
|
|
||||||
* @brief Service API.
|
|
||||||
*/
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
/// Initializes the service API.
|
|
||||||
Result srvSysInit(void);
|
|
||||||
|
|
||||||
/// Exits the service API.
|
|
||||||
Result srvSysExit(void);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Retrieves a service handle, retrieving from the environment handle list if possible.
|
|
||||||
* @param out Pointer to write the handle to.
|
|
||||||
* @param name Name of the service.
|
|
||||||
*/
|
|
||||||
Result srvSysGetServiceHandle(Handle* out, const char* name);
|
|
||||||
|
|
||||||
/// Registers the current process as a client to the service API.
|
|
||||||
Result srvSysRegisterClient(void);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Enables service notificatios, returning a notification semaphore.
|
|
||||||
* @param semaphoreOut Pointer to output the notification semaphore to.
|
|
||||||
*/
|
|
||||||
Result srvSysEnableNotification(Handle* semaphoreOut);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Receives a notification.
|
|
||||||
* @param notificationIdOut Pointer to output the ID of the received notification to.
|
|
||||||
*/
|
|
||||||
Result srvSysReceiveNotification(u32* notificationIdOut);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Registers the current process as a service.
|
|
||||||
* @param out Pointer to write the service handle to.
|
|
||||||
* @param name Name of the service.
|
|
||||||
* @param maxSessions Maximum number of sessions the service can handle.
|
|
||||||
*/
|
|
||||||
Result srvSysRegisterService(Handle* out, const char* name, int maxSessions);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Unregisters the current process as a service.
|
|
||||||
* @param name Name of the service.
|
|
||||||
*/
|
|
||||||
Result srvSysUnregisterService(const char* name);
|
|
@ -1,41 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of Luma3DS
|
|
||||||
* Copyright (C) 2016-2019 Aurora Wright, TuxSH
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* Additional Terms 7.b and 7.c of GPLv3 apply to this file:
|
|
||||||
* * Requiring preservation of specified reasonable legal notices or
|
|
||||||
* author attributions in that material or in the Appropriate Legal
|
|
||||||
* Notices displayed by works containing it.
|
|
||||||
* * Prohibiting misrepresentation of the origin of that material,
|
|
||||||
* or requiring that modified versions of such material be marked in
|
|
||||||
* reasonable ways as different from the original version.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <3ds/types.h>
|
|
||||||
#include <3ds/exheader.h>
|
|
||||||
|
|
||||||
Result fsregInit(void);
|
|
||||||
void fsregExit(void);
|
|
||||||
Result FSREG_CheckHostLoadId(u64 prog_handle);
|
|
||||||
Result FSREG_LoadProgram(u64 *prog_handle, FS_ProgramInfo *title);
|
|
||||||
Result FSREG_GetProgramInfo(ExHeader *exheader, u32 entry_count, u64 prog_handle);
|
|
||||||
Result FSREG_UnloadProgram(u64 prog_handle);
|
|
||||||
Result FSREG_Unregister(u32 pid);
|
|
||||||
Result FSREG_Register(u32 pid, u64 prog_handle, FS_ProgramInfo *info, void *storageinfo);
|
|
||||||
Result fsregSetupPermissions(void);
|
|
||||||
Handle fsregGetHandle(void);
|
|
@ -1,40 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of Luma3DS
|
|
||||||
* Copyright (C) 2016-2019 Aurora Wright, TuxSH
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* Additional Terms 7.b and 7.c of GPLv3 apply to this file:
|
|
||||||
* * Requiring preservation of specified reasonable legal notices or
|
|
||||||
* author attributions in that material or in the Appropriate Legal
|
|
||||||
* Notices displayed by works containing it.
|
|
||||||
* * Prohibiting misrepresentation of the origin of that material,
|
|
||||||
* or requiring that modified versions of such material be marked in
|
|
||||||
* reasonable ways as different from the original version.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <3ds/types.h>
|
|
||||||
|
|
||||||
#define SDK_VERSION 0x70200C8
|
|
||||||
|
|
||||||
/// Initializes the service API.
|
|
||||||
Result srvSysInit(void);
|
|
||||||
|
|
||||||
/// Exits the service API.
|
|
||||||
Result srvSysExit(void);
|
|
||||||
|
|
||||||
/// Initializes FSUSER. Requires FSREG.
|
|
||||||
void fsSysInit(void);
|
|
@ -1,181 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of Luma3DS
|
|
||||||
* Copyright (C) 2016-2019 Aurora Wright, TuxSH
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* Additional Terms 7.b and 7.c of GPLv3 apply to this file:
|
|
||||||
* * Requiring preservation of specified reasonable legal notices or
|
|
||||||
* author attributions in that material or in the Appropriate Legal
|
|
||||||
* Notices displayed by works containing it.
|
|
||||||
* * Prohibiting misrepresentation of the origin of that material,
|
|
||||||
* or requiring that modified versions of such material be marked in
|
|
||||||
* reasonable ways as different from the original version.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <3ds.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include "fsreg.h"
|
|
||||||
#include "services.h"
|
|
||||||
#include "csvc.h"
|
|
||||||
|
|
||||||
static Handle fsregHandle;
|
|
||||||
static int fsregRefCount;
|
|
||||||
|
|
||||||
Result fsregInit(void)
|
|
||||||
{
|
|
||||||
Result ret = 0;
|
|
||||||
|
|
||||||
if(AtomicPostIncrement(&fsregRefCount))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
ret = svcControlService(SERVICEOP_STEAL_CLIENT_SESSION, &fsregHandle, "fs:REG");
|
|
||||||
while(ret == 0x9401BFE)
|
|
||||||
{
|
|
||||||
svcSleepThread(500 * 1000LL);
|
|
||||||
ret = svcControlService(SERVICEOP_STEAL_CLIENT_SESSION, &fsregHandle, "fs:REG");
|
|
||||||
}
|
|
||||||
|
|
||||||
if(R_FAILED(ret))
|
|
||||||
AtomicDecrement(&fsregRefCount);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
void fsregExit(void)
|
|
||||||
{
|
|
||||||
if(AtomicDecrement(&fsregRefCount) || !fsregHandle)
|
|
||||||
return;
|
|
||||||
svcCloseHandle(fsregHandle);
|
|
||||||
}
|
|
||||||
|
|
||||||
Handle fsregGetHandle(void)
|
|
||||||
{
|
|
||||||
return fsregHandle;
|
|
||||||
}
|
|
||||||
|
|
||||||
Result fsregSetupPermissions(void)
|
|
||||||
{
|
|
||||||
u32 pid;
|
|
||||||
Result res;
|
|
||||||
FS_ProgramInfo info;
|
|
||||||
ExHeader_Arm11StorageInfo storage = {0};
|
|
||||||
|
|
||||||
// SDMC access and NAND access flags
|
|
||||||
storage.fs_access_info = FSACCESS_NANDRW | FSACCESS_NANDRO_RW |
|
|
||||||
FSACCESS_SDMC_RW | FSACCESS_CATEGORY_SYSTEM_APPLICATION;
|
|
||||||
info.programId = 0x0004013000006902LL; // Rosalina TID
|
|
||||||
info.mediaType = MEDIATYPE_NAND;
|
|
||||||
|
|
||||||
if(R_SUCCEEDED(res = svcGetProcessId(&pid, CUR_PROCESS_HANDLE))) // 0xFFFF8001 is an handle to the active process
|
|
||||||
res = FSREG_Register(pid, 0xFFFF000000000000LL, &info, &storage);
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
Result FSREG_CheckHostLoadId(u64 prog_handle)
|
|
||||||
{
|
|
||||||
u32 *cmdbuf = getThreadCommandBuffer();
|
|
||||||
|
|
||||||
cmdbuf[0] = IPC_MakeHeader(0x406,2,0); // 0x4060080
|
|
||||||
cmdbuf[1] = (u32) (prog_handle);
|
|
||||||
cmdbuf[2] = (u32) (prog_handle >> 32);
|
|
||||||
|
|
||||||
Result ret = 0;
|
|
||||||
if(R_FAILED(ret = svcSendSyncRequest(fsregHandle)))
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
return cmdbuf[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
Result FSREG_LoadProgram(u64 *prog_handle, FS_ProgramInfo *title)
|
|
||||||
{
|
|
||||||
u32 *cmdbuf = getThreadCommandBuffer();
|
|
||||||
|
|
||||||
cmdbuf[0] = IPC_MakeHeader(0x404,4,0); // 0x4040100
|
|
||||||
memcpy(&cmdbuf[1], &title->programId, sizeof(u64));
|
|
||||||
*(u8 *)&cmdbuf[3] = title->mediaType;
|
|
||||||
memcpy(((u8 *)&cmdbuf[3])+1, &title->padding, 7);
|
|
||||||
|
|
||||||
Result ret = 0;
|
|
||||||
if(R_FAILED(ret = svcSendSyncRequest(fsregHandle)))
|
|
||||||
return ret;
|
|
||||||
*prog_handle = *(u64 *)&cmdbuf[2];
|
|
||||||
|
|
||||||
return cmdbuf[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
Result FSREG_GetProgramInfo(ExHeader *exheader, u32 entry_count, u64 prog_handle)
|
|
||||||
{
|
|
||||||
u32 *cmdbuf = getThreadCommandBuffer();
|
|
||||||
|
|
||||||
cmdbuf[0] = IPC_MakeHeader(0x403,3,0); // 0x40300C0
|
|
||||||
cmdbuf[1] = entry_count;
|
|
||||||
*(u64 *)&cmdbuf[2] = prog_handle;
|
|
||||||
cmdbuf[64] = ((entry_count << 10) << 14) | 2;
|
|
||||||
cmdbuf[65] = (u32) exheader;
|
|
||||||
|
|
||||||
Result ret = 0;
|
|
||||||
if(R_FAILED(ret = svcSendSyncRequest(fsregHandle)))
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
return cmdbuf[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
Result FSREG_UnloadProgram(u64 prog_handle)
|
|
||||||
{
|
|
||||||
u32 *cmdbuf = getThreadCommandBuffer();
|
|
||||||
|
|
||||||
cmdbuf[0] = IPC_MakeHeader(0x405,2,0); // 0x4050080
|
|
||||||
cmdbuf[1] = (u32) (prog_handle);
|
|
||||||
cmdbuf[2] = (u32) (prog_handle >> 32);
|
|
||||||
|
|
||||||
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_Register(u32 pid, u64 prog_handle, FS_ProgramInfo *info, void *storageinfo)
|
|
||||||
{
|
|
||||||
u32 *cmdbuf = getThreadCommandBuffer();
|
|
||||||
|
|
||||||
cmdbuf[0] = IPC_MakeHeader(0x401,0xf,0); // 0x40103C0
|
|
||||||
cmdbuf[1] = pid;
|
|
||||||
*(u64 *)&cmdbuf[2] = prog_handle;
|
|
||||||
memcpy(&cmdbuf[4], &info->programId, sizeof(u64));
|
|
||||||
*(u8 *)&cmdbuf[6] = info->mediaType;
|
|
||||||
memcpy(((u8 *)&cmdbuf[6])+1, &info->padding, 7);
|
|
||||||
memcpy((u8 *)&cmdbuf[8], storageinfo, 32);
|
|
||||||
|
|
||||||
Result ret = 0;
|
|
||||||
if(R_FAILED(ret = svcSendSyncRequest(fsregHandle)))
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
return cmdbuf[1];
|
|
||||||
}
|
|
@ -246,21 +246,21 @@ void HBLDR_HandleCommands(void *ctx)
|
|||||||
}
|
}
|
||||||
case 4:
|
case 4:
|
||||||
{
|
{
|
||||||
if (cmdbuf[0] != IPC_MakeHeader(4, 0, 2) || cmdbuf[1] != IPC_Desc_Buffer(sizeof(ExHeader), IPC_BUFFER_RW))
|
if (cmdbuf[0] != IPC_MakeHeader(4, 0, 2) || cmdbuf[1] != IPC_Desc_Buffer(sizeof(ExHeader_Info), IPC_BUFFER_RW))
|
||||||
{
|
{
|
||||||
error(cmdbuf, 0xD9001830);
|
error(cmdbuf, 0xD9001830);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Perform ExHeader patches
|
// Perform ExHeader patches
|
||||||
ExHeader* exh = (ExHeader*)cmdbuf[2];
|
ExHeader_Info* exh = (ExHeader_Info*)cmdbuf[2];
|
||||||
memcpy(exh->info.sci.codeset_info.name, "3dsx_app", 8);
|
u32 stacksize = 4096; // 3dsx/libctru don't require anymore than this
|
||||||
exh->info.sci.codeset_info.stack_size = 0x1000; // 3dsx/libctru don't require anymore than this
|
memcpy(exh->sci.codeset_info.name, "3dsx_app", 8);
|
||||||
memset(&exh->info.sci.dependencies, 0, sizeof(exh->info.sci.dependencies));
|
memcpy(&exh->sci.codeset_info.stack_size, &stacksize, 4);
|
||||||
memcpy(exh->info.sci.dependencies, dependencyList, sizeof(dependencyList));
|
memset(&exh->sci.dependencies, 0, sizeof(exh->sci.dependencies));
|
||||||
|
memcpy(exh->sci.dependencies, dependencyList, sizeof(dependencyList));
|
||||||
|
|
||||||
ExHeader_Arm11SystemLocalCapabilities* localcaps0 = &exh->info.aci.local_caps;
|
ExHeader_Arm11SystemLocalCapabilities* localcaps0 = &exh->aci.local_caps;
|
||||||
ExHeader_Arm11SystemLocalCapabilities* localcaps1 = &exh->access_descriptor.acli.local_caps;
|
|
||||||
|
|
||||||
localcaps0->core_info.core_version = 2;
|
localcaps0->core_info.core_version = 2;
|
||||||
localcaps0->core_info.use_cpu_clockrate_804MHz = false;
|
localcaps0->core_info.use_cpu_clockrate_804MHz = false;
|
||||||
@ -271,65 +271,41 @@ void HBLDR_HandleCommands(void *ctx)
|
|||||||
localcaps0->core_info.o3ds_system_mode = SYSMODE_O3DS_PROD;
|
localcaps0->core_info.o3ds_system_mode = SYSMODE_O3DS_PROD;
|
||||||
localcaps0->core_info.priority = 0x30;
|
localcaps0->core_info.priority = 0x30;
|
||||||
|
|
||||||
localcaps1->core_info.core_version = 2;
|
|
||||||
localcaps1->core_info.use_cpu_clockrate_804MHz = false;
|
|
||||||
localcaps1->core_info.enable_l2c = false;
|
|
||||||
localcaps1->core_info.n3ds_system_mode = SYSMODE_N3DS_PROD;
|
|
||||||
localcaps1->core_info.ideal_processor = BIT(0); // Intended, this is an oddity of the ExHeader
|
|
||||||
localcaps1->core_info.affinity_mask = BIT(0);
|
|
||||||
localcaps1->core_info.o3ds_system_mode = SYSMODE_O3DS_PROD;
|
|
||||||
localcaps1->core_info.priority = 0; // Intended
|
|
||||||
|
|
||||||
memset(localcaps0->reslimits, 0, sizeof(localcaps0->reslimits));
|
memset(localcaps0->reslimits, 0, sizeof(localcaps0->reslimits));
|
||||||
memset(localcaps1->reslimits, 0, sizeof(localcaps0->reslimits));
|
|
||||||
|
|
||||||
localcaps0->reslimits[0] = 0x9E; // Stuff needed to run stuff on core1
|
localcaps0->reslimits[0] = 0x9E; // Stuff needed to run stuff on core1
|
||||||
localcaps1->reslimits[1] = 0x9E;
|
|
||||||
|
|
||||||
localcaps0->storage_info.fs_access_info = 0xFFFFFFFF; // Give access to everything
|
localcaps0->storage_info.fs_access_info = 0xFFFFFFFF; // Give access to everything
|
||||||
localcaps0->storage_info.no_romfs = true;
|
localcaps0->storage_info.no_romfs = true;
|
||||||
localcaps0->storage_info.use_extended_savedata_access = true; // Whatever
|
localcaps0->storage_info.use_extended_savedata_access = true; // Whatever
|
||||||
|
|
||||||
localcaps1->storage_info.fs_access_info = 0xFFFFFFFF; // Give access to everything
|
|
||||||
localcaps0->storage_info.no_romfs = true;
|
|
||||||
localcaps0->storage_info.use_extended_savedata_access = true; // Whatever
|
|
||||||
|
|
||||||
/* We have a patched SM, so whatever... */
|
/* We have a patched SM, so whatever... */
|
||||||
memset(localcaps0->service_access, 0, sizeof(localcaps0->service_access));
|
memset(localcaps0->service_access, 0, sizeof(localcaps0->service_access));
|
||||||
memcpy(localcaps0->service_access, serviceList, sizeof(serviceList));
|
memcpy(localcaps0->service_access, serviceList, sizeof(serviceList));
|
||||||
|
|
||||||
memset(localcaps1->service_access, 0, sizeof(localcaps0->service_access));
|
|
||||||
memcpy(localcaps1->service_access, serviceList, sizeof(serviceList));
|
|
||||||
|
|
||||||
localcaps0->reslimit_category = RESLIMIT_CATEGORY_APPLICATION;
|
localcaps0->reslimit_category = RESLIMIT_CATEGORY_APPLICATION;
|
||||||
localcaps1->reslimit_category = RESLIMIT_CATEGORY_APPLICATION;
|
|
||||||
|
|
||||||
ExHeader_Arm11KernelCapabilities* kcaps0 = &exh->info.aci.kernel_caps;
|
ExHeader_Arm11KernelCapabilities* kcaps0 = &exh->aci.kernel_caps;
|
||||||
ExHeader_Arm11KernelCapabilities* kcaps1 = &exh->access_descriptor.acli.kernel_caps;
|
|
||||||
memset(kcaps0->descriptors, 0xFF, sizeof(kcaps0->descriptors));
|
memset(kcaps0->descriptors, 0xFF, sizeof(kcaps0->descriptors));
|
||||||
memset(kcaps1->descriptors, 0xFF, sizeof(kcaps1->descriptors));
|
|
||||||
memcpy(kcaps0->descriptors, kernelCaps, sizeof(kernelCaps));
|
memcpy(kcaps0->descriptors, kernelCaps, sizeof(kernelCaps));
|
||||||
memcpy(kcaps1->descriptors, kernelCaps, sizeof(kernelCaps));
|
|
||||||
|
|
||||||
u64 lastdep = sizeof(dependencyList)/8;
|
u64 lastdep = sizeof(dependencyList)/8;
|
||||||
if (osGetFirmVersion() >= SYSTEM_VERSION(2,50,0)) // 9.6+ FIRM
|
if (osGetFirmVersion() >= SYSTEM_VERSION(2,50,0)) // 9.6+ FIRM
|
||||||
{
|
{
|
||||||
exh->info.sci.dependencies[lastdep++] = 0x0004013000004002ULL; // nfc
|
exh->sci.dependencies[lastdep++] = 0x0004013000004002ULL; // nfc
|
||||||
strncpy((char*)&localcaps0->service_access[0x20], "nfc:u", 8);
|
strncpy((char*)&localcaps0->service_access[0x20], "nfc:u", 8);
|
||||||
strncpy((char*)&localcaps1->service_access[0x20], "nfc:u", 8);
|
|
||||||
s64 dummy = 0;
|
s64 dummy = 0;
|
||||||
bool isN3DS = svcGetSystemInfo(&dummy, 0x10001, 0) == 0;
|
bool isN3DS = svcGetSystemInfo(&dummy, 0x10001, 0) == 0;
|
||||||
if (isN3DS)
|
if (isN3DS)
|
||||||
{
|
{
|
||||||
exh->info.sci.dependencies[lastdep++] = 0x0004013020004102ULL; // mvd
|
exh->sci.dependencies[lastdep++] = 0x0004013020004102ULL; // mvd
|
||||||
strncpy((char*)&localcaps0->service_access[0x21], "mvd:STD", 8);
|
strncpy((char*)&localcaps0->service_access[0x21], "mvd:STD", 8);
|
||||||
strncpy((char*)&localcaps1->service_access[0x21], "mvd:STD", 8);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cmdbuf[0] = IPC_MakeHeader(4, 1, 2);
|
cmdbuf[0] = IPC_MakeHeader(4, 1, 2);
|
||||||
cmdbuf[1] = 0;
|
cmdbuf[1] = 0;
|
||||||
cmdbuf[2] = IPC_Desc_Buffer(sizeof(ExHeader), IPC_BUFFER_RW);
|
cmdbuf[2] = IPC_Desc_Buffer(sizeof(ExHeader_Info), IPC_BUFFER_RW);
|
||||||
cmdbuf[3] = (u32)exh;
|
cmdbuf[3] = (u32)exh;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -26,8 +26,6 @@
|
|||||||
|
|
||||||
#include <3ds.h>
|
#include <3ds.h>
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
#include "services.h"
|
|
||||||
#include "fsreg.h"
|
|
||||||
#include "menu.h"
|
#include "menu.h"
|
||||||
#include "service_manager.h"
|
#include "service_manager.h"
|
||||||
#include "errdisp.h"
|
#include "errdisp.h"
|
||||||
@ -40,22 +38,61 @@
|
|||||||
#include "menus/screen_filters.h"
|
#include "menus/screen_filters.h"
|
||||||
#include "shell_open.h"
|
#include "shell_open.h"
|
||||||
|
|
||||||
|
static Result stealFsReg(void)
|
||||||
|
{
|
||||||
|
Result ret = 0;
|
||||||
|
|
||||||
|
ret = svcControlService(SERVICEOP_STEAL_CLIENT_SESSION, fsRegGetSessionHandle(), "fs:REG");
|
||||||
|
while(ret == 0x9401BFE)
|
||||||
|
{
|
||||||
|
svcSleepThread(500 * 1000LL);
|
||||||
|
ret = svcControlService(SERVICEOP_STEAL_CLIENT_SESSION, fsRegGetSessionHandle(), "fs:REG");
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Result fsRegSetupPermissions(void)
|
||||||
|
{
|
||||||
|
u32 pid;
|
||||||
|
Result res;
|
||||||
|
FS_ProgramInfo info;
|
||||||
|
|
||||||
|
ExHeader_Arm11StorageInfo storageInfo = {
|
||||||
|
.fs_access_info = FSACCESS_NANDRO_RW | FSACCESS_NANDRW | FSACCESS_SDMC_RW,
|
||||||
|
};
|
||||||
|
|
||||||
|
info.programId = 0x0004013000006902LL; // Rosalina TID
|
||||||
|
info.mediaType = MEDIATYPE_NAND;
|
||||||
|
|
||||||
|
if(R_SUCCEEDED(res = svcGetProcessId(&pid, CUR_PROCESS_HANDLE)))
|
||||||
|
res = FSREG_Register(pid, 0xFFFF000000000000LL, &info, &storageInfo);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
// this is called before main
|
// this is called before main
|
||||||
bool isN3DS;
|
bool isN3DS;
|
||||||
void __appInit()
|
void __appInit()
|
||||||
{
|
{
|
||||||
srvSysInit();
|
Result res;
|
||||||
fsregInit();
|
for(res = 0xD88007FA; res == (Result)0xD88007FA; svcSleepThread(500 * 1000LL))
|
||||||
|
{
|
||||||
|
res = srvInit();
|
||||||
|
if(R_FAILED(res) && res != (Result)0xD88007FA)
|
||||||
|
svcBreak(USERBREAK_PANIC);
|
||||||
|
}
|
||||||
|
|
||||||
fsSysInit();
|
if (R_FAILED(stealFsReg()) || R_FAILED(fsRegSetupPermissions()) || R_FAILED(fsInit()))
|
||||||
|
svcBreak(USERBREAK_PANIC);
|
||||||
}
|
}
|
||||||
|
|
||||||
// this is called after main exits
|
// this is called after main exits
|
||||||
void __appExit()
|
void __appExit()
|
||||||
{
|
{
|
||||||
fsExit();
|
fsExit();
|
||||||
fsregExit();
|
svcCloseHandle(*fsRegGetSessionHandle());
|
||||||
srvSysExit();
|
srvExit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@ static Result SOCU_Initialize(Handle memhandle, u32 memsize)
|
|||||||
|
|
||||||
cmdbuf[0] = IPC_MakeHeader(0x1,1,4); // 0x10044
|
cmdbuf[0] = IPC_MakeHeader(0x1,1,4); // 0x10044
|
||||||
cmdbuf[1] = memsize;
|
cmdbuf[1] = memsize;
|
||||||
cmdbuf[2] = IPC_Desc_CurProcessHandle();
|
cmdbuf[2] = IPC_Desc_CurProcessId();
|
||||||
cmdbuf[4] = IPC_Desc_SharedHandles(1);
|
cmdbuf[4] = IPC_Desc_SharedHandles(1);
|
||||||
cmdbuf[5] = memhandle;
|
cmdbuf[5] = memhandle;
|
||||||
|
|
||||||
@ -180,7 +180,7 @@ int socSocket(int domain, int type, int protocol)
|
|||||||
cmdbuf[1] = domain;
|
cmdbuf[1] = domain;
|
||||||
cmdbuf[2] = type;
|
cmdbuf[2] = type;
|
||||||
cmdbuf[3] = protocol;
|
cmdbuf[3] = protocol;
|
||||||
cmdbuf[4] = IPC_Desc_CurProcessHandle();
|
cmdbuf[4] = IPC_Desc_CurProcessId();
|
||||||
|
|
||||||
ret = svcSendSyncRequest(SOCU_handle);
|
ret = svcSendSyncRequest(SOCU_handle);
|
||||||
if(ret != 0)
|
if(ret != 0)
|
||||||
@ -228,7 +228,7 @@ int socBind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
|
|||||||
cmdbuf[0] = IPC_MakeHeader(0x5,2,4); // 0x50084
|
cmdbuf[0] = IPC_MakeHeader(0x5,2,4); // 0x50084
|
||||||
cmdbuf[1] = (u32)sockfd;
|
cmdbuf[1] = (u32)sockfd;
|
||||||
cmdbuf[2] = (u32)tmp_addrlen;
|
cmdbuf[2] = (u32)tmp_addrlen;
|
||||||
cmdbuf[3] = IPC_Desc_CurProcessHandle();
|
cmdbuf[3] = IPC_Desc_CurProcessId();
|
||||||
cmdbuf[5] = IPC_Desc_StaticBuffer(tmp_addrlen,0);
|
cmdbuf[5] = IPC_Desc_StaticBuffer(tmp_addrlen,0);
|
||||||
cmdbuf[6] = (u32)tmpaddr;
|
cmdbuf[6] = (u32)tmpaddr;
|
||||||
|
|
||||||
@ -258,7 +258,7 @@ int socListen(int sockfd, int max_connections)
|
|||||||
cmdbuf[0] = IPC_MakeHeader(0x3,2,2); // 0x30082
|
cmdbuf[0] = IPC_MakeHeader(0x3,2,2); // 0x30082
|
||||||
cmdbuf[1] = (u32)sockfd;
|
cmdbuf[1] = (u32)sockfd;
|
||||||
cmdbuf[2] = (u32)max_connections;
|
cmdbuf[2] = (u32)max_connections;
|
||||||
cmdbuf[3] = IPC_Desc_CurProcessHandle();
|
cmdbuf[3] = IPC_Desc_CurProcessId();
|
||||||
|
|
||||||
ret = svcSendSyncRequest(SOCU_handle);
|
ret = svcSendSyncRequest(SOCU_handle);
|
||||||
if(ret != 0)
|
if(ret != 0)
|
||||||
@ -293,7 +293,7 @@ int socAccept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
|
|||||||
cmdbuf[0] = IPC_MakeHeader(0x4,2,2); // 0x40082
|
cmdbuf[0] = IPC_MakeHeader(0x4,2,2); // 0x40082
|
||||||
cmdbuf[1] = (u32)sockfd;
|
cmdbuf[1] = (u32)sockfd;
|
||||||
cmdbuf[2] = (u32)tmp_addrlen;
|
cmdbuf[2] = (u32)tmp_addrlen;
|
||||||
cmdbuf[3] = IPC_Desc_CurProcessHandle();
|
cmdbuf[3] = IPC_Desc_CurProcessId();
|
||||||
|
|
||||||
u32 *staticbufs = getThreadStaticBuffers();
|
u32 *staticbufs = getThreadStaticBuffers();
|
||||||
saved_threadstorage[0] = staticbufs[0];
|
saved_threadstorage[0] = staticbufs[0];
|
||||||
@ -350,7 +350,7 @@ int socPoll(struct pollfd *fds, nfds_t nfds, int timeout)
|
|||||||
cmdbuf[0] = IPC_MakeHeader(0x14,2,4); // 0x140084
|
cmdbuf[0] = IPC_MakeHeader(0x14,2,4); // 0x140084
|
||||||
cmdbuf[1] = (u32)nfds;
|
cmdbuf[1] = (u32)nfds;
|
||||||
cmdbuf[2] = (u32)timeout;
|
cmdbuf[2] = (u32)timeout;
|
||||||
cmdbuf[3] = IPC_Desc_CurProcessHandle();
|
cmdbuf[3] = IPC_Desc_CurProcessId();
|
||||||
cmdbuf[5] = IPC_Desc_StaticBuffer(size,10);
|
cmdbuf[5] = IPC_Desc_StaticBuffer(size,10);
|
||||||
cmdbuf[6] = (u32)fds;
|
cmdbuf[6] = (u32)fds;
|
||||||
|
|
||||||
@ -389,7 +389,7 @@ int socClose(int sockfd)
|
|||||||
|
|
||||||
cmdbuf[0] = IPC_MakeHeader(0xB,1,2); // 0xB0042
|
cmdbuf[0] = IPC_MakeHeader(0xB,1,2); // 0xB0042
|
||||||
cmdbuf[1] = (u32)sockfd;
|
cmdbuf[1] = (u32)sockfd;
|
||||||
cmdbuf[2] = IPC_Desc_CurProcessHandle();
|
cmdbuf[2] = IPC_Desc_CurProcessId();
|
||||||
|
|
||||||
ret = svcSendSyncRequest(SOCU_handle);
|
ret = svcSendSyncRequest(SOCU_handle);
|
||||||
if(ret != 0) {
|
if(ret != 0) {
|
||||||
@ -419,7 +419,7 @@ int socSetsockopt(int sockfd, int level, int optname, const void *optval, sockle
|
|||||||
cmdbuf[2] = (u32)level;
|
cmdbuf[2] = (u32)level;
|
||||||
cmdbuf[3] = (u32)optname;
|
cmdbuf[3] = (u32)optname;
|
||||||
cmdbuf[4] = (u32)optlen;
|
cmdbuf[4] = (u32)optlen;
|
||||||
cmdbuf[5] = IPC_Desc_CurProcessHandle();
|
cmdbuf[5] = IPC_Desc_CurProcessId();
|
||||||
cmdbuf[7] = IPC_Desc_StaticBuffer(optlen,9);
|
cmdbuf[7] = IPC_Desc_StaticBuffer(optlen,9);
|
||||||
cmdbuf[8] = (u32)optval;
|
cmdbuf[8] = (u32)optval;
|
||||||
|
|
||||||
|
@ -1,108 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of Luma3DS
|
|
||||||
* Copyright (C) 2016-2019 Aurora Wright, TuxSH
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* Additional Terms 7.b and 7.c of GPLv3 apply to this file:
|
|
||||||
* * Requiring preservation of specified reasonable legal notices or
|
|
||||||
* author attributions in that material or in the Appropriate Legal
|
|
||||||
* Notices displayed by works containing it.
|
|
||||||
* * Prohibiting misrepresentation of the origin of that material,
|
|
||||||
* or requiring that modified versions of such material be marked in
|
|
||||||
* reasonable ways as different from the original version.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <3ds.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include "fsreg.h"
|
|
||||||
#include "services.h"
|
|
||||||
|
|
||||||
static Handle *srvHandlePtr;
|
|
||||||
static int srvRefCount;
|
|
||||||
static RecursiveLock initLock;
|
|
||||||
static int initLockinit = 0;
|
|
||||||
|
|
||||||
Result srvSysInit(void)
|
|
||||||
{
|
|
||||||
Result rc = 0;
|
|
||||||
|
|
||||||
if (!initLockinit)
|
|
||||||
RecursiveLock_Init(&initLock);
|
|
||||||
|
|
||||||
RecursiveLock_Lock(&initLock);
|
|
||||||
|
|
||||||
if (srvRefCount > 0)
|
|
||||||
{
|
|
||||||
RecursiveLock_Unlock(&initLock);
|
|
||||||
return MAKERESULT(RL_INFO, RS_NOP, 25, RD_ALREADY_INITIALIZED);
|
|
||||||
}
|
|
||||||
|
|
||||||
srvHandlePtr = srvGetSessionHandle();
|
|
||||||
|
|
||||||
while(1)
|
|
||||||
{
|
|
||||||
rc = svcConnectToPort(srvHandlePtr, "srv:");
|
|
||||||
if (R_LEVEL(rc) != RL_PERMANENT ||
|
|
||||||
R_SUMMARY(rc) != RS_NOTFOUND ||
|
|
||||||
R_DESCRIPTION(rc) != RD_NOT_FOUND
|
|
||||||
) break;
|
|
||||||
svcSleepThread(500 * 1000LL);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(R_SUCCEEDED(rc))
|
|
||||||
{
|
|
||||||
rc = srvRegisterClient();
|
|
||||||
srvRefCount++;
|
|
||||||
}
|
|
||||||
|
|
||||||
RecursiveLock_Unlock(&initLock);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
Result srvSysExit(void)
|
|
||||||
{
|
|
||||||
Result rc = 0;
|
|
||||||
RecursiveLock_Lock(&initLock);
|
|
||||||
|
|
||||||
if(srvRefCount > 1)
|
|
||||||
{
|
|
||||||
srvRefCount--;
|
|
||||||
RecursiveLock_Unlock(&initLock);
|
|
||||||
return MAKERESULT(RL_INFO, RS_NOP, 25, RD_BUSY);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(srvHandlePtr != 0)
|
|
||||||
svcCloseHandle(*srvHandlePtr);
|
|
||||||
else
|
|
||||||
svcBreak(USERBREAK_ASSERT);
|
|
||||||
|
|
||||||
srvHandlePtr = 0;
|
|
||||||
srvRefCount--;
|
|
||||||
|
|
||||||
RecursiveLock_Unlock(&initLock);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
void fsSysInit(void)
|
|
||||||
{
|
|
||||||
if(R_FAILED(fsregSetupPermissions()))
|
|
||||||
svcBreak(USERBREAK_ASSERT);
|
|
||||||
|
|
||||||
Handle *fsHandlePtr = fsGetSessionHandle();
|
|
||||||
srvGetServiceHandle(fsHandlePtr, "fs:USER");
|
|
||||||
|
|
||||||
FSUSER_InitializeWithSdkVersion(*fsHandlePtr, SDK_VERSION);
|
|
||||||
FSUSER_SetPriority(0);
|
|
||||||
}
|
|
@ -19,7 +19,7 @@ Result srvHandleCommands(SessionData *sessionData)
|
|||||||
{
|
{
|
||||||
case 1: // RegisterClient
|
case 1: // RegisterClient
|
||||||
{
|
{
|
||||||
if(cmdbuf[0] == IPC_MakeHeader(1, 0, 2) && cmdbuf[1] == IPC_Desc_CurProcessHandle())
|
if(cmdbuf[0] == IPC_MakeHeader(1, 0, 2) && cmdbuf[1] == IPC_Desc_CurProcessId())
|
||||||
{
|
{
|
||||||
sessionData->pid = cmdbuf[2];
|
sessionData->pid = cmdbuf[2];
|
||||||
cmdbuf[0] = IPC_MakeHeader(1, 1, 0);
|
cmdbuf[0] = IPC_MakeHeader(1, 1, 0);
|
||||||
|
Reference in New Issue
Block a user