IPC

From 3dbrew
Revision as of 17:25, 9 April 2015 by Ichfly (talk | contribs)
Jump to navigation Jump to search

The IPC commands are written to the Thread Local Storage, at offset 0x80. Every IPC command sent to services starts with a u32 header code, and parameters, if any, are written after this header. If the kernel was able to dispatch the request, the server reply will be written to TLS+0x80. Often the first word of the response data is the error code (or 0 if success).

The command header is a 32-bit integer that can be decompossed in the following parts:

Bits Description
0-5 Number of translate parameters (=y)
6-11 Number of normal parameters (=x)
12-15 Unused
16-31 Command ID

The entire command has the following structure:

Word Size Description
0 1 Header code
1 x Normal parameters
x y Translate parameters

Translate parameters are modified/translated transparently by the kernel. They are used to transfer handles/buffers between the different processes.

The type of parameter is described by the bits 1-3 in the translation descriptor. Parameter types accepted for sending by the kernel are: 0, 1, 2, 5, 6, 7. Type 0 is used to send handles across processes:

if desc & 0x30 == 0x20:
  write process id to value
else:
  translate handle
  if desc & 0x30 == 0x10:
    close handle for caller

For replies, only 0, 1, 5, 6, 7 are allowed. In other words any type 2 fields must be zeroed before calling svcReplyAndReceive on the server-side. For replies type 0, 1, 2 are ignored. Types 5, 6, 7 do something with the mem pointer upon reply. The type 0 descriptor can be used to ignore parameters. The number of parameters covered by a type-0 descriptor is (desc >> 26) + 1.

Type Usual form Description
0 0x00000000 | ((num_handles-1)<<26)

<handle 0>

<handle 1> ...

The corresponding values are KHandles, that should be closed in calling process. Or zero otherwise.
0 0x00000010 | ((num_handles-1)<<26)

<handle 0>

<handle 1> ...

The corresponding values are KHandles, that will be duplicated. Or zero otherwise.
0 0x00000020

<placeholder>

Let kernel set value to calling process ProcessID.
1 0x00000002 | (size<<14) | (static_buffer_id<<10)

<ptr>

The corresponding value contains a ptr to a buffer of said size, that should be copied to an already set-up buffer in destination process at Thread Local Storage offset 0x180 + static_buffer_id*8. The static_buffer_id is only 4 bits, making it possible for at most up to 16 buffers in total per thread.
2 0x00000004 | (size<<4) This is used for PXI commands input/output buffers. The address written to the destination cmd-buf is a phys-addr for a table located in the BASE memregion. This table contains the phys-addrs for the actual data, the array entries have the following format: {u32 *datachunk_physaddr, u32 datachunk_bytesize}.
3 0x00000006 | (size<<4) Does nothing?
4 0x00000008 This command will cause a kernelpanic.
5 0x0000000A | (size<<4)

<ptr>

The corresponding value contains a ptr to a buffer of said size. It is mapped R- in the destination process??
6 0x0000000C | (size<<4)

<ptr>

The corresponding value contains a ptr to a buffer of said size. It is mapped -W in the destination process??
7 0x0000000E | (size<<4)

<ptr>

The corresponding value contains a ptr to a buffer of said size. It is mapped RW in the destination process??

Buffers from commands 5,6,7 will get mapped at virtual address 0x04000000+ in destination process.