blob: b64f3abc37ee5da276635c9d6782b8f91891e7fc [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
Xindong Xu2e748322024-11-22 09:24:46 +0800486#ifdef CONFIG_AVB2_KPUB_VENDOR
487 printf("AVB2 verifying with vendor kpub\n");
488 printf("avb2_kpub_vendor_len = %d\n", avb2_kpub_vendor_len);
489 if (avb2_kpub_vendor_len == public_key_length &&
490 !avb_safe_memcmp(public_key_data,
491 avb2_kpub_vendor, avb2_kpub_vendor_len)) {
492 *out_is_trusted = true;
493 ret = AVB_IO_RESULT_OK;
494 }
495 if (is_device_unlocked())
496 ret = AVB_IO_RESULT_OK;
497
498#ifdef CONFIG_TESTKEY
499 if (ret != AVB_IO_RESULT_OK) {
500 printf("AVB2 re-verify with default kpub\n");
501 if (avb2_kpub_default_len == public_key_length &&
502 !avb_safe_memcmp(public_key_data,
503 avb2_kpub_default, public_key_length)) {
504 *out_is_trusted = true;
505 ret = AVB_IO_RESULT_OK;
506 }
507 }
508#endif
509 if (ret != AVB_IO_RESULT_OK)
510 printf("AVB2 key in bootloader does not match with the key in vbmeta\n");
511 return ret;
512#endif
513
Bo Lv72d0e902023-01-02 14:27:34 +0000514#if CONFIG_AVB2_KPUB_FROM_FIP
515 printf("AVB2 verifying with fip key\n");
516 result = compare_avbkey_with_fipkey(public_key_data, public_key_length);
517 if (result == -2) {
518 printf("AVB2 verified with fip key failed\n");
519 *out_is_trusted = false;
520 ret = AVB_IO_RESULT_OK;
521 return ret;
522 } else if (result == -1) {
523 printf("AVB2 cannot find fip key\n");
524 } else if (result == 0) {
525 printf("AVB2 verified with fip key success\n");
526 *out_is_trusted = true;
527 ret = AVB_IO_RESULT_OK;
528 return ret;
529 }
530#endif
531
532 /*
533 * disable AVB custom key and test key
534 * if device secure boot enabled
535 */
536 if (!IS_FEAT_BOOT_VERIFY()) {
537 key.size = 0;
538 keybuf = (char *)malloc(AVB_CUSTOM_KEY_LEN_MAX);
539 if (keybuf) {
540 memset(keybuf, 0, AVB_CUSTOM_KEY_LEN_MAX);
Matthew Shyu837ffa52024-05-03 01:59:44 -0700541 size = store_logic_cap(partition);
Bo Lv72d0e902023-01-02 14:27:34 +0000542 if (size != 1) {
Matthew Shyu837ffa52024-05-03 01:59:44 -0700543 /* no need workaround for nand. The size is 4K multiple,
544 * and AVB_CUSTOM_KEY_LEN_MAX is 4K. The offset will lay on
545 * 4K boundary.
546 */
547 if (store_logic_read((const char *)partition,
548 size - AVB_CUSTOM_KEY_LEN_MAX,
549 AVB_CUSTOM_KEY_LEN_MAX,
550 (unsigned char *)keybuf) >= 0) {
Bo Lv72d0e902023-01-02 14:27:34 +0000551 memcpy(&key, keybuf, sizeof(AvbKey_t));
552 }
553 }
554 }
555
556 if (keybuf && (strncmp(keybuf, "AVBK", 4) == 0)) {
557 printf("AVB2 verify with avb_custom_key\n");
558 if (key.size == public_key_length &&
559 !avb_safe_memcmp(public_key_data,
560 keybuf + sizeof(AvbKey_t), public_key_length)) {
561 *out_is_trusted = true;
562 ret = AVB_IO_RESULT_OK;
563 }
Jason Tong6a3cca92023-08-24 18:08:17 +0800564 if (is_device_unlocked())
565 ret = AVB_IO_RESULT_OK;
Bo Lv72d0e902023-01-02 14:27:34 +0000566 } else {
567 /**
568 * When the custom key is set
569 * and the device is in the LOCKED state
570 * it will boot images signed with both the built-in key
571 * as well as the custom key
572 */
573 printf("AVB2 verify with default kpub:%d, vbmeta kpub:%ld\n",
574 avb2_kpub_default_len, public_key_length);
575 if (avb2_kpub_default_len == public_key_length &&
576 !avb_safe_memcmp(public_key_data,
577 avb2_kpub_default, public_key_length)) {
578 *out_is_trusted = true;
579 ret = AVB_IO_RESULT_OK;
580 }
581 }
582 } else {
583 printf("AVB2 verify with production kpub:%d, vbmeta kpub:%ld\n",
584 avb2_kpub_production_len, public_key_length);
585 if (avb2_kpub_production_len == public_key_length &&
586 !avb_safe_memcmp(public_key_data,
587 avb2_kpub_production, public_key_length)) {
588 *out_is_trusted = true;
589 ret = AVB_IO_RESULT_OK;
590 }
591 for (i = 0; i < avb2_kpub_production_len; i++) {
592 if (avb2_kpub_production[i] != 0)
593 break;
594 }
595 if (i == avb2_kpub_production_len)
596 printf("ERROR: DID YOU FORGET TO CHANGE AVB2 KEY FOR SECURE BOOT?");
597 }
598
599 if (keybuf)
600 free(keybuf);
601 if (ret != AVB_IO_RESULT_OK)
602 printf("AVB2 key in bootloader does not match with the key in vbmeta\n");
603 return ret;
604}
605
Matthew Shyuc710a122023-12-14 00:08:41 -0800606static AvbIOResult validate_public_key_for_partition(AvbOps *ops,
607 const char *partition,
608 const u8 *public_key_data,
609 size_t public_key_length,
610 const u8 *public_key_metadata,
611 size_t public_key_metadata_length,
612 bool *out_is_trusted,
613 uint32_t *out_rollback_index_location
614)
615{
616 AvbIOResult ret = AVB_IO_RESULT_ERROR_IO;
617
618 if (!ops || !partition || !public_key_data || !out_is_trusted ||
619 !out_rollback_index_location)
620 return AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE;
621
622 *out_is_trusted = false;
623
624 if (!strcmp(partition, "recovery") ||
625 !strcmp(partition, "recovery-memory")) {
626 printf("checking for recovery partition\n");
627 ret = validate_vbmeta_public_key(ops, public_key_data,
628 public_key_length, public_key_metadata,
629 public_key_metadata_length,
630 out_is_trusted);
631 *out_rollback_index_location = RECOVERY_ARB_LOCATION;
632 } else {
633 *out_rollback_index_location = 0;
634 return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
635 }
636
637 return ret;
638}
639
Bo Lv72d0e902023-01-02 14:27:34 +0000640static AvbIOResult read_rollback_index(AvbOps *ops, size_t rollback_index_location,
641 uint64_t *out_rollback_index)
642{
Mingyen Hung6e468002023-01-04 23:43:04 -0800643 AvbIOResult result = AVB_IO_RESULT_OK;
Bo Lv72d0e902023-01-02 14:27:34 +0000644#if defined(CONFIG_AML_ANTIROLLBACK) || defined(CONFIG_AML_AVB2_ANTIROLLBACK)
Mingyen Hung6e468002023-01-04 23:43:04 -0800645 uint32_t version = 0;
Bo Lv72d0e902023-01-02 14:27:34 +0000646#endif
Mingyen Hung6e468002023-01-04 23:43:04 -0800647
648 *out_rollback_index = 0;
649
650#if defined(CONFIG_AML_ANTIROLLBACK) || defined(CONFIG_AML_AVB2_ANTIROLLBACK)
651 if (is_avb_arb_available()) {
652 if (get_avb_antirollback(rollback_index_location, &version)) {
653 *out_rollback_index = version;
654 } else {
655 printf("failed to read rollback index: %zd\n", rollback_index_location);
656 result = AVB_IO_RESULT_ERROR_NO_SUCH_VALUE;
657 }
658 }
659#endif
660
661 return result;
Bo Lv72d0e902023-01-02 14:27:34 +0000662}
663
664static AvbIOResult write_rollback_index(AvbOps* ops, size_t rollback_index_location,
665 uint64_t rollback_index)
666{
667 AvbIOResult result = AVB_IO_RESULT_OK;
Mingyen Hung6e468002023-01-04 23:43:04 -0800668
Bo Lv72d0e902023-01-02 14:27:34 +0000669#if defined(CONFIG_AML_ANTIROLLBACK) || defined(CONFIG_AML_AVB2_ANTIROLLBACK)
670 uint32_t version = rollback_index;
671
Mingyen Hung6e468002023-01-04 23:43:04 -0800672 if (is_avb_arb_available()) {
673 if (!set_avb_antirollback(rollback_index_location, version)) {
674 printf("failed to set rollback index: %zd, version: %u\n",
675 rollback_index_location, version);
676 result = AVB_IO_RESULT_ERROR_NO_SUCH_VALUE;
677 }
Bo Lv72d0e902023-01-02 14:27:34 +0000678 }
Bo Lv72d0e902023-01-02 14:27:34 +0000679#endif
Mingyen Hung6e468002023-01-04 23:43:04 -0800680
Bo Lv72d0e902023-01-02 14:27:34 +0000681 return result;
682}
683
684static AvbIOResult read_is_device_unlocked(AvbOps* ops, bool* out_is_unlocked)
685{
686 AvbIOResult result = AVB_IO_RESULT_OK;
Mingyen Hung6e468002023-01-04 23:43:04 -0800687 LockData_t info = { 0 };
Bo Lv72d0e902023-01-02 14:27:34 +0000688#if defined(CONFIG_AML_ANTIROLLBACK) || defined(CONFIG_AML_AVB2_ANTIROLLBACK)
Mingyen Hung6e468002023-01-04 23:43:04 -0800689 uint32_t lock_state = 0;
690#endif
691 char *lock_s = env_get("lock");
Bo Lv72d0e902023-01-02 14:27:34 +0000692
Mingyen Hung6e468002023-01-04 23:43:04 -0800693 if (!lock_s)
694 return AVB_IO_RESULT_ERROR_IO;
Bo Lv72d0e902023-01-02 14:27:34 +0000695
Mingyen Hung6e468002023-01-04 23:43:04 -0800696#if defined(CONFIG_AML_ANTIROLLBACK) || defined(CONFIG_AML_AVB2_ANTIROLLBACK)
697 if (is_avb_arb_available()) {
698 if (get_avb_lock_state(&lock_state)) {
699 *out_is_unlocked = !lock_state;
700 if (*out_is_unlocked)
701 lock_s[4] = '0';
702 else
703 lock_s[4] = '1';
704 } else {
705 printf("failed to read device lock status from rpmb\n");
706 result = AVB_IO_RESULT_ERROR_IO;
707 }
708 return result;
Bo Lv72d0e902023-01-02 14:27:34 +0000709 }
Mingyen Hung6e468002023-01-04 23:43:04 -0800710#endif
Bo Lv72d0e902023-01-02 14:27:34 +0000711
712 memset(&info, 0, sizeof(struct LockData));
Bo Lv72d0e902023-01-02 14:27:34 +0000713 info.version_major = (int)(lock_s[0] - '0');
714 info.version_minor = (int)(lock_s[1] - '0');
715 info.lock_state = (int)(lock_s[4] - '0');
716 info.lock_critical_state = (int)(lock_s[5] - '0');
717 info.lock_bootloader = (int)(lock_s[6] - '0');
718
719 if (info.lock_state == 1)
720 *out_is_unlocked = false;
721 else
722 *out_is_unlocked = true;
Mingyen Hung6e468002023-01-04 23:43:04 -0800723
Bo Lv72d0e902023-01-02 14:27:34 +0000724 return result;
725}
726
Matthew Shyu837ffa52024-05-03 01:59:44 -0700727#if CONFIG_IS_ENABLED(MMC_MESON_GX)
Mingyen Hung6e468002023-01-04 23:43:04 -0800728/* 4K bytes are allocated to store persistent value
729 * The first 4B is the persistent store magic word "@AVB"
730 * It is further divided into 132B slots
731 * Each 132B contains a persistent_value_t structure.
732 */
733#define AVB_PERSISTENT_MISC_OFFSET (2040 * 1024)
734#define AVB_PERSISTENT_SLOT (31)
735/* 4100 */
736#define AVB_PERSISTENT_SIZE (4 + 4 + 132 * AVB_PERSISTENT_SLOT)
737#define AVB_PERSISTENT_MAGIC "@AVB"
738#define AVB_PERSISTENT_VERSION (0x0)
739#define PERSISTENT_NAME_MAX_LEN (64)
740#define PERSISTENT_VALUE_MAX_LEN (64)
741#define PERSISTENT_FILENAME "avb_persist"
742
743#define DEV_NAME "mmc"
744#define DEV_NO (1)
745#define PART_TYPE "user"
746#define PART_NAME_RSV "rsv"
747#define PART_NAME_FTY "factory"
748#define NAND_FTY_MOUNT_PT "mnt"
749
750struct persistent_value {
751 uint8_t name_length;
752 uint8_t value_length;
753 uint16_t rsv;
754 char name[PERSISTENT_NAME_MAX_LEN];
755 uint8_t value[PERSISTENT_VALUE_MAX_LEN];
756};
757
758static uint8_t *persistent_store(int32_t *is_empty)
759{
760 uint8_t *buf = NULL;
761 int rc = 0;
762 loff_t act_read = 0;
763
764 /* initialize factory partition */
765 rc = run_command("factory_provision init", 0);
766 if (rc) {
767 printf("init factory partition failed\n");
768 return NULL;
769 }
770
771 buf = malloc(AVB_PERSISTENT_SIZE);
772 if (!buf) {
773 printf("failed to allocate buf for persistent store\n");
774 return NULL;
775 }
776 if (fat_read_file(PERSISTENT_FILENAME, buf, 0,
777 AVB_PERSISTENT_SIZE, &act_read)) {
778 printf("failed to read persistent store\n");
779 goto empty;
780 } else {
781 if (act_read != AVB_PERSISTENT_SIZE) {
782 printf("unexpected size: %lld\n", act_read);
783 memset(buf, 0, AVB_PERSISTENT_SIZE);
784 goto empty;
785 }
786 }
787
788empty:
789 if (memcmp(&buf[0], AVB_PERSISTENT_MAGIC, 4)) {
790 printf("empty persistent store, resetting\n");
791 memset(buf, 0, AVB_PERSISTENT_SIZE);
792 memcpy(&buf[0], AVB_PERSISTENT_MAGIC, 4);
793 if (is_empty)
794 *is_empty = 1;
795 } else {
796 if (is_empty)
797 *is_empty = 0;
798 }
799
800 return buf;
801}
802
803static AvbIOResult persistent_test(AvbOps *ops)
804{
805 AvbIOResult ret = AVB_IO_RESULT_OK;
806 static const char case_I[] = "smart wolves";
807 static const char case_II[] = "happy wife";
808 static const char case_III[] = "lion king";
809 char case_I_read[sizeof(case_I)] = {0};
810 char case_II_read[sizeof(case_II)] = {0};
811 char case_III_read[sizeof(case_III)] = {0};
812 size_t out_num_bytes_read = 0;
813
814 ret = ops->write_persistent_value(ops, "persist test case I",
815 sizeof(case_I), (const uint8_t *)case_I);
816 if (ret != AVB_IO_RESULT_OK) {
817 printf("failed to write case I\n");
818 return ret;
819 }
820 ret = ops->write_persistent_value(ops, "persist test case II",
821 sizeof(case_II), (const uint8_t *)case_II);
822 if (ret != AVB_IO_RESULT_OK) {
823 printf("failed to write case II\n");
824 return ret;
825 }
826 ret = ops->write_persistent_value(ops, "persist test case III",
827 sizeof(case_III), (const uint8_t *)case_III);
828 if (ret != AVB_IO_RESULT_OK) {
829 printf("failed to write case III\n");
830 return ret;
831 }
832
833 ret = ops->read_persistent_value(ops, "persist test case I",
834 sizeof(case_I_read), (uint8_t *)case_I_read, &out_num_bytes_read);
835 if (ret != AVB_IO_RESULT_OK) {
836 printf("failed to read case I\n");
837 return ret;
838 }
839 if (out_num_bytes_read == sizeof(case_I_read) &&
840 !strncmp(case_I, case_I_read, sizeof(case_I))) {
841 printf("case I passed\n");
842 } else {
843 printf("case I failed\n");
844 }
845
846 ret = ops->read_persistent_value(ops, "persist test case II",
847 sizeof(case_II_read), (uint8_t *)case_II_read,
848 &out_num_bytes_read);
849 if (ret != AVB_IO_RESULT_OK) {
850 printf("failed to read case II\n");
851 return ret;
852 }
853 if (out_num_bytes_read == sizeof(case_II_read) &&
854 !strncmp(case_II, case_II_read, sizeof(case_II))) {
855 printf("case II passed\n");
856 } else {
857 printf("case II failed\n");
858 }
859
860 ret = ops->read_persistent_value(ops, "persist test case III",
861 sizeof(case_III_read), (uint8_t *)case_III_read,
862 &out_num_bytes_read);
863 if (ret != AVB_IO_RESULT_OK) {
864 printf("failed to read case III\n");
865 return ret;
866 }
867 if (out_num_bytes_read == sizeof(case_III_read) &&
868 !strncmp(case_III, case_III_read, sizeof(case_III))) {
869 printf("case III passed\n");
870 } else {
871 printf("case III failed\n");
872 }
873
874 return ret;
875}
Matthew Shyu837ffa52024-05-03 01:59:44 -0700876#endif
Mingyen Hung6e468002023-01-04 23:43:04 -0800877
Matthew Shyu837ffa52024-05-03 01:59:44 -0700878#if CONFIG_IS_ENABLED(MMC_MESON_GX)
Mingyen Hung6e468002023-01-04 23:43:04 -0800879uint32_t create_csrs(void)
880{
881 int part_num = get_partition_num_by_name(PART_NAME_FTY);
882 char part_name[32] = {0};
883 char cmd[64] = {0};
884 uint8_t buf[1] = {0};
885
886 if (part_num >= 0)
887 strcpy(part_name, PART_NAME_FTY);
888 else
889 strcpy(part_name, PART_NAME_RSV);
890
891 sprintf(cmd, "fatmkdir %s 0x%X:0x%X %s", DEV_NAME, DEV_NO,
892 get_partition_num_by_name(part_name), "csrs");
893 if (run_command(cmd, 0)) {
894 printf("command[%s] failed\n", cmd);
895 return AVB_IO_RESULT_ERROR_IO;
896 }
897
898 memset(cmd, 0, sizeof(cmd));
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), "csrs/csrs.json", 1);
903 if (run_command(cmd, 0)) {
904 printf("command[%s] failed\n", cmd);
905 return AVB_IO_RESULT_ERROR_IO;
906 }
907 return AVB_IO_RESULT_OK;
908}
Matthew Shyu837ffa52024-05-03 01:59:44 -0700909#else
910uint32_t create_csrs(void)
911{
912 return AVB_IO_RESULT_OK;
913}
914#endif
Mingyen Hung6e468002023-01-04 23:43:04 -0800915
Matthew Shyu837ffa52024-05-03 01:59:44 -0700916#if CONFIG_IS_ENABLED(MMC_MESON_GX)
Mingyen Hung6e468002023-01-04 23:43:04 -0800917static AvbIOResult write_persistent_to_factory(uint8_t *buf, uint32_t size)
918{
919 int part_num = get_partition_num_by_name(PART_NAME_FTY);
920 char part_name[32] = {0};
921 char cmd[64] = {0};
922
923 if (part_num >= 0)
924 strcpy(part_name, PART_NAME_FTY);
925 else
926 strcpy(part_name, PART_NAME_RSV);
927
928 sprintf(cmd, "fatwrite %s 0x%X:0x%X 0x%08X %s 0x%X", DEV_NAME, DEV_NO,
929 get_partition_num_by_name(part_name),
930 (uint32_t)virt_to_phys((void *)buf), PERSISTENT_FILENAME, size);
931 if (run_command(cmd, 0)) {
932 printf("command[%s] failed\n", cmd);
933 return AVB_IO_RESULT_ERROR_IO;
934 }
935
936 return AVB_IO_RESULT_OK;
937}
938
939static AvbIOResult persistent_wipe(void)
940{
941 uint8_t *buf = NULL;
942 AvbIOResult ret = AVB_IO_RESULT_OK;
943
944 buf = persistent_store(NULL);
945 if (buf) {
946 memset(buf, 0, AVB_PERSISTENT_SIZE);
947 memcpy(&buf[0], AVB_PERSISTENT_MAGIC, 4);
948 *(uint32_t *)&buf[4] = AVB_PERSISTENT_VERSION;
949 } else {
950 return AVB_IO_RESULT_ERROR_IO;
951 }
952
953 ret = write_persistent_to_factory(buf, AVB_PERSISTENT_SIZE);
954
955 free(buf);
956 return ret;
957}
958
959static AvbIOResult persistent_dump(void)
960{
961 uint8_t *buf = NULL;
962 int rc = 0;
963 AvbIOResult ret = AVB_IO_RESULT_OK;
964 char *name = NULL;
965 int i = 0;
966 char cmd[64] = {0};
967 struct persistent_value *persist = NULL;
968
969 buf = persistent_store(NULL);
970 if (buf) {
971 printf("persistent store:\n");
972 /* skip magic word and version */
973 persist = (struct persistent_value *)(buf + 8);
974 for (i = 0; i < AVB_PERSISTENT_SLOT; i++) {
975 printf("%d:\n", i);
976 if (persist[i].name_length) {
977 name = malloc(persist[i].name_length);
978 if (!name) {
979 printf("failed to allocate name\n");
980 goto out;
981 }
982 strncpy(name, persist[i].name,
983 persist[i].name_length);
984 printf("%s\n", name);
985 free(name);
986 printf("length = %d\n",
987 persist[i].value_length);
988 snprintf(cmd, sizeof(cmd),
989 "md.b %p %x", persist[i].value,
990 persist[i].value_length);
991 rc = run_command(cmd, 0);
992 if (rc) {
993 printf("failed to run cmd: %s\n", cmd);
994 ret = AVB_IO_RESULT_ERROR_IO;
995 goto out;
996 }
997 } else {
998 printf("empty slot\n");
999 }
1000 }
1001 } else {
1002 return AVB_IO_RESULT_ERROR_IO;
1003 }
1004
1005out:
1006 free(buf);
1007 return ret;
1008}
1009
1010AvbIOResult read_persistent_value(AvbOps *ops, const char *name,
1011 size_t buffer_size, uint8_t *out_buffer, size_t *out_num_bytes_read)
1012{
1013 uint8_t *buf = NULL;
1014 uint32_t value_found = 0;
1015 uint32_t i = 0;
1016 struct persistent_value *persist = NULL;
1017 AvbIOResult ret = AVB_IO_RESULT_OK;
1018 AvbIOResult ret_write = AVB_IO_RESULT_OK;
1019 int32_t is_empty = 0;
1020
1021 if (!out_buffer) {
1022 if (!buffer_size)
1023 return AVB_IO_RESULT_OK;
1024 else
1025 return AVB_IO_RESULT_ERROR_IO;
1026 }
1027
1028 buf = persistent_store(&is_empty);
1029 if (buf) {
1030 /* skip magic word and version */
1031 persist = (struct persistent_value *)(buf + 8);
1032 for (i = 0; i < AVB_PERSISTENT_SLOT; i++) {
1033 if (strlen(name) == persist[i].name_length &&
1034 !strncmp(persist[i].name, name, persist[i].name_length)) {
1035 if (buffer_size >= persist[i].value_length) {
1036 memcpy(out_buffer, persist[i].value,
1037 persist[i].value_length);
1038 *out_num_bytes_read = persist[i].value_length;
1039 ret = AVB_IO_RESULT_OK;
1040 } else {
1041 ret = AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE;
1042 *out_num_bytes_read = persist[i].value_length;
1043 }
1044 value_found = 1;
1045 break;
1046 }
1047 }
1048 if (!value_found)
1049 ret = AVB_IO_RESULT_ERROR_NO_SUCH_VALUE;
1050 } else {
1051 ret = AVB_IO_RESULT_ERROR_IO;
1052 }
1053
1054 /* write storage, if empty */
1055 if (is_empty) {
1056 ret_write = write_persistent_to_factory(buf, AVB_PERSISTENT_SIZE);
1057 if (ret_write != AVB_IO_RESULT_OK)
1058 printf("failed to write empty persistent data\n");
1059 }
1060
1061 free(buf);
1062 return ret;
1063}
1064
1065AvbIOResult write_persistent_value(AvbOps *ops, const char *name,
1066 size_t value_size, const uint8_t *value)
1067{
1068 uint8_t *buf = NULL;
1069 struct persistent_value *empty_slot = NULL;
1070 uint32_t value_found = 0;
1071 uint32_t i = 0;
1072 struct persistent_value *persist = NULL;
1073 AvbIOResult ret = AVB_IO_RESULT_OK;
1074
1075 if (value_size > PERSISTENT_VALUE_MAX_LEN)
1076 return AVB_IO_RESULT_ERROR_INVALID_VALUE_SIZE;
1077 if (strlen(name) > PERSISTENT_NAME_MAX_LEN)
1078 return AVB_IO_RESULT_ERROR_NO_SUCH_VALUE;
1079
1080 buf = persistent_store(NULL);
1081 if (buf) {
1082 /* skip magic word and version */
1083 persist = (struct persistent_value *)(buf + 8);
1084 for (i = 0; i < AVB_PERSISTENT_SLOT; i++) {
1085 if (!persist[i].name_length) {
1086 if (!empty_slot)
1087 empty_slot = &persist[i];
1088 } else {
1089 if (strlen(name) == persist[i].name_length &&
1090 !strncmp(persist[i].name, name,
1091 persist[i].name_length)) {
1092 memset(persist[i].value, 0, sizeof(persist[i].value));
1093 memcpy(persist[i].value, value, value_size);
1094 persist[i].value_length = value_size;
1095 value_found = 1;
1096 break;
1097 }
1098 }
1099 }
1100 if (!value_found) {
1101 if (empty_slot) {
1102 empty_slot->name_length = strlen(name);
1103 memset(empty_slot->name, 0, sizeof(empty_slot->name));
1104 memcpy(empty_slot->name, name, empty_slot->name_length);
1105 memset(empty_slot->value, 0, sizeof(empty_slot->value));
1106 memcpy(empty_slot->value, value, value_size);
1107 empty_slot->value_length = value_size;
1108 } else {
1109 printf("no more slots\n");
1110 ret = AVB_IO_RESULT_ERROR_IO;
1111 goto out;
1112 }
1113 }
1114 } else {
1115 ret = AVB_IO_RESULT_ERROR_IO;
1116 goto out;
1117 }
1118 ret = write_persistent_to_factory(buf, AVB_PERSISTENT_SIZE);
1119
1120out:
1121 free(buf);
1122 return ret;
1123}
Matthew Shyu837ffa52024-05-03 01:59:44 -07001124#endif
Mingyen Hung6e468002023-01-04 23:43:04 -08001125
Bo Lv72d0e902023-01-02 14:27:34 +00001126static int avb_init(void)
1127{
Matthew Shyu837ffa52024-05-03 01:59:44 -07001128 int factory_part_num = -1;
1129#if CONFIG_IS_ENABLED(MMC_MESON_GX)
1130 /* partition name is valid */
1131 if (find_mmc_partition_by_name(PART_NAME_FTY))
1132 factory_part_num = get_partition_num_by_name(PART_NAME_FTY);
1133#endif
Mingyen Hung6e468002023-01-04 23:43:04 -08001134 enum boot_type_e type = store_get_type();
Bo Lv72d0e902023-01-02 14:27:34 +00001135
1136 memset(&avb_ops_, 0, sizeof(AvbOps));
1137 avb_ops_.read_from_partition = read_from_partition;
Matthew Shyu837ffa52024-05-03 01:59:44 -07001138 avb_ops_.get_preloaded_partition = get_preloaded_partition;
Bo Lv72d0e902023-01-02 14:27:34 +00001139 avb_ops_.write_to_partition = write_to_partition;
1140 avb_ops_.validate_vbmeta_public_key = validate_vbmeta_public_key;
1141 avb_ops_.read_rollback_index = read_rollback_index;
1142 avb_ops_.write_rollback_index = write_rollback_index;
1143 avb_ops_.read_is_device_unlocked = read_is_device_unlocked;
1144 avb_ops_.get_unique_guid_for_partition = get_unique_guid_for_partition;
1145 avb_ops_.get_size_of_partition = get_size_of_partition;
Matthew Shyuc710a122023-12-14 00:08:41 -08001146 avb_ops_.validate_public_key_for_partition = validate_public_key_for_partition;
Matthew Shyu837ffa52024-05-03 01:59:44 -07001147
Mingyen Hung6e468002023-01-04 23:43:04 -08001148 if (type == BOOT_NAND_MTD || type == BOOT_SNAND || factory_part_num < 0) {
1149 avb_ops_.read_persistent_value = NULL;
1150 avb_ops_.write_persistent_value = NULL;
1151 } else {
Matthew Shyu837ffa52024-05-03 01:59:44 -07001152#if CONFIG_IS_ENABLED(MMC_MESON_GX)
Mingyen Hung6e468002023-01-04 23:43:04 -08001153 avb_ops_.read_persistent_value = read_persistent_value;
1154 avb_ops_.write_persistent_value = write_persistent_value;
Matthew Shyu837ffa52024-05-03 01:59:44 -07001155#else
1156 avb_ops_.read_persistent_value = NULL;
1157 avb_ops_.write_persistent_value = NULL;
1158#endif
Mingyen Hung6e468002023-01-04 23:43:04 -08001159 }
Bo Lv72d0e902023-01-02 14:27:34 +00001160
1161 return 0;
1162}
1163
1164int is_device_unlocked(void)
1165{
1166 AvbIOResult ret;
1167 bool out_is_unlocked;
1168
1169 ret = read_is_device_unlocked(&avb_ops_, &out_is_unlocked);
1170 if (ret == AVB_IO_RESULT_OK)
1171 return out_is_unlocked;
1172 else
1173 return 0;
1174}
1175
1176int avb_verify(AvbSlotVerifyData** out_data)
1177{
Matthew Shyu88b14432024-07-09 00:16:28 -07001178 /* The last slot must be NULL */
1179 const char *requested_partitions[AVB_NUM_SLOT + 1] = {"boot", "dt", "dtbo",
1180 "init_boot", "vendor_boot", NULL, NULL};
Bo Lv72d0e902023-01-02 14:27:34 +00001181 AvbSlotVerifyResult result = AVB_SLOT_VERIFY_RESULT_OK;
1182 char *s1 = NULL;
1183 char *ab_suffix = NULL;
Matthew Shyu837ffa52024-05-03 01:59:44 -07001184 int factory_part_num = -1;
Matthew Shyu837ffa52024-05-03 01:59:44 -07001185
Mingyen Hung6e468002023-01-04 23:43:04 -08001186 AvbHashtreeErrorMode hashtree_error_mode =
1187 AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE;
Matthew Shyu837ffa52024-05-03 01:59:44 -07001188#if CONFIG_IS_ENABLED(MMC_MESON_GX)
1189 /* partition name is valid */
1190 if (find_mmc_partition_by_name(PART_NAME_FTY))
1191 factory_part_num = get_partition_num_by_name(PART_NAME_FTY);
1192#endif
Mingyen Hung6e468002023-01-04 23:43:04 -08001193 enum boot_type_e type = store_get_type();
Bo Lv72d0e902023-01-02 14:27:34 +00001194
1195 s1 = env_get("active_slot");
1196 if (!s1) {
1197 run_command("get_valid_slot;", 0);
1198 s1 = env_get("active_slot");
1199 }
1200 if (s1) {
1201 printf("active_slot is %s\n", s1);
1202 if (!strcmp(s1, "normal"))
1203 ab_suffix = "";
1204 else
1205 ab_suffix = env_get("active_slot");
1206 }
1207
1208 if (!ab_suffix)
1209 ab_suffix = "";
1210 printf("ab_suffix is %s\n", ab_suffix);
1211
Bo Lv72d0e902023-01-02 14:27:34 +00001212 AvbSlotVerifyFlags flags = AVB_SLOT_VERIFY_FLAGS_NONE;
Bo Lv72d0e902023-01-02 14:27:34 +00001213
1214 avb_init();
1215
Matthew Shyufcd728f2023-12-07 01:44:32 -08001216 if (is_device_unlocked())
Bo Lv72d0e902023-01-02 14:27:34 +00001217 flags |= AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR;
1218
Matthew Shyuc710a122023-12-14 00:08:41 -08001219 if (!strcmp(ab_suffix, "")) {
1220 printf("recovery: %d\n", run_in_recovery);
1221 if (run_in_recovery) {
1222 flags |= AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION;
1223 memset(requested_partitions, 0, sizeof(requested_partitions));
Matthew Shyuc4ba2192024-06-19 01:23:35 -07001224 if (recovery_from_memory)
1225 requested_partitions[0] = "recovery-memory";
1226 else
1227 requested_partitions[0] = "recovery";
1228 recovery_from_memory = 0;
Matthew Shyuc710a122023-12-14 00:08:41 -08001229 }
1230 }
Matthew Shyu837ffa52024-05-03 01:59:44 -07001231
Mingyen Hung6e468002023-01-04 23:43:04 -08001232 if (type == BOOT_NAND_MTD || type == BOOT_SNAND || factory_part_num < 0)
1233 hashtree_error_mode =
1234 AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE;
1235 else
1236 hashtree_error_mode =
1237 AVB_HASHTREE_ERROR_MODE_MANAGED_RESTART_AND_EIO;
Matthew Shyuc710a122023-12-14 00:08:41 -08001238
Matthew Shyu88b14432024-07-09 00:16:28 -07001239 result = avb_slot_verify(&avb_ops_, requested_partitions, ab_suffix,
1240 flags, hashtree_error_mode, out_data);
Bo Lv72d0e902023-01-02 14:27:34 +00001241
Matthew Shyu837ffa52024-05-03 01:59:44 -07001242 clear_avb_parts();
1243
Matthew Shyu88b14432024-07-09 00:16:28 -07001244 run_in_recovery = 0;
Bo Lv72d0e902023-01-02 14:27:34 +00001245 return result;
Bo Lv72d0e902023-01-02 14:27:34 +00001246}
1247
1248static int do_avb_verify(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
1249{
1250 AvbSlotVerifyResult result = AVB_SLOT_VERIFY_RESULT_OK;
1251 AvbSlotVerifyData *out_data = NULL;
1252 uint32_t i = 0;
Mingyen Hung6e468002023-01-04 23:43:04 -08001253#if defined(CONFIG_AML_ANTIROLLBACK) || defined(CONFIG_AML_AVB2_ANTIROLLBACK)
1254 uint32_t version = 0;
1255 uint32_t lock_state = 0;
1256#endif
Bo Lv72d0e902023-01-02 14:27:34 +00001257
1258 result = (AvbSlotVerifyResult)avb_verify(&out_data);
1259
1260 printf("result: %d\n", result);
1261 if (result == AVB_SLOT_VERIFY_RESULT_OK && out_data) {
Bo Lv72d0e902023-01-02 14:27:34 +00001262 printf("ab_suffix: %s\n", out_data->ab_suffix);
1263 printf("vbmeta: name: %s, size: %zd, result: %d\n",
1264 out_data->vbmeta_images->partition_name,
1265 out_data->vbmeta_images->vbmeta_size,
1266 out_data->vbmeta_images->verify_result);
1267 printf("num of vbmeta: %zd\n", out_data->num_vbmeta_images);
1268 printf("loaded name: %s, size: %zd, preload: %d\n",
1269 out_data->loaded_partitions->partition_name,
1270 out_data->loaded_partitions->data_size,
1271 out_data->loaded_partitions->preloaded);
1272 printf("num of loaded: %zd\n", out_data->num_loaded_partitions);
1273 printf("cmdline: %s\n", out_data->cmdline);
1274 for (i = 0; i < AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS; i++)
1275 printf("rollback(%d) = %llu\n", i, out_data->rollback_indexes[i]);
1276
1277#if defined(CONFIG_AML_ANTIROLLBACK) || defined(CONFIG_AML_AVB2_ANTIROLLBACK)
Mingyen Hung6e468002023-01-04 23:43:04 -08001278 if (is_avb_arb_available()) {
1279 for (i = 0; i < AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS; i++)
1280 if (get_avb_antirollback(i, &version))
1281 printf("rpmb rollback(%d) = %u\n", i, version);
1282 if (get_avb_lock_state(&lock_state))
1283 printf("rpmb lock state: %u\n", lock_state);
1284 }
Bo Lv72d0e902023-01-02 14:27:34 +00001285#endif
1286
1287 avb_slot_verify_data_free(out_data);
1288 }
1289
1290 return result;
1291}
1292
Matthew Shyu837ffa52024-05-03 01:59:44 -07001293#if CONFIG_IS_ENABLED(MMC_MESON_GX)
1294static int do_avb_persist(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
1295{
1296 int result = 0;
1297 u32 cmd = 0;
1298
1299 if (argc != 2) {
1300 printf("invalid argc: %d\n", argc);
1301 return -1;
1302 }
1303
1304 avb_init();
1305
1306 if (!strcmp(argv[1], "test")) {
1307 cmd = 0;
1308 } else if (!strcmp(argv[1], "wipe")) {
1309 cmd = 1;
1310 } else if (!strcmp(argv[1], "dump")) {
1311 cmd = 2;
1312 } else {
1313 printf("unknown cmd: %s\n", argv[1]);
1314 return -1;
1315 }
1316
1317 switch (cmd) {
1318 case 0:
1319 printf("persist test\n");
1320 result = persistent_test(&avb_ops_);
1321 break;
1322 case 1:
1323 printf("persist wipe\n");
1324 result = persistent_wipe();
1325 break;
1326 case 2:
1327 printf("persist dump\n");
1328 result = persistent_dump();
1329 break;
1330 }
1331 return result;
1332}
1333#endif
1334
Matthew Shyuc710a122023-12-14 00:08:41 -08001335static int do_avb_verify_memory(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
1336{
Matthew Shyuc710a122023-12-14 00:08:41 -08001337 if (argc != 3)
1338 return 0;
1339
1340 if (is_device_unlocked())
1341 return CMD_RET_SUCCESS;
1342
Xindong Xuac88caf2024-10-28 17:10:12 +08001343#ifndef CONFIG_AVB2
1344 return CMD_RET_SUCCESS;
1345#else
Matthew Shyuc4ba2192024-06-19 01:23:35 -07001346 if (strcmp(argv[1], "recovery"))
Matthew Shyuc710a122023-12-14 00:08:41 -08001347 return CMD_RET_FAILURE;
1348
1349 memory_addr = (void *)simple_strtoul(argv[2], NULL, 16);
Matthew Shyuc4ba2192024-06-19 01:23:35 -07001350 recovery_from_memory = 1;
1351 return CMD_RET_SUCCESS;
Xindong Xuac88caf2024-10-28 17:10:12 +08001352#endif
Matthew Shyuc710a122023-12-14 00:08:41 -08001353}
1354
1355static int do_avb_recovery(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
1356{
Matthew Shyuc710a122023-12-14 00:08:41 -08001357 run_in_recovery = 0;
1358
1359 if (argc != 2)
1360 return CMD_RET_FAILURE;
1361
1362 if (is_device_unlocked())
1363 return CMD_RET_SUCCESS;
1364
Xindong Xuac88caf2024-10-28 17:10:12 +08001365#ifndef CONFIG_AVB2
1366 return CMD_RET_SUCCESS;
1367#else
Matthew Shyuc710a122023-12-14 00:08:41 -08001368 if (!strcmp(argv[1], "1"))
1369 run_in_recovery = 1;
1370 else
1371 run_in_recovery = 0;
1372
1373 return CMD_RET_SUCCESS;
Xindong Xuac88caf2024-10-28 17:10:12 +08001374#endif
Matthew Shyuc710a122023-12-14 00:08:41 -08001375}
Matthew Shyu837ffa52024-05-03 01:59:44 -07001376
1377static int do_avb_preload(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
Mingyen Hung6e468002023-01-04 23:43:04 -08001378{
Matthew Shyu837ffa52024-05-03 01:59:44 -07001379 run_in_recovery = 0;
Mingyen Hung6e468002023-01-04 23:43:04 -08001380
Matthew Shyu837ffa52024-05-03 01:59:44 -07001381 if (argc != 2)
1382 return CMD_RET_FAILURE;
Mingyen Hung6e468002023-01-04 23:43:04 -08001383
Xindong Xuac88caf2024-10-28 17:10:12 +08001384#ifndef CONFIG_AVB2
1385 return CMD_RET_SUCCESS;
1386#else
Matthew Shyu837ffa52024-05-03 01:59:44 -07001387 if (!strcmp(argv[1], "1"))
1388 avb_preload = 1;
1389 else
1390 avb_preload = 0;
1391
1392 return CMD_RET_SUCCESS;
Xindong Xuac88caf2024-10-28 17:10:12 +08001393#endif
Mingyen Hung6e468002023-01-04 23:43:04 -08001394}
Matthew Shyuc710a122023-12-14 00:08:41 -08001395
Bo Lv72d0e902023-01-02 14:27:34 +00001396uint32_t avb_get_boot_patchlevel_from_vbmeta(AvbSlotVerifyData *data)
1397{
1398 int i, j;
1399 AvbVBMetaData *p;
1400 const char *ret = NULL;
1401 size_t len = 0;
1402 char buff[9];
1403 unsigned long boot_patchlevel;
1404
1405 if (!data)
1406 return 0;
1407
1408 for (i = 0; i < data->num_vbmeta_images; i++) {
1409 p = &data->vbmeta_images[i];
1410 if (strcmp(p->partition_name, "vbmeta") == 0) { /* match */
1411 if (p->verify_result != AVB_VBMETA_VERIFY_RESULT_OK) {
1412 // not verified
1413 printf("vbmeta verify_result %d\n", p->verify_result);
1414
1415 /*device lock, treat as error*/
1416 if (!is_device_unlocked()) {
1417 printf("device lock, but vbmeta verify fail\n");
1418 return 0;
1419 }
1420 }
1421
1422 ret = avb_property_lookup(p->vbmeta_data,
1423 p->vbmeta_size,
Mingyen Hung6e468002023-01-04 23:43:04 -08001424 "com.android.build.init_boot.security_patch",
1425 0,
1426 &len);
1427 if (ret)
1428 break;
1429
1430 ret = avb_property_lookup(p->vbmeta_data,
1431 p->vbmeta_size,
Bo Lv72d0e902023-01-02 14:27:34 +00001432 "com.android.build.boot.security_patch",
1433 0,
1434 &len);
Bo Lv72d0e902023-01-02 14:27:34 +00001435 if (ret)
1436 break;
Mingyen Hung6e468002023-01-04 23:43:04 -08001437
Bo Lv72d0e902023-01-02 14:27:34 +00001438// else
1439// printf("not found com.android.build.boot.
1440// security_patch,len = %d\n", (int)len);
1441 }
1442 }
1443
1444 if (ret) {
1445 for (i = 0, j = 0; i < len; i++) {
1446 if (ret[i] != '-' && j < 8)
1447 buff[j++] = ret[i];
1448 }
1449 buff[8] = '\0';
1450 if (!strict_strtoul(buff, 10, &boot_patchlevel))
1451 return (uint32_t)boot_patchlevel;
1452 }
1453
1454 return 0;
1455}
1456
1457static cmd_tbl_t cmd_avb_sub[] = {
Mingyen Hung6e468002023-01-04 23:43:04 -08001458 U_BOOT_CMD_MKENT(verify, 0, 0, do_avb_verify, "", ""),
Matthew Shyu837ffa52024-05-03 01:59:44 -07001459#if CONFIG_IS_ENABLED(MMC_MESON_GX)
Mingyen Hung6e468002023-01-04 23:43:04 -08001460 U_BOOT_CMD_MKENT(persist, 2, 0, do_avb_persist, "avb persist test/wipe/dump",
1461 "avb persist test/wipe/dump"),
Matthew Shyu837ffa52024-05-03 01:59:44 -07001462#endif
Matthew Shyuc710a122023-12-14 00:08:41 -08001463 U_BOOT_CMD_MKENT(memory, 4, 0, do_avb_verify_memory, "", ""),
1464 U_BOOT_CMD_MKENT(recovery, 2, 0, do_avb_recovery, "", ""),
Matthew Shyu837ffa52024-05-03 01:59:44 -07001465 U_BOOT_CMD_MKENT(preload, 2, 0, do_avb_preload, "", ""),
Bo Lv72d0e902023-01-02 14:27:34 +00001466};
1467
1468static int do_avb_ops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
1469{
1470 cmd_tbl_t *c;
Matthew Shyuc710a122023-12-14 00:08:41 -08001471 int ret = CMD_RET_SUCCESS;
Bo Lv72d0e902023-01-02 14:27:34 +00001472
Mingyen Hung6e468002023-01-04 23:43:04 -08001473 /* Strip off leading 'avb' command argument */
Bo Lv72d0e902023-01-02 14:27:34 +00001474 argc--;
1475 argv++;
1476
1477 c = find_cmd_tbl(argv[0], &cmd_avb_sub[0], ARRAY_SIZE(cmd_avb_sub));
1478
1479 if (c) {
1480 ret = c->cmd(cmdtp, flag, argc, argv);
1481 } else {
1482 cmd_usage(cmdtp);
Matthew Shyuc710a122023-12-14 00:08:41 -08001483 ret = CMD_RET_FAILURE;
Bo Lv72d0e902023-01-02 14:27:34 +00001484 }
1485
1486 return ret;
1487}
1488
Xindong Xuac88caf2024-10-28 17:10:12 +08001489int do_GetAvbMode(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
1490{
1491#ifdef CONFIG_AVB2
1492 env_set("avb2", "1");
1493#else
1494 env_set("avb2", "0");
1495#endif
1496
1497 return 0;
1498}
1499
1500U_BOOT_CMD
1501(get_avb_mode, 1, 0, do_GetAvbMode,
1502"get_avb_mode",
1503"\nThis command will get avb mode\n"
1504"So you can execute command: get_avb_mode"
1505);
Bo Lv72d0e902023-01-02 14:27:34 +00001506
1507U_BOOT_CMD(
Matthew Shyuc710a122023-12-14 00:08:41 -08001508 avb, 4, 0, do_avb_ops,
Bo Lv72d0e902023-01-02 14:27:34 +00001509 "avb",
1510 "\nThis command will trigger related avb operations\n"
1511 );