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