blob: 1a9c0969b4ab3aefd014f3f55d2bc9b6bd256164 [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>
Mingyen Hung6e468002023-01-04 23:43:04 -080024#include <fs.h>
25#include <fat.h>
26#include <factory_provision/factory_provision_utils.h>
Bo Lv72d0e902023-01-02 14:27:34 +000027
28#define AVB_USE_TESTKEY
29#define MAX_DTB_SIZE (AML_DTB_IMG_MAX_SZ + 512)
30#define DTB_PARTITION_SIZE 258048
Matthew Shyu837ffa52024-05-03 01:59:44 -070031#define AVB_NUM_SLOT (6)
Bo Lv72d0e902023-01-02 14:27:34 +000032/* use max nand page size, 4K */
33#define NAND_PAGE_SIZE (0x1000)
34
Matthew Shyuc710a122023-12-14 00:08:41 -080035// The last slot is reserved for recovery partition
36#define RECOVERY_ARB_LOCATION (31)
Matthew Shyu837ffa52024-05-03 01:59:44 -070037#define CONFIG_AVB2_KPUB_EMBEDDED
38
Bo Lv72d0e902023-01-02 14:27:34 +000039#ifdef CONFIG_AVB2_KPUB_VENDOR
40extern const char avb2_kpub_vendor[];
41extern const int avb2_kpub_vendor_len;
42#endif /* CONFIG_AVB_KPUB_VENDOR */
43
44extern const char avb2_kpub_default[];
45extern const int avb2_kpub_default_len;
46extern const char avb2_kpub_production[];
47extern const int avb2_kpub_production_len;
48
49#ifndef CONFIG_AVB2_KPUB_FROM_FIP
50#define CONFIG_AVB2_KPUB_FROM_FIP (0)
51#endif
52
53#if CONFIG_AVB2_KPUB_FROM_FIP
54int compare_avbkey_with_fipkey(const uint8_t* public_key_data, size_t public_key_length);
55#endif
56
Matthew Shyuc710a122023-12-14 00:08:41 -080057void *memory_addr;
Bo Lv72d0e902023-01-02 14:27:34 +000058AvbOps avb_ops_;
Matthew Shyuc710a122023-12-14 00:08:41 -080059int run_in_recovery;
Matthew Shyuc4ba2192024-06-19 01:23:35 -070060int recovery_from_memory;
Bo Lv72d0e902023-01-02 14:27:34 +000061
Matthew Shyu837ffa52024-05-03 01:59:44 -070062struct avb_part {
63 char name[16];
64 u8 *addr;
65 size_t length;
66};
67
68struct avb_part parts[AVB_NUM_SLOT];
69u32 avb_part_num;
70bool avb_preload = true;
71
72void set_avb_parts(const char *partname, uint8_t *addr, size_t length)
73{
74 struct avb_part *part = NULL;
75
76 if (!is_device_unlocked() && avb_preload) {
77 assert(avb_part_num < AVB_NUM_SLOT);
78
79 part = &parts[avb_part_num];
80 memset(part->name, 0, sizeof(part->name));
81 strlcpy(part->name, partname, sizeof(part->name));
82 part->addr = malloc(length);
83 if (part->addr) {
84 memcpy(part->addr, addr, length);
85 part->length = length;
86 avb_part_num++;
87 }
88 }
89}
90
91void clear_avb_parts(void)
92{
93 struct avb_part *part = NULL;
94 u32 i = 0;
95
96 if (!is_device_unlocked()) {
97 for (i = 0; i < avb_part_num; i++) {
98 part = &parts[i];
99 memset(part->name, 0, sizeof(part->name));
100 if (part->addr) {
101 free(part->addr);
102 part->addr = NULL;
103 part->length = 0;
104 }
105 }
106 }
107 avb_part_num = 0;
108}
109
110u64 get_size_avb_footer(const char *partname)
111{
112 AvbFooter footer_src, footer_desc;
113 u64 rc = 0;
114 enum boot_type_e type = store_get_type();
115 u32 read_size = 512;
116 u8 read_buf[NAND_PAGE_SIZE];
117
118 if (!partname)
119 return 0;
120
121 if (type == BOOT_NAND_MTD || type == BOOT_SNAND)
122 read_size = NAND_PAGE_SIZE;
123
124 rc = store_logic_cap(partname);
125 if (rc > read_size) {
126 rc = store_logic_read(partname, rc - read_size,
127 read_size, read_buf);
128 if (rc) {
129 printf("failed to read footer from: %s\n", partname);
130 return 0;
131 }
132 memcpy(&footer_src, &read_buf[read_size - AVB_FOOTER_SIZE], AVB_FOOTER_SIZE);
133 if (avb_footer_validate_and_byteswap(&footer_src, &footer_desc))
134 return footer_desc.original_image_size;
135 else
136 return 0;
137 } else {
138 return rc;
139 }
140}
141
Bo Lv72d0e902023-01-02 14:27:34 +0000142static AvbIOResult read_from_partition(AvbOps *ops, const char *partition, int64_t offset,
143 size_t num_bytes, void *buffer, size_t *out_num_read)
144{
145 int rc = 0;
146 uint64_t part_bytes = 0;
147 AvbIOResult result = AVB_IO_RESULT_OK;
148 size_t total_bytes = num_bytes;
149
150 if (ops->get_size_of_partition(ops, partition, &part_bytes) != AVB_IO_RESULT_OK) {
151 result = AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
152 goto out;
153 }
154
155 if (part_bytes < offset) {
156 result = AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION;
157 goto out;
158 }
159
160 *out_num_read = 0;
161 if (!strcmp(partition, "dt_a") || !strcmp(partition, "dt_b") ||
162 !strcmp(partition, "dt")) {
163 char *dtb_buf = malloc(MAX_DTB_SIZE);
164
165 if (!dtb_buf) {
166 result = AVB_IO_RESULT_ERROR_OOM;
167 goto out;
168 }
169
170 /* rc = store_dtb_rw(dtb_buf, MAX_DTB_SIZE, 2); */
171 memset(dtb_buf, 0x00, MAX_DTB_SIZE);
172 rc = store_rsv_read("dtb", MAX_DTB_SIZE, (void *)dtb_buf);
173 if (rc) {
174 printf("Failed to read dtb\n");
175 free(dtb_buf);
176 result = AVB_IO_RESULT_ERROR_IO;
177 goto out;
178 } else {
179 *out_num_read = num_bytes > MAX_DTB_SIZE ? MAX_DTB_SIZE : num_bytes;
180 memcpy(buffer, dtb_buf, *out_num_read);
181 free(dtb_buf);
182 result = AVB_IO_RESULT_OK;
183 goto out;
184 }
Matthew Shyuc710a122023-12-14 00:08:41 -0800185 } else if (!strcmp(partition, "recovery-memory")) {
186 u32 filesize = simple_strtoul(env_get("filesize"), NULL, 16);
187
188 if (memory_addr) {
189 num_bytes = (filesize - offset >= num_bytes) ? num_bytes :
190 (filesize - offset);
191 memcpy(buffer, (uint8_t *)(memory_addr + offset), num_bytes);
192 *out_num_read = num_bytes;
193 return AVB_IO_RESULT_OK;
194 }
195 return AVB_IO_RESULT_ERROR_IO;
Bo Lv72d0e902023-01-02 14:27:34 +0000196 } else {
197 enum boot_type_e type = store_get_type();
198
199 /* There is only 1 recovery partition even in A/B */
200 if (!strcmp(partition, "recovery_a") ||
201 !strcmp(partition, "recovery_b") ||
202 !strcmp(partition, "recovery"))
203 partition = "recovery";
204
205 if (type == BOOT_NAND_MTD || type == BOOT_SNAND) {
206 if (offset != 0) {
207 uint8_t *tmp_buf = malloc(NAND_PAGE_SIZE);
208 int64_t align = offset & ~(NAND_PAGE_SIZE - 1);
209 int64_t drop_bytes = offset - align;
210 int32_t valid_data = NAND_PAGE_SIZE - drop_bytes;
211
212 if (!tmp_buf) {
213 printf("failed to allocate tmp buf for nand\n");
214 result = AVB_IO_RESULT_ERROR_IO;
215 goto out;
216 }
217
218 rc = store_logic_read(partition, align, NAND_PAGE_SIZE, tmp_buf);
219 if (rc) {
220 free(tmp_buf);
221 printf("part 1: Failed to read %dB from part[%s] at %lld\n",
222 NAND_PAGE_SIZE, partition, align);
223 result = AVB_IO_RESULT_ERROR_IO;
224 goto out;
225 } else {
226 if (num_bytes > valid_data) {
227 memcpy(buffer, tmp_buf + drop_bytes, valid_data);
228 num_bytes -= valid_data;
Mingyen Hung6e468002023-01-04 23:43:04 -0800229 buffer = (uint8_t *)buffer + valid_data;
Bo Lv72d0e902023-01-02 14:27:34 +0000230 } else {
231 memcpy(buffer, tmp_buf + drop_bytes, num_bytes);
232 num_bytes = 0;
233 }
234 offset = align + NAND_PAGE_SIZE;
235 free(tmp_buf);
236 }
Mingyen Hung6e468002023-01-04 23:43:04 -0800237 if (num_bytes > 0) {
238 rc = store_logic_read(partition, offset,
239 num_bytes, buffer);
240 printf("Failed to read");
241 printf("%zdB from part[%s] at %lld\n",
242 num_bytes, partition, offset);
243 }
Bo Lv72d0e902023-01-02 14:27:34 +0000244 } else {
245 rc = store_logic_read(partition, 0, num_bytes, buffer);
246 }
247 } else {
Matthew Shyu837ffa52024-05-03 01:59:44 -0700248 rc = store_logic_read(partition, offset, num_bytes, buffer);
Bo Lv72d0e902023-01-02 14:27:34 +0000249 }
250
251 if (rc) {
252 printf("Part 2 Failed to read %zdB from part[%s] at %lld\n",
253 num_bytes, partition, offset);
254 result = AVB_IO_RESULT_ERROR_IO;
255 goto out;
256 }
257 *out_num_read = total_bytes;
258 }
259
260out:
261 return result;
262}
263
Matthew Shyu837ffa52024-05-03 01:59:44 -0700264static AvbIOResult get_preloaded_partition(AvbOps *ops, const char *partition,
265 size_t num_bytes,
266 u8 **out_pointer,
267 size_t *out_num_bytes_preloaded)
268{
269 u32 i = 0;
270
271 *out_pointer = NULL;
272 *out_num_bytes_preloaded = 0;
273
274 if (avb_preload) {
275 for (i = 0; i < avb_part_num; i++) {
276 if (!strcmp(partition, parts[i].name)) {
277 if (num_bytes <= parts[i].length) {
278 *out_pointer = parts[i].addr;
279 *out_num_bytes_preloaded = num_bytes;
280 } else {
281 printf("preload: %s expected: %zd, got: %zd\n",
282 partition, num_bytes, parts[i].length);
283 if (parts[i].addr) {
284 free(parts[i].addr);
285 parts[i].addr = NULL;
286 parts[i].length = 0;
287 memset(parts[i].name, 0, sizeof(parts[i].name));
288 }
289 }
290 return AVB_IO_RESULT_OK;
291 }
292 }
293 printf("cannot find %s in preload, use storage read\n", partition);
294 }
295
296 return AVB_IO_RESULT_OK;
297}
298
Bo Lv72d0e902023-01-02 14:27:34 +0000299static AvbIOResult write_to_partition(AvbOps *ops, const char *partition,
300 int64_t offset, size_t num_bytes, const void *buffer)
301{
302 int rc = 0;
303 uint64_t part_bytes = 0;
304 AvbIOResult result = AVB_IO_RESULT_OK;
Matthew Shyu837ffa52024-05-03 01:59:44 -0700305 const char *recovery = "recovery";
306 enum boot_type_e type = store_get_type();
Bo Lv72d0e902023-01-02 14:27:34 +0000307
308 if (ops->get_size_of_partition(ops, partition, &part_bytes) != AVB_IO_RESULT_OK) {
309 result = AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
310 goto out;
311 }
312 if (part_bytes < offset) {
313 result = AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION;
314 goto out;
315 }
316
317 if (!strcmp(partition, "dt_a") || !strcmp(partition, "dt_b") ||
318 !strcmp(partition, "dt")) {
Matthew Shyu837ffa52024-05-03 01:59:44 -0700319 if (offset) {
320 result = AVB_IO_RESULT_ERROR_IO;
321 goto out;
322 }
323 if (type == BOOT_NAND_MTD || type == BOOT_SNAND) {
324 rc = store_rsv_erase("dtb");
325 if (rc) {
326 printf("Failed to write dtb\n");
327 result = AVB_IO_RESULT_ERROR_IO;
328 goto out;
329 }
330 }
Bo Lv72d0e902023-01-02 14:27:34 +0000331 rc = store_rsv_write("dtb", num_bytes, (void *)buffer);
332 if (rc) {
333 printf("Failed to write dtb\n");
334 result = AVB_IO_RESULT_ERROR_IO;
335 goto out;
336 } else {
337 result = AVB_IO_RESULT_OK;
338 goto out;
339 }
340 } else {
341 /* There is only 1 recovery partition even in A/B */
342 if (!strcmp(partition, "recovery_a") ||
343 !strcmp(partition, "recovery_b") ||
344 !strcmp(partition, "recovery"))
Matthew Shyu837ffa52024-05-03 01:59:44 -0700345 partition = recovery;
346
347 if (type == BOOT_NAND_MTD || type == BOOT_SNAND) {
348 u8 *local_buf = NULL;
349 u32 local_size = 0;
350
351 local_size = (offset + num_bytes + NAND_PAGE_SIZE - 1);
352 local_size = local_size / NAND_PAGE_SIZE *
353 NAND_PAGE_SIZE;
354 local_buf = malloc(local_size);
355 if (!local_buf) {
356 printf("Failed local buf: %u\n", local_size);
357 result = AVB_IO_RESULT_ERROR_OOM;
358 goto out;
359 }
360 rc = store_logic_read(partition, 0, local_size,
361 local_buf);
362 if (rc) {
363 printf("Failed to read to local buf\n");
364 result = AVB_IO_RESULT_ERROR_IO;
365 free(local_buf);
366 goto out;
367 }
368 memcpy(local_buf + offset, buffer, num_bytes);
369 rc = store_erase(partition, 0, local_size, 0);
370 if (rc) {
371 printf("Failed to erase: %s %u\n",
372 partition, local_size);
373 result = AVB_IO_RESULT_ERROR_IO;
374 free(local_buf);
375 goto out;
376 }
377 rc = store_logic_write(partition, 0, local_size, local_buf);
378 free(local_buf);
379 } else {
380 rc = store_logic_write(partition, offset, num_bytes,
381 (unsigned char *)buffer);
382 }
Bo Lv72d0e902023-01-02 14:27:34 +0000383 if (rc) {
384 printf("Failed to write %zdB from part[%s] at %lld\n",
385 num_bytes, partition, offset);
386 result = AVB_IO_RESULT_ERROR_IO;
387 goto out;
388 }
389 }
390
391out:
392 return result;
393}
394
395static AvbIOResult get_unique_guid_for_partition(AvbOps *ops, const char *partition,
396 char *guid_buf, size_t guid_buf_size)
397{
398 char *s1;
399 int ret;
400 char part_name[128];
401
402 memset(guid_buf, 0, guid_buf_size);
403 s1 = env_get("active_slot");
404 if (!s1) {
405 run_command("get_valid_slot;", 0);
406 s1 = env_get("active_slot");
407 }
408 //printf("active_slot is %s\n", s1);
409 if (!memcmp(partition, "system", strlen("system"))) {
Matthew Shyu837ffa52024-05-03 01:59:44 -0700410#if CONFIG_IS_ENABLED(MMC_MESON_GX)
Bo Lv72d0e902023-01-02 14:27:34 +0000411 if (s1 && (strcmp(s1, "_a") == 0))
412 ret = get_partition_num_by_name("system_a");
413 else if (s1 && (strcmp(s1, "_b") == 0))
414 ret = get_partition_num_by_name("system_b");
415 else
416 ret = get_partition_num_by_name("system");
Matthew Shyu837ffa52024-05-03 01:59:44 -0700417#else
418 ret = 0;
419#endif
Bo Lv72d0e902023-01-02 14:27:34 +0000420
421 if (ret >= 0) {
422 sprintf(part_name, "/dev/mmcblk0p%d", ret + 1);
423 strncpy(guid_buf, part_name, guid_buf_size);
424 } else {
425 printf("system part isn't exist\n");
426 return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
427 }
428 } else if (!memcmp(partition, "vbmeta", strlen("vbmeta"))) {
429 strncpy(guid_buf, "/dev/block/vbmeta", guid_buf_size);
430 }
431 return AVB_IO_RESULT_OK;
432}
433
434static AvbIOResult get_size_of_partition(AvbOps *ops, const char *partition,
435 uint64_t *out_size_num_bytes)
436{
437 uint64_t rc = 0;
438
439 if (!strcmp(partition, "dt_a") || !strcmp(partition, "dt_b") ||
440 !strcmp(partition, "dt")) {
441 *out_size_num_bytes = DTB_PARTITION_SIZE;
Matthew Shyuc710a122023-12-14 00:08:41 -0800442 } else if (!strcmp(partition, "recovery-memory")) {
443 *out_size_num_bytes = simple_strtoul(env_get("filesize"), NULL, 16);
Bo Lv72d0e902023-01-02 14:27:34 +0000444 } else {
445 /* There is only 1 recovery partition even in A/B */
446 if (!strcmp(partition, "recovery_a") ||
447 !strcmp(partition, "recovery_b") ||
448 !strcmp(partition, "recovery"))
449 rc = store_logic_cap("recovery");
450 else
451 rc = store_logic_cap(partition);
452 if (rc == 1) {
453 printf("Failed to get partition[%s] size\n", partition);
454 return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
455 }
456 *out_size_num_bytes = rc;
457 }
458
459 return AVB_IO_RESULT_OK;
460}
461
462/**
463 * normally, we should read vendor avb public key from a virtual partition with the name avb_custom_key.
464 * Flashing and erasing this partition only works in the UNLOCKED state. Setting the custom key is done like this:
465 * $ avbtool extract_public_key --key key.pem --output pkmd.bin
466 * $ fastboot flash avb_custom_key pkmd.bin
467 *
468 * Erasing the key is done by erasing the virtual partition:
469 * $ fastboot erase avb_custom_key
470 */
471static AvbIOResult validate_vbmeta_public_key(AvbOps *ops, const uint8_t *public_key_data,
472 size_t public_key_length, const uint8_t *public_key_metadata,
473 size_t public_key_metadata_length, bool *out_is_trusted)
474{
475 *out_is_trusted = false;
476 AvbIOResult ret = AVB_IO_RESULT_ERROR_IO;
477 char *keybuf = NULL;
478 char *partition = "misc";
479 AvbKey_t key;
Matthew Shyu837ffa52024-05-03 01:59:44 -0700480 u64 size = 0;
Bo Lv72d0e902023-01-02 14:27:34 +0000481#if CONFIG_AVB2_KPUB_FROM_FIP
482 int result = 0;
483#endif
484 int i = 0;
485
486#if CONFIG_AVB2_KPUB_FROM_FIP
487 printf("AVB2 verifying with fip key\n");
488 result = compare_avbkey_with_fipkey(public_key_data, public_key_length);
489 if (result == -2) {
490 printf("AVB2 verified with fip key failed\n");
491 *out_is_trusted = false;
492 ret = AVB_IO_RESULT_OK;
493 return ret;
494 } else if (result == -1) {
495 printf("AVB2 cannot find fip key\n");
496 } else if (result == 0) {
497 printf("AVB2 verified with fip key success\n");
498 *out_is_trusted = true;
499 ret = AVB_IO_RESULT_OK;
500 return ret;
501 }
502#endif
503
504 /*
505 * disable AVB custom key and test key
506 * if device secure boot enabled
507 */
508 if (!IS_FEAT_BOOT_VERIFY()) {
509 key.size = 0;
510 keybuf = (char *)malloc(AVB_CUSTOM_KEY_LEN_MAX);
511 if (keybuf) {
512 memset(keybuf, 0, AVB_CUSTOM_KEY_LEN_MAX);
Matthew Shyu837ffa52024-05-03 01:59:44 -0700513 size = store_logic_cap(partition);
Bo Lv72d0e902023-01-02 14:27:34 +0000514 if (size != 1) {
Matthew Shyu837ffa52024-05-03 01:59:44 -0700515 /* no need workaround for nand. The size is 4K multiple,
516 * and AVB_CUSTOM_KEY_LEN_MAX is 4K. The offset will lay on
517 * 4K boundary.
518 */
519 if (store_logic_read((const char *)partition,
520 size - AVB_CUSTOM_KEY_LEN_MAX,
521 AVB_CUSTOM_KEY_LEN_MAX,
522 (unsigned char *)keybuf) >= 0) {
Bo Lv72d0e902023-01-02 14:27:34 +0000523 memcpy(&key, keybuf, sizeof(AvbKey_t));
524 }
525 }
526 }
527
528 if (keybuf && (strncmp(keybuf, "AVBK", 4) == 0)) {
529 printf("AVB2 verify with avb_custom_key\n");
530 if (key.size == public_key_length &&
531 !avb_safe_memcmp(public_key_data,
532 keybuf + sizeof(AvbKey_t), public_key_length)) {
533 *out_is_trusted = true;
534 ret = AVB_IO_RESULT_OK;
535 }
Jason Tong6a3cca92023-08-24 18:08:17 +0800536 if (is_device_unlocked())
537 ret = AVB_IO_RESULT_OK;
Bo Lv72d0e902023-01-02 14:27:34 +0000538 } else {
539 /**
540 * When the custom key is set
541 * and the device is in the LOCKED state
542 * it will boot images signed with both the built-in key
543 * as well as the custom key
544 */
545 printf("AVB2 verify with default kpub:%d, vbmeta kpub:%ld\n",
546 avb2_kpub_default_len, public_key_length);
547 if (avb2_kpub_default_len == public_key_length &&
548 !avb_safe_memcmp(public_key_data,
549 avb2_kpub_default, public_key_length)) {
550 *out_is_trusted = true;
551 ret = AVB_IO_RESULT_OK;
552 }
553 }
554 } else {
555 printf("AVB2 verify with production kpub:%d, vbmeta kpub:%ld\n",
556 avb2_kpub_production_len, public_key_length);
557 if (avb2_kpub_production_len == public_key_length &&
558 !avb_safe_memcmp(public_key_data,
559 avb2_kpub_production, public_key_length)) {
560 *out_is_trusted = true;
561 ret = AVB_IO_RESULT_OK;
562 }
563 for (i = 0; i < avb2_kpub_production_len; i++) {
564 if (avb2_kpub_production[i] != 0)
565 break;
566 }
567 if (i == avb2_kpub_production_len)
568 printf("ERROR: DID YOU FORGET TO CHANGE AVB2 KEY FOR SECURE BOOT?");
569 }
570
571 if (keybuf)
572 free(keybuf);
573 if (ret != AVB_IO_RESULT_OK)
574 printf("AVB2 key in bootloader does not match with the key in vbmeta\n");
575 return ret;
576}
577
Matthew Shyuc710a122023-12-14 00:08:41 -0800578static AvbIOResult validate_public_key_for_partition(AvbOps *ops,
579 const char *partition,
580 const u8 *public_key_data,
581 size_t public_key_length,
582 const u8 *public_key_metadata,
583 size_t public_key_metadata_length,
584 bool *out_is_trusted,
585 uint32_t *out_rollback_index_location
586)
587{
588 AvbIOResult ret = AVB_IO_RESULT_ERROR_IO;
589
590 if (!ops || !partition || !public_key_data || !out_is_trusted ||
591 !out_rollback_index_location)
592 return AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE;
593
594 *out_is_trusted = false;
595
596 if (!strcmp(partition, "recovery") ||
597 !strcmp(partition, "recovery-memory")) {
598 printf("checking for recovery partition\n");
599 ret = validate_vbmeta_public_key(ops, public_key_data,
600 public_key_length, public_key_metadata,
601 public_key_metadata_length,
602 out_is_trusted);
603 *out_rollback_index_location = RECOVERY_ARB_LOCATION;
604 } else {
605 *out_rollback_index_location = 0;
606 return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
607 }
608
609 return ret;
610}
611
Bo Lv72d0e902023-01-02 14:27:34 +0000612static AvbIOResult read_rollback_index(AvbOps *ops, size_t rollback_index_location,
613 uint64_t *out_rollback_index)
614{
Mingyen Hung6e468002023-01-04 23:43:04 -0800615 AvbIOResult result = AVB_IO_RESULT_OK;
Bo Lv72d0e902023-01-02 14:27:34 +0000616#if defined(CONFIG_AML_ANTIROLLBACK) || defined(CONFIG_AML_AVB2_ANTIROLLBACK)
Mingyen Hung6e468002023-01-04 23:43:04 -0800617 uint32_t version = 0;
Bo Lv72d0e902023-01-02 14:27:34 +0000618#endif
Mingyen Hung6e468002023-01-04 23:43:04 -0800619
620 *out_rollback_index = 0;
621
622#if defined(CONFIG_AML_ANTIROLLBACK) || defined(CONFIG_AML_AVB2_ANTIROLLBACK)
623 if (is_avb_arb_available()) {
624 if (get_avb_antirollback(rollback_index_location, &version)) {
625 *out_rollback_index = version;
626 } else {
627 printf("failed to read rollback index: %zd\n", rollback_index_location);
628 result = AVB_IO_RESULT_ERROR_NO_SUCH_VALUE;
629 }
630 }
631#endif
632
633 return result;
Bo Lv72d0e902023-01-02 14:27:34 +0000634}
635
636static AvbIOResult write_rollback_index(AvbOps* ops, size_t rollback_index_location,
637 uint64_t rollback_index)
638{
639 AvbIOResult result = AVB_IO_RESULT_OK;
Mingyen Hung6e468002023-01-04 23:43:04 -0800640
Bo Lv72d0e902023-01-02 14:27:34 +0000641#if defined(CONFIG_AML_ANTIROLLBACK) || defined(CONFIG_AML_AVB2_ANTIROLLBACK)
642 uint32_t version = rollback_index;
643
Mingyen Hung6e468002023-01-04 23:43:04 -0800644 if (is_avb_arb_available()) {
645 if (!set_avb_antirollback(rollback_index_location, version)) {
646 printf("failed to set rollback index: %zd, version: %u\n",
647 rollback_index_location, version);
648 result = AVB_IO_RESULT_ERROR_NO_SUCH_VALUE;
649 }
Bo Lv72d0e902023-01-02 14:27:34 +0000650 }
Bo Lv72d0e902023-01-02 14:27:34 +0000651#endif
Mingyen Hung6e468002023-01-04 23:43:04 -0800652
Bo Lv72d0e902023-01-02 14:27:34 +0000653 return result;
654}
655
656static AvbIOResult read_is_device_unlocked(AvbOps* ops, bool* out_is_unlocked)
657{
658 AvbIOResult result = AVB_IO_RESULT_OK;
Mingyen Hung6e468002023-01-04 23:43:04 -0800659 LockData_t info = { 0 };
Bo Lv72d0e902023-01-02 14:27:34 +0000660#if defined(CONFIG_AML_ANTIROLLBACK) || defined(CONFIG_AML_AVB2_ANTIROLLBACK)
Mingyen Hung6e468002023-01-04 23:43:04 -0800661 uint32_t lock_state = 0;
662#endif
663 char *lock_s = env_get("lock");
Bo Lv72d0e902023-01-02 14:27:34 +0000664
Mingyen Hung6e468002023-01-04 23:43:04 -0800665 if (!lock_s)
666 return AVB_IO_RESULT_ERROR_IO;
Bo Lv72d0e902023-01-02 14:27:34 +0000667
Mingyen Hung6e468002023-01-04 23:43:04 -0800668#if defined(CONFIG_AML_ANTIROLLBACK) || defined(CONFIG_AML_AVB2_ANTIROLLBACK)
669 if (is_avb_arb_available()) {
670 if (get_avb_lock_state(&lock_state)) {
671 *out_is_unlocked = !lock_state;
672 if (*out_is_unlocked)
673 lock_s[4] = '0';
674 else
675 lock_s[4] = '1';
676 } else {
677 printf("failed to read device lock status from rpmb\n");
678 result = AVB_IO_RESULT_ERROR_IO;
679 }
680 return result;
Bo Lv72d0e902023-01-02 14:27:34 +0000681 }
Mingyen Hung6e468002023-01-04 23:43:04 -0800682#endif
Bo Lv72d0e902023-01-02 14:27:34 +0000683
684 memset(&info, 0, sizeof(struct LockData));
Bo Lv72d0e902023-01-02 14:27:34 +0000685 info.version_major = (int)(lock_s[0] - '0');
686 info.version_minor = (int)(lock_s[1] - '0');
687 info.lock_state = (int)(lock_s[4] - '0');
688 info.lock_critical_state = (int)(lock_s[5] - '0');
689 info.lock_bootloader = (int)(lock_s[6] - '0');
690
691 if (info.lock_state == 1)
692 *out_is_unlocked = false;
693 else
694 *out_is_unlocked = true;
Mingyen Hung6e468002023-01-04 23:43:04 -0800695
Bo Lv72d0e902023-01-02 14:27:34 +0000696 return result;
697}
698
Matthew Shyu837ffa52024-05-03 01:59:44 -0700699#if CONFIG_IS_ENABLED(MMC_MESON_GX)
Mingyen Hung6e468002023-01-04 23:43:04 -0800700/* 4K bytes are allocated to store persistent value
701 * The first 4B is the persistent store magic word "@AVB"
702 * It is further divided into 132B slots
703 * Each 132B contains a persistent_value_t structure.
704 */
705#define AVB_PERSISTENT_MISC_OFFSET (2040 * 1024)
706#define AVB_PERSISTENT_SLOT (31)
707/* 4100 */
708#define AVB_PERSISTENT_SIZE (4 + 4 + 132 * AVB_PERSISTENT_SLOT)
709#define AVB_PERSISTENT_MAGIC "@AVB"
710#define AVB_PERSISTENT_VERSION (0x0)
711#define PERSISTENT_NAME_MAX_LEN (64)
712#define PERSISTENT_VALUE_MAX_LEN (64)
713#define PERSISTENT_FILENAME "avb_persist"
714
715#define DEV_NAME "mmc"
716#define DEV_NO (1)
717#define PART_TYPE "user"
718#define PART_NAME_RSV "rsv"
719#define PART_NAME_FTY "factory"
720#define NAND_FTY_MOUNT_PT "mnt"
721
722struct persistent_value {
723 uint8_t name_length;
724 uint8_t value_length;
725 uint16_t rsv;
726 char name[PERSISTENT_NAME_MAX_LEN];
727 uint8_t value[PERSISTENT_VALUE_MAX_LEN];
728};
729
730static uint8_t *persistent_store(int32_t *is_empty)
731{
732 uint8_t *buf = NULL;
733 int rc = 0;
734 loff_t act_read = 0;
735
736 /* initialize factory partition */
737 rc = run_command("factory_provision init", 0);
738 if (rc) {
739 printf("init factory partition failed\n");
740 return NULL;
741 }
742
743 buf = malloc(AVB_PERSISTENT_SIZE);
744 if (!buf) {
745 printf("failed to allocate buf for persistent store\n");
746 return NULL;
747 }
748 if (fat_read_file(PERSISTENT_FILENAME, buf, 0,
749 AVB_PERSISTENT_SIZE, &act_read)) {
750 printf("failed to read persistent store\n");
751 goto empty;
752 } else {
753 if (act_read != AVB_PERSISTENT_SIZE) {
754 printf("unexpected size: %lld\n", act_read);
755 memset(buf, 0, AVB_PERSISTENT_SIZE);
756 goto empty;
757 }
758 }
759
760empty:
761 if (memcmp(&buf[0], AVB_PERSISTENT_MAGIC, 4)) {
762 printf("empty persistent store, resetting\n");
763 memset(buf, 0, AVB_PERSISTENT_SIZE);
764 memcpy(&buf[0], AVB_PERSISTENT_MAGIC, 4);
765 if (is_empty)
766 *is_empty = 1;
767 } else {
768 if (is_empty)
769 *is_empty = 0;
770 }
771
772 return buf;
773}
774
775static AvbIOResult persistent_test(AvbOps *ops)
776{
777 AvbIOResult ret = AVB_IO_RESULT_OK;
778 static const char case_I[] = "smart wolves";
779 static const char case_II[] = "happy wife";
780 static const char case_III[] = "lion king";
781 char case_I_read[sizeof(case_I)] = {0};
782 char case_II_read[sizeof(case_II)] = {0};
783 char case_III_read[sizeof(case_III)] = {0};
784 size_t out_num_bytes_read = 0;
785
786 ret = ops->write_persistent_value(ops, "persist test case I",
787 sizeof(case_I), (const uint8_t *)case_I);
788 if (ret != AVB_IO_RESULT_OK) {
789 printf("failed to write case I\n");
790 return ret;
791 }
792 ret = ops->write_persistent_value(ops, "persist test case II",
793 sizeof(case_II), (const uint8_t *)case_II);
794 if (ret != AVB_IO_RESULT_OK) {
795 printf("failed to write case II\n");
796 return ret;
797 }
798 ret = ops->write_persistent_value(ops, "persist test case III",
799 sizeof(case_III), (const uint8_t *)case_III);
800 if (ret != AVB_IO_RESULT_OK) {
801 printf("failed to write case III\n");
802 return ret;
803 }
804
805 ret = ops->read_persistent_value(ops, "persist test case I",
806 sizeof(case_I_read), (uint8_t *)case_I_read, &out_num_bytes_read);
807 if (ret != AVB_IO_RESULT_OK) {
808 printf("failed to read case I\n");
809 return ret;
810 }
811 if (out_num_bytes_read == sizeof(case_I_read) &&
812 !strncmp(case_I, case_I_read, sizeof(case_I))) {
813 printf("case I passed\n");
814 } else {
815 printf("case I failed\n");
816 }
817
818 ret = ops->read_persistent_value(ops, "persist test case II",
819 sizeof(case_II_read), (uint8_t *)case_II_read,
820 &out_num_bytes_read);
821 if (ret != AVB_IO_RESULT_OK) {
822 printf("failed to read case II\n");
823 return ret;
824 }
825 if (out_num_bytes_read == sizeof(case_II_read) &&
826 !strncmp(case_II, case_II_read, sizeof(case_II))) {
827 printf("case II passed\n");
828 } else {
829 printf("case II failed\n");
830 }
831
832 ret = ops->read_persistent_value(ops, "persist test case III",
833 sizeof(case_III_read), (uint8_t *)case_III_read,
834 &out_num_bytes_read);
835 if (ret != AVB_IO_RESULT_OK) {
836 printf("failed to read case III\n");
837 return ret;
838 }
839 if (out_num_bytes_read == sizeof(case_III_read) &&
840 !strncmp(case_III, case_III_read, sizeof(case_III))) {
841 printf("case III passed\n");
842 } else {
843 printf("case III failed\n");
844 }
845
846 return ret;
847}
Matthew Shyu837ffa52024-05-03 01:59:44 -0700848#endif
Mingyen Hung6e468002023-01-04 23:43:04 -0800849
Matthew Shyu837ffa52024-05-03 01:59:44 -0700850#if CONFIG_IS_ENABLED(MMC_MESON_GX)
Mingyen Hung6e468002023-01-04 23:43:04 -0800851uint32_t create_csrs(void)
852{
853 int part_num = get_partition_num_by_name(PART_NAME_FTY);
854 char part_name[32] = {0};
855 char cmd[64] = {0};
856 uint8_t buf[1] = {0};
857
858 if (part_num >= 0)
859 strcpy(part_name, PART_NAME_FTY);
860 else
861 strcpy(part_name, PART_NAME_RSV);
862
863 sprintf(cmd, "fatmkdir %s 0x%X:0x%X %s", DEV_NAME, DEV_NO,
864 get_partition_num_by_name(part_name), "csrs");
865 if (run_command(cmd, 0)) {
866 printf("command[%s] failed\n", cmd);
867 return AVB_IO_RESULT_ERROR_IO;
868 }
869
870 memset(cmd, 0, sizeof(cmd));
871
872 sprintf(cmd, "fatwrite %s 0x%X:0x%X 0x%08X %s 0x%X", DEV_NAME, DEV_NO,
873 get_partition_num_by_name(part_name),
874 (uint32_t)virt_to_phys((void *)buf), "csrs/csrs.json", 1);
875 if (run_command(cmd, 0)) {
876 printf("command[%s] failed\n", cmd);
877 return AVB_IO_RESULT_ERROR_IO;
878 }
879 return AVB_IO_RESULT_OK;
880}
Matthew Shyu837ffa52024-05-03 01:59:44 -0700881#else
882uint32_t create_csrs(void)
883{
884 return AVB_IO_RESULT_OK;
885}
886#endif
Mingyen Hung6e468002023-01-04 23:43:04 -0800887
Matthew Shyu837ffa52024-05-03 01:59:44 -0700888#if CONFIG_IS_ENABLED(MMC_MESON_GX)
Mingyen Hung6e468002023-01-04 23:43:04 -0800889static AvbIOResult write_persistent_to_factory(uint8_t *buf, uint32_t size)
890{
891 int part_num = get_partition_num_by_name(PART_NAME_FTY);
892 char part_name[32] = {0};
893 char cmd[64] = {0};
894
895 if (part_num >= 0)
896 strcpy(part_name, PART_NAME_FTY);
897 else
898 strcpy(part_name, PART_NAME_RSV);
899
900 sprintf(cmd, "fatwrite %s 0x%X:0x%X 0x%08X %s 0x%X", DEV_NAME, DEV_NO,
901 get_partition_num_by_name(part_name),
902 (uint32_t)virt_to_phys((void *)buf), PERSISTENT_FILENAME, size);
903 if (run_command(cmd, 0)) {
904 printf("command[%s] failed\n", cmd);
905 return AVB_IO_RESULT_ERROR_IO;
906 }
907
908 return AVB_IO_RESULT_OK;
909}
910
911static AvbIOResult persistent_wipe(void)
912{
913 uint8_t *buf = NULL;
914 AvbIOResult ret = AVB_IO_RESULT_OK;
915
916 buf = persistent_store(NULL);
917 if (buf) {
918 memset(buf, 0, AVB_PERSISTENT_SIZE);
919 memcpy(&buf[0], AVB_PERSISTENT_MAGIC, 4);
920 *(uint32_t *)&buf[4] = AVB_PERSISTENT_VERSION;
921 } else {
922 return AVB_IO_RESULT_ERROR_IO;
923 }
924
925 ret = write_persistent_to_factory(buf, AVB_PERSISTENT_SIZE);
926
927 free(buf);
928 return ret;
929}
930
931static AvbIOResult persistent_dump(void)
932{
933 uint8_t *buf = NULL;
934 int rc = 0;
935 AvbIOResult ret = AVB_IO_RESULT_OK;
936 char *name = NULL;
937 int i = 0;
938 char cmd[64] = {0};
939 struct persistent_value *persist = NULL;
940
941 buf = persistent_store(NULL);
942 if (buf) {
943 printf("persistent store:\n");
944 /* skip magic word and version */
945 persist = (struct persistent_value *)(buf + 8);
946 for (i = 0; i < AVB_PERSISTENT_SLOT; i++) {
947 printf("%d:\n", i);
948 if (persist[i].name_length) {
949 name = malloc(persist[i].name_length);
950 if (!name) {
951 printf("failed to allocate name\n");
952 goto out;
953 }
954 strncpy(name, persist[i].name,
955 persist[i].name_length);
956 printf("%s\n", name);
957 free(name);
958 printf("length = %d\n",
959 persist[i].value_length);
960 snprintf(cmd, sizeof(cmd),
961 "md.b %p %x", persist[i].value,
962 persist[i].value_length);
963 rc = run_command(cmd, 0);
964 if (rc) {
965 printf("failed to run cmd: %s\n", cmd);
966 ret = AVB_IO_RESULT_ERROR_IO;
967 goto out;
968 }
969 } else {
970 printf("empty slot\n");
971 }
972 }
973 } else {
974 return AVB_IO_RESULT_ERROR_IO;
975 }
976
977out:
978 free(buf);
979 return ret;
980}
981
982AvbIOResult read_persistent_value(AvbOps *ops, const char *name,
983 size_t buffer_size, uint8_t *out_buffer, size_t *out_num_bytes_read)
984{
985 uint8_t *buf = NULL;
986 uint32_t value_found = 0;
987 uint32_t i = 0;
988 struct persistent_value *persist = NULL;
989 AvbIOResult ret = AVB_IO_RESULT_OK;
990 AvbIOResult ret_write = AVB_IO_RESULT_OK;
991 int32_t is_empty = 0;
992
993 if (!out_buffer) {
994 if (!buffer_size)
995 return AVB_IO_RESULT_OK;
996 else
997 return AVB_IO_RESULT_ERROR_IO;
998 }
999
1000 buf = persistent_store(&is_empty);
1001 if (buf) {
1002 /* skip magic word and version */
1003 persist = (struct persistent_value *)(buf + 8);
1004 for (i = 0; i < AVB_PERSISTENT_SLOT; i++) {
1005 if (strlen(name) == persist[i].name_length &&
1006 !strncmp(persist[i].name, name, persist[i].name_length)) {
1007 if (buffer_size >= persist[i].value_length) {
1008 memcpy(out_buffer, persist[i].value,
1009 persist[i].value_length);
1010 *out_num_bytes_read = persist[i].value_length;
1011 ret = AVB_IO_RESULT_OK;
1012 } else {
1013 ret = AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE;
1014 *out_num_bytes_read = persist[i].value_length;
1015 }
1016 value_found = 1;
1017 break;
1018 }
1019 }
1020 if (!value_found)
1021 ret = AVB_IO_RESULT_ERROR_NO_SUCH_VALUE;
1022 } else {
1023 ret = AVB_IO_RESULT_ERROR_IO;
1024 }
1025
1026 /* write storage, if empty */
1027 if (is_empty) {
1028 ret_write = write_persistent_to_factory(buf, AVB_PERSISTENT_SIZE);
1029 if (ret_write != AVB_IO_RESULT_OK)
1030 printf("failed to write empty persistent data\n");
1031 }
1032
1033 free(buf);
1034 return ret;
1035}
1036
1037AvbIOResult write_persistent_value(AvbOps *ops, const char *name,
1038 size_t value_size, const uint8_t *value)
1039{
1040 uint8_t *buf = NULL;
1041 struct persistent_value *empty_slot = NULL;
1042 uint32_t value_found = 0;
1043 uint32_t i = 0;
1044 struct persistent_value *persist = NULL;
1045 AvbIOResult ret = AVB_IO_RESULT_OK;
1046
1047 if (value_size > PERSISTENT_VALUE_MAX_LEN)
1048 return AVB_IO_RESULT_ERROR_INVALID_VALUE_SIZE;
1049 if (strlen(name) > PERSISTENT_NAME_MAX_LEN)
1050 return AVB_IO_RESULT_ERROR_NO_SUCH_VALUE;
1051
1052 buf = persistent_store(NULL);
1053 if (buf) {
1054 /* skip magic word and version */
1055 persist = (struct persistent_value *)(buf + 8);
1056 for (i = 0; i < AVB_PERSISTENT_SLOT; i++) {
1057 if (!persist[i].name_length) {
1058 if (!empty_slot)
1059 empty_slot = &persist[i];
1060 } else {
1061 if (strlen(name) == persist[i].name_length &&
1062 !strncmp(persist[i].name, name,
1063 persist[i].name_length)) {
1064 memset(persist[i].value, 0, sizeof(persist[i].value));
1065 memcpy(persist[i].value, value, value_size);
1066 persist[i].value_length = value_size;
1067 value_found = 1;
1068 break;
1069 }
1070 }
1071 }
1072 if (!value_found) {
1073 if (empty_slot) {
1074 empty_slot->name_length = strlen(name);
1075 memset(empty_slot->name, 0, sizeof(empty_slot->name));
1076 memcpy(empty_slot->name, name, empty_slot->name_length);
1077 memset(empty_slot->value, 0, sizeof(empty_slot->value));
1078 memcpy(empty_slot->value, value, value_size);
1079 empty_slot->value_length = value_size;
1080 } else {
1081 printf("no more slots\n");
1082 ret = AVB_IO_RESULT_ERROR_IO;
1083 goto out;
1084 }
1085 }
1086 } else {
1087 ret = AVB_IO_RESULT_ERROR_IO;
1088 goto out;
1089 }
1090 ret = write_persistent_to_factory(buf, AVB_PERSISTENT_SIZE);
1091
1092out:
1093 free(buf);
1094 return ret;
1095}
Matthew Shyu837ffa52024-05-03 01:59:44 -07001096#endif
Mingyen Hung6e468002023-01-04 23:43:04 -08001097
Bo Lv72d0e902023-01-02 14:27:34 +00001098static int avb_init(void)
1099{
Matthew Shyu837ffa52024-05-03 01:59:44 -07001100 int factory_part_num = -1;
1101#if CONFIG_IS_ENABLED(MMC_MESON_GX)
1102 /* partition name is valid */
1103 if (find_mmc_partition_by_name(PART_NAME_FTY))
1104 factory_part_num = get_partition_num_by_name(PART_NAME_FTY);
1105#endif
Mingyen Hung6e468002023-01-04 23:43:04 -08001106 enum boot_type_e type = store_get_type();
Bo Lv72d0e902023-01-02 14:27:34 +00001107
1108 memset(&avb_ops_, 0, sizeof(AvbOps));
1109 avb_ops_.read_from_partition = read_from_partition;
Matthew Shyu837ffa52024-05-03 01:59:44 -07001110 avb_ops_.get_preloaded_partition = get_preloaded_partition;
Bo Lv72d0e902023-01-02 14:27:34 +00001111 avb_ops_.write_to_partition = write_to_partition;
1112 avb_ops_.validate_vbmeta_public_key = validate_vbmeta_public_key;
1113 avb_ops_.read_rollback_index = read_rollback_index;
1114 avb_ops_.write_rollback_index = write_rollback_index;
1115 avb_ops_.read_is_device_unlocked = read_is_device_unlocked;
1116 avb_ops_.get_unique_guid_for_partition = get_unique_guid_for_partition;
1117 avb_ops_.get_size_of_partition = get_size_of_partition;
Matthew Shyuc710a122023-12-14 00:08:41 -08001118 avb_ops_.validate_public_key_for_partition = validate_public_key_for_partition;
Matthew Shyu837ffa52024-05-03 01:59:44 -07001119
Mingyen Hung6e468002023-01-04 23:43:04 -08001120 if (type == BOOT_NAND_MTD || type == BOOT_SNAND || factory_part_num < 0) {
1121 avb_ops_.read_persistent_value = NULL;
1122 avb_ops_.write_persistent_value = NULL;
1123 } else {
Matthew Shyu837ffa52024-05-03 01:59:44 -07001124#if CONFIG_IS_ENABLED(MMC_MESON_GX)
Mingyen Hung6e468002023-01-04 23:43:04 -08001125 avb_ops_.read_persistent_value = read_persistent_value;
1126 avb_ops_.write_persistent_value = write_persistent_value;
Matthew Shyu837ffa52024-05-03 01:59:44 -07001127#else
1128 avb_ops_.read_persistent_value = NULL;
1129 avb_ops_.write_persistent_value = NULL;
1130#endif
Mingyen Hung6e468002023-01-04 23:43:04 -08001131 }
Bo Lv72d0e902023-01-02 14:27:34 +00001132
1133 return 0;
1134}
1135
1136int is_device_unlocked(void)
1137{
1138 AvbIOResult ret;
1139 bool out_is_unlocked;
1140
1141 ret = read_is_device_unlocked(&avb_ops_, &out_is_unlocked);
1142 if (ret == AVB_IO_RESULT_OK)
1143 return out_is_unlocked;
1144 else
1145 return 0;
1146}
1147
1148int avb_verify(AvbSlotVerifyData** out_data)
1149{
Matthew Shyu88b14432024-07-09 00:16:28 -07001150 /* The last slot must be NULL */
1151 const char *requested_partitions[AVB_NUM_SLOT + 1] = {"boot", "dt", "dtbo",
1152 "init_boot", "vendor_boot", NULL, NULL};
Bo Lv72d0e902023-01-02 14:27:34 +00001153 AvbSlotVerifyResult result = AVB_SLOT_VERIFY_RESULT_OK;
1154 char *s1 = NULL;
1155 char *ab_suffix = NULL;
Matthew Shyu837ffa52024-05-03 01:59:44 -07001156 int factory_part_num = -1;
Matthew Shyu837ffa52024-05-03 01:59:44 -07001157
Mingyen Hung6e468002023-01-04 23:43:04 -08001158 AvbHashtreeErrorMode hashtree_error_mode =
1159 AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE;
Matthew Shyu837ffa52024-05-03 01:59:44 -07001160#if CONFIG_IS_ENABLED(MMC_MESON_GX)
1161 /* partition name is valid */
1162 if (find_mmc_partition_by_name(PART_NAME_FTY))
1163 factory_part_num = get_partition_num_by_name(PART_NAME_FTY);
1164#endif
Mingyen Hung6e468002023-01-04 23:43:04 -08001165 enum boot_type_e type = store_get_type();
Bo Lv72d0e902023-01-02 14:27:34 +00001166
1167 s1 = env_get("active_slot");
1168 if (!s1) {
1169 run_command("get_valid_slot;", 0);
1170 s1 = env_get("active_slot");
1171 }
1172 if (s1) {
1173 printf("active_slot is %s\n", s1);
1174 if (!strcmp(s1, "normal"))
1175 ab_suffix = "";
1176 else
1177 ab_suffix = env_get("active_slot");
1178 }
1179
1180 if (!ab_suffix)
1181 ab_suffix = "";
1182 printf("ab_suffix is %s\n", ab_suffix);
1183
Bo Lv72d0e902023-01-02 14:27:34 +00001184 AvbSlotVerifyFlags flags = AVB_SLOT_VERIFY_FLAGS_NONE;
Bo Lv72d0e902023-01-02 14:27:34 +00001185
1186 avb_init();
1187
Matthew Shyufcd728f2023-12-07 01:44:32 -08001188 if (is_device_unlocked())
Bo Lv72d0e902023-01-02 14:27:34 +00001189 flags |= AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR;
1190
Matthew Shyuc710a122023-12-14 00:08:41 -08001191 if (!strcmp(ab_suffix, "")) {
1192 printf("recovery: %d\n", run_in_recovery);
1193 if (run_in_recovery) {
1194 flags |= AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION;
1195 memset(requested_partitions, 0, sizeof(requested_partitions));
Matthew Shyuc4ba2192024-06-19 01:23:35 -07001196 if (recovery_from_memory)
1197 requested_partitions[0] = "recovery-memory";
1198 else
1199 requested_partitions[0] = "recovery";
1200 recovery_from_memory = 0;
Matthew Shyuc710a122023-12-14 00:08:41 -08001201 }
1202 }
Matthew Shyu837ffa52024-05-03 01:59:44 -07001203
Mingyen Hung6e468002023-01-04 23:43:04 -08001204 if (type == BOOT_NAND_MTD || type == BOOT_SNAND || factory_part_num < 0)
1205 hashtree_error_mode =
1206 AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE;
1207 else
1208 hashtree_error_mode =
1209 AVB_HASHTREE_ERROR_MODE_MANAGED_RESTART_AND_EIO;
Matthew Shyuc710a122023-12-14 00:08:41 -08001210
Matthew Shyu88b14432024-07-09 00:16:28 -07001211 result = avb_slot_verify(&avb_ops_, requested_partitions, ab_suffix,
1212 flags, hashtree_error_mode, out_data);
Bo Lv72d0e902023-01-02 14:27:34 +00001213
Matthew Shyu837ffa52024-05-03 01:59:44 -07001214 clear_avb_parts();
1215
Matthew Shyu88b14432024-07-09 00:16:28 -07001216 run_in_recovery = 0;
Bo Lv72d0e902023-01-02 14:27:34 +00001217 return result;
Bo Lv72d0e902023-01-02 14:27:34 +00001218}
1219
1220static int do_avb_verify(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
1221{
1222 AvbSlotVerifyResult result = AVB_SLOT_VERIFY_RESULT_OK;
1223 AvbSlotVerifyData *out_data = NULL;
1224 uint32_t i = 0;
Mingyen Hung6e468002023-01-04 23:43:04 -08001225#if defined(CONFIG_AML_ANTIROLLBACK) || defined(CONFIG_AML_AVB2_ANTIROLLBACK)
1226 uint32_t version = 0;
1227 uint32_t lock_state = 0;
1228#endif
Bo Lv72d0e902023-01-02 14:27:34 +00001229
1230 result = (AvbSlotVerifyResult)avb_verify(&out_data);
1231
1232 printf("result: %d\n", result);
1233 if (result == AVB_SLOT_VERIFY_RESULT_OK && out_data) {
Bo Lv72d0e902023-01-02 14:27:34 +00001234 printf("ab_suffix: %s\n", out_data->ab_suffix);
1235 printf("vbmeta: name: %s, size: %zd, result: %d\n",
1236 out_data->vbmeta_images->partition_name,
1237 out_data->vbmeta_images->vbmeta_size,
1238 out_data->vbmeta_images->verify_result);
1239 printf("num of vbmeta: %zd\n", out_data->num_vbmeta_images);
1240 printf("loaded name: %s, size: %zd, preload: %d\n",
1241 out_data->loaded_partitions->partition_name,
1242 out_data->loaded_partitions->data_size,
1243 out_data->loaded_partitions->preloaded);
1244 printf("num of loaded: %zd\n", out_data->num_loaded_partitions);
1245 printf("cmdline: %s\n", out_data->cmdline);
1246 for (i = 0; i < AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS; i++)
1247 printf("rollback(%d) = %llu\n", i, out_data->rollback_indexes[i]);
1248
1249#if defined(CONFIG_AML_ANTIROLLBACK) || defined(CONFIG_AML_AVB2_ANTIROLLBACK)
Mingyen Hung6e468002023-01-04 23:43:04 -08001250 if (is_avb_arb_available()) {
1251 for (i = 0; i < AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS; i++)
1252 if (get_avb_antirollback(i, &version))
1253 printf("rpmb rollback(%d) = %u\n", i, version);
1254 if (get_avb_lock_state(&lock_state))
1255 printf("rpmb lock state: %u\n", lock_state);
1256 }
Bo Lv72d0e902023-01-02 14:27:34 +00001257#endif
1258
1259 avb_slot_verify_data_free(out_data);
1260 }
1261
1262 return result;
1263}
1264
Matthew Shyu837ffa52024-05-03 01:59:44 -07001265#if CONFIG_IS_ENABLED(MMC_MESON_GX)
1266static int do_avb_persist(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
1267{
1268 int result = 0;
1269 u32 cmd = 0;
1270
1271 if (argc != 2) {
1272 printf("invalid argc: %d\n", argc);
1273 return -1;
1274 }
1275
1276 avb_init();
1277
1278 if (!strcmp(argv[1], "test")) {
1279 cmd = 0;
1280 } else if (!strcmp(argv[1], "wipe")) {
1281 cmd = 1;
1282 } else if (!strcmp(argv[1], "dump")) {
1283 cmd = 2;
1284 } else {
1285 printf("unknown cmd: %s\n", argv[1]);
1286 return -1;
1287 }
1288
1289 switch (cmd) {
1290 case 0:
1291 printf("persist test\n");
1292 result = persistent_test(&avb_ops_);
1293 break;
1294 case 1:
1295 printf("persist wipe\n");
1296 result = persistent_wipe();
1297 break;
1298 case 2:
1299 printf("persist dump\n");
1300 result = persistent_dump();
1301 break;
1302 }
1303 return result;
1304}
1305#endif
1306
Matthew Shyuc710a122023-12-14 00:08:41 -08001307static int do_avb_verify_memory(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
1308{
Matthew Shyuc710a122023-12-14 00:08:41 -08001309 if (argc != 3)
1310 return 0;
1311
1312 if (is_device_unlocked())
1313 return CMD_RET_SUCCESS;
1314
Xindong Xuac88caf2024-10-28 17:10:12 +08001315#ifndef CONFIG_AVB2
1316 return CMD_RET_SUCCESS;
1317#else
Matthew Shyuc4ba2192024-06-19 01:23:35 -07001318 if (strcmp(argv[1], "recovery"))
Matthew Shyuc710a122023-12-14 00:08:41 -08001319 return CMD_RET_FAILURE;
1320
1321 memory_addr = (void *)simple_strtoul(argv[2], NULL, 16);
Matthew Shyuc4ba2192024-06-19 01:23:35 -07001322 recovery_from_memory = 1;
1323 return CMD_RET_SUCCESS;
Xindong Xuac88caf2024-10-28 17:10:12 +08001324#endif
Matthew Shyuc710a122023-12-14 00:08:41 -08001325}
1326
1327static int do_avb_recovery(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
1328{
Matthew Shyuc710a122023-12-14 00:08:41 -08001329 run_in_recovery = 0;
1330
1331 if (argc != 2)
1332 return CMD_RET_FAILURE;
1333
1334 if (is_device_unlocked())
1335 return CMD_RET_SUCCESS;
1336
Xindong Xuac88caf2024-10-28 17:10:12 +08001337#ifndef CONFIG_AVB2
1338 return CMD_RET_SUCCESS;
1339#else
Matthew Shyuc710a122023-12-14 00:08:41 -08001340 if (!strcmp(argv[1], "1"))
1341 run_in_recovery = 1;
1342 else
1343 run_in_recovery = 0;
1344
1345 return CMD_RET_SUCCESS;
Xindong Xuac88caf2024-10-28 17:10:12 +08001346#endif
Matthew Shyuc710a122023-12-14 00:08:41 -08001347}
Matthew Shyu837ffa52024-05-03 01:59:44 -07001348
1349static int do_avb_preload(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
Mingyen Hung6e468002023-01-04 23:43:04 -08001350{
Matthew Shyu837ffa52024-05-03 01:59:44 -07001351 run_in_recovery = 0;
Mingyen Hung6e468002023-01-04 23:43:04 -08001352
Matthew Shyu837ffa52024-05-03 01:59:44 -07001353 if (argc != 2)
1354 return CMD_RET_FAILURE;
Mingyen Hung6e468002023-01-04 23:43:04 -08001355
Xindong Xuac88caf2024-10-28 17:10:12 +08001356#ifndef CONFIG_AVB2
1357 return CMD_RET_SUCCESS;
1358#else
Matthew Shyu837ffa52024-05-03 01:59:44 -07001359 if (!strcmp(argv[1], "1"))
1360 avb_preload = 1;
1361 else
1362 avb_preload = 0;
1363
1364 return CMD_RET_SUCCESS;
Xindong Xuac88caf2024-10-28 17:10:12 +08001365#endif
Mingyen Hung6e468002023-01-04 23:43:04 -08001366}
Matthew Shyuc710a122023-12-14 00:08:41 -08001367
Bo Lv72d0e902023-01-02 14:27:34 +00001368uint32_t avb_get_boot_patchlevel_from_vbmeta(AvbSlotVerifyData *data)
1369{
1370 int i, j;
1371 AvbVBMetaData *p;
1372 const char *ret = NULL;
1373 size_t len = 0;
1374 char buff[9];
1375 unsigned long boot_patchlevel;
1376
1377 if (!data)
1378 return 0;
1379
1380 for (i = 0; i < data->num_vbmeta_images; i++) {
1381 p = &data->vbmeta_images[i];
1382 if (strcmp(p->partition_name, "vbmeta") == 0) { /* match */
1383 if (p->verify_result != AVB_VBMETA_VERIFY_RESULT_OK) {
1384 // not verified
1385 printf("vbmeta verify_result %d\n", p->verify_result);
1386
1387 /*device lock, treat as error*/
1388 if (!is_device_unlocked()) {
1389 printf("device lock, but vbmeta verify fail\n");
1390 return 0;
1391 }
1392 }
1393
1394 ret = avb_property_lookup(p->vbmeta_data,
1395 p->vbmeta_size,
Mingyen Hung6e468002023-01-04 23:43:04 -08001396 "com.android.build.init_boot.security_patch",
1397 0,
1398 &len);
1399 if (ret)
1400 break;
1401
1402 ret = avb_property_lookup(p->vbmeta_data,
1403 p->vbmeta_size,
Bo Lv72d0e902023-01-02 14:27:34 +00001404 "com.android.build.boot.security_patch",
1405 0,
1406 &len);
Bo Lv72d0e902023-01-02 14:27:34 +00001407 if (ret)
1408 break;
Mingyen Hung6e468002023-01-04 23:43:04 -08001409
Bo Lv72d0e902023-01-02 14:27:34 +00001410// else
1411// printf("not found com.android.build.boot.
1412// security_patch,len = %d\n", (int)len);
1413 }
1414 }
1415
1416 if (ret) {
1417 for (i = 0, j = 0; i < len; i++) {
1418 if (ret[i] != '-' && j < 8)
1419 buff[j++] = ret[i];
1420 }
1421 buff[8] = '\0';
1422 if (!strict_strtoul(buff, 10, &boot_patchlevel))
1423 return (uint32_t)boot_patchlevel;
1424 }
1425
1426 return 0;
1427}
1428
1429static cmd_tbl_t cmd_avb_sub[] = {
Mingyen Hung6e468002023-01-04 23:43:04 -08001430 U_BOOT_CMD_MKENT(verify, 0, 0, do_avb_verify, "", ""),
Matthew Shyu837ffa52024-05-03 01:59:44 -07001431#if CONFIG_IS_ENABLED(MMC_MESON_GX)
Mingyen Hung6e468002023-01-04 23:43:04 -08001432 U_BOOT_CMD_MKENT(persist, 2, 0, do_avb_persist, "avb persist test/wipe/dump",
1433 "avb persist test/wipe/dump"),
Matthew Shyu837ffa52024-05-03 01:59:44 -07001434#endif
Matthew Shyuc710a122023-12-14 00:08:41 -08001435 U_BOOT_CMD_MKENT(memory, 4, 0, do_avb_verify_memory, "", ""),
1436 U_BOOT_CMD_MKENT(recovery, 2, 0, do_avb_recovery, "", ""),
Matthew Shyu837ffa52024-05-03 01:59:44 -07001437 U_BOOT_CMD_MKENT(preload, 2, 0, do_avb_preload, "", ""),
Bo Lv72d0e902023-01-02 14:27:34 +00001438};
1439
1440static int do_avb_ops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
1441{
1442 cmd_tbl_t *c;
Matthew Shyuc710a122023-12-14 00:08:41 -08001443 int ret = CMD_RET_SUCCESS;
Bo Lv72d0e902023-01-02 14:27:34 +00001444
Mingyen Hung6e468002023-01-04 23:43:04 -08001445 /* Strip off leading 'avb' command argument */
Bo Lv72d0e902023-01-02 14:27:34 +00001446 argc--;
1447 argv++;
1448
1449 c = find_cmd_tbl(argv[0], &cmd_avb_sub[0], ARRAY_SIZE(cmd_avb_sub));
1450
1451 if (c) {
1452 ret = c->cmd(cmdtp, flag, argc, argv);
1453 } else {
1454 cmd_usage(cmdtp);
Matthew Shyuc710a122023-12-14 00:08:41 -08001455 ret = CMD_RET_FAILURE;
Bo Lv72d0e902023-01-02 14:27:34 +00001456 }
1457
1458 return ret;
1459}
1460
Xindong Xuac88caf2024-10-28 17:10:12 +08001461int do_GetAvbMode(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
1462{
1463#ifdef CONFIG_AVB2
1464 env_set("avb2", "1");
1465#else
1466 env_set("avb2", "0");
1467#endif
1468
1469 return 0;
1470}
1471
1472U_BOOT_CMD
1473(get_avb_mode, 1, 0, do_GetAvbMode,
1474"get_avb_mode",
1475"\nThis command will get avb mode\n"
1476"So you can execute command: get_avb_mode"
1477);
Bo Lv72d0e902023-01-02 14:27:34 +00001478
1479U_BOOT_CMD(
Matthew Shyuc710a122023-12-14 00:08:41 -08001480 avb, 4, 0, do_avb_ops,
Bo Lv72d0e902023-01-02 14:27:34 +00001481 "avb",
1482 "\nThis command will trigger related avb operations\n"
1483 );