This is xnu-11215.1.10. See this file in:
/*
 * Copyright (c) 2023 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@
 */

#if CONFIG_EXCLAVES

#pragma once

#include <kern/bits.h>
#include <kern/locks.h>
#include <kern/queue.h>
#include <mach/exclaves.h>
#include <mach/kern_return.h>
#include <sys/event.h>

#include <stdint.h>
#include <os/base.h>

#include "kern/exclaves.tightbeam.h"

__BEGIN_DECLS


/* -------------------------------------------------------------------------- */
#pragma mark Exclaves Resources

#define EXCLAVES_DOMAIN_KERNEL "com.apple.kernel"
#define EXCLAVES_DOMAIN_DARWIN "com.apple.darwin"

/*
 * Data associated with a conclave.
 */

/*
 * Conclave State Machine:
 *
 *                 Launch Syscall
 *       +---------+         +--------------+
 *       |Attached | ------->|  Launching   |
 *       |         |         |              |
 *       +---------+         +--------------+
 *          ^ |                 |       |
 *    Spawn | |proc_exit   Exit |       |   Start IPC
 *          | |                 |       |  to Conclave Manager
 *          | v                 v       v
 *      +---------+   +-----------+   +----------+
 * *--> |  None   |   |    Stop   |   | Launched |
 *      |         |   | Requested |   |          |
 *      +---------+   +-----------+   +----------+
 *           ^                  |       |
 *  proc_exit|          Launch  |       |  Exit
 *           |        Completion|       |
 *           |                  v       v
 *         +---------+       +------------+
 *         | Stopped |<------|  Stopping  |
 *         |         |       |            |
 *         +---------+       +------------+
 *                    Stop IPC
 *                   to Conclave Manager
 */
typedef enum  {
	CONCLAVE_S_NONE = 0,
	CONCLAVE_S_ATTACHED,
	CONCLAVE_S_LAUNCHING,
	CONCLAVE_S_LAUNCHED,
	CONCLAVE_S_STOP_REQUESTED,
	CONCLAVE_S_STOPPING,
	CONCLAVE_S_STOPPED,
} conclave_state_t;

/* The maximum number of services available in any conclave. */
#define CONCLAVE_SERVICE_MAX 128

typedef struct {
	conclave_state_t       c_state;
	tb_client_connection_t c_control;
	task_t XNU_PTRAUTH_SIGNED_PTR("conclave.task") c_task;
	bitmap_t               c_service_bitmap[BITMAP_LEN(CONCLAVE_SERVICE_MAX)];
} conclave_resource_t;

#define EXCLAVES_SHARED_BUFFER_MAX_RANGES 256

typedef struct {
	char *address;
	size_t npages;
} named_buffer_range_t;

typedef struct {
	size_t nb_size;
	exclaves_buffer_perm_t nb_perm;
	size_t nb_nranges;
	named_buffer_range_t nb_range[EXCLAVES_SHARED_BUFFER_MAX_RANGES];
} named_buffer_resource_t;

typedef struct {
	size_t sm_size;
	exclaves_buffer_perm_t sm_perm;
	size_t sm_nranges;
	named_buffer_range_t sm_range[EXCLAVES_SHARED_BUFFER_MAX_RANGES];
	sharedmemorybase_mapping_s sm_mapping;
	sharedmemorybase_segxnuaccess_s sm_client;
} shared_memory_resource_t;

typedef struct {
	/* how many times *this* sensor resource handle has been
	 * used to call sensor_start */
	uint64_t s_startcount;
} sensor_resource_t;

typedef struct {
	struct klist notification_klist;
} exclaves_notification_t;

/*
 * Every resource has an associated name and some other common state.
 * Additionally there may be type specific data associated with the resource.
 */
#define EXCLAVES_RESOURCE_NAME_MAX 128
typedef struct exclaves_resource {
	char                r_name[EXCLAVES_RESOURCE_NAME_MAX];
	xnuproxy_resourcetype_s r_type;
	uint64_t            r_id;
	_Atomic uint32_t    r_usecnt;
	ipc_port_t          r_port;
	lck_mtx_t           r_mutex;
	bool                r_active;
	bool                r_connected;

	union {
		conclave_resource_t     r_conclave;
		named_buffer_resource_t r_named_buffer;
		sensor_resource_t       r_sensor;
		exclaves_notification_t r_notification;
		shared_memory_resource_t r_shared_memory;
	};
} exclaves_resource_t;

