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