Line 5:
Line 5:
=== Sessions ===
=== Sessions ===
−
Sessions are communication channels consisting of a client and server, through which data can be exchanged in the form of a request and response, respectively. Through sessions, the standard [[#Command Structure|IPC command protocol]] is implemented. Clients use their client session handle to send IPC commands to the server using svcSendSyncRequest, while servers use svcReplyAndReceive to reply. Client sessions can't be used with svcReplyAndReceive. In both cases, the kernel takes care of transferring IPC command data from the [[Thread Local Storage]] of the sending thread to the TLS of the receiving thread. Sessions can be created through svcCreateSession, which provides the caller with the client and server handles.
+
Sessions are communication channels consisting of a client and server, through which data can be exchanged in the form of a request and response, respectively. Through sessions, the standard [[#Message Structure|IPC command protocol]] is implemented. Clients use their client session handle to send IPC commands to the server using svcSendSyncRequest, while servers use svcReplyAndReceive to reply. Client sessions can't be used with svcReplyAndReceive. In both cases, the kernel takes care of transferring IPC command data from the [[Thread Local Storage]] of the sending thread to the TLS of the receiving thread. Sessions can be created through svcCreateSession, which provides the caller with the client and server handles.
Sessions are used in their raw form to implement [[FS:OpenFile|file handles]]. In this case, fs-module creates a raw session using svcCreateSession, and provides the "fs:USER" client with the resulting client session handle, keeping the server session handle for its own use. These sessions expose their [[Filesystem services#File service|own set of IPC commands]] which act on the file that was opened through fs:USER.
Sessions are used in their raw form to implement [[FS:OpenFile|file handles]]. In this case, fs-module creates a raw session using svcCreateSession, and provides the "fs:USER" client with the resulting client session handle, keeping the server session handle for its own use. These sessions expose their [[Filesystem services#File service|own set of IPC commands]] which act on the file that was opened through fs:USER.
Line 99:
Line 99:
|-
|-
| 4
| 4
−
| If set, the handles are closed for the caller. Interaction with bit5 unknown.
+
| If set, the handles are closed for the caller.
|-
|-
| 5
| 5
Line 108:
Line 108:
|}
|}
−
Usage examples:
+
Setting both bit4 and bit5 causes a kernel panic. Usage examples:
+
{| class="wikitable" border="1"
{| class="wikitable" border="1"
|-
|-
Line 219:
Line 220:
| 0x0000000E <nowiki>|</nowiki> (size<<4)
| 0x0000000E <nowiki>|</nowiki> (size<<4)
<ptr>
<ptr>
−
| The corresponding value contains a ptr to a buffer of said size. The buffer specified by the source process must have read permission during cmd-request handling(write permission is checked during cmd-reply handling for the original buffer). This isn't known to be used by any processes. When handling command requests this is handled the same way as 0x0000000A, and for handling command replies this is handled the same way as 0x0000000C(besides the descriptor type written into the dst cmdbuf for both of these).
+
| The corresponding value contains a ptr to a buffer of said size. The buffer specified by the source process must have read permission during cmd-request handling(write permission is checked during cmd-reply handling for the original buffer). Some calls like [[CECDU:WriteMessageWithHMAC]] use it, however it is unsure as to why. When handling command requests this is handled the same way as 0x0000000A, and for handling command replies this is handled the same way as 0x0000000C(besides the descriptor type written into the dst cmdbuf for both of these).
|}
|}
Line 231:
Line 232:
|-
|-
| 2
| 2
−
| 0x00000004 <nowiki>|</nowiki> (size<<14) <nowiki>|</nowiki> (static_buffer_id<<4)
+
| 0x00000004 <nowiki>|</nowiki> (size<<8) <nowiki>|</nowiki> (static_buffer_id<<4)
<ptr>
<ptr>
| This is typically used for RW buffers over PXI, but any process can use this. The address written to the destination cmd-buf is a phys-addr for a table located in the corresponding static buffer of the receiving process (which must be provided by the latter, otherwise the kernel dereferences NULL). Each static buffer needs to be page-aligned and musn't exceed a page's length (kernelpanic otherwise). This table contains the phys-addrs for the actual data, the array entries have the following format: {u32 *datachunk_physaddr, u32 datachunk_bytesize}.
| This is typically used for RW buffers over PXI, but any process can use this. The address written to the destination cmd-buf is a phys-addr for a table located in the corresponding static buffer of the receiving process (which must be provided by the latter, otherwise the kernel dereferences NULL). Each static buffer needs to be page-aligned and musn't exceed a page's length (kernelpanic otherwise). This table contains the phys-addrs for the actual data, the array entries have the following format: {u32 *datachunk_physaddr, u32 datachunk_bytesize}.
|-
|-
| 3
| 3
−
| 0x00000006 <nowiki>|</nowiki> (size<<14) <nowiki>|</nowiki> (static_buffer_id<<4)
+
| 0x00000006 <nowiki>|</nowiki> (size<<8) <nowiki>|</nowiki> (static_buffer_id<<4)
<ptr>
<ptr>
| Same as above except for read-only buffer. Prior(?) to the kernel version which implemented memory-permission checking for PXI buffers, this was unused and hence triggered a kernelpanic.
| Same as above except for read-only buffer. Prior(?) to the kernel version which implemented memory-permission checking for PXI buffers, this was unused and hence triggered a kernelpanic.
|}
|}
+
+
+
== SVCs ==
+
+
=== svcReplyAndReceive ===
+
+
'''Signature:'''
+
Result ReplyAndReceive(s32* index, Handle* handles, s32 handleCount, Handle replyTarget)
+
+
In a single operation, sends a IPC reply and waits for a new request. <code>handles</code> should be a pointer to an array of <code>handleCount</code> handles.<sup>TODO: Are only port/session handles supported?</sup>
+
<code>replyTarget</code> should contain a handle to the session to send the reply to. (This is usually the session from which we received the previous request.)
+
If <code>replyTarget</code> is 0, no reply and the call will simply wait for an incoming event.<sup>TODO: It doesn't seem like the 0xFFFF0000 command id mentioned in the above sections is necessary, but needs confirmation.</sup>
+
+
Upon returning, <code>index</code> will contain an index into <code>handles</code> specifying which object changed state.
+
If it's a server port endpoint, it means that there is a new incoming connection on that port which should be accepted using svcAcceptSession.
+
If it's a server session endpoint it means that we received a request from that session and should process and then reply to it by calling svcReplyAndReceive again with <code>replyTarget</code> set to that session's handle.
+
+
An example of a server svcReplyAndReceive loop is:
+
+
#define MAX_CLIENTS 4
+
Handle server_port = ...;
+
s32 requesting_index;
+
Handle handles[1 + MAX_CLIENTS] = { server_port };
+
s32 connected_clients = 0;
+
Handle reply_target = 0;
+
+
while (true) {
+
Result res = svcReplyAndReceive(&requesting_index, handles, 1 + connected_clients, reply_target);
+
+
if (res == 0xC920181A) {
+
// Session was closed by remote
+
// TODO: Handle disconnects
+
reply_target = 0;
+
continue;
+
}
+
+
if (requesting_index == 0) {
+
// New connection in server_port
+
ASSERT(connected_client < MAX_CLIENTS);
+
svcAcceptSession(&handles[1 + connected_clients++], server_port);
+
reply_target = 0;
+
continue;
+
}
+
+
reply_target = handles[requesting_index];
+
+
// Handle command here and write reply to command buffer
+
}