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