1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Permission is hereby granted, free of charge, to any person 5 * obtaining a copy of this software and associated documentation 6 * files (the "Software"), to deal in the Software without 7 * restriction, including without limitation the rights to use, copy, 8 * modify, merge, publish, distribute, sublicense, and/or sell copies 9 * of the Software, and to permit persons to whom the Software is 10 * furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice shall be 13 * included in all copies or substantial portions of the Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 * SOFTWARE. 23 */ 24 25 #include <efi.h> 26 #include <efilib.h> 27 28 #include <libavb_ab/libavb_ab.h> 29 30 #include "uefi_avb_ops.h" 31 #include "uefi_avb_util.h" 32 33 #include <efi.h> 34 #include <efilib.h> 35 36 /* GPT related constants. */ 37 #define GPT_REVISION 0x00010000 38 #define GPT_MAGIC "EFI PART" 39 #define GPT_MIN_SIZE 92 40 #define GPT_ENTRIES_LBA 2 41 #define AVB_BLOCK_SIZE 512 42 #define ENTRIES_PER_BLOCK 4 43 #define ENTRY_NAME_LEN 36 44 #define MAX_GPT_ENTRIES 128 45 46 typedef struct { 47 uint8_t signature[8]; 48 uint32_t revision; 49 uint32_t header_size; 50 uint32_t header_crc32; 51 uint32_t reserved; 52 uint64_t header_lba; 53 uint64_t alternate_header_lba; 54 uint64_t first_usable_lba; 55 uint64_t last_usable_lba; 56 uint8_t disk_guid[16]; 57 uint64_t entry_lba; 58 uint32_t entry_count; 59 uint32_t entry_size; 60 uint32_t entry_crc32; 61 uint8_t reserved2[420]; 62 } GPTHeader; 63 64 typedef struct { 65 uint8_t type_GUID[16]; 66 uint8_t unique_GUID[16]; 67 uint64_t first_lba; 68 uint64_t last_lba; 69 uint64_t flags; 70 uint16_t name[ENTRY_NAME_LEN]; 71 } GPTEntry; 72 73 static EFI_STATUS find_partition_entry_by_name(IN EFI_BLOCK_IO* block_io, 74 const char* partition_name, 75 GPTEntry** entry_buf) { 76 EFI_STATUS err; 77 GPTHeader* gpt_header = NULL; 78 GPTEntry all_gpt_entries[MAX_GPT_ENTRIES]; 79 uint16_t* partition_name_ucs2 = NULL; 80 size_t partition_name_bytes; 81 size_t partition_name_ucs2_capacity; 82 size_t partition_name_ucs2_len; 83 84 gpt_header = (GPTHeader*)avb_malloc(sizeof(GPTHeader)); 85 if (gpt_header == NULL) { 86 avb_error("Could not allocate for GPT header\n"); 87 return EFI_NOT_FOUND; 88 } 89 90 *entry_buf = (GPTEntry*)avb_malloc(sizeof(GPTEntry) * ENTRIES_PER_BLOCK); 91 if (entry_buf == NULL) { 92 avb_error("Could not allocate for partition entry\n"); 93 avb_free(gpt_header); 94 return EFI_NOT_FOUND; 95 } 96 97 err = uefi_call_wrapper(block_io->ReadBlocks, 98 NUM_ARGS_READ_BLOCKS, 99 block_io, 100 block_io->Media->MediaId, 101 1, 102 sizeof(GPTHeader), 103 gpt_header); 104 if (EFI_ERROR(err)) { 105 avb_error("Could not ReadBlocks for gpt header\n"); 106 avb_free(gpt_header); 107 avb_free(*entry_buf); 108 *entry_buf = NULL; 109 return EFI_NOT_FOUND; 110 } 111 112 partition_name_bytes = avb_strlen(partition_name); 113 partition_name_ucs2_capacity = sizeof(uint16_t) * (partition_name_bytes + 1); 114 partition_name_ucs2 = avb_calloc(partition_name_ucs2_capacity); 115 if (partition_name_ucs2 == NULL) { 116 avb_error("Could not allocate for ucs2 partition name\n"); 117 avb_free(gpt_header); 118 avb_free(*entry_buf); 119 *entry_buf = NULL; 120 return EFI_NOT_FOUND; 121 } 122 if (!uefi_avb_utf8_to_ucs2((const uint8_t*)partition_name, 123 partition_name_bytes, 124 partition_name_ucs2, 125 partition_name_ucs2_capacity, 126 NULL)) { 127 avb_error("Could not convert partition name to UCS-2\n"); 128 avb_free(gpt_header); 129 avb_free(partition_name_ucs2); 130 avb_free(*entry_buf); 131 *entry_buf = NULL; 132 return EFI_NOT_FOUND; 133 } 134 partition_name_ucs2_len = StrLen(partition_name_ucs2); 135 136 /* Block-aligned bytes for entries. */ 137 UINTN entries_num_bytes = 138 block_io->Media->BlockSize * (MAX_GPT_ENTRIES / ENTRIES_PER_BLOCK); 139 140 err = uefi_call_wrapper(block_io->ReadBlocks, 141 NUM_ARGS_READ_BLOCKS, 142 block_io, 143 block_io->Media->MediaId, 144 GPT_ENTRIES_LBA, 145 entries_num_bytes, 146 &all_gpt_entries); 147 if (EFI_ERROR(err)) { 148 avb_error("Could not ReadBlocks for GPT header\n"); 149 avb_free(gpt_header); 150 avb_free(partition_name_ucs2); 151 avb_free(*entry_buf); 152 *entry_buf = NULL; 153 return EFI_NOT_FOUND; 154 } 155 156 /* Find matching partition name. */ 157 for (int n = 0; n < gpt_header->entry_count; n++) { 158 if ((partition_name_ucs2_len == StrLen(all_gpt_entries[n].name)) && 159 avb_memcmp(all_gpt_entries[n].name, 160 partition_name_ucs2, 161 partition_name_ucs2_len * 2) == 0) { 162 avb_memcpy((*entry_buf), &all_gpt_entries[n], sizeof(GPTEntry)); 163 avb_free(partition_name_ucs2); 164 avb_free(gpt_header); 165 return EFI_SUCCESS; 166 } 167 } 168 169 avb_free(partition_name_ucs2); 170 avb_free(gpt_header); 171 avb_free(*entry_buf); 172 *entry_buf = NULL; 173 return EFI_NOT_FOUND; 174 } 175 176 static AvbIOResult read_from_partition(AvbOps* ops, 177 const char* partition_name, 178 int64_t offset_from_partition, 179 size_t num_bytes, 180 void* buf, 181 size_t* out_num_read) { 182 EFI_STATUS err; 183 GPTEntry* partition_entry; 184 uint64_t partition_size; 185 UEFIAvbOpsData* data = (UEFIAvbOpsData*)ops->user_data; 186 187 avb_assert(partition_name != NULL); 188 avb_assert(buf != NULL); 189 avb_assert(out_num_read != NULL); 190 191 err = find_partition_entry_by_name( 192 data->block_io, partition_name, &partition_entry); 193 if (EFI_ERROR(err)) { 194 return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION; 195 } 196 197 partition_size = 198 (partition_entry->last_lba - partition_entry->first_lba + 1) * 199 data->block_io->Media->BlockSize; 200 201 if (offset_from_partition < 0) { 202 if ((-offset_from_partition) > partition_size) { 203 avb_error("Offset outside range.\n"); 204 avb_free(partition_entry); 205 return AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION; 206 } 207 offset_from_partition = partition_size - (-offset_from_partition); 208 } 209 210 /* Check if num_bytes goes beyond partition end. If so, don't read beyond 211 * this boundary -- do a partial I/O instead. 212 */ 213 if (num_bytes > partition_size - offset_from_partition) 214 *out_num_read = partition_size - offset_from_partition; 215 else 216 *out_num_read = num_bytes; 217 218 err = uefi_call_wrapper( 219 data->disk_io->ReadDisk, 220 5, 221 data->disk_io, 222 data->block_io->Media->MediaId, 223 (partition_entry->first_lba * data->block_io->Media->BlockSize) + 224 offset_from_partition, 225 *out_num_read, 226 buf); 227 if (EFI_ERROR(err)) { 228 avb_error("Could not read from Disk.\n"); 229 *out_num_read = 0; 230 avb_free(partition_entry); 231 return AVB_IO_RESULT_ERROR_IO; 232 } 233 234 avb_free(partition_entry); 235 return AVB_IO_RESULT_OK; 236 } 237 238 static AvbIOResult write_to_partition(AvbOps* ops, 239 const char* partition_name, 240 int64_t offset_from_partition, 241 size_t num_bytes, 242 const void* buf) { 243 EFI_STATUS err; 244 GPTEntry* partition_entry; 245 uint64_t partition_size; 246 UEFIAvbOpsData* data = (UEFIAvbOpsData*)ops->user_data; 247 248 avb_assert(partition_name != NULL); 249 avb_assert(buf != NULL); 250 251 err = find_partition_entry_by_name( 252 data->block_io, partition_name, &partition_entry); 253 if (EFI_ERROR(err)) { 254 return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION; 255 } 256 257 partition_size = (partition_entry->last_lba - partition_entry->first_lba) * 258 data->block_io->Media->BlockSize; 259 260 if (offset_from_partition < 0) { 261 if ((-offset_from_partition) > partition_size) { 262 avb_error("Offset outside range.\n"); 263 avb_free(partition_entry); 264 return AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION; 265 } 266 offset_from_partition = partition_size - (-offset_from_partition); 267 } 268 269 /* Check if num_bytes goes beyond partition end. If so, error out -- no 270 * partial I/O. 271 */ 272 if (num_bytes > partition_size - offset_from_partition) { 273 avb_error("Cannot write beyond partition boundary.\n"); 274 avb_free(partition_entry); 275 return AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION; 276 } 277 278 err = uefi_call_wrapper( 279 data->disk_io->WriteDisk, 280 5, 281 data->disk_io, 282 data->block_io->Media->MediaId, 283 (partition_entry->first_lba * data->block_io->Media->BlockSize) + 284 offset_from_partition, 285 num_bytes, 286 buf); 287 288 if (EFI_ERROR(err)) { 289 avb_error("Could not write to Disk.\n"); 290 avb_free(partition_entry); 291 return AVB_IO_RESULT_ERROR_IO; 292 } 293 294 avb_free(partition_entry); 295 return AVB_IO_RESULT_OK; 296 } 297 298 static AvbIOResult get_size_of_partition(AvbOps* ops, 299 const char* partition_name, 300 uint64_t* out_size) { 301 EFI_STATUS err; 302 GPTEntry* partition_entry; 303 uint64_t partition_size; 304 UEFIAvbOpsData* data = (UEFIAvbOpsData*)ops->user_data; 305 306 avb_assert(partition_name != NULL); 307 308 err = find_partition_entry_by_name( 309 data->block_io, partition_name, &partition_entry); 310 if (EFI_ERROR(err)) { 311 return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION; 312 } 313 314 partition_size = 315 (partition_entry->last_lba - partition_entry->first_lba + 1) * 316 data->block_io->Media->BlockSize; 317 318 if (out_size != NULL) { 319 *out_size = partition_size; 320 } 321 322 avb_free(partition_entry); 323 return AVB_IO_RESULT_OK; 324 } 325 326 /* Helper method to get the parent path to the current |walker| path 327 * given the initial path, |init|. Resulting path is stored in |next|. 328 * Caller is responsible for freeing |next|. Stores allocated bytes 329 * for |next| in |out_bytes|. Returns EFI_SUCCESS on success. 330 */ 331 static EFI_STATUS walk_path(IN EFI_DEVICE_PATH* init, 332 IN EFI_DEVICE_PATH* walker, 333 OUT EFI_DEVICE_PATH** next, 334 OUT UINTN* out_bytes) { 335 /* Number of bytes from initial path to current walker. */ 336 UINTN walker_bytes = (uint8_t*)NextDevicePathNode(walker) - (uint8_t*)init; 337 *out_bytes = sizeof(EFI_DEVICE_PATH) + walker_bytes; 338 339 *next = (EFI_DEVICE_PATH*)avb_malloc(*out_bytes); 340 if (*next == NULL) { 341 *out_bytes = 0; 342 return EFI_NOT_FOUND; 343 } 344 345 /* Copy in the previous paths. */ 346 avb_memcpy((*next), init, walker_bytes); 347 /* Copy in the new ending of the path. */ 348 avb_memcpy( 349 (uint8_t*)(*next) + walker_bytes, EndDevicePath, sizeof(EFI_DEVICE_PATH)); 350 return EFI_SUCCESS; 351 } 352 353 /* Helper method to validate a GPT header, |gpth|. 354 * 355 * @return EFI_STATUS EFI_SUCCESS on success. 356 */ 357 static EFI_STATUS validate_gpt(const IN GPTHeader* gpth) { 358 if (avb_memcmp(gpth->signature, GPT_MAGIC, sizeof(gpth->signature)) != 0) { 359 avb_error("GPT signature does not match.\n"); 360 return EFI_NOT_FOUND; 361 } 362 /* Make sure GPT header bytes are within minimun and block size. */ 363 if (gpth->header_size < GPT_MIN_SIZE) { 364 avb_error("GPT header too small.\n"); 365 return EFI_NOT_FOUND; 366 } 367 if (gpth->header_size > AVB_BLOCK_SIZE) { 368 avb_error("GPT header too big.\n"); 369 return EFI_NOT_FOUND; 370 } 371 372 GPTHeader gpth_tmp = {{0}}; 373 avb_memcpy(&gpth_tmp, gpth, sizeof(GPTHeader)); 374 uint32_t gpt_header_crc = gpth_tmp.header_crc32; 375 gpth_tmp.header_crc32 = 0; 376 uint32_t gpt_header_crc_calc = 377 CalculateCrc((uint8_t*)&gpth_tmp, gpth_tmp.header_size); 378 379 if (gpt_header_crc != gpt_header_crc_calc) { 380 avb_error("GPT header crc invalid.\n"); 381 return EFI_NOT_FOUND; 382 } 383 384 if (gpth->revision != GPT_REVISION) { 385 avb_error("GPT header wrong revision.\n"); 386 return EFI_NOT_FOUND; 387 } 388 389 return EFI_SUCCESS; 390 } 391 392 /* Queries |disk_handle| for a |block_io| device and the corresponding 393 * path, |block_path|. The |block_io| device is found by iteratively 394 * querying parent devices and checking for a GPT Header. This 395 * ensures the resulting |block_io| device is the top level block 396 * device having access to partition entries. Returns EFI_STATUS 397 * EFI_NOT_FOUND on failure, EFI_SUCCESS otherwise. 398 */ 399 static EFI_STATUS get_disk_block_io(IN EFI_HANDLE* block_handle, 400 OUT EFI_BLOCK_IO** block_io, 401 OUT EFI_DISK_IO** disk_io, 402 OUT EFI_DEVICE_PATH** io_path) { 403 EFI_STATUS err; 404 EFI_HANDLE disk_handle; 405 UINTN path_bytes; 406 EFI_DEVICE_PATH* disk_path; 407 EFI_DEVICE_PATH* walker_path; 408 EFI_DEVICE_PATH* init_path; 409 GPTHeader gpt_header = {{0}}; 410 init_path = DevicePathFromHandle(block_handle); 411 412 if (!init_path) { 413 return EFI_NOT_FOUND; 414 } 415 416 walker_path = init_path; 417 while (!IsDevicePathEnd(walker_path)) { 418 walker_path = NextDevicePathNode(walker_path); 419 420 err = walk_path(init_path, walker_path, &(*io_path), &path_bytes); 421 if (EFI_ERROR(err)) { 422 avb_error("Cannot walk device path.\n"); 423 return EFI_NOT_FOUND; 424 } 425 426 disk_path = (EFI_DEVICE_PATH*)avb_malloc(path_bytes); 427 avb_memcpy(disk_path, *io_path, path_bytes); 428 err = uefi_call_wrapper(BS->LocateDevicePath, 429 NUM_ARGS_LOCATE_DEVICE_PATH, 430 &BlockIoProtocol, 431 &(*io_path), 432 &block_handle); 433 if (EFI_ERROR(err)) { 434 avb_free(*io_path); 435 avb_free(disk_path); 436 continue; 437 } 438 err = uefi_call_wrapper(BS->LocateDevicePath, 439 NUM_ARGS_LOCATE_DEVICE_PATH, 440 &DiskIoProtocol, 441 &disk_path, 442 &disk_handle); 443 if (EFI_ERROR(err)) { 444 avb_error("LocateDevicePath, DISK_IO_PROTOCOL.\n"); 445 avb_free(*io_path); 446 avb_free(disk_path); 447 continue; 448 } 449 450 /* Handle Block and Disk I/O. Attempt to get handle on device, 451 * must be Block/Disk Io type. 452 */ 453 err = uefi_call_wrapper(BS->HandleProtocol, 454 NUM_ARGS_HANDLE_PROTOCOL, 455 block_handle, 456 &BlockIoProtocol, 457 (VOID**)&(*block_io)); 458 if (EFI_ERROR(err)) { 459 avb_error("Cannot get handle on block device.\n"); 460 avb_free(*io_path); 461 avb_free(disk_path); 462 continue; 463 } 464 err = uefi_call_wrapper(BS->HandleProtocol, 465 NUM_ARGS_HANDLE_PROTOCOL, 466 disk_handle, 467 &DiskIoProtocol, 468 (VOID**)&(*disk_io)); 469 if (EFI_ERROR(err)) { 470 avb_error("Cannot get handle on disk device.\n"); 471 avb_free(*io_path); 472 avb_free(disk_path); 473 continue; 474 } 475 476 if ((*block_io)->Media->LogicalPartition || 477 !(*block_io)->Media->MediaPresent) { 478 avb_error("Logical partion or No Media Present, continue...\n"); 479 avb_free(*io_path); 480 avb_free(disk_path); 481 continue; 482 } 483 484 err = uefi_call_wrapper((*block_io)->ReadBlocks, 485 NUM_ARGS_READ_BLOCKS, 486 (*block_io), 487 (*block_io)->Media->MediaId, 488 1, 489 sizeof(GPTHeader), 490 &gpt_header); 491 492 if (EFI_ERROR(err)) { 493 avb_error("ReadBlocks, Block Media error.\n"); 494 avb_free(*io_path); 495 avb_free(disk_path); 496 continue; 497 } 498 499 err = validate_gpt(&gpt_header); 500 if (EFI_ERROR(err)) { 501 avb_error("Invalid GPTHeader\n"); 502 avb_free(*io_path); 503 avb_free(disk_path); 504 continue; 505 } 506 507 return EFI_SUCCESS; 508 } 509 510 (*block_io) = NULL; 511 return EFI_NOT_FOUND; 512 } 513 514 static AvbIOResult validate_vbmeta_public_key( 515 AvbOps* ops, 516 const uint8_t* public_key_data, 517 size_t public_key_length, 518 const uint8_t* public_key_metadata, 519 size_t public_key_metadata_length, 520 bool* out_key_is_trusted) { 521 /* For now we just allow any key. */ 522 if (out_key_is_trusted != NULL) { 523 *out_key_is_trusted = true; 524 } 525 avb_debug("TODO: implement validate_vbmeta_public_key().\n"); 526 return AVB_IO_RESULT_OK; 527 } 528 529 static AvbIOResult read_rollback_index(AvbOps* ops, 530 size_t rollback_index_slot, 531 uint64_t* out_rollback_index) { 532 /* For now we always return 0 as the stored rollback index. */ 533 avb_debug("TODO: implement read_rollback_index().\n"); 534 if (out_rollback_index != NULL) { 535 *out_rollback_index = 0; 536 } 537 return AVB_IO_RESULT_OK; 538 } 539 540 static AvbIOResult write_rollback_index(AvbOps* ops, 541 size_t rollback_index_slot, 542 uint64_t rollback_index) { 543 /* For now this is a no-op. */ 544 avb_debug("TODO: implement write_rollback_index().\n"); 545 return AVB_IO_RESULT_OK; 546 } 547 548 static AvbIOResult read_is_device_unlocked(AvbOps* ops, bool* out_is_unlocked) { 549 /* For now we always return that the device is unlocked. */ 550 avb_debug("TODO: implement read_is_device_unlocked().\n"); 551 *out_is_unlocked = true; 552 return AVB_IO_RESULT_OK; 553 } 554 555 static void set_hex(char* buf, uint8_t value) { 556 char hex_digits[17] = "0123456789abcdef"; 557 buf[0] = hex_digits[value >> 4]; 558 buf[1] = hex_digits[value & 0x0f]; 559 } 560 561 static AvbIOResult get_unique_guid_for_partition(AvbOps* ops, 562 const char* partition, 563 char* guid_buf, 564 size_t guid_buf_size) { 565 EFI_STATUS err; 566 GPTEntry* partition_entry; 567 UEFIAvbOpsData* data = (UEFIAvbOpsData*)ops->user_data; 568 569 avb_assert(partition != NULL); 570 avb_assert(guid_buf != NULL); 571 572 err = 573 find_partition_entry_by_name(data->block_io, partition, &partition_entry); 574 if (EFI_ERROR(err)) { 575 avb_error("Error getting unique GUID for partition.\n"); 576 return AVB_IO_RESULT_ERROR_IO; 577 } 578 579 if (guid_buf_size < 37) { 580 avb_error("GUID buffer size too small.\n"); 581 return AVB_IO_RESULT_ERROR_IO; 582 } 583 584 /* The GUID encoding is somewhat peculiar in terms of byte order. It 585 * is what it is. 586 */ 587 set_hex(guid_buf + 0, partition_entry->unique_GUID[3]); 588 set_hex(guid_buf + 2, partition_entry->unique_GUID[2]); 589 set_hex(guid_buf + 4, partition_entry->unique_GUID[1]); 590 set_hex(guid_buf + 6, partition_entry->unique_GUID[0]); 591 guid_buf[8] = '-'; 592 set_hex(guid_buf + 9, partition_entry->unique_GUID[5]); 593 set_hex(guid_buf + 11, partition_entry->unique_GUID[4]); 594 guid_buf[13] = '-'; 595 set_hex(guid_buf + 14, partition_entry->unique_GUID[7]); 596 set_hex(guid_buf + 16, partition_entry->unique_GUID[6]); 597 guid_buf[18] = '-'; 598 set_hex(guid_buf + 19, partition_entry->unique_GUID[8]); 599 set_hex(guid_buf + 21, partition_entry->unique_GUID[9]); 600 guid_buf[23] = '-'; 601 set_hex(guid_buf + 24, partition_entry->unique_GUID[10]); 602 set_hex(guid_buf + 26, partition_entry->unique_GUID[11]); 603 set_hex(guid_buf + 28, partition_entry->unique_GUID[12]); 604 set_hex(guid_buf + 30, partition_entry->unique_GUID[13]); 605 set_hex(guid_buf + 32, partition_entry->unique_GUID[14]); 606 set_hex(guid_buf + 34, partition_entry->unique_GUID[15]); 607 guid_buf[36] = '\0'; 608 return AVB_IO_RESULT_OK; 609 } 610 611 AvbOps* uefi_avb_ops_new(EFI_HANDLE app_image) { 612 UEFIAvbOpsData* data; 613 EFI_STATUS err; 614 EFI_LOADED_IMAGE* loaded_app_image = NULL; 615 EFI_GUID loaded_image_protocol = LOADED_IMAGE_PROTOCOL; 616 617 data = avb_calloc(sizeof(UEFIAvbOpsData)); 618 data->ops.user_data = data; 619 620 data->efi_image_handle = app_image; 621 err = uefi_call_wrapper(BS->HandleProtocol, 622 NUM_ARGS_HANDLE_PROTOCOL, 623 app_image, 624 &loaded_image_protocol, 625 (VOID**)&loaded_app_image); 626 if (EFI_ERROR(err)) { 627 avb_error("HandleProtocol, LOADED_IMAGE_PROTOCOL.\n"); 628 return 0; 629 } 630 631 /* Get parent device disk and block I/O. */ 632 err = get_disk_block_io(loaded_app_image->DeviceHandle, 633 &data->block_io, 634 &data->disk_io, 635 &data->path); 636 if (EFI_ERROR(err)) { 637 avb_error("Could not acquire block or disk device handle.\n"); 638 return 0; 639 } 640 641 data->ops.ab_ops = &data->ab_ops; 642 data->ops.read_from_partition = read_from_partition; 643 data->ops.write_to_partition = write_to_partition; 644 data->ops.validate_vbmeta_public_key = validate_vbmeta_public_key; 645 data->ops.read_rollback_index = read_rollback_index; 646 data->ops.write_rollback_index = write_rollback_index; 647 data->ops.read_is_device_unlocked = read_is_device_unlocked; 648 data->ops.get_unique_guid_for_partition = get_unique_guid_for_partition; 649 data->ops.get_size_of_partition = get_size_of_partition; 650 651 data->ab_ops.ops = &data->ops; 652 data->ab_ops.read_ab_metadata = avb_ab_data_read; 653 data->ab_ops.write_ab_metadata = avb_ab_data_write; 654 655 return &data->ops; 656 } 657 658 void uefi_avb_ops_free(AvbOps* ops) { 659 UEFIAvbOpsData* data = ops->user_data; 660 avb_free(data); 661 } 662