/*! * @header * Interfaces for manipulating Image4 firmware objects. */ #ifndef __IMG4_FIRMWARE_H #define __IMG4_FIRMWARE_H #define __IMG4_INDIRECT 1 #include /*! * @discussion * When used from the pmap layer, this header pulls in the types from libsa, * which conflict with the BSD sys/types.h header that we need to pull in. But * we only need it for the errno_t typedef and the vnode_t typedef. So when * building MACH_KERNEL_PRIVATE, we do two things: * * 1. Explicitly pull in , so we get errno_t and * nothing else (no transitive #include's) * 2. #define _SYS_TYPES_H_ before #includ'ing so that * we don't get the transitive #include of but we still get * the definitions we need */ #if IMG4_TARGET_XNU #if MACH_KERNEL_PRIVATE #define _SYS_TYPES_H_ 1 #include #include #else #include #include #endif #if XNU_KERNEL_PRIVATE #include #endif #endif // IMG4_TARGET_XNU #if IMG4_TARGET_DARWIN #include #include #include #include #endif #include __BEGIN_DECLS OS_ASSUME_NONNULL_BEGIN OS_ASSUME_PTR_ABI_SINGLE_BEGIN /*! * @typedef img4_4cc_t * A type which represents a four-character code (4cc) that identifies the * firmware. These 4cc's are statically assigned and correspond to long-form tag * names -- e.g. the 4cc 'krnl' corresponds to the "KernelCache" tag. */ IMG4_API_AVAILABLE_20200508 typedef uint32_t img4_4cc_t; /*! * @typedef img4_buff_t * A structure describing a buffer. See {@link _img4_buff}. */ IMG4_API_AVAILABLE_20200508 typedef struct _img4_buff img4_buff_t; /*! * @const IMG4_DGST_STRUCT_VERSION * The version of the {@link img4_dgst_t} structure supported by the * implementation. */ #define IMG4_DGST_STRUCT_VERSION (0u) /*! * @const IMG4_DGST_MAX_LEN * The maximum length of a digest representable by an {@link img4_dgst_t}. */ #define IMG4_DGST_MAX_LEN (48u) /*! * @typedef img4_dgst_t * A type representing an Image4 identifier which is a digest. * * @field i4d_len * The version of the structure. Initialize to {@link IMG4_DGST_STRUCT_VERSION}. * * @field i4d_len * The length of the digest. * * @field i4d_bytes * The digest bytes. */ IMG4_API_AVAILABLE_20200508 typedef struct _img4_dgst { img4_struct_version_t i4d_version; size_t i4d_len; uint8_t i4d_bytes[IMG4_DGST_MAX_LEN]; } img4_dgst_t; /*! * @const IMG4_DGST_INIT * A convenience initializer for an {@link img4_dgst_t} structure. */ #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L #define IMG4_DGST_INIT (img4_dgst_t){ \ .i4d_version = IMG4_DGST_STRUCT_VERSION, \ .i4d_len = 0, \ .i4d_bytes = {0}, \ } #elif defined(__cplusplus) && __cplusplus >= 201103L #define IMG4_DGST_INIT (img4_dgst_t{ \ IMG4_DGST_STRUCT_VERSION, \ 0, \ {0}, \ }) #elif defined(__cplusplus) #define IMG4_DGST_INIT (img4_nonce_t((img4_nonce_t){ \ IMG4_DGST_STRUCT_VERSION, \ 0, \ {0}, \ })) #else #define IMG4_DGST_INIT {IMG4_DGST_STRUCT_VERSION} #endif /*! * @struct _img4_cstr * A type representing an Image4 identifier which is a C-string. These * identifiers can be no more than 64 bytes in length, including the null * terminating byte. * * @field i4b_len * The length of the C-string, not including the null terminating byte. * * @field i4b_cstr * The null-terminated C-string. * * @discussion * This structure is intentionally unversioned. It should never evolve into * anything more complex than it is. */ IMG4_API_AVAILABLE_20210113 typedef struct _img4_cstr { size_t i4cs_len; char i4cs_cstr[64]; } img4_cstr_t; /*! * @const IMG4_CSTR_INIT * A convenience initializer for an {@link img4_cstr_t}. */ #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L #define IMG4_CSTR_INIT (img4_cstr_t){ \ .i4cs_len = 0, \ .i4cs_cstr = {0}, \ } #elif defined(__cplusplus) && __cplusplus >= 201103L #define IMG4_CSTR_INIT (img4_cstr_t{ \ 0, \ {0}, \ }) #elif defined(__cplusplus) #define IMG4_CSTR_INIT \ (img4_cstr_t((img4_cstr_t){ \ 0, \ {0}, \ })) #else #define IMG4_CSTR_INIT {0} #endif /*! * @typedef img4_chip_t * An opaque type describing a destination chip environment for the firmware * image. */ IMG4_API_AVAILABLE_20200508 typedef struct _img4_chip img4_chip_t; /*! * @typedef img4_firmware_t * An opaque type describing an Image4 firmware object. */ IMG4_API_AVAILABLE_20200508 typedef struct _img4_firmware *img4_firmware_t; /*! * @typedef img4_image_t * An opaque type describing an authenticated Image4 firmware image. */ IMG4_API_AVAILABLE_20200508 typedef struct _img4_image *img4_image_t; /*! * @typedef img4_runtime_t * A structure describing required primitives in the operating environment's * runtime. See {@link _img4_runtime}. */ IMG4_API_AVAILABLE_20200508 typedef struct _img4_runtime img4_runtime_t; OS_ASSUME_PTR_ABI_SINGLE_END OS_ASSUME_NONNULL_END #include #include #include #include #include #include #include #include #include #include #include #if TXM #include #endif OS_ASSUME_NONNULL_BEGIN OS_ASSUME_PTR_ABI_SINGLE_BEGIN /*! * @typedef img4_firmware_authenticated_execute_t * A firmware execution function. This function is called when the firmware has * been successfully authenticated and is ready for execution. * * @param fw * The firmware which has been authenticated. * * @param image * The resulting firmware image that may be executed. The implementation will * pass NULL if there was a failure. * * This object is automatically freed by the implementation upon return. * * @param error * An error code describing the result of the authentication. If authentication * was successful, the implementation will pass zero. Otherwise, one of the * following error codes will be provided: * * [EILSEQ] The firmware data is not valid Image4 data -- this will not * be passed for firmwares created with * {@link IMG4_FIRMWARE_FLAG_BARE} * [EFTYPE] The attached manifest is not a valid Image4 manifest * [ENOENT] The attached manifest does not authenticate this type of * firmware * [EAUTH] The attached manifest is not authentic (i.e. was not signed * by an Apple CA) * [EACCES] The given chip does not satisfy the constraints of the * attached manifest * [ESTALE] The manifest has been invalidated and is no longer valid for * the provided chip * [ENOEXEC] The firmware has been corrupted, or the given chip does not * satisfy the constraints of the corresponding object in the * attached manifest * * @param _ctx * The user-provided context pointer. */ IMG4_API_AVAILABLE_20200508 typedef void (*img4_firmware_authenticated_execute_t)( const img4_firmware_t fw, img4_image_t _Nullable image, errno_t error, void *_ctx ); #if IMG4_TARGET_EFI typedef void (*img4_firmware_authenticated_execute_efi_t)( const img4_firmware_t fw, img4_image_t _Nullable image, EFI_STATUS status, void *_ctx ); #endif /*! * @define IMG4_FIRMWARE_EXECUTION_CONTEXT_STRUCT_VERSION * The version of the {@link img4_firmware_execution_context_t} structure * supported by the implementation. */ #define IMG4_FIRMWARE_EXECUTION_CONTEXT_STRUCT_VERSION (1u) /*! * @typedef img4_firmware_execution_context_t * A structure describing the context in which a firmware is to be executed. * * @field i4fex_version * The version of the structure supported by the implementation. Initialize to * {@link IMG4_FIRMWARE_EXECUTION_CONTEXT_STRUCT_VERSION}. * * @field i4fex_execute * A pointer to the firmware execution function. * * @field i4fex_execute_efi * A pointer to the EFI-specific firmware execution function. This is only * available in the EFI environment. If both this field and * {@link i4fex_execute} are specified in the execution context, the * one which is called by the implementation will be undefined. * * This field was added in version 1 of the structure. It was not appended to * the end of the structure since the non-EFI structure did not change, and the * structure did not previously exist in the EFI environment. The version * increment was not strictly necessary, but was done for hygienic reasons. * * @field i4fex_context * A caller-provided context pointer that will be passed to functions invoked * from the execution context. */ IMG4_API_AVAILABLE_20200508 typedef struct _img4_firmware_execution_context { img4_struct_version_t i4fex_version; img4_firmware_authenticated_execute_t i4fex_execute; #if IMG4_TARGET_EFI img4_firmware_authenticated_execute_efi_t i4fex_execute_efi; #endif void *i4fex_context; } img4_firmware_execution_context_t; /*! * @typedef img4_firmware_flags_t * A bitfield modifying the behavior of an {@link img4_firmware_t} object. * * @const IMG4_FIRMWARE_FLAG_INIT * No bits set. This value is suitable for initialization purposes. * * @const IMG4_FIRMWARE_FLAG_ATTACHED_MANIFEST * The manifest authenticating the firmware is attached (i.e. the buffer given * represents a .img4 file). * * This flag no longer does anything and probably never did. The implementation * assumes that, if {@link img4_firmware_attach_manifest} was not called, then * the manifest is attached to the payload. * * @const IMG4_FIRMWARE_FLAG_BARE * The firmware image is not wrapped with an Image4 payload structure. This flag * is mutually exclusive with {@link IMG4_FIRMWARE_FLAG_ATTACHED_MANIFEST}, and * if both are present, the implementation's behavior is undefined. * * @const IMG4_FIRMWARE_FLAG_SUBSEQUENT_STAGE * The firmware image extends an existing chain of trust. * * This flag no longer does anything; the implementation is now designed to * understand which environments are first-stage or subsequent-stage boots. * * @const IMG4_FIRMWARE_FLAG_RESPECT_AMNM * Forces the implementation to respect the manifest's AMNM entitlement if it is * present, even if the validation is creating a new chain of trust. This is * technically maybe sort of against the Image4 spec, but it is useful for * certain internal workflows (cf. v2.3, ยง2.2.10). * * This flag has no effect if {@link IMG4_FIRMWARE_FLAG_SUBSEQUENT_STAGE} is * also passed. * * @const IMG4_FIRMWARE_FLAG_PASSTHROUGH * Causes the wrapped payload bytes to be delivered to the image execution * callback. These bytes do not have the Image4 wrapping stripped. * * This flag no longer does anything. * * @const IMG4_FIRMWARE_FLAG_FORCE_ANTI_REPLAY * Force anti-replay enforcement even when performing just manifest evaluation * without executing a firmware. When executing a firmware, this flag need not * be passed in since anti-replay enforcement is always enabled. */ IMG4_API_AVAILABLE_20200508 OS_CLOSED_OPTIONS(img4_firmware_flags, uint64_t, IMG4_FIRMWARE_FLAG_INIT, IMG4_FIRMWARE_FLAG_ATTACHED_MANIFEST = (1 << 0), IMG4_FIRMWARE_FLAG_BARE = (1 << 1), IMG4_FIRMWARE_FLAG_SUBSEQUENT_STAGE = (1 << 2), IMG4_FIRMWARE_FLAG_RESPECT_AMNM = (1 << 3), IMG4_FIRMWARE_FLAG_PASSTHROUGH = (1 << 4), IMG4_FIRMWARE_FLAG_FORCE_ANTI_REPLAY = (1 << 5), ); /*! * @function img4_firmware_new * Allocate and initialize a new firmware object. * * @param rt * The runtime in which to initialize the object. * * @param _4cc * The 4cc which distinguishes the firmware. * * @param buff * A buffer containing a valid Image4 payload (usually the contents of either a * .im4p or .img4 file). * * Upon return, the destructor in the buffer is replaced with NULL, and the * implementation assumes responsibility for deallocating the underlying memory. * * @param flags * Flags modifying the behavior of the object. * * @result * A new firmware object or NULL if there was an allocation failure. If * {@link rt} has a NULL allocation function, NULL is returned. * * @discussion * The resulting object assumes ownership of the given buffer. * * In the Darwin userspace runtime, NULL will not be returned. */ #if !XNU_KERNEL_PRIVATE IMG4_API_AVAILABLE_20200508 OS_EXPORT OS_WARN_RESULT OS_MALLOC OS_NONNULL1 OS_NONNULL2 OS_NONNULL4 img4_firmware_t _Nullable img4_firmware_new(const img4_runtime_t *rt, const img4_firmware_execution_context_t *exec, img4_4cc_t _4cc, img4_buff_t *buff, img4_firmware_flags_t flags); #else #define img4_firmware_new(...) (img4if->i4if_v7.firmware_new(__VA_ARGS__)) #endif /*! * @function img4_firmware_new_from_vnode_4xnu * Allocate and initialize a new firmware object from a vnode. * * @param rt * The runtime in which to initialize the object. This interface is only * supported with the Darwin kernel runtime. If any other runtime is provided, * the implementation's behavior is undefined. * * @param _4cc * The 4cc which distinguishes the firmware. * * @param vn * A vnode representing a valid Image4 payload (usually the contents of either a * .im4p or .img4 file). * * @param flags * Flags modifying the behavior of the object. * * @result * A new firmware object or NULL if there was an allocation failure. * * @discussion * Verification of a vnode is performed by reading in chunks of data, updating * an ongoing hash operation with that data, and then discarding it. Therefore, * firmware objects created in this manner can only guarantee their validity at * the time the check was performed since the vnode's contents are not kept in * memory and may be tampered with after validation has been performed. * * As such, on successful execution, the image passed to the * {@link img4_firmware_authenticated_execute_t} function of the execution * context is NULL. * * Firmwares created with this interface cannot be created with the * {@link IMG4_FIRMWARE_FLAG_ATTACHED_MANIFEST} flag. */ #if IMG4_TARGET_XNU #if !XNU_KERNEL_PRIVATE IMG4_API_AVAILABLE_20200508 OS_EXPORT OS_WARN_RESULT OS_MALLOC OS_NONNULL1 OS_NONNULL2 OS_NONNULL4 img4_firmware_t _Nullable img4_firmware_new_from_vnode_4xnu(const img4_runtime_t *rt, const img4_firmware_execution_context_t *exec, img4_4cc_t _4cc, vnode_t vn, img4_firmware_flags_t flags); #else #define img4_firmware_new_from_vnode_4xnu(...) \ (img4if->i4if_v7.firmware_new_from_vnode_4xnu(__VA_ARGS__)) #endif // !XNU_KERNEL_PRIVATE #endif // IMG4_TARGET_XNU /*! * @function img4_firmware_new_from_fd_4MSM * Allocate and initialize a new firmware object from a file descriptor. * * @param rt * The runtime in which to initialize the object. This interface is only * supported with the Darwin userspace runtime. If any other runtime is * provided, the implementation's behavior is undefined. * * @param _4cc * The 4cc which distinguishes the firmware. * * @param fd * A pointer to a file descriptor representing a valid Image4 payload (usually * the contents of either a .im4p or .img4 file). The object assumes ownership * of the descriptor, and upon return, the value referenced by the pointer will * be set to -1. * * @param flags * Flags modifying the behavior of the object. * * @result * A new firmware object. The implementation will not return NULL. * * @discussion * This interface is the userspace equivalent of * {@link img4_firmware_new_from_vnode_4xnu}, and all the same caveats apply. */ #if IMG4_TARGET_DARWIN IMG4_API_AVAILABLE_20200508 OS_EXPORT OS_WARN_RESULT OS_MALLOC OS_NONNULL1 OS_NONNULL2 img4_firmware_t img4_firmware_new_from_fd_4MSM(const img4_runtime_t *rt, const img4_firmware_execution_context_t *exec, img4_4cc_t _4cc, os_fd_t *fd, img4_firmware_flags_t flags); #endif /*! * @function img4_firmware_init_from_buff * Initializes a buffer as a firmware object. This interface is useful for * runtimes which do not provide for dynamic memory allocation. * * @param storage * A pointer to the storage to use for the firmware object. * * @param len * The size of the buffer. * * @discussion * The caller is expected to pass a buffer that is "big enough". If the provided * buffer is too small, the implementation will abort the caller. * * @example * * uint8_t _buff[IMG4_FIRMWARE_SIZE_RECOMMENDED]; * img4_firmware_t fw = NULL; * * fw = img4_firmware_init_from_buff(_buff, sizeof(_buff)); * img4_firmware_init(fw, IMG4_RUNTIME_DEFAULT, &exec_context, * kImg4Tag_krnl, fw_buff, 0); */ #if !XNU_KERNEL_PRIVATE IMG4_API_AVAILABLE_20200508 OS_EXPORT OS_WARN_RESULT OS_NONNULL1 img4_firmware_t img4_firmware_init_from_buff(void *__sized_by(len) buff, size_t len); #else #define img4_firmware_init_from_buff(...) \ (img4if->i4if_v7.firmware_init_from_buff(__VA_ARGS__)) #endif /*! * @function img4_firmware_init * Initialize a firmware object. * * @param fw * A pointer to the storage for the firmware object. This pointer should refer * to a region of memory that is sufficient to hold a {@link img4_firmware_t} * object. This size should be queried with the {@link i4rt_object_size} * function of the runtime. * * @param rt * The runtime in which to initialize the object. * * @param _4cc * The 4cc which distinguishes the firmware. * * @param buff * A buffer containing a valid Image4 payload (usually the contents of either a * .im4p or .img4 file). * * Upon return, the destructor in the buffer is replaced with NULL, and the * implementation assumes responsibility for deallocating the underlying memory. * * @param flags * Flags modifying the behavior of the object. * * @discussion * The resulting object assumes ownership of the given buffer. This routine * should only be used when dynamic memory allocation is not available in the * runtime. Otherwise, use {@link img4_firmware_new}. */ #if !XNU_KERNEL_PRIVATE IMG4_API_AVAILABLE_20200508 OS_EXPORT OS_NONNULL1 OS_NONNULL2 OS_NONNULL3 OS_NONNULL5 void img4_firmware_init(img4_firmware_t fw, const img4_runtime_t *rt, const img4_firmware_execution_context_t *exec, img4_4cc_t _4cc, img4_buff_t *buff, img4_firmware_flags_t flags); #else #define img4_firmware_init(...) (img4if->i4if_v7.firmware_init(__VA_ARGS__)) #endif /*! * @function img4_firmware_init_sentinel * Initialize a firmware object as a sentinel without any manifest attached. * This firmware has no object tag and is not executable. It is only suitable * for use with {@link img4_firmware_attach_manifest} and * {@link img4_firmware_evaluate} to determine whether a manifest is acceptable * to a particular chip environment. * * @param fw * A pointer to the storage for the firmware object. This pointer should refer * to a region of memory that is sufficient to hold a {@link img4_firmware_t} * object. This size should be queried with the {@link i4rt_object_size} * function of the runtime. * * @param rt * The runtime in which to initialize the object. * * @param flags * Flags modifying the behavior of the object. * * @discussion * Sentinel firmwares do not enforce anti-replay, so * {@link img4_firmware_evaluate} will not return ESTALE when evaluating such * firmwares. Anti-replay enforcement can be enabled by using * {@link IMG4_FIRMWARE_FLAG_FORCE_ANTI_REPLAY}. */ #if !XNU_KERNEL_PRIVATE IMG4_API_AVAILABLE_20211126 OS_EXPORT OS_NONNULL1 OS_NONNULL2 void img4_firmware_init_sentinel(img4_firmware_t fw, const img4_runtime_t *rt, img4_firmware_flags_t flags); #else #define img4_firmware_init_sentinel(...) \ (img4if->i4if_v17.firmware_init_sentinel(__VA_ARGS__)) #endif /*! * @function img4_firmware_attach_manifest * Attaches a signed manifest to the firmware. * * @param fw * The firmware to manipulate. * * @param buff * A buffer containing a valid Image4 manifest (usually the contents of either a * .im4m or .img4 file). * * Upon return, the destructor in the buffer is replaced with NULL, and the * implementation assumes responsibility for deallocating the underlying memory. * * @discussion * If this interface is called on a firmware created with the * {@link IMG4_FIRMWARE_FLAG_ATTACHED_MANIFEST} flag, the implementation's * behavior is undefined. * * This interface must be called on any firmware created with the * {@link IMG4_FIRMWARE_FLAG_BARE} flag. * * The object assumes ownership of the given buffer. */ #if !XNU_KERNEL_PRIVATE IMG4_API_AVAILABLE_20200508 OS_EXPORT OS_NONNULL1 OS_NONNULL2 void img4_firmware_attach_manifest(img4_firmware_t fw, img4_buff_t *buff); #else #define img4_firmware_attach_manifest(...) \ (img4if->i4if_v7.firmware_attach_manifest(__VA_ARGS__)) #endif /*! * @function img4_firmware_select_chip * Returns the chip from the provided array which may be used to authenticate * the firmware. * * @param fw * The firmware to query. * * @param chips * An array of chips the caller finds acceptable to verify the firmware. * * @param chips_cnt * The number of elements in {@link chips}. * * @result * If the manifest may be authenticated by the certificate chain associated with * one of the manifests provided in {@link chips}, that chip is * returned. If the manifest cannot be authenticated with any of the provided * chips, NULL is returned. * * @discussion * The result of calling this function on a firmware which does not have a * manifest attached is undefined. * * If multiple chips may be used to authenticate the firmware, the * implementation does not define which of those chips will be returned. * * If the firmware was created without the * {@link IMG4_FIRMWARE_FLAG_SUBSEQUENT_STAGE} flag, this function will return * NULL. This function cannot be used to establish new trust chains, only to * verify an existing one. */ #if !XNU_KERNEL_PRIVATE IMG4_API_AVAILABLE_20200724 OS_EXPORT OS_WARN_RESULT const img4_chip_t *_Nullable img4_firmware_select_chip(const img4_firmware_t fw, const img4_chip_select_array_t __counted_by(chips_cnt) _Nonnull chips, size_t chips_cnt); #else #define img4_firmware_select_chip(...) \ (img4if->i4if_v10.firmware_select_chip(__VA_ARGS__)) #endif /*! * @function img4_firmware_execute * Authenticate the firmware and execute it within its context. * * @param fw * The firmware to execute. * * @param chip * The chip on which to execute the firmware. * * @param nonce * The nonce to use for authentication. May be NULL if the chip environment does * not maintain an anti-replay token or if a chained evaluation is being * performed. * * @discussion * The implementation will always invoke the * {@link img4_firmware_authenticated_execute_t} provided in the execution * context with either a successful result or a failure. All error handling must * take place in that context. * * The {@link img4_firmware_authenticated_execute_t} is called before the * implementation returns. * * The result of executing a firmware without a manifest attached (either via * {@link img4_firmware_attach_manifest} or by creating the firmware with the * {@link IMG4_FIRMWARE_FLAG_ATTACHED_MANIFEST} flag set) is undefined. */ #if !XNU_KERNEL_PRIVATE IMG4_API_AVAILABLE_20200508 OS_EXPORT OS_NONNULL1 OS_NONNULL2 void img4_firmware_execute(img4_firmware_t fw, const img4_chip_t *chip, const img4_nonce_t *_Nullable nonce); #else #define img4_firmware_execute(...) \ (img4if->i4if_v7.firmware_execute(__VA_ARGS__)) #endif /*! * @function img4_firmware_evaluate * Evaluate the firmware for authenticity. * * @param fw * The firmware to evaluate. * * @param chip * The chip on which to evaluate the firmware. * * @param nonce * The nonce to use for authentication. May be NULL if the chip environment does * not maintain an anti-replay token or if a chained evaluation is being * performed. * * @result * An error code describing the result of the authentication. If authentication * was successful, zero is returned. Otherwise, one of the following error codes * will be returned: * * [EILSEQ] The firmware data is not valid Image4 data -- this will not * be returned for firmwares created with * {@link IMG4_FIRMWARE_FLAG_BARE} * [EFTYPE] The attached manifest is not a valid Image4 manifest * [ENOENT] The attached manifest does not authenticate this type of * firmware * [EAUTH] The attached manifest is not authentic (i.e. was not signed * by an Apple CA) * [EACCES] The given chip does not satisfy the constraints of the * attached manifest * [ESTALE] The manifest has been invalidated and is no longer valid for * the provided chip * [ENOEXEC] The firmware has been corrupted, or the given chip does not * satisfy the constraints of the corresponding object in the * attached manifest * [EPWROFF] The chip environment has not yet booted; most chip * environments are booted and available by the time the caller * has begun executing, but some require additional * initialization before they can execute objects * * @discussion * This interface should be used when the caller is only concerned with the * authenticity and integrity of the firmware image and does not intend to * execute it. * * The result of evaluating a firmware without a manifest attached (either via * {@link img4_firmware_attach_manifest} or by creating the firmware with the * {@link IMG4_FIRMWARE_FLAG_ATTACHED_MANIFEST} flag set) is undefined. */ #if !XNU_KERNEL_PRIVATE IMG4_API_AVAILABLE_20200608 OS_EXPORT OS_WARN_RESULT OS_NONNULL1 OS_NONNULL2 errno_t img4_firmware_evaluate(img4_firmware_t fw, const img4_chip_t *chip, const img4_nonce_t *_Nullable nonce); #else #define img4_firmware_evaluate(...) \ (img4if->i4if_v9.firmware_evaluate(__VA_ARGS__)) #endif /*! * @function img4_firmware_destroy * Destroys a firmware object and releases the associated resources according to * the runtime's specification. * * @param fw * A pointer to the firmware object. * * Upon return, this will be replaced with a known-invalid pointer value. This * parameter may be NULL in which case the implementation will return * immediately. * * @discussion * The implementation will invoke the provided deallocation function of the * buffer object underlying the firmware. */ #if !XNU_KERNEL_PRIVATE IMG4_API_AVAILABLE_20200508 OS_EXPORT void img4_firmware_destroy(img4_firmware_t _Nullable *_Nonnull fw); #else #define img4_firmware_destroy(...) \ (img4if->i4if_v7.firmware_destroy(__VA_ARGS__)) #endif OS_ASSUME_PTR_ABI_SINGLE_END OS_ASSUME_NONNULL_END __END_DECLS #endif // __IMG4_FIRMWARE_H