blob: 11f428a86289e29d0aa2db38144138992cf87075 [file] [log] [blame]
Monika Singh5e170362018-03-14 00:48:36 +05301/*
lijuangb4647592018-06-25 14:24:47 +08002 * Copyright (C) 2017 The Android Open Source Project
Monika Singh5e170362018-03-14 00:48:36 +05303 *
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/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
26 *
27 * Redistribution and use in source and binary forms, with or without
28 * modification, are permitted provided that the following conditions are
29 * met:
30 * * Redistributions of source code must retain the above copyright
31 * notice, this list of conditions and the following disclaimer.
32 * * Redistributions in binary form must reproduce the above
33 * copyright notice, this list of conditions and the following
34 * disclaimer in the documentation and/or other materials provided
35 * with the distribution.
36 * * Neither the name of The Linux Foundation nor the names of its
37 * contributors may be used to endorse or promote products derived
38 * from this software without specific prior written permission.
39 *
40 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
41 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
42 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
43 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
44 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
45 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
46 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
47 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
48 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
49 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
50 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
51*/
52
53#include "../OEMPublicKey.h"
54#include "avb_sysdeps.h"
55#include "libavb.h"
56#include <platform.h>
57#include <err.h>
58#include <ab_partition_parser.h>
59#include <partition_parser.h>
Monika Singh7aa8e112019-07-26 11:58:41 +053060#define MAX_FOOTER_SIZE 4096
Monika Singh5e170362018-03-14 00:48:36 +053061
62struct partition_entry *PtnEntries;
63
64bool IsCurrentSlotSuccessful()
65{
66 struct ab_slot_info slot_info[AB_SUPPORTED_SLOTS];
67 int slot_idx =INVALID;
68
69 slot_idx = partition_find_active_slot();
70 if(slot_idx == INVALID)
71 {
72 dprintf(CRITICAL,
73 "IsCurrentSlotSuccessful: no active slots found!\n");
74 return FALSE;
75 }
76 partition_fill_slot_meta(slot_info);
77 if(!strncmp(slot_info[slot_idx].slot_is_succesful_rsp,"yes",strlen("yes")))
78 return TRUE;
79
80 return FALSE;
81}
82
83static struct partition_entry *Getpartition_entry(const char *Partition)
84{
85 int32_t Index = partition_get_index(Partition);
86 struct partition_entry *partition_entries =
87 partition_get_partition_entries();
88 if (partition_entries == NULL) {
89 dprintf(CRITICAL, "Getpartition_entry: No partition entry found\n");
90 return NULL;
91 }
92
93 PtnEntries = partition_entries;
94
95 if (Index == INVALID_PTN) {
96 dprintf(CRITICAL, "Getpartition_entry: No partition entry for "
97 "%s, invalid index\n", Partition);
98 return NULL;
99 }
100 return &PtnEntries[Index];
101}
102
103int get_unique_guid(const char *Partition, char *unique_guid)
104{
105 struct partition_entry *gp = Getpartition_entry(Partition);
106 if(gp == NULL)
107 {
108 dprintf(CRITICAL, "Partition entry not found\n");
109 return -1;
110
111 }
112 if (!unique_guid)
113 return -1;
114
115 memcpy(unique_guid, gp->unique_partition_guid, UNIQUE_PARTITION_GUID_SIZE);
116
117 return 0;
118}
119
120static struct partition_entry *GetBootpartition_entry(Slot *BootSlot)
121{
122 int32_t Index = INVALID_PTN;
123 struct partition_entry *partition_entries =
124 partition_get_partition_entries();
125 if( BootSlot == NULL)
126 {
127 dprintf(INFO, "No bootable slot found \n");
128 return NULL;
129
130 }
131 if( partition_entries == NULL)
132 {
133 dprintf(INFO, "No partition entry found \n");
134 return NULL;
135
136 }
137 PtnEntries = partition_entries;
138
139 if (strncmp("_a", (const char *)BootSlot->Suffix, strlen((const char *)BootSlot->Suffix)) == 0) {
140 Index = partition_get_index("boot_a");
141 } else if (strncmp("_b", (const char *)BootSlot->Suffix, strlen((const char *)BootSlot->Suffix)) == 0) {
142 Index = partition_get_index("boot_b");
143 } else {
144 dprintf(CRITICAL, "GetBootpartition_entry: No boot partition "
145 "entry for slot %s\n", (char *)BootSlot->Suffix);
146 return NULL;
147 }
148
149 if (Index == INVALID_PTN) {
150 dprintf(CRITICAL,
151 "GetBootpartition_entry: No boot partition entry "
152 "for slot %s, invalid index\n", (char *)BootSlot->Suffix);
153 return NULL;
154 }
155 return &PtnEntries[Index];
156}
157
158AvbIOResult AvbReadFromPartition(AvbOps *Ops, const char *Partition, int64_t ReadOffset,
159 size_t NumBytes, void *Buffer, size_t *OutNumRead)
160{
161 AvbIOResult Result = AVB_IO_RESULT_OK;
162 EFI_STATUS Status = EFI_SUCCESS;
163 VOID *Page = NULL;
Monika Singhd1f33732018-12-28 14:51:35 +0530164 UINT64 Offset = 0;
165 UINT64 ptn = 0;
166 UINT64 part_size = 0;
Monika Singh5e170362018-03-14 00:48:36 +0530167 UINT32 PageSize = 0;
Monika Singhd1f33732018-12-28 14:51:35 +0530168 UINT64 StartBlock = 0;
169 UINT64 LastBlock = 0;
170 UINT64 FullBlock = 0;
171 UINT64 StartPageReadSize = 0;
Monika Singh5e170362018-03-14 00:48:36 +0530172 int index = INVALID_PTN;
173
174 if (Partition == NULL || Buffer == NULL || OutNumRead == NULL || NumBytes <= 0) {
175 dprintf(CRITICAL, "bad input paramaters\n");
176 Result = AVB_IO_RESULT_ERROR_IO;
177 goto out;
178 }
179 *OutNumRead = 0;
180
Monika Singh7aa8e112019-07-26 11:58:41 +0530181 if (NumBytes > MAX_FOOTER_SIZE && !getimage(Buffer, OutNumRead, Partition)) {
Mayank Grover698adb02018-09-04 20:15:06 +0530182 /* API returns previously loaded Images buffer address and size */
Monika Singh5c317dc2018-09-25 11:09:55 +0530183 dprintf(SPEW, "DEBUG: %s already loaded \n", Partition);
Monika Singh5e170362018-03-14 00:48:36 +0530184 return AVB_IO_RESULT_OK;
185 }
Monika Singh5c317dc2018-09-25 11:09:55 +0530186 dprintf(SPEW, "Loading image %s\n", Partition);
Monika Singh5e170362018-03-14 00:48:36 +0530187 index = partition_get_index(Partition);
188 ptn = partition_get_offset(index);
Monika Singh5c317dc2018-09-25 11:09:55 +0530189 part_size = partition_get_size(index);
Monika Singh5e170362018-03-14 00:48:36 +0530190
191 if (ReadOffset < 0) {
Monika Singh5c317dc2018-09-25 11:09:55 +0530192 if ((-ReadOffset) > (int64_t)part_size) {
Monika Singh5e170362018-03-14 00:48:36 +0530193 dprintf(CRITICAL,
194 "Negative Offset outside range.\n");
195 Result = AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION;
196 goto out;
197 }
Monika Singh5c317dc2018-09-25 11:09:55 +0530198 Offset = part_size - (-ReadOffset);
Monika Singh5e170362018-03-14 00:48:36 +0530199 dprintf(DEBUG,
Monika Singh5c317dc2018-09-25 11:09:55 +0530200 "negative Offset (%lld) converted to (0x%llx) \n", ReadOffset, Offset);
Monika Singh5e170362018-03-14 00:48:36 +0530201 } else {
202 // check int64_t to UINT32 converstion?
203 Offset = ReadOffset;
204 }
205
Monika Singh5c317dc2018-09-25 11:09:55 +0530206 if (Offset > part_size) {
Monika Singh5e170362018-03-14 00:48:36 +0530207 dprintf(CRITICAL, "Offset outside range.\n");
208 Result = AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION;
209 goto out;
210 }
211
Monika Singh5c317dc2018-09-25 11:09:55 +0530212 if (NumBytes > part_size - Offset) {
213 NumBytes = part_size - Offset;
Monika Singh5e170362018-03-14 00:48:36 +0530214 }
215
216 dprintf(CRITICAL,
Monika Singh5c317dc2018-09-25 11:09:55 +0530217 "read from %s, 0x%x bytes at Offset 0x%llx, partition size %llu\n",
Monika Singh5e170362018-03-14 00:48:36 +0530218 Partition, NumBytes, Offset, ptn);
219
Monika Singh5c317dc2018-09-25 11:09:55 +0530220 /* |NumBytes| and or |Offset| can be unaligned to block size.
Monika Singh5e170362018-03-14 00:48:36 +0530221 */
Monika Singh5c317dc2018-09-25 11:09:55 +0530222 PageSize = mmc_get_device_blocksize();
Monika Singh5e170362018-03-14 00:48:36 +0530223 Page = avb_malloc(PageSize);
224 if (Page == NULL) {
225 dprintf(CRITICAL, "Allocate for partial read failed!");
226 Result = AVB_IO_RESULT_ERROR_OOM;
227 goto out;
228 }
229
230 StartBlock = Offset / PageSize;
231 LastBlock = (NumBytes + Offset) / PageSize;
232 FullBlock = StartBlock;
233 StartPageReadSize = 0;
234
235 if (Offset % PageSize != 0) {
236 /* Offset not aligned to PageSize*/
Monika Singhd1f33732018-12-28 14:51:35 +0530237 UINT64 StartPageReadOffset = Offset - (StartBlock * PageSize);
Monika Singh5e170362018-03-14 00:48:36 +0530238
239 if (StartBlock == LastBlock) {
240 /* Offset & Offset + NumBytes are in same block */
241 StartPageReadSize = NumBytes;
242 } else {
243 StartPageReadSize = PageSize - StartPageReadOffset;
244 FullBlock++;
245 }
246
247 dprintf(DEBUG,
Monika Singhd1f33732018-12-28 14:51:35 +0530248 "StartBlock 0x%llx, ReadOffset 0x%llx, read_size 0x%llx\n",
249 StartBlock, StartPageReadOffset, StartPageReadSize);
Monika Singh5e170362018-03-14 00:48:36 +0530250 if (StartPageReadSize <= 0 || StartPageReadOffset >= PageSize ||
251 StartPageReadSize > PageSize - StartPageReadOffset ||
252 StartPageReadSize > NumBytes) {
253 dprintf(CRITICAL,
Monika Singhd1f33732018-12-28 14:51:35 +0530254 "StartBlock 0x%llx, ReadOffset 0x%llx,"
255 "read_size 0x%llx outside range.\n",
Monika Singh5e170362018-03-14 00:48:36 +0530256 StartBlock, StartPageReadOffset, StartPageReadSize);
257 Result = AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION;
258 goto out;
259 }
260
Monika Singh5c317dc2018-09-25 11:09:55 +0530261 Status = mmc_read(ptn + (StartBlock * PageSize), Page, PageSize);
Monika Singh5e170362018-03-14 00:48:36 +0530262 if (Status == EFI_SUCCESS) {
263 avb_memcpy(Buffer, Page + StartPageReadOffset, StartPageReadSize);
264 *OutNumRead += StartPageReadSize;
265 } else {
266 *OutNumRead = 0;
267 dprintf(CRITICAL, "ReadBlocks failed %d\n", Status);
268 goto out;
269 }
270 }
271
272 if (*OutNumRead < NumBytes && (NumBytes + Offset) % PageSize != 0) {
273 /* NumBytes + Offset not aligned to PageSize*/
274 /* Offset for last block is always zero, start at Page boundary
275 */
Monika Singhd1f33732018-12-28 14:51:35 +0530276 UINT64 LastPageReadOffset = 0;
277 UINT64 ReadOffset2 = (LastBlock * PageSize);
278 UINT64 LastPageReadSize = (Offset + NumBytes) - ReadOffset2;
Monika Singh5e170362018-03-14 00:48:36 +0530279
280 dprintf(DEBUG,
Monika Singhd1f33732018-12-28 14:51:35 +0530281 "LastBlock 0x%llx, ReadOffset 0x%llx, read_size 0x%llx\n",
Monika Singh5e170362018-03-14 00:48:36 +0530282 LastBlock, LastPageReadOffset, LastPageReadSize);
283
284 if (LastPageReadSize <= 0 || LastPageReadSize >= PageSize ||
285 LastPageReadSize > (NumBytes - *OutNumRead)) {
286 dprintf(CRITICAL,
Monika Singhd1f33732018-12-28 14:51:35 +0530287 "LastBlock 0x%llx, ReadOffset 0x%llx, read_size "
lijuang1f8c8322018-06-20 18:21:19 +0800288 "0x%llx outside range.\n",
Monika Singh5e170362018-03-14 00:48:36 +0530289 LastBlock, LastPageReadOffset, LastPageReadSize);
290 Result = AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION;
291 goto out;
292 }
293
294 Status = mmc_read(ptn + ReadOffset2, Page, PageSize);
295 if (Status == EFI_SUCCESS) {
296 avb_memcpy(Buffer + (NumBytes - LastPageReadSize), Page,
297 LastPageReadSize);
298 *OutNumRead += LastPageReadSize;
299 } else {
300 *OutNumRead = 0;
301 dprintf(CRITICAL, "ReadBlocks failed %d\n", Status);
302 goto out;
303 }
304 }
305
306 if (*OutNumRead < NumBytes) {
307 /* full block reads */
Monika Singhd1f33732018-12-28 14:51:35 +0530308 UINT64 FillPageReadSize = NumBytes - *OutNumRead;
Monika Singh5e170362018-03-14 00:48:36 +0530309
310 if ((FillPageReadSize % PageSize) != 0 ||
311 (NumBytes - StartPageReadSize) < FillPageReadSize) {
312 dprintf(CRITICAL,
Monika Singhd1f33732018-12-28 14:51:35 +0530313 "FullBlock 0x%llx, ReadOffset 0x%x, read_size "
lijuang1f8c8322018-06-20 18:21:19 +0800314 "0x%llx outside range.\n",
Monika Singh5e170362018-03-14 00:48:36 +0530315 FullBlock, 0, FillPageReadSize);
316 Result = AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION;
317 goto out;
318 }
319 dprintf(SPEW,
Monika Singhd1f33732018-12-28 14:51:35 +0530320 "FullBlock 0x%llx, ReadOffset 0x%x, read_size "
lijuang1f8c8322018-06-20 18:21:19 +0800321 "0x%llx outside range. StartPageReadSize %#llx PageSize %d ptn %#llx Buffer %p\n",
Monika Singh5e170362018-03-14 00:48:36 +0530322 FullBlock, 0, FillPageReadSize, StartPageReadSize, PageSize, ptn, Buffer);
323 Status = mmc_read(ptn + FullBlock * PageSize, Buffer + StartPageReadSize,
324 FillPageReadSize);
325 if (Status == EFI_SUCCESS) {
326 *OutNumRead += FillPageReadSize;
327 } else {
328 *OutNumRead = 0;
329 dprintf(CRITICAL, "ReadBlocks failed %d\n", Status);
330 goto out;
331 }
332 }
333out:
334 if (Page != NULL) {
335 avb_free(Page);
336 }
337
338 return Result;
339}
340
341AvbIOResult AvbWriteToPartition(AvbOps *Ops, const char *Partition, int64_t Offset,
342 size_t NumBytes, const void *Buffer)
343{
344 /* unsupported api */
345 return AVB_IO_RESULT_ERROR_IO;
346}
347
348AvbIOResult
349AvbValidateVbmetaPublicKey(AvbOps *Ops, const uint8_t *PublicKeyData,
350 size_t PublicKeyLength, const uint8_t *PublicKeyMetadata,
351 size_t PublicKeyMetadataLength, bool *OutIsTrusted)
352{
353 UINT8 *UserKeyBuffer = NULL;
354 UINT32 UserKeyLength = 0;
355 EFI_STATUS Status = EFI_SUCCESS;
356 AvbOpsUserData *UserData = NULL;
357
358 dprintf(DEBUG, "ValidateVbmetaPublicKey PublicKeyLength %d, "
359 "PublicKeyMetadataLength %d\n",
360 PublicKeyLength, PublicKeyMetadataLength);
361
362 if (Ops == NULL || OutIsTrusted == NULL || PublicKeyData == NULL) {
363 dprintf(CRITICAL, "Invalid parameters\n");
364 return AVB_IO_RESULT_ERROR_IO;
365 }
366
367 Status = get_userkey(&UserKeyBuffer, &UserKeyLength);
368 if (Status != EFI_SUCCESS) {
369 dprintf(CRITICAL, "get_userkey failed\n");
370 return AVB_IO_RESULT_ERROR_IO;
371 }
372
373 UserData = (AvbOpsUserData *)Ops->user_data;
374 UserData->IsUserKey = FALSE;
375
376 if (PublicKeyLength == UserKeyLength &&
377 memcmp(PublicKeyData, UserKeyBuffer, PublicKeyLength) == 0) {
378 *OutIsTrusted = true;
379 UserData->IsUserKey = TRUE;
380 } else if (PublicKeyLength == ARRAY_SIZE(OEMPublicKey) &&
381 memcmp(PublicKeyData, OEMPublicKey, PublicKeyLength) == 0) {
382 *OutIsTrusted = true;
383 } else {
384 *OutIsTrusted = false;
385 memset(UserData->PublicKey, 0, ARRAY_SIZE(UserData->PublicKey));
386 UserData->PublicKeyLen = 0;
387 }
388
389 if (*OutIsTrusted == true) {
390 if (PublicKeyLength > ARRAY_SIZE(UserData->PublicKey)) {
391 dprintf(CRITICAL, "ValidateVbmetaPublicKey: "
392 "public key length too large %d\n",
393 PublicKeyLength);
394 return AVB_IO_RESULT_ERROR_OOM;
395 }
396 memcpy(UserData->PublicKey, PublicKeyData, PublicKeyLength);
397 UserData->PublicKeyLen = PublicKeyLength;
398 }
399 dprintf(DEBUG,
400 "ValidateVbmetaPublicKey OutIsTrusted %d, UserKey %d\n",
401 *OutIsTrusted, UserData->IsUserKey);
402 return AVB_IO_RESULT_OK;
403}
404
405
406AvbIOResult AvbReadRollbackIndex(AvbOps *Ops, size_t RollbackIndexLocation,
407 uint64_t *OutRollbackIndex)
408{
409
410 EFI_STATUS Status = read_rollback_index(RollbackIndexLocation, OutRollbackIndex);
411
412 if (Status != EFI_SUCCESS) {
413 dprintf(CRITICAL, "ReadRollbackIndex failed! %d\n", Status);
414 return AVB_IO_RESULT_ERROR_IO;
415 }
416 dprintf(DEBUG,
417 "ReadRollbackIndex Location %zu, RollbackIndex %llu\n",
418 RollbackIndexLocation, *OutRollbackIndex);
419 return AVB_IO_RESULT_OK;
420}
421
422AvbIOResult
423AvbWriteRollbackIndex(AvbOps *Ops, size_t RollbackIndexLocation, uint64_t RollbackIndex)
424{
425 EFI_STATUS Status = EFI_SUCCESS;
Monika Singh2c9d2b82018-05-01 12:24:59 +0530426 BOOLEAN UpdateRollbackIndex = FALSE;
427 AvbOpsUserData *UserData = NULL;
Monika Singh5e170362018-03-14 00:48:36 +0530428
429 dprintf(DEBUG,
430 "WriteRollbackIndex Location %zu, RollbackIndex %llu\n",
431 RollbackIndexLocation, RollbackIndex);
Monika Singh2c9d2b82018-05-01 12:24:59 +0530432
433 UserData = (AvbOpsUserData *)Ops->user_data;
434 if(UserData->IsMultiSlot) {
435 /* Update rollback if the current slot is successful */
436 if (IsCurrentSlotSuccessful()) {
437 UpdateRollbackIndex = TRUE;
438 } else {
439 UpdateRollbackIndex = FALSE;
440 dprintf(DEBUG, "Not updating rollback index as current "
441 "slot is unbootable\n");
442 }
443 } else {
444 /* When Multislot is disabled, always update*/
445 UpdateRollbackIndex = TRUE;
446 }
447
448 if(UpdateRollbackIndex == TRUE) {
Monika Singh5e170362018-03-14 00:48:36 +0530449 dprintf(INFO,
450 "Updating rollback index %llu, for location %zu\n",
451 RollbackIndex, RollbackIndexLocation);
452 Status = write_rollback_index(RollbackIndexLocation, RollbackIndex);
453 if (Status != EFI_SUCCESS) {
454 dprintf(CRITICAL, "ReadRollbackIndex failed! %d\n", Status);
455 return AVB_IO_RESULT_ERROR_IO;
456 }
Monika Singh5e170362018-03-14 00:48:36 +0530457 }
458 return AVB_IO_RESULT_OK;
459}
460
461AvbIOResult AvbReadIsDeviceUnlocked(AvbOps *Ops, bool *OutIsUnlocked)
462{
463 if (OutIsUnlocked == NULL) {
464 dprintf(CRITICAL, "bad input paramaters\n");
465 return AVB_IO_RESULT_ERROR_IO;
466 }
467 *OutIsUnlocked = !is_device_locked();
468 return AVB_IO_RESULT_OK;
469}
470
471static VOID GuidToHex(CHAR8 *Buf, EFI_GUID *Guid)
472{
473 CHAR8 HexDigits[17] = "0123456789abcdef";
474
475 Buf[0] = HexDigits[(Guid->Data1 >> 28) & 0x0f];
476 Buf[1] = HexDigits[(Guid->Data1 >> 24) & 0x0f];
477 Buf[2] = HexDigits[(Guid->Data1 >> 20) & 0x0f];
478 Buf[3] = HexDigits[(Guid->Data1 >> 16) & 0x0f];
479 Buf[4] = HexDigits[(Guid->Data1 >> 12) & 0x0f];
480 Buf[5] = HexDigits[(Guid->Data1 >> 8) & 0x0f];
481 Buf[6] = HexDigits[(Guid->Data1 >> 4) & 0x0f];
482 Buf[7] = HexDigits[(Guid->Data1 >> 0) & 0x0f];
483 Buf[8] = '-';
484 Buf[9] = HexDigits[(Guid->Data2 >> 12) & 0x0f];
485 Buf[10] = HexDigits[(Guid->Data2 >> 8) & 0x0f];
486 Buf[11] = HexDigits[(Guid->Data2 >> 4) & 0x0f];
487 Buf[12] = HexDigits[(Guid->Data2 >> 0) & 0x0f];
488 Buf[13] = '-';
489 Buf[14] = HexDigits[(Guid->Data3 >> 12) & 0x0f];
490 Buf[15] = HexDigits[(Guid->Data3 >> 8) & 0x0f];
491 Buf[16] = HexDigits[(Guid->Data3 >> 4) & 0x0f];
492 Buf[17] = HexDigits[(Guid->Data3 >> 0) & 0x0f];
493 Buf[18] = '-';
494 Buf[19] = HexDigits[(Guid->Data4[0] >> 4) & 0x0f];
495 Buf[20] = HexDigits[(Guid->Data4[0] >> 0) & 0x0f];
496 Buf[21] = HexDigits[(Guid->Data4[1] >> 4) & 0x0f];
497 Buf[22] = HexDigits[(Guid->Data4[1] >> 0) & 0x0f];
498 Buf[23] = '-';
499 Buf[24] = HexDigits[(Guid->Data4[2] >> 4) & 0x0f];
500 Buf[25] = HexDigits[(Guid->Data4[2] >> 0) & 0x0f];
501 Buf[26] = HexDigits[(Guid->Data4[3] >> 4) & 0x0f];
502 Buf[27] = HexDigits[(Guid->Data4[3] >> 0) & 0x0f];
503 Buf[28] = HexDigits[(Guid->Data4[4] >> 4) & 0x0f];
504 Buf[29] = HexDigits[(Guid->Data4[4] >> 0) & 0x0f];
505 Buf[30] = HexDigits[(Guid->Data4[5] >> 4) & 0x0f];
506 Buf[31] = HexDigits[(Guid->Data4[5] >> 0) & 0x0f];
507 Buf[32] = HexDigits[(Guid->Data4[6] >> 4) & 0x0f];
508 Buf[33] = HexDigits[(Guid->Data4[6] >> 0) & 0x0f];
509 Buf[34] = HexDigits[(Guid->Data4[7] >> 4) & 0x0f];
510 Buf[35] = HexDigits[(Guid->Data4[7] >> 0) & 0x0f];
511 Buf[36] = '\0';
512}
513
514AvbIOResult AvbGetUniqueGuidForPartition(AvbOps *Ops, const char *PartitionName,
515 char *GuidBuf, size_t GuidBufSize)
516{
517 EFI_STATUS Status = EFI_SUCCESS;
518 char unique_partition_guid[UNIQUE_PARTITION_GUID_SIZE];
519 CHAR16 UnicodePartition[MAX_GPT_NAME_SIZE] = {0};
520
521 Status = get_unique_guid(PartitionName, unique_partition_guid);
522 if (Status) {
523 dprintf(CRITICAL,
524 "get_unique_guid: No partition entry for %s\n",
525 PartitionName);
526 return AVB_IO_RESULT_ERROR_IO;
527 }
528
529 if ((strlen(PartitionName) + 1) > ARRAY_SIZE(UnicodePartition)) {
530 dprintf(CRITICAL, "AvbGetUniqueGuidForPartition: Partition "
531 "%s, name too large\n",
532 PartitionName);
533 return AVB_IO_RESULT_ERROR_IO;
534 }
535
536 GuidToHex(GuidBuf, (EFI_GUID *)unique_partition_guid);
537 dprintf(DEBUG, "%s uuid: %s\n", PartitionName, GuidBuf);
538
539 return AVB_IO_RESULT_OK;
540}
541
542AvbIOResult AvbGetSizeOfPartition(AvbOps *Ops, const char *Partition, uint64_t *OutSizeNumBytes)
543{
544 AvbIOResult Result = AVB_IO_RESULT_OK;
545 int index;
546
547 if (Ops == NULL || Partition == NULL || OutSizeNumBytes == NULL) {
548 dprintf(CRITICAL,
549 "AvbGetSizeOfPartition invalid parameter pointers\n");
550 return AVB_IO_RESULT_ERROR_IO;
551 }
552
553 index = partition_get_index(Partition);
554 *OutSizeNumBytes = (uint64_t)partition_get_size(index);
555 if (*OutSizeNumBytes == 0)
556 return AVB_IO_RESULT_ERROR_IO;
557
558 return Result;
559}
560
561AvbOps *AvbOpsNew(VOID *UserData)
562{
563 AvbOps *Ops = avb_calloc(sizeof(AvbOps));
564 if (Ops == NULL) {
565 dprintf(CRITICAL, "Error allocating memory for AvbOps.\n");
566 goto out;
567 }
568
569 Ops->user_data = UserData;
570 Ops->read_from_partition = AvbReadFromPartition;
571 Ops->write_to_partition = AvbWriteToPartition;
572 Ops->validate_vbmeta_public_key = AvbValidateVbmetaPublicKey;
573 Ops->read_rollback_index = AvbReadRollbackIndex;
574 Ops->write_rollback_index = AvbWriteRollbackIndex;
575 Ops->read_is_device_unlocked = AvbReadIsDeviceUnlocked;
576 Ops->get_unique_guid_for_partition = AvbGetUniqueGuidForPartition;
577 Ops->get_size_of_partition = AvbGetSizeOfPartition;
578
579out:
580 return Ops;
581}
582
583VOID AvbOpsFree(AvbOps *Ops)
584{
585 if (Ops != NULL) {
586 avb_free(Ops);
587 }
588}