/*!
 * @function exclaves_resource_init
 *
 * @abstract
 * Called during exclaves_boot to dump the resource information from xnu proxy
 * and build the xnu-side tables.
 *
 * @return
 * KERN_SUCCESS on success otherwise an error code.
 */
extern kern_return_t
exclaves_resource_init(void);

/*!
 * @function exclaves_resource_name
 *
 * @abstract
 * Return the name associated with a resource.
 *
 * @param resource
 * Conclave manager resource.
 *
 * @return
 * The name of the resource or NULL.
 */
extern const char *
exclaves_resource_name(const exclaves_resource_t *resource);

/*!
 * @function exclaves_resource_retain
 *
 * @abstract
 * Grab a reference to the specified resource
 *
 * @param resource
 * The resource to retain.
 *
 * @return
 * The value of the use count before the retain
 */
extern uint32_t
exclaves_resource_retain(exclaves_resource_t *resource);

/*!
 * @function exclaves_resource_release
 *
 * @abstract
 * Drop a reference to the specified resource
 *
 * @param resource
 * The resource to release.
 *
 * @discussion
 * This may result in a resource type specific release function being called
 * which can grab locks, free memory etc.
 * After this function has been called, the resource should not be accessed as
 * it may be in an uninitialized state.
 */
extern void
exclaves_resource_release(exclaves_resource_t *resource);

/*!
 * @function exclaves_resource_from_port_name
 *
 * @abstract
 * Find the resource associated with a port name in the specified space.
 *
 * @param space
 * IPC space to search
 *
 * @param name
 * Port name of the resource.
 *
 * @param resource
 * Out parameter holding a pointer to the resource.
 *
 * @return
 * KERN_SUCCESS or error code on failure.
 *
 * @discussion
 * Returns with a +1 use-count on the resource which must be dropped with
 * exclaves_resource_release().
 */
extern kern_return_t
exclaves_resource_from_port_name(ipc_space_t space, mach_port_name_t name,
    exclaves_resource_t **resource);


/*!
 * @function exclaves_resource_create_port_name
 *
 * @abstract
 * Create a port name for the given resource in the specified space.
 *
 * @param name
 * Our parameter for holding a pointer to the port name.
 *
 * @param space
 * IPC space in which to create the name
 *
 * @param resource
 * Resource for which to create a port name for.
 *
 * @return
 * KERN_SUCCESS or error code on failure.
 *
 * @discussion
 * Returns with a +1 use-count on the resource which is associated with the life
 * of the newly created send right.
 */
extern kern_return_t
exclaves_resource_create_port_name(exclaves_resource_t *resource, ipc_space_t space,
    mach_port_name_t *name);




/* -------------------------------------------------------------------------- */
#pragma mark Named Buffers

/*!
 * @function exclaves_named_buffer_map
 *
 * @abstract
 * Map a named buffer resource.
 *
 * @param domain
 * The domain to search.
 *
 * @param name
 * The name of the named buffer resource.
 *
 * @param size
 * Size of named buffer region to map.
 *
 * @param perm
 * The permissions of the named buffer.
 *
 * @param resource
 * Out parameter which holds the resource on success.
 *
 * @return
 * KERN_SUCCESS or an error code.
 *
 * @discussion
 * Returns with a +1 use-count on the resource which must be dropped with
 * exclaves_resource_release().
 */
extern kern_return_t
exclaves_named_buffer_map(const char *domain, const char *name, size_t size,
    exclaves_buffer_perm_t perm, exclaves_resource_t **resource);

/*!
 * @function exclaves_named_buffer_copyin
 *
 * @abstract
 * Copy user data into a named buffer.
 *
 * @param resource
 * Named buffer resource.
 *
 * @param ubuffer
 * Source of data to copy.
 *
 * @param usize1
 * Size of data to copy.
 *
 * @param uoffset1
 * Offset into the named buffer.
 *
 * @param usize2
 * Size of 2nd range of data to copy (can be 0).
 *
 * @param uoffset2
 * Offset of 2nd range into the named buffer.
 *
 * @return
 * KERN_SUCCESS or error code on failure.
 */
extern kern_return_t
exclaves_named_buffer_copyin(exclaves_resource_t *resource,
    user_addr_t ubuffer, mach_vm_size_t usize1, mach_vm_size_t uoffset1,
    mach_vm_size_t usize2, mach_vm_size_t uoffset2);

