• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
get_size_of_partition(AvbOps * ops,const char * partition_name,uint64_t * out_size)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  */
walk_path(IN EFI_DEVICE_PATH * init,IN EFI_DEVICE_PATH * walker,OUT EFI_DEVICE_PATH ** next,OUT UINTN * out_bytes)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  */
validate_gpt(const IN GPTHeader * gpth)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  */
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)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 
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)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 
read_rollback_index(AvbOps * ops,size_t rollback_index_slot,uint64_t * out_rollback_index)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 
write_rollback_index(AvbOps * ops,size_t rollback_index_slot,uint64_t rollback_index)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 
read_is_device_unlocked(AvbOps * ops,bool * out_is_unlocked)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 
set_hex(char * buf,uint8_t value)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 
get_unique_guid_for_partition(AvbOps * ops,const char * partition,char * guid_buf,size_t guid_buf_size)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 
uefi_avb_ops_new(EFI_HANDLE app_image)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 
uefi_avb_ops_free(AvbOps * ops)658 void uefi_avb_ops_free(AvbOps* ops) {
659   UEFIAvbOpsData* data = ops->user_data;
660   avb_free(data);
661 }
662