9 #include "../arm/tls.h" 10 #include "../kernel/svc.h" 13 #define SFCI_MAGIC 0x49434653 15 #define SFCO_MAGIC 0x4f434653 18 #define IPC_INVALID_OBJECT_ID UINT32_MAX 24 #define IPC_MAX_BUFFERS 8 25 #define IPC_MAX_OBJECTS 8 35 BufferDirection_Send=0,
36 BufferDirection_Recv=1,
37 BufferDirection_Exch=2,
41 IpcCommandType_Invalid = 0,
42 IpcCommandType_LegacyRequest = 1,
43 IpcCommandType_Close = 2,
44 IpcCommandType_LegacyControl = 3,
45 IpcCommandType_Request = 4,
46 IpcCommandType_Control = 5,
47 IpcCommandType_RequestWithContext = 6,
48 IpcCommandType_ControlWithContext = 7
66 size_t NumHandlesCopy;
67 size_t NumHandlesMove;
68 Handle Handles[IPC_MAX_OBJECTS];
71 u32 ObjectIds[IPC_MAX_OBJECTS];
109 size_t off = cmd->NumSend;
110 cmd->Buffers[off] = buffer;
111 cmd->BufferSizes[off] = size;
112 cmd->BufferTypes[off] = type;
124 size_t off = cmd->NumSend + cmd->NumRecv;
125 cmd->Buffers[off] = buffer;
126 cmd->BufferSizes[off] = size;
127 cmd->BufferTypes[off] = type;
139 size_t off = cmd->NumSend + cmd->NumRecv + cmd->NumExch;
140 cmd->Buffers[off] = buffer;
141 cmd->BufferSizes[off] = size;
142 cmd->BufferTypes[off] = type;
154 size_t off = cmd->NumStaticIn;
155 cmd->Statics[off] = buffer;
156 cmd->StaticSizes[off] = size;
157 cmd->StaticIndices[off] = index;
169 size_t off = cmd->NumStaticIn + cmd->NumStaticOut;
170 cmd->Statics[off] = buffer;
171 cmd->StaticSizes[off] = size;
172 cmd->StaticIndices[off] = index;
185 if (ipc_buffer_size != 0 && size <= ipc_buffer_size) {
203 if (ipc_buffer_size != 0 && size <= ipc_buffer_size) {
227 cmd->Handles[cmd->NumHandlesCopy++] = h;
237 cmd->Handles[cmd->NumHandlesCopy + cmd->NumHandlesMove++] = h;
249 *buf++ = IpcCommandType_Request | (cmd->NumStaticIn << 16) | (cmd->NumSend << 20) | (cmd->NumRecv << 24) | (cmd->NumExch << 28);
251 u32* fill_in_size_later = buf;
253 if (cmd->NumStaticOut > 0) {
254 *buf = (cmd->NumStaticOut + 2) << 10;
260 if (cmd->SendPid || cmd->NumHandlesCopy > 0 || cmd->NumHandlesMove > 0) {
261 *buf++ |= 0x80000000;
262 *buf++ = (!!cmd->SendPid) | (cmd->NumHandlesCopy << 1) | (cmd->NumHandlesMove << 5);
267 for (i=0; i<(cmd->NumHandlesCopy + cmd->NumHandlesMove); i++)
268 *buf++ = cmd->Handles[i];
274 for (i=0; i<cmd->NumStaticIn; i++, buf+=2) {
277 uintptr_t ptr = (uintptr_t) cmd->Statics[i];
279 desc->
Packed = cmd->StaticIndices[i] | (cmd->StaticSizes[i] << 16) |
280 (((ptr >> 32) & 15) << 12) | (((ptr >> 36) & 15) << 6);
283 for (i=0; i<(cmd->NumSend + cmd->NumRecv + cmd->NumExch); i++, buf+=3) {
285 desc->
Size = cmd->BufferSizes[i];
287 uintptr_t ptr = (uintptr_t) cmd->Buffers[i];
289 desc->
Packed = cmd->BufferTypes[i] |
290 (((ptr >> 32) & 15) << 28) | ((ptr >> 36) << 2);
293 u32 padding = ((16 - (((uintptr_t) buf) & 15)) & 15) / 4;
294 u32* raw = (
u32*) (buf + padding);
296 size_t raw_size = (sizeof_raw/4) + 4;
299 u16* buf_u16 = (
u16*) buf;
301 for (i=0; i<cmd->NumStaticOut; i++) {
302 size_t off = cmd->NumStaticIn + i;
303 size_t sz = (uintptr_t) cmd->StaticSizes[off];
305 buf_u16[i] = (sz > 0xFFFF) ? 0 : sz;
308 size_t u16s_size = ((2*cmd->NumStaticOut) + 3)/4;
310 raw_size += u16s_size;
312 *fill_in_size_later |= raw_size;
314 for (i=0; i<cmd->NumStaticOut; i++, buf+=2) {
316 size_t off = cmd->NumStaticIn + i;
318 uintptr_t ptr = (uintptr_t) cmd->Statics[off];
320 desc->
Packed = (ptr >> 32) | (cmd->StaticSizes[off] << 16);
349 bool WasHandleCopied[IPC_MAX_OBJECTS];
353 u32 ObjectIds[IPC_MAX_OBJECTS];
384 r->
CommandType = (IpcCommandType) (ctrl0 & 0xffff);
386 r->
RawSize = (ctrl1 & 0x1ff) * 4;
393 if (ctrl1 & 0x80000000) {
399 r->
Pid |= ((
u64)(*buf++)) << 32;
402 size_t num_handles_copy = ((ctrl2 >> 1) & 15);
403 size_t num_handles_move = ((ctrl2 >> 5) & 15);
405 size_t num_handles = num_handles_copy + num_handles_move;
406 u32* buf_after_handles = buf + num_handles;
408 if (num_handles > IPC_MAX_OBJECTS)
409 num_handles = IPC_MAX_OBJECTS;
411 for (i=0; i<num_handles; i++)
418 buf = buf_after_handles;
421 size_t num_statics = (ctrl0 >> 16) & 15;
422 u32* buf_after_statics = buf + num_statics*2;
427 for (i=0; i<num_statics; i++, buf+=2) {
431 r->
Statics[i] = (
void*) (desc->
Addr | (((packed >> 12) & 15) << 32) | (((packed >> 6) & 15) << 36));
437 buf = buf_after_statics;
439 size_t num_bufs_send = (ctrl0 >> 20) & 15;
440 size_t num_bufs_recv = (ctrl0 >> 24) & 15;
441 size_t num_bufs_exch = (ctrl0 >> 28) & 15;
443 size_t num_bufs = num_bufs_send + num_bufs_recv + num_bufs_exch;
444 r->
Raw = (
void*)(((uintptr_t)(buf + num_bufs*3) + 15) &~ 15);
450 for (i=0; i<num_bufs; i++, buf+=3) {
454 r->
Buffers[i] = (
void*) (desc->
Addr | ((packed >> 28) << 32) | (((packed >> 2) & 15) << 36));
458 if (i < num_bufs_send)
460 else if (i < (num_bufs_send + num_bufs_recv))
479 buf[0] = IpcCommandType_Control;
494 struct ipcQueryPointerBufferSizeResponse {
498 } *raw = (
struct ipcQueryPointerBufferSizeResponse*)r.
Raw;
503 *size = raw->size & 0xffff;
517 buf[0] = IpcCommandType_Close;
534 buf[0] = IpcCommandType_Control;
547 struct ipcConvertSessionToDomainResponse {
551 } *raw = (
struct ipcConvertSessionToDomainResponse*)r.
Raw;
556 *object_id_out = raw->object_id;
569 cmd->ObjectIds[cmd->NumObjectIds++] = object_id;
594 hdr->NumObjectIds = (
u8)cmd->NumObjectIds;
595 hdr->Length = sizeof_raw;
596 hdr->ThisObjectId = object_id;
597 hdr->Pad[0] = hdr->Pad[1] = 0;
599 for(
size_t i = 0; i < cmd->NumObjectIds; i++)
600 object_ids[i] = cmd->ObjectIds[i];
621 r->
NumObjectIds = hdr->NumObjectIds > 8 ? 8 : hdr->NumObjectIds;
642 hdr->NumObjectIds = 0;
644 hdr->ThisObjectId = object_id;
645 hdr->Pad[0] = hdr->Pad[1] = 0;
void * Statics[8]
Pointers to the statics.
Definition: ipc.h:362
static Result ipcQueryPointerBufferSize(Handle session, size_t *size)
Queries the size of an IPC pointer buffer.
Definition: ipc.h:476
static void ipcSendPid(IpcCommand *cmd)
Tags an IPC command structure to send the PID.
Definition: ipc.h:216
BufferType BufferTypes[8]
Types of the buffers.
Definition: ipc.h:358
IPC static send-buffer descriptor.
Definition: ipc.h:90
void * Raw
Pointer to the raw embedded data structure in the response.
Definition: ipc.h:368
static void * ipcPrepareHeaderForDomain(IpcCommand *cmd, size_t sizeof_raw, u32 object_id)
Prepares the header of an IPC command structure (domain version).
Definition: ipc.h:588
uint16_t u16
16-bit unsigned integer.
Definition: types.h:22
static void ipcSendHandleMove(IpcCommand *cmd, Handle h)
Adds a move-handle to be sent through an IPC command structure.
Definition: ipc.h:236
IPC static receive-buffer descriptor.
Definition: ipc.h:96
static void ipcAddExchBuffer(IpcCommand *cmd, void *buffer, size_t size, BufferType type)
Adds an exchange-buffer to an IPC command structure.
Definition: ipc.h:138
u32 Addr
Lower 32-bits of the address of the buffer.
Definition: ipc.h:85
Handle Handles[8]
Handles.
Definition: ipc.h:348
static Result ipcCloseObjectById(Handle session, u32 object_id)
Closes a domain object by ID.
Definition: ipc.h:634
size_t NumStaticsOut
Number of output statics available in the response.
Definition: ipc.h:366
#define IPC_MAX_BUFFERS
IPC command (request) structure.
Definition: ipc.h:24
u32 Addr
Lower 32-bits of the address.
Definition: ipc.h:92
void * RawWithoutPadding
Pointer to the raw embedded data structure, without padding.
Definition: ipc.h:369
void * Buffers[8]
Pointers to the buffers.
Definition: ipc.h:356
u32 Handle
Kernel object handle.
Definition: types.h:45
static void * ipcPrepareHeader(IpcCommand *cmd, size_t sizeof_raw)
Prepares the header of an IPC command structure.
Definition: ipc.h:246
BufferDirection BufferDirections[8]
Direction of each buffer.
Definition: ipc.h:359
size_t RawSize
Size of the raw embedded data.
Definition: ipc.h:370
u32 Result
Function error code result type.
Definition: types.h:46
Allows ProcessMemory and shared TransferMemory.
Definition: ipc.h:29
size_t NumObjectIds
Number of object IDs (for domain messages).
Definition: ipc.h:352
IPC buffer descriptor.
Definition: ipc.h:83
uint8_t u8
8-bit unsigned integer.
Definition: types.h:21
static Result ipcCloseSession(Handle session)
Closes the IPC session with proper clean up.
Definition: ipc.h:515
u32 Size
Size of the buffer.
Definition: ipc.h:84
IPC parsed command (response) structure.
Definition: ipc.h:341
static void ipcInitialize(IpcCommand *cmd)
Initializes an IPC command structure.
Definition: ipc.h:78
size_t StaticSizes[8]
Sizes of the statics.
Definition: ipc.h:363
uint64_t u64
64-bit unsigned integer.
Definition: types.h:24
static void * armGetTls(void)
Gets the thread local storage buffer.
Definition: tls.h:14
u32 ObjectIds[8]
Object IDs (for domain messages).
Definition: ipc.h:353
uint32_t u32
32-bit unsigned integer.
Definition: types.h:23
static Result ipcParseForDomain(IpcParsedCommand *r)
Parse an IPC command response into an IPC parsed command structure (domain version).
Definition: ipc.h:609
static void ipcAddRecvBuffer(IpcCommand *cmd, void *buffer, size_t size, BufferType type)
Adds a receive-buffer to an IPC command structure.
Definition: ipc.h:123
static void ipcAddRecvStatic(IpcCommand *cmd, void *buffer, size_t size, u8 index)
Adds a static-receive-buffer to an IPC command structure.
Definition: ipc.h:168
bool WasHandleCopied[8]
true if the handle was moved, false if it was copied.
Definition: ipc.h:349
static Result ipcDispatch(Handle session)
Dispatches an IPC request.
Definition: ipc.h:331
bool HasPid
true if the 'Pid' field is filled out.
Definition: ipc.h:344
static void ipcAddSendStatic(IpcCommand *cmd, const void *buffer, size_t size, u8 index)
Adds a static-buffer to an IPC command structure.
Definition: ipc.h:153
size_t NumBuffers
Number of buffers in the response.
Definition: ipc.h:355
#define SFCI_MAGIC
IPC input header magic.
Definition: ipc.h:13
static void ipcSendObjectId(IpcCommand *cmd, u32 object_id)
Adds an object ID to be sent through an IPC domain command structure.
Definition: ipc.h:568
u64 Pid
PID included in the response (only if HasPid is true)
Definition: ipc.h:345
Regular buffer.
Definition: ipc.h:28
u32 Packed
Packed data (including higher bits of the address)
Definition: ipc.h:86
u32 Packed
Packed data (including higher bits of the address)
Definition: ipc.h:91
IPC domain message header.
Definition: ipc.h:573
size_t NumHandles
Number of handles copied.
Definition: ipc.h:347
u32 Packed
Packed data (including higher bits of the address)
Definition: ipc.h:98
u32 ThisObjectId
Object ID to call the command on (for domain messages).
Definition: ipc.h:351
BufferType
Definition: ipc.h:27
#define R_SUCCEEDED(res)
Checks whether a result code indicates success.
Definition: result.h:10
static Result ipcParse(IpcParsedCommand *r)
Parse an IPC command response into an IPC parsed command structure.
Definition: ipc.h:378
IpcCommandType CommandType
Type of the command.
Definition: ipc.h:342
u32 Addr
Lower 32-bits of the address of the buffer.
Definition: ipc.h:97
size_t NumStatics
Number of statics in the response.
Definition: ipc.h:361
static void ipcSendHandleCopy(IpcCommand *cmd, Handle h)
Adds a copy-handle to be sent through an IPC command structure.
Definition: ipc.h:226
#define R_FAILED(res)
Checks whether a result code indicates failure.
Definition: result.h:12
static void ipcAddSendSmart(IpcCommand *cmd, size_t ipc_buffer_size, const void *buffer, size_t size, u8 index)
Adds a smart-buffer (buffer + static-buffer pair) to an IPC command structure.
Definition: ipc.h:184
u8 StaticIndices[8]
Indices of the statics.
Definition: ipc.h:364
static void ipcAddRecvSmart(IpcCommand *cmd, size_t ipc_buffer_size, void *buffer, size_t size, u8 index)
Adds a smart-receive-buffer (buffer + static-receive-buffer pair) to an IPC command structure...
Definition: ipc.h:202
Same as Type1 except remote process is not allowed to use device-mapping.
Definition: ipc.h:31
size_t BufferSizes[8]
Sizes of the buffers.
Definition: ipc.h:357
static void ipcAddSendBuffer(IpcCommand *cmd, const void *buffer, size_t size, BufferType type)
Adds a buffer to an IPC command structure.
Definition: ipc.h:108
Result svcSendSyncRequest(Handle session)
Sends an IPC synchronization request to a session.
static Result ipcConvertSessionToDomain(Handle session, u32 *object_id_out)
Converts an IPC session handle into a domain.
Definition: ipc.h:531