blob: 18fe3fd468eaf348efd606be7ee769f7be56efc9 [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 }
Jason Tong6a3cca92023-08-24 18:08:17 +0800342 if (is_device_unlocked())
343 ret = AVB_IO_RESULT_OK;
Bo Lv72d0e902023-01-02 14:27:34 +0000344 } else {
345 /**
346 * When the custom key is set
347 * and the device is in the LOCKED state
348 * it will boot images signed with both the built-in key
349 * as well as the custom key
350 */
351 printf("AVB2 verify with default kpub:%d, vbmeta kpub:%ld\n",
352 avb2_kpub_default_len, public_key_length);
353 if (avb2_kpub_default_len == public_key_length &&
354 !avb_safe_memcmp(public_key_data,
355 avb2_kpub_default, public_key_length)) {
356 *out_is_trusted = true;
357 ret = AVB_IO_RESULT_OK;
358 }
359 }
360 } else {
361 printf("AVB2 verify with production kpub:%d, vbmeta kpub:%ld\n",
362 avb2_kpub_production_len, public_key_length);
363 if (avb2_kpub_production_len == public_key_length &&
364 !avb_safe_memcmp(public_key_data,
365 avb2_kpub_production, public_key_length)) {
366 *out_is_trusted = true;
367 ret = AVB_IO_RESULT_OK;
368 }
369 for (i = 0; i < avb2_kpub_production_len; i++) {
370 if (avb2_kpub_production[i] != 0)
371 break;
372 }
373 if (i == avb2_kpub_production_len)
374 printf("ERROR: DID YOU FORGET TO CHANGE AVB2 KEY FOR SECURE BOOT?");
375 }
376
377 if (keybuf)
378 free(keybuf);
379 if (ret != AVB_IO_RESULT_OK)
380 printf("AVB2 key in bootloader does not match with the key in vbmeta\n");
381 return ret;
382}
383
384static AvbIOResult read_rollback_index(AvbOps *ops, size_t rollback_index_location,
385 uint64_t *out_rollback_index)
386{
387#if defined(CONFIG_AML_ANTIROLLBACK) || defined(CONFIG_AML_AVB2_ANTIROLLBACK)
388 uint32_t version;
389
390 if (get_avb_antirollback(rollback_index_location, &version)) {
391 *out_rollback_index = version;
392 } else {
393 printf("failed to read rollback index: %zd\n", rollback_index_location);
394 return AVB_IO_RESULT_ERROR_NO_SUCH_VALUE;
395 }
396#else
397 *out_rollback_index = 0;
398#endif
399 return AVB_IO_RESULT_OK;
400}
401
402static AvbIOResult write_rollback_index(AvbOps* ops, size_t rollback_index_location,
403 uint64_t rollback_index)
404{
405 AvbIOResult result = AVB_IO_RESULT_OK;
406#if defined(CONFIG_AML_ANTIROLLBACK) || defined(CONFIG_AML_AVB2_ANTIROLLBACK)
407 uint32_t version = rollback_index;
408
409 if (set_avb_antirollback(rollback_index_location, version)) {
410 result = AVB_IO_RESULT_OK;
411 goto out;
412 } else {
413 printf("failed to set rollback index: %zd, version: %u\n",
414 rollback_index_location, version);
415 result = AVB_IO_RESULT_ERROR_NO_SUCH_VALUE;
416 goto out;
417 }
418out:
419#endif
420 return result;
421}
422
423static AvbIOResult read_is_device_unlocked(AvbOps* ops, bool* out_is_unlocked)
424{
425 AvbIOResult result = AVB_IO_RESULT_OK;
426#if defined(CONFIG_AML_ANTIROLLBACK) || defined(CONFIG_AML_AVB2_ANTIROLLBACK)
427 uint32_t lock_state;
428 char *lock_s;
429
430 if (get_avb_lock_state(&lock_state)) {
431 *out_is_unlocked = !lock_state;
432 lock_s = env_get("lock");
433 if (*out_is_unlocked)
434 lock_s[4] = '0';
435 else
436 lock_s[4] = '1';
437 lock_s = env_get("lock");
438 result = AVB_IO_RESULT_OK;
439 goto out;
440 } else {
441 printf("failed to read device lock status from rpmb\n");
442 result = AVB_IO_RESULT_ERROR_IO;
443 goto out;
444 }
445#else
446 char *lock_s;
447 LockData_t info;
448
449 lock_s = env_get("lock");
450 if (!lock_s) {
451 result = AVB_IO_RESULT_ERROR_IO;
452 goto out;
453 }
454
455 memset(&info, 0, sizeof(struct LockData));
456
457 info.version_major = (int)(lock_s[0] - '0');
458 info.version_minor = (int)(lock_s[1] - '0');
459 info.lock_state = (int)(lock_s[4] - '0');
460 info.lock_critical_state = (int)(lock_s[5] - '0');
461 info.lock_bootloader = (int)(lock_s[6] - '0');
462
463 if (info.lock_state == 1)
464 *out_is_unlocked = false;
465 else
466 *out_is_unlocked = true;
467 result = AVB_IO_RESULT_OK;
468#endif
469out:
470 return result;
471}
472
473static int avb_init(void)
474{
475
476 memset(&avb_ops_, 0, sizeof(AvbOps));
477 avb_ops_.read_from_partition = read_from_partition;
478 avb_ops_.get_preloaded_partition = NULL;
479 avb_ops_.write_to_partition = write_to_partition;
480 avb_ops_.validate_vbmeta_public_key = validate_vbmeta_public_key;
481 avb_ops_.read_rollback_index = read_rollback_index;
482 avb_ops_.write_rollback_index = write_rollback_index;
483 avb_ops_.read_is_device_unlocked = read_is_device_unlocked;
484 avb_ops_.get_unique_guid_for_partition = get_unique_guid_for_partition;
485 avb_ops_.get_size_of_partition = get_size_of_partition;
486 avb_ops_.read_persistent_value = NULL;
487 avb_ops_.write_persistent_value = NULL;
488
489 //avb_ops_.user_data = NULL;
490
491 return 0;
492}
493
494int is_device_unlocked(void)
495{
496 AvbIOResult ret;
497 bool out_is_unlocked;
498
499 ret = read_is_device_unlocked(&avb_ops_, &out_is_unlocked);
500 if (ret == AVB_IO_RESULT_OK)
501 return out_is_unlocked;
502 else
503 return 0;
504}
505
506int avb_verify(AvbSlotVerifyData** out_data)
507{
508#ifdef CONFIG_AVB2_RECOVERY
509#define RECOVERY "recovery"
510#else
511#define RECOVERY NULL
512#endif
513#ifdef CONFIG_OF_LIBFDT_OVERLAY
514 const char *requested_partitions_ab[AVB_NUM_SLOT + 1] = {"boot", "dtbo",
515 RECOVERY, NULL, NULL};
516#else
517 const char *requested_partitions_ab[AVB_NUM_SLOT + 1] = {"boot", RECOVERY,
518 NULL, NULL, NULL};
519#endif
520 const char *requested_partitions[AVB_NUM_SLOT + 1] = {"boot", "dt",
521 RECOVERY, NULL, NULL};
522 AvbSlotVerifyResult result = AVB_SLOT_VERIFY_RESULT_OK;
523 char *s1 = NULL;
524 char *ab_suffix = NULL;
525 const char *vendor_boot = "vendor_boot";
526 char *vendor_boot_status = NULL;
527 const char **partition_select = requested_partitions;
528 int i = 0;
529
530 s1 = env_get("active_slot");
531 if (!s1) {
532 run_command("get_valid_slot;", 0);
533 s1 = env_get("active_slot");
534 }
535 if (s1) {
536 printf("active_slot is %s\n", s1);
537 if (!strcmp(s1, "normal"))
538 ab_suffix = "";
539 else
540 ab_suffix = env_get("active_slot");
541 }
542
543 if (!ab_suffix)
544 ab_suffix = "";
545 printf("ab_suffix is %s\n", ab_suffix);
546
547 if (strcmp(ab_suffix, ""))
548 partition_select = requested_partitions_ab;
549
550 AvbSlotVerifyFlags flags = AVB_SLOT_VERIFY_FLAGS_NONE;
551 char *upgradestep = NULL;
552
553 avb_init();
554
555 upgradestep = env_get("upgrade_step");
556 vendor_boot_status = env_get("vendor_boot_mode");
557 if (!strcmp(vendor_boot_status, "true")) {
558 for (i = 0; i < AVB_NUM_SLOT; i++) {
559 if (!partition_select[i]) {
560 partition_select[i] = vendor_boot;
561 break;
562 }
563 }
564 }
565
566 if (is_device_unlocked() || (upgradestep && (!strcmp(upgradestep, "3"))))
567 flags |= AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR;
568
569 result = avb_slot_verify(&avb_ops_, partition_select, ab_suffix,
570 flags,
571 AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE, out_data);
572
573 if (upgradestep && (!strcmp(upgradestep, "3"))) {
574 run_command("setenv bootconfig ${bootconfig} androidboot.vbmeta.avb_version=1.1;",
575 0);
576 result = AVB_SLOT_VERIFY_RESULT_OK;
577 }
578
579 return result;
580#undef RECOVERY
581}
582
583static int do_avb_verify(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
584{
585 AvbSlotVerifyResult result = AVB_SLOT_VERIFY_RESULT_OK;
586 AvbSlotVerifyData *out_data = NULL;
587 uint32_t i = 0;
588
589 result = (AvbSlotVerifyResult)avb_verify(&out_data);
590
591 printf("result: %d\n", result);
592 if (result == AVB_SLOT_VERIFY_RESULT_OK && out_data) {
593#if defined(CONFIG_AML_ANTIROLLBACK) || defined(CONFIG_AML_AVB2_ANTIROLLBACK)
594 uint32_t version;
595 uint32_t lock_state;
596#endif
597
598 printf("ab_suffix: %s\n", out_data->ab_suffix);
599 printf("vbmeta: name: %s, size: %zd, result: %d\n",
600 out_data->vbmeta_images->partition_name,
601 out_data->vbmeta_images->vbmeta_size,
602 out_data->vbmeta_images->verify_result);
603 printf("num of vbmeta: %zd\n", out_data->num_vbmeta_images);
604 printf("loaded name: %s, size: %zd, preload: %d\n",
605 out_data->loaded_partitions->partition_name,
606 out_data->loaded_partitions->data_size,
607 out_data->loaded_partitions->preloaded);
608 printf("num of loaded: %zd\n", out_data->num_loaded_partitions);
609 printf("cmdline: %s\n", out_data->cmdline);
610 for (i = 0; i < AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS; i++)
611 printf("rollback(%d) = %llu\n", i, out_data->rollback_indexes[i]);
612
613#if defined(CONFIG_AML_ANTIROLLBACK) || defined(CONFIG_AML_AVB2_ANTIROLLBACK)
614 for (i = 0; i < AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS; i++)
615 if (get_avb_antirollback(i, &version))
616 printf("rpmb rollback(%d) = %u\n", i, version);
617 if (get_avb_lock_state(&lock_state))
618 printf("rpmb lock state: %u\n", lock_state);
619#endif
620
621 avb_slot_verify_data_free(out_data);
622 }
623
624 return result;
625}
626
627uint32_t avb_get_boot_patchlevel_from_vbmeta(AvbSlotVerifyData *data)
628{
629 int i, j;
630 AvbVBMetaData *p;
631 const char *ret = NULL;
632 size_t len = 0;
633 char buff[9];
634 unsigned long boot_patchlevel;
635
636 if (!data)
637 return 0;
638
639 for (i = 0; i < data->num_vbmeta_images; i++) {
640 p = &data->vbmeta_images[i];
641 if (strcmp(p->partition_name, "vbmeta") == 0) { /* match */
642 if (p->verify_result != AVB_VBMETA_VERIFY_RESULT_OK) {
643 // not verified
644 printf("vbmeta verify_result %d\n", p->verify_result);
645
646 /*device lock, treat as error*/
647 if (!is_device_unlocked()) {
648 printf("device lock, but vbmeta verify fail\n");
649 return 0;
650 }
651 }
652
653 ret = avb_property_lookup(p->vbmeta_data,
654 p->vbmeta_size,
655 "com.android.build.boot.security_patch",
656 0,
657 &len);
658
659 if (ret)
660 break;
661// else
662// printf("not found com.android.build.boot.
663// security_patch,len = %d\n", (int)len);
664 }
665 }
666
667 if (ret) {
668 for (i = 0, j = 0; i < len; i++) {
669 if (ret[i] != '-' && j < 8)
670 buff[j++] = ret[i];
671 }
672 buff[8] = '\0';
673 if (!strict_strtoul(buff, 10, &boot_patchlevel))
674 return (uint32_t)boot_patchlevel;
675 }
676
677 return 0;
678}
679
680static cmd_tbl_t cmd_avb_sub[] = {
681 U_BOOT_CMD_MKENT(verify, 4, 0, do_avb_verify, "", ""),
682};
683
684static int do_avb_ops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
685{
686 cmd_tbl_t *c;
687 int ret = 0;
688
689 /* Strip off leading 'bmp' command argument */
690 argc--;
691 argv++;
692
693 c = find_cmd_tbl(argv[0], &cmd_avb_sub[0], ARRAY_SIZE(cmd_avb_sub));
694
695 if (c) {
696 ret = c->cmd(cmdtp, flag, argc, argv);
697 } else {
698 cmd_usage(cmdtp);
699 ret = 1;
700 }
701
702 return ret;
703}
704
705
706U_BOOT_CMD(
707 avb, 2, 0, do_avb_ops,
708 "avb",
709 "\nThis command will trigger related avb operations\n"
710 );