xref: /rk3399_rockchip-uboot/cmd/boot_android.c (revision 008aee876ae5041eb6e2889c9becb47351d0ee47)
1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * SPDX-License-Identifier: BSD-2-Clause
5  */
6 
7 #include <android_bootloader.h>
8 #include <android_avb/avb_version.h>
9 #include <android_avb/avb_ab_flow.h>
10 #include <android_avb/avb_ops_user.h>
11 #include <android_cmds.h>
12 #include <malloc.h>
13 #include <common.h>
14 #include <bootm.h>
15 #include <command.h>
16 #include <android_bootloader_message.h>
17 #include <android_avb/rk_avb_ops_user.h>
18 #include <android_avb/avb_atx_ops.h>
19 
20 static int do_boot_android(cmd_tbl_t *cmdtp, int flag, int argc,
21 			   char * const argv[])
22 {
23 	unsigned long load_address;
24 	int ret = CMD_RET_SUCCESS;
25 	char *addr_arg_endp, *addr_str;
26 	struct blk_desc *dev_desc;
27 
28 	if (argc < 3)
29 		return CMD_RET_USAGE;
30 	if (argc > 5)
31 		return CMD_RET_USAGE;
32 
33 	if (argc >= 5) {
34 		load_address = simple_strtoul(argv[4], &addr_arg_endp, 16);
35 		if (addr_arg_endp == argv[4] || *addr_arg_endp != '\0')
36 			return CMD_RET_USAGE;
37 	} else {
38 		addr_str = env_get("kernel_addr_r");
39 		if (addr_str)
40 			load_address = simple_strtoul(addr_str, NULL, 16);
41 		else
42 			load_address = CONFIG_SYS_LOAD_ADDR;
43 	}
44 
45 #if defined(CONFIG_ARM64)
46 	/* ARM64 kernel load addr need to align to 0x80000, and android boot.img
47 	 * have a 2KB header, need to reserve space for it.
48 	 */
49 	load_address &= ~0x7ffff;
50 #endif
51 	load_address -= 0x800; /* default page size for boot header */
52 	dev_desc = blk_get_dev(argv[1], simple_strtoul(argv[2], NULL, 16));
53 	if (!dev_desc) {
54 		printf("Could not get %s %s\n", argv[1], argv[2]);
55 		return CMD_RET_FAILURE;
56 	}
57 
58 	ret = android_bootloader_boot_flow(dev_desc, load_address);
59 	if (ret < 0) {
60 		printf("Android boot failed, error %d.\n", ret);
61 		return CMD_RET_FAILURE;
62 	}
63 	return CMD_RET_SUCCESS;
64 }
65 
66 U_BOOT_CMD(
67 	boot_android, 5, 0, do_boot_android,
68 	"Execute the Android Bootloader flow.",
69 	"<interface> <dev[:part|;part_name]> <slot> [<kernel_addr>]\n"
70 	"    - Load the Boot Control Block (BCB) from the partition 'part' on\n"
71 	"      device type 'interface' instance 'dev' to determine the boot\n"
72 	"      mode, and load and execute the appropriate kernel.\n"
73 	"      In normal and recovery mode, the kernel will be loaded from\n"
74 	"      the corresponding \"boot\" partition. In bootloader mode, the\n"
75 	"      command defined in the \"fastbootcmd\" variable will be\n"
76 	"      executed.\n"
77 	"      On Android devices with multiple slots, the pass 'slot' is\n"
78 	"      used to load the appropriate kernel. The standard slot names\n"
79 	"      are 'a' and 'b'.\n"
80 	"    - If 'part_name' is passed, preceded with a ; instead of :, the\n"
81 	"      partition name whose label is 'part_name' will be looked up in\n"
82 	"      the partition table. This is commonly the \"misc\" partition.\n"
83 );
84 
85 #ifdef CONFIG_RK_AVB_LIBAVB_USER
86 static int bootloader_message_read(struct android_bootloader_message *data)
87 {
88 	AvbOps *ops;
89 	char requested_partitions[] = "misc";
90 	size_t out_num_read;
91 	char *buffer;
92 
93 	ops = avb_ops_user_new();
94 	buffer = (char *)data;
95 
96 	if (ops == NULL) {
97 		printf("avb_ops_user_new() failed!\n");
98 		return CMD_RET_FAILURE;
99 	}
100 
101 	if (ops->read_from_partition(ops, requested_partitions,
102 				     0, 2048, buffer,
103 				     &out_num_read) != 0) {
104 		printf("do avb read error!\n");
105 		avb_ops_user_free(ops);
106 		return CMD_RET_FAILURE;
107 	}
108 
109 	avb_ops_user_free(ops);
110 
111 	return CMD_RET_SUCCESS;
112 }
113 
114 static int bootloader_message_write(struct android_bootloader_message *data)
115 {
116 	AvbOps *ops;
117 	char requested_partitions[] = "misc";
118 	char *buffer;
119 
120 	ops = avb_ops_user_new();
121 	buffer = (char *)data;
122 
123 	if (ops == NULL) {
124 		printf("avb_ops_user_new() failed!\n");
125 		return CMD_RET_FAILURE;
126 	}
127 
128 	if (ops->write_to_partition(ops, requested_partitions,
129 				     0, 2048, buffer) != 0) {
130 		printf("do avb write error!\n");
131 		avb_ops_user_free(ops);
132 		return CMD_RET_FAILURE;
133 	}
134 
135 	avb_ops_user_free(ops);
136 
137 	return CMD_RET_SUCCESS;
138 }
139 
140 int do_avb_init_ab_metadata(cmd_tbl_t *cmdtp, int flag,
141 			    int argc, char * const argv[])
142 {
143 	AvbOps *ops;
144 	AvbABData ab_data;
145 
146 	memset(&ab_data, 0, sizeof(AvbABData));
147 	debug("sizeof(AvbABData) = %d\n", (int)(size_t)sizeof(AvbABData));
148 	if (argc != 1)
149 		return CMD_RET_USAGE;
150 
151 	ops = avb_ops_user_new();
152 	if (ops == NULL) {
153 		printf("avb_ops_user_new() failed!\n");
154 		return CMD_RET_FAILURE;
155 	}
156 
157 	avb_ab_data_init(&ab_data);
158 	if (ops->ab_ops->write_ab_metadata(ops->ab_ops, &ab_data) != 0) {
159 		printf("do_avb_init_ab_metadata error!\n");
160 		avb_ops_user_free(ops);
161 		return CMD_RET_FAILURE;
162 	}
163 
164 	avb_ops_user_free(ops);
165 
166 	return CMD_RET_SUCCESS;
167 }
168 
169 int do_avb_version(cmd_tbl_t *cmdtp, int flag, int argc,
170 		   char * const argv[])
171 {
172 	const char *avb_version;
173 
174 	if (argc != 1)
175 		return CMD_RET_USAGE;
176 
177 	avb_version = avb_version_string();
178 	printf("Android avb version is %s.\n", avb_version);
179 
180 	return CMD_RET_SUCCESS;
181 }
182 
183 int do_avb_ab_mark_slot_active(cmd_tbl_t *cmdtp, int flag,
184 			       int argc, char * const argv[])
185 {
186 	AvbOps *ops;
187 	unsigned int slot_number;
188 
189 	if (argc != 2)
190 		return CMD_RET_USAGE;
191 
192 	ops = avb_ops_user_new();
193 	if (ops == NULL) {
194 		printf("avb_ops_user_new() failed!\n");
195 		return CMD_RET_FAILURE;
196 	}
197 
198 	slot_number = simple_strtoul(argv[1], NULL, 16);
199 	if (avb_ab_mark_slot_active(ops->ab_ops, slot_number) != 0) {
200 		printf("avb_ab_mark_slot_active error!\n");
201 		avb_ops_user_free(ops);
202 		return CMD_RET_FAILURE;
203 	}
204 
205 	avb_ops_user_free(ops);
206 
207 	return CMD_RET_SUCCESS;
208 }
209 
210 int do_avb_ab_mark_slot_unbootable(cmd_tbl_t *cmdtp, int flag,
211 				   int argc, char * const argv[])
212 {
213 	AvbOps *ops;
214 	unsigned int slot_number;
215 
216 	if (argc != 2)
217 		return CMD_RET_USAGE;
218 
219 	ops = avb_ops_user_new();
220 	if (ops == NULL) {
221 		printf("avb_ops_user_new() failed!\n");
222 		return CMD_RET_FAILURE;
223 	}
224 
225 	slot_number = simple_strtoul(argv[1], NULL, 16);
226 	if (avb_ab_mark_slot_unbootable(ops->ab_ops, slot_number) != 0) {
227 		printf("do_avb_ab_mark_slot_unbootable error!\n");
228 		avb_ops_user_free(ops);
229 		return CMD_RET_FAILURE;
230 	}
231 
232 	avb_ops_user_free(ops);
233 
234 	return CMD_RET_SUCCESS;
235 }
236 
237 int do_avb_ab_mark_slot_successful(cmd_tbl_t *cmdtp, int flag,
238 				   int argc, char * const argv[])
239 {
240 	AvbOps *ops;
241 	unsigned int slot_number;
242 
243 	if (argc != 2)
244 		return CMD_RET_USAGE;
245 
246 	ops = avb_ops_user_new();
247 	if (ops == NULL) {
248 		printf("avb_ops_user_new() failed!\n");
249 		return CMD_RET_FAILURE;
250 	}
251 
252 	slot_number = simple_strtoul(argv[1], NULL, 16);
253 	if (avb_ab_mark_slot_successful(ops->ab_ops, slot_number) != 0) {
254 		printf("do_avb_ab_mark_slot_successful error!\n");
255 		avb_ops_user_free(ops);
256 		return CMD_RET_FAILURE;
257 	}
258 
259 	avb_ops_user_free(ops);
260 
261 	return CMD_RET_SUCCESS;
262 }
263 
264 int do_avb_read_rollback_index(cmd_tbl_t *cmdtp, int flag,
265 			       int argc, char * const argv[])
266 {
267 	AvbOps *ops;
268 	uint64_t out_rollback_index;
269 	size_t rollback_index_location;
270 
271 	if (argc != 2)
272 		return CMD_RET_USAGE;
273 
274 	ops = avb_ops_user_new();
275 	if (ops == NULL) {
276 		printf("avb_ops_user_new() failed!\n");
277 		return CMD_RET_FAILURE;
278 	}
279 
280 	rollback_index_location = simple_strtoul(argv[1], NULL, 16);
281 	if (ops->read_rollback_index(ops, rollback_index_location,
282 				     &out_rollback_index) != 0) {
283 		printf("do_avb_read_rollback_index error!\n");
284 		avb_ops_user_free(ops);
285 		return CMD_RET_FAILURE;
286 	}
287 
288 	printf("out_rollback_index = %llx\n", out_rollback_index);
289 	avb_ops_user_free(ops);
290 
291 	return CMD_RET_SUCCESS;
292 }
293 
294 int do_avb_write_rollback_index(cmd_tbl_t *cmdtp, int flag,
295 				int argc, char * const argv[])
296 {
297 	AvbOps *ops;
298 	uint64_t out_rollback_index;
299 	size_t rollback_index_location;
300 
301 	if (argc != 3)
302 		return CMD_RET_USAGE;
303 
304 	rollback_index_location = simple_strtoul(argv[1], NULL, 16);
305 	out_rollback_index = simple_strtoull(argv[2], NULL, 16);
306 	debug("out_rollback_index = %llx\n", out_rollback_index);
307 	ops = avb_ops_user_new();
308 	if (ops == NULL) {
309 		printf("avb_ops_user_new() failed!\n");
310 		return CMD_RET_FAILURE;
311 	}
312 
313 	if (ops->write_rollback_index(ops, rollback_index_location,
314 				      out_rollback_index) != 0) {
315 		printf("do_avb_write_rollback_index error!\n");
316 		avb_ops_user_free(ops);
317 		return CMD_RET_FAILURE;
318 	}
319 
320 	avb_ops_user_free(ops);
321 
322 	return CMD_RET_SUCCESS;
323 }
324 
325 int do_avb_read_is_device_unlocked(cmd_tbl_t *cmdtp, int flag,
326 				   int argc, char * const argv[])
327 {
328 	AvbOps *ops;
329 	bool out_is_unlocked;
330 
331 	if (argc != 1)
332 		return CMD_RET_USAGE;
333 
334 	ops = avb_ops_user_new();
335 	if (ops == NULL) {
336 		printf("avb_ops_user_new() failed!\n");
337 		return CMD_RET_FAILURE;
338 	}
339 
340 	if (ops->read_is_device_unlocked(ops, &out_is_unlocked) != 0) {
341 		printf("do_avb_read_is_device_unlocked error!\n");
342 		avb_ops_user_free(ops);
343 		return CMD_RET_FAILURE;
344 	}
345 
346 	printf("out_is_unlocked = %d\n", out_is_unlocked);
347 	avb_ops_user_free(ops);
348 
349 	return CMD_RET_SUCCESS;
350 }
351 int do_avb_write_is_device_unlocked(cmd_tbl_t *cmdtp, int flag,
352 				    int argc, char * const argv[])
353 {
354 	AvbOps *ops;
355 	bool out_is_unlocked;
356 
357 	if (argc != 2)
358 		return CMD_RET_USAGE;
359 
360 	out_is_unlocked = simple_strtoul(argv[1], NULL, 16);
361 	if ((out_is_unlocked != 0) || (out_is_unlocked != 1))
362 		printf("enter out_is_unlocked value must is '0' or '1'\n");
363 
364 	ops = avb_ops_user_new();
365 	if (ops == NULL) {
366 		printf("avb_ops_user_new() failed!\n");
367 		return CMD_RET_FAILURE;
368 	}
369 
370 	if (ops->write_is_device_unlocked(ops, &out_is_unlocked) != 0) {
371 		printf("do_avb_write_is_device_unlocked error!\n");
372 		avb_ops_user_free(ops);
373 		return CMD_RET_FAILURE;
374 	}
375 
376 	debug("out_is_unlocked = %d\n", out_is_unlocked);
377 	avb_ops_user_free(ops);
378 
379 	return CMD_RET_SUCCESS;
380 }
381 
382 int do_avb_get_size_of_partition(cmd_tbl_t *cmdtp, int flag,
383 				 int argc, char * const argv[])
384 {
385 	AvbOps *ops;
386 	char *requested_partitions;
387 	uint64_t out_size_in_bytes;
388 
389 	if (argc != 2)
390 		return CMD_RET_USAGE;
391 
392 	requested_partitions = argv[1];
393 	ops = avb_ops_user_new();
394 	if (ops == NULL) {
395 		printf("avb_ops_user_new() failed!\n");
396 		return CMD_RET_FAILURE;
397 	}
398 
399 	if (ops->get_size_of_partition(ops, requested_partitions,
400 				       &out_size_in_bytes) != 0) {
401 		printf("do_avb_get_size_of_partition error!\n");
402 		avb_ops_user_free(ops);
403 		return CMD_RET_FAILURE;
404 	}
405 
406 	printf("partition size = %lld\n", out_size_in_bytes);
407 	avb_ops_user_free(ops);
408 
409 	return CMD_RET_SUCCESS;
410 }
411 
412 int do_avb_get_get_unique_guid_for_partition(cmd_tbl_t *cmdtp, int flag,
413 					     int argc, char * const argv[])
414 {
415 	AvbOps *ops;
416 	char *requested_partitions;
417 	size_t guid_buf_size = 37;
418 	char guid_buf[37];
419 
420 	if (argc != 2)
421 		return CMD_RET_USAGE;
422 
423 	requested_partitions = argv[1];
424 	ops = avb_ops_user_new();
425 	if (ops == NULL) {
426 		printf("avb_ops_user_new() failed!\n");
427 		return CMD_RET_FAILURE;
428 	}
429 
430 	if (ops->get_unique_guid_for_partition(ops, requested_partitions,
431 					       guid_buf, guid_buf_size) != 0) {
432 		printf("do_avb_get_get_unique_guid_for_partition error!\n");
433 		avb_ops_user_free(ops);
434 		return CMD_RET_FAILURE;
435 	}
436 
437 	printf("guid = %s\n", guid_buf);
438 	avb_ops_user_free(ops);
439 
440 	return CMD_RET_SUCCESS;
441 }
442 
443 int do_avb_read(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
444 {
445 	AvbOps *ops;
446 	char *requested_partitions;
447 	int64_t offset_blk;
448 	size_t blkcnt;
449 	size_t out_num_read;
450 	int i;
451 	char *buffer;
452 
453 	if (argc != 4)
454 		return CMD_RET_USAGE;
455 
456 	requested_partitions = argv[1];
457 	offset_blk = simple_strtoul(argv[2], NULL, 16);
458 	blkcnt = simple_strtoul(argv[3], NULL, 16);
459 	ops = avb_ops_user_new();
460 	buffer = (char *)malloc(blkcnt * 512);
461 	if (buffer == NULL)
462 		printf("malloc buffer failed!\n");
463 
464 	if (ops == NULL) {
465 		printf("avb_ops_user_new() failed!\n");
466 		return CMD_RET_FAILURE;
467 	}
468 
469 	if (ops->read_from_partition(ops, requested_partitions,
470 				     offset_blk, blkcnt, buffer,
471 				     &out_num_read) != 0) {
472 		printf("do avb read error!\n");
473 		free(buffer);
474 		avb_ops_user_free(ops);
475 		return CMD_RET_FAILURE;
476 	}
477 
478 	for (i = 0; i < 512 * blkcnt; i++)
479 		printf("buffer %d = %d\n", i, buffer[i]);
480 
481 	free(buffer);
482 	avb_ops_user_free(ops);
483 
484 	return CMD_RET_SUCCESS;
485 }
486 
487 int do_avb_write(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
488 {
489 	AvbOps *ops;
490 	char *requested_partitions;
491 	int64_t offset_blk;
492 	size_t blkcnt;
493 	size_t out_num_read;
494 	char *buffer;
495 
496 	if (argc != 4)
497 		return CMD_RET_USAGE;
498 
499 	requested_partitions = argv[1];
500 	offset_blk = simple_strtoul(argv[2], NULL, 16);
501 	blkcnt = simple_strtoul(argv[3], NULL, 16);
502 	ops = avb_ops_user_new();
503 	buffer = (char *)malloc(blkcnt * 512);
504 	if (buffer == NULL) {
505 		printf("malloc buffer failed!\n");
506 		return CMD_RET_FAILURE;
507 	}
508 
509 	if (ops == NULL) {
510 		printf("avb_ops_user_new() failed!\n");
511 		return CMD_RET_FAILURE;
512 	}
513 	if (ops->read_from_partition(ops, requested_partitions, offset_blk,
514 				     blkcnt, buffer, &out_num_read) != 0) {
515 		printf("do_avb_write error!\n");
516 		free(buffer);
517 		avb_ops_user_free(ops);
518 		return CMD_RET_FAILURE;
519 	}
520 
521 	free(buffer);
522 	avb_ops_user_free(ops);
523 
524 	return CMD_RET_SUCCESS;
525 }
526 
527 int do_avb_read_ab_metadata(cmd_tbl_t *cmdtp, int flag,
528 			    int argc, char * const argv[])
529 {
530 	AvbOps *ops;
531 	AvbABData ab_data;
532 
533 	if (argc != 1)
534 		return CMD_RET_USAGE;
535 
536 	ops = avb_ops_user_new();
537 	if (ops == NULL) {
538 		printf("avb_ops_user_new() failed!\n");
539 		return CMD_RET_FAILURE;
540 	}
541 
542 	if (ops->ab_ops->read_ab_metadata(ops->ab_ops, &ab_data) != 0) {
543 		printf("do_avb_write_ab_metadata error!\n");
544 		avb_ops_user_free(ops);
545 		return CMD_RET_FAILURE;
546 	}
547 
548 	avb_ops_user_free(ops);
549 
550 	return CMD_RET_SUCCESS;
551 }
552 
553 int do_avb_write_ab_metadata(cmd_tbl_t *cmdtp, int flag,
554 			     int argc, char * const argv[])
555 {
556 	AvbOps *ops;
557 	AvbABData ab_data;
558 
559 	if (argc != 1)
560 		return CMD_RET_USAGE;
561 
562 	ops = avb_ops_user_new();
563 	if (ops == NULL) {
564 		printf("avb_ops_user_new() failed!\n");
565 		return CMD_RET_FAILURE;
566 	}
567 
568 	if (ops->ab_ops->write_ab_metadata(ops->ab_ops, &ab_data) != 0) {
569 		printf("do_avb_write_ab_metadata error!\n");
570 		avb_ops_user_free(ops);
571 		return CMD_RET_FAILURE;
572 	}
573 
574 	avb_ops_user_free(ops);
575 
576 	return CMD_RET_SUCCESS;
577 }
578 
579 int do_perm_attr_test(cmd_tbl_t *cmdtp, int flag,
580 		      int argc, char * const argv[])
581 {
582 	AvbOps *ops;
583 	int i;
584 	uint8_t hash[AVB_SHA256_DIGEST_SIZE];
585 
586 	if (argc != 1)
587 		return CMD_RET_USAGE;
588 
589 	ops = avb_ops_user_new();
590 	if (ops == NULL) {
591 		printf("avb_ops_user_new() failed!\n");
592 		return CMD_RET_FAILURE;
593 	}
594 
595 	if (ops->atx_ops->read_permanent_attributes_hash(ops->atx_ops, hash) != 0) {
596 		printf("read_permanent_attributes_hash error!\n");
597 		avb_ops_user_free(ops);
598 		return CMD_RET_FAILURE;
599 	}
600 
601 	for (i = 0; i < AVB_SHA256_DIGEST_SIZE; i++) {
602 		if (i % 4 == 0)
603 			printf("\n");
604 		printf("0x%x  ", hash[i]);
605 	}
606 
607 	avb_ops_user_free(ops);
608 
609 	return CMD_RET_SUCCESS;
610 }
611 
612 int do_avb_verify_partition(cmd_tbl_t *cmdtp, int flag,
613 			    int argc, char * const argv[])
614 {
615 	AvbOps *ops;
616 	const char *requested_partitions[1];
617 	const char * slot_suffixes[2] = {"_a", "_b"};
618 	AvbSlotVerifyFlags flags;
619 	AvbSlotVerifyData *slot_data[2] = {NULL, NULL};
620 	AvbSlotVerifyResult verify_result;
621 	size_t n;
622 
623 	if (argc != 3)
624 		return CMD_RET_USAGE;
625 
626 	requested_partitions[0] = argv[1];
627 	n = simple_strtoul(argv[2], NULL, 16);
628 	ops = avb_ops_user_new();
629 	flags = AVB_SLOT_VERIFY_FLAGS_NONE;
630 	verify_result =
631 		avb_slot_verify(ops,
632 				requested_partitions,
633 				slot_suffixes[n],
634 				flags,
635 				AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
636 				&slot_data[n]);
637 	if (verify_result != 0)
638 		return CMD_RET_FAILURE;
639 
640 	avb_ops_user_free(ops);
641 
642 	return CMD_RET_SUCCESS;
643 }
644 
645 int do_avb_flow(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
646 {
647 	char slot_partition[2][20] = {{0}, {0}};
648 	unsigned long load_address;
649 	AvbOps *ops;
650 	const char *avb_version;
651 	AvbSlotVerifyData *slot_data;
652 	AvbSlotVerifyFlags flags;
653 	const char *requested_partitions[] = {"boot", "system", NULL};
654 	char *command_line;
655 	bool unlocked;
656 	const char *mode_cmdline = NULL;
657 	char root_data[70] = "root=PARTUUID=";
658 	char *vboot_state = "androidboot.verifiedbootstate=";
659 	char avb_root_data[2000] = {0};
660 	size_t guid_buf_size = 37;
661 	char guid_buf[37];
662 	char verify_flag;
663 	char boot_slot_select[5];
664 	struct android_bootloader_message data;
665 	const char *fastboot_cmd = env_get("fastbootcmd");
666 	AvbABFlowResult ab_result;
667 
668 	if (argc != 2)
669 		return CMD_RET_USAGE;
670 
671 	bootloader_message_read(&data);
672 	if (!strcmp("bootonce-bootloader", data.command)) {
673 		memset(data.command, 0, sizeof(data.command));
674 		bootloader_message_write(&data);
675 		if (fastboot_cmd) {
676 			printf("bootonce-bootloader!\n");
677 			return run_command(fastboot_cmd, CMD_FLAG_ENV);
678 		} else {
679 			printf("The fastbootcmd is NULL!\n");
680 			goto fail;
681 		}
682 	} else if (!strcmp("boot-recovery", data.command)) {
683 		printf("Enter boot-recovery!\n");
684 	} else if(!strcmp("boot-normal", data.command)) {
685 		printf("Enter boot-normal!\n");
686 		mode_cmdline = "skip_initramfs";
687 	} else {
688 		/*
689 		 * Firstly, confirm if there is a command in misc partition in
690 		 * previous cases, and then we need to confirm whether user has
691 		 * requested to enter recovery mode by entering "reboot recovery"
692 		 * command through adb or serial console.
693 		 */
694 		char *env_rebootmode = env_get("reboot_mode");
695 
696 		if (env_rebootmode && !strcmp("recovery", env_rebootmode))
697 			printf("Enter recovery mode by command 'reboot recovery'!\n");
698 		else
699 			mode_cmdline = "skip_initramfs";
700 	}
701 
702 	avb_version = avb_version_string();
703 	printf("Android avb version is %s.\n", avb_version);
704 	ops = avb_ops_user_new();
705 	if (ops == NULL) {
706 		printf("avb_ops_user_new() failed!\n");
707 		goto fail;
708 	}
709 
710 	if (ops->read_is_device_unlocked(ops, &unlocked) != 0) {
711 		printf("Error determining whether device is unlocked.\n");
712 		unlocked = ANDROID_VBOOT_UNLOCK;
713 		if (ops->write_is_device_unlocked(ops, &unlocked) != 0) {
714 			printf("Can not write lock state!\n");
715 			unlocked = ANDROID_VBOOT_LOCK;
716 		}
717 		if (ops->read_is_device_unlocked(ops, &unlocked) != 0) {
718 			printf("Can not read lock state!\n");
719 			unlocked = ANDROID_VBOOT_LOCK;
720 		}
721 	}
722 
723 	printf("read_is_device_unlocked() ops returned that device is %s\n",
724 	       unlocked ? "UNLOCKED" : "LOCKED");
725 
726 	flags = AVB_SLOT_VERIFY_FLAGS_NONE;
727 	if (unlocked)
728 		flags |= AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR;
729 
730 	verify_flag = argv[1][0];
731 	if (verify_flag == 'v') {
732 		debug("start with verify!\n");
733 		ab_result =
734 		    avb_ab_flow(ops->ab_ops,
735 				requested_partitions,
736 				flags,
737 				AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
738 				&slot_data);
739 		if ((ab_result != AVB_AB_FLOW_RESULT_OK) &&
740 		    (ab_result !=
741 		    AVB_AB_FLOW_RESULT_OK_WITH_VERIFICATION_ERROR)) {
742 			printf("avb_ab_flow() error!\n");
743 			avb_ops_user_free(ops);
744 			goto fail;
745 		}
746 
747 		if (ab_result ==\
748 		    AVB_AB_FLOW_RESULT_OK_WITH_VERIFICATION_ERROR) {
749 			strcat(avb_root_data, vboot_state);
750 			strcat(avb_root_data, "orange");
751 		} else if (ab_result == AVB_AB_FLOW_RESULT_OK) {
752 			strcat(avb_root_data, vboot_state);
753 			strcat(avb_root_data, "green");
754 		}
755 
756 		command_line = android_assemble_cmdline(slot_data->ab_suffix,
757 							mode_cmdline);
758 		strcat(avb_root_data, " ");
759 		strcat(avb_root_data, command_line);
760 		strcat(avb_root_data, " ");
761 		strcat(avb_root_data, slot_data->cmdline);
762 		env_set("bootargs", avb_root_data);
763 		load_address = CONFIG_SYS_LOAD_ADDR;
764 		if (rk_avb_close_optee_client())
765 			printf("Can not close optee client!\n");
766 
767 		memcpy((uint8_t*)load_address,
768 		       slot_data->loaded_partitions->data,
769 		       slot_data->loaded_partitions->data_size);
770 		android_bootloader_boot_kernel(load_address);
771 		avb_ops_user_free(ops);
772 	} else if (verify_flag == 'n') {
773 		load_address = CONFIG_SYS_LOAD_ADDR;
774 		rk_avb_ab_slot_select(ops->ab_ops, boot_slot_select);
775 		strcat(slot_partition[1], requested_partitions[1]);
776 		strcat(slot_partition[1], boot_slot_select);
777 		printf("%s\n", slot_partition[1]);
778 		ops->get_unique_guid_for_partition(ops,
779 						   slot_partition[1],
780 						   guid_buf,
781 						   guid_buf_size);
782 		strcat(root_data, guid_buf);
783 		command_line = android_assemble_cmdline(boot_slot_select,
784 							mode_cmdline);
785 		strcat(root_data, " ");
786 		strcat(root_data, command_line);
787 		env_set("bootargs", root_data);
788 		if (android_avb_boot_flow(boot_slot_select, load_address)) {
789 			printf("Cannot boot the system, goto the fastboot!\n");
790 			avb_ops_user_free(ops);
791 			goto fail;
792 		}
793 		avb_ops_user_free(ops);
794 	} else if (verify_flag == 'o') {
795 		load_address = CONFIG_SYS_LOAD_ADDR;
796 		strcat(slot_partition[1], requested_partitions[1]);
797 		ops->get_unique_guid_for_partition(ops,
798 						   slot_partition[1],
799 						   guid_buf,
800 						   guid_buf_size);
801 		strcat(root_data, guid_buf);
802 		command_line = android_assemble_cmdline(boot_slot_select,
803 							mode_cmdline);
804 		strcat(root_data, " ");
805 		strcat(root_data, command_line);
806 		env_set("bootargs", root_data);
807 		if (android_boot_flow(load_address)) {
808 			printf("Cannot boot the system, goto the fastboot!\n");
809 			avb_ops_user_free(ops);
810 			goto fail;
811 		}
812 		avb_ops_user_free(ops);
813 	} else {
814 		return CMD_RET_USAGE;
815 	}
816 
817 	return CMD_RET_SUCCESS;
818 fail:
819 	if (fastboot_cmd == NULL) {
820 		printf("fastboot_cmd is null, run default fastboot_cmd!\n");
821 		fastboot_cmd = "fastboot usb 0";
822 	}
823 
824 	return run_command(fastboot_cmd, CMD_FLAG_ENV);
825 }
826 
827 static cmd_tbl_t cmd_avb[] = {
828 	U_BOOT_CMD_MKENT(init, 1, 1, do_avb_init_ab_metadata, "", ""),
829 	U_BOOT_CMD_MKENT(version, 1, 1, do_avb_version, "", ""),
830 	U_BOOT_CMD_MKENT(slot_active, 2, 1,
831 			 do_avb_ab_mark_slot_active, "", ""),
832 	U_BOOT_CMD_MKENT(slot_unbootable, 2, 1,
833 			 do_avb_ab_mark_slot_unbootable, "", ""),
834 	U_BOOT_CMD_MKENT(slot_successful, 2, 1,
835 			 do_avb_ab_mark_slot_successful, "", ""),
836 	U_BOOT_CMD_MKENT(read_rollback, 2, 1,
837 			 do_avb_read_rollback_index, "", ""),
838 	U_BOOT_CMD_MKENT(write_rollback, 3, 1,
839 			 do_avb_write_rollback_index, "", ""),
840 	U_BOOT_CMD_MKENT(read_lock_status, 1, 1,
841 			 do_avb_read_is_device_unlocked, "", ""),
842 	U_BOOT_CMD_MKENT(write_lock_status, 2, 1,
843 			 do_avb_write_is_device_unlocked, "", ""),
844 	U_BOOT_CMD_MKENT(part_size, 2, 1,
845 			 do_avb_get_size_of_partition, "", ""),
846 	U_BOOT_CMD_MKENT(part_guid, 2, 1,
847 			 do_avb_get_get_unique_guid_for_partition, "", ""),
848 	U_BOOT_CMD_MKENT(read, 4, 1, do_avb_read, "", ""),
849 	U_BOOT_CMD_MKENT(write, 4, 1, do_avb_write, "", ""),
850 	U_BOOT_CMD_MKENT(readabmisc, 1, 1, do_avb_read_ab_metadata, "", ""),
851 	U_BOOT_CMD_MKENT(writeabmisc, 1, 1, do_avb_write_ab_metadata, "", ""),
852 	U_BOOT_CMD_MKENT(perm_attr_test, 1, 1, do_perm_attr_test, "", ""),
853 	U_BOOT_CMD_MKENT(verify, 3, 1, do_avb_verify_partition, "", ""),
854 	U_BOOT_CMD_MKENT(flow, 2, 1, do_avb_flow, "", "")
855 };
856 
857 static int do_boot_avb(cmd_tbl_t *cmdtp,
858 		       int flag,
859 		       int argc,
860 		       char * const argv[])
861 {
862 	cmd_tbl_t *cp;
863 
864 	cp = find_cmd_tbl(argv[1], cmd_avb, ARRAY_SIZE(cmd_avb));
865 
866 	argc--;
867 	argv++;
868 
869 	if (cp == NULL || argc > cp->maxargs)
870 		return CMD_RET_USAGE;
871 	if (flag == CMD_FLAG_REPEAT && !cp->repeatable)
872 		return CMD_RET_SUCCESS;
873 
874 	return cp->cmd(cmdtp, flag, argc, argv);
875 }
876 
877 U_BOOT_CMD(
878 	bootavb, 29, 1, do_boot_avb,
879 	"Execute the Android avb a/b boot flow.",
880 	"init - initialize the avbabmeta\n"
881 	"bootavb version - display info of bootavb version\n"
882 	"bootavb slot_active cnt\n"
883 	"bootavb slot_unbootable cnt\n"
884 	"bootavb slot_successful cnt\n"
885 	"bootavb read_rollback rollback_index_location\n"
886 	"bootavb write_rollback rollback_index_location out_rollback_index\n"
887 	"bootavb read_lock_status\n"
888 	"bootavb write_lock_status 0 or 1\n"
889 	"bootavb part_size partitions_name\n"
890 	"bootavb part_guid partitions_name\n"
891 	"bootavb read partition offset_blk cnt\n"
892 	"bootavb write partition offset_blk cnt\n"
893 	"bootavb readabmisc\n"
894 	"bootavb writeabmisc\n"
895 	"bootavb perm_attr_test\n"
896 	"bootavb verify partition slot_cnt;partion name without '_a' or '_b'\n"
897 	"bootavb flow v/n\n"
898 );
899 #endif
900