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