/*!
 * @function exclaves_named_buffer_copyout
 *
 * @abstract
 * Copy user data into a named buffer.
 *
 * @param resource
 * Named buffer resource.
 *
 * @param ubuffer
 * Destination to copy data to.
 *
 * @param usize1
 * Size of data to copy.
 *
 * @param uoffset1
 * Offset into the named buffer.
 *
 * @param usize2
 * Size of 2nd range of data to copy (can be 0).
 *
 * @param uoffset2
 * Offset of 2nd range into the named buffer.
 *
 * @return
 * KERN_SUCCESS or error code on failure.
 */
extern kern_return_t
exclaves_named_buffer_copyout(exclaves_resource_t *resource,
    user_addr_t ubuffer, mach_vm_size_t usize1, mach_vm_size_t uoffset1,
    mach_vm_size_t usize2, mach_vm_size_t uoffset2);


/*!
 * @function exclaves_named_buffer_io
 *
 * @abstract
 * Perform IO on a named buffer
 *
 * @param resource
 * Named buffer resource.
 *
 * @param offset
 * Offset into the named buffer
 *
 * @param len
 * Size of the IO
 *
 * @param cb
 * A block which is called (potentially) multiple times to perform the IO.
 *
 * @return
 * 0 on success. If cb returns a non-zero value, exclaves_named_buffer_io()
 * immediately returns with that non-zero value.
 */
extern int
    exclaves_named_buffer_io(exclaves_resource_t * resource, off_t offset,
    size_t len, int (^cb)(char *buffer, size_t size));

/* -------------------------------------------------------------------------- */
#pragma mark Audio buffers

/*!
 * @function exclaves_audio_buffer_map
 *
 * @abstract
 * Map an audio buffer resource.
 *
 * @param domain
 * The domain to search.
 *
 * @param name
 * The name of audio buffer resource.
 *
 * @param size
 * Size of named buffer region to map.
 *
 * @param resource
 * Out parameter which holds the resource on success.
 *
 * @return
 * KERN_SUCCESS or error code on failure.
 *
 * @discussion
 * Returns with a +1 use-count on the resource which must be dropped with
 * exclaves_resource_release().
 */
extern kern_return_t
exclaves_audio_buffer_map(const char *domain, const char *name, size_t size,
    exclaves_resource_t **resource);

/*!
 * @function exclaves_audio_buffer_copyout
 *
 * @abstract
 * Copy user data into a audio buffer.
 *
 * @param resource
 * audio buffer resource.
 *
 * @param ubuffer
 * Destination to copy data to.
 *
 * @param usize1
 * Size of data to copy.
 *
 * @param uoffset1
 * Offset into the audio buffer.
 *
 * @param usize2
 * Size of 2nd range of data to copy (can be 0).
 *
 * @param uoffset2
 * Offset of 2nd range into the audio buffer.
 *
 * @return
 * KERN_SUCCESS or error code on failure.
 */
extern kern_return_t
exclaves_audio_buffer_copyout(exclaves_resource_t *resource,
    user_addr_t ubuffer, mach_vm_size_t usize1, mach_vm_size_t uoffset1,
    mach_vm_size_t usize2, mach_vm_size_t uoffset2);




/* -------------------------------------------------------------------------- */
#pragma mark Conclaves

/*!
 * @function exclaves_conclave_attach
 *
 * @abstract
 * Attach a conclave to a task. The conclave must not already be attached to any
 * task. Once attached, this conclave is exclusively associated with the task.
 *
 * @param name
 * The name of conclave resource.
 *
 * @param task
 * Task to attach the conclave to.
 *
 * @return
 * KERN_SUCCESS on success, error code otherwise.
 */
extern kern_return_t
exclaves_conclave_attach(const char *name, task_t task);

/*!
 * @function exclaves_conclave_detach
 *
 * @abstract
 * Detach a conclave from a task. The conclave must already be attached to the
 * task and stopped. Once detached, this conclave is available for other tasks.
 *
 * @param resource
 * Conclave Manager resource.
 *
 * @param task
 * Task to detach the conclave from.
 *
 * @return
 * KERN_SUCCESS on success, error code otherwise.
 */
extern kern_return_t
exclaves_conclave_detach(exclaves_resource_t *resource, task_t task);

/*!
 * @function exclaves_conclave_inherit
 *
 * @abstract
 * Pass an attached conclave from one task to another.
 *
 * @param resource
 * Conclave Manager resource.
 *
 * @param old_task
 * Task with attached conclave.
 *
 * @param new_task
 * Task which will inherit the conclave.
 *
 * @return
 * KERN_SUCCESS on success, error code otherwise.
 */
