11 #define CMIF_IN_HEADER_MAGIC 0x49434653
12 #define CMIF_OUT_HEADER_MAGIC 0x4F434653
14 typedef enum CmifCommandType {
15 CmifCommandType_Invalid = 0,
16 CmifCommandType_LegacyRequest = 1,
17 CmifCommandType_Close = 2,
18 CmifCommandType_LegacyControl = 3,
19 CmifCommandType_Request = 4,
20 CmifCommandType_Control = 5,
21 CmifCommandType_RequestWithContext = 6,
22 CmifCommandType_ControlWithContext = 7,
25 typedef enum CmifDomainRequestType {
26 CmifDomainRequestType_Invalid = 0,
27 CmifDomainRequestType_SendMessage = 1,
28 CmifDomainRequestType_Close = 2,
29 } CmifDomainRequestType;
64 u32 server_pointer_size;
65 u32 num_in_auto_buffers;
66 u32 num_out_auto_buffers;
69 u32 num_inout_buffers;
72 u32 num_out_fixed_pointers;
81 u16* out_pointer_sizes;
83 u32 server_pointer_size;
94 NX_INLINE void* cmifGetAlignedDataStart(
u32* data_words,
void* base)
96 intptr_t data_start = ((
u8*)data_words - (
u8*)base + 15) &~ 15;
97 return (
u8*)base + data_start;
103 u32 actual_size = 16;
107 actual_size = (actual_size + 1) &~ 1;
108 u32 out_pointer_size_table_offset = actual_size;
109 u32 out_pointer_size_table_size = fmt.num_out_auto_buffers + fmt.num_out_pointers;
110 actual_size +=
sizeof(
u16)*out_pointer_size_table_size;
111 u32 num_data_words = (actual_size + 3) / 4;
114 req.hipc = hipcMakeRequestInline(base,
115 .type = fmt.context ? CmifCommandType_RequestWithContext : CmifCommandType_Request,
116 .num_send_statics = fmt.num_in_auto_buffers + fmt.num_in_pointers,
117 .num_send_buffers = fmt.num_in_auto_buffers + fmt.num_in_buffers,
118 .num_recv_buffers = fmt.num_out_auto_buffers + fmt.num_out_buffers,
119 .num_exch_buffers = fmt.num_inout_buffers,
120 .num_data_words = num_data_words,
121 .num_recv_statics = out_pointer_size_table_size + fmt.num_out_fixed_pointers,
122 .send_pid = fmt.send_pid,
123 .num_copy_handles = fmt.num_handles,
124 .num_move_handles = 0,
128 void* start = cmifGetAlignedDataStart(req.hipc.data_words, base);
133 .type = CmifDomainRequestType_SendMessage,
134 .num_in_objects = (
u8)fmt.num_objects,
135 .data_size = (
u16)payload_size,
136 .object_id = fmt.object_id,
138 .token = fmt.context,
141 req.objects = (
u32*)((
u8*)hdr + payload_size);
146 .magic = CMIF_IN_HEADER_MAGIC,
147 .version = fmt.context ? 1U : 0U,
148 .command_id = fmt.request_id,
149 .token = fmt.object_id ? 0U : fmt.context,
153 req.out_pointer_sizes = (
u16*)(
void*)((
u8*)(
void*)req.hipc.data_words + out_pointer_size_table_offset);
154 req.server_pointer_size = fmt.server_pointer_size;
159 NX_INLINE void* cmifMakeControlRequest(
void* base,
u32 request_id,
u32 size)
163 .type = CmifCommandType_Control,
164 .num_data_words = (actual_size + 3) / 4,
168 .magic = CMIF_IN_HEADER_MAGIC,
170 .command_id = request_id,
176 NX_INLINE void cmifMakeCloseRequest(
void* base,
u32 object_id)
180 .type = CmifCommandType_Request,
185 .type = CmifDomainRequestType_Close,
186 .object_id = object_id,
189 hipcMakeRequestInline(base,
190 .type = CmifCommandType_Close,
197 *req->hipc.send_buffers++ = hipcMakeBuffer(buffer, size, mode);
202 *req->hipc.recv_buffers++ = hipcMakeBuffer(buffer, size, mode);
207 *req->hipc.exch_buffers++ = hipcMakeBuffer(buffer, size, mode);
212 *req->hipc.send_statics++ = hipcMakeSendStatic(buffer, size, req->cur_in_ptr_id++);
213 req->server_pointer_size -= size;
218 *req->hipc.recv_list++ = hipcMakeRecvStatic(buffer, size);
219 req->server_pointer_size -= size;
224 cmifRequestOutFixedPointer(req, buffer, size);
225 *req->out_pointer_sizes++ = size;
228 NX_CONSTEXPR void cmifRequestInAutoBuffer(
CmifRequest* req,
const void* buffer,
size_t size, HipcBufferMode mode)
230 if (req->server_pointer_size && size <= req->server_pointer_size) {
231 cmifRequestInPointer(req, buffer, size);
232 cmifRequestInBuffer(req, NULL, 0, mode);
234 cmifRequestInPointer(req, NULL, 0);
235 cmifRequestInBuffer(req, buffer, size, mode);
241 if (req->server_pointer_size && size <= req->server_pointer_size) {
242 cmifRequestOutPointer(req, buffer, size);
243 cmifRequestOutBuffer(req, NULL, 0, mode);
245 cmifRequestOutPointer(req, NULL, 0);
246 cmifRequestOutBuffer(req, buffer, size, mode);
252 *req->objects++ = object_id;
257 *req->hipc.copy_handles++ = handle;
263 void* start = cmifGetAlignedDataStart(hipc.data_words, base);
275 if (hdr->magic != CMIF_OUT_HEADER_MAGIC)
276 return MAKERESULT(Module_Libnx, LibnxError_InvalidCmifOutHeader);
283 .copy_handles = hipc.copy_handles,
284 .move_handles = hipc.move_handles,
292 return *res->objects++;
297 return *res->copy_handles++;
302 return *res->move_handles++;
307 cmifMakeControlRequest(
armGetTls(), 0, 0);
311 rc = cmifParseResponse(&resp,
armGetTls(),
false,
sizeof(
u32));
313 *out_object_id = *(
u32*)resp.data;
320 void* raw = cmifMakeControlRequest(
armGetTls(), 1,
sizeof(
u32));
321 *(
u32*)raw = object_id;
325 rc = cmifParseResponse(&resp,
armGetTls(),
false, 0);
327 *out_h = resp.move_handles[0];
334 cmifMakeControlRequest(
armGetTls(), 2, 0);
338 rc = cmifParseResponse(&resp,
armGetTls(),
false, 0);
340 *out_h = resp.move_handles[0];
347 cmifMakeControlRequest(
armGetTls(), 3, 0);
351 rc = cmifParseResponse(&resp,
armGetTls(),
false,
sizeof(
u16));
353 *out_size = *(
u16*)resp.data;
360 void* raw = cmifMakeControlRequest(
armGetTls(), 4,
sizeof(
u32));
365 rc = cmifParseResponse(&resp,
armGetTls(),
false, 0);
367 *out_h = resp.move_handles[0];
Horizon Inter-Process Communication protocol.
#define R_FAILED(res)
Checks whether a result code indicates failure.
Definition: result.h:12
#define MAKERESULT(module, description)
Builds a result code from its constituent components.
Definition: result.h:21
#define R_SUCCEEDED(res)
Checks whether a result code indicates success.
Definition: result.h:10
Result svcSendSyncRequest(Handle session)
Sends an IPC synchronization request to a session.
static void * armGetTls(void)
Gets the thread local storage buffer.
Definition: tls.h:14
#define NX_INLINE
Flags a function as (always) inline.
Definition: types.h:86
uint8_t u8
8-bit unsigned integer.
Definition: types.h:19
u32 Handle
Kernel object handle.
Definition: types.h:43
uint16_t u16
16-bit unsigned integer.
Definition: types.h:20
u32 Result
Function error code result type.
Definition: types.h:44
#define NX_CONSTEXPR
Flags a function as constexpr in C++14 and above; or as (always) inline otherwise.
Definition: types.h:92
uint32_t u32
32-bit unsigned integer.
Definition: types.h:21