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