Changes

Line 1: Line 1:  +
= LaunchFlags =
 +
 +
On [[5.0.0]]+, the LaunchFlag enum looks like this:
 +
 +
{| class=wikitable
 +
! Bit || Mask || Name
 +
|-
 +
| 0 || 1 || LaunchFlags_SignalOnExit
 +
|-
 +
| 1 || 2 || LaunchFlags_SignalOnStart
 +
|-
 +
| 2 || 4 || LaunchFlags_SignalOnCrash
 +
|-
 +
| 3 || 8 || LaunchFlags_SignalOnDebug
 +
|-
 +
| 4 || 0x10 || LaunchFlags_StartSuspended
 +
|-
 +
| 5 || 0x20 || LaunchFlags_DisableAslr
 +
|}
 +
 +
Prior to system version [[5.0.0]], the LaunchFlag enum had its entries in a different order:
 +
 +
{| class=wikitable
 +
! Bit || Mask || Name
 +
|-
 +
| 0 || 1 || LaunchFlags_SignalOnExit
 +
|-
 +
| 1 || 2 || LaunchFlags_StartSuspended
 +
|-
 +
| 2 || 4 || LaunchFlags_SignalOnCrash
 +
|-
 +
| 3 || 8 || LaunchFlags_DisableAslr
 +
|-
 +
| 4 || 0x10 || LaunchFlags_SignalOnDebug
 +
|-
 +
| 5 || 0x20 || [2.0.0+] LaunchFlags_SignalOnStart
 +
|}
 +
 +
= ProcessEventInfo =
 +
{| class="wikitable" border="1"
 +
|-
 +
! Offset
 +
! Size
 +
! Description
 +
|-
 +
| 0x0
 +
| 0x4
 +
| ProcessEvent
 +
|-
 +
| 0x4
 +
| 0x4
 +
| Padding/Reserved
 +
|-
 +
| 0x8
 +
| 0x8
 +
| ProcessId
 +
|-
 +
|}
 +
 
= Process Tracker thread =
 
= Process Tracker thread =
 
PM has a separate thread that is waiting for synchronization on process handles.
 
PM has a separate thread that is waiting for synchronization on process handles.
    
== State changes ==
 
== State changes ==
When the kernel signals a process handle, it uses svcResetSignal on the process handle and then it uses svcGetProcessInfo to read out the ProcessState.
+
When the kernel signals a process handle, it uses svcResetSignal on the process handle and then it uses svcGetProcessInfo to read out the ProcessEvent.
   −
If the process moved state non-3 -> 3 it clears 4 in process flags.
+
If the process moved from non-crashed -> ProcessEvent_Crashed it clears 4 in process flags.
    
If process flags has mask 8 set:
 
If process flags has mask 8 set:
* If new state is 2, it clears 0x20 and sets 0x10 in process flags, and signals the ProcessEventWaiter handle.
+
* If event is ProcessEvent_Running or ProcessEvent_DebugDetached, it clears 0x20 and sets 0x10 in process flags, and signals the ProcessEventWaiter handle.
* If new state is 4, it clears 0x20 and sets 0x10 in process flags, and signals the ProcessEventWaiter handle.
+
* If event is ProcessEvent_DebugSuspended, it sets 0x20 and 0x10 in process flags, and signals the ProcessEventWaiter handle.
* If new state is 7, it sets 0x30 in process flags, and signals the ProcessEventWaiter handle.
     −
[2.0.0+] If new state is 2, and process flags has 0x80 set, it sets mask 0x100 and signals the ProcessEventWaiter handle.
+
[2.0.0+] If new state is ProcessEvent_DebugDetached, and process flags has 0x80 set, it sets mask 0x100 and signals the ProcessEventWaiter handle.
    
If process flags has mask 1 set:
 
If process flags has mask 1 set:
* If new state is 6, it signals the ProcessEventWaiter handle.
+
* If new state is ProcessEvent_Exited, it signals the ProcessEventWaiter handle.
    
