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