1 /*
2 * Copyright (c) 2022 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28
29 #ifndef _MACH_EXCLAVES_L4_H
30 #define _MACH_EXCLAVES_L4_H
31
32 #include <mach/exclaves.h>
33
34 /*
35 * Equivalent versions of the subset of cL4 APIs needed for construction of
36 * IPC message buffers & tags (with prefix changed L4_ -> Exclaves_L4_)
37 */
38
39 __BEGIN_DECLS
40
41 #ifdef PRIVATE
42
43 #if defined(__LP64__)
44
45 /* -------------------------------------------------------------------------- */
46
47 /* Void data type */
48 typedef void Exclaves_L4_Void_t;
49
50 /** Boolean data type */;
51 typedef unsigned char Exclaves_L4_Bool_t;
52
53 /** Unsigned 32-bit data type */
54 typedef unsigned int Exclaves_L4_Word32_t;
55
56 /** Unsigned data type with native word length size */
57 typedef unsigned long Exclaves_L4_Word_t;
58
59 /** Data type for L4 system call return values */
60 typedef Exclaves_L4_Word_t Exclaves_L4_Error_t;
61
62 /**
63 * Convert a value into a native word type
64 *
65 * @param x Value to convert
66 * @return Value cast to the native word type
67 */
68 #define Exclaves_L4_Word(x) ((Exclaves_L4_Word_t) (x))
69
70 /**
71 * Convert a value into a 32-bit word type
72 *
73 * @param x Value to convert
74 * @return Value cast to the 32-bit word type
75 */
76 #define Exclaves_L4_Word32(x) ((Exclaves_L4_Word32_t) (x))
77
78 #define __Exclaves_L4_Packed __attribute__ ((__packed__))
79
80 /* Size of native word length in bits */
81 #define Exclaves_L4_WordBits (64)
82
83 /**
84 * Produce a bitfield mask
85 *
86 * @param base Starting bit position within the created mask
87 * @param bits Number of bits to set in the mask
88 * @return A mask value
89 */
90 #define Exclaves_L4_BfmW(base, bits) \
91 (((~Exclaves_L4_Word(0)) >> (Exclaves_L4_WordBits - (bits))) << (base))
92
93 /**
94 * Extract a value from a bitfield
95 *
96 * @param bitfield Bitfield contents to extract a value from
97 * @param base Starting bit position of the value to extract
98 * @param bits Number of bits for the value within the bitfield
99 * @return The extracted value
100 */
101 #define Exclaves_L4_BfxW(bitfield, base, bits) \
102 (((bitfield) & Exclaves_L4_BfmW((base), (bits))) >> (base))
103
104 /**
105 * Return a bitfield with a particular value inserted
106 *
107 * @param bitfield Bitfield current contents
108 * @param base Starting bit position of the value to insert
109 * @param bits Number of bits for the value within the bitfield
110 * @param value Value to insert
111 * @return The bitfield with the value inserted, overwriting any previous
112 * value in the corresponding bits
113 */
114 #define Exclaves_L4_BfiW(bitfield, base, bits, value) \
115 (((bitfield) & (~Exclaves_L4_BfmW((base), (bits)))) | \
116 (((Exclaves_L4_Word(value)) << (base)) & Exclaves_L4_BfmW((base), (bits))))
117
118 /**
119 * Return an otherwise empty bitfield that had a value inserted
120 *
121 * @param base Starting bit position of the value to insert
122 * @param bits Number of bits for the value within the bitfield
123 * @param value Value to insert
124 * @return The value encoded in the bitfield, with all other bits set to 0.
125 */
126 #define Exclaves_L4_BfW(base, bits, value) \
127 (Exclaves_L4_BfiW(Exclaves_L4_Word(0), (base), (bits), (value)))
128
129 /** Nil (zero) value */
130 #define Exclaves_L4_Nil ((Exclaves_L4_Word_t) 0)
131
132 /** Boolean true value */
133 #define Exclaves_L4_True ((Exclaves_L4_Bool_t) 1)
134
135 /** Boolean false value */
136 #define Exclaves_L4_False ((Exclaves_L4_Bool_t) 0)
137
138 /* -------------------------------------------------------------------------- */
139
140 /**
141 * Create an Exclaves_L4_Error from a provided code and value
142 *
143 * @param code Specific Exclaves_L4_Error code
144 * @param value Supplementary information providing more context about
145 * the error
146 * @return The complete error value
147 */
148 #define Exclaves_L4_Error(code, value) (((Exclaves_L4_Word(value)) << 8) | (Exclaves_L4_Word(code)))
149
150 /**
151 * Extract the error code from a constructed Exclaves_L4_Error_t
152 *
153 * @param error The error
154 * @return The error code
155 */
156 #define Exclaves_L4_ErrorCode(error) ((error) & (((Exclaves_L4_Word(1)) << 8) - 1))
157
158 /**
159 * Extract the error value from a constructed Exclaves_L4_Error_t
160 *
161 * @param error The error
162 * @return The error value
163 */
164 #define Exclaves_L4_ErrorValue(error) ((error) >> 8)
165
166 /**
167 * L4 error codes
168 */
169
170 enum {
171 Exclaves_L4_ErrorCodeSuccess,
172 Exclaves_L4_ErrorCodePreempted,
173 Exclaves_L4_ErrorCodeCanceled,
174 Exclaves_L4_ErrorCodeTruncated,
175 Exclaves_L4_ErrorCodeCapInvalid,
176 Exclaves_L4_ErrorCodeSlotInvalid,
177 Exclaves_L4_ErrorCodeMethodInvalid,
178 Exclaves_L4_ErrorCodeArgumentInvalid,
179 Exclaves_L4_ErrorCodeOperationInvalid,
180 Exclaves_L4_ErrorCodePermissionInvalid,
181 Exclaves_L4_ErrorCodeMax
182 };
183
184 #define Exclaves_L4_Success \
185 Exclaves_L4_Error(Exclaves_L4_ErrorCodeSuccess, Exclaves_L4_Nil)
186 #define Exclaves_L4_Preempted \
187 Exclaves_L4_Error(Exclaves_L4_ErrorCodePreempted, Exclaves_L4_Nil)
188 #define Exclaves_L4_ErrorCanceled(reason) \
189 Exclaves_L4_Error(Exclaves_L4_ErrorCodeCanceled, reason)
190 #define Exclaves_L4_ErrorTruncated \
191 Exclaves_L4_Error(Exclaves_L4_ErrorCodeTruncated, Exclaves_L4_Nil)
192 #define Exclaves_L4_ErrorCapInvalid \
193 Exclaves_L4_Error(Exclaves_L4_ErrorCodeCapInvalid, Exclaves_L4_Nil)
194 #define Exclaves_L4_ErrorSlotInvalid \
195 Exclaves_L4_Error(Exclaves_L4_ErrorCodeSlotInvalid, Exclaves_L4_Nil)
196 #define Exclaves_L4_ErrorMethodInvalid \
197 Exclaves_L4_Error(Exclaves_L4_ErrorCodeMethodInvalid, Exclaves_L4_Nil)
198 #define Exclaves_L4_ErrorArgumentInvalid(argument) \
199 Exclaves_L4_Error(Exclaves_L4_ErrorCodeArgumentInvalid, argument)
200 #define Exclaves_L4_ErrorOperationInvalid \
201 Exclaves_L4_Error(Exclaves_L4_ErrorCodeOperationInvalid, Exclaves_L4_Nil)
202 #define Exclaves_L4_ErrorPermissionInvalid \
203 Exclaves_L4_Error(Exclaves_L4_ErrorCodePermissionInvalid, Exclaves_L4_Nil)
204
205 /* -------------------------------------------------------------------------- */
206
207 /* Exclaves_L4_MessageTag_t
208 *
209 * 32 0
210 * llllllllllllllll...nuuucccrrrrrr
211 *
212 * r: message registers (6 bits)
213 * c: capability registers (3 bits)
214 * u: unwrapped capabilities (3 bits)
215 * n: non-blocking (1 bit)
216 * l: label (16 bits)
217 */
218
219 typedef Exclaves_L4_Word_t Exclaves_L4_MessageTag_t;
220
221 /* Exclaves_L4_MessageTag_Mrs */
222 #define Exclaves_L4_MessageTag_Mrs_Base 0
223 #define Exclaves_L4_MessageTag_Mrs_Bits 6
224
225 /* Exclaves_L4_MessageTag_Crs */
226 #define Exclaves_L4_MessageTag_Crs_Base 6
227 #define Exclaves_L4_MessageTag_Crs_Bits 3
228
229 /* Exclaves_L4_MessageTag_Unwrapped */
230 #define Exclaves_L4_MessageTag_Unwrapped_Base 9
231 #define Exclaves_L4_MessageTag_Unwrapped_Bits 3
232
233 /* Exclaves_L4_MessageTag_NonBlocking */
234 #define Exclaves_L4_MessageTag_NonBlocking_Base 12
235 #define Exclaves_L4_MessageTag_NonBlocking_Bits 1
236
237 /* Exclaves_L4_MessageTag_Label */
238 #define Exclaves_L4_MessageTag_Label_Base 16
239 #define Exclaves_L4_MessageTag_Label_Bits 16
240
241 static inline Exclaves_L4_Word_t
Exclaves_L4_MessageTag_Mrs(Exclaves_L4_MessageTag_t tag)242 Exclaves_L4_MessageTag_Mrs(Exclaves_L4_MessageTag_t tag)
243 {
244 return Exclaves_L4_Word(Exclaves_L4_BfxW(tag, Exclaves_L4_MessageTag_Mrs_Base,
245 Exclaves_L4_MessageTag_Mrs_Bits));
246 }
247
248 static inline Exclaves_L4_Word_t
Exclaves_L4_MessageTag_Crs(Exclaves_L4_MessageTag_t tag)249 Exclaves_L4_MessageTag_Crs(Exclaves_L4_MessageTag_t tag)
250 {
251 return Exclaves_L4_Word(Exclaves_L4_BfxW(tag, Exclaves_L4_MessageTag_Crs_Base,
252 Exclaves_L4_MessageTag_Crs_Bits));
253 }
254
255 static inline Exclaves_L4_Word_t
Exclaves_L4_MessageTag_Unwrapped(Exclaves_L4_MessageTag_t tag)256 Exclaves_L4_MessageTag_Unwrapped(Exclaves_L4_MessageTag_t tag)
257 {
258 return Exclaves_L4_Word(Exclaves_L4_BfxW(tag, Exclaves_L4_MessageTag_Unwrapped_Base,
259 Exclaves_L4_MessageTag_Unwrapped_Bits));
260 }
261
262 static inline Exclaves_L4_Word_t
Exclaves_L4_MessageTag_Label(Exclaves_L4_MessageTag_t tag)263 Exclaves_L4_MessageTag_Label(Exclaves_L4_MessageTag_t tag)
264 {
265 return Exclaves_L4_Word(Exclaves_L4_BfxW(tag, Exclaves_L4_MessageTag_Label_Base,
266 Exclaves_L4_MessageTag_Label_Bits));
267 }
268
269 static inline Exclaves_L4_MessageTag_t
Exclaves_L4_MessageTag(Exclaves_L4_Word_t mrs,Exclaves_L4_Word_t crs,Exclaves_L4_Word_t label,Exclaves_L4_Bool_t nonblocking)270 Exclaves_L4_MessageTag(Exclaves_L4_Word_t mrs, Exclaves_L4_Word_t crs, Exclaves_L4_Word_t label,
271 Exclaves_L4_Bool_t nonblocking)
272 {
273 Exclaves_L4_Word_t tag = (
274 Exclaves_L4_BfW(Exclaves_L4_MessageTag_Mrs_Base,
275 Exclaves_L4_MessageTag_Mrs_Bits, Exclaves_L4_Word(mrs)) |
276 Exclaves_L4_BfW(Exclaves_L4_MessageTag_Crs_Base,
277 Exclaves_L4_MessageTag_Crs_Bits, Exclaves_L4_Word(crs)) |
278 Exclaves_L4_BfW(Exclaves_L4_MessageTag_NonBlocking_Base,
279 Exclaves_L4_MessageTag_NonBlocking_Bits, Exclaves_L4_Word(nonblocking)) |
280 Exclaves_L4_BfW(Exclaves_L4_MessageTag_Label_Base,
281 Exclaves_L4_MessageTag_Label_Bits, Exclaves_L4_Word(label)));
282
283 return (Exclaves_L4_MessageTag_t) tag;
284 }
285
286 /* -------------------------------------------------------------------------- */
287
288 /* Exclaves_L4_IpcBuffer_t */
289
290 /* number of ipc buffer message registers */
291 #define Exclaves_L4_IpcBuffer_Mrs 56
292 /* numver of ipc buffer capability registers */
293 #define Exclaves_L4_IpcBuffer_Crs 4
294 /* ipc buffer size */
295 #define Exclaves_L4_IpcBuffer_Size (sizeof(Exclaves_L4_IpcBuffer_t))
296
297 /* ipc buffer object */
298 typedef struct __Exclaves_L4_Packed {
299 /* message registers */
300 Exclaves_L4_Word_t mr[Exclaves_L4_IpcBuffer_Mrs];
301 /* source capability registers */
302 Exclaves_L4_Word_t scr[Exclaves_L4_IpcBuffer_Crs];
303 /* destination capability registers */
304 Exclaves_L4_Word_t dcr[Exclaves_L4_IpcBuffer_Crs];
305 } Exclaves_L4_IpcBuffer_t;
306
307 /** Cast to a Exclaves IPC buffer pointer */
308 #define Exclaves_L4_IpcBuffer_Ptr(x) \
309 (__unsafe_forge_single(Exclaves_L4_IpcBuffer_t *, (x)))
310
311 /* L4 IPC invocation message registers */
312 enum {
313 Exclaves_L4_Ipc_Mr_Tag,
314 Exclaves_L4_Ipc_Mr_Badge,
315 Exclaves_L4_Ipc_Mr_Message
316 };
317
318 #ifdef KERNEL_PRIVATE
319
320 static inline Exclaves_L4_IpcBuffer_t *
Exclaves_L4_IpcBuffer(Exclaves_L4_Void_t)321 Exclaves_L4_IpcBuffer(Exclaves_L4_Void_t)
322 {
323 return Exclaves_L4_IpcBuffer_Ptr(exclaves_get_ipc_buffer());
324 }
325
326 #endif /* KERNEL_PRIVATE */
327
328 #ifdef MACH_KERNEL_PRIVATE
329
330 /* -------------------------------------------------------------------------- */
331
332 static inline Exclaves_L4_Word_t
Exclaves_L4_GetMr(Exclaves_L4_Word32_t mr)333 Exclaves_L4_GetMr(Exclaves_L4_Word32_t mr)
334 {
335 return Exclaves_L4_IpcBuffer()->mr[mr];
336 }
337
338 static inline Exclaves_L4_Void_t
Exclaves_L4_SetMr(Exclaves_L4_Word32_t mr,Exclaves_L4_Word_t word)339 Exclaves_L4_SetMr(Exclaves_L4_Word32_t mr, Exclaves_L4_Word_t word)
340 {
341 Exclaves_L4_IpcBuffer()->mr[mr] = word;
342 }
343
344 static inline Exclaves_L4_Void_t
Exclaves_L4_SetMrs(Exclaves_L4_Word32_t mr,Exclaves_L4_Word32_t count,Exclaves_L4_Word_t * __counted_by (count)words)345 Exclaves_L4_SetMrs(Exclaves_L4_Word32_t mr, Exclaves_L4_Word32_t count,
346 Exclaves_L4_Word_t * __counted_by(count)words)
347 {
348 Exclaves_L4_IpcBuffer_t *ipcb = Exclaves_L4_IpcBuffer();
349
350 for (Exclaves_L4_Word32_t offset = 0; offset < count; offset++) {
351 ipcb->mr[mr + offset] = words[offset];
352 }
353 }
354
355 static inline Exclaves_L4_Void_t
Exclaves_L4_GetMrs(Exclaves_L4_Word32_t mr,Exclaves_L4_Word32_t count,Exclaves_L4_Word_t * __counted_by (count)words)356 Exclaves_L4_GetMrs(Exclaves_L4_Word32_t mr, Exclaves_L4_Word32_t count,
357 Exclaves_L4_Word_t * __counted_by(count)words)
358 {
359 Exclaves_L4_IpcBuffer_t *ipcb = Exclaves_L4_IpcBuffer();
360
361 for (Exclaves_L4_Word32_t offset = 0; offset < count; offset++) {
362 words[offset] = ipcb->mr[mr + offset];
363 }
364 }
365
366 static inline Exclaves_L4_Word_t
Exclaves_L4_GetCr(Exclaves_L4_Word32_t cr,Exclaves_L4_Bool_t dst)367 Exclaves_L4_GetCr(Exclaves_L4_Word32_t cr, Exclaves_L4_Bool_t dst)
368 {
369 if (dst == Exclaves_L4_True) {
370 return Exclaves_L4_IpcBuffer()->dcr[cr];
371 } else {
372 return Exclaves_L4_IpcBuffer()->scr[cr];
373 }
374 }
375
376 static inline Exclaves_L4_Void_t
Exclaves_L4_SetCr(Exclaves_L4_Word32_t cr,Exclaves_L4_Word_t word,Exclaves_L4_Bool_t dst)377 Exclaves_L4_SetCr(Exclaves_L4_Word32_t cr, Exclaves_L4_Word_t word, Exclaves_L4_Bool_t dst)
378 {
379 if (dst == Exclaves_L4_True) {
380 Exclaves_L4_IpcBuffer()->dcr[cr] = word;
381 } else {
382 Exclaves_L4_IpcBuffer()->scr[cr] = word;
383 }
384 }
385
386 static inline Exclaves_L4_MessageTag_t
Exclaves_L4_GetMessageTag(Exclaves_L4_Void_t)387 Exclaves_L4_GetMessageTag(Exclaves_L4_Void_t)
388 {
389 return (Exclaves_L4_MessageTag_t) (Exclaves_L4_GetMr(Exclaves_L4_Ipc_Mr_Tag));
390 }
391
392 static inline Exclaves_L4_Void_t
Exclaves_L4_SetMessageTag(Exclaves_L4_MessageTag_t tag)393 Exclaves_L4_SetMessageTag(Exclaves_L4_MessageTag_t tag)
394 {
395 Exclaves_L4_SetMr(Exclaves_L4_Ipc_Mr_Tag, Exclaves_L4_Word(tag));
396 }
397
398 static inline Exclaves_L4_Word_t
Exclaves_L4_GetMessageMr(Exclaves_L4_Word32_t mr)399 Exclaves_L4_GetMessageMr(Exclaves_L4_Word32_t mr)
400 {
401 return Exclaves_L4_GetMr(Exclaves_L4_Ipc_Mr_Message + mr);
402 }
403
404 static inline Exclaves_L4_Void_t
Exclaves_L4_SetMessageMr(Exclaves_L4_Word32_t mr,Exclaves_L4_Word_t word)405 Exclaves_L4_SetMessageMr(Exclaves_L4_Word32_t mr, Exclaves_L4_Word_t word)
406 {
407 Exclaves_L4_SetMr((Exclaves_L4_Ipc_Mr_Message + mr), word);
408 }
409
410 #endif /* MACH_KERNEL_PRIVATE */
411
412 /* -------------------------------------------------------------------------- */
413
414 /* Private communication protocol between Libsyscall, xnu and xnu proxy */
415
416 /* Return value of the endpoint message forwarding call. */
417 #define EXCLAVES_XNU_PROXY_CR_RETVAL(ipcb) ((ipcb)->dcr[3])
418
419 /* identifiers for exclaves reachable through xnuproxy */
420 typedef enum : uint64_t {
421 /* HelloExclaves: c-hello-exclave */
422 EXCLAVES_XNUPROXY_EXCLAVE_HELLOEXCLAVE = 0,
423 /* templated user_app */
424 EXCLAVES_XNUPROXY_EXCLAVE_USERAPP,
425 /* HelloTightbeam: swift-hello-exclave */
426 EXCLAVES_XNUPROXY_EXCLAVE_HELLOTIGHTBEAM,
427 /* HelloDrivers */
428 EXCLAVES_XNUPROXY_EXCLAVE_HELLODRIVERS,
429 /* HelloStorage */
430 EXCLAVES_XNUPROXY_EXCLAVE_HELLOSTORAGE,
431 /* templated user_app2 */
432 EXCLAVES_XNUPROXY_EXCLAVE_USERAPP2,
433 /* templated user_app3 */
434 EXCLAVES_XNUPROXY_EXCLAVE_USERAPP3,
435 /* audio */
436 EXCLAVES_XNUPROXY_EXCLAVE_AUDIODRIVER,
437 /* HelloDriverInterrupts */
438 EXCLAVES_XNUPROXY_EXCLAVE_HELLODRIVERINTERRUPTS,
439 /* ExclaveDriverKit */
440 EXCLAVES_XNUPROXY_EXCLAVE_EXCLAVEDRIVERKIT,
441 /* SecureRTBuddy for AOP */
442 EXCLAVES_XNUPROXY_EXCLAVE_SECURERTBUDDY_AOP,
443 /* SecureRTBuddy for DCP */
444 EXCLAVES_XNUPROXY_EXCLAVE_SECURERTBUDDY_DCP,
445 /* conclave launcher control */
446 EXCLAVES_XNUPROXY_EXCLAVE_CONCLAVECONTROL,
447 /* conclave launcher control */
448 EXCLAVES_XNUPROXY_EXCLAVE_CONCLAVEDEBUG,
449 /* SecureRTBuddy EDK connection for AOP */
450 EXCLAVES_XNUPROXY_EXCLAVE_SECURERTBUDDY_AOP_EDK,
451 /* SecureRTBuddy EDK connection for DCP */
452 EXCLAVES_XNUPROXY_EXCLAVE_SECURERTBUDDY_DCP_EDK,
453 } exclaves_xnuproxy_exclaves_t;
454
455 typedef enum : uint32_t {
456 EXCLAVES_XNUPROXY_TEST_BUF1 = 1,
457 EXCLAVES_XNUPROXY_TEST_BUF2,
458 EXCLAVES_XNUPROXY_TEST_BUF3,
459 EXCLAVES_XNUPROXY_TEST_BUF4,
460 /* 5 is empty */
461 EXCLAVES_XNUPROXY_NAMED_BUFFER_STORAGE_BUF_1 = 6,
462 EXCLAVES_XNUPROXY_NAMED_BUFFER_STORAGE_BUF_2 = 7,
463
464 EXCLAVES_XNUPROXY_LAST_STATIC_BUF = 111,
465 EXCLAVES_XNUPROXY_TEST_DYN_BUF1,
466 EXCLAVES_XNUPROXY_TEST_DYN_BUF2,
467 } exclaves_named_buffer_id_t;
468
469 #endif /* defined(__LP64__) */
470
471 #endif /* PRIVATE */
472
473 __END_DECLS
474
475 #endif /* _MACH_EXCLAVES_L4_H */
476