diff --git a/nx/include/switch/services/ns.h b/nx/include/switch/services/ns.h index 2fc96ec1..372f0299 100644 --- a/nx/include/switch/services/ns.h +++ b/nx/include/switch/services/ns.h @@ -41,18 +41,8 @@ typedef struct { u8 storageID; u8 index; u8 is_application; - u8 padding[1]; } NsLaunchProperties; -typedef enum { - NsLaunchFlag_SignalOnExit = (1 << 0), - NsLaunchFlag_SignalOnStart = (1 << 1), - NsLaunchFlag_SignalOnCrash = (1 << 2), - NsLaunchFlag_SignalOnDebug = (1 << 3), - NsLaunchFlag_StartSuspended = (1 << 4), - NsLaunchFlag_DisableAslr = (1 << 5), -} NsLaunchFlag; - typedef enum { NsShellEvent_None = 0, NsShellEvent_Exit = 1, @@ -62,7 +52,7 @@ typedef enum { } NsShellEvent; typedef struct { - NsShellEvent event : 32; + NsShellEvent event; u64 process_id; } NsShellEventInfo; @@ -97,10 +87,10 @@ Result nsvmGetSafeSystemVersion(u16 *out); Result nsdevInitialize(void); void nsdevExit(void); -Result nsdevLaunchProgram(u64* out_pid, NsLaunchProperties* properties, u32 flags); +Result nsdevLaunchProgram(u64* out_pid, const NsLaunchProperties* properties, u32 flags); Result nsdevTerminateProcess(u64 pid); Result nsdevTerminateProgram(u64 tid); -Result nsdevGetShellEvent(Event* out); +Result nsdevGetShellEvent(Event* out); // Autoclear for nsdevShellEvent is always true. Result nsdevGetShellEventInfo(NsShellEventInfo* out); Result nsdevTerminateApplication(void); Result nsdevPrepareLaunchProgramFromHost(NsLaunchProperties* out, const char* path, size_t path_len); @@ -108,4 +98,4 @@ Result nsdevLaunchApplication(u64* out_pid, u64 app_title_id, u32 flags); Result nsdevLaunchApplicationWithStorageId(u64* out_pid, u64 app_title_id, u32 flags, u8 app_storage_id, u8 patch_storage_id); Result nsdevIsSystemMemoryResourceLimitBoosted(bool* out); Result nsdevGetRunningApplicationProcessId(u64* out_pid); -Result nsdevSetCurrentApplicationRightsEnvironmentCanBeActive(bool can_be_active); \ No newline at end of file +Result nsdevSetCurrentApplicationRightsEnvironmentCanBeActive(bool can_be_active); diff --git a/nx/include/switch/services/pm.h b/nx/include/switch/services/pm.h index afd19d69..4bb838c9 100644 --- a/nx/include/switch/services/pm.h +++ b/nx/include/switch/services/pm.h @@ -8,6 +8,42 @@ */ #pragma once #include "../types.h" +#include "../kernel/event.h" + +typedef enum { + PmLaunchFlag_None = 0, + + ///< PmLaunchFlag_* should be used on 5.0.0+. + PmLaunchFlag_SignalOnExit = (1 << 0), + PmLaunchFlag_SignalOnStart = (1 << 1), + PmLaunchFlag_SignalOnCrash = (1 << 2), + PmLaunchFlag_SignalOnDebug = (1 << 3), + PmLaunchFlag_StartSuspended = (1 << 4), + PmLaunchFlag_DisableAslr = (1 << 5), + + ///< PmLaunchFlagOld_* should be used on 1.0.0-4.1.0. + PmLaunchFlagOld_SignalOnExit = (1 << 0), + PmLaunchFlagOld_StartSuspended = (1 << 1), + PmLaunchFlagOld_SignalOnCrash = (1 << 2), + PmLaunchFlagOld_DisableAslr = (1 << 3), + PmLaunchFlagOld_SignalOnDebug = (1 << 4), + ///< PmLaunchFlagOld_SignalOnStart was added in 2.0.0. + PmLaunchFlagOld_SignalOnStart = (1 << 5), +} PmLaunchFlag; + +typedef enum { + PmProcessEvent_None = 0, + PmProcessEvent_Exit = 1, + PmProcessEvent_Start = 2, + PmProcessEvent_Crash = 3, + PmProcessEvent_DebugStart = 4, + PmProcessEvent_DebugBreak = 5, +} PmProcessEvent; + +typedef struct { + PmProcessEvent event; + u64 process_id; +} PmProcessEventInfo; Result pmdmntInitialize(void); void pmdmntExit(void); @@ -29,5 +65,12 @@ Result pmdmntDisableDebug(void); Result pminfoGetTitleId(u64* title_id_out, u64 pid); Result pmshellLaunchProcess(u32 launch_flags, u64 titleID, u64 storageID, u64 *pid); +Result pmshellTerminateProcessByProcessId(u64 processID); Result pmshellTerminateProcessByTitleId(u64 titleID); +Result pmshellGetProcessEvent(Event* out); // Autoclear for pmshellProcessEvent is always true. +Result pmshellGetProcessEventInfo(PmProcessEventInfo* out); +Result pmshellFinalizeDeadProcess(u64 pid); +Result pmshellClearProcessExceptionOccurred(u64 pid); +Result pmshellNotifyBootFinished(void); Result pmshellGetApplicationPid(u64* pid_out); +Result pmshellBoostSystemMemoryResourceLimit(u64 boost_size); diff --git a/nx/source/services/ns.c b/nx/source/services/ns.c index 778d9f71..5303195a 100644 --- a/nx/source/services/ns.c +++ b/nx/source/services/ns.c @@ -383,7 +383,7 @@ Result nsvmGetSafeSystemVersion(u16 *out) return rc; } -Result nsdevLaunchProgram(u64* out_pid, NsLaunchProperties* properties, u32 flags) { +Result nsdevLaunchProgram(u64* out_pid, const NsLaunchProperties* properties, u32 flags) { IpcCommand c; ipcInitialize(&c); @@ -844,4 +844,4 @@ Result nsdevSetCurrentApplicationRightsEnvironmentCanBeActive(bool can_be_active } return rc; -} \ No newline at end of file +} diff --git a/nx/source/services/pm.c b/nx/source/services/pm.c index cabfee9e..060f5e82 100644 --- a/nx/source/services/pm.c +++ b/nx/source/services/pm.c @@ -386,6 +386,39 @@ Result pmshellLaunchProcess(u32 launch_flags, u64 titleID, u64 storageID, u64 *p return rc; } +Result pmshellTerminateProcessByProcessId(u64 processID) { + IpcCommand c; + ipcInitialize(&c); + + struct { + u64 magic; + u64 cmd_id; + u64 processID; + } *raw; + + raw = ipcPrepareHeader(&c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = 1; + raw->processID = processID; + + Result rc = serviceIpcDispatch(&g_pmshellSrv); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + ipcParse(&r); + + struct { + u64 magic; + u64 result; + } *resp = r.Raw; + + rc = resp->result; + } + + return rc; +} + Result pmshellTerminateProcessByTitleId(u64 titleID) { IpcCommand c; ipcInitialize(&c); @@ -419,6 +452,183 @@ Result pmshellTerminateProcessByTitleId(u64 titleID) { return rc; } +Result pmshellGetProcessEvent(Event* out) { + IpcCommand c; + ipcInitialize(&c); + + struct { + u64 magic; + u64 cmd_id; + } *raw; + + raw = ipcPrepareHeader(&c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = 3; + + Result rc = serviceIpcDispatch(&g_pmshellSrv); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + ipcParse(&r); + + struct { + u64 magic; + u64 result; + } *resp = r.Raw; + + rc = resp->result; + + if (R_SUCCEEDED(rc)) { + eventLoadRemote(out, r.Handles[0], true); + } + } + + return rc; +} + +Result pmshellGetProcessEventInfo(PmProcessEventInfo* out) { + IpcCommand c; + ipcInitialize(&c); + + struct { + u64 magic; + u64 cmd_id; + } *raw; + + raw = ipcPrepareHeader(&c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = 4; + + Result rc = serviceIpcDispatch(&g_pmshellSrv); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + ipcParse(&r); + + struct { + u64 magic; + u64 result; + u32 event; + u32 pad; + u64 process_id; + } *resp = r.Raw; + + rc = resp->result; + + if (R_SUCCEEDED(rc)) { + if (out) { + out->event = (PmProcessEvent)resp->event; + out->process_id = resp->process_id; + } + } + } + + return rc; +} + +Result pmshellFinalizeDeadProcess(u64 pid) { + if (kernelAbove500()) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + IpcCommand c; + ipcInitialize(&c); + + struct { + u64 magic; + u64 cmd_id; + u64 pid; + } *raw; + + raw = ipcPrepareHeader(&c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = 5; + raw->pid = pid; + + Result rc = serviceIpcDispatch(&g_pmshellSrv); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + ipcParse(&r); + + struct { + u64 magic; + u64 result; + } *resp = r.Raw; + + rc = resp->result; + } + + return rc; +} + +Result pmshellClearProcessExceptionOccurred(u64 pid) { + if (kernelAbove500()) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + IpcCommand c; + ipcInitialize(&c); + + struct { + u64 magic; + u64 cmd_id; + u64 pid; + } *raw; + + raw = ipcPrepareHeader(&c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = 6; + raw->pid = pid; + + Result rc = serviceIpcDispatch(&g_pmshellSrv); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + ipcParse(&r); + + struct { + u64 magic; + u64 result; + } *resp = r.Raw; + + rc = resp->result; + } + + return rc; +} + +Result pmshellNotifyBootFinished(void) { + IpcCommand c; + ipcInitialize(&c); + + struct { + u64 magic; + u64 cmd_id; + } *raw; + + raw = ipcPrepareHeader(&c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = kernelAbove500() ? 5 : 7; + + Result rc = serviceIpcDispatch(&g_pmshellSrv); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + ipcParse(&r); + + struct { + u64 magic; + u64 result; + } *resp = r.Raw; + + rc = resp->result; + } + + return rc; +} + Result pmshellGetApplicationPid(u64* pid_out) { IpcCommand c; ipcInitialize(&c); @@ -454,3 +664,38 @@ Result pmshellGetApplicationPid(u64* pid_out) { return rc; } + +Result pmshellBoostSystemMemoryResourceLimit(u64 boost_size) { + if (!kernelAbove400()) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + IpcCommand c; + ipcInitialize(&c); + + struct { + u64 magic; + u64 cmd_id; + u64 boost_size; + } *raw; + + raw = ipcPrepareHeader(&c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = kernelAbove500() ? 7 : 9; + raw->boost_size = boost_size; + + Result rc = serviceIpcDispatch(&g_pmshellSrv); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + ipcParse(&r); + + struct { + u64 magic; + u64 result; + } *resp = r.Raw; + + rc = resp->result; + } + + return rc; +}