If mask 1 is not set, it immediately does what is otherwise done by the [[#FinalizeDeadProcess]] command.
 
If mask 1 is not set, it immediately does what is otherwise done by the [[#FinalizeDeadProcess]] command.
Line 24: Line 82:  
It uses [[Loader_services|ldr:pm]] GetProgramInfo with the supplied title-id.
 
It uses [[Loader_services|ldr:pm]] GetProgramInfo with the supplied title-id.
   −
If ((*(u8*) (info_output+2)) & 3) is == 1, it goes through the process list and errors if any has bit 0x40 set. Thus only one process can have bit 0x40 set at a time.
+
If ApplicationType == Application, it goes through the process list and errors if any has mask 0x40 set. Thus you can only run one Application at a time.
   −
Resource limits for the process is selected by ((*(u8*) (info_output+2)) & 3) being 0, 1, or 2. Value 3 is not used.
+
Resource limits for the process is selected by ApplicationType.
    
It calls [[Loader_services|ldr:pm]] RegisterTitle, then [[Loader_services|ldr:pm]] CreateProcess, then [[Filesystem_services|fsp-pr]] RegisterTitle, then [[Services_API|sm:m]] RegisterTitle.
 
It calls [[Loader_services|ldr:pm]] RegisterTitle, then [[Loader_services|ldr:pm]] CreateProcess, then [[Filesystem_services|fsp-pr]] RegisterTitle, then [[Services_API|sm:m]] RegisterTitle.
Line 42: Line 100:  
[2.0.0+] The launch_flags mask 0x10 and 0x20 will be ignored unless ((*(u8*) (info_output+2)) & 4) is set.
 
[2.0.0+] The launch_flags mask 0x10 and 0x20 will be ignored unless ((*(u8*) (info_output+2)) & 4) is set.
   −
If ((*(u8*) (info_output+2)) & 3) is == 1, it sets 0x40 in the process flags, and signals the event returned by [[#EnableDebug]]. svcStartProcess is not called in this case, it has to be done manually by the [[#StartProcess]] command.
+
If ApplicationType == Application, it sets 0x40 in the process flags, and signals the event returned by [[#EnableDebugForApplication]]. svcStartProcess is not called in this case, it has to be done manually by the [[#StartProcess]] command.
    
If the title-id matches the title-id given in [[#EnableDebugForTitleId]], then svcStartProcess is not called. Instead process remains in suspended state, and has to be done manually by the [[#StartProcess]] command.
 
If the title-id matches the title-id given in [[#EnableDebugForTitleId]], then svcStartProcess is not called. Instead process remains in suspended state, and has to be done manually by the [[#StartProcess]] command.
Line 55: Line 113:     
= pm:bm =
 
= pm:bm =
 +
This is "nn::pm::detail::IBootModeInterface".
 +
 
{| class="wikitable" border="1"
 
{| class="wikitable" border="1"
 
|-
 
|-
 
! Cmd || Name
 
! Cmd || Name
 
|-
 
|-
| 0 || GetMaintenanceMode
+
| 0 || GetBootMode
 
|-
 
|-
| 1 || EnableMaintenanceMode
+
| 1 || SetMaintenanceBoot
 
|}
 
|}
    
= pm:dmnt =
 
= pm:dmnt =
 +
This is "nn::pm::detail::IDebugMonitorInterface".
 +
 
{| class="wikitable" border="1"
 
{| class="wikitable" border="1"
 
|-
 
|-
 
! Cmd || Name
 
! Cmd || Name
 
|-
 
|-
| 0 || [[#GetDebugMode]]
+
| [1.0.0-4.1.0] 0 || [[#GetModuleIdList]]
 +
|-
 +
| 0 ([1.0.0-4.1.0] 1) || [[#GetJitDebugProcessIdList]]
 +
|-
 +
| 1 ([1.0.0-4.1.0] 2) || [[#StartProcess]]
 
|-
 
|-
| 1 || [[#GetDebugProcesses]]
+
| 2 ([1.0.0-4.1.0] 3) || [[#GetProcessId]]
 
|-
 
|-
| 2 || [[#StartDebugProcess]]
+
| 3 ([1.0.0-4.1.0] 4) || [[#HookToCreateProcess]]
 
|-
 
|-
| 3 || [[#GetDebugProcessTitleIdByPid]]
+
| 4 ([1.0.0-4.1.0] 5) || [[#GetApplicationProcessId]]
 
|-
 
|-
| 4 || [[#EnableDebugForTitleId]]
+
| 5 ([1.0.0-4.1.0] 6) || [[#HookToCreateApplicationProcess]]
 
|-
 
|-
| 5 || [[#GetCrashingDebugProcessPid]]
+
| [6.0.0+] 6 || [[#ClearHook]]
 
|-
 
|-
| 6 || [[#EnableDebug]]
+
| [14.0.0+] 7 || GetProgramId
 
|}
 
|}
   −
== GetDebugMode ==
  −
Always returns u32 0 on retail.
     −
[2.0.0+] Additional check on input that can return 0xC0F. The meaning is probably useless because function is somewhat nopped on non-dev builds anyway.
+
== GetModuleIdList==
 +
Stubbed in all versions of retail firmware (just returns 0).
   −
== GetDebugProcesses ==
+
[2.0.0+] When output buffer size is > INT_MAX, returns ResultInvalidSize.
 +
 
 +
== GetJitDebugProcessIdList ==
 
Returns an array of pids of all processes that have mask 4 set in process flags.
 
Returns an array of pids of all processes that have mask 4 set in process flags.
   −
[2.0.0+] Additional check on input that can return 0xC0F. The meaning is probably useless because function is somewhat nopped on non-dev builds anyway.
+
[2.0.0+] When output buffer size is > INT_MAX, returns ResultInvalidSize.
   −
== StartDebugProcess ==
+
== StartProcess ==
Takes a pid. Process state must be 0 or 1. Then it uses svcStartProcess(process_handle, u8, u8, u32) with args coming from ldr:pm GetProgramInfo.
+
Takes a pid. Last process event must be ProcessEvent_Created or ProcessEvent_DebugAttached.
   −
After that, it sets process state to 2.
+
Then it uses svcStartProcess(process_handle, u8, u8, u32) with args coming from ldr:pm GetProgramInfo.
   −
== GetDebugProcessTitleIdByPid ==
+
After that, it sets last process state to ProcessEvent_DebugDetached.
Same as [[Process_Manager_services#GetProcessTitleIdByPid|GetProcessTitleIdByPid]] but for debug processes.
     −
== EnableDebugForTitleId ==
+
== GetProcessId ==
Takes a title-id of the program to debug. Sets this to a global field. Next time it gets launched it will be handled differently.
+
Takes a title-id and returns the pid.
   −
Returns an event handle that is signaled when the requested title is launched.
+
== HookToCreateProcess ==
 +
Takes a title-id of the program to debug. Sets this to a global field.
   −
== GetCrashingDebugProcessPid ==
+
Next time it gets launched it will be handled differently.
Same as [[Process_Manager_services#GetCrashingProcessPid|GetCrashingProcessPid]] but for debug processes.
     −
== EnableDebug ==
+
Returns an event handle that is signaled when the requested title is about to be launched.
 +
 
 +
== GetApplicationProcessId ==
 +
Returns the pid of the application process.
 +
 
 +
== HookToCreateApplicationProcess ==
 
Does *not* take a specific title-id as input.
 
Does *not* take a specific title-id as input.
   −
Returns an event handle that is triggered for debug titles.
+
Returns an event handle that is triggered for application titles.
 +
 
 +
== ClearHook ==
 +
Takes in a u32 of bitflags.
 +
 
 +
Disables debugging/clears the globally specified tid if bit 0 is set, disables debugging/clears the next application if bit 1 is set.
    
= pm:info =
 
= pm:info =
 +
This is "nn::pm::detail::IInformationInterface".
 +
 
{| class="wikitable" border="1"
 
{| class="wikitable" border="1"
 
|-
 
|-
 
! Cmd || Name
 
! Cmd || Name
 
|-
 
|-
| 0 || [[#GetProcessTitleIdByPid]]
+
| 0 || [[#GetProgramId]]
 +
|-
 +
| 1 || [14.0.0+] GetAppletCurrentResourceLimitValues
 +
|-
 +
| 2 || [14.0.0+] GetAppletPeakResourceLimitValues
 
|}
 
|}
   −
== GetProcessTitleIdByPid ==
+
== GetProgramId ==
 
Takes a pid and returns the title-id associated with the process.
 
Takes a pid and returns the title-id associated with the process.
    
= pm:shell =
 
= pm:shell =
 +
This is "nn::pm::detail::IShellInterface".
 +
 
{| class="wikitable" border="1"
 
{| class="wikitable" border="1"
 
|-
 
|-
 
! Cmd || Name
 
! Cmd || Name
 
|-
 
|-
| 0 || [[#LaunchProcess]]
+
| 0 || [[#LaunchProgram]]
 +
|-
 +
| 1 || TerminateProcess
 +
|-
 +
| 2 || TerminateProgram
 +
|-
 +
| 3 || GetProcessEventHandle
 +
|-
 +
| 4 || [[#GetProcessEventInfo]]
 
|-
 
|-
| 1 || TerminateProcessByPid
+
| ([1.0.0-4.1.0] 5) || [[#CleanupProcess]]
 
|-
 
|-
| 2 || TerminateProcessByTitleId
+
| ([1.0.0-4.1.0] 6) || [[#ClearJitDebugOccured]]
 
|-
 
|-
| 3 || GetProcessEventWaiter
+
| 5 ([1.0.0-4.1.0] 7) || [[#NotifyBootFinished]]
 
|-
 
|-
| 4 || [[#GetProcessEventType]]
+
| 6 ([1.0.0-4.1.0] 8) || [[#GetApplicationProcessIdForShell]]
 
|-
 
|-
| 5 || [[#FinalizeDeadProcess]]
+
| 7 ([4.0.0-4.1.0] 9) || [4.0.0+] [[#BoostSystemMemoryResourceLimit]]
 
|-
 
|-
| 6 || [[#ClearProcessNotificationFlag]]
+
| 8 || [7.0.0+] [[#BoostApplicationThreadResourceLimit]]
 
|-
 
|-
| 7 || [[#NotifyBootFinished]]
+
| 9 || [8.0.0+] [[#GetBootFinishedEventHandle]]
 
|-
 
|-
| 8 || [[#GetCrashingProcessPid]]
+
| 10 || [14.0.0+] BoostSystemThreadResourceLimit
 
|}
 
|}
   −
== LaunchProcess ==
+
== LaunchProgram ==
Takes a title-id and launch_flags. See [[#Process launch]].
+
Takes an u32 launch_flags and [[NCM_services#ProgramLocation|ProgramLocation]]. Returns the u64 title PID.
 +
 
 +
See [[#Process launch]].
   −
== GetProcessEventType ==
+
== GetProcessEventInfo ==
 
Returns 1 if flags has mask 2 set.
 
Returns 1 if flags has mask 2 set.
    
Returns 2 if flags has mask 1 set and state is 6.
 
Returns 2 if flags has mask 1 set and state is 6.
   −
Returns 3 if flags has mask 0x10 set and not bit5.
+
Returns 3 if flags has mask 0x10 set and not 0x20.
    
Returns 4 if flags has mask 0x30 set.
 
Returns 4 if flags has mask 0x30 set.
Line 166: Line 260:  
Returns 0 if process is not found.
 
Returns 0 if process is not found.
   −
== FinalizeDeadProcess ==
+
== CleanupProcess ==
 
Takes a pid as input. If the process with pid has the state "dead", it unregisters the pid in fsp:pr, sm:m, and ldr:pm.
 
Takes a pid as input. If the process with pid has the state "dead", it unregisters the pid in fsp:pr, sm:m, and ldr:pm.
    
Then it removes the process from PMs internal linked-list of active processes.
 
Then it removes the process from PMs internal linked-list of active processes.
   −
== ClearProcessNotificationFlag ==
+
[5.0.0+] This command was removed.
Takes a pid as input. Clears 0x10 from process flags.  
+
 
 +
== ClearJitDebugOccured ==
 +
Takes a pid as input. Clears 0x10 from process flags.
 +
 
 +
[5.0.0+] This command was removed.
    
== NotifyBootFinished ==
 
== NotifyBootFinished ==
Launches a process with hardcoded [[boot2]] title-id.
+
This [[#LaunchProgram|launches]] the [[boot2]] title with launch_flags=0.
 +
 
 +
[10.0.0+] The functionality described [[SMC#DisableProgramVerification|here]] was added, prior to title-launching.
 +
 
 +
[4.0.0+] When booting from SafeMode Firmware, instead of [[boot2]], this launches the following titles in order (launch_flags=0):
 +
* 0100000000000009 (settings)
 +
* 0100000000000006 (usb)
 +
* 010000000000001D (pcie)
 +
* 0100000000000007 (tma)
 +
* 0100000000000042 (pgl) [10.0.0+]
 +
* 010000000000001F (ns)
 +
* 0100000000000015 (lm)
 +
* 0100000000000010 (ptm)
 +
* 0100000000000016 (wlan)
 +
* 0100000000000012 (bsdsockets)
 +
* 0100000000000046 (eth) [15.0.0+]
 +
* 010000000000000F (nifm)
 +
* 0100000000000024 (ssl)
 +
* 0100000000000025 (nim)
 +
* 0100000000000031 (glue)
 +
* 010000000000003D (safemode)
   −
== GetCrashingProcessPid ==
+
== GetApplicationProcessIdForShell ==
 
Loops through the internal linked-list of processes, looks for mask 0x40 set in process flags. Returns pid of first such entry.
 
Loops through the internal linked-list of processes, looks for mask 0x40 set in process flags. Returns pid of first such entry.
 +
 +
== BoostSystemMemoryResourceLimit ==
 +
Takes an u64 '''mem_size''' as input. If the desired memory size doesn't exceed an internal limit (imposed by PM by looking at the [[SPL_services#MemoryArrange|MemoryArrange]] ConfigItem), PM calls svcSetResourceLimitLimitValue to set the new [[SVC#LimitableResource|LimitableResource_Memory]] value.
 +
 +
This is used directly by [[NS_Services#IApplicationManagerInterface|ns:am2 BoostSystemMemoryResourceLimit]].
 +
 +
== BoostApplicationThreadResourceLimit ==
 +
Calls svcSetResourceLimitLimitValue to increase the limit on application threads by an amount calculated dynamically during setup.
 +
 +
This function can only increase the limit once, on further calls it will call svcSetResourceLimitLimitValue with the same value it called the first time.
 +
 +
On normal [[7.0.0]] retail firmware, this will double the limit on application threads from 0x60 to 0xC0.
 +
 +
== GetBootFinishedEventHandle ==
 +
This function returns a handle to an event that is signaled when [[#NotifyBootFinished]] is called.
 +
 +
However, this is only used/available in safe mode; in normal, non-safe FIRM, the implementation for this command just does "abort();".
    
[[Category:Services]]
 
[[Category:Services]]