xref: /rk3399_rockchip-uboot/cmd/boot_android.c (revision 785b4fbf6c5db1eb4c0ddf983292d7ab077c4212)
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 
18 static int do_boot_android(cmd_tbl_t *cmdtp, int flag, int argc,
19 			   char * const argv[])
20 {
21 	unsigned long load_address;
22 	int ret = CMD_RET_SUCCESS;
23 	char *addr_arg_endp, *addr_str;
24 	struct blk_desc *dev_desc;
25 
26 	if (argc < 3)
27 		return CMD_RET_USAGE;
28 	if (argc > 5)
29 		return CMD_RET_USAGE;
30 
31 	if (argc >= 5) {
32 		load_address = simple_strtoul(argv[4], &addr_arg_endp, 16);
33 		if (addr_arg_endp == argv[4] || *addr_arg_endp != '\0')
34 			return CMD_RET_USAGE;
35 	} else {
36 		addr_str = env_get("kernel_addr_r");
37 		if (addr_str)
38 			load_address = simple_strtoul(addr_str, NULL, 16);
39 		else
40 			load_address = CONFIG_SYS_LOAD_ADDR;
41 	}
42 
43 	dev_desc = blk_get_dev(argv[1], simple_strtoul(argv[2], NULL, 16));
44 	if (!dev_desc) {
45 		printf("Could not get %s %s\n", argv[1], argv[2]);
46 		return CMD_RET_FAILURE;
47 	}
48 
49 	ret = android_bootloader_boot_flow(dev_desc, load_address);
50 	if (ret < 0) {
51 		printf("Android boot failed, error %d.\n", ret);
52 		return CMD_RET_FAILURE;
53 	}
54 	return CMD_RET_SUCCESS;
55 }
56 
57 U_BOOT_CMD(
58 	boot_android, 5, 0, do_boot_android,
59 	"Execute the Android Bootloader flow.",
60 	"<interface> <dev[:part|;part_name]> <slot> [<kernel_addr>]\n"
61 	"    - Load the Boot Control Block (BCB) from the partition 'part' on\n"
62 	"      device type 'interface' instance 'dev' to determine the boot\n"
63 	"      mode, and load and execute the appropriate kernel.\n"
64 	"      In normal and recovery mode, the kernel will be loaded from\n"
65 	"      the corresponding \"boot\" partition. In bootloader mode, the\n"
66 	"      command defined in the \"fastbootcmd\" variable will be\n"
67 	"      executed.\n"
68 	"      On Android devices with multiple slots, the pass 'slot' is\n"
69 	"      used to load the appropriate kernel. The standard slot names\n"
70 	"      are 'a' and 'b'.\n"
71 	"    - If 'part_name' is passed, preceded with a ; instead of :, the\n"
72 	"      partition name whose label is 'part_name' will be looked up in\n"
73 	"      the partition table. This is commonly the \"misc\" partition.\n"
74 );
75 
76 #ifdef CONFIG_AVB_LIBAVB_USER
77 static int bootloader_message_read(struct android_bootloader_message *data)
78 {
79 	AvbOps *ops;
80 	char requested_partitions[] = "misc";
81 	size_t out_num_read;
82 	char *buffer;
83 
84 	ops = avb_ops_user_new();
85 	buffer = (char *)data;
86 
87 	if (ops == NULL) {
88 		printf("avb_ops_user_new() failed!\n");
89 		return CMD_RET_FAILURE;
90 	}
91 
92 	if (ops->read_from_partition(ops, requested_partitions,
93 				     0, 2048, buffer,
94 				     &out_num_read) != 0) {
95 		printf("do avb read error!\n");
96 		avb_ops_user_free(ops);
97 		return CMD_RET_FAILURE;
98 	}
99 
100 	avb_ops_user_free(ops);
101 
102 	return CMD_RET_SUCCESS;
103 }
104 
105 static int bootloader_message_write(struct android_bootloader_message *data)
106 {
107 	AvbOps *ops;
108 	char requested_partitions[] = "misc";
109 	char *buffer;
110 
111 	ops = avb_ops_user_new();
112 	buffer = (char *)data;
113 
114 	if (ops == NULL) {
115 		printf("avb_ops_user_new() failed!\n");
116 		return CMD_RET_FAILURE;
117 	}
118 
119 	if (ops->write_to_partition(ops, requested_partitions,
120 				     0, 2048, buffer) != 0) {
121 		printf("do avb write error!\n");
122 		avb_ops_user_free(ops);
123 		return CMD_RET_FAILURE;
124 	}
125 
126 	avb_ops_user_free(ops);
127 
128 	return CMD_RET_SUCCESS;
129 }
130 
131 int do_avb_init_ab_metadata(cmd_tbl_t *cmdtp, int flag,
132 			    int argc, char * const argv[])
133 {
134 	AvbOps *ops;
135 	AvbABData ab_data;
136 
137 	memset(&ab_data, 0, sizeof(AvbABData));
138 	debug("sizeof(AvbABData) = %d\n", sizeof(AvbABData));
139 	if (argc != 1)
140 		return CMD_RET_USAGE;
141 
142 	ops = avb_ops_user_new();
143 	if (ops == NULL) {
144 		printf("avb_ops_user_new() failed!\n");
145 		return CMD_RET_FAILURE;
146 	}
147 
148 	ops->ab_ops->init_ab_metadata(&ab_data);
149 	debug("init");
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_load_ab_metadata(cmd_tbl_t *cmdtp, int flag,
520 			    int argc, char * const argv[])
521 {
522 	AvbOps *ops;
523 	AvbABData ab_data, ab_data_orig;
524 	char *data;
525 	int i;
526 
527 	if (argc != 1)
528 		return CMD_RET_USAGE;
529 
530 	ops = avb_ops_user_new();
531 	if (ops == NULL) {
532 		printf("avb_ops_user_new() failed!\n");
533 		return CMD_RET_FAILURE;
534 	}
535 
536 	if (load_metadata(ops->ab_ops, &ab_data, &ab_data_orig) != 0) {
537 		printf("do_avb_write_ab_metadata error!\n");
538 		avb_ops_user_free(ops);
539 		return CMD_RET_FAILURE;
540 	}
541 
542 	data = (char *)&ab_data;
543 	for (i = 0; i < 33; i++)
544 		printf("%d\n", data[i]);
545 
546 	avb_ops_user_free(ops);
547 
548 	return CMD_RET_SUCCESS;
549 }
550 
551 int do_avb_read_ab_metadata(cmd_tbl_t *cmdtp, int flag,
552 			    int argc, char * const argv[])
553 {
554 	AvbOps *ops;
555 	AvbABData ab_data;
556 
557 	if (argc != 1)
558 		return CMD_RET_USAGE;
559 
560 	ops = avb_ops_user_new();
561 	if (ops == NULL) {
562 		printf("avb_ops_user_new() failed!\n");
563 		return CMD_RET_FAILURE;
564 	}
565 
566 	if (ops->ab_ops->read_ab_metadata(ops->ab_ops, &ab_data) != 0) {
567 		printf("do_avb_write_ab_metadata error!\n");
568 		avb_ops_user_free(ops);
569 		return CMD_RET_FAILURE;
570 	}
571 
572 	avb_ops_user_free(ops);
573 
574 	return CMD_RET_SUCCESS;
575 }
576 
577 int do_avb_write_ab_metadata(cmd_tbl_t *cmdtp, int flag,
578 			     int argc, char * const argv[])
579 {
580 	AvbOps *ops;
581 	AvbABData ab_data;
582 
583 	if (argc != 1)
584 		return CMD_RET_USAGE;
585 
586 	ops = avb_ops_user_new();
587 	if (ops == NULL) {
588 		printf("avb_ops_user_new() failed!\n");
589 		return CMD_RET_FAILURE;
590 	}
591 
592 	if (ops->ab_ops->write_ab_metadata(ops->ab_ops, &ab_data) != 0) {
593 		printf("do_avb_write_ab_metadata error!\n");
594 		avb_ops_user_free(ops);
595 		return CMD_RET_FAILURE;
596 	}
597 
598 	avb_ops_user_free(ops);
599 
600 	return CMD_RET_SUCCESS;
601 }
602 
603 int do_avb_verify_partition(cmd_tbl_t *cmdtp, int flag,
604 			    int argc, char * const argv[])
605 {
606 	AvbOps *ops;
607 	const char *requested_partitions[1];
608 	const char * slot_suffixes[2] = {"_a", "_b"};
609 	AvbSlotVerifyFlags flags;
610 	AvbSlotVerifyData *slot_data[2] = {NULL, NULL};
611 	AvbSlotVerifyResult verify_result;
612 	size_t n;
613 
614 	if (argc != 3)
615 		return CMD_RET_USAGE;
616 
617 	requested_partitions[0] = argv[1];
618 	n = simple_strtoul(argv[2], NULL, 16);
619 	ops = avb_ops_user_new();
620 	flags = AVB_SLOT_VERIFY_FLAGS_NONE;
621 	verify_result =
622 		avb_slot_verify(ops,
623 				requested_partitions,
624 				slot_suffixes[n],
625 				flags,
626 				AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
627 				&slot_data[n]);
628 	if (verify_result != 0)
629 		return CMD_RET_FAILURE;
630 
631 	avb_ops_user_free(ops);
632 
633 	return CMD_RET_SUCCESS;
634 }
635 
636 int do_avb_flow(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
637 {
638 	char slot_partition[2][20] = {{0}, {0}};
639 	unsigned long load_address;
640 	AvbOps *ops;
641 	const char *avb_version;
642 	AvbSlotVerifyData *slot_data;
643 	AvbSlotVerifyFlags flags;
644 	const char *requested_partitions[] = {"boot", "system", NULL};
645 	char *command_line;
646 	bool unlocked = true;
647 	const char *mode_cmdline = NULL;
648 	char root_data[70] = "root=PARTUUID=";
649 	char avb_root_data[2000] = {0};
650 	size_t guid_buf_size = 37;
651 	char guid_buf[37];
652 	char verify_flag;
653 	char boot_slot_select[5];
654 	struct android_bootloader_message data;
655 	const char *fastboot_cmd = env_get("fastbootcmd");
656 
657 	if (argc != 2)
658 		return CMD_RET_USAGE;
659 
660 	bootloader_message_read(&data);
661 	if (!strcmp("bootonce-bootloader", data.command)) {
662 		memset(data.command, 0, sizeof(data.command));
663 		bootloader_message_write(&data);
664 		if (fastboot_cmd) {
665 			printf("bootonce-bootloader!\n");
666 			return run_command(fastboot_cmd, CMD_FLAG_ENV);
667 		} else {
668 			printf("The fastbootcmd is NULL!\n");
669 			return CMD_RET_SUCCESS;
670 		}
671 	} else if (!strcmp("boot-recovery", data.command)) {
672 		printf("Enter boot-recovery!\n");
673 	} else if(!strcmp("boot-normal", data.command)) {
674 		printf("Enter boot-normal!\n");
675 		mode_cmdline = "skip_initramfs";
676 	} else {
677 		/*
678 		 * Firstly, confirm if there is a command in misc partition in
679 		 * previous cases, and then we need to confirm whether user has
680 		 * requested to enter recovery mode by entering "reboot recovery"
681 		 * command through adb or serial console.
682 		 */
683 		char *env_rebootmode = env_get("reboot_mode");
684 
685 		if (env_rebootmode && !strcmp("recovery", env_rebootmode))
686 			printf("Enter recovery mode by command 'reboot recovery'!\n");
687 		else
688 			mode_cmdline = "skip_initramfs";
689 	}
690 
691 	avb_version = avb_version_string();
692 	printf("Android avb version is %s.\n", avb_version);
693 	ops = avb_ops_user_new();
694 	if (ops == NULL)
695 		printf("avb_ops_user_new() failed!\n");
696 
697 	if (ops->read_is_device_unlocked(ops, &unlocked) != 0)
698 		printf("Error determining whether device is unlocked.\n");
699 
700 	printf("read_is_device_unlocked() ops returned that device is %s\n",
701 	       unlocked ? "UNLOCKED" : "LOCKED");
702 
703 	flags = AVB_SLOT_VERIFY_FLAGS_NONE;
704 	if (unlocked)
705 		flags |= AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR;
706 
707 	verify_flag = argv[1][0];
708 	if (verify_flag == 'v') {
709 		debug("start with verify!\n");
710 		if (avb_ab_flow(ops->ab_ops,
711 				requested_partitions,
712 				flags,
713 				AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
714 				&slot_data)) {
715 			avb_slot_verify_data_free(slot_data);
716 			avb_ops_user_free(ops);
717 			printf("avb_ab_flow() error!\n");
718 			return CMD_RET_FAILURE;
719 		}
720 
721 		command_line = android_assemble_cmdline(slot_data->ab_suffix,
722 							mode_cmdline);
723 		strcat(avb_root_data, " ");
724 		strcat(avb_root_data, command_line);
725 		strcat(avb_root_data, " ");
726 		strcat(avb_root_data, slot_data->cmdline);
727 		env_set("bootargs", avb_root_data);
728 		load_address = CONFIG_SYS_LOAD_ADDR;
729 		if (avb_close_optee_client())
730 			printf("Can not close optee client!\n");
731 
732 		memcpy((uint8_t*)load_address,
733 		       slot_data->loaded_partitions->data,
734 		       slot_data->loaded_partitions->data_size);
735 		android_bootloader_boot_kernel(load_address);
736 	} else if (verify_flag == 'n') {
737 		load_address = CONFIG_SYS_LOAD_ADDR;
738 		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 		android_avb_boot_flow(boot_slot_select, load_address);
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 		android_boot_flow(load_address);
767 	} else {
768 		return CMD_RET_USAGE;
769 	}
770 
771 	return CMD_RET_SUCCESS;
772 }
773 
774 static cmd_tbl_t cmd_avb[] = {
775 	U_BOOT_CMD_MKENT(init, 1, 1, do_avb_init_ab_metadata, "", ""),
776 	U_BOOT_CMD_MKENT(version, 1, 1, do_avb_version, "", ""),
777 	U_BOOT_CMD_MKENT(slot_active, 2, 1,
778 			 do_avb_ab_mark_slot_active, "", ""),
779 	U_BOOT_CMD_MKENT(slot_unbootable, 2, 1,
780 			 do_avb_ab_mark_slot_unbootable, "", ""),
781 	U_BOOT_CMD_MKENT(slot_successful, 2, 1,
782 			 do_avb_ab_mark_slot_successful, "", ""),
783 	U_BOOT_CMD_MKENT(read_rollback, 2, 1,
784 			 do_avb_read_rollback_index, "", ""),
785 	U_BOOT_CMD_MKENT(write_rollback, 3, 1,
786 			 do_avb_write_rollback_index, "", ""),
787 	U_BOOT_CMD_MKENT(read_lock_status, 1, 1,
788 			 do_avb_read_is_device_unlocked, "", ""),
789 	U_BOOT_CMD_MKENT(write_lock_status, 2, 1,
790 			 do_avb_write_is_device_unlocked, "", ""),
791 	U_BOOT_CMD_MKENT(part_size, 2, 1,
792 			 do_avb_get_size_of_partition, "", ""),
793 	U_BOOT_CMD_MKENT(part_guid, 2, 1,
794 			 do_avb_get_get_unique_guid_for_partition, "", ""),
795 	U_BOOT_CMD_MKENT(read, 4, 1, do_avb_read, "", ""),
796 	U_BOOT_CMD_MKENT(write, 4, 1, do_avb_write, "", ""),
797 	U_BOOT_CMD_MKENT(loadabmisc, 1, 1, do_avb_load_ab_metadata, "", ""),
798 	U_BOOT_CMD_MKENT(readabmisc, 1, 1, do_avb_read_ab_metadata, "", ""),
799 	U_BOOT_CMD_MKENT(writeabmisc, 1, 1, do_avb_write_ab_metadata, "", ""),
800 	U_BOOT_CMD_MKENT(verify, 3, 1, do_avb_verify_partition, "", ""),
801 	U_BOOT_CMD_MKENT(flow, 2, 1, do_avb_flow, "", "")
802 };
803 
804 static int do_boot_avb(cmd_tbl_t *cmdtp,
805 		       int flag,
806 		       int argc,
807 		       char * const argv[])
808 {
809 	cmd_tbl_t *cp;
810 
811 	cp = find_cmd_tbl(argv[1], cmd_avb, ARRAY_SIZE(cmd_avb));
812 
813 	argc--;
814 	argv++;
815 
816 	if (cp == NULL || argc > cp->maxargs)
817 		return CMD_RET_USAGE;
818 	if (flag == CMD_FLAG_REPEAT && !cp->repeatable)
819 		return CMD_RET_SUCCESS;
820 
821 	return cp->cmd(cmdtp, flag, argc, argv);
822 }
823 
824 U_BOOT_CMD(
825 	bootavb, 29, 1, do_boot_avb,
826 	"Execute the Android avb a/b boot flow.",
827 	"init - initialize the avbabmeta\n"
828 	"bootavb version - display info of bootavb version\n"
829 	"bootavb slot_active cnt\n"
830 	"bootavb slot_unbootable cnt\n"
831 	"bootavb slot_successful cnt\n"
832 	"bootavb read_rollback rollback_index_location\n"
833 	"bootavb write_rollback rollback_index_location out_rollback_index\n"
834 	"bootavb read_lock_status\n"
835 	"bootavb write_lock_status 0 or 1\n"
836 	"bootavb part_size partitions_name\n"
837 	"bootavb part_guid partitions_name\n"
838 	"bootavb read partition offset_blk cnt\n"
839 	"bootavb write partition offset_blk cnt\n"
840 	"bootavb loadabmisc\n"
841 	"bootavb readabmisc\n"
842 	"bootavb writeabmisc\n"
843 	"bootavb verify partition slot_cnt;partion name without '_a' or '_b'\n"
844 	"bootavb flow v/n\n"
845 );
846 #endif
847