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 bit4 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 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 22: |
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 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. |
| | | |
− | The second input argument for [[Loader_services|ldr:pm]] CreateProcess is (launch_flags >> 2) & 3. | + | [1.0.0] The second input argument for [[Loader_services|ldr:pm]] CreateProcess is (launch_flags >> 2) & 3. |
| + | |
| + | [2.0.0+] The second input argument for [[Loader_services|ldr:pm]] CreateProcess is ((launch_flags >> 2) & 2) | ((launch_flags >> 1) != 1). |
| | | |
| If launch_flags has mask 1 set, it sets mask 1 in process flags. | | If launch_flags has mask 1 set, it sets mask 1 in process flags. |
| | | |
− | If launch_flags flags has mask 0x10 set, it sets mask 8 in process flags. | + | If launch_flags has mask 0x10 set, it sets mask 8 in process flags. |
| + | |
| + | [2.0.0+] If launch_flags has mask 0x20 set, it sets mask 0x80 in process flags. |
| + | |
| + | [2.0.0+] The launch_flags mask 0x10 and 0x20 will be ignored unless ((*(u8*) (info_output+2)) & 4) is set. |
| + | |
| + | 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 ((*(u8*) (info_output+2)) & 3) is == 1, it sets 0x40 in the process flags, and signals the event returned by [[#EnableDebug]]. | + | If launch_flags has mask 2 set, svcStartProcess is skipped. |
| | | |
| Finally it does svcStartProcess on the process handle that was returned by [[Loader_services|ldr:pm]] CreateProcess, and sets process state to 2. | | Finally it does svcStartProcess on the process handle that was returned by [[Loader_services|ldr:pm]] CreateProcess, and sets process state to 2. |
| | | |
− | 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.
| + | The arguments for svcStartProcess are process_handle, *(u8*)info_output, *(u8*)(info_output+1), *(u32*)(info_output+4). |
| | | |
| Thus at the point of launch, the pid is already registered in ldr, fs, sm, and pm. | | Thus at the point of launch, the pid is already registered in ldr, fs, sm, and pm. |
| | | |
| = 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 |
| + | |- |
| + | | 2 || [19.0.0+] |
| + | |- |
| + | | 3 || [19.0.0+] |
| |} | | |} |
| | | |
| = pm:dmnt = | | = pm:dmnt = |
| + | This is "nn::pm::detail::IDebugMonitorInterface". |
| + | |
| {| class="wikitable" border="1" | | {| class="wikitable" border="1" |
| |- | | |- |
| ! Cmd || Name | | ! Cmd || Name |
| |- | | |- |
− | | 0 || [[#GetZero]] | + | | [1.0.0-4.1.0] 0 || [[#GetModuleIdList]] |
| |- | | |- |
− | | 1 || [[#GetProcessesWithFlag4]] | + | | 0 ([1.0.0-4.1.0] 1) || [[#GetJitDebugProcessIdList]] |
| |- | | |- |
− | | 2 || [[#StartProcess]] | + | | 1 ([1.0.0-4.1.0] 2) || [[#StartProcess]] |
| |- | | |- |
− | | 3 || GetProcessTitleIdByPid | + | | 2 ([1.0.0-4.1.0] 3) || [[#GetProcessId]] |
| |- | | |- |
− | | 4 || [[#EnableDebugForTitleId]] | + | | 3 ([1.0.0-4.1.0] 4) || [[#HookToCreateProcess]] |
| |- | | |- |
− | | 5 || GetCrashingProcessPid | + | | 4 ([1.0.0-4.1.0] 5) || [[#GetApplicationProcessId]] |
| |- | | |- |
− | | 6 || [[#EnableDebug]] | + | | 5 ([1.0.0-4.1.0] 6) || [[#HookToCreateApplicationProcess]] |
| + | |- |
| + | | [6.0.0+] 6 || [[#ClearHook]] |
| + | |- |
| + | | [14.0.0+] 7 || GetProgramId |
| |} | | |} |
| | | |
− | == GetZero ==
| |
− | Always returns u32 0.
| |
| | | |
− | == GetProcessesWithFlag4 == | + | == GetModuleIdList== |
| + | Stubbed in all versions of retail firmware (just returns 0). |
| + | |
| + | [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+] When output buffer size is > INT_MAX, returns ResultInvalidSize. |
| | | |
| == StartProcess == | | == 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. |
| + | |
| + | Then it uses svcStartProcess(process_handle, u8, u8, u32) with args coming from ldr:pm GetProgramInfo. |
| | | |
− | After that, it sets process state to 2. | + | After that, it sets last process state to ProcessEvent_DebugDetached. |
| | | |
− | == 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. |
| | | |
− | == EnableDebug == | + | Next time it gets launched it will be handled differently. |
| + | |
| + | 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 |
| |} | | |} |
| + | |
| + | == GetProgramId == |
| + | 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 || TerminateProcessByPid | + | | 1 || TerminateProcess |
| |- | | |- |
− | | 2 || TerminateProcessByTitleID | + | | 2 || TerminateProgram |
| |- | | |- |
− | | 3 || GetProcessEventWaiter | + | | 3 || GetProcessEventHandle |
| |- | | |- |
− | | 4 || GetProcessEventType (0=CONTINUE, 1=CRASHING, 2,3,5) | + | | 4 || [[#GetProcessEventInfo]] |
| |- | | |- |
− | | 5 || [[#FinalizeDeadProcess]] | + | | ([1.0.0-4.1.0] 5) || [[#CleanupProcess]] |
| |- | | |- |
− | | 6 || [[#ClearProcessNotificationFlag]] | + | | ([1.0.0-4.1.0] 6) || [[#ClearJitDebugOccured]] |
| |- | | |- |
− | | 7 || [[#NotifyBootFinished]] | + | | 5 ([1.0.0-4.1.0] 7) || [[#NotifyBootFinished]] |
| |- | | |- |
− | | 8 || [[#GetCrashingProcessPid]] | + | | 6 ([1.0.0-4.1.0] 8) || [[#GetApplicationProcessIdForShell]] |
| + | |- |
| + | | 7 ([4.0.0-4.1.0] 9) || [4.0.0+] [[#BoostSystemMemoryResourceLimit]] |
| + | |- |
| + | | 8 || [7.0.0+] [[#BoostApplicationThreadResourceLimit]] |
| + | |- |
| + | | 9 || [8.0.0+] [[#GetBootFinishedEventHandle]] |
| + | |- |
| + | | 10 || [14.0.0+] BoostSystemThreadResourceLimit |
| + | |- |
| + | | 12 || [19.0.0+] GetProcessId |
| |} | | |} |
| | | |
− | == 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]]. |
| + | |
| + | == GetProcessEventInfo == |
| + | Returns 1 if flags has mask 2 set. |
| + | |
| + | Returns 2 if flags has mask 1 set and state is 6. |
| + | |
| + | Returns 3 if flags has mask 0x10 set and not 0x20. |
| + | |
| + | Returns 4 if flags has mask 0x30 set. |
| | | |
− | == FinalizeDeadProcess == | + | [2.0.0+] returns 5 if state >= 2 and flags has mask 0x100 set. |
| + | |
| + | Returns 0 if process is not found. |
| + | |
| + | == 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. |
| | | |
− | == GetCrashingProcessPid == | + | [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) |
| + | |
| + | == 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]] |