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
find_partition_entry_by_name(IN EFI_BLOCK_IO * block_io,const char * partition_name,GPTEntry ** entry_buf)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
read_from_partition(AvbOps * ops,const char * partition_name,int64_t offset_from_partition,size_t num_bytes,void * buf,size_t * out_num_read)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
write_to_partition(AvbOps * ops,const char * partition_name,int64_t offset_from_partition,size_t num_bytes,const void * buf)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 */
walk_path(IN EFI_DEVICE_PATH * init,IN EFI_DEVICE_PATH * walker,OUT EFI_DEVICE_PATH ** next,OUT UINTN * out_bytes)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 */
validate_gpt(const IN GPTHeader * gpth)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 */
get_disk_block_io(IN EFI_HANDLE * block_handle,OUT EFI_BLOCK_IO ** block_io,OUT EFI_DISK_IO ** disk_io,OUT EFI_DEVICE_PATH ** io_path)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
validate_vbmeta_public_key(AvbOps * ops,const uint8_t * public_key_data,size_t public_key_length,const uint8_t * public_key_metadata,size_t public_key_metadata_length,bool * out_key_is_trusted)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
read_rollback_index(AvbOps * ops,size_t rollback_index_slot,uint64_t * out_rollback_index)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
write_rollback_index(AvbOps * ops,size_t rollback_index_slot,uint64_t rollback_index)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
read_is_device_unlocked(AvbOps * ops,bool * out_is_unlocked)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
set_hex(char * buf,uint8_t value)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
get_unique_guid_for_partition(AvbOps * ops,const char * partition,char * guid_buf,size_t guid_buf_size)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
uefi_avb_ops_new(EFI_HANDLE app_image)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
uefi_avb_ops_free(AvbOps * ops)629 void uefi_avb_ops_free(AvbOps* ops) {
630 UEFIAvbOpsData* data = ops->user_data;
631 avb_free(data);
632 }
633