Services are an abstraction of ports and are the commonly used way of inter-process communication outside of the kernel. While handles of regular ports are retrieved from SVC(svcConnectToPort), service handles are retrieved through the port srv: ("service manager").

When a service is registered, svcCreatePort is used without a port-name. This means that the port is inaccessible via the port SVCs outside of sm-module. See below for getting a session handle for sending commands to services.

Processes with PID less than or equal to the number of NATIVE_FIRM built-in modules (fs, sm, pm, pxi, ldr) have access to all services. This value is obtained from svcGetSystemInfo.

Attempting to use srvGetServiceSession with a service that the process has access to when that service isn't registered, results in svcSendSyncRequest never returning(the exact cause is unknown).

Service Manager Port "srv:"

Command Header Description
0x00010002 Initialize
0x00020000 GetProcSemaphore() (the handle from this gets signaled when notifications for this process gets triggered)
0x00030100 RegisterService(8-byte servicename, u32 strlen, u32 max_sessions)
0x000400C0 UnregisterService(8-byte servicename, u32 strlen)
0x00050100 GetServiceSession(8-byte servicename, u32 strlen, u32 flags)

Flags bit0: if not set, return port-handle instead of session-handle(from svcCreateSessionToPort) when session-handle unavailable (max sessions/timeout?).

0x000600C2 RegisterPort(8-byte servicename, u32 strlen, Handle client_port)
0x000700C0 UnregisterPort(8-byte servicename, u32 strlen)
0x00080100 GetPort(8-byte servicename, u32 strlen, u32 flags).

Flags bit0: return 0 instead of port handle if port was found.

0x00090040 Subscribe(u32 notification_id). This enables the specified notificationID for the current process.
0x000A0040 Unsubscribe(u32 notification_id). This disables the specified notificationID for the current process.
0x000B0000 ReceiveNotification() This returns the notificationID which was triggered, if any(see GetProcSemaphore).
0x000C0080 PublishToSubscriber(u32 notification_id, u32 flag). This fires an notification. Bit0: only fire if not already fired, bit1: return error if error happens, else it always returns 0.
0x000D0040 This can fire notificationIDs and return the number of fired notificationID
0x000E00C0 HasAccessToService(8-byte servicename, u32 strlen). Returns 1 if your process has access to the service.

Service Manager Process-Manager Port "srv:pm"

Command Header, prior to 7.0.0-13 Description
0x04030082 RegisterProcess (u32 procid, u32 wordsz, ((wordsz<<16) | 2), serviceaccesscontrol*).
0x04040040 UnregisterProcess (u32 procid).

The Register command registers a process with the service-manager, which includes registering the serviceaccesscontrol for the process which normally originates from the exheader.

Prior to to 7.0.0-13, the commands listed for "srv:" were also accessible under this port with the same command-headers. Starting with 7.0.0-13, the "srv:pm" port was changed to a service. With this change, commandIDs for these commands were changed. "srv:pm" was originally vulnerable, this was fixed with 7.0.0-13, see here. Originally any process could use "srv:pm", however starting with 7.0.0-13 only the built-in NATIVE_FIRM sysmodules have access to it. The only system title which uses "srv:pm" is the Process Manager.

Notifications

ID Description
0x100 This indicates that all processes must terminate: power-off, reboot, or FIRM-launch.
0x105 This indicates that the system is entering sleep mode.
0x108 error at boot?
0x202 POWER button pressed
0x204 This indicates that the HOME button was pressed.
0x205 HOME button pressed
0x207 SD card inserted
0x208 Game cartridge inserted
0x209 SD card removed
0x20A Game cartridge removed
0x20B Game cartridge inserted or removed