extern kern_return_t
exclaves_conclave_inherit(exclaves_resource_t *resource, task_t old_task,
    task_t new_task);


/*!
 * @function exclaves_conclave_is_attached
 *
 * @abstract
 * Returns true if the conclave is in the ATTACHED state.
 *
 * @param resource
 * Conclave Manager resource.
 *
 * @return
 * True if conclave is attached, false otherwise
 */
extern bool
exclaves_conclave_is_attached(const exclaves_resource_t *resource);

/*!
 * @function exclaves_conclave_launch
 *
 * @abstract
 * Launch a conclave. The conclave must be attached to a task and not already
 * launched.
 *
 * @param resource
 * Conclave Manager resource.
 *
 * @return
 * KERN_SUCCESS on success, error code otherwise.
 */
extern kern_return_t
exclaves_conclave_launch(exclaves_resource_t *resource);

/*!
 * @function exclaves_conclave_lookup_resources
 *
 * @abstract
 * Lookup conclave resource. The conclave must be attached to a task and
 * launched.
 *
 * @param resource
 * Conclave Manager resource.
 *
 * @param conclave_resource_user
 * Array to fill user resources for Conclave
 *
 * @param resource_count
 * Number of resources in array
 *
 * @return
 * KERN_SUCCESS on success, error code otherwise.
 */
extern kern_return_t
exclaves_conclave_lookup_resources(exclaves_resource_t *resource,
    struct exclaves_resource_user *conclave_resource_user, int resource_count);

/*!
 * @function exclaves_conclave_stop
 *
 * @abstract
 * Stop a conclave. The conclave must be launched and attached.
 *
 * @param resource
 * Conclave Manager resource.
 *
 * @param gather_crash_bt
 * Conclave Manager needs to gather backtraces
 *
 * @return
 * KERN_SUCCESS on success, error code otherwise.
 */
extern kern_return_t
exclaves_conclave_stop(exclaves_resource_t *resource, bool gather_crash_bt);

/*!
 * @function exclaves_conclave_stop_upcall
 *
 * @abstract
 * Stop a conclave. The conclave must be launched and attached.
 *
 * @param resource
 * Conclave Manager resource.
 *
 * @return
 * KERN_SUCCESS on success, error code otherwise.
 */
extern kern_return_t
exclaves_conclave_stop_upcall(exclaves_resource_t *resource);

/*!
 * @function exclaves_conclave_stop_upcall_complete
 *
 * @abstract
 * Complete the Conclave stop once back in regular context.
 *
 * @param resource
 * Conclave Manager resource.
 *
 * @param task
 * Conclave Host task
 *
 * @return
 * KERN_SUCCESS on success, error code otherwise.
 */
extern kern_return_t
exclaves_conclave_stop_upcall_complete(exclaves_resource_t *resource, task_t task);

/*!
 * @function exclaves_conclave_get_domain
 *
 * @abstract
 * Return the domain associated with the specified conclave resource. Or the
 * kernel domain if the conclave resource is NULL.
 *
 * @param resource
 * Conclave Manager resource.
 *
 * @return
 * The domain of the conclave or the kernel domain.
 */
extern const char *
exclaves_conclave_get_domain(exclaves_resource_t *resource);


/*!
 * @function exclaves_conclave_has_service
 *
 * @abstract
 * Return true if the service ID is associated with the specified conclave
 * resource.
 *
 * @param resource
 * Conclave Manager resource.
 *
 * @params id
 * ID of a SERVICE resource.
 *
 * @return
 * true if the ID is available to conclave, false otherwise
 */
extern bool
exclaves_conclave_has_service(exclaves_resource_t *resource, uint64_t id);

/* -------------------------------------------------------------------------- */
#pragma mark Sensors

/*!
 * @function exclaves_resource_sensor_open
 *
 * @abstract
 * Open a sensor resource.
 *
 * @param domain
 * The domain to search.
 *
 * @param name
 * The name of the sensor resource.
 *
 * @param resource
 * Out parameter which holds the resource on success.
 *
 * @return
 * KERN_SUCCESS on success, error code otherwise.
 *
 * @discussion
 * Returns with a +1 use-count on the resource which must be dropped with
 * exclaves_resource_release().
 */
