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 /* Helper method to get the parent path to the current |walker| path 299 * given the initial path, |init|. Resulting path is stored in |next|. 300 * Caller is responsible for freeing |next|. Stores allocated bytes 301 * for |next| in |out_bytes|. Returns EFI_SUCCESS on success. 302 */ 303 static EFI_STATUS walk_path(IN EFI_DEVICE_PATH* init, 304 IN EFI_DEVICE_PATH* walker, 305 OUT EFI_DEVICE_PATH** next, 306 OUT UINTN* out_bytes) { 307 /* Number of bytes from initial path to current walker. */ 308 UINTN walker_bytes = (uint8_t*)NextDevicePathNode(walker) - (uint8_t*)init; 309 *out_bytes = sizeof(EFI_DEVICE_PATH) + walker_bytes; 310 311 *next = (EFI_DEVICE_PATH*)avb_malloc(*out_bytes); 312 if (*next == NULL) { 313 *out_bytes = 0; 314 return EFI_NOT_FOUND; 315 } 316 317 /* Copy in the previous paths. */ 318 avb_memcpy((*next), init, walker_bytes); 319 /* Copy in the new ending of the path. */ 320 avb_memcpy( 321 (uint8_t*)(*next) + walker_bytes, EndDevicePath, sizeof(EFI_DEVICE_PATH)); 322 return EFI_SUCCESS; 323 } 324 325 /* Helper method to validate a GPT header, |gpth|. 326 * 327 * @return EFI_STATUS EFI_SUCCESS on success. 328 */ 329 static EFI_STATUS validate_gpt(const IN GPTHeader* gpth) { 330 if (avb_memcmp(gpth->signature, GPT_MAGIC, sizeof(gpth->signature)) != 0) { 331 avb_error("GPT signature does not match.\n"); 332 return EFI_NOT_FOUND; 333 } 334 /* Make sure GPT header bytes are within minimun and block size. */ 335 if (gpth->header_size < GPT_MIN_SIZE) { 336 avb_error("GPT header too small.\n"); 337 return EFI_NOT_FOUND; 338 } 339 if (gpth->header_size > AVB_BLOCK_SIZE) { 340 avb_error("GPT header too big.\n"); 341 return EFI_NOT_FOUND; 342 } 343 344 GPTHeader gpth_tmp = {{0}}; 345 avb_memcpy(&gpth_tmp, gpth, sizeof(GPTHeader)); 346 uint32_t gpt_header_crc = gpth_tmp.header_crc32; 347 gpth_tmp.header_crc32 = 0; 348 uint32_t gpt_header_crc_calc = 349 CalculateCrc((uint8_t*)&gpth_tmp, gpth_tmp.header_size); 350 351 if (gpt_header_crc != gpt_header_crc_calc) { 352 avb_error("GPT header crc invalid.\n"); 353 return EFI_NOT_FOUND; 354 } 355 356 if (gpth->revision != GPT_REVISION) { 357 avb_error("GPT header wrong revision.\n"); 358 return EFI_NOT_FOUND; 359 } 360 361 return EFI_SUCCESS; 362 } 363 364 /* Queries |disk_handle| for a |block_io| device and the corresponding 365 * path, |block_path|. The |block_io| device is found by iteratively 366 * querying parent devices and checking for a GPT Header. This 367 * ensures the resulting |block_io| device is the top level block 368 * device having access to partition entries. Returns EFI_STATUS 369 * EFI_NOT_FOUND on failure, EFI_SUCCESS otherwise. 370 */ 371 static EFI_STATUS get_disk_block_io(IN EFI_HANDLE* block_handle, 372 OUT EFI_BLOCK_IO** block_io, 373 OUT EFI_DISK_IO** disk_io, 374 OUT EFI_DEVICE_PATH** io_path) { 375 EFI_STATUS err; 376 EFI_HANDLE disk_handle; 377 UINTN path_bytes; 378 EFI_DEVICE_PATH* disk_path; 379 EFI_DEVICE_PATH* walker_path; 380 EFI_DEVICE_PATH* init_path; 381 GPTHeader gpt_header = {{0}}; 382 init_path = DevicePathFromHandle(block_handle); 383 384 if (!init_path) { 385 return EFI_NOT_FOUND; 386 } 387 388 walker_path = init_path; 389 while (!IsDevicePathEnd(walker_path)) { 390 walker_path = NextDevicePathNode(walker_path); 391 392 err = walk_path(init_path, walker_path, &(*io_path), &path_bytes); 393 if (EFI_ERROR(err)) { 394 avb_error("Cannot walk device path.\n"); 395 return EFI_NOT_FOUND; 396 } 397 398 disk_path = (EFI_DEVICE_PATH*)avb_malloc(path_bytes); 399 avb_memcpy(disk_path, *io_path, path_bytes); 400 err = uefi_call_wrapper(BS->LocateDevicePath, 401 NUM_ARGS_LOCATE_DEVICE_PATH, 402 &BlockIoProtocol, 403 &(*io_path), 404 &block_handle); 405 if (EFI_ERROR(err)) { 406 avb_free(*io_path); 407 avb_free(disk_path); 408 continue; 409 } 410 err = uefi_call_wrapper(BS->LocateDevicePath, 411 NUM_ARGS_LOCATE_DEVICE_PATH, 412 &DiskIoProtocol, 413 &disk_path, 414 &disk_handle); 415 if (EFI_ERROR(err)) { 416 avb_error("LocateDevicePath, DISK_IO_PROTOCOL.\n"); 417 avb_free(*io_path); 418 avb_free(disk_path); 419 continue; 420 } 421 422 /* Handle Block and Disk I/O. Attempt to get handle on device, 423 * must be Block/Disk Io type. 424 */ 425 err = uefi_call_wrapper(BS->HandleProtocol, 426 NUM_ARGS_HANDLE_PROTOCOL, 427 block_handle, 428 &BlockIoProtocol, 429 (VOID**)&(*block_io)); 430 if (EFI_ERROR(err)) { 431 avb_error("Cannot get handle on block device.\n"); 432 avb_free(*io_path); 433 avb_free(disk_path); 434 continue; 435 } 436 err = uefi_call_wrapper(BS->HandleProtocol, 437 NUM_ARGS_HANDLE_PROTOCOL, 438 disk_handle, 439 &DiskIoProtocol, 440 (VOID**)&(*disk_io)); 441 if (EFI_ERROR(err)) { 442 avb_error("Cannot get handle on disk device.\n"); 443 avb_free(*io_path); 444 avb_free(disk_path); 445 continue; 446 } 447 448 if ((*block_io)->Media->LogicalPartition || 449 !(*block_io)->Media->MediaPresent) { 450 avb_error("Logical partion or No Media Present, continue...\n"); 451 avb_free(*io_path); 452 avb_free(disk_path); 453 continue; 454 } 455 456 err = uefi_call_wrapper((*block_io)->ReadBlocks, 457 NUM_ARGS_READ_BLOCKS, 458 (*block_io), 459 (*block_io)->Media->MediaId, 460 1, 461 sizeof(GPTHeader), 462 &gpt_header); 463 464 if (EFI_ERROR(err)) { 465 avb_error("ReadBlocks, Block Media error.\n"); 466 avb_free(*io_path); 467 avb_free(disk_path); 468 continue; 469 } 470 471 err = validate_gpt(&gpt_header); 472 if (EFI_ERROR(err)) { 473 avb_error("Invalid GPTHeader\n"); 474 avb_free(*io_path); 475 avb_free(disk_path); 476 continue; 477 } 478 479 return EFI_SUCCESS; 480 } 481 482 (*block_io) = NULL; 483 return EFI_NOT_FOUND; 484 } 485 486 static AvbIOResult validate_vbmeta_public_key( 487 AvbOps* ops, 488 const uint8_t* public_key_data, 489 size_t public_key_length, 490 const uint8_t* public_key_metadata, 491 size_t public_key_metadata_length, 492 bool* out_key_is_trusted) { 493 /* For now we just allow any key. */ 494 if (out_key_is_trusted != NULL) { 495 *out_key_is_trusted = true; 496 } 497 avb_debug("TODO: implement validate_vbmeta_public_key().\n"); 498 return AVB_IO_RESULT_OK; 499 } 500 501 static AvbIOResult read_rollback_index(AvbOps* ops, 502 size_t rollback_index_slot, 503 uint64_t* out_rollback_index) { 504 /* For now we always return 0 as the stored rollback index. */ 505 avb_debug("TODO: implement read_rollback_index().\n"); 506 if (out_rollback_index != NULL) { 507 *out_rollback_index = 0; 508 } 509 return AVB_IO_RESULT_OK; 510 } 511 512 static AvbIOResult write_rollback_index(AvbOps* ops, 513 size_t rollback_index_slot, 514 uint64_t rollback_index) { 515 /* For now this is a no-op. */ 516 avb_debug("TODO: implement write_rollback_index().\n"); 517 return AVB_IO_RESULT_OK; 518 } 519 520 static AvbIOResult read_is_device_unlocked(AvbOps* ops, bool* out_is_unlocked) { 521 /* For now we always return that the device is unlocked. */ 522 avb_debug("TODO: implement read_is_device_unlocked().\n"); 523 *out_is_unlocked = true; 524 return AVB_IO_RESULT_OK; 525 } 526 527 static void set_hex(char* buf, uint8_t value) { 528 char hex_digits[17] = "0123456789abcdef"; 529 buf[0] = hex_digits[value >> 4]; 530 buf[1] = hex_digits[value & 0x0f]; 531 } 532 533 static AvbIOResult get_unique_guid_for_partition(AvbOps* ops, 534 const char* partition, 535 char* guid_buf, 536 size_t guid_buf_size) { 537 EFI_STATUS err; 538 GPTEntry* partition_entry; 539 UEFIAvbOpsData* data = (UEFIAvbOpsData*)ops->user_data; 540 541 avb_assert(partition != NULL); 542 avb_assert(guid_buf != NULL); 543 544 err = 545 find_partition_entry_by_name(data->block_io, partition, &partition_entry); 546 if (EFI_ERROR(err)) { 547 avb_error("Error getting unique GUID for partition.\n"); 548 return AVB_IO_RESULT_ERROR_IO; 549 } 550 551 if (guid_buf_size < 37) { 552 avb_error("GUID buffer size too small.\n"); 553 return AVB_IO_RESULT_ERROR_IO; 554 } 555 556 /* The GUID encoding is somewhat peculiar in terms of byte order. It 557 * is what it is. 558 */ 559 set_hex(guid_buf + 0, partition_entry->unique_GUID[3]); 560 set_hex(guid_buf + 2, partition_entry->unique_GUID[2]); 561 set_hex(guid_buf + 4, partition_entry->unique_GUID[1]); 562 set_hex(guid_buf + 6, partition_entry->unique_GUID[0]); 563 guid_buf[8] = '-'; 564 set_hex(guid_buf + 9, partition_entry->unique_GUID[5]); 565 set_hex(guid_buf + 11, partition_entry->unique_GUID[4]); 566 guid_buf[13] = '-'; 567 set_hex(guid_buf + 14, partition_entry->unique_GUID[7]); 568 set_hex(guid_buf + 16, partition_entry->unique_GUID[6]); 569 guid_buf[18] = '-'; 570 set_hex(guid_buf + 19, partition_entry->unique_GUID[8]); 571 set_hex(guid_buf + 21, partition_entry->unique_GUID[9]); 572 guid_buf[23] = '-'; 573 set_hex(guid_buf + 24, partition_entry->unique_GUID[10]); 574 set_hex(guid_buf + 26, partition_entry->unique_GUID[11]); 575 set_hex(guid_buf + 28, partition_entry->unique_GUID[12]); 576 set_hex(guid_buf + 30, partition_entry->unique_GUID[13]); 577 set_hex(guid_buf + 32, partition_entry->unique_GUID[14]); 578 set_hex(guid_buf + 34, partition_entry->unique_GUID[15]); 579 guid_buf[36] = '\0'; 580 return AVB_IO_RESULT_OK; 581 } 582 583 AvbOps* uefi_avb_ops_new(EFI_HANDLE app_image) { 584 UEFIAvbOpsData* data; 585 EFI_STATUS err; 586 EFI_LOADED_IMAGE* loaded_app_image = NULL; 587 EFI_GUID loaded_image_protocol = LOADED_IMAGE_PROTOCOL; 588 589 data = avb_calloc(sizeof(UEFIAvbOpsData)); 590 data->ops.user_data = data; 591 592 data->efi_image_handle = app_image; 593 err = uefi_call_wrapper(BS->HandleProtocol, 594 NUM_ARGS_HANDLE_PROTOCOL, 595 app_image, 596 &loaded_image_protocol, 597 (VOID**)&loaded_app_image); 598 if (EFI_ERROR(err)) { 599 avb_error("HandleProtocol, LOADED_IMAGE_PROTOCOL.\n"); 600 return 0; 601 } 602 603 /* Get parent device disk and block I/O. */ 604 err = get_disk_block_io(loaded_app_image->DeviceHandle, 605 &data->block_io, 606 &data->disk_io, 607 &data->path); 608 if (EFI_ERROR(err)) { 609 avb_error("Could not acquire block or disk device handle.\n"); 610 return 0; 611 } 612 613 data->ops.ab_ops = &data->ab_ops; 614 data->ops.read_from_partition = read_from_partition; 615 data->ops.write_to_partition = write_to_partition; 616 data->ops.validate_vbmeta_public_key = validate_vbmeta_public_key; 617 data->ops.read_rollback_index = read_rollback_index; 618 data->ops.write_rollback_index = write_rollback_index; 619 data->ops.read_is_device_unlocked = read_is_device_unlocked; 620 data->ops.get_unique_guid_for_partition = get_unique_guid_for_partition; 621 622 data->ab_ops.ops = &data->ops; 623 data->ab_ops.read_ab_metadata = avb_ab_data_read; 624 data->ab_ops.write_ab_metadata = avb_ab_data_write; 625 626 return &data->ops; 627 } 628 629 void uefi_avb_ops_free(AvbOps* ops) { 630 UEFIAvbOpsData* data = ops->user_data; 631 avb_free(data); 632 } 633