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