blob: 08dff1b85951f29810c3f04fdf4b17fda21e4260 [file] [log] [blame]
Bo Lv72d0e902023-01-02 14:27:34 +00001// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
2/*
3 * Copyright (c) 2019 Amlogic, Inc. All rights reserved.
4 */
5
6#include <common.h>
7#include <command.h>
8#include <env.h>
9#include <malloc.h>
10#include <asm/byteorder.h>
11#include <config.h>
12#include <asm/amlogic/arch/io.h>
13#include <amlogic/partition_table.h>
14#include <amlogic/libavb/libavb.h>
15#include <amlogic/emmc_partitions.h>
16#include <amlogic/storage.h>
17#include <asm/amlogic/arch/bl31_apis.h>
18#if defined(CONFIG_AML_ANTIROLLBACK) || defined(CONFIG_AML_AVB2_ANTIROLLBACK)
19#include <amlogic/anti-rollback.h>
20#endif
21#include <version.h>
22#include <amlogic/aml_efuse.h>
23#include <amlogic/store_wrapper.h>
24
25#define AVB_USE_TESTKEY
26#define MAX_DTB_SIZE (AML_DTB_IMG_MAX_SZ + 512)
27#define DTB_PARTITION_SIZE 258048
28#define AVB_NUM_SLOT (4)
29#define MAX_AVBKEY_LEN (8 + 1024)
30
31/* use max nand page size, 4K */
32#define NAND_PAGE_SIZE (0x1000)
33
34#define CONFIG_AVB2_KPUB_EMBEDDED
35
36#ifdef CONFIG_AVB2_KPUB_VENDOR
37extern const char avb2_kpub_vendor[];
38extern const int avb2_kpub_vendor_len;
39#endif /* CONFIG_AVB_KPUB_VENDOR */
40
41extern const char avb2_kpub_default[];
42extern const int avb2_kpub_default_len;
43extern const char avb2_kpub_production[];
44extern const int avb2_kpub_production_len;
45
46#ifndef CONFIG_AVB2_KPUB_FROM_FIP
47#define CONFIG_AVB2_KPUB_FROM_FIP (0)
48#endif
49
50#if CONFIG_AVB2_KPUB_FROM_FIP
51int compare_avbkey_with_fipkey(const uint8_t* public_key_data, size_t public_key_length);
52#endif
53
54AvbOps avb_ops_;
55
56static AvbIOResult read_from_partition(AvbOps *ops, const char *partition, int64_t offset,
57 size_t num_bytes, void *buffer, size_t *out_num_read)
58{
59 int rc = 0;
60 uint64_t part_bytes = 0;
61 AvbIOResult result = AVB_IO_RESULT_OK;
62 size_t total_bytes = num_bytes;
63
64 if (ops->get_size_of_partition(ops, partition, &part_bytes) != AVB_IO_RESULT_OK) {
65 result = AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
66 goto out;
67 }
68
69 if (part_bytes < offset) {
70 result = AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION;
71 goto out;
72 }
73
74 *out_num_read = 0;
75 if (!strcmp(partition, "dt_a") || !strcmp(partition, "dt_b") ||
76 !strcmp(partition, "dt")) {
77 char *dtb_buf = malloc(MAX_DTB_SIZE);
78
79 if (!dtb_buf) {
80 result = AVB_IO_RESULT_ERROR_OOM;
81 goto out;
82 }
83
84 /* rc = store_dtb_rw(dtb_buf, MAX_DTB_SIZE, 2); */
85 memset(dtb_buf, 0x00, MAX_DTB_SIZE);
86 rc = store_rsv_read("dtb", MAX_DTB_SIZE, (void *)dtb_buf);
87 if (rc) {
88 printf("Failed to read dtb\n");
89 free(dtb_buf);
90 result = AVB_IO_RESULT_ERROR_IO;
91 goto out;
92 } else {
93 *out_num_read = num_bytes > MAX_DTB_SIZE ? MAX_DTB_SIZE : num_bytes;
94 memcpy(buffer, dtb_buf, *out_num_read);
95 free(dtb_buf);
96 result = AVB_IO_RESULT_OK;
97 goto out;
98 }
99 } else {
100 enum boot_type_e type = store_get_type();
101
102 /* There is only 1 recovery partition even in A/B */
103 if (!strcmp(partition, "recovery_a") ||
104 !strcmp(partition, "recovery_b") ||
105 !strcmp(partition, "recovery"))
106 partition = "recovery";
107
108 if (type == BOOT_NAND_MTD || type == BOOT_SNAND) {
109 if (offset != 0) {
110 uint8_t *tmp_buf = malloc(NAND_PAGE_SIZE);
111 int64_t align = offset & ~(NAND_PAGE_SIZE - 1);
112 int64_t drop_bytes = offset - align;
113 int32_t valid_data = NAND_PAGE_SIZE - drop_bytes;
114
115 if (!tmp_buf) {
116 printf("failed to allocate tmp buf for nand\n");
117 result = AVB_IO_RESULT_ERROR_IO;
118 goto out;
119 }
120
121 rc = store_logic_read(partition, align, NAND_PAGE_SIZE, tmp_buf);
122 if (rc) {
123 free(tmp_buf);
124 printf("part 1: Failed to read %dB from part[%s] at %lld\n",
125 NAND_PAGE_SIZE, partition, align);
126 result = AVB_IO_RESULT_ERROR_IO;
127 goto out;
128 } else {
129 if (num_bytes > valid_data) {
130 memcpy(buffer, tmp_buf + drop_bytes, valid_data);
131 num_bytes -= valid_data;
132 } else {
133 memcpy(buffer, tmp_buf + drop_bytes, num_bytes);
134 num_bytes = 0;
135 }
136 offset = align + NAND_PAGE_SIZE;
137 free(tmp_buf);
138 }
139 if (num_bytes > 0)
140 rc = store_logic_read(partition, offset, num_bytes, buffer);
141 } else {
142 rc = store_logic_read(partition, 0, num_bytes, buffer);
143 }
144 } else {
145 rc = store_read(partition, offset, num_bytes, buffer);
146 }
147
148 if (rc) {
149 printf("Part 2 Failed to read %zdB from part[%s] at %lld\n",
150 num_bytes, partition, offset);
151 result = AVB_IO_RESULT_ERROR_IO;
152 goto out;
153 }
154 *out_num_read = total_bytes;
155 }
156
157out:
158 return result;
159}
160
161static AvbIOResult write_to_partition(AvbOps *ops, const char *partition,
162 int64_t offset, size_t num_bytes, const void *buffer)
163{
164 int rc = 0;
165 uint64_t part_bytes = 0;
166 AvbIOResult result = AVB_IO_RESULT_OK;
167
168 if (ops->get_size_of_partition(ops, partition, &part_bytes) != AVB_IO_RESULT_OK) {
169 result = AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
170 goto out;
171 }
172 if (part_bytes < offset) {
173 result = AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION;
174 goto out;
175 }
176
177 if (!strcmp(partition, "dt_a") || !strcmp(partition, "dt_b") ||
178 !strcmp(partition, "dt")) {
179 if (offset)
180 return AVB_IO_RESULT_ERROR_IO;
181 /* rc = store_dtb_rw((void *)buffer, num_bytes, 1); */
182 rc = store_rsv_write("dtb", num_bytes, (void *)buffer);
183 if (rc) {
184 printf("Failed to write dtb\n");
185 result = AVB_IO_RESULT_ERROR_IO;
186 goto out;
187 } else {
188 result = AVB_IO_RESULT_OK;
189 goto out;
190 }
191 } else {
192 /* There is only 1 recovery partition even in A/B */
193 if (!strcmp(partition, "recovery_a") ||
194 !strcmp(partition, "recovery_b") ||
195 !strcmp(partition, "recovery"))
196 rc = store_write("recovery", offset, num_bytes, (unsigned char *)buffer);
197 else
198 rc = store_write(partition, offset, num_bytes, (unsigned char *)buffer);
199 if (rc) {
200 printf("Failed to write %zdB from part[%s] at %lld\n",
201 num_bytes, partition, offset);
202 result = AVB_IO_RESULT_ERROR_IO;
203 goto out;
204 }
205 }
206
207out:
208 return result;
209}
210
211static AvbIOResult get_unique_guid_for_partition(AvbOps *ops, const char *partition,
212 char *guid_buf, size_t guid_buf_size)
213{
214 char *s1;
215 int ret;
216 char part_name[128];
217
218 memset(guid_buf, 0, guid_buf_size);
219 s1 = env_get("active_slot");
220 if (!s1) {
221 run_command("get_valid_slot;", 0);
222 s1 = env_get("active_slot");
223 }
224 //printf("active_slot is %s\n", s1);
225 if (!memcmp(partition, "system", strlen("system"))) {
226 if (s1 && (strcmp(s1, "_a") == 0))
227 ret = get_partition_num_by_name("system_a");
228 else if (s1 && (strcmp(s1, "_b") == 0))
229 ret = get_partition_num_by_name("system_b");
230 else
231 ret = get_partition_num_by_name("system");
232
233 if (ret >= 0) {
234 sprintf(part_name, "/dev/mmcblk0p%d", ret + 1);
235 strncpy(guid_buf, part_name, guid_buf_size);
236 } else {
237 printf("system part isn't exist\n");
238 return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
239 }
240 } else if (!memcmp(partition, "vbmeta", strlen("vbmeta"))) {
241 strncpy(guid_buf, "/dev/block/vbmeta", guid_buf_size);
242 }
243 return AVB_IO_RESULT_OK;
244}
245
246static AvbIOResult get_size_of_partition(AvbOps *ops, const char *partition,
247 uint64_t *out_size_num_bytes)
248{
249 uint64_t rc = 0;
250
251 if (!strcmp(partition, "dt_a") || !strcmp(partition, "dt_b") ||
252 !strcmp(partition, "dt")) {
253 *out_size_num_bytes = DTB_PARTITION_SIZE;
254 } else {
255 /* There is only 1 recovery partition even in A/B */
256 if (!strcmp(partition, "recovery_a") ||
257 !strcmp(partition, "recovery_b") ||
258 !strcmp(partition, "recovery"))
259 rc = store_logic_cap("recovery");
260 else
261 rc = store_logic_cap(partition);
262 if (rc == 1) {
263 printf("Failed to get partition[%s] size\n", partition);
264 return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
265 }
266 *out_size_num_bytes = rc;
267 }
268
269 return AVB_IO_RESULT_OK;
270}
271
272/**
273 * normally, we should read vendor avb public key from a virtual partition with the name avb_custom_key.
274 * Flashing and erasing this partition only works in the UNLOCKED state. Setting the custom key is done like this:
275 * $ avbtool extract_public_key --key key.pem --output pkmd.bin
276 * $ fastboot flash avb_custom_key pkmd.bin
277 *
278 * Erasing the key is done by erasing the virtual partition:
279 * $ fastboot erase avb_custom_key
280 */
281static AvbIOResult validate_vbmeta_public_key(AvbOps *ops, const uint8_t *public_key_data,
282 size_t public_key_length, const uint8_t *public_key_metadata,
283 size_t public_key_metadata_length, bool *out_is_trusted)
284{
285 *out_is_trusted = false;
286 AvbIOResult ret = AVB_IO_RESULT_ERROR_IO;
287 char *keybuf = NULL;
288 char *partition = "misc";
289 AvbKey_t key;
290 int size = 0;
291#if CONFIG_AVB2_KPUB_FROM_FIP
292 int result = 0;
293#endif
294 int i = 0;
295
296#if CONFIG_AVB2_KPUB_FROM_FIP
297 printf("AVB2 verifying with fip key\n");
298 result = compare_avbkey_with_fipkey(public_key_data, public_key_length);
299 if (result == -2) {
300 printf("AVB2 verified with fip key failed\n");
301 *out_is_trusted = false;
302 ret = AVB_IO_RESULT_OK;
303 return ret;
304 } else if (result == -1) {
305 printf("AVB2 cannot find fip key\n");
306 } else if (result == 0) {
307 printf("AVB2 verified with fip key success\n");
308 *out_is_trusted = true;
309 ret = AVB_IO_RESULT_OK;
310 return ret;
311 }
312#endif
313
314 /*
315 * disable AVB custom key and test key
316 * if device secure boot enabled
317 */
318 if (!IS_FEAT_BOOT_VERIFY()) {
319 key.size = 0;
320 keybuf = (char *)malloc(AVB_CUSTOM_KEY_LEN_MAX);
321 if (keybuf) {
322 memset(keybuf, 0, AVB_CUSTOM_KEY_LEN_MAX);
323 size = store_part_size(partition);
324 if (size != 1) {
325 if (store_read((const char *)partition,
326 size - AVB_CUSTOM_KEY_LEN_MAX,
327 AVB_CUSTOM_KEY_LEN_MAX,
328 (unsigned char *)keybuf) >= 0) {
329 memcpy(&key, keybuf, sizeof(AvbKey_t));
330 }
331 }
332 }
333
334 if (keybuf && (strncmp(keybuf, "AVBK", 4) == 0)) {
335 printf("AVB2 verify with avb_custom_key\n");
336 if (key.size == public_key_length &&
337 !avb_safe_memcmp(public_key_data,
338 keybuf + sizeof(AvbKey_t), public_key_length)) {
339 *out_is_trusted = true;
340 ret = AVB_IO_RESULT_OK;
341 }
342 } else {
343 /**
344 * When the custom key is set
345 * and the device is in the LOCKED state
346 * it will boot images signed with both the built-in key
347 * as well as the custom key
348 */
349 printf("AVB2 verify with default kpub:%d, vbmeta kpub:%ld\n",
350 avb2_kpub_default_len, public_key_length);
351 if (avb2_kpub_default_len == public_key_length &&
352 !avb_safe_memcmp(public_key_data,
353 avb2_kpub_default, public_key_length)) {
354 *out_is_trusted = true;
355 ret = AVB_IO_RESULT_OK;
356 }
357 }
358 } else {
359 printf("AVB2 verify with production kpub:%d, vbmeta kpub:%ld\n",
360 avb2_kpub_production_len, public_key_length);
361 if (avb2_kpub_production_len == public_key_length &&
362 !avb_safe_memcmp(public_key_data,
363 avb2_kpub_production, public_key_length)) {
364 *out_is_trusted = true;
365 ret = AVB_IO_RESULT_OK;
366 }
367 for (i = 0; i < avb2_kpub_production_len; i++) {
368 if (avb2_kpub_production[i] != 0)
369 break;
370 }
371 if (i == avb2_kpub_production_len)
372 printf("ERROR: DID YOU FORGET TO CHANGE AVB2 KEY FOR SECURE BOOT?");
373 }
374
375 if (keybuf)
376 free(keybuf);
377 if (ret != AVB_IO_RESULT_OK)
378 printf("AVB2 key in bootloader does not match with the key in vbmeta\n");
379 return ret;
380}
381
382static AvbIOResult read_rollback_index(AvbOps *ops, size_t rollback_index_location,
383 uint64_t *out_rollback_index)
384{
385#if defined(CONFIG_AML_ANTIROLLBACK) || defined(CONFIG_AML_AVB2_ANTIROLLBACK)
386 uint32_t version;
387
388 if (get_avb_antirollback(rollback_index_location, &version)) {
389 *out_rollback_index = version;
390 } else {
391 printf("failed to read rollback index: %zd\n", rollback_index_location);
392 return AVB_IO_RESULT_ERROR_NO_SUCH_VALUE;
393 }
394#else
395 *out_rollback_index = 0;
396#endif
397 return AVB_IO_RESULT_OK;
398}
399
400static AvbIOResult write_rollback_index(AvbOps* ops, size_t rollback_index_location,
401 uint64_t rollback_index)
402{
403 AvbIOResult result = AVB_IO_RESULT_OK;
404#if defined(CONFIG_AML_ANTIROLLBACK) || defined(CONFIG_AML_AVB2_ANTIROLLBACK)
405 uint32_t version = rollback_index;
406
407 if (set_avb_antirollback(rollback_index_location, version)) {
408 result = AVB_IO_RESULT_OK;
409 goto out;
410 } else {
411 printf("failed to set rollback index: %zd, version: %u\n",
412 rollback_index_location, version);
413 result = AVB_IO_RESULT_ERROR_NO_SUCH_VALUE;
414 goto out;
415 }
416out:
417#endif
418 return result;
419}
420
421static AvbIOResult read_is_device_unlocked(AvbOps* ops, bool* out_is_unlocked)
422{
423 AvbIOResult result = AVB_IO_RESULT_OK;
424#if defined(CONFIG_AML_ANTIROLLBACK) || defined(CONFIG_AML_AVB2_ANTIROLLBACK)
425 uint32_t lock_state;
426 char *lock_s;
427
428 if (get_avb_lock_state(&lock_state)) {
429 *out_is_unlocked = !lock_state;
430 lock_s = env_get("lock");
431 if (*out_is_unlocked)
432 lock_s[4] = '0';
433 else
434 lock_s[4] = '1';
435 lock_s = env_get("lock");
436 result = AVB_IO_RESULT_OK;
437 goto out;
438 } else {
439 printf("failed to read device lock status from rpmb\n");
440 result = AVB_IO_RESULT_ERROR_IO;
441 goto out;
442 }
443#else
444 char *lock_s;
445 LockData_t info;
446
447 lock_s = env_get("lock");
448 if (!lock_s) {
449 result = AVB_IO_RESULT_ERROR_IO;
450 goto out;
451 }
452
453 memset(&info, 0, sizeof(struct LockData));
454
455 info.version_major = (int)(lock_s[0] - '0');
456 info.version_minor = (int)(lock_s[1] - '0');
457 info.lock_state = (int)(lock_s[4] - '0');
458 info.lock_critical_state = (int)(lock_s[5] - '0');
459 info.lock_bootloader = (int)(lock_s[6] - '0');
460
461 if (info.lock_state == 1)
462 *out_is_unlocked = false;
463 else
464 *out_is_unlocked = true;
465 result = AVB_IO_RESULT_OK;
466#endif
467out:
468 return result;
469}
470
471static int avb_init(void)
472{
473
474 memset(&avb_ops_, 0, sizeof(AvbOps));
475 avb_ops_.read_from_partition = read_from_partition;
476 avb_ops_.get_preloaded_partition = NULL;
477 avb_ops_.write_to_partition = write_to_partition;
478 avb_ops_.validate_vbmeta_public_key = validate_vbmeta_public_key;
479 avb_ops_.read_rollback_index = read_rollback_index;
480 avb_ops_.write_rollback_index = write_rollback_index;
481 avb_ops_.read_is_device_unlocked = read_is_device_unlocked;
482 avb_ops_.get_unique_guid_for_partition = get_unique_guid_for_partition;
483 avb_ops_.get_size_of_partition = get_size_of_partition;
484 avb_ops_.read_persistent_value = NULL;
485 avb_ops_.write_persistent_value = NULL;
486
487 //avb_ops_.user_data = NULL;
488
489 return 0;
490}
491
492int is_device_unlocked(void)
493{
494 AvbIOResult ret;
495 bool out_is_unlocked;
496
497 ret = read_is_device_unlocked(&avb_ops_, &out_is_unlocked);
498 if (ret == AVB_IO_RESULT_OK)
499 return out_is_unlocked;
500 else
501 return 0;
502}
503
504int avb_verify(AvbSlotVerifyData** out_data)
505{
506#ifdef CONFIG_AVB2_RECOVERY
507#define RECOVERY "recovery"
508#else
509#define RECOVERY NULL
510#endif
511#ifdef CONFIG_OF_LIBFDT_OVERLAY
512 const char *requested_partitions_ab[AVB_NUM_SLOT + 1] = {"boot", "dtbo",
513 RECOVERY, NULL, NULL};
514#else
515 const char *requested_partitions_ab[AVB_NUM_SLOT + 1] = {"boot", RECOVERY,
516 NULL, NULL, NULL};
517#endif
518 const char *requested_partitions[AVB_NUM_SLOT + 1] = {"boot", "dt",
519 RECOVERY, NULL, NULL};
520 AvbSlotVerifyResult result = AVB_SLOT_VERIFY_RESULT_OK;
521 char *s1 = NULL;
522 char *ab_suffix = NULL;
523 const char *vendor_boot = "vendor_boot";
524 char *vendor_boot_status = NULL;
525 const char **partition_select = requested_partitions;
526 int i = 0;
527
528 s1 = env_get("active_slot");
529 if (!s1) {
530 run_command("get_valid_slot;", 0);
531 s1 = env_get("active_slot");
532 }
533 if (s1) {
534 printf("active_slot is %s\n", s1);
535 if (!strcmp(s1, "normal"))
536 ab_suffix = "";
537 else
538 ab_suffix = env_get("active_slot");
539 }
540
541 if (!ab_suffix)
542 ab_suffix = "";
543 printf("ab_suffix is %s\n", ab_suffix);
544
545 if (strcmp(ab_suffix, ""))
546 partition_select = requested_partitions_ab;
547
548 AvbSlotVerifyFlags flags = AVB_SLOT_VERIFY_FLAGS_NONE;
549 char *upgradestep = NULL;
550
551 avb_init();
552
553 upgradestep = env_get("upgrade_step");
554 vendor_boot_status = env_get("vendor_boot_mode");
555 if (!strcmp(vendor_boot_status, "true")) {
556 for (i = 0; i < AVB_NUM_SLOT; i++) {
557 if (!partition_select[i]) {
558 partition_select[i] = vendor_boot;
559 break;
560 }
561 }
562 }
563
564 if (is_device_unlocked() || (upgradestep && (!strcmp(upgradestep, "3"))))
565 flags |= AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR;
566
567 result = avb_slot_verify(&avb_ops_, partition_select, ab_suffix,
568 flags,
569 AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE, out_data);
570
571 if (upgradestep && (!strcmp(upgradestep, "3"))) {
572 run_command("setenv bootconfig ${bootconfig} androidboot.vbmeta.avb_version=1.1;",
573 0);
574 result = AVB_SLOT_VERIFY_RESULT_OK;
575 }
576
577 return result;
578#undef RECOVERY
579}
580
581static int do_avb_verify(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
582{
583 AvbSlotVerifyResult result = AVB_SLOT_VERIFY_RESULT_OK;
584 AvbSlotVerifyData *out_data = NULL;
585 uint32_t i = 0;
586
587 result = (AvbSlotVerifyResult)avb_verify(&out_data);
588
589 printf("result: %d\n", result);
590 if (result == AVB_SLOT_VERIFY_RESULT_OK && out_data) {
591#if defined(CONFIG_AML_ANTIROLLBACK) || defined(CONFIG_AML_AVB2_ANTIROLLBACK)
592 uint32_t version;
593 uint32_t lock_state;
594#endif
595
596 printf("ab_suffix: %s\n", out_data->ab_suffix);
597 printf("vbmeta: name: %s, size: %zd, result: %d\n",
598 out_data->vbmeta_images->partition_name,
599 out_data->vbmeta_images->vbmeta_size,
600 out_data->vbmeta_images->verify_result);
601 printf("num of vbmeta: %zd\n", out_data->num_vbmeta_images);
602 printf("loaded name: %s, size: %zd, preload: %d\n",
603 out_data->loaded_partitions->partition_name,
604 out_data->loaded_partitions->data_size,
605 out_data->loaded_partitions->preloaded);
606 printf("num of loaded: %zd\n", out_data->num_loaded_partitions);
607 printf("cmdline: %s\n", out_data->cmdline);
608 for (i = 0; i < AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS; i++)
609 printf("rollback(%d) = %llu\n", i, out_data->rollback_indexes[i]);
610
611#if defined(CONFIG_AML_ANTIROLLBACK) || defined(CONFIG_AML_AVB2_ANTIROLLBACK)
612 for (i = 0; i < AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS; i++)
613 if (get_avb_antirollback(i, &version))
614 printf("rpmb rollback(%d) = %u\n", i, version);
615 if (get_avb_lock_state(&lock_state))
616 printf("rpmb lock state: %u\n", lock_state);
617#endif
618
619 avb_slot_verify_data_free(out_data);
620 }
621
622 return result;
623}
624
625uint32_t avb_get_boot_patchlevel_from_vbmeta(AvbSlotVerifyData *data)
626{
627 int i, j;
628 AvbVBMetaData *p;
629 const char *ret = NULL;
630 size_t len = 0;
631 char buff[9];
632 unsigned long boot_patchlevel;
633
634 if (!data)
635 return 0;
636
637 for (i = 0; i < data->num_vbmeta_images; i++) {
638 p = &data->vbmeta_images[i];
639 if (strcmp(p->partition_name, "vbmeta") == 0) { /* match */
640 if (p->verify_result != AVB_VBMETA_VERIFY_RESULT_OK) {
641 // not verified
642 printf("vbmeta verify_result %d\n", p->verify_result);
643
644 /*device lock, treat as error*/
645 if (!is_device_unlocked()) {
646 printf("device lock, but vbmeta verify fail\n");
647 return 0;
648 }
649 }
650
651 ret = avb_property_lookup(p->vbmeta_data,
652 p->vbmeta_size,
653 "com.android.build.boot.security_patch",
654 0,
655 &len);
656
657 if (ret)
658 break;
659// else
660// printf("not found com.android.build.boot.
661// security_patch,len = %d\n", (int)len);
662 }
663 }
664
665 if (ret) {
666 for (i = 0, j = 0; i < len; i++) {
667 if (ret[i] != '-' && j < 8)
668 buff[j++] = ret[i];
669 }
670 buff[8] = '\0';
671 if (!strict_strtoul(buff, 10, &boot_patchlevel))
672 return (uint32_t)boot_patchlevel;
673 }
674
675 return 0;
676}
677
678static cmd_tbl_t cmd_avb_sub[] = {
679 U_BOOT_CMD_MKENT(verify, 4, 0, do_avb_verify, "", ""),
680};
681
682static int do_avb_ops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
683{
684 cmd_tbl_t *c;
685 int ret = 0;
686
687 /* Strip off leading 'bmp' command argument */
688 argc--;
689 argv++;
690
691 c = find_cmd_tbl(argv[0], &cmd_avb_sub[0], ARRAY_SIZE(cmd_avb_sub));
692
693 if (c) {
694 ret = c->cmd(cmdtp, flag, argc, argv);
695 } else {
696 cmd_usage(cmdtp);
697 ret = 1;
698 }
699
700 return ret;
701}
702
703
704U_BOOT_CMD(
705 avb, 2, 0, do_avb_ops,
706 "avb",
707 "\nThis command will trigger related avb operations\n"
708 );