extern kern_return_t
exclaves_resource_sensor_open(const char *domain, const char *name,
    exclaves_resource_t **resource);

/*!
 * @function exclaves_resource_sensor_start
 *
 * @abstract
 * Start accessing a sensor.
 *
 * @param resource
 * Sensor resource.
 *
 * @param flags
 * Flags to pass to implementation.
 *
 * @param status
 * output parameter for status of sensor after this operation.
 *
 * @return
 * KERN_SUCCESS on success, error code otherwise.
 */
kern_return_t
exclaves_resource_sensor_start(exclaves_resource_t *resource, uint64_t flags,
    exclaves_sensor_status_t *status);

/*!
 * @function exclaves_resource_sensor_stop
 *
 * @abstract
 * Stop accessing a sensor.
 *
 * @param resource
 * Sensor resource.
 *
 * @param flags
 * Flags to pass to implementation.
 *
 * @param status
 * output parameter for status of sensor after this operation.
 *
 * @return
 * KERN_SUCCESS on success, error code otherwise.
 */
kern_return_t
exclaves_resource_sensor_stop(exclaves_resource_t *resource, uint64_t flags,
    exclaves_sensor_status_t *status);

/*!
 * @function exclaves_resource_sensor_status
 *
 * @abstract
 * Query the status of access to a sensor.
 *
 * @param resource
 * Sensor resource.
 *
 * @param flags
 * Flags to pass to implementation.
 *
 * @param status
 * output parameter for status of sensor after this operation.
 *
 * @return
 * KERN_SUCCESS on success, error code otherwise.
 */
kern_return_t
exclaves_resource_sensor_status(exclaves_resource_t *resource, uint64_t flags,
    exclaves_sensor_status_t *status);

/* -------------------------------------------------------------------------- */
#pragma mark Notifications

/*!
 * @function exclaves_notification_create
 *
 * @abstract
 * Set up an exclave notification from the specified resource.
 *
 * @param domain
 * The domain to search.
 *
 * @param name
 * The name of the notification resource.
 *
 * @return
 * A notification resource or NULL.
 *
 * @discussion
 * Returns with a +1 use-count on the resource which must be dropped with
 * exclaves_resource_release().
 */
extern kern_return_t
exclaves_notification_create(const char *domain, const char *name,
    exclaves_resource_t **resource);

/*!
 * @function exclaves_notification_signal
 *
 * @abstract
 * To be called from upcall context when the specified notification resource is signaled.
 *
 * @param resource
 * Notification resource.
 *
 * @param event_mask
 * Bit mask of events for the notification.
 *
 * @return
 * KERN_SUCCESS on success, error code otherwise.
 */
extern kern_return_t
exclaves_notification_signal(exclaves_resource_t *resource, long event_mask);


/*!
 * @function exclaves_notificatione_lookup_by_id
 *
 * @abstract
 * Find an exclave notification  by ID.
 *
 * @param id
 * The resource ID.
 *
 * @param domain
 * The domain to search.
 *
 * @return
 * Pointer to the resource
 */
exclaves_resource_t *
exclaves_notification_lookup_by_id(const char *domain, uint64_t id);


/* -------------------------------------------------------------------------- */
#pragma mark Services

/*
 * Indicates an invalid service. */
#define  EXCLAVES_INVALID_ID UINT64_C(~0)

/*!
 * @function exclaves_service_lookup
 *
 * @abstract
 * Look up a service resource
 *
 * @param domain
 * The domain to search.
 *
 * @param name
 * The name of the service resource.
 *
 * @return
 * ID of service or EXCLAVES_INVALID_ID if the service cannot be found.
 */
extern uint64_t
exclaves_service_lookup(const char *domain, const char *name);


/* -------------------------------------------------------------------------- */
#pragma mark Shared Memory

/*!
 * @function exclaves_resource_shared_memory_map
 *
 * @abstract
 * Map a shared memory resource.
 *
 * @param domain
 * The domain to search.
 *
 * @param name
 * The name of the shared memory resource.
 *
 * @param size
 * Size of shared memory region to map.
 *
 * @param perm
 * The permissions of the shared memory.
 *
 * @param resource
 * Out parameter which holds the resource on success.
 *
 * @return
 * KERN_SUCCESS or an error code.
 *
 * @discussion
 * Returns with a +1 use-count on the resource which must be dropped with
 * exclaves_resource_release().
 */
extern kern_return_t
exclaves_resource_shared_memory_map(const char *domain, const char *name,
    size_t size, exclaves_buffer_perm_t perm, exclaves_resource_t **resource);

/*!
 * @function exclaves_resource_shared_memory_copyin
 *
 * @abstract
 * Copy user data into a shared memory.
 *
 * @param resource
 * Named buffer resource.
 *
 * @param ubuffer
 * Source of data to copy.
 *
 * @param usize1
 * Size of data to copy.
 *
 * @param uoffset1
 * Offset into the shared memory.
 *
 * @param usize2
 * Size of 2nd range of data to copy (can be 0).
 *
 * @param uoffset2
 * Offset of 2nd range into the shared memory.
 *
 * @return
 * KERN_SUCCESS or error code on failure.
 */
extern kern_return_t
exclaves_resource_shared_memory_copyin(exclaves_resource_t *resource,
    user_addr_t ubuffer, mach_vm_size_t usize1, mach_vm_size_t uoffset1,
    mach_vm_size_t usize2, mach_vm_size_t uoffset2);

/*!
 * @function exclaves_resource_shared_memory_copyout
 *
 * @abstract
 * Copy user data into a shared memory.
 *
 * @param resource
 * Named buffer resource.
 *
 * @param ubuffer
 * Destination to copy data to.
 *
 * @param usize1
 * Size of data to copy.
 *
 * @param uoffset1
 * Offset into the shared memory.
 *
 * @param usize2
 * Size of 2nd range of data to copy (can be 0).
 *
 * @param uoffset2
 * Offset of 2nd range into the shared memory.
 *
 * @return
 * KERN_SUCCESS or error code on failure.
 */
extern kern_return_t
exclaves_resource_shared_memory_copyout(exclaves_resource_t *resource,
    user_addr_t ubuffer, mach_vm_size_t usize1, mach_vm_size_t uoffset1,
    mach_vm_size_t usize2, mach_vm_size_t uoffset2);


/*!
 * @function exclaves_resource_shared_memory_io
 *
 * @abstract
 * Perform IO on a shared memory
 *
 * @param resource
 * Named buffer resource.
 *
 * @param offset
 * Offset into the shared memory
 *
 * @param len
 * Size of the IO
 *
 * @param cb
 * A block which is called (potentially) multiple times to perform the IO.
 *
 * @return
 * 0 on success. If cb returns a non-zero value, exclaves_resource_shared_memory_io()
 * immediately returns with that non-zero value.
 */
extern int
    exclaves_resource_shared_memory_io(exclaves_resource_t * resource, off_t offset,
    size_t len, int (^cb)(char *buffer, size_t size));


/* -------------------------------------------------------------------------- */
#pragma mark Arbitrated Audio Memory

/*!
 * @function exclaves_resource_audio_memory_map
 *
 * @abstract
 * Map an audio memory resource.
 *
 * @param domain
 * The domain to search.
 *
 * @param name
 * The name of audio memory resource.
 *
 * @param size
 * Size of named buffer region to map.
 *
 * @param resource
 * Out parameter which holds the resource on success.
 *
 * @return
 * KERN_SUCCESS or error code on failure.
 *
 * @discussion
 * Returns with a +1 use-count on the resource which must be dropped with
 * exclaves_resource_release().
 */
extern kern_return_t
exclaves_resource_audio_memory_map(const char *domain, const char *name, size_t size,
    exclaves_resource_t **resource);

/*!
 * @function exclaves_resource_audio_memory_copyout
 *
 * @abstract
 * Copy user data into a audio memory.
 *
 * @param resource
 * audio memory resource.
 *
 * @param ubuffer
 * Destination to copy data to.
 *
 * @param usize1
 * Size of data to copy.
 *
 * @param uoffset1
 * Offset into the audio memory.
 *
 * @param usize2
 * Size of 2nd range of data to copy (can be 0).
 *
 * @param uoffset2
 * Offset of 2nd range into the audio memory.
 *
 * @return
 * KERN_SUCCESS or error code on failure.
 */
extern kern_return_t
exclaves_resource_audio_memory_copyout(exclaves_resource_t *resource,
    user_addr_t ubuffer, mach_vm_size_t usize1, mach_vm_size_t uoffset1,
    mach_vm_size_t usize2, mach_vm_size_t uoffset2);

extern exclaves_resource_t *
exclaves_resource_lookup_by_name(const char *domain_name, const char *name,
    xnuproxy_resourcetype_s type);

__END_DECLS

#endif /* CONFIG_EXCLAVES */