/*
* Copyright (c) 2022 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. The rights granted to you under the License
* may not be used to create, or enable the creation or redistribution of,
* unlawful or unlicensed copies of an Apple operating system, or to
* circumvent, violate, or enable the circumvention or violation of, any
* terms of an Apple operating system software license agreement.
*
* Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_END@
*/
#ifndef _MACH_EXCLAVES_L4_H
#define _MACH_EXCLAVES_L4_H
#include <mach/exclaves.h>
/*
* Equivalent versions of the subset of cL4 APIs needed for construction of
* IPC message buffers & tags (with prefix changed L4_ -> Exclaves_L4_)
*/
__BEGIN_DECLS
#ifdef PRIVATE
#if defined(__LP64__)
#ifndef EXCLAVES_NO_L4_TYPES
/* -------------------------------------------------------------------------- */
/* Void data type */
typedef void Exclaves_L4_Void_t;
/** Boolean data type */;
typedef unsigned char Exclaves_L4_Bool_t;
/** Unsigned 32-bit data type */
typedef unsigned int Exclaves_L4_Word32_t;
/** Unsigned data type with native word length size */
typedef unsigned long Exclaves_L4_Word_t;
/** Data type for L4 system call return values */
typedef Exclaves_L4_Word_t Exclaves_L4_Error_t;
/**
* Convert a value into a native word type
*
* @param x Value to convert
* @return Value cast to the native word type
*/
#define Exclaves_L4_Word(x) ((Exclaves_L4_Word_t) (x))
/**
* Convert a value into a 32-bit word type
*
* @param x Value to convert
* @return Value cast to the 32-bit word type
*/
#define Exclaves_L4_Word32(x) ((Exclaves_L4_Word32_t) (x))
#define __Exclaves_L4_Packed __attribute__ ((__packed__))
/* Size of native word length in bits */
#define Exclaves_L4_WordBits (64)
/**
* Produce a bitfield mask
*
* @param base Starting bit position within the created mask
* @param bits Number of bits to set in the mask
* @return A mask value
*/
#define Exclaves_L4_BfmW(base, bits) \
(((~Exclaves_L4_Word(0)) >> (Exclaves_L4_WordBits - (bits))) << (base))
/**
* Extract a value from a bitfield
*
* @param bitfield Bitfield contents to extract a value from
* @param base Starting bit position of the value to extract
* @param bits Number of bits for the value within the bitfield
* @return The extracted value
*/
#define Exclaves_L4_BfxW(bitfield, base, bits) \
(((bitfield) & Exclaves_L4_BfmW((base), (bits))) >> (base))
/**
* Return a bitfield with a particular value inserted
*
* @param bitfield Bitfield current contents
* @param base Starting bit position of the value to insert
* @param bits Number of bits for the value within the bitfield
* @param value Value to insert
* @return The bitfield with the value inserted, overwriting any previous
* value in the corresponding bits
*/
#define Exclaves_L4_BfiW(bitfield, base, bits, value) \
(((bitfield) & (~Exclaves_L4_BfmW((base), (bits)))) | \
(((Exclaves_L4_Word(value)) << (base)) & Exclaves_L4_BfmW((base), (bits))))
/**
* Return an otherwise empty bitfield that had a value inserted
*
* @param base Starting bit position of the value to insert
* @param bits Number of bits for the value within the bitfield
* @param value Value to insert
* @return The value encoded in the bitfield, with all other bits set to 0.
*/
#define Exclaves_L4_BfW(base, bits, value) \
(Exclaves_L4_BfiW(Exclaves_L4_Word(0), (base), (bits), (value)))
/** Nil (zero) value */
#define Exclaves_L4_Nil ((Exclaves_L4_Word_t) 0)
/** Boolean true value */
#define Exclaves_L4_True ((Exclaves_L4_Bool_t) 1)
/** Boolean false value */
#define Exclaves_L4_False ((Exclaves_L4_Bool_t) 0)
/* -------------------------------------------------------------------------- */
/**
* Create an Exclaves_L4_Error from a provided code and value
*
* @param code Specific Exclaves_L4_Error code
* @param value Supplementary information providing more context about
* the error
* @return The complete error value
*/
#define Exclaves_L4_Error(code, value) (((Exclaves_L4_Word(value)) << 8) | (Exclaves_L4_Word(code)))
/**
* Extract the error code from a constructed Exclaves_L4_Error_t
*
* @param error The error
* @return The error code
*/
#define Exclaves_L4_ErrorCode(error) ((error) & (((Exclaves_L4_Word(1)) << 8) - 1))
/**
* Extract the error value from a constructed Exclaves_L4_Error_t
*
* @param error The error
* @return The error value
*/
#define Exclaves_L4_ErrorValue(error) ((error) >> 8)
/**
* L4 error codes
*/
enum {
Exclaves_L4_ErrorCodeSuccess,
Exclaves_L4_ErrorCodePreempted,
Exclaves_L4_ErrorCodeCanceled,
Exclaves_L4_ErrorCodeTruncated,
Exclaves_L4_ErrorCodeCapInvalid,
Exclaves_L4_ErrorCodeSlotInvalid,
Exclaves_L4_ErrorCodeMethodInvalid,
Exclaves_L4_ErrorCodeArgumentInvalid,
Exclaves_L4_ErrorCodeOperationInvalid,
Exclaves_L4_ErrorCodePermissionInvalid,
Exclaves_L4_ErrorCodeMax
};
#define Exclaves_L4_Success \
Exclaves_L4_Error(Exclaves_L4_ErrorCodeSuccess, Exclaves_L4_Nil)
#define Exclaves_L4_Preempted \
Exclaves_L4_Error(Exclaves_L4_ErrorCodePreempted, Exclaves_L4_Nil)
#define Exclaves_L4_ErrorCanceled(reason) \
Exclaves_L4_Error(Exclaves_L4_ErrorCodeCanceled, reason)
#define Exclaves_L4_ErrorTruncated \
Exclaves_L4_Error(Exclaves_L4_ErrorCodeTruncated, Exclaves_L4_Nil)
#define Exclaves_L4_ErrorCapInvalid \
Exclaves_L4_Error(Exclaves_L4_ErrorCodeCapInvalid, Exclaves_L4_Nil)
#define Exclaves_L4_ErrorSlotInvalid \
Exclaves_L4_Error(Exclaves_L4_ErrorCodeSlotInvalid, Exclaves_L4_Nil)
#define Exclaves_L4_ErrorMethodInvalid \
Exclaves_L4_Error(Exclaves_L4_ErrorCodeMethodInvalid, Exclaves_L4_Nil)
#define Exclaves_L4_ErrorArgumentInvalid(argument) \
Exclaves_L4_Error(Exclaves_L4_ErrorCodeArgumentInvalid, argument)
#define Exclaves_L4_ErrorOperationInvalid \
Exclaves_L4_Error(Exclaves_L4_ErrorCodeOperationInvalid, Exclaves_L4_Nil)
#define Exclaves_L4_ErrorPermissionInvalid \
Exclaves_L4_Error(Exclaves_L4_ErrorCodePermissionInvalid, Exclaves_L4_Nil)
/* -------------------------------------------------------------------------- */
/* Exclaves_L4_MessageTag_t
*
* 32 0
* llllllllllllllll...nuuucccrrrrrr
*
* r: message registers (6 bits)
* c: capability registers (3 bits)
* u: unwrapped capabilities (3 bits)
* n: non-blocking (1 bit)
* l: label (16 bits)
*/
typedef Exclaves_L4_Word_t Exclaves_L4_MessageTag_t;
/* Exclaves_L4_MessageTag_Mrs */
#define Exclaves_L4_MessageTag_Mrs_Base 0
#define Exclaves_L4_MessageTag_Mrs_Bits 6
/* Exclaves_L4_MessageTag_Crs */
#define Exclaves_L4_MessageTag_Crs_Base 6
#define Exclaves_L4_MessageTag_Crs_Bits 3
/* Exclaves_L4_MessageTag_Unwrapped */
#define Exclaves_L4_MessageTag_Unwrapped_Base 9
#define Exclaves_L4_MessageTag_Unwrapped_Bits 3
/* Exclaves_L4_MessageTag_NonBlocking */
#define Exclaves_L4_MessageTag_NonBlocking_Base 12
#define Exclaves_L4_MessageTag_NonBlocking_Bits 1
/* Exclaves_L4_MessageTag_Label */
#define Exclaves_L4_MessageTag_Label_Base 16
#define Exclaves_L4_MessageTag_Label_Bits 16
static inline Exclaves_L4_Word_t
Exclaves_L4_MessageTag_Mrs(Exclaves_L4_MessageTag_t tag)
{
return Exclaves_L4_Word(Exclaves_L4_BfxW(tag, Exclaves_L4_MessageTag_Mrs_Base,
Exclaves_L4_MessageTag_Mrs_Bits));
}
static inline Exclaves_L4_Word_t
Exclaves_L4_MessageTag_Crs(Exclaves_L4_MessageTag_t tag)
{
return Exclaves_L4_Word(Exclaves_L4_BfxW(tag, Exclaves_L4_MessageTag_Crs_Base,
Exclaves_L4_MessageTag_Crs_Bits));
}
static inline Exclaves_L4_Word_t
Exclaves_L4_MessageTag_Unwrapped(Exclaves_L4_MessageTag_t tag)
{
return Exclaves_L4_Word(Exclaves_L4_BfxW(tag, Exclaves_L4_MessageTag_Unwrapped_Base,
Exclaves_L4_MessageTag_Unwrapped_Bits));
}
static inline Exclaves_L4_Word_t
Exclaves_L4_MessageTag_Label(Exclaves_L4_MessageTag_t tag)
{
return Exclaves_L4_Word(Exclaves_L4_BfxW(tag, Exclaves_L4_MessageTag_Label_Base,
Exclaves_L4_MessageTag_Label_Bits));
}
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)
{
Exclaves_L4_Word_t tag = (
Exclaves_L4_BfW(Exclaves_L4_MessageTag_Mrs_Base,
Exclaves_L4_MessageTag_Mrs_Bits, Exclaves_L4_Word(mrs)) |
Exclaves_L4_BfW(Exclaves_L4_MessageTag_Crs_Base,
Exclaves_L4_MessageTag_Crs_Bits, Exclaves_L4_Word(crs)) |
Exclaves_L4_BfW(Exclaves_L4_MessageTag_NonBlocking_Base,
Exclaves_L4_MessageTag_NonBlocking_Bits, Exclaves_L4_Word(nonblocking)) |
Exclaves_L4_BfW(Exclaves_L4_MessageTag_Label_Base,
Exclaves_L4_MessageTag_Label_Bits, Exclaves_L4_Word(label)));
return (Exclaves_L4_MessageTag_t) tag;
}
/* -------------------------------------------------------------------------- */
/* Exclaves_L4_IpcBuffer_t */
/* number of ipc buffer message registers */
#define Exclaves_L4_IpcBuffer_Mrs 56
/* numver of ipc buffer capability registers */
#define Exclaves_L4_IpcBuffer_Crs 4
/* ipc buffer size */
#define Exclaves_L4_IpcBuffer_Size (sizeof(Exclaves_L4_IpcBuffer_t))
/* ipc buffer object */
typedef struct __Exclaves_L4_Packed {
/* message registers */
Exclaves_L4_Word_t mr[Exclaves_L4_IpcBuffer_Mrs];
/* source capability registers */
Exclaves_L4_Word_t scr[Exclaves_L4_IpcBuffer_Crs];
/* destination capability registers */
Exclaves_L4_Word_t dcr[Exclaves_L4_IpcBuffer_Crs];
} Exclaves_L4_IpcBuffer_t;
/** Cast to a Exclaves IPC buffer pointer */
#define Exclaves_L4_IpcBuffer_Ptr(x) \
(__unsafe_forge_single(Exclaves_L4_IpcBuffer_t *, (x)))
/* L4 IPC invocation message registers */
enum {
Exclaves_L4_Ipc_Mr_Tag,
Exclaves_L4_Ipc_Mr_Badge,
Exclaves_L4_Ipc_Mr_Message
};
#ifdef KERNEL_PRIVATE
static inline Exclaves_L4_IpcBuffer_t *
Exclaves_L4_IpcBuffer(Exclaves_L4_Void_t)
{
return Exclaves_L4_IpcBuffer_Ptr(exclaves_get_ipc_buffer());
}
#endif /* KERNEL_PRIVATE */
#ifdef MACH_KERNEL_PRIVATE
/* -------------------------------------------------------------------------- */
static inline Exclaves_L4_Word_t
Exclaves_L4_GetMr(Exclaves_L4_Word32_t mr)
{
return Exclaves_L4_IpcBuffer()->mr[mr];
}
static inline Exclaves_L4_Void_t
Exclaves_L4_SetMr(Exclaves_L4_Word32_t mr, Exclaves_L4_Word_t word)
{
Exclaves_L4_IpcBuffer()->mr[mr] = word;
}
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)
{
Exclaves_L4_IpcBuffer_t *ipcb = Exclaves_L4_IpcBuffer();
for (Exclaves_L4_Word32_t offset = 0; offset < count; offset++) {
ipcb->mr[mr + offset] = words[offset];
}
}
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)
{
Exclaves_L4_IpcBuffer_t *ipcb = Exclaves_L4_IpcBuffer();
for (Exclaves_L4_Word32_t offset = 0; offset < count; offset++) {
words[offset] = ipcb->mr[mr + offset];
}
}
static inline Exclaves_L4_Word_t
Exclaves_L4_GetCr(Exclaves_L4_Word32_t cr, Exclaves_L4_Bool_t dst)
{
if (dst == Exclaves_L4_True) {
return Exclaves_L4_IpcBuffer()->dcr[cr];
} else {
return Exclaves_L4_IpcBuffer()->scr[cr];
}
}
static inline Exclaves_L4_Void_t
Exclaves_L4_SetCr(Exclaves_L4_Word32_t cr, Exclaves_L4_Word_t word, Exclaves_L4_Bool_t dst)
{
if (dst == Exclaves_L4_True) {
Exclaves_L4_IpcBuffer()->dcr[cr] = word;
} else {
Exclaves_L4_IpcBuffer()->scr[cr] = word;
}
}
static inline Exclaves_L4_MessageTag_t
Exclaves_L4_GetMessageTag(Exclaves_L4_Void_t)
{
return (Exclaves_L4_MessageTag_t) (Exclaves_L4_GetMr(Exclaves_L4_Ipc_Mr_Tag));
}
static inline Exclaves_L4_Void_t
Exclaves_L4_SetMessageTag(Exclaves_L4_MessageTag_t tag)
{
Exclaves_L4_SetMr(Exclaves_L4_Ipc_Mr_Tag, Exclaves_L4_Word(tag));
}
static inline Exclaves_L4_Word_t
Exclaves_L4_GetMessageMr(Exclaves_L4_Word32_t mr)
{
return Exclaves_L4_GetMr(Exclaves_L4_Ipc_Mr_Message + mr);
}
static inline Exclaves_L4_Void_t
Exclaves_L4_SetMessageMr(Exclaves_L4_Word32_t mr, Exclaves_L4_Word_t word)
{
Exclaves_L4_SetMr((Exclaves_L4_Ipc_Mr_Message + mr), word);
}
#endif /* MACH_KERNEL_PRIVATE */
/* -------------------------------------------------------------------------- */
/* Private communication protocol between Libsyscall, xnu and xnu proxy */
/* Return value of the endpoint message forwarding call. */
#define EXCLAVES_XNU_PROXY_CR_RETVAL(ipcb) ((ipcb)->dcr[3])
#endif /* EXCLAVES_NO_L4_TYPES */
/* -------------------------------------------------------------------------- */
/* identifiers for exclaves reachable through xnuproxy */
typedef enum : uint64_t {
/* HelloExclaves: c-hello-exclave */
EXCLAVES_XNUPROXY_EXCLAVE_HELLOEXCLAVE = 0,
/* templated user_app */
EXCLAVES_XNUPROXY_EXCLAVE_USERAPP,
/* Removed */
EXCLAVES_XNUPROXY_EXCLAVE_RESERVED,
/* HelloDrivers */
EXCLAVES_XNUPROXY_EXCLAVE_HELLODRIVERS,
/* HelloStorage */
EXCLAVES_XNUPROXY_EXCLAVE_HELLOSTORAGE,
/* templated user_app2 */
EXCLAVES_XNUPROXY_EXCLAVE_USERAPP2,
/* templated user_app3 */
EXCLAVES_XNUPROXY_EXCLAVE_USERAPP3,
/* audio */
EXCLAVES_XNUPROXY_EXCLAVE_AUDIODRIVER,
/* HelloDriverInterrupts */
EXCLAVES_XNUPROXY_EXCLAVE_HELLODRIVERINTERRUPTS,
/* ExclaveDriverKit */
EXCLAVES_XNUPROXY_EXCLAVE_EXCLAVEDRIVERKIT,
/* SecureRTBuddy for AOP */
EXCLAVES_XNUPROXY_EXCLAVE_SECURERTBUDDY_AOP,
/* SecureRTBuddy for DCP */
EXCLAVES_XNUPROXY_EXCLAVE_SECURERTBUDDY_DCP,
/* conclave launcher control */
EXCLAVES_XNUPROXY_EXCLAVE_CONCLAVECONTROL,
/* conclave launcher control */
EXCLAVES_XNUPROXY_EXCLAVE_CONCLAVEDEBUG,
/* SecureRTBuddy EDK connection for AOP */
EXCLAVES_XNUPROXY_EXCLAVE_SECURERTBUDDY_AOP_EDK,
/* SecureRTBuddy EDK connection for DCP */
EXCLAVES_XNUPROXY_EXCLAVE_SECURERTBUDDY_DCP_EDK,
} exclaves_xnuproxy_exclaves_t;
typedef enum : uint32_t {
EXCLAVES_XNUPROXY_TEST_BUF1 = 1,
EXCLAVES_XNUPROXY_TEST_BUF2,
EXCLAVES_XNUPROXY_TEST_BUF3,
EXCLAVES_XNUPROXY_TEST_BUF4,
/* 5 is empty */
EXCLAVES_XNUPROXY_NAMED_BUFFER_STORAGE_BUF_1 = 6,
EXCLAVES_XNUPROXY_NAMED_BUFFER_STORAGE_BUF_2 = 7,
EXCLAVES_XNUPROXY_LAST_STATIC_BUF = 111,
EXCLAVES_XNUPROXY_TEST_DYN_BUF1,
EXCLAVES_XNUPROXY_TEST_DYN_BUF2,
} exclaves_named_buffer_id_t;
#endif /* defined(__LP64__) */
#endif /* PRIVATE */
__END_DECLS
#endif /* _MACH_EXCLAVES_L4_H */