blob: 9350ff52144e201705a1aebec75ee6bcdaa55e40 [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;
Bo Lv72d0e902023-01-02 14:27:34 +000060
Matthew Shyu837ffa52024-05-03 01:59:44 -070061struct avb_part {
62 char name[16];
63 u8 *addr;
64 size_t length;
65};
66
67struct avb_part parts[AVB_NUM_SLOT];
68u32 avb_part_num;
69bool avb_preload = true;
70
71void set_avb_parts(const char *partname, uint8_t *addr, size_t length)
72{
73 struct avb_part *part = NULL;
74
75 if (!is_device_unlocked() && avb_preload) {
76 assert(avb_part_num < AVB_NUM_SLOT);
77
78 part = &parts[avb_part_num];
79 memset(part->name, 0, sizeof(part->name));
80 strlcpy(part->name, partname, sizeof(part->name));
81 part->addr = malloc(length);
82 if (part->addr) {
83 memcpy(part->addr, addr, length);
84 part->length = length;
85 avb_part_num++;
86 }
87 }
88}
89
90void clear_avb_parts(void)
91{
92 struct avb_part *part = NULL;
93 u32 i = 0;
94
95 if (!is_device_unlocked()) {
96 for (i = 0; i < avb_part_num; i++) {
97 part = &parts[i];
98 memset(part->name, 0, sizeof(part->name));
99 if (part->addr) {
100 free(part->addr);
101 part->addr = NULL;
102 part->length = 0;
103 }
104 }
105 }
106 avb_part_num = 0;
107}
108
109u64 get_size_avb_footer(const char *partname)
110{
111 AvbFooter footer_src, footer_desc;
112 u64 rc = 0;
113 enum boot_type_e type = store_get_type();
114 u32 read_size = 512;
115 u8 read_buf[NAND_PAGE_SIZE];
116
117 if (!partname)
118 return 0;
119
120 if (type == BOOT_NAND_MTD || type == BOOT_SNAND)
121 read_size = NAND_PAGE_SIZE;
122
123 rc = store_logic_cap(partname);
124 if (rc > read_size) {
125 rc = store_logic_read(partname, rc - read_size,
126 read_size, read_buf);
127 if (rc) {
128 printf("failed to read footer from: %s\n", partname);
129 return 0;
130 }
131 memcpy(&footer_src, &read_buf[read_size - AVB_FOOTER_SIZE], AVB_FOOTER_SIZE);
132 if (avb_footer_validate_and_byteswap(&footer_src, &footer_desc))
133 return footer_desc.original_image_size;
134 else
135 return 0;
136 } else {
137 return rc;
138 }
139}
140
Bo Lv72d0e902023-01-02 14:27:34 +0000141static AvbIOResult read_from_partition(AvbOps *ops, const char *partition, int64_t offset,
142 size_t num_bytes, void *buffer, size_t *out_num_read)
143{
144 int rc = 0;
145 uint64_t part_bytes = 0;
146 AvbIOResult result = AVB_IO_RESULT_OK;
147 size_t total_bytes = num_bytes;
148
149 if (ops->get_size_of_partition(ops, partition, &part_bytes) != AVB_IO_RESULT_OK) {
150 result = AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
151 goto out;
152 }
153
154 if (part_bytes < offset) {
155 result = AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION;
156 goto out;
157 }
158
159 *out_num_read = 0;
160 if (!strcmp(partition, "dt_a") || !strcmp(partition, "dt_b") ||
161 !strcmp(partition, "dt")) {
162 char *dtb_buf = malloc(MAX_DTB_SIZE);
163
164 if (!dtb_buf) {
165 result = AVB_IO_RESULT_ERROR_OOM;
166 goto out;
167 }
168
169 /* rc = store_dtb_rw(dtb_buf, MAX_DTB_SIZE, 2); */
170 memset(dtb_buf, 0x00, MAX_DTB_SIZE);
171 rc = store_rsv_read("dtb", MAX_DTB_SIZE, (void *)dtb_buf);
172 if (rc) {
173 printf("Failed to read dtb\n");
174 free(dtb_buf);
175 result = AVB_IO_RESULT_ERROR_IO;
176 goto out;
177 } else {
178 *out_num_read = num_bytes > MAX_DTB_SIZE ? MAX_DTB_SIZE : num_bytes;
179 memcpy(buffer, dtb_buf, *out_num_read);
180 free(dtb_buf);
181 result = AVB_IO_RESULT_OK;
182 goto out;
183 }
Matthew Shyuc710a122023-12-14 00:08:41 -0800184 } else if (!strcmp(partition, "recovery-memory")) {
185 u32 filesize = simple_strtoul(env_get("filesize"), NULL, 16);
186
187 if (memory_addr) {
188 num_bytes = (filesize - offset >= num_bytes) ? num_bytes :
189 (filesize - offset);
190 memcpy(buffer, (uint8_t *)(memory_addr + offset), num_bytes);
191 *out_num_read = num_bytes;
192 return AVB_IO_RESULT_OK;
193 }
194 return AVB_IO_RESULT_ERROR_IO;
Bo Lv72d0e902023-01-02 14:27:34 +0000195 } else {
196 enum boot_type_e type = store_get_type();
197
198 /* There is only 1 recovery partition even in A/B */
199 if (!strcmp(partition, "recovery_a") ||
200 !strcmp(partition, "recovery_b") ||
201 !strcmp(partition, "recovery"))
202 partition = "recovery";
203
204 if (type == BOOT_NAND_MTD || type == BOOT_SNAND) {
205 if (offset != 0) {
206 uint8_t *tmp_buf = malloc(NAND_PAGE_SIZE);
207 int64_t align = offset & ~(NAND_PAGE_SIZE - 1);
208 int64_t drop_bytes = offset - align;
209 int32_t valid_data = NAND_PAGE_SIZE - drop_bytes;
210
211 if (!tmp_buf) {
212 printf("failed to allocate tmp buf for nand\n");
213 result = AVB_IO_RESULT_ERROR_IO;
214 goto out;
215 }
216
217 rc = store_logic_read(partition, align, NAND_PAGE_SIZE, tmp_buf);
218 if (rc) {
219 free(tmp_buf);
220 printf("part 1: Failed to read %dB from part[%s] at %lld\n",
221 NAND_PAGE_SIZE, partition, align);
222 result = AVB_IO_RESULT_ERROR_IO;
223 goto out;
224 } else {
225 if (num_bytes > valid_data) {
226 memcpy(buffer, tmp_buf + drop_bytes, valid_data);
227 num_bytes -= valid_data;
Mingyen Hung6e468002023-01-04 23:43:04 -0800228 buffer = (uint8_t *)buffer + valid_data;
Bo Lv72d0e902023-01-02 14:27:34 +0000229 } else {
230 memcpy(buffer, tmp_buf + drop_bytes, num_bytes);
231 num_bytes = 0;
232 }
233 offset = align + NAND_PAGE_SIZE;
234 free(tmp_buf);
235 }
Mingyen Hung6e468002023-01-04 23:43:04 -0800236 if (num_bytes > 0) {
237 rc = store_logic_read(partition, offset,
238 num_bytes, buffer);
239 printf("Failed to read");
240 printf("%zdB from part[%s] at %lld\n",
241 num_bytes, partition, offset);
242 }
Bo Lv72d0e902023-01-02 14:27:34 +0000243 } else {
244 rc = store_logic_read(partition, 0, num_bytes, buffer);
245 }
246 } else {
Matthew Shyu837ffa52024-05-03 01:59:44 -0700247 rc = store_logic_read(partition, offset, num_bytes, buffer);
Bo Lv72d0e902023-01-02 14:27:34 +0000248 }
249
250 if (rc) {
251 printf("Part 2 Failed to read %zdB from part[%s] at %lld\n",
252 num_bytes, partition, offset);
253 result = AVB_IO_RESULT_ERROR_IO;
254 goto out;
255 }
256 *out_num_read = total_bytes;
257 }
258
259out:
260 return result;
261}
262
Matthew Shyu837ffa52024-05-03 01:59:44 -0700263static AvbIOResult get_preloaded_partition(AvbOps *ops, const char *partition,
264 size_t num_bytes,
265 u8 **out_pointer,
266 size_t *out_num_bytes_preloaded)
267{
268 u32 i = 0;
269
270 *out_pointer = NULL;
271 *out_num_bytes_preloaded = 0;
272
273 if (avb_preload) {
274 for (i = 0; i < avb_part_num; i++) {
275 if (!strcmp(partition, parts[i].name)) {
276 if (num_bytes <= parts[i].length) {
277 *out_pointer = parts[i].addr;
278 *out_num_bytes_preloaded = num_bytes;
279 } else {
280 printf("preload: %s expected: %zd, got: %zd\n",
281 partition, num_bytes, parts[i].length);
282 if (parts[i].addr) {
283 free(parts[i].addr);
284 parts[i].addr = NULL;
285 parts[i].length = 0;
286 memset(parts[i].name, 0, sizeof(parts[i].name));
287 }
288 }
289 return AVB_IO_RESULT_OK;
290 }
291 }
292 printf("cannot find %s in preload, use storage read\n", partition);
293 }
294
295 return AVB_IO_RESULT_OK;
296}
297
Bo Lv72d0e902023-01-02 14:27:34 +0000298static AvbIOResult write_to_partition(AvbOps *ops, const char *partition,
299 int64_t offset, size_t num_bytes, const void *buffer)
300{
301 int rc = 0;
302 uint64_t part_bytes = 0;
303 AvbIOResult result = AVB_IO_RESULT_OK;
Matthew Shyu837ffa52024-05-03 01:59:44 -0700304 const char *recovery = "recovery";
305 enum boot_type_e type = store_get_type();
Bo Lv72d0e902023-01-02 14:27:34 +0000306
307 if (ops->get_size_of_partition(ops, partition, &part_bytes) != AVB_IO_RESULT_OK) {
308 result = AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
309 goto out;
310 }
311 if (part_bytes < offset) {
312 result = AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION;
313 goto out;
314 }
315
316 if (!strcmp(partition, "dt_a") || !strcmp(partition, "dt_b") ||
317 !strcmp(partition, "dt")) {
Matthew Shyu837ffa52024-05-03 01:59:44 -0700318 if (offset) {
319 result = AVB_IO_RESULT_ERROR_IO;
320 goto out;
321 }
322 if (type == BOOT_NAND_MTD || type == BOOT_SNAND) {
323 rc = store_rsv_erase("dtb");
324 if (rc) {
325 printf("Failed to write dtb\n");
326 result = AVB_IO_RESULT_ERROR_IO;
327 goto out;
328 }
329 }
Bo Lv72d0e902023-01-02 14:27:34 +0000330 rc = store_rsv_write("dtb", num_bytes, (void *)buffer);
331 if (rc) {
332 printf("Failed to write dtb\n");
333 result = AVB_IO_RESULT_ERROR_IO;
334 goto out;
335 } else {
336 result = AVB_IO_RESULT_OK;
337 goto out;
338 }
339 } else {
340 /* There is only 1 recovery partition even in A/B */
341 if (!strcmp(partition, "recovery_a") ||
342 !strcmp(partition, "recovery_b") ||
343 !strcmp(partition, "recovery"))
Matthew Shyu837ffa52024-05-03 01:59:44 -0700344 partition = recovery;
345
346 if (type == BOOT_NAND_MTD || type == BOOT_SNAND) {
347 u8 *local_buf = NULL;
348 u32 local_size = 0;
349
350 local_size = (offset + num_bytes + NAND_PAGE_SIZE - 1);
351 local_size = local_size / NAND_PAGE_SIZE *
352 NAND_PAGE_SIZE;
353 local_buf = malloc(local_size);
354 if (!local_buf) {
355 printf("Failed local buf: %u\n", local_size);
356 result = AVB_IO_RESULT_ERROR_OOM;
357 goto out;
358 }
359 rc = store_logic_read(partition, 0, local_size,
360 local_buf);
361 if (rc) {
362 printf("Failed to read to local buf\n");
363 result = AVB_IO_RESULT_ERROR_IO;
364 free(local_buf);
365 goto out;
366 }
367 memcpy(local_buf + offset, buffer, num_bytes);
368 rc = store_erase(partition, 0, local_size, 0);
369 if (rc) {
370 printf("Failed to erase: %s %u\n",
371 partition, local_size);
372 result = AVB_IO_RESULT_ERROR_IO;
373 free(local_buf);
374 goto out;
375 }
376 rc = store_logic_write(partition, 0, local_size, local_buf);
377 free(local_buf);
378 } else {
379 rc = store_logic_write(partition, offset, num_bytes,
380 (unsigned char *)buffer);
381 }
Bo Lv72d0e902023-01-02 14:27:34 +0000382 if (rc) {
383 printf("Failed to write %zdB from part[%s] at %lld\n",
384 num_bytes, partition, offset);
385 result = AVB_IO_RESULT_ERROR_IO;
386 goto out;
387 }
388 }
389
390out:
391 return result;
392}
393
394static AvbIOResult get_unique_guid_for_partition(AvbOps *ops, const char *partition,
395 char *guid_buf, size_t guid_buf_size)
396{
397 char *s1;
398 int ret;
399 char part_name[128];
400
401 memset(guid_buf, 0, guid_buf_size);
402 s1 = env_get("active_slot");
403 if (!s1) {
404 run_command("get_valid_slot;", 0);
405 s1 = env_get("active_slot");
406 }
407 //printf("active_slot is %s\n", s1);
408 if (!memcmp(partition, "system", strlen("system"))) {
Matthew Shyu837ffa52024-05-03 01:59:44 -0700409#if CONFIG_IS_ENABLED(MMC_MESON_GX)
Bo Lv72d0e902023-01-02 14:27:34 +0000410 if (s1 && (strcmp(s1, "_a") == 0))
411 ret = get_partition_num_by_name("system_a");
412 else if (s1 && (strcmp(s1, "_b") == 0))
413 ret = get_partition_num_by_name("system_b");
414 else
415 ret = get_partition_num_by_name("system");
Matthew Shyu837ffa52024-05-03 01:59:44 -0700416#else
417 ret = 0;
418#endif
Bo Lv72d0e902023-01-02 14:27:34 +0000419
420 if (ret >= 0) {
421 sprintf(part_name, "/dev/mmcblk0p%d", ret + 1);
422 strncpy(guid_buf, part_name, guid_buf_size);
423 } else {
424 printf("system part isn't exist\n");
425 return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
426 }
427 } else if (!memcmp(partition, "vbmeta", strlen("vbmeta"))) {
428 strncpy(guid_buf, "/dev/block/vbmeta", guid_buf_size);
429 }
430 return AVB_IO_RESULT_OK;
431}
432
433static AvbIOResult get_size_of_partition(AvbOps *ops, const char *partition,
434 uint64_t *out_size_num_bytes)
435{
436 uint64_t rc = 0;
437
438 if (!strcmp(partition, "dt_a") || !strcmp(partition, "dt_b") ||
439 !strcmp(partition, "dt")) {
440 *out_size_num_bytes = DTB_PARTITION_SIZE;
Matthew Shyuc710a122023-12-14 00:08:41 -0800441 } else if (!strcmp(partition, "recovery-memory")) {
442 *out_size_num_bytes = simple_strtoul(env_get("filesize"), NULL, 16);
Bo Lv72d0e902023-01-02 14:27:34 +0000443 } else {
444 /* There is only 1 recovery partition even in A/B */
445 if (!strcmp(partition, "recovery_a") ||
446 !strcmp(partition, "recovery_b") ||
447 !strcmp(partition, "recovery"))
448 rc = store_logic_cap("recovery");
449 else
450 rc = store_logic_cap(partition);
451 if (rc == 1) {
452 printf("Failed to get partition[%s] size\n", partition);
453 return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
454 }
455 *out_size_num_bytes = rc;
456 }
457
458 return AVB_IO_RESULT_OK;
459}
460
461/**
462 * normally, we should read vendor avb public key from a virtual partition with the name avb_custom_key.
463 * Flashing and erasing this partition only works in the UNLOCKED state. Setting the custom key is done like this:
464 * $ avbtool extract_public_key --key key.pem --output pkmd.bin
465 * $ fastboot flash avb_custom_key pkmd.bin
466 *
467 * Erasing the key is done by erasing the virtual partition:
468 * $ fastboot erase avb_custom_key
469 */
470static AvbIOResult validate_vbmeta_public_key(AvbOps *ops, const uint8_t *public_key_data,
471 size_t public_key_length, const uint8_t *public_key_metadata,
472 size_t public_key_metadata_length, bool *out_is_trusted)
473{
474 *out_is_trusted = false;
475 AvbIOResult ret = AVB_IO_RESULT_ERROR_IO;
476 char *keybuf = NULL;
477 char *partition = "misc";
478 AvbKey_t key;
Matthew Shyu837ffa52024-05-03 01:59:44 -0700479 u64 size = 0;
Bo Lv72d0e902023-01-02 14:27:34 +0000480#if CONFIG_AVB2_KPUB_FROM_FIP
481 int result = 0;
482#endif
483 int i = 0;
484
485#if CONFIG_AVB2_KPUB_FROM_FIP
486 printf("AVB2 verifying with fip key\n");
487 result = compare_avbkey_with_fipkey(public_key_data, public_key_length);
488 if (result == -2) {
489 printf("AVB2 verified with fip key failed\n");
490 *out_is_trusted = false;
491 ret = AVB_IO_RESULT_OK;
492 return ret;
493 } else if (result == -1) {
494 printf("AVB2 cannot find fip key\n");
495 } else if (result == 0) {
496 printf("AVB2 verified with fip key success\n");
497 *out_is_trusted = true;
498 ret = AVB_IO_RESULT_OK;
499 return ret;
500 }
501#endif
502
503 /*
504 * disable AVB custom key and test key
505 * if device secure boot enabled
506 */
507 if (!IS_FEAT_BOOT_VERIFY()) {
508 key.size = 0;
509 keybuf = (char *)malloc(AVB_CUSTOM_KEY_LEN_MAX);
510 if (keybuf) {
511 memset(keybuf, 0, AVB_CUSTOM_KEY_LEN_MAX);
Matthew Shyu837ffa52024-05-03 01:59:44 -0700512 size = store_logic_cap(partition);
Bo Lv72d0e902023-01-02 14:27:34 +0000513 if (size != 1) {
Matthew Shyu837ffa52024-05-03 01:59:44 -0700514 /* no need workaround for nand. The size is 4K multiple,
515 * and AVB_CUSTOM_KEY_LEN_MAX is 4K. The offset will lay on
516 * 4K boundary.
517 */
518 if (store_logic_read((const char *)partition,
519 size - AVB_CUSTOM_KEY_LEN_MAX,
520 AVB_CUSTOM_KEY_LEN_MAX,
521 (unsigned char *)keybuf) >= 0) {
Bo Lv72d0e902023-01-02 14:27:34 +0000522 memcpy(&key, keybuf, sizeof(AvbKey_t));
523 }
524 }
525 }
526
527 if (keybuf && (strncmp(keybuf, "AVBK", 4) == 0)) {
528 printf("AVB2 verify with avb_custom_key\n");
529 if (key.size == public_key_length &&
530 !avb_safe_memcmp(public_key_data,
531 keybuf + sizeof(AvbKey_t), public_key_length)) {
532 *out_is_trusted = true;
533 ret = AVB_IO_RESULT_OK;
534 }
Jason Tong6a3cca92023-08-24 18:08:17 +0800535 if (is_device_unlocked())
536 ret = AVB_IO_RESULT_OK;
Bo Lv72d0e902023-01-02 14:27:34 +0000537 } else {
538 /**
539 * When the custom key is set
540 * and the device is in the LOCKED state
541 * it will boot images signed with both the built-in key
542 * as well as the custom key
543 */
544 printf("AVB2 verify with default kpub:%d, vbmeta kpub:%ld\n",
545 avb2_kpub_default_len, public_key_length);
546 if (avb2_kpub_default_len == public_key_length &&
547 !avb_safe_memcmp(public_key_data,
548 avb2_kpub_default, public_key_length)) {
549 *out_is_trusted = true;
550 ret = AVB_IO_RESULT_OK;
551 }
552 }
553 } else {
554 printf("AVB2 verify with production kpub:%d, vbmeta kpub:%ld\n",
555 avb2_kpub_production_len, public_key_length);
556 if (avb2_kpub_production_len == public_key_length &&
557 !avb_safe_memcmp(public_key_data,
558 avb2_kpub_production, public_key_length)) {
559 *out_is_trusted = true;
560 ret = AVB_IO_RESULT_OK;
561 }
562 for (i = 0; i < avb2_kpub_production_len; i++) {
563 if (avb2_kpub_production[i] != 0)
564 break;
565 }
566 if (i == avb2_kpub_production_len)
567 printf("ERROR: DID YOU FORGET TO CHANGE AVB2 KEY FOR SECURE BOOT?");
568 }
569
570 if (keybuf)
571 free(keybuf);
572 if (ret != AVB_IO_RESULT_OK)
573 printf("AVB2 key in bootloader does not match with the key in vbmeta\n");
574 return ret;
575}
576
Matthew Shyuc710a122023-12-14 00:08:41 -0800577static AvbIOResult validate_public_key_for_partition(AvbOps *ops,
578 const char *partition,
579 const u8 *public_key_data,
580 size_t public_key_length,
581 const u8 *public_key_metadata,
582 size_t public_key_metadata_length,
583 bool *out_is_trusted,
584 uint32_t *out_rollback_index_location
585)
586{
587 AvbIOResult ret = AVB_IO_RESULT_ERROR_IO;
588
589 if (!ops || !partition || !public_key_data || !out_is_trusted ||
590 !out_rollback_index_location)
591 return AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE;
592
593 *out_is_trusted = false;
594
595 if (!strcmp(partition, "recovery") ||
596 !strcmp(partition, "recovery-memory")) {
597 printf("checking for recovery partition\n");
598 ret = validate_vbmeta_public_key(ops, public_key_data,
599 public_key_length, public_key_metadata,
600 public_key_metadata_length,
601 out_is_trusted);
602 *out_rollback_index_location = RECOVERY_ARB_LOCATION;
603 } else {
604 *out_rollback_index_location = 0;
605 return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
606 }
607
608 return ret;
609}
610
Bo Lv72d0e902023-01-02 14:27:34 +0000611static AvbIOResult read_rollback_index(AvbOps *ops, size_t rollback_index_location,
612 uint64_t *out_rollback_index)
613{
Mingyen Hung6e468002023-01-04 23:43:04 -0800614 AvbIOResult result = AVB_IO_RESULT_OK;
Bo Lv72d0e902023-01-02 14:27:34 +0000615#if defined(CONFIG_AML_ANTIROLLBACK) || defined(CONFIG_AML_AVB2_ANTIROLLBACK)
Mingyen Hung6e468002023-01-04 23:43:04 -0800616 uint32_t version = 0;
Bo Lv72d0e902023-01-02 14:27:34 +0000617#endif
Mingyen Hung6e468002023-01-04 23:43:04 -0800618
619 *out_rollback_index = 0;
620
621#if defined(CONFIG_AML_ANTIROLLBACK) || defined(CONFIG_AML_AVB2_ANTIROLLBACK)
622 if (is_avb_arb_available()) {
623 if (get_avb_antirollback(rollback_index_location, &version)) {
624 *out_rollback_index = version;
625 } else {
626 printf("failed to read rollback index: %zd\n", rollback_index_location);
627 result = AVB_IO_RESULT_ERROR_NO_SUCH_VALUE;
628 }
629 }
630#endif
631
632 return result;
Bo Lv72d0e902023-01-02 14:27:34 +0000633}
634
635static AvbIOResult write_rollback_index(AvbOps* ops, size_t rollback_index_location,
636 uint64_t rollback_index)
637{
638 AvbIOResult result = AVB_IO_RESULT_OK;
Mingyen Hung6e468002023-01-04 23:43:04 -0800639
Bo Lv72d0e902023-01-02 14:27:34 +0000640#if defined(CONFIG_AML_ANTIROLLBACK) || defined(CONFIG_AML_AVB2_ANTIROLLBACK)
641 uint32_t version = rollback_index;
642
Mingyen Hung6e468002023-01-04 23:43:04 -0800643 if (is_avb_arb_available()) {
644 if (!set_avb_antirollback(rollback_index_location, version)) {
645 printf("failed to set rollback index: %zd, version: %u\n",
646 rollback_index_location, version);
647 result = AVB_IO_RESULT_ERROR_NO_SUCH_VALUE;
648 }
Bo Lv72d0e902023-01-02 14:27:34 +0000649 }
Bo Lv72d0e902023-01-02 14:27:34 +0000650#endif
Mingyen Hung6e468002023-01-04 23:43:04 -0800651
Bo Lv72d0e902023-01-02 14:27:34 +0000652 return result;
653}
654
655static AvbIOResult read_is_device_unlocked(AvbOps* ops, bool* out_is_unlocked)
656{
657 AvbIOResult result = AVB_IO_RESULT_OK;
Mingyen Hung6e468002023-01-04 23:43:04 -0800658 LockData_t info = { 0 };
Bo Lv72d0e902023-01-02 14:27:34 +0000659#if defined(CONFIG_AML_ANTIROLLBACK) || defined(CONFIG_AML_AVB2_ANTIROLLBACK)
Mingyen Hung6e468002023-01-04 23:43:04 -0800660 uint32_t lock_state = 0;
661#endif
662 char *lock_s = env_get("lock");
Bo Lv72d0e902023-01-02 14:27:34 +0000663
Mingyen Hung6e468002023-01-04 23:43:04 -0800664 if (!lock_s)
665 return AVB_IO_RESULT_ERROR_IO;
Bo Lv72d0e902023-01-02 14:27:34 +0000666
Mingyen Hung6e468002023-01-04 23:43:04 -0800667#if defined(CONFIG_AML_ANTIROLLBACK) || defined(CONFIG_AML_AVB2_ANTIROLLBACK)
668 if (is_avb_arb_available()) {
669 if (get_avb_lock_state(&lock_state)) {
670 *out_is_unlocked = !lock_state;
671 if (*out_is_unlocked)
672 lock_s[4] = '0';
673 else
674 lock_s[4] = '1';
675 } else {
676 printf("failed to read device lock status from rpmb\n");
677 result = AVB_IO_RESULT_ERROR_IO;
678 }
679 return result;
Bo Lv72d0e902023-01-02 14:27:34 +0000680 }
Mingyen Hung6e468002023-01-04 23:43:04 -0800681#endif
Bo Lv72d0e902023-01-02 14:27:34 +0000682
683 memset(&info, 0, sizeof(struct LockData));
Bo Lv72d0e902023-01-02 14:27:34 +0000684 info.version_major = (int)(lock_s[0] - '0');
685 info.version_minor = (int)(lock_s[1] - '0');
686 info.lock_state = (int)(lock_s[4] - '0');
687 info.lock_critical_state = (int)(lock_s[5] - '0');
688 info.lock_bootloader = (int)(lock_s[6] - '0');
689
690 if (info.lock_state == 1)
691 *out_is_unlocked = false;
692 else
693 *out_is_unlocked = true;
Mingyen Hung6e468002023-01-04 23:43:04 -0800694
Bo Lv72d0e902023-01-02 14:27:34 +0000695 return result;
696}
697
Matthew Shyu837ffa52024-05-03 01:59:44 -0700698#if CONFIG_IS_ENABLED(MMC_MESON_GX)
Mingyen Hung6e468002023-01-04 23:43:04 -0800699/* 4K bytes are allocated to store persistent value
700 * The first 4B is the persistent store magic word "@AVB"
701 * It is further divided into 132B slots
702 * Each 132B contains a persistent_value_t structure.
703 */
704#define AVB_PERSISTENT_MISC_OFFSET (2040 * 1024)
705#define AVB_PERSISTENT_SLOT (31)
706/* 4100 */
707#define AVB_PERSISTENT_SIZE (4 + 4 + 132 * AVB_PERSISTENT_SLOT)
708#define AVB_PERSISTENT_MAGIC "@AVB"
709#define AVB_PERSISTENT_VERSION (0x0)
710#define PERSISTENT_NAME_MAX_LEN (64)
711#define PERSISTENT_VALUE_MAX_LEN (64)
712#define PERSISTENT_FILENAME "avb_persist"
713
714#define DEV_NAME "mmc"
715#define DEV_NO (1)
716#define PART_TYPE "user"
717#define PART_NAME_RSV "rsv"
718#define PART_NAME_FTY "factory"
719#define NAND_FTY_MOUNT_PT "mnt"
720
721struct persistent_value {
722 uint8_t name_length;
723 uint8_t value_length;
724 uint16_t rsv;
725 char name[PERSISTENT_NAME_MAX_LEN];
726 uint8_t value[PERSISTENT_VALUE_MAX_LEN];
727};
728
729static uint8_t *persistent_store(int32_t *is_empty)
730{
731 uint8_t *buf = NULL;
732 int rc = 0;
733 loff_t act_read = 0;
734
735 /* initialize factory partition */
736 rc = run_command("factory_provision init", 0);
737 if (rc) {
738 printf("init factory partition failed\n");
739 return NULL;
740 }
741
742 buf = malloc(AVB_PERSISTENT_SIZE);
743 if (!buf) {
744 printf("failed to allocate buf for persistent store\n");
745 return NULL;
746 }
747 if (fat_read_file(PERSISTENT_FILENAME, buf, 0,
748 AVB_PERSISTENT_SIZE, &act_read)) {
749 printf("failed to read persistent store\n");
750 goto empty;
751 } else {
752 if (act_read != AVB_PERSISTENT_SIZE) {
753 printf("unexpected size: %lld\n", act_read);
754 memset(buf, 0, AVB_PERSISTENT_SIZE);
755 goto empty;
756 }
757 }
758
759empty:
760 if (memcmp(&buf[0], AVB_PERSISTENT_MAGIC, 4)) {
761 printf("empty persistent store, resetting\n");
762 memset(buf, 0, AVB_PERSISTENT_SIZE);
763 memcpy(&buf[0], AVB_PERSISTENT_MAGIC, 4);
764 if (is_empty)
765 *is_empty = 1;
766 } else {
767 if (is_empty)
768 *is_empty = 0;
769 }
770
771 return buf;
772}
773
774static AvbIOResult persistent_test(AvbOps *ops)
775{
776 AvbIOResult ret = AVB_IO_RESULT_OK;
777 static const char case_I[] = "smart wolves";
778 static const char case_II[] = "happy wife";
779 static const char case_III[] = "lion king";
780 char case_I_read[sizeof(case_I)] = {0};
781 char case_II_read[sizeof(case_II)] = {0};
782 char case_III_read[sizeof(case_III)] = {0};
783 size_t out_num_bytes_read = 0;
784
785 ret = ops->write_persistent_value(ops, "persist test case I",
786 sizeof(case_I), (const uint8_t *)case_I);
787 if (ret != AVB_IO_RESULT_OK) {
788 printf("failed to write case I\n");
789 return ret;
790 }
791 ret = ops->write_persistent_value(ops, "persist test case II",
792 sizeof(case_II), (const uint8_t *)case_II);
793 if (ret != AVB_IO_RESULT_OK) {
794 printf("failed to write case II\n");
795 return ret;
796 }
797 ret = ops->write_persistent_value(ops, "persist test case III",
798 sizeof(case_III), (const uint8_t *)case_III);
799 if (ret != AVB_IO_RESULT_OK) {
800 printf("failed to write case III\n");
801 return ret;
802 }
803
804 ret = ops->read_persistent_value(ops, "persist test case I",
805 sizeof(case_I_read), (uint8_t *)case_I_read, &out_num_bytes_read);
806 if (ret != AVB_IO_RESULT_OK) {
807 printf("failed to read case I\n");
808 return ret;
809 }
810 if (out_num_bytes_read == sizeof(case_I_read) &&
811 !strncmp(case_I, case_I_read, sizeof(case_I))) {
812 printf("case I passed\n");
813 } else {
814 printf("case I failed\n");
815 }
816
817 ret = ops->read_persistent_value(ops, "persist test case II",
818 sizeof(case_II_read), (uint8_t *)case_II_read,
819 &out_num_bytes_read);
820 if (ret != AVB_IO_RESULT_OK) {
821 printf("failed to read case II\n");
822 return ret;
823 }
824 if (out_num_bytes_read == sizeof(case_II_read) &&
825 !strncmp(case_II, case_II_read, sizeof(case_II))) {
826 printf("case II passed\n");
827 } else {
828 printf("case II failed\n");
829 }
830
831 ret = ops->read_persistent_value(ops, "persist test case III",
832 sizeof(case_III_read), (uint8_t *)case_III_read,
833 &out_num_bytes_read);
834 if (ret != AVB_IO_RESULT_OK) {
835 printf("failed to read case III\n");
836 return ret;
837 }
838 if (out_num_bytes_read == sizeof(case_III_read) &&
839 !strncmp(case_III, case_III_read, sizeof(case_III))) {
840 printf("case III passed\n");
841 } else {
842 printf("case III failed\n");
843 }
844
845 return ret;
846}
Matthew Shyu837ffa52024-05-03 01:59:44 -0700847#endif
Mingyen Hung6e468002023-01-04 23:43:04 -0800848
Matthew Shyu837ffa52024-05-03 01:59:44 -0700849#if CONFIG_IS_ENABLED(MMC_MESON_GX)
Mingyen Hung6e468002023-01-04 23:43:04 -0800850uint32_t create_csrs(void)
851{
852 int part_num = get_partition_num_by_name(PART_NAME_FTY);
853 char part_name[32] = {0};
854 char cmd[64] = {0};
855 uint8_t buf[1] = {0};
856
857 if (part_num >= 0)
858 strcpy(part_name, PART_NAME_FTY);
859 else
860 strcpy(part_name, PART_NAME_RSV);
861
862 sprintf(cmd, "fatmkdir %s 0x%X:0x%X %s", DEV_NAME, DEV_NO,
863 get_partition_num_by_name(part_name), "csrs");
864 if (run_command(cmd, 0)) {
865 printf("command[%s] failed\n", cmd);
866 return AVB_IO_RESULT_ERROR_IO;
867 }
868
869 memset(cmd, 0, sizeof(cmd));
870
871 sprintf(cmd, "fatwrite %s 0x%X:0x%X 0x%08X %s 0x%X", DEV_NAME, DEV_NO,
872 get_partition_num_by_name(part_name),
873 (uint32_t)virt_to_phys((void *)buf), "csrs/csrs.json", 1);
874 if (run_command(cmd, 0)) {
875 printf("command[%s] failed\n", cmd);
876 return AVB_IO_RESULT_ERROR_IO;
877 }
878 return AVB_IO_RESULT_OK;
879}
Matthew Shyu837ffa52024-05-03 01:59:44 -0700880#else
881uint32_t create_csrs(void)
882{
883 return AVB_IO_RESULT_OK;
884}
885#endif
Mingyen Hung6e468002023-01-04 23:43:04 -0800886
Matthew Shyu837ffa52024-05-03 01:59:44 -0700887#if CONFIG_IS_ENABLED(MMC_MESON_GX)
Mingyen Hung6e468002023-01-04 23:43:04 -0800888static AvbIOResult write_persistent_to_factory(uint8_t *buf, uint32_t size)
889{
890 int part_num = get_partition_num_by_name(PART_NAME_FTY);
891 char part_name[32] = {0};
892 char cmd[64] = {0};
893
894 if (part_num >= 0)
895 strcpy(part_name, PART_NAME_FTY);
896 else
897 strcpy(part_name, PART_NAME_RSV);
898
899 sprintf(cmd, "fatwrite %s 0x%X:0x%X 0x%08X %s 0x%X", DEV_NAME, DEV_NO,
900 get_partition_num_by_name(part_name),
901 (uint32_t)virt_to_phys((void *)buf), PERSISTENT_FILENAME, size);
902 if (run_command(cmd, 0)) {
903 printf("command[%s] failed\n", cmd);
904 return AVB_IO_RESULT_ERROR_IO;
905 }
906
907 return AVB_IO_RESULT_OK;
908}
909
910static AvbIOResult persistent_wipe(void)
911{
912 uint8_t *buf = NULL;
913 AvbIOResult ret = AVB_IO_RESULT_OK;
914
915 buf = persistent_store(NULL);
916 if (buf) {
917 memset(buf, 0, AVB_PERSISTENT_SIZE);
918 memcpy(&buf[0], AVB_PERSISTENT_MAGIC, 4);
919 *(uint32_t *)&buf[4] = AVB_PERSISTENT_VERSION;
920 } else {
921 return AVB_IO_RESULT_ERROR_IO;
922 }
923
924 ret = write_persistent_to_factory(buf, AVB_PERSISTENT_SIZE);
925
926 free(buf);
927 return ret;
928}
929
930static AvbIOResult persistent_dump(void)
931{
932 uint8_t *buf = NULL;
933 int rc = 0;
934 AvbIOResult ret = AVB_IO_RESULT_OK;
935 char *name = NULL;
936 int i = 0;
937 char cmd[64] = {0};
938 struct persistent_value *persist = NULL;
939
940 buf = persistent_store(NULL);
941 if (buf) {
942 printf("persistent store:\n");
943 /* skip magic word and version */
944 persist = (struct persistent_value *)(buf + 8);
945 for (i = 0; i < AVB_PERSISTENT_SLOT; i++) {
946 printf("%d:\n", i);
947 if (persist[i].name_length) {
948 name = malloc(persist[i].name_length);
949 if (!name) {
950 printf("failed to allocate name\n");
951 goto out;
952 }
953 strncpy(name, persist[i].name,
954 persist[i].name_length);
955 printf("%s\n", name);
956 free(name);
957 printf("length = %d\n",
958 persist[i].value_length);
959 snprintf(cmd, sizeof(cmd),
960 "md.b %p %x", persist[i].value,
961 persist[i].value_length);
962 rc = run_command(cmd, 0);
963 if (rc) {
964 printf("failed to run cmd: %s\n", cmd);
965 ret = AVB_IO_RESULT_ERROR_IO;
966 goto out;
967 }
968 } else {
969 printf("empty slot\n");
970 }
971 }
972 } else {
973 return AVB_IO_RESULT_ERROR_IO;
974 }
975
976out:
977 free(buf);
978 return ret;
979}
980
981AvbIOResult read_persistent_value(AvbOps *ops, const char *name,
982 size_t buffer_size, uint8_t *out_buffer, size_t *out_num_bytes_read)
983{
984 uint8_t *buf = NULL;
985 uint32_t value_found = 0;
986 uint32_t i = 0;
987 struct persistent_value *persist = NULL;
988 AvbIOResult ret = AVB_IO_RESULT_OK;
989 AvbIOResult ret_write = AVB_IO_RESULT_OK;
990 int32_t is_empty = 0;
991
992 if (!out_buffer) {
993 if (!buffer_size)
994 return AVB_IO_RESULT_OK;
995 else
996 return AVB_IO_RESULT_ERROR_IO;
997 }
998
999 buf = persistent_store(&is_empty);
1000 if (buf) {
1001 /* skip magic word and version */
1002 persist = (struct persistent_value *)(buf + 8);
1003 for (i = 0; i < AVB_PERSISTENT_SLOT; i++) {
1004 if (strlen(name) == persist[i].name_length &&
1005 !strncmp(persist[i].name, name, persist[i].name_length)) {
1006 if (buffer_size >= persist[i].value_length) {
1007 memcpy(out_buffer, persist[i].value,
1008 persist[i].value_length);
1009 *out_num_bytes_read = persist[i].value_length;
1010 ret = AVB_IO_RESULT_OK;
1011 } else {
1012 ret = AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE;
1013 *out_num_bytes_read = persist[i].value_length;
1014 }
1015 value_found = 1;
1016 break;
1017 }
1018 }
1019 if (!value_found)
1020 ret = AVB_IO_RESULT_ERROR_NO_SUCH_VALUE;
1021 } else {
1022 ret = AVB_IO_RESULT_ERROR_IO;
1023 }
1024
1025 /* write storage, if empty */
1026 if (is_empty) {
1027 ret_write = write_persistent_to_factory(buf, AVB_PERSISTENT_SIZE);
1028 if (ret_write != AVB_IO_RESULT_OK)
1029 printf("failed to write empty persistent data\n");
1030 }
1031
1032 free(buf);
1033 return ret;
1034}
1035
1036AvbIOResult write_persistent_value(AvbOps *ops, const char *name,
1037 size_t value_size, const uint8_t *value)
1038{
1039 uint8_t *buf = NULL;
1040 struct persistent_value *empty_slot = NULL;
1041 uint32_t value_found = 0;
1042 uint32_t i = 0;
1043 struct persistent_value *persist = NULL;
1044 AvbIOResult ret = AVB_IO_RESULT_OK;
1045
1046 if (value_size > PERSISTENT_VALUE_MAX_LEN)
1047 return AVB_IO_RESULT_ERROR_INVALID_VALUE_SIZE;
1048 if (strlen(name) > PERSISTENT_NAME_MAX_LEN)
1049 return AVB_IO_RESULT_ERROR_NO_SUCH_VALUE;
1050
1051 buf = persistent_store(NULL);
1052 if (buf) {
1053 /* skip magic word and version */
1054 persist = (struct persistent_value *)(buf + 8);
1055 for (i = 0; i < AVB_PERSISTENT_SLOT; i++) {
1056 if (!persist[i].name_length) {
1057 if (!empty_slot)
1058 empty_slot = &persist[i];
1059 } else {
1060 if (strlen(name) == persist[i].name_length &&
1061 !strncmp(persist[i].name, name,
1062 persist[i].name_length)) {
1063 memset(persist[i].value, 0, sizeof(persist[i].value));
1064 memcpy(persist[i].value, value, value_size);
1065 persist[i].value_length = value_size;
1066 value_found = 1;
1067 break;
1068 }
1069 }
1070 }
1071 if (!value_found) {
1072 if (empty_slot) {
1073 empty_slot->name_length = strlen(name);
1074 memset(empty_slot->name, 0, sizeof(empty_slot->name));
1075 memcpy(empty_slot->name, name, empty_slot->name_length);
1076 memset(empty_slot->value, 0, sizeof(empty_slot->value));
1077 memcpy(empty_slot->value, value, value_size);
1078 empty_slot->value_length = value_size;
1079 } else {
1080 printf("no more slots\n");
1081 ret = AVB_IO_RESULT_ERROR_IO;
1082 goto out;
1083 }
1084 }
1085 } else {
1086 ret = AVB_IO_RESULT_ERROR_IO;
1087 goto out;
1088 }
1089 ret = write_persistent_to_factory(buf, AVB_PERSISTENT_SIZE);
1090
1091out:
1092 free(buf);
1093 return ret;
1094}
Matthew Shyu837ffa52024-05-03 01:59:44 -07001095#endif
Mingyen Hung6e468002023-01-04 23:43:04 -08001096
Bo Lv72d0e902023-01-02 14:27:34 +00001097static int avb_init(void)
1098{
Matthew Shyu837ffa52024-05-03 01:59:44 -07001099 int factory_part_num = -1;
1100#if CONFIG_IS_ENABLED(MMC_MESON_GX)
1101 /* partition name is valid */
1102 if (find_mmc_partition_by_name(PART_NAME_FTY))
1103 factory_part_num = get_partition_num_by_name(PART_NAME_FTY);
1104#endif
Mingyen Hung6e468002023-01-04 23:43:04 -08001105 enum boot_type_e type = store_get_type();
Bo Lv72d0e902023-01-02 14:27:34 +00001106
1107 memset(&avb_ops_, 0, sizeof(AvbOps));
1108 avb_ops_.read_from_partition = read_from_partition;
Matthew Shyu837ffa52024-05-03 01:59:44 -07001109 avb_ops_.get_preloaded_partition = get_preloaded_partition;
Bo Lv72d0e902023-01-02 14:27:34 +00001110 avb_ops_.write_to_partition = write_to_partition;
1111 avb_ops_.validate_vbmeta_public_key = validate_vbmeta_public_key;
1112 avb_ops_.read_rollback_index = read_rollback_index;
1113 avb_ops_.write_rollback_index = write_rollback_index;
1114 avb_ops_.read_is_device_unlocked = read_is_device_unlocked;
1115 avb_ops_.get_unique_guid_for_partition = get_unique_guid_for_partition;
1116 avb_ops_.get_size_of_partition = get_size_of_partition;
Matthew Shyuc710a122023-12-14 00:08:41 -08001117 avb_ops_.validate_public_key_for_partition = validate_public_key_for_partition;
Matthew Shyu837ffa52024-05-03 01:59:44 -07001118
Mingyen Hung6e468002023-01-04 23:43:04 -08001119 if (type == BOOT_NAND_MTD || type == BOOT_SNAND || factory_part_num < 0) {
1120 avb_ops_.read_persistent_value = NULL;
1121 avb_ops_.write_persistent_value = NULL;
1122 } else {
Matthew Shyu837ffa52024-05-03 01:59:44 -07001123#if CONFIG_IS_ENABLED(MMC_MESON_GX)
Mingyen Hung6e468002023-01-04 23:43:04 -08001124 avb_ops_.read_persistent_value = read_persistent_value;
1125 avb_ops_.write_persistent_value = write_persistent_value;
Matthew Shyu837ffa52024-05-03 01:59:44 -07001126#else
1127 avb_ops_.read_persistent_value = NULL;
1128 avb_ops_.write_persistent_value = NULL;
1129#endif
Mingyen Hung6e468002023-01-04 23:43:04 -08001130 }
Bo Lv72d0e902023-01-02 14:27:34 +00001131
1132 return 0;
1133}
1134
1135int is_device_unlocked(void)
1136{
1137 AvbIOResult ret;
1138 bool out_is_unlocked;
1139
1140 ret = read_is_device_unlocked(&avb_ops_, &out_is_unlocked);
1141 if (ret == AVB_IO_RESULT_OK)
1142 return out_is_unlocked;
1143 else
1144 return 0;
1145}
1146
1147int avb_verify(AvbSlotVerifyData** out_data)
1148{
Matthew Shyu88b14432024-07-09 00:16:28 -07001149 /* The last slot must be NULL */
1150 const char *requested_partitions[AVB_NUM_SLOT + 1] = {"boot", "dt", "dtbo",
1151 "init_boot", "vendor_boot", NULL, NULL};
Bo Lv72d0e902023-01-02 14:27:34 +00001152 AvbSlotVerifyResult result = AVB_SLOT_VERIFY_RESULT_OK;
1153 char *s1 = NULL;
1154 char *ab_suffix = NULL;
Matthew Shyu837ffa52024-05-03 01:59:44 -07001155 int factory_part_num = -1;
Matthew Shyu837ffa52024-05-03 01:59:44 -07001156
Mingyen Hung6e468002023-01-04 23:43:04 -08001157 AvbHashtreeErrorMode hashtree_error_mode =
1158 AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE;
Matthew Shyu837ffa52024-05-03 01:59:44 -07001159#if CONFIG_IS_ENABLED(MMC_MESON_GX)
1160 /* partition name is valid */
1161 if (find_mmc_partition_by_name(PART_NAME_FTY))
1162 factory_part_num = get_partition_num_by_name(PART_NAME_FTY);
1163#endif
Mingyen Hung6e468002023-01-04 23:43:04 -08001164 enum boot_type_e type = store_get_type();
Bo Lv72d0e902023-01-02 14:27:34 +00001165
1166 s1 = env_get("active_slot");
1167 if (!s1) {
1168 run_command("get_valid_slot;", 0);
1169 s1 = env_get("active_slot");
1170 }
1171 if (s1) {
1172 printf("active_slot is %s\n", s1);
1173 if (!strcmp(s1, "normal"))
1174 ab_suffix = "";
1175 else
1176 ab_suffix = env_get("active_slot");
1177 }
1178
1179 if (!ab_suffix)
1180 ab_suffix = "";
1181 printf("ab_suffix is %s\n", ab_suffix);
1182
Bo Lv72d0e902023-01-02 14:27:34 +00001183 AvbSlotVerifyFlags flags = AVB_SLOT_VERIFY_FLAGS_NONE;
Bo Lv72d0e902023-01-02 14:27:34 +00001184
1185 avb_init();
1186
Matthew Shyufcd728f2023-12-07 01:44:32 -08001187 if (is_device_unlocked())
Bo Lv72d0e902023-01-02 14:27:34 +00001188 flags |= AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR;
1189
Matthew Shyuc710a122023-12-14 00:08:41 -08001190 if (!strcmp(ab_suffix, "")) {
1191 printf("recovery: %d\n", run_in_recovery);
1192 if (run_in_recovery) {
1193 flags |= AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION;
1194 memset(requested_partitions, 0, sizeof(requested_partitions));
1195 requested_partitions[0] = "recovery";
1196 }
1197 }
Matthew Shyu837ffa52024-05-03 01:59:44 -07001198
Mingyen Hung6e468002023-01-04 23:43:04 -08001199 if (type == BOOT_NAND_MTD || type == BOOT_SNAND || factory_part_num < 0)
1200 hashtree_error_mode =
1201 AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE;
1202 else
1203 hashtree_error_mode =
1204 AVB_HASHTREE_ERROR_MODE_MANAGED_RESTART_AND_EIO;
Matthew Shyuc710a122023-12-14 00:08:41 -08001205
Matthew Shyu88b14432024-07-09 00:16:28 -07001206 result = avb_slot_verify(&avb_ops_, requested_partitions, ab_suffix,
1207 flags, hashtree_error_mode, out_data);
Bo Lv72d0e902023-01-02 14:27:34 +00001208
Matthew Shyu837ffa52024-05-03 01:59:44 -07001209 clear_avb_parts();
1210
Matthew Shyu88b14432024-07-09 00:16:28 -07001211 run_in_recovery = 0;
Bo Lv72d0e902023-01-02 14:27:34 +00001212 return result;
Bo Lv72d0e902023-01-02 14:27:34 +00001213}
1214
1215static int do_avb_verify(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
1216{
1217 AvbSlotVerifyResult result = AVB_SLOT_VERIFY_RESULT_OK;
1218 AvbSlotVerifyData *out_data = NULL;
1219 uint32_t i = 0;
Mingyen Hung6e468002023-01-04 23:43:04 -08001220#if defined(CONFIG_AML_ANTIROLLBACK) || defined(CONFIG_AML_AVB2_ANTIROLLBACK)
1221 uint32_t version = 0;
1222 uint32_t lock_state = 0;
1223#endif
Bo Lv72d0e902023-01-02 14:27:34 +00001224
1225 result = (AvbSlotVerifyResult)avb_verify(&out_data);
1226
1227 printf("result: %d\n", result);
1228 if (result == AVB_SLOT_VERIFY_RESULT_OK && out_data) {
Bo Lv72d0e902023-01-02 14:27:34 +00001229 printf("ab_suffix: %s\n", out_data->ab_suffix);
1230 printf("vbmeta: name: %s, size: %zd, result: %d\n",
1231 out_data->vbmeta_images->partition_name,
1232 out_data->vbmeta_images->vbmeta_size,
1233 out_data->vbmeta_images->verify_result);
1234 printf("num of vbmeta: %zd\n", out_data->num_vbmeta_images);
1235 printf("loaded name: %s, size: %zd, preload: %d\n",
1236 out_data->loaded_partitions->partition_name,
1237 out_data->loaded_partitions->data_size,
1238 out_data->loaded_partitions->preloaded);
1239 printf("num of loaded: %zd\n", out_data->num_loaded_partitions);
1240 printf("cmdline: %s\n", out_data->cmdline);
1241 for (i = 0; i < AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS; i++)
1242 printf("rollback(%d) = %llu\n", i, out_data->rollback_indexes[i]);
1243
1244#if defined(CONFIG_AML_ANTIROLLBACK) || defined(CONFIG_AML_AVB2_ANTIROLLBACK)
Mingyen Hung6e468002023-01-04 23:43:04 -08001245 if (is_avb_arb_available()) {
1246 for (i = 0; i < AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS; i++)
1247 if (get_avb_antirollback(i, &version))
1248 printf("rpmb rollback(%d) = %u\n", i, version);
1249 if (get_avb_lock_state(&lock_state))
1250 printf("rpmb lock state: %u\n", lock_state);
1251 }
Bo Lv72d0e902023-01-02 14:27:34 +00001252#endif
1253
1254 avb_slot_verify_data_free(out_data);
1255 }
1256
1257 return result;
1258}
1259
Matthew Shyu837ffa52024-05-03 01:59:44 -07001260#if CONFIG_IS_ENABLED(MMC_MESON_GX)
1261static int do_avb_persist(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
1262{
1263 int result = 0;
1264 u32 cmd = 0;
1265
1266 if (argc != 2) {
1267 printf("invalid argc: %d\n", argc);
1268 return -1;
1269 }
1270
1271 avb_init();
1272
1273 if (!strcmp(argv[1], "test")) {
1274 cmd = 0;
1275 } else if (!strcmp(argv[1], "wipe")) {
1276 cmd = 1;
1277 } else if (!strcmp(argv[1], "dump")) {
1278 cmd = 2;
1279 } else {
1280 printf("unknown cmd: %s\n", argv[1]);
1281 return -1;
1282 }
1283
1284 switch (cmd) {
1285 case 0:
1286 printf("persist test\n");
1287 result = persistent_test(&avb_ops_);
1288 break;
1289 case 1:
1290 printf("persist wipe\n");
1291 result = persistent_wipe();
1292 break;
1293 case 2:
1294 printf("persist dump\n");
1295 result = persistent_dump();
1296 break;
1297 }
1298 return result;
1299}
1300#endif
1301
Matthew Shyuc710a122023-12-14 00:08:41 -08001302static int do_avb_verify_memory(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
1303{
1304 AvbSlotVerifyResult result = AVB_SLOT_VERIFY_RESULT_OK;
1305 AvbSlotVerifyData *out_data = NULL;
1306 const char *requested_partitions[2] = {NULL, NULL};
1307 char *avb_s = NULL;
1308
1309 if (argc != 3)
1310 return 0;
1311
1312 if (is_device_unlocked())
1313 return CMD_RET_SUCCESS;
1314
1315 run_command("get_avb_mode;", 0);
1316 avb_s = env_get("avb2");
1317 if (!avb_s || !strcmp(avb_s, "0"))
1318 return CMD_RET_SUCCESS;
1319
1320 if (!strcmp(argv[1], "recovery"))
1321 requested_partitions[0] = "recovery-memory";
1322 else
1323 return CMD_RET_FAILURE;
1324
1325 memory_addr = (void *)simple_strtoul(argv[2], NULL, 16);
1326
1327 AvbSlotVerifyFlags flags = AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION;
1328
1329 avb_init();
1330 result = avb_slot_verify(&avb_ops_, requested_partitions, "",
1331 flags,
1332 AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE, &out_data);
1333
1334 avb_slot_verify_data_free(out_data);
1335
1336 if (result == AVB_SLOT_VERIFY_RESULT_OK)
1337 return CMD_RET_SUCCESS;
1338 else
1339 return CMD_RET_FAILURE;
1340}
1341
1342static int do_avb_recovery(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
1343{
1344 char *avb_s = NULL;
1345
1346 run_in_recovery = 0;
1347
1348 if (argc != 2)
1349 return CMD_RET_FAILURE;
1350
1351 if (is_device_unlocked())
1352 return CMD_RET_SUCCESS;
1353
1354 run_command("get_avb_mode;", 0);
1355 avb_s = env_get("avb2");
1356 if (!avb_s || !strcmp(avb_s, "0"))
1357 return CMD_RET_SUCCESS;
1358
1359 if (!strcmp(argv[1], "1"))
1360 run_in_recovery = 1;
1361 else
1362 run_in_recovery = 0;
1363
1364 return CMD_RET_SUCCESS;
1365}
Matthew Shyu837ffa52024-05-03 01:59:44 -07001366
1367static int do_avb_preload(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
Mingyen Hung6e468002023-01-04 23:43:04 -08001368{
Matthew Shyu837ffa52024-05-03 01:59:44 -07001369 char *avb_s = NULL;
Mingyen Hung6e468002023-01-04 23:43:04 -08001370
Matthew Shyu837ffa52024-05-03 01:59:44 -07001371 run_in_recovery = 0;
Mingyen Hung6e468002023-01-04 23:43:04 -08001372
Matthew Shyu837ffa52024-05-03 01:59:44 -07001373 if (argc != 2)
1374 return CMD_RET_FAILURE;
Mingyen Hung6e468002023-01-04 23:43:04 -08001375
Matthew Shyu837ffa52024-05-03 01:59:44 -07001376 run_command("get_avb_mode;", 0);
1377 avb_s = env_get("avb2");
1378 if (!avb_s || !strcmp(avb_s, "0"))
1379 return CMD_RET_SUCCESS;
Mingyen Hung6e468002023-01-04 23:43:04 -08001380
Matthew Shyu837ffa52024-05-03 01:59:44 -07001381 if (!strcmp(argv[1], "1"))
1382 avb_preload = 1;
1383 else
1384 avb_preload = 0;
1385
1386 return CMD_RET_SUCCESS;
Mingyen Hung6e468002023-01-04 23:43:04 -08001387}
Matthew Shyuc710a122023-12-14 00:08:41 -08001388
Bo Lv72d0e902023-01-02 14:27:34 +00001389uint32_t avb_get_boot_patchlevel_from_vbmeta(AvbSlotVerifyData *data)
1390{
1391 int i, j;
1392 AvbVBMetaData *p;
1393 const char *ret = NULL;
1394 size_t len = 0;
1395 char buff[9];
1396 unsigned long boot_patchlevel;
1397
1398 if (!data)
1399 return 0;
1400
1401 for (i = 0; i < data->num_vbmeta_images; i++) {
1402 p = &data->vbmeta_images[i];
1403 if (strcmp(p->partition_name, "vbmeta") == 0) { /* match */
1404 if (p->verify_result != AVB_VBMETA_VERIFY_RESULT_OK) {
1405 // not verified
1406 printf("vbmeta verify_result %d\n", p->verify_result);
1407
1408 /*device lock, treat as error*/
1409 if (!is_device_unlocked()) {
1410 printf("device lock, but vbmeta verify fail\n");
1411 return 0;
1412 }
1413 }
1414
1415 ret = avb_property_lookup(p->vbmeta_data,
1416 p->vbmeta_size,
Mingyen Hung6e468002023-01-04 23:43:04 -08001417 "com.android.build.init_boot.security_patch",
1418 0,
1419 &len);
1420 if (ret)
1421 break;
1422
1423 ret = avb_property_lookup(p->vbmeta_data,
1424 p->vbmeta_size,
Bo Lv72d0e902023-01-02 14:27:34 +00001425 "com.android.build.boot.security_patch",
1426 0,
1427 &len);
Bo Lv72d0e902023-01-02 14:27:34 +00001428 if (ret)
1429 break;
Mingyen Hung6e468002023-01-04 23:43:04 -08001430
Bo Lv72d0e902023-01-02 14:27:34 +00001431// else
1432// printf("not found com.android.build.boot.
1433// security_patch,len = %d\n", (int)len);
1434 }
1435 }
1436
1437 if (ret) {
1438 for (i = 0, j = 0; i < len; i++) {
1439 if (ret[i] != '-' && j < 8)
1440 buff[j++] = ret[i];
1441 }
1442 buff[8] = '\0';
1443 if (!strict_strtoul(buff, 10, &boot_patchlevel))
1444 return (uint32_t)boot_patchlevel;
1445 }
1446
1447 return 0;
1448}
1449
1450static cmd_tbl_t cmd_avb_sub[] = {
Mingyen Hung6e468002023-01-04 23:43:04 -08001451 U_BOOT_CMD_MKENT(verify, 0, 0, do_avb_verify, "", ""),
Matthew Shyu837ffa52024-05-03 01:59:44 -07001452#if CONFIG_IS_ENABLED(MMC_MESON_GX)
Mingyen Hung6e468002023-01-04 23:43:04 -08001453 U_BOOT_CMD_MKENT(persist, 2, 0, do_avb_persist, "avb persist test/wipe/dump",
1454 "avb persist test/wipe/dump"),
Matthew Shyu837ffa52024-05-03 01:59:44 -07001455#endif
Matthew Shyuc710a122023-12-14 00:08:41 -08001456 U_BOOT_CMD_MKENT(memory, 4, 0, do_avb_verify_memory, "", ""),
1457 U_BOOT_CMD_MKENT(recovery, 2, 0, do_avb_recovery, "", ""),
Matthew Shyu837ffa52024-05-03 01:59:44 -07001458 U_BOOT_CMD_MKENT(preload, 2, 0, do_avb_preload, "", ""),
Bo Lv72d0e902023-01-02 14:27:34 +00001459};
1460
1461static int do_avb_ops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
1462{
1463 cmd_tbl_t *c;
Matthew Shyuc710a122023-12-14 00:08:41 -08001464 int ret = CMD_RET_SUCCESS;
Bo Lv72d0e902023-01-02 14:27:34 +00001465
Mingyen Hung6e468002023-01-04 23:43:04 -08001466 /* Strip off leading 'avb' command argument */
Bo Lv72d0e902023-01-02 14:27:34 +00001467 argc--;
1468 argv++;
1469
1470 c = find_cmd_tbl(argv[0], &cmd_avb_sub[0], ARRAY_SIZE(cmd_avb_sub));
1471
1472 if (c) {
1473 ret = c->cmd(cmdtp, flag, argc, argv);
1474 } else {
1475 cmd_usage(cmdtp);
Matthew Shyuc710a122023-12-14 00:08:41 -08001476 ret = CMD_RET_FAILURE;
Bo Lv72d0e902023-01-02 14:27:34 +00001477 }
1478
1479 return ret;
1480}
1481
1482
1483U_BOOT_CMD(
Matthew Shyuc710a122023-12-14 00:08:41 -08001484 avb, 4, 0, do_avb_ops,
Bo Lv72d0e902023-01-02 14:27:34 +00001485 "avb",
1486 "\nThis command will trigger related avb operations\n"
1487 );