xref: /xnu-8019.80.24/EXTERNAL_HEADERS/img4/firmware.h (revision a325d9c4a84054e40bbe985afedcb50ab80993ea)
1 /*!
2  * @header
3  * Interfaces for manipulating Image4 firmware objects.
4  */
5 #ifndef __IMG4_FIRMWARE_H
6 #define __IMG4_FIRMWARE_H
7 
8 #define __IMG4_INDIRECT 1
9 #include <img4/api.h>
10 
11 /*!
12  * @discussion
13  * When used from the pmap layer, this header pulls in the types from libsa,
14  * which conflict with the BSD sys/types.h header that we need to pull in. But
15  * we only need it for the errno_t typedef and the vnode_t typedef. So when
16  * building MACH_KERNEL_PRIVATE, we do two things:
17  *
18  *     1. Explicitly pull in <sys/_types/_errno_t.h>, so we get errno_t and
19  *        nothing else (no transitive #include's)
20  *     2. #define _SYS_TYPES_H_ before #includ'ing <sys/kernel_types.h> so that
21  *        we don't get the transitive #include of <sys/types.h> but we still get
22  *        the definitions we need
23  */
24 #if IMG4_TARGET_XNU
25 #if MACH_KERNEL_PRIVATE
26 #define _SYS_TYPES_H_ 1
27 #include <sys/kernel_types.h>
28 #include <sys/_types/_errno_t.h>
29 #else
30 #include <sys/kernel_types.h>
31 #include <sys/types.h>
32 #endif
33 #endif // IMG4_TARGET_XNU
34 
35 #if IMG4_TARGET_DARWIN
36 #include <os/stdio.h>
37 #include <sys/types.h>
38 #endif
39 
40 __BEGIN_DECLS;
41 
42 OS_ASSUME_NONNULL_BEGIN
43 
44 /*!
45  * @typedef img4_4cc_t
46  * A type which represents a four-character code (4cc) that identifies the
47  * firmware. These 4cc's are statically assigned and correspond to long-form tag
48  * names -- e.g. the 4cc 'krnl' corresponds to the "KernelCache" tag.
49  */
50 IMG4_API_AVAILABLE_20200508
51 typedef uint32_t img4_4cc_t;
52 
53 /*!
54  * @typedef img4_buff_t
55  * A structure describing a buffer. See {@link _img4_buff}.
56  */
57 IMG4_API_AVAILABLE_20200508
58 typedef struct _img4_buff img4_buff_t;
59 
60 /*!
61  * @typedef img4_cstr_t
62  * A type representing an Image4 identifier which is a C-string. These
63  * identifiers can be no more than 128 bytes in length, including the null
64  * terminating byte.
65  */
66 IMG4_API_AVAILABLE_20210113
67 typedef struct _img4_cstr img4_cstr_t;
68 
69 /*!
70  * @typedef img4_firmware_t
71  * An opaque type describing an Image4 firmware object.
72  */
73 IMG4_API_AVAILABLE_20200508
74 typedef struct _img4_firmware *img4_firmware_t;
75 
76 /*!
77  * @typedef img4_image_t
78  * An opaque type describing an authenticated Image4 firmware image.
79  */
80 IMG4_API_AVAILABLE_20200508
81 typedef struct _img4_image *img4_image_t;
82 
83 /*!
84  * @typedef img4_runtime_t
85  * A structure describing required primitives in the operating environment's
86  * runtime. See {@link _img4_runtime}.
87  */
88 IMG4_API_AVAILABLE_20200508
89 typedef struct _img4_runtime img4_runtime_t;
90 
91 OS_ASSUME_NONNULL_END
92 
93 #include <img4/nonce.h>
94 #include <img4/object.h>
95 #include <img4/chip.h>
96 #include <img4/image.h>
97 #include <img4/runtime.h>
98 
99 OS_ASSUME_NONNULL_BEGIN
100 
101 /*!
102  * @typedef img4_firmware_authenticated_execute_t
103  * A firmware execution function. This function is called when the firmware has
104  * been successfully authenticated and is ready for execution.
105  *
106  * @param fw
107  * The firmware which has been authenticated.
108  *
109  * @param image
110  * The resulting firmware image that may be executed. The implementation will
111  * pass NULL if there was a failure.
112  *
113  * This object is automatically freed by the implementation upon return.
114  *
115  * @param error
116  * An error code describing the result of the authentication. If authentication
117  * was successful, the implementation will pass zero. Otherwise, one of the
118  * following error codes will be provided:
119  *
120  *     [EILSEQ]     The firmware data is not valid Image4 data -- this will not
121  *                  be passed for firmwares created with
122  *                  {@link IMG4_FIRMWARE_FLAG_BARE}
123  *     [EFTYPE]     The attached manifest is not a valid Image4 manifest
124  *     [ENOENT]     The attached manifest does not authenticate this type of
125  *                  firmware
126  *     [EAUTH]      The attached manifest is not authentic (i.e. was not signed
127  *                  by an Apple CA)
128  *     [EACCES]     The given chip does not satisfy the constraints of the
129  *                  attached manifest
130  *     [ESTALE]     The manifest has been invalidated and is no longer valid for
131  *                  the provided chip
132  *     [ENOEXEC]    The firmware has been corrupted, or the given chip does not
133  *                  satisfy the constraints of the corresponding object in the
134  *                  attached manifest
135  *
136  * @param _ctx
137  * The user-provided context pointer.
138  */
139 IMG4_API_AVAILABLE_20200508
140 typedef void (*img4_firmware_authenticated_execute_t)(
141 	const img4_firmware_t fw,
142 	img4_image_t _Nullable image,
143 	errno_t error,
144 	void *_ctx
145 );
146 
147 #if IMG4_TARGET_EFI
148 typedef void (*img4_firmware_authenticated_execute_efi_t)(
149 	const img4_firmware_t fw,
150 	img4_image_t _Nullable image,
151 	EFI_STATUS status,
152 	void *_ctx
153 );
154 #endif
155 
156 /*!
157  * @define IMG4_FIRMWARE_EXECUTION_CONTEXT_STRUCT_VERSION
158  * The version of the {@link img4_firmware_execution_context_t} structure
159  * supported by the implementation.
160  */
161 #define IMG4_FIRMWARE_EXECUTION_CONTEXT_STRUCT_VERSION (1u)
162 
163 /*!
164  * @typedef img4_firmware_execution_context_t
165  * A structure describing the context in which a firmware is to be executed.
166  *
167  * @field i4fex_version
168  * The version of the structure supported by the implementation. Initialize to
169  * {@link IMG4_FIRMWARE_EXECUTION_CONTEXT_STRUCT_VERSION}.
170  *
171  * @field i4fex_execute
172  * A pointer to the firmware execution function.
173  *
174  * @field i4fex_execute_efi
175  * A pointer to the EFI-specific firmware execution function. This is only
176  * available in the EFI environment. If both this field and
177  * {@link i4fex_execute} are specified in the execution context, the
178  * one which is called by the implementation will be undefined.
179  *
180  * This field was added in version 1 of the structure. It was not appended to
181  * the end of the structure since the non-EFI structure did not change, and the
182  * structure did not previously exist in the EFI environment. The version
183  * increment was not strictly necessary, but was done for hygienic reasons.
184  *
185  * @field i4fex_context
186  * A caller-provided context pointer that will be passed to functions invoked
187  * from the execution context.
188  */
189 IMG4_API_AVAILABLE_20200508
190 typedef struct _img4_firmware_execution_context {
191 	img4_struct_version_t i4fex_version;
192 	img4_firmware_authenticated_execute_t i4fex_execute;
193 #if IMG4_TARGET_EFI
194 	img4_firmware_authenticated_execute_efi_t i4fex_execute_efi;
195 #endif
196 	void *i4fex_context;
197 } img4_firmware_execution_context_t;
198 
199 /*!
200  * @typedef img4_firmware_flags_t
201  * A bitfield modifying the behavior of an {@link img4_firmware_t} object.
202  *
203  * @const IMG4_FIRMWARE_FLAG_INIT
204  * No bits set. This value is suitable for initialization purposes.
205  *
206  * @const IMG4_FIRMWARE_FLAG_ATTACHED_MANIFEST
207  * The manifest authenticating the firmware is attached (i.e. the buffer given
208  * represents a .img4 file).
209  *
210  * @const IMG4_FIRMWARE_FLAG_BARE
211  * The firmware image is not wrapped with an Image4 payload structure. This flag
212  * is mutually exclusive with {@link IMG4_FIRMWARE_FLAG_ATTACHED_MANIFEST}, and
213  * if both are present, the implementation's behavior is undefined.
214  *
215  * @const IMG4_FIRMWARE_FLAG_SUBSEQUENT_STAGE
216  * The firmware image extends an existing chain of trust. If set, the
217  * runtime must provide a {@link i4rt_get_digest} function which returns a
218  * digest for {@link IMG4_IDENTIFIER_CHMH}.
219  *
220  * If set, the firmware may optionally provide a {@link i4rt_get_bool} function
221  * which returns a value for {@link IMG4_IDENTIFIER_AMNM}.
222  *
223  * @const IMG4_FIRMWARE_FLAG_RESPECT_AMNM
224  * Forces the implementation to respect the manifest's AMNM entitlement if it is
225  * present, even if the validation is creating a new chain of trust. This is
226  * technically maybe sort of against the Image4 spec, but it is useful for
227  * certain internal workflows (cf. v2.3, §2.2.10).
228  *
229  * This flag has no effect if {@link IMG4_FIRMWARE_FLAG_SUBSEQUENT_STAGE} is
230  * also passed.
231  *
232  * @const IMG4_FIRMWARE_FLAG_PASSTHROUGH
233  * Causes the wrapped payload bytes to be delivered to the image execution
234  * callback. These bytes do not have the Image4 wrapping stripped.
235  */
236 IMG4_API_AVAILABLE_20200508
237 OS_CLOSED_OPTIONS(img4_firmware_flags, uint64_t,
238 	IMG4_FIRMWARE_FLAG_INIT,
239 	IMG4_FIRMWARE_FLAG_ATTACHED_MANIFEST = (1 << 0),
240 	IMG4_FIRMWARE_FLAG_BARE = (1 << 1),
241 	IMG4_FIRMWARE_FLAG_SUBSEQUENT_STAGE = (1 << 2),
242 	IMG4_FIRMWARE_FLAG_RESPECT_AMNM = (1 << 3),
243 	IMG4_FIRMWARE_FLAG_PASSTHROUGH = (1 << 4),
244 );
245 
246 /*!
247  * @function img4_firmware_new
248  * Allocate and initialize a new firmware object.
249  *
250  * @param rt
251  * The runtime in which to initialize the object.
252  *
253  * @param _4cc
254  * The 4cc which distinguishes the firmware.
255  *
256  * @param buff
257  * A buffer containing a valid Image4 payload (usually the contents of either a
258  * .im4p or .img4 file).
259  *
260  * Upon return, the destructor in the buffer is replaced with NULL, and the
261  * implementation assumes responsibility for deallocating the underlying memory.
262  *
263  * @param flags
264  * Flags modifying the behavior of the object.
265  *
266  * @result
267  * A new firmware object or NULL if there was an allocation failure. If
268  * {@link rt} has a NULL allocation function, NULL is returned.
269  *
270  * @discussion
271  * The resulting object assumes ownership of the given buffer.
272  *
273  * In the Darwin userspace runtime, NULL will not be returned.
274  */
275 #if !XNU_KERNEL_PRIVATE
276 IMG4_API_AVAILABLE_20200508
277 OS_EXPORT OS_WARN_RESULT OS_MALLOC OS_NONNULL1 OS_NONNULL2 OS_NONNULL4
278 img4_firmware_t _Nullable
279 img4_firmware_new(const img4_runtime_t *rt,
280 		const img4_firmware_execution_context_t *exec,
281 		img4_4cc_t _4cc,
282 		img4_buff_t *buff,
283 		img4_firmware_flags_t flags);
284 #else
285 #define img4_firmware_new(...) (img4if->i4if_v7.firmware_new(__VA_ARGS__))
286 #endif
287 
288 /*!
289  * @function img4_firmware_new_from_vnode_4xnu
290  * Allocate and initialize a new firmware object from a vnode.
291  *
292  * @param rt
293  * The runtime in which to initialize the object. This interface is only
294  * supported with the Darwin kernel runtime. If any other runtime is provided,
295  * the implementation's behavior is undefined.
296  *
297  * @param _4cc
298  * The 4cc which distinguishes the firmware.
299  *
300  * @param vn
301  * A vnode representing a valid Image4 payload (usually the contents of either a
302  * .im4p or .img4 file).
303  *
304  * @param flags
305  * Flags modifying the behavior of the object.
306  *
307  * @result
308  * A new firmware object or NULL if there was an allocation failure.
309  *
310  * @discussion
311  * Verification of a vnode is performed by reading in chunks of data, updating
312  * an ongoing hash operation with that data, and then discarding it. Therefore,
313  * firmware objects created in this manner can only guarantee their validity at
314  * the time the check was performed since the vnode's contents are not kept in
315  * memory and may be tampered with after validation has been performed.
316  *
317  * As such, on successful execution, the image passed to the
318  * {@link img4_firmware_authenticated_execute_t} function of the execution
319  * context is NULL.
320  *
321  * Firmwares created with this interface cannot be created with the
322  * {@link IMG4_FIRMWARE_FLAG_ATTACHED_MANIFEST} flag.
323  */
324 #if IMG4_TARGET_XNU
325 #if !XNU_KERNEL_PRIVATE
326 IMG4_API_AVAILABLE_20200508
327 OS_EXPORT OS_WARN_RESULT OS_MALLOC OS_NONNULL1 OS_NONNULL2 OS_NONNULL4
328 img4_firmware_t _Nullable
329 img4_firmware_new_from_vnode_4xnu(const img4_runtime_t *rt,
330 		const img4_firmware_execution_context_t *exec,
331 		img4_4cc_t _4cc,
332 		vnode_t vn,
333 		img4_firmware_flags_t flags);
334 #else
335 #define img4_firmware_new_from_vnode_4xnu(...) \
336 		(img4if->i4if_v7.firmware_new_from_vnode_4xnu(__VA_ARGS__))
337 #endif // !XNU_KERNEL_PRIVATE
338 #endif // IMG4_TARGET_XNU
339 
340 /*!
341  * @function img4_firmware_new_from_fd_4MSM
342  * Allocate and initialize a new firmware object from a file descriptor.
343  *
344  * @param rt
345  * The runtime in which to initialize the object. This interface is only
346  * supported with the Darwin userspace runtime. If any other runtime is
347  * provided, the implementation's behavior is undefined.
348  *
349  * @param _4cc
350  * The 4cc which distinguishes the firmware.
351  *
352  * @param fd
353  * A pointer to a file descriptor representing a valid Image4 payload (usually
354  * the contents of either a .im4p or .img4 file). The object assumes ownership
355  * of the descriptor, and upon return, the value referenced by the pointer will
356  * be set to -1.
357  *
358  * @param flags
359  * Flags modifying the behavior of the object.
360  *
361  * @result
362  * A new firmware object. The implementation will not return NULL.
363  *
364  * @discussion
365  * This interface is the userspace equivalent of
366  * {@link img4_firmware_new_from_vnode_4xnu}, and all the same caveats apply.
367  */
368 #if IMG4_TARGET_DARWIN
369 IMG4_API_AVAILABLE_20200508
370 OS_EXPORT OS_WARN_RESULT OS_MALLOC OS_NONNULL1 OS_NONNULL2
371 img4_firmware_t
372 img4_firmware_new_from_fd_4MSM(const img4_runtime_t *rt,
373 		const img4_firmware_execution_context_t *exec,
374 		img4_4cc_t _4cc,
375 		os_fd_t *fd,
376 		img4_firmware_flags_t flags);
377 #endif
378 
379 /*!
380  * @function img4_firmware_init_from_buff
381  * Initializes a buffer as a firmware object. This interface is useful for
382  * runtimes which do not provide for dynamic memory allocation.
383  *
384  * @param storage
385  * A pointer to the storage to use for the firmware object.
386  *
387  * @param len
388  * The size of the buffer.
389  *
390  * @discussion
391  * The caller is expected to pass a buffer that is "big enough". If the provided
392  * buffer is too small, the implementation will abort the caller.
393  *
394  * @example
395  *
396  *     uint8_t _buff[IMG4_FIRMWARE_SIZE_RECOMMENDED];
397  *     img4_firmware_t fw = NULL;
398  *
399  *     fw = img4_firmware_init_from_buff(_buff, sizeof(_buff));
400  *     img4_firmware_init(fw, IMG4_RUNTIME_DEFAULT, &exec_context,
401  *             kImg4Tag_krnl, fw_buff, 0);
402  */
403 #if !XNU_KERNEL_PRIVATE
404 IMG4_API_AVAILABLE_20200508
405 OS_EXPORT OS_WARN_RESULT OS_NONNULL1
406 img4_firmware_t
407 img4_firmware_init_from_buff(void *buff, size_t len);
408 #else
409 #define img4_firmware_init_from_buff(...) \
410 		(img4if->i4if_v7.firmware_init_from_buff(__VA_ARGS__))
411 #endif
412 
413 /*!
414  * @function img4_firmware_init
415  * Initialize a firmware object.
416  *
417  * @param fw
418  * A pointer to the storage for the firmware object. This pointer should refer
419  * to a region of memory that is sufficient to hold a {@link img4_firmware_t}
420  * object. This size should be queried with the {@link i4rt_object_size}
421  * function of the runtime.
422  *
423  * @param rt
424  * The runtime in which to initialize the object.
425  *
426  * @param _4cc
427  * The 4cc which distinguishes the firmware.
428  *
429  * @param buff
430  * A buffer containing a valid Image4 payload (usually the contents of either a
431  * .im4p or .img4 file).
432  *
433  * Upon return, the destructor in the buffer is replaced with NULL, and the
434  * implementation assumes responsibility for deallocating the underlying memory.
435  *
436  * @param flags
437  * Flags modifying the behavior of the object.
438  *
439  * @discussion
440  * The resulting object assumes ownership of the given buffer. This routine
441  * should only be used when dynamic memory allocation is not available in the
442  * runtime. Otherwise, use {@link img4_firmware_new}.
443  */
444 #if !XNU_KERNEL_PRIVATE
445 IMG4_API_AVAILABLE_20200508
446 OS_EXPORT OS_NONNULL1 OS_NONNULL2 OS_NONNULL3 OS_NONNULL5
447 void
448 img4_firmware_init(img4_firmware_t fw,
449 		const img4_runtime_t *rt,
450 		const img4_firmware_execution_context_t *exec,
451 		img4_4cc_t _4cc,
452 		img4_buff_t *buff,
453 		img4_firmware_flags_t flags);
454 #else
455 #define img4_firmware_init(...) (img4if->i4if_v7.firmware_init(__VA_ARGS__))
456 #endif
457 
458 /*!
459  * @function img4_firmware_attach_manifest
460  * Attaches a signed manifest to the firmware.
461  *
462  * @param fw
463  * The firmware to manipulate.
464  *
465  * @param buff
466  * A buffer containing a valid Image4 manifest (usually the contents of either a
467  * .im4m or .img4 file).
468  *
469  * Upon return, the destructor in the buffer is replaced with NULL, and the
470  * implementation assumes responsibility for deallocating the underlying memory.
471  *
472  * @discussion
473  * If this interface is called on a firmware created with the
474  * {@link IMG4_FIRMWARE_FLAG_ATTACHED_MANIFEST} flag, the implementation's
475  * behavior is undefined.
476  *
477  * This interface must be called on any firmware created with the
478  * {@link IMG4_FIRMWARE_FLAG_BARE} flag.
479  *
480  * The object assumes ownership of the given buffer.
481  */
482 #if !XNU_KERNEL_PRIVATE
483 IMG4_API_AVAILABLE_20200508
484 OS_EXPORT OS_NONNULL1 OS_NONNULL2
485 void
486 img4_firmware_attach_manifest(img4_firmware_t fw,
487 		img4_buff_t *buff);
488 #else
489 #define img4_firmware_attach_manifest(...) \
490 		(img4if->i4if_v7.firmware_attach_manifest(__VA_ARGS__))
491 #endif
492 
493 /*!
494  * @function img4_firmware_select_chip
495  * Returns the chip from the provided array which may be used to authenticate
496  * the firmware.
497  *
498  * @param fw
499  * The firmware to query.
500  *
501  * @param acceptable_chips
502  * An array of chips the caller finds acceptable to verify the firmware.
503  *
504  * @param acceptable_chips_cnt
505  * The number of elements in {@link acceptable_chips}.
506  *
507  * @result
508  * If the manifest may be authenticated by the certificate chain associated with
509  * one of the manifests provided in {@link acceptable_chips}, that chip is
510  * returned. If the manifest cannot be authenticated with any of the provided
511  * chips, NULL is returned.
512  *
513  * @discussion
514  * The result of calling this function on a firmware which does not have a
515  * manifest attached is undefined.
516  *
517  * If multiple chips may be used to authenticate the firmware, the
518  * implementation does not define which of those chips will be returned.
519  *
520  * If the firmware was created without the
521  * {@link IMG4_FIRMWARE_FLAG_SUBSEQUENT_STAGE} flag, this function will return
522  * NULL. This function cannot be used to establish new trust chains, only to
523  * verify an existing one.
524  */
525 #if !XNU_KERNEL_PRIVATE
526 IMG4_API_AVAILABLE_20200724
527 OS_EXPORT OS_WARN_RESULT
528 const img4_chip_t *_Nullable
529 img4_firmware_select_chip(const img4_firmware_t fw,
530 		const img4_chip_select_array_t _Nonnull acceptable_chips,
531 		size_t acceptable_chips_cnt);
532 #else
533 #define img4_firmware_select_chip(...) \
534 		(img4if->i4if_v10.firmware_select_chip(__VA_ARGS__))
535 #endif
536 
537 /*!
538  * @function img4_firmware_execute
539  * Authenticate the firmware and execute it within its context.
540  *
541  * @param fw
542  * The firmware to execute.
543  *
544  * @param chip
545  * The chip on which to execute the firmware.
546  *
547  * @param nonce
548  * The nonce to use for authentication. May be NULL if the chip environment does
549  * not maintain an anti-replay token or if a chained evaluation is being
550  * performed.
551  *
552  * @discussion
553  * The implementation will always invoke the
554  * {@link img4_firmware_authenticated_execute_t} provided in the execution
555  * context with either a successful result or a failure. All error handling must
556  * take place in that context.
557  *
558  * The {@link img4_firmware_authenticated_execute_t} is called before the
559  * implementation returns.
560  *
561  * The result of executing a firmware without a manifest attached (either via
562  * {@link img4_firmware_attach_manifest} or by creating the firmware with the
563  * {@link IMG4_FIRMWARE_FLAG_ATTACHED_MANIFEST} flag set) is undefined.
564  */
565 #if !XNU_KERNEL_PRIVATE
566 IMG4_API_AVAILABLE_20200508
567 OS_EXPORT OS_NONNULL1 OS_NONNULL2
568 void
569 img4_firmware_execute(img4_firmware_t fw,
570 		const img4_chip_t *chip,
571 		const img4_nonce_t *_Nullable nonce);
572 #else
573 #define img4_firmware_execute(...) \
574 		(img4if->i4if_v7.firmware_execute(__VA_ARGS__))
575 #endif
576 
577 /*!
578  * @function img4_firmware_evaluate
579  * Evaluate the firmware for authenticity.
580  *
581  * @param fw
582  * The firmware to evaluate.
583  *
584  * @param chip
585  * The chip on which to evaluate the firmware.
586  *
587  * @param nonce
588  * The nonce to use for authentication. May be NULL if the chip environment does
589  * not maintain an anti-replay token or if a chained evaluation is being
590  * performed.
591  *
592  * @result
593  * An error code describing the result of the authentication. If authentication
594  * was successful, zero is returned. Otherwise, one of the following error codes
595  * will be returned:
596  *
597  *     [EILSEQ]     The firmware data is not valid Image4 data -- this will not
598  *                  be returned for firmwares created with
599  *                  {@link IMG4_FIRMWARE_FLAG_BARE}
600  *     [EFTYPE]     The attached manifest is not a valid Image4 manifest
601  *     [ENOENT]     The attached manifest does not authenticate this type of
602  *                  firmware
603  *     [EAUTH]      The attached manifest is not authentic (i.e. was not signed
604  *                  by an Apple CA)
605  *     [EACCES]     The given chip does not satisfy the constraints of the
606  *                  attached manifest
607  *     [ESTALE]     The manifest has been invalidated and is no longer valid for
608  *                  the provided chip
609  *     [ENOEXEC]    The firmware has been corrupted, or the given chip does not
610  *                  satisfy the constraints of the corresponding object in the
611  *                  attached manifest
612  *     [EPWROFF]    The chip environment has not yet booted; most chip
613  *                  environments are booted and available by the time the caller
614  *                  has begun executing, but some require additional
615  *                  initialization before they can execute objects
616  *
617  * @discussion
618  * This interface should be used when the caller is only concerned with the
619  * authenticity and integrity of the firmware image and does not intend to
620  * execute it.
621  *
622  * The result of evaluating a firmware without a manifest attached (either via
623  * {@link img4_firmware_attach_manifest} or by creating the firmware with the
624  * {@link IMG4_FIRMWARE_FLAG_ATTACHED_MANIFEST} flag set) is undefined.
625  */
626 #if !XNU_KERNEL_PRIVATE
627 IMG4_API_AVAILABLE_20200608
628 OS_EXPORT OS_WARN_RESULT OS_NONNULL1 OS_NONNULL2
629 errno_t
630 img4_firmware_evaluate(img4_firmware_t fw,
631 		const img4_chip_t *chip,
632 		const img4_nonce_t *_Nullable nonce);
633 #else
634 #define img4_firmware_evaluate(...) \
635 		(img4if->i4if_v9.firmware_evaluate(__VA_ARGS__))
636 #endif
637 
638 /*!
639  * @function img4_firmware_destroy
640  * Destroys a firmware object and releases the associated resources according to
641  * the runtime's specification.
642  *
643  * @param fw
644  * A pointer to the firmware object.
645  *
646  * Upon return, this will be replaced with a known-invalid pointer value. This
647  * parameter may be NULL in which case the implementation will return
648  * immediately.
649  *
650  * @discussion
651  * The implementation will invoke the provided deallocation function of the
652  * buffer object underlying the firmware.
653  */
654 #if !XNU_KERNEL_PRIVATE
655 IMG4_API_AVAILABLE_20200508
656 OS_EXPORT
657 void
658 img4_firmware_destroy(img4_firmware_t _Nonnull *_Nullable fw);
659 #else
660 #define img4_firmware_destroy(...) \
661 		(img4if->i4if_v7.firmware_destroy(__VA_ARGS__))
662 #endif
663 
664 OS_ASSUME_NONNULL_END
665 
666 __END_DECLS;
667 
668 #endif // __IMG4_FIRMWARE_H
669