ldr: update for new-ipc

This commit is contained in:
Michael Scire 2019-10-19 00:10:45 -07:00 committed by fincs
parent a3e7b1affb
commit 9e2df3ad53
No known key found for this signature in database
GPG Key ID: 62C7609ADA219C60
2 changed files with 56 additions and 295 deletions

View File

@ -6,7 +6,7 @@
*/ */
#pragma once #pragma once
#include "../types.h" #include "../types.h"
#include "../services/sm.h" #include "../sf/service.h"
#include "../services/fs.h" #include "../services/fs.h"
typedef struct { typedef struct {

View File

@ -1,334 +1,95 @@
// Copyright 2018 SciresM #define NX_SERVICE_ASSUME_NON_DOMAIN
#include <string.h> #include "service_guard.h"
#include "types.h" #include "runtime/hosversion.h"
#include "result.h"
#include "arm/atomics.h"
#include "kernel/ipc.h"
#include "services/ldr.h" #include "services/ldr.h"
#include "services/fs.h"
#include "services/sm.h"
static Service g_shellSrv, g_dmntSrv, g_pmSrv; #define LDR_GENERATE_SERVICE_INIT(name, srvname) \
static u64 g_shellRefCnt, g_dmntRefCnt, g_pmRefCnt; static Service g_ldr##name##Srv; \
\
/* Service init/exit helpers. */ NX_GENERATE_SERVICE_GUARD(ldr##name); \
static Result _ldrSrvInitialize(Service* srv, u64 *refcnt, const char *name) { \
atomicIncrement64(refcnt); Result _ldr##name##Initialize(void) { \
return smGetService(&g_ldr##name##Srv, "ldr:"#srvname); \
if (serviceIsActive(srv)) } \
return 0; \
void _ldr##name##Cleanup(void) { \
return smGetService(srv, name); serviceClose(&g_ldr##name##Srv); \
} \
\
Service* ldr##name##GetServiceSession(void) { \
return &g_ldr##name##Srv; \
} }
static void _ldrSrvExit(Service* srv, u64 *refcnt) { LDR_GENERATE_SERVICE_INIT(Shell, shel);
if (atomicDecrement64(refcnt) == 0) LDR_GENERATE_SERVICE_INIT(Dmnt, dmnt);
serviceClose(srv); LDR_GENERATE_SERVICE_INIT(Pm, pm);
NX_INLINE Result _ldrAddTitleToLaunchQueue(Service* srv, u64 tid, const void *args, size_t args_size) {
return serviceDispatchIn(srv, 0, tid,
.buffer_attrs = { SfBufferAttr_In | SfBufferAttr_HipcPointer },
.buffers = { { args, args_size } },
);
} }
Result ldrShellInitialize(void) { NX_INLINE Result _ldrClearLaunchQueue(Service* srv) {
return _ldrSrvInitialize(&g_shellSrv, &g_shellRefCnt, "ldr:shel"); return serviceDispatch(srv, 1);
}
void ldrShellExit(void) {
return _ldrSrvExit(&g_shellSrv, &g_shellRefCnt);
}
Service* ldrShellGetServiceSession(void) {
return &g_shellSrv;
}
Result ldrDmntInitialize(void) {
return _ldrSrvInitialize(&g_dmntSrv, &g_dmntRefCnt, "ldr:dmnt");
}
void ldrDmntExit(void) {
return _ldrSrvExit(&g_dmntSrv, &g_dmntRefCnt);
}
Service* ldrDmntGetServiceSession(void) {
return &g_dmntSrv;
}
Result ldrPmInitialize(void) {
return _ldrSrvInitialize(&g_pmSrv, &g_pmRefCnt, "ldr:pm");
}
void ldrPmExit(void) {
return _ldrSrvExit(&g_pmSrv, &g_pmRefCnt);
}
Service* ldrPmGetServiceSession(void) {
return &g_pmSrv;
}
static Result _ldrAddTitleToLaunchQueue(Service* srv, u64 tid, const void *args, size_t args_size) {
IpcCommand c;
ipcInitialize(&c);
ipcAddSendStatic(&c, args, args_size, 0);
struct {
u64 magic;
u64 cmd_id;
u64 tid;
} *raw;
raw = ipcPrepareHeader(&c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 0;
raw->tid = tid;
Result rc = serviceIpcDispatch(srv);
if (R_SUCCEEDED(rc)) {
IpcParsedCommand r;
ipcParse(&r);
struct {
u64 magic;
u64 result;
} *resp = r.Raw;
rc = resp->result;
}
return rc;
}
static Result _ldrClearLaunchQueue(Service* srv) {
IpcCommand c;
ipcInitialize(&c);
struct {
u64 magic;
u64 cmd_id;
} *raw;
raw = ipcPrepareHeader(&c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 1;
Result rc = serviceIpcDispatch(srv);
if (R_SUCCEEDED(rc)) {
IpcParsedCommand r;
ipcParse(&r);
struct {
u64 magic;
u64 result;
} *resp = r.Raw;
rc = resp->result;
}
return rc;
} }
Result ldrShellAddTitleToLaunchQueue(u64 tid, const void *args, size_t args_size) { Result ldrShellAddTitleToLaunchQueue(u64 tid, const void *args, size_t args_size) {
return _ldrAddTitleToLaunchQueue(&g_shellSrv, tid, args, args_size); return _ldrAddTitleToLaunchQueue(&g_ldrShellSrv, tid, args, args_size);
} }
Result ldrShellClearLaunchQueue(void) { Result ldrShellClearLaunchQueue(void) {
return _ldrClearLaunchQueue(&g_shellSrv); return _ldrClearLaunchQueue(&g_ldrShellSrv);
} }
Result ldrDmntAddTitleToLaunchQueue(u64 tid, const void *args, size_t args_size) { Result ldrDmntAddTitleToLaunchQueue(u64 tid, const void *args, size_t args_size) {
return _ldrAddTitleToLaunchQueue(&g_dmntSrv, tid, args, args_size); return _ldrAddTitleToLaunchQueue(&g_ldrDmntSrv, tid, args, args_size);
} }
Result ldrDmntClearLaunchQueue(void) { Result ldrDmntClearLaunchQueue(void) {
return _ldrClearLaunchQueue(&g_dmntSrv); return _ldrClearLaunchQueue(&g_ldrDmntSrv);
} }
Result ldrDmntGetModuleInfos(u64 pid, LoaderModuleInfo *out_module_infos, size_t max_out_modules, u32 *num_out) { Result ldrDmntGetModuleInfos(u64 pid, LoaderModuleInfo *out_module_infos, size_t max_out_modules, u32 *num_out) {
IpcCommand c; return serviceDispatchInOut(&g_ldrDmntSrv, 2, pid, *num_out,
ipcInitialize(&c); .buffer_attrs = { SfBufferAttr_Out | SfBufferAttr_HipcPointer },
.buffers = { { out_module_infos, max_out_modules * sizeof(*out_module_infos) } },
ipcAddRecvStatic(&c, out_module_infos, max_out_modules * sizeof(*out_module_infos), 0); );
struct {
u64 magic;
u64 cmd_id;
u64 pid;
} *raw;
raw = ipcPrepareHeader(&c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 2;
raw->pid = pid;
Result rc = serviceIpcDispatch(&g_dmntSrv);
if (R_SUCCEEDED(rc)) {
IpcParsedCommand r;
ipcParse(&r);
struct {
u64 magic;
u64 result;
u32 num_out;
} *resp = r.Raw;
rc = resp->result;
if (R_SUCCEEDED(rc) && num_out != NULL) {
*num_out = resp->num_out;
}
}
return rc;
} }
Result ldrPmCreateProcess(u64 flags, u64 launch_index, Handle reslimit_h, Handle *out_process_h) { Result ldrPmCreateProcess(u64 flags, u64 launch_index, Handle reslimit_h, Handle *out_process_h) {
IpcCommand c; const struct {
ipcInitialize(&c);
ipcSendHandleCopy(&c, reslimit_h);
struct {
u64 magic;
u64 cmd_id;
u64 flags; u64 flags;
u64 launch_index; u64 launch_index;
} *raw; } in = { flags, launch_index };
return serviceDispatchIn(&g_ldrPmSrv, 0, in,
raw = ipcPrepareHeader(&c, sizeof(*raw)); .in_num_handles = 1,
.in_handles = { reslimit_h },
raw->magic = SFCI_MAGIC; .out_handle_attrs = { SfOutHandleAttr_HipcMove },
raw->cmd_id = 0; .out_handles = out_process_h,
raw->flags = flags; );
raw->launch_index = launch_index;
Result rc = serviceIpcDispatch(&g_pmSrv);
if (R_SUCCEEDED(rc)) {
IpcParsedCommand r;
ipcParse(&r);
struct {
u64 magic;
u64 result;
} *resp = r.Raw;
rc = resp->result;
if (R_SUCCEEDED(rc)) {
*out_process_h = r.Handles[0];
}
}
return rc;
} }
Result ldrPmGetProgramInfo(u64 title_id, FsStorageId storage_id, LoaderProgramInfo *out_program_info) { Result ldrPmGetProgramInfo(u64 title_id, FsStorageId storage_id, LoaderProgramInfo *out_program_info) {
IpcCommand c; const struct {
ipcInitialize(&c);
ipcAddRecvStatic(&c, out_program_info, sizeof(LoaderProgramInfo), 0);
struct {
u64 magic;
u64 cmd_id;
u64 title_id; u64 title_id;
u64 storage_id; u64 storage_id;
} *raw; } in = { title_id, storage_id };
return serviceDispatchIn(&g_ldrPmSrv, 1, in,
raw = ipcPrepareHeader(&c, sizeof(*raw)); .buffer_attrs = { SfBufferAttr_Out | SfBufferAttr_HipcPointer | SfBufferAttr_FixedSize },
.buffers = { { out_program_info, sizeof(*out_program_info) } },
raw->magic = SFCI_MAGIC; );
raw->cmd_id = 1;
raw->title_id = title_id;
raw->storage_id = storage_id;
Result rc = serviceIpcDispatch(&g_pmSrv);
if (R_SUCCEEDED(rc)) {
IpcParsedCommand r;
ipcParse(&r);
struct {
u64 magic;
u64 result;
} *resp = r.Raw;
rc = resp->result;
}
return rc;
} }
Result ldrPmRegisterTitle(u64 title_id, FsStorageId storage_id, u64 *out_index) { Result ldrPmRegisterTitle(u64 title_id, FsStorageId storage_id, u64 *out_index) {
IpcCommand c; const struct {
ipcInitialize(&c);
struct {
u64 magic;
u64 cmd_id;
u64 title_id; u64 title_id;
u64 storage_id; u64 storage_id;
} *raw; } in = { title_id, storage_id };
return serviceDispatchInOut(&g_ldrPmSrv, 2, in, *out_index);
raw = ipcPrepareHeader(&c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 2;
raw->title_id = title_id;
raw->storage_id = storage_id;
Result rc = serviceIpcDispatch(&g_pmSrv);
if (R_SUCCEEDED(rc)) {
IpcParsedCommand r;
ipcParse(&r);
struct {
u64 magic;
u64 result;
u64 index;
} *resp = r.Raw;
rc = resp->result;
if (R_SUCCEEDED(rc)) {
*out_index = resp->index;
}
}
return rc;
} }
Result ldrPmUnregisterTitle(u64 launch_index) { Result ldrPmUnregisterTitle(u64 launch_index) {
IpcCommand c; return serviceDispatchIn(&g_ldrPmSrv, 3, launch_index);
ipcInitialize(&c);
struct {
u64 magic;
u64 cmd_id;
u64 launch_index;
} *raw;
raw = ipcPrepareHeader(&c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 3;
raw->launch_index = launch_index;
Result rc = serviceIpcDispatch(&g_pmSrv);
if (R_SUCCEEDED(rc)) {
IpcParsedCommand r;
ipcParse(&r);
struct {
u64 magic;
u64 result;
} *resp = r.Raw;
rc = resp->result;
}
return rc;
} }