libnx
ipc.h
Go to the documentation of this file.
1 /**
2  * @file ipc.h
3  * @brief Inter-process communication handling
4  * @author plutoo
5  * @copyright libnx Authors
6  */
7 #pragma once
8 #include "../result.h"
9 #include "../arm/tls.h"
10 #include "../kernel/svc.h"
11 
12 /// IPC input header magic
13 #define SFCI_MAGIC 0x49434653
14 /// IPC output header magic
15 #define SFCO_MAGIC 0x4f434653
16 
17 /// IPC invalid object ID
18 #define IPC_INVALID_OBJECT_ID UINT32_MAX
19 
20 ///@name IPC request building
21 ///@{
22 
23 /// IPC command (request) structure.
24 #define IPC_MAX_BUFFERS 8
25 #define IPC_MAX_OBJECTS 8
26 
27 typedef enum {
28  BufferType_Normal=0, ///< Regular buffer.
29  BufferType_Type1=1, ///< Allows ProcessMemory and shared TransferMemory.
30  BufferType_Invalid=2,
31  BufferType_Type3=3 ///< Same as Type1 except remote process is not allowed to use device-mapping.
32 } BufferType;
33 
34 typedef enum {
35  BufferDirection_Send=0,
36  BufferDirection_Recv=1,
37  BufferDirection_Exch=2,
38 } BufferDirection;
39 
40 typedef enum {
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
49 } IpcCommandType;
50 
51 typedef struct {
52  size_t NumSend; // A
53  size_t NumRecv; // B
54  size_t NumExch; // W
55  const void* Buffers[IPC_MAX_BUFFERS];
56  size_t BufferSizes[IPC_MAX_BUFFERS];
57  BufferType BufferTypes[IPC_MAX_BUFFERS];
58 
59  size_t NumStaticIn; // X
60  size_t NumStaticOut; // C
61  const void* Statics[IPC_MAX_BUFFERS];
62  size_t StaticSizes[IPC_MAX_BUFFERS];
63  u8 StaticIndices[IPC_MAX_BUFFERS];
64 
65  bool SendPid;
66  size_t NumHandlesCopy;
67  size_t NumHandlesMove;
68  Handle Handles[IPC_MAX_OBJECTS];
69 
70  size_t NumObjectIds;
71  u32 ObjectIds[IPC_MAX_OBJECTS];
72 } IpcCommand;
73 
74 /**
75  * @brief Initializes an IPC command structure.
76  * @param cmd IPC command structure.
77  */
78 static inline void ipcInitialize(IpcCommand* cmd) {
79  *cmd = (IpcCommand){0};
80 }
81 
82 /// IPC buffer descriptor.
83 typedef struct {
84  u32 Size; ///< Size of the buffer.
85  u32 Addr; ///< Lower 32-bits of the address of the buffer
86  u32 Packed; ///< Packed data (including higher bits of the address)
88 
89 /// IPC static send-buffer descriptor.
90 typedef struct {
91  u32 Packed; ///< Packed data (including higher bits of the address)
92  u32 Addr; ///< Lower 32-bits of the address
94 
95 /// IPC static receive-buffer descriptor.
96 typedef struct {
97  u32 Addr; ///< Lower 32-bits of the address of the buffer
98  u32 Packed; ///< Packed data (including higher bits of the address)
100 
101 /**
102  * @brief Adds a buffer to an IPC command structure.
103  * @param cmd IPC command structure.
104  * @param buffer Address of the buffer.
105  * @param size Size of the buffer.
106  * @param type Buffer type.
107  */
108 static inline void ipcAddSendBuffer(IpcCommand* cmd, const void* buffer, size_t size, BufferType type) {
109  size_t off = cmd->NumSend;
110  cmd->Buffers[off] = buffer;
111  cmd->BufferSizes[off] = size;
112  cmd->BufferTypes[off] = type;
113  cmd->NumSend++;
114 }
115 
116 /**
117  * @brief Adds a receive-buffer to an IPC command structure.
118  * @param cmd IPC command structure.
119  * @param buffer Address of the buffer.
120  * @param size Size of the buffer.
121  * @param type Buffer type.
122  */
123 static inline void ipcAddRecvBuffer(IpcCommand* cmd, void* buffer, size_t size, BufferType type) {
124  size_t off = cmd->NumSend + cmd->NumRecv;
125  cmd->Buffers[off] = buffer;
126  cmd->BufferSizes[off] = size;
127  cmd->BufferTypes[off] = type;
128  cmd->NumRecv++;
129 }
130 
131 /**
132  * @brief Adds an exchange-buffer to an IPC command structure.
133  * @param cmd IPC command structure.
134  * @param buffer Address of the buffer.
135  * @param size Size of the buffer.
136  * @param type Buffer type.
137  */
138 static inline void ipcAddExchBuffer(IpcCommand* cmd, void* buffer, size_t size, BufferType 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;
143  cmd->NumExch++;
144 }
145 
146 /**
147  * @brief Adds a static-buffer to an IPC command structure.
148  * @param cmd IPC command structure.
149  * @param buffer Address of the buffer.
150  * @param size Size of the buffer.
151  * @param index Index of buffer.
152  */
153 static inline void ipcAddSendStatic(IpcCommand* cmd, const void* buffer, size_t size, u8 index) {
154  size_t off = cmd->NumStaticIn;
155  cmd->Statics[off] = buffer;
156  cmd->StaticSizes[off] = size;
157  cmd->StaticIndices[off] = index;
158  cmd->NumStaticIn++;
159 }
160 
161 /**
162  * @brief Adds a static-receive-buffer to an IPC command structure.
163  * @param cmd IPC command structure.
164  * @param buffer Address of the buffer.
165  * @param size Size of the buffer.
166  * @param index Index of buffer.
167  */
168 static inline void ipcAddRecvStatic(IpcCommand* cmd, void* buffer, size_t size, u8 index) {
169  size_t off = cmd->NumStaticIn + cmd->NumStaticOut;
170  cmd->Statics[off] = buffer;
171  cmd->StaticSizes[off] = size;
172  cmd->StaticIndices[off] = index;
173  cmd->NumStaticOut++;
174 }
175 
176 /**
177  * @brief Adds a smart-buffer (buffer + static-buffer pair) to an IPC command structure.
178  * @param cmd IPC command structure.
179  * @param ipc_buffer_size IPC buffer size.
180  * @param buffer Address of the buffer.
181  * @param size Size of the buffer.
182  * @param index Index of buffer.
183  */
184 static inline void ipcAddSendSmart(IpcCommand* cmd, size_t ipc_buffer_size, const void* buffer, size_t size, u8 index) {
185  if (ipc_buffer_size != 0 && size <= ipc_buffer_size) {
186  ipcAddSendBuffer(cmd, NULL, 0, BufferType_Normal);
187  ipcAddSendStatic(cmd, buffer, size, index);
188  } else {
189  ipcAddSendBuffer(cmd, buffer, size, BufferType_Normal);
190  ipcAddSendStatic(cmd, NULL, 0, index);
191  }
192 }
193 
194 /**
195  * @brief Adds a smart-receive-buffer (buffer + static-receive-buffer pair) to an IPC command structure.
196  * @param cmd IPC command structure.
197  * @param ipc_buffer_size IPC buffer size.
198  * @param buffer Address of the buffer.
199  * @param size Size of the buffer.
200  * @param index Index of buffer.
201  */
202 static inline void ipcAddRecvSmart(IpcCommand* cmd, size_t ipc_buffer_size, void* buffer, size_t size, u8 index) {
203  if (ipc_buffer_size != 0 && size <= ipc_buffer_size) {
204  ipcAddRecvBuffer(cmd, NULL, 0, BufferType_Normal);
205  ipcAddRecvStatic(cmd, buffer, size, index);
206  } else {
207  ipcAddRecvBuffer(cmd, buffer, size, BufferType_Normal);
208  ipcAddRecvStatic(cmd, NULL, 0, index);
209  }
210 }
211 
212 /**
213  * @brief Tags an IPC command structure to send the PID.
214  * @param cmd IPC command structure.
215  */
216 static inline void ipcSendPid(IpcCommand* cmd) {
217  cmd->SendPid = true;
218 }
219 
220 /**
221  * @brief Adds a copy-handle to be sent through an IPC command structure.
222  * @param cmd IPC command structure.
223  * @param h Handle to send.
224  * @remark The receiving process gets a copy of the handle.
225  */
226 static inline void ipcSendHandleCopy(IpcCommand* cmd, Handle h) {
227  cmd->Handles[cmd->NumHandlesCopy++] = h;
228 }
229 
230 /**
231  * @brief Adds a move-handle to be sent through an IPC command structure.
232  * @param cmd IPC command structure.
233  * @param h Handle to send.
234  * @remark The sending process loses ownership of the handle, which is transferred to the receiving process.
235  */
236 static inline void ipcSendHandleMove(IpcCommand* cmd, Handle h) {
237  cmd->Handles[cmd->NumHandlesCopy + cmd->NumHandlesMove++] = h;
238 }
239 
240 /**
241  * @brief Prepares the header of an IPC command structure.
242  * @param cmd IPC command structure.
243  * @param sizeof_raw Size in bytes of the raw data structure to embed inside the IPC request
244  * @return Pointer to the raw embedded data structure in the request, ready to be filled out.
245  */
246 static inline void* ipcPrepareHeader(IpcCommand* cmd, size_t sizeof_raw) {
247  u32* buf = (u32*)armGetTls();
248  size_t i;
249  *buf++ = IpcCommandType_Request | (cmd->NumStaticIn << 16) | (cmd->NumSend << 20) | (cmd->NumRecv << 24) | (cmd->NumExch << 28);
250 
251  u32* fill_in_size_later = buf;
252 
253  if (cmd->NumStaticOut > 0) {
254  *buf = (cmd->NumStaticOut + 2) << 10;
255  }
256  else {
257  *buf = 0;
258  }
259 
260  if (cmd->SendPid || cmd->NumHandlesCopy > 0 || cmd->NumHandlesMove > 0) {
261  *buf++ |= 0x80000000;
262  *buf++ = (!!cmd->SendPid) | (cmd->NumHandlesCopy << 1) | (cmd->NumHandlesMove << 5);
263 
264  if (cmd->SendPid)
265  buf += 2;
266 
267  for (i=0; i<(cmd->NumHandlesCopy + cmd->NumHandlesMove); i++)
268  *buf++ = cmd->Handles[i];
269  }
270  else {
271  buf++;
272  }
273 
274  for (i=0; i<cmd->NumStaticIn; i++, buf+=2) {
276 
277  uintptr_t ptr = (uintptr_t) cmd->Statics[i];
278  desc->Addr = ptr;
279  desc->Packed = cmd->StaticIndices[i] | (cmd->StaticSizes[i] << 16) |
280  (((ptr >> 32) & 15) << 12) | (((ptr >> 36) & 15) << 6);
281  }
282 
283  for (i=0; i<(cmd->NumSend + cmd->NumRecv + cmd->NumExch); i++, buf+=3) {
285  desc->Size = cmd->BufferSizes[i];
286 
287  uintptr_t ptr = (uintptr_t) cmd->Buffers[i];
288  desc->Addr = ptr;
289  desc->Packed = cmd->BufferTypes[i] |
290  (((ptr >> 32) & 15) << 28) | ((ptr >> 36) << 2);
291  }
292 
293  u32 padding = ((16 - (((uintptr_t) buf) & 15)) & 15) / 4;
294  u32* raw = (u32*) (buf + padding);
295 
296  size_t raw_size = (sizeof_raw/4) + 4;
297  buf += raw_size;
298 
299  u16* buf_u16 = (u16*) buf;
300 
301  for (i=0; i<cmd->NumStaticOut; i++) {
302  size_t off = cmd->NumStaticIn + i;
303  size_t sz = (uintptr_t) cmd->StaticSizes[off];
304 
305  buf_u16[i] = (sz > 0xFFFF) ? 0 : sz;
306  }
307 
308  size_t u16s_size = ((2*cmd->NumStaticOut) + 3)/4;
309  buf += u16s_size;
310  raw_size += u16s_size;
311 
312  *fill_in_size_later |= raw_size;
313 
314  for (i=0; i<cmd->NumStaticOut; i++, buf+=2) {
316  size_t off = cmd->NumStaticIn + i;
317 
318  uintptr_t ptr = (uintptr_t) cmd->Statics[off];
319  desc->Addr = ptr;
320  desc->Packed = (ptr >> 32) | (cmd->StaticSizes[off] << 16);
321  }
322 
323  return (void*) raw;
324 }
325 
326 /**
327  * @brief Dispatches an IPC request.
328  * @param session IPC session handle.
329  * @return Result code.
330  */
331 static inline Result ipcDispatch(Handle session) {
332  return svcSendSyncRequest(session);
333 }
334 
335 ///@}
336 
337 ///@name IPC response parsing
338 ///@{
339 
340 /// IPC parsed command (response) structure.
341 typedef struct {
342  IpcCommandType CommandType; ///< Type of the command
343 
344  bool HasPid; ///< true if the 'Pid' field is filled out.
345  u64 Pid; ///< PID included in the response (only if HasPid is true)
346 
347  size_t NumHandles; ///< Number of handles copied.
348  Handle Handles[IPC_MAX_OBJECTS]; ///< Handles.
349  bool WasHandleCopied[IPC_MAX_OBJECTS]; ///< true if the handle was moved, false if it was copied.
350 
351  u32 ThisObjectId; ///< Object ID to call the command on (for domain messages).
352  size_t NumObjectIds; ///< Number of object IDs (for domain messages).
353  u32 ObjectIds[IPC_MAX_OBJECTS]; ///< Object IDs (for domain messages).
354 
355  size_t NumBuffers; ///< Number of buffers in the response.
356  void* Buffers[IPC_MAX_BUFFERS]; ///< Pointers to the buffers.
357  size_t BufferSizes[IPC_MAX_BUFFERS]; ///< Sizes of the buffers.
358  BufferType BufferTypes[IPC_MAX_BUFFERS]; ///< Types of the buffers.
359  BufferDirection BufferDirections[IPC_MAX_BUFFERS]; ///< Direction of each buffer.
360 
361  size_t NumStatics; ///< Number of statics in the response.
362  void* Statics[IPC_MAX_BUFFERS]; ///< Pointers to the statics.
363  size_t StaticSizes[IPC_MAX_BUFFERS]; ///< Sizes of the statics.
364  u8 StaticIndices[IPC_MAX_BUFFERS]; ///< Indices of the statics.
365 
366  size_t NumStaticsOut; ///< Number of output statics available in the response.
367 
368  void* Raw; ///< Pointer to the raw embedded data structure in the response.
369  void* RawWithoutPadding; ///< Pointer to the raw embedded data structure, without padding.
370  size_t RawSize; ///< Size of the raw embedded data.
372 
373 /**
374  * @brief Parse an IPC command response into an IPC parsed command structure.
375  * @param IPC parsed command structure to fill in.
376  * @return Result code.
377  */
378 static inline Result ipcParse(IpcParsedCommand* r) {
379  u32* buf = (u32*)armGetTls();
380  u32 ctrl0 = *buf++;
381  u32 ctrl1 = *buf++;
382  size_t i;
383 
384  r->CommandType = (IpcCommandType) (ctrl0 & 0xffff);
385  r->HasPid = false;
386  r->RawSize = (ctrl1 & 0x1ff) * 4;
387  r->NumHandles = 0;
388 
389  r->NumStaticsOut = (ctrl1 >> 10) & 15;
390  if (r->NumStaticsOut >> 1) r->NumStaticsOut--; // Value 2 -> Single descriptor
391  if (r->NumStaticsOut >> 1) r->NumStaticsOut--; // Value 3+ -> (Value - 2) descriptors
392 
393  if (ctrl1 & 0x80000000) {
394  u32 ctrl2 = *buf++;
395 
396  if (ctrl2 & 1) {
397  r->HasPid = true;
398  r->Pid = *buf++;
399  r->Pid |= ((u64)(*buf++)) << 32;
400  }
401 
402  size_t num_handles_copy = ((ctrl2 >> 1) & 15);
403  size_t num_handles_move = ((ctrl2 >> 5) & 15);
404 
405  size_t num_handles = num_handles_copy + num_handles_move;
406  u32* buf_after_handles = buf + num_handles;
407 
408  if (num_handles > IPC_MAX_OBJECTS)
409  num_handles = IPC_MAX_OBJECTS;
410 
411  for (i=0; i<num_handles; i++)
412  {
413  r->Handles[i] = *(buf+i);
414  r->WasHandleCopied[i] = (i < num_handles_copy);
415  }
416 
417  r->NumHandles = num_handles;
418  buf = buf_after_handles;
419  }
420 
421  size_t num_statics = (ctrl0 >> 16) & 15;
422  u32* buf_after_statics = buf + num_statics*2;
423 
424  if (num_statics > IPC_MAX_BUFFERS)
425  num_statics = IPC_MAX_BUFFERS;
426 
427  for (i=0; i<num_statics; i++, buf+=2) {
429  u64 packed = (u64) desc->Packed;
430 
431  r->Statics[i] = (void*) (desc->Addr | (((packed >> 12) & 15) << 32) | (((packed >> 6) & 15) << 36));
432  r->StaticSizes[i] = packed >> 16;
433  r->StaticIndices[i] = packed & 63;
434  }
435 
436  r->NumStatics = num_statics;
437  buf = buf_after_statics;
438 
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;
442 
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);
445  r->RawWithoutPadding = (void*)((uintptr_t)(buf + num_bufs*3));
446 
447  if (num_bufs > IPC_MAX_BUFFERS)
448  num_bufs = IPC_MAX_BUFFERS;
449 
450  for (i=0; i<num_bufs; i++, buf+=3) {
452  u64 packed = (u64) desc->Packed;
453 
454  r->Buffers[i] = (void*) (desc->Addr | ((packed >> 28) << 32) | (((packed >> 2) & 15) << 36));
455  r->BufferSizes[i] = desc->Size;
456  r->BufferTypes[i] = (BufferType) (packed & 3);
457 
458  if (i < num_bufs_send)
459  r->BufferDirections[i] = BufferDirection_Send;
460  else if (i < (num_bufs_send + num_bufs_recv))
461  r->BufferDirections[i] = BufferDirection_Recv;
462  else
463  r->BufferDirections[i] = BufferDirection_Exch;
464  }
465 
466  r->NumBuffers = num_bufs;
467  return 0;
468 }
469 
470 /**
471  * @brief Queries the size of an IPC pointer buffer.
472  * @param session IPC session handle.
473  * @param size Output variable in which to store the size.
474  * @return Result code.
475  */
476 static inline Result ipcQueryPointerBufferSize(Handle session, size_t *size) {
477  u32* buf = (u32*)armGetTls();
478 
479  buf[0] = IpcCommandType_Control;
480  buf[1] = 8;
481  buf[2] = 0;
482  buf[3] = 0;
483  buf[4] = SFCI_MAGIC;
484  buf[5] = 0;
485  buf[6] = 3;
486  buf[7] = 0;
487 
488  Result rc = ipcDispatch(session);
489 
490  if (R_SUCCEEDED(rc)) {
492  ipcParse(&r);
493 
494  struct ipcQueryPointerBufferSizeResponse {
495  u64 magic;
496  u64 result;
497  u32 size;
498  } *raw = (struct ipcQueryPointerBufferSizeResponse*)r.Raw;
499 
500  rc = raw->result;
501 
502  if (R_SUCCEEDED(rc)) {
503  *size = raw->size & 0xffff;
504  }
505  }
506 
507  return rc;
508 }
509 
510 /**
511  * @brief Closes the IPC session with proper clean up.
512  * @param session IPC session handle.
513  * @return Result code.
514  */
515 static inline Result ipcCloseSession(Handle session) {
516  u32* buf = (u32*)armGetTls();
517  buf[0] = IpcCommandType_Close;
518  return ipcDispatch(session);
519 }
520 ///@}
521 
522 ///@name IPC domain handling
523 ///@{
524 
525 /**
526  * @brief Converts an IPC session handle into a domain.
527  * @param session IPC session handle.
528  * @param object_id_out Output variable in which to store the object ID.
529  * @return Result code.
530  */
531 static inline Result ipcConvertSessionToDomain(Handle session, u32* object_id_out) {
532  u32* buf = (u32*)armGetTls();
533 
534  buf[0] = IpcCommandType_Control;
535  buf[1] = 8;
536  buf[4] = SFCI_MAGIC;
537  buf[5] = 0;
538  buf[6] = 0;
539  buf[7] = 0;
540 
541  Result rc = ipcDispatch(session);
542 
543  if (R_SUCCEEDED(rc)) {
545  ipcParse(&r);
546 
547  struct ipcConvertSessionToDomainResponse {
548  u64 magic;
549  u64 result;
550  u32 object_id;
551  } *raw = (struct ipcConvertSessionToDomainResponse*)r.Raw;
552 
553  rc = raw->result;
554 
555  if (R_SUCCEEDED(rc)) {
556  *object_id_out = raw->object_id;
557  }
558  }
559 
560  return rc;
561 }
562 
563 /**
564  * @brief Adds an object ID to be sent through an IPC domain command structure.
565  * @param cmd IPC domain command structure.
566  * @param object_id Object ID to send.
567  */
568 static inline void ipcSendObjectId(IpcCommand* cmd, u32 object_id) {
569  cmd->ObjectIds[cmd->NumObjectIds++] = object_id;
570 }
571 
572 /// IPC domain message header.
573 typedef struct {
574  u8 Type;
575  u8 NumObjectIds;
576  u16 Length;
577  u32 ThisObjectId;
578  u32 Pad[2];
580 
581 /**
582  * @brief Prepares the header of an IPC command structure (domain version).
583  * @param cmd IPC command structure.
584  * @param sizeof_raw Size in bytes of the raw data structure to embed inside the IPC request
585  * @oaram object_id Domain object ID.
586  * @return Pointer to the raw embedded data structure in the request, ready to be filled out.
587  */
588 static inline void* ipcPrepareHeaderForDomain(IpcCommand* cmd, size_t sizeof_raw, u32 object_id) {
589  void* raw = ipcPrepareHeader(cmd, sizeof_raw + sizeof(DomainMessageHeader));
591  u32 *object_ids = (u32*)(((uintptr_t) raw) + sizeof(DomainMessageHeader) + sizeof_raw);
592 
593  hdr->Type = 1;
594  hdr->NumObjectIds = (u8)cmd->NumObjectIds;
595  hdr->Length = sizeof_raw;
596  hdr->ThisObjectId = object_id;
597  hdr->Pad[0] = hdr->Pad[1] = 0;
598 
599  for(size_t i = 0; i < cmd->NumObjectIds; i++)
600  object_ids[i] = cmd->ObjectIds[i];
601  return (void*)(((uintptr_t) raw) + sizeof(DomainMessageHeader));
602 }
603 
604 /**
605  * @brief Parse an IPC command response into an IPC parsed command structure (domain version).
606  * @param IPC parsed command structure to fill in.
607  * @return Result code.
608  */
610  Result rc = ipcParse(r);
611  DomainMessageHeader* hdr;
612  u32 *object_ids;
613  if(R_FAILED(rc))
614  return rc;
615 
616  hdr = (DomainMessageHeader*) r->Raw;
617  object_ids = (u32*)(((uintptr_t) hdr) + sizeof(DomainMessageHeader) + hdr->Length);
618  r->Raw = (void*)(((uintptr_t) r->Raw) + sizeof(DomainMessageHeader));
619 
620  r->ThisObjectId = hdr->ThisObjectId;
621  r->NumObjectIds = hdr->NumObjectIds > 8 ? 8 : hdr->NumObjectIds;
622  for(size_t i = 0; i < r->NumObjectIds; i++)
623  r->ObjectIds[i] = object_ids[i];
624 
625  return rc;
626 }
627 
628 /**
629  * @brief Closes a domain object by ID.
630  * @param session IPC session handle.
631  * @param object_id ID of the object to close.
632  * @return Result code.
633  */
634 static inline Result ipcCloseObjectById(Handle session, u32 object_id) {
635  IpcCommand c;
636  DomainMessageHeader* hdr;
637 
638  ipcInitialize(&c);
640 
641  hdr->Type = 2;
642  hdr->NumObjectIds = 0;
643  hdr->Length = 0;
644  hdr->ThisObjectId = object_id;
645  hdr->Pad[0] = hdr->Pad[1] = 0;
646 
647  return ipcDispatch(session); // this command has no associated response
648 }
649 
650 ///@}
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
Definition: ipc.h:51
#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 &#39;Pid&#39; 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