xref: /rk3399_rockchip-uboot/cmd/boot_android.c (revision e8e29e8d8b70fc092891ebc18d0488d061d26c38)
106f4a874SAlex Deymo /*
206f4a874SAlex Deymo  * Copyright (C) 2016 The Android Open Source Project
306f4a874SAlex Deymo  *
406f4a874SAlex Deymo  * SPDX-License-Identifier: BSD-2-Clause
506f4a874SAlex Deymo  */
606f4a874SAlex Deymo 
706f4a874SAlex Deymo #include <android_bootloader.h>
8*e8e29e8dSJason Zhu #include <android_avb/avb_version.h>
9*e8e29e8dSJason Zhu #include <android_avb/avb_ab_flow.h>
10*e8e29e8dSJason Zhu #include <android_avb/avb_ops_user.h>
11180cc7c6SAlex Deymo #include <android_cmds.h>
12*e8e29e8dSJason Zhu #include <malloc.h>
1306f4a874SAlex Deymo #include <common.h>
14*e8e29e8dSJason Zhu #include <bootm.h>
1506f4a874SAlex Deymo #include <command.h>
1606f4a874SAlex Deymo 
1706f4a874SAlex Deymo static int do_boot_android(cmd_tbl_t *cmdtp, int flag, int argc,
1806f4a874SAlex Deymo 			   char * const argv[])
1906f4a874SAlex Deymo {
2006f4a874SAlex Deymo 	unsigned long load_address;
2106f4a874SAlex Deymo 	int ret = CMD_RET_SUCCESS;
2206f4a874SAlex Deymo 	char *addr_arg_endp, *addr_str;
2306f4a874SAlex Deymo 	struct blk_desc *dev_desc;
2406f4a874SAlex Deymo 	disk_partition_t part_info;
2506f4a874SAlex Deymo 
2680622240SAlex Deymo 	if (argc < 4)
2706f4a874SAlex Deymo 		return CMD_RET_USAGE;
2880622240SAlex Deymo 	if (argc > 5)
2906f4a874SAlex Deymo 		return CMD_RET_USAGE;
3006f4a874SAlex Deymo 
3180622240SAlex Deymo 	if (argc >= 5) {
3280622240SAlex Deymo 		load_address = simple_strtoul(argv[4], &addr_arg_endp, 16);
3380622240SAlex Deymo 		if (addr_arg_endp == argv[4] || *addr_arg_endp != '\0')
3406f4a874SAlex Deymo 			return CMD_RET_USAGE;
3506f4a874SAlex Deymo 	} else {
3606f4a874SAlex Deymo 		addr_str = env_get("loadaddr");
3706f4a874SAlex Deymo 		if (addr_str)
3806f4a874SAlex Deymo 			load_address = simple_strtoul(addr_str, NULL, 16);
3906f4a874SAlex Deymo 		else
4006f4a874SAlex Deymo 			load_address = CONFIG_SYS_LOAD_ADDR;
4106f4a874SAlex Deymo 	}
4206f4a874SAlex Deymo 
43180cc7c6SAlex Deymo 	if (part_get_info_by_dev_and_name_or_num(argv[1], argv[2],
4406f4a874SAlex Deymo 						 &dev_desc, &part_info) < 0) {
4506f4a874SAlex Deymo 		return CMD_RET_FAILURE;
4606f4a874SAlex Deymo 	}
4706f4a874SAlex Deymo 
4880622240SAlex Deymo 	ret = android_bootloader_boot_flow(dev_desc, &part_info, argv[3],
4980622240SAlex Deymo 					   load_address);
5006f4a874SAlex Deymo 	if (ret < 0) {
5106f4a874SAlex Deymo 		printf("Android boot failed, error %d.\n", ret);
5206f4a874SAlex Deymo 		return CMD_RET_FAILURE;
5306f4a874SAlex Deymo 	}
5406f4a874SAlex Deymo 	return CMD_RET_SUCCESS;
5506f4a874SAlex Deymo }
5606f4a874SAlex Deymo 
5706f4a874SAlex Deymo U_BOOT_CMD(
5880622240SAlex Deymo 	boot_android, 5, 0, do_boot_android,
5906f4a874SAlex Deymo 	"Execute the Android Bootloader flow.",
60df7cce43SAlex Deymo 	"<interface> <dev[:part|;part_name]> <slot> [<kernel_addr>]\n"
6106f4a874SAlex Deymo 	"    - Load the Boot Control Block (BCB) from the partition 'part' on\n"
6206f4a874SAlex Deymo 	"      device type 'interface' instance 'dev' to determine the boot\n"
6306f4a874SAlex Deymo 	"      mode, and load and execute the appropriate kernel.\n"
6406f4a874SAlex Deymo 	"      In normal and recovery mode, the kernel will be loaded from\n"
6506f4a874SAlex Deymo 	"      the corresponding \"boot\" partition. In bootloader mode, the\n"
6606f4a874SAlex Deymo 	"      command defined in the \"fastbootcmd\" variable will be\n"
6706f4a874SAlex Deymo 	"      executed.\n"
6880622240SAlex Deymo 	"      On Android devices with multiple slots, the pass 'slot' is\n"
6980622240SAlex Deymo 	"      used to load the appropriate kernel. The standard slot names\n"
7080622240SAlex Deymo 	"      are 'a' and 'b'.\n"
7106f4a874SAlex Deymo 	"    - If 'part_name' is passed, preceded with a ; instead of :, the\n"
7206f4a874SAlex Deymo 	"      partition name whose label is 'part_name' will be looked up in\n"
7306f4a874SAlex Deymo 	"      the partition table. This is commonly the \"misc\" partition.\n"
7406f4a874SAlex Deymo );
75*e8e29e8dSJason Zhu 
76*e8e29e8dSJason Zhu #ifdef CONFIG_AVB_LIBAVB_USER
77*e8e29e8dSJason Zhu int do_avb_init_ab_metadata(cmd_tbl_t *cmdtp, int flag,
78*e8e29e8dSJason Zhu 			    int argc, char * const argv[])
79*e8e29e8dSJason Zhu {
80*e8e29e8dSJason Zhu 	AvbOps *ops;
81*e8e29e8dSJason Zhu 	AvbABData ab_data;
82*e8e29e8dSJason Zhu 
83*e8e29e8dSJason Zhu 	memset(&ab_data, 0, sizeof(AvbABData));
84*e8e29e8dSJason Zhu 	debug("sizeof(AvbABData) = %d\n", sizeof(AvbABData));
85*e8e29e8dSJason Zhu 	if (argc != 1)
86*e8e29e8dSJason Zhu 		return CMD_RET_USAGE;
87*e8e29e8dSJason Zhu 
88*e8e29e8dSJason Zhu 	ops = avb_ops_user_new();
89*e8e29e8dSJason Zhu 	if (ops == NULL) {
90*e8e29e8dSJason Zhu 		printf("avb_ops_user_new() failed!\n");
91*e8e29e8dSJason Zhu 		return CMD_RET_FAILURE;
92*e8e29e8dSJason Zhu 	}
93*e8e29e8dSJason Zhu 
94*e8e29e8dSJason Zhu 	ops->ab_ops->init_ab_metadata(&ab_data);
95*e8e29e8dSJason Zhu 	debug("init");
96*e8e29e8dSJason Zhu 	if (ops->ab_ops->write_ab_metadata(ops->ab_ops, &ab_data) != 0) {
97*e8e29e8dSJason Zhu 		printf("do_avb_init_ab_metadata error!\n");
98*e8e29e8dSJason Zhu 		avb_ops_user_free(ops);
99*e8e29e8dSJason Zhu 		return CMD_RET_FAILURE;
100*e8e29e8dSJason Zhu 	}
101*e8e29e8dSJason Zhu 
102*e8e29e8dSJason Zhu 	avb_ops_user_free(ops);
103*e8e29e8dSJason Zhu 
104*e8e29e8dSJason Zhu 	return CMD_RET_SUCCESS;
105*e8e29e8dSJason Zhu }
106*e8e29e8dSJason Zhu 
107*e8e29e8dSJason Zhu int do_avb_version(cmd_tbl_t *cmdtp, int flag, int argc,
108*e8e29e8dSJason Zhu 		   char * const argv[])
109*e8e29e8dSJason Zhu {
110*e8e29e8dSJason Zhu 	const char *avb_version;
111*e8e29e8dSJason Zhu 
112*e8e29e8dSJason Zhu 	if (argc != 1)
113*e8e29e8dSJason Zhu 		return CMD_RET_USAGE;
114*e8e29e8dSJason Zhu 
115*e8e29e8dSJason Zhu 	avb_version = avb_version_string();
116*e8e29e8dSJason Zhu 	printf("Android avb version is %s.\n", avb_version);
117*e8e29e8dSJason Zhu 
118*e8e29e8dSJason Zhu 	return CMD_RET_SUCCESS;
119*e8e29e8dSJason Zhu }
120*e8e29e8dSJason Zhu 
121*e8e29e8dSJason Zhu int do_avb_ab_mark_slot_active(cmd_tbl_t *cmdtp, int flag,
122*e8e29e8dSJason Zhu 			       int argc, char * const argv[])
123*e8e29e8dSJason Zhu {
124*e8e29e8dSJason Zhu 	AvbOps *ops;
125*e8e29e8dSJason Zhu 	unsigned int slot_number;
126*e8e29e8dSJason Zhu 
127*e8e29e8dSJason Zhu 	if (argc != 2)
128*e8e29e8dSJason Zhu 		return CMD_RET_USAGE;
129*e8e29e8dSJason Zhu 
130*e8e29e8dSJason Zhu 	ops = avb_ops_user_new();
131*e8e29e8dSJason Zhu 	if (ops == NULL) {
132*e8e29e8dSJason Zhu 		printf("avb_ops_user_new() failed!\n");
133*e8e29e8dSJason Zhu 		return CMD_RET_FAILURE;
134*e8e29e8dSJason Zhu 	}
135*e8e29e8dSJason Zhu 
136*e8e29e8dSJason Zhu 	slot_number = simple_strtoul(argv[1], NULL, 16);
137*e8e29e8dSJason Zhu 	if (avb_ab_mark_slot_active(ops->ab_ops, slot_number) != 0) {
138*e8e29e8dSJason Zhu 		printf("avb_ab_mark_slot_active error!\n");
139*e8e29e8dSJason Zhu 		avb_ops_user_free(ops);
140*e8e29e8dSJason Zhu 		return CMD_RET_FAILURE;
141*e8e29e8dSJason Zhu 	}
142*e8e29e8dSJason Zhu 
143*e8e29e8dSJason Zhu 	avb_ops_user_free(ops);
144*e8e29e8dSJason Zhu 
145*e8e29e8dSJason Zhu 	return CMD_RET_SUCCESS;
146*e8e29e8dSJason Zhu }
147*e8e29e8dSJason Zhu 
148*e8e29e8dSJason Zhu int do_avb_ab_mark_slot_unbootable(cmd_tbl_t *cmdtp, int flag,
149*e8e29e8dSJason Zhu 				   int argc, char * const argv[])
150*e8e29e8dSJason Zhu {
151*e8e29e8dSJason Zhu 	AvbOps *ops;
152*e8e29e8dSJason Zhu 	unsigned int slot_number;
153*e8e29e8dSJason Zhu 
154*e8e29e8dSJason Zhu 	if (argc != 2)
155*e8e29e8dSJason Zhu 		return CMD_RET_USAGE;
156*e8e29e8dSJason Zhu 
157*e8e29e8dSJason Zhu 	ops = avb_ops_user_new();
158*e8e29e8dSJason Zhu 	if (ops == NULL) {
159*e8e29e8dSJason Zhu 		printf("avb_ops_user_new() failed!\n");
160*e8e29e8dSJason Zhu 		return CMD_RET_FAILURE;
161*e8e29e8dSJason Zhu 	}
162*e8e29e8dSJason Zhu 
163*e8e29e8dSJason Zhu 	slot_number = simple_strtoul(argv[1], NULL, 16);
164*e8e29e8dSJason Zhu 	if (avb_ab_mark_slot_unbootable(ops->ab_ops, slot_number) != 0) {
165*e8e29e8dSJason Zhu 		printf("do_avb_ab_mark_slot_unbootable error!\n");
166*e8e29e8dSJason Zhu 		avb_ops_user_free(ops);
167*e8e29e8dSJason Zhu 		return CMD_RET_FAILURE;
168*e8e29e8dSJason Zhu 	}
169*e8e29e8dSJason Zhu 
170*e8e29e8dSJason Zhu 	avb_ops_user_free(ops);
171*e8e29e8dSJason Zhu 
172*e8e29e8dSJason Zhu 	return CMD_RET_SUCCESS;
173*e8e29e8dSJason Zhu }
174*e8e29e8dSJason Zhu 
175*e8e29e8dSJason Zhu int do_avb_ab_mark_slot_successful(cmd_tbl_t *cmdtp, int flag,
176*e8e29e8dSJason Zhu 				   int argc, char * const argv[])
177*e8e29e8dSJason Zhu {
178*e8e29e8dSJason Zhu 	AvbOps *ops;
179*e8e29e8dSJason Zhu 	unsigned int slot_number;
180*e8e29e8dSJason Zhu 
181*e8e29e8dSJason Zhu 	if (argc != 2)
182*e8e29e8dSJason Zhu 		return CMD_RET_USAGE;
183*e8e29e8dSJason Zhu 
184*e8e29e8dSJason Zhu 	ops = avb_ops_user_new();
185*e8e29e8dSJason Zhu 	if (ops == NULL) {
186*e8e29e8dSJason Zhu 		printf("avb_ops_user_new() failed!\n");
187*e8e29e8dSJason Zhu 		return CMD_RET_FAILURE;
188*e8e29e8dSJason Zhu 	}
189*e8e29e8dSJason Zhu 
190*e8e29e8dSJason Zhu 	slot_number = simple_strtoul(argv[1], NULL, 16);
191*e8e29e8dSJason Zhu 	if (avb_ab_mark_slot_successful(ops->ab_ops, slot_number) != 0) {
192*e8e29e8dSJason Zhu 		printf("do_avb_ab_mark_slot_successful error!\n");
193*e8e29e8dSJason Zhu 		avb_ops_user_free(ops);
194*e8e29e8dSJason Zhu 		return CMD_RET_FAILURE;
195*e8e29e8dSJason Zhu 	}
196*e8e29e8dSJason Zhu 
197*e8e29e8dSJason Zhu 	avb_ops_user_free(ops);
198*e8e29e8dSJason Zhu 
199*e8e29e8dSJason Zhu 	return CMD_RET_SUCCESS;
200*e8e29e8dSJason Zhu }
201*e8e29e8dSJason Zhu 
202*e8e29e8dSJason Zhu int do_avb_read_rollback_index(cmd_tbl_t *cmdtp, int flag,
203*e8e29e8dSJason Zhu 			       int argc, char * const argv[])
204*e8e29e8dSJason Zhu {
205*e8e29e8dSJason Zhu 	AvbOps *ops;
206*e8e29e8dSJason Zhu 	uint64_t out_rollback_index;
207*e8e29e8dSJason Zhu 	size_t rollback_index_location;
208*e8e29e8dSJason Zhu 
209*e8e29e8dSJason Zhu 	if (argc != 2)
210*e8e29e8dSJason Zhu 		return CMD_RET_USAGE;
211*e8e29e8dSJason Zhu 
212*e8e29e8dSJason Zhu 	ops = avb_ops_user_new();
213*e8e29e8dSJason Zhu 	if (ops == NULL) {
214*e8e29e8dSJason Zhu 		printf("avb_ops_user_new() failed!\n");
215*e8e29e8dSJason Zhu 		return CMD_RET_FAILURE;
216*e8e29e8dSJason Zhu 	}
217*e8e29e8dSJason Zhu 
218*e8e29e8dSJason Zhu 	rollback_index_location = simple_strtoul(argv[1], NULL, 16);
219*e8e29e8dSJason Zhu 	if (ops->read_rollback_index(ops, rollback_index_location,
220*e8e29e8dSJason Zhu 				     &out_rollback_index) != 0) {
221*e8e29e8dSJason Zhu 		printf("do_avb_read_rollback_index error!\n");
222*e8e29e8dSJason Zhu 		avb_ops_user_free(ops);
223*e8e29e8dSJason Zhu 		return CMD_RET_FAILURE;
224*e8e29e8dSJason Zhu 	}
225*e8e29e8dSJason Zhu 
226*e8e29e8dSJason Zhu 	printf("out_rollback_index = %llx\n", out_rollback_index);
227*e8e29e8dSJason Zhu 	avb_ops_user_free(ops);
228*e8e29e8dSJason Zhu 
229*e8e29e8dSJason Zhu 	return CMD_RET_SUCCESS;
230*e8e29e8dSJason Zhu }
231*e8e29e8dSJason Zhu 
232*e8e29e8dSJason Zhu int do_avb_write_rollback_index(cmd_tbl_t *cmdtp, int flag,
233*e8e29e8dSJason Zhu 				int argc, char * const argv[])
234*e8e29e8dSJason Zhu {
235*e8e29e8dSJason Zhu 	AvbOps *ops;
236*e8e29e8dSJason Zhu 	uint64_t out_rollback_index;
237*e8e29e8dSJason Zhu 	size_t rollback_index_location;
238*e8e29e8dSJason Zhu 
239*e8e29e8dSJason Zhu 	if (argc != 3)
240*e8e29e8dSJason Zhu 		return CMD_RET_USAGE;
241*e8e29e8dSJason Zhu 
242*e8e29e8dSJason Zhu 	rollback_index_location = simple_strtoul(argv[1], NULL, 16);
243*e8e29e8dSJason Zhu 	out_rollback_index = simple_strtoull(argv[2], NULL, 16);
244*e8e29e8dSJason Zhu 	debug("out_rollback_index = %llx\n", out_rollback_index);
245*e8e29e8dSJason Zhu 	ops = avb_ops_user_new();
246*e8e29e8dSJason Zhu 	if (ops == NULL) {
247*e8e29e8dSJason Zhu 		printf("avb_ops_user_new() failed!\n");
248*e8e29e8dSJason Zhu 		return CMD_RET_FAILURE;
249*e8e29e8dSJason Zhu 	}
250*e8e29e8dSJason Zhu 
251*e8e29e8dSJason Zhu 	if (ops->write_rollback_index(ops, rollback_index_location,
252*e8e29e8dSJason Zhu 				      out_rollback_index) != 0) {
253*e8e29e8dSJason Zhu 		printf("do_avb_write_rollback_index error!\n");
254*e8e29e8dSJason Zhu 		avb_ops_user_free(ops);
255*e8e29e8dSJason Zhu 		return CMD_RET_FAILURE;
256*e8e29e8dSJason Zhu 	}
257*e8e29e8dSJason Zhu 
258*e8e29e8dSJason Zhu 	avb_ops_user_free(ops);
259*e8e29e8dSJason Zhu 
260*e8e29e8dSJason Zhu 	return CMD_RET_SUCCESS;
261*e8e29e8dSJason Zhu }
262*e8e29e8dSJason Zhu 
263*e8e29e8dSJason Zhu int do_avb_read_is_device_unlocked(cmd_tbl_t *cmdtp, int flag,
264*e8e29e8dSJason Zhu 				   int argc, char * const argv[])
265*e8e29e8dSJason Zhu {
266*e8e29e8dSJason Zhu 	AvbOps *ops;
267*e8e29e8dSJason Zhu 	bool out_is_unlocked;
268*e8e29e8dSJason Zhu 
269*e8e29e8dSJason Zhu 	if (argc != 1)
270*e8e29e8dSJason Zhu 		return CMD_RET_USAGE;
271*e8e29e8dSJason Zhu 
272*e8e29e8dSJason Zhu 	ops = avb_ops_user_new();
273*e8e29e8dSJason Zhu 	if (ops == NULL) {
274*e8e29e8dSJason Zhu 		printf("avb_ops_user_new() failed!\n");
275*e8e29e8dSJason Zhu 		return CMD_RET_FAILURE;
276*e8e29e8dSJason Zhu 	}
277*e8e29e8dSJason Zhu 
278*e8e29e8dSJason Zhu 	if (ops->read_is_device_unlocked(ops, &out_is_unlocked) != 0) {
279*e8e29e8dSJason Zhu 		printf("do_avb_read_is_device_unlocked error!\n");
280*e8e29e8dSJason Zhu 		avb_ops_user_free(ops);
281*e8e29e8dSJason Zhu 		return CMD_RET_FAILURE;
282*e8e29e8dSJason Zhu 	}
283*e8e29e8dSJason Zhu 
284*e8e29e8dSJason Zhu 	debug("out_is_unlocked = %d\n", out_is_unlocked);
285*e8e29e8dSJason Zhu 	avb_ops_user_free(ops);
286*e8e29e8dSJason Zhu 
287*e8e29e8dSJason Zhu 	return CMD_RET_SUCCESS;
288*e8e29e8dSJason Zhu }
289*e8e29e8dSJason Zhu int do_avb_write_is_device_unlocked(cmd_tbl_t *cmdtp, int flag,
290*e8e29e8dSJason Zhu 				    int argc, char * const argv[])
291*e8e29e8dSJason Zhu {
292*e8e29e8dSJason Zhu 	AvbOps *ops;
293*e8e29e8dSJason Zhu 	bool out_is_unlocked;
294*e8e29e8dSJason Zhu 
295*e8e29e8dSJason Zhu 	if (argc != 2)
296*e8e29e8dSJason Zhu 		return CMD_RET_USAGE;
297*e8e29e8dSJason Zhu 
298*e8e29e8dSJason Zhu 	out_is_unlocked = simple_strtoul(argv[1], NULL, 16);
299*e8e29e8dSJason Zhu 	if ((out_is_unlocked != 0) || (out_is_unlocked != 1))
300*e8e29e8dSJason Zhu 		printf("enter out_is_unlocked value must is '0' or '1'\n");
301*e8e29e8dSJason Zhu 
302*e8e29e8dSJason Zhu 	ops = avb_ops_user_new();
303*e8e29e8dSJason Zhu 	if (ops == NULL) {
304*e8e29e8dSJason Zhu 		printf("avb_ops_user_new() failed!\n");
305*e8e29e8dSJason Zhu 		return CMD_RET_FAILURE;
306*e8e29e8dSJason Zhu 	}
307*e8e29e8dSJason Zhu 
308*e8e29e8dSJason Zhu 	if (ops->write_is_device_unlocked(ops, &out_is_unlocked) != 0) {
309*e8e29e8dSJason Zhu 		printf("do_avb_write_is_device_unlocked error!\n");
310*e8e29e8dSJason Zhu 		avb_ops_user_free(ops);
311*e8e29e8dSJason Zhu 		return CMD_RET_FAILURE;
312*e8e29e8dSJason Zhu 	}
313*e8e29e8dSJason Zhu 
314*e8e29e8dSJason Zhu 	debug("out_is_unlocked = %d\n", out_is_unlocked);
315*e8e29e8dSJason Zhu 	avb_ops_user_free(ops);
316*e8e29e8dSJason Zhu 
317*e8e29e8dSJason Zhu 	return CMD_RET_SUCCESS;
318*e8e29e8dSJason Zhu }
319*e8e29e8dSJason Zhu 
320*e8e29e8dSJason Zhu int do_avb_get_size_of_partition(cmd_tbl_t *cmdtp, int flag,
321*e8e29e8dSJason Zhu 				 int argc, char * const argv[])
322*e8e29e8dSJason Zhu {
323*e8e29e8dSJason Zhu 	AvbOps *ops;
324*e8e29e8dSJason Zhu 	char *requested_partitions;
325*e8e29e8dSJason Zhu 	uint64_t out_size_in_bytes;
326*e8e29e8dSJason Zhu 
327*e8e29e8dSJason Zhu 	if (argc != 2)
328*e8e29e8dSJason Zhu 		return CMD_RET_USAGE;
329*e8e29e8dSJason Zhu 
330*e8e29e8dSJason Zhu 	requested_partitions = argv[1];
331*e8e29e8dSJason Zhu 	ops = avb_ops_user_new();
332*e8e29e8dSJason Zhu 	if (ops == NULL) {
333*e8e29e8dSJason Zhu 		printf("avb_ops_user_new() failed!\n");
334*e8e29e8dSJason Zhu 		return CMD_RET_FAILURE;
335*e8e29e8dSJason Zhu 	}
336*e8e29e8dSJason Zhu 
337*e8e29e8dSJason Zhu 	if (ops->get_size_of_partition(ops, requested_partitions,
338*e8e29e8dSJason Zhu 				       &out_size_in_bytes) != 0) {
339*e8e29e8dSJason Zhu 		printf("do_avb_get_size_of_partition error!\n");
340*e8e29e8dSJason Zhu 		avb_ops_user_free(ops);
341*e8e29e8dSJason Zhu 		return CMD_RET_FAILURE;
342*e8e29e8dSJason Zhu 	}
343*e8e29e8dSJason Zhu 
344*e8e29e8dSJason Zhu 	printf("partition size = %lld\n", out_size_in_bytes);
345*e8e29e8dSJason Zhu 	avb_ops_user_free(ops);
346*e8e29e8dSJason Zhu 
347*e8e29e8dSJason Zhu 	return CMD_RET_SUCCESS;
348*e8e29e8dSJason Zhu }
349*e8e29e8dSJason Zhu 
350*e8e29e8dSJason Zhu int do_avb_get_get_unique_guid_for_partition(cmd_tbl_t *cmdtp, int flag,
351*e8e29e8dSJason Zhu 					     int argc, char * const argv[])
352*e8e29e8dSJason Zhu {
353*e8e29e8dSJason Zhu 	AvbOps *ops;
354*e8e29e8dSJason Zhu 	char *requested_partitions;
355*e8e29e8dSJason Zhu 	size_t guid_buf_size = 37;
356*e8e29e8dSJason Zhu 	char guid_buf[37];
357*e8e29e8dSJason Zhu 
358*e8e29e8dSJason Zhu 	if (argc != 2)
359*e8e29e8dSJason Zhu 		return CMD_RET_USAGE;
360*e8e29e8dSJason Zhu 
361*e8e29e8dSJason Zhu 	requested_partitions = argv[1];
362*e8e29e8dSJason Zhu 	ops = avb_ops_user_new();
363*e8e29e8dSJason Zhu 	if (ops == NULL) {
364*e8e29e8dSJason Zhu 		printf("avb_ops_user_new() failed!\n");
365*e8e29e8dSJason Zhu 		return CMD_RET_FAILURE;
366*e8e29e8dSJason Zhu 	}
367*e8e29e8dSJason Zhu 
368*e8e29e8dSJason Zhu 	if (ops->get_unique_guid_for_partition(ops, requested_partitions,
369*e8e29e8dSJason Zhu 					       guid_buf, guid_buf_size) != 0) {
370*e8e29e8dSJason Zhu 		printf("do_avb_get_get_unique_guid_for_partition error!\n");
371*e8e29e8dSJason Zhu 		avb_ops_user_free(ops);
372*e8e29e8dSJason Zhu 		return CMD_RET_FAILURE;
373*e8e29e8dSJason Zhu 	}
374*e8e29e8dSJason Zhu 
375*e8e29e8dSJason Zhu 	printf("guid = %s\n", guid_buf);
376*e8e29e8dSJason Zhu 	avb_ops_user_free(ops);
377*e8e29e8dSJason Zhu 
378*e8e29e8dSJason Zhu 	return CMD_RET_SUCCESS;
379*e8e29e8dSJason Zhu }
380*e8e29e8dSJason Zhu 
381*e8e29e8dSJason Zhu int do_avb_read(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
382*e8e29e8dSJason Zhu {
383*e8e29e8dSJason Zhu 	AvbOps *ops;
384*e8e29e8dSJason Zhu 	char *requested_partitions;
385*e8e29e8dSJason Zhu 	int64_t offset_blk;
386*e8e29e8dSJason Zhu 	size_t blkcnt;
387*e8e29e8dSJason Zhu 	size_t out_num_read;
388*e8e29e8dSJason Zhu 	int i;
389*e8e29e8dSJason Zhu 	char *buffer;
390*e8e29e8dSJason Zhu 
391*e8e29e8dSJason Zhu 	if (argc != 4)
392*e8e29e8dSJason Zhu 		return CMD_RET_USAGE;
393*e8e29e8dSJason Zhu 
394*e8e29e8dSJason Zhu 	requested_partitions = argv[1];
395*e8e29e8dSJason Zhu 	offset_blk = simple_strtoul(argv[2], NULL, 16);
396*e8e29e8dSJason Zhu 	blkcnt = simple_strtoul(argv[3], NULL, 16);
397*e8e29e8dSJason Zhu 	ops = avb_ops_user_new();
398*e8e29e8dSJason Zhu 	buffer = (char *)malloc(blkcnt * 512);
399*e8e29e8dSJason Zhu 	if (buffer == NULL)
400*e8e29e8dSJason Zhu 		printf("malloc buffer failed!\n");
401*e8e29e8dSJason Zhu 
402*e8e29e8dSJason Zhu 	if (ops == NULL) {
403*e8e29e8dSJason Zhu 		printf("avb_ops_user_new() failed!\n");
404*e8e29e8dSJason Zhu 		return CMD_RET_FAILURE;
405*e8e29e8dSJason Zhu 	}
406*e8e29e8dSJason Zhu 
407*e8e29e8dSJason Zhu 	if (ops->read_from_partition(ops, requested_partitions,
408*e8e29e8dSJason Zhu 				     offset_blk, blkcnt, buffer,
409*e8e29e8dSJason Zhu 				     &out_num_read) != 0) {
410*e8e29e8dSJason Zhu 		printf("do avb read error!\n");
411*e8e29e8dSJason Zhu 		free(buffer);
412*e8e29e8dSJason Zhu 		avb_ops_user_free(ops);
413*e8e29e8dSJason Zhu 		return CMD_RET_FAILURE;
414*e8e29e8dSJason Zhu 	}
415*e8e29e8dSJason Zhu 
416*e8e29e8dSJason Zhu 	for (i = 0; i < 512 * blkcnt; i++)
417*e8e29e8dSJason Zhu 		printf("buffer %d = %d\n", i, buffer[i]);
418*e8e29e8dSJason Zhu 
419*e8e29e8dSJason Zhu 	free(buffer);
420*e8e29e8dSJason Zhu 	avb_ops_user_free(ops);
421*e8e29e8dSJason Zhu 
422*e8e29e8dSJason Zhu 	return CMD_RET_SUCCESS;
423*e8e29e8dSJason Zhu }
424*e8e29e8dSJason Zhu 
425*e8e29e8dSJason Zhu int do_avb_write(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
426*e8e29e8dSJason Zhu {
427*e8e29e8dSJason Zhu 	AvbOps *ops;
428*e8e29e8dSJason Zhu 	char *requested_partitions;
429*e8e29e8dSJason Zhu 	int64_t offset_blk;
430*e8e29e8dSJason Zhu 	size_t blkcnt;
431*e8e29e8dSJason Zhu 	size_t out_num_read;
432*e8e29e8dSJason Zhu 	char *buffer;
433*e8e29e8dSJason Zhu 
434*e8e29e8dSJason Zhu 	if (argc != 4)
435*e8e29e8dSJason Zhu 		return CMD_RET_USAGE;
436*e8e29e8dSJason Zhu 
437*e8e29e8dSJason Zhu 	requested_partitions = argv[1];
438*e8e29e8dSJason Zhu 	offset_blk = simple_strtoul(argv[2], NULL, 16);
439*e8e29e8dSJason Zhu 	blkcnt = simple_strtoul(argv[3], NULL, 16);
440*e8e29e8dSJason Zhu 	ops = avb_ops_user_new();
441*e8e29e8dSJason Zhu 	buffer = (char *)malloc(blkcnt * 512);
442*e8e29e8dSJason Zhu 	if (buffer == NULL) {
443*e8e29e8dSJason Zhu 		printf("malloc buffer failed!\n");
444*e8e29e8dSJason Zhu 		return CMD_RET_FAILURE;
445*e8e29e8dSJason Zhu 	}
446*e8e29e8dSJason Zhu 
447*e8e29e8dSJason Zhu 	if (ops == NULL) {
448*e8e29e8dSJason Zhu 		printf("avb_ops_user_new() failed!\n");
449*e8e29e8dSJason Zhu 		return CMD_RET_FAILURE;
450*e8e29e8dSJason Zhu 	}
451*e8e29e8dSJason Zhu 	if (ops->read_from_partition(ops, requested_partitions, offset_blk,
452*e8e29e8dSJason Zhu 				     blkcnt, buffer, &out_num_read) != 0) {
453*e8e29e8dSJason Zhu 		printf("do_avb_write error!\n");
454*e8e29e8dSJason Zhu 		free(buffer);
455*e8e29e8dSJason Zhu 		avb_ops_user_free(ops);
456*e8e29e8dSJason Zhu 		return CMD_RET_FAILURE;
457*e8e29e8dSJason Zhu 	}
458*e8e29e8dSJason Zhu 
459*e8e29e8dSJason Zhu 	free(buffer);
460*e8e29e8dSJason Zhu 	avb_ops_user_free(ops);
461*e8e29e8dSJason Zhu 
462*e8e29e8dSJason Zhu 	return CMD_RET_SUCCESS;
463*e8e29e8dSJason Zhu }
464*e8e29e8dSJason Zhu 
465*e8e29e8dSJason Zhu int do_avb_load_ab_metadata(cmd_tbl_t *cmdtp, int flag,
466*e8e29e8dSJason Zhu 			    int argc, char * const argv[])
467*e8e29e8dSJason Zhu {
468*e8e29e8dSJason Zhu 	AvbOps *ops;
469*e8e29e8dSJason Zhu 	AvbABData ab_data, ab_data_orig;
470*e8e29e8dSJason Zhu 	char *data;
471*e8e29e8dSJason Zhu 	int i;
472*e8e29e8dSJason Zhu 
473*e8e29e8dSJason Zhu 	if (argc != 1)
474*e8e29e8dSJason Zhu 		return CMD_RET_USAGE;
475*e8e29e8dSJason Zhu 
476*e8e29e8dSJason Zhu 	ops = avb_ops_user_new();
477*e8e29e8dSJason Zhu 	if (ops == NULL) {
478*e8e29e8dSJason Zhu 		printf("avb_ops_user_new() failed!\n");
479*e8e29e8dSJason Zhu 		return CMD_RET_FAILURE;
480*e8e29e8dSJason Zhu 	}
481*e8e29e8dSJason Zhu 
482*e8e29e8dSJason Zhu 	if (load_metadata(ops->ab_ops, &ab_data, &ab_data_orig) != 0) {
483*e8e29e8dSJason Zhu 		printf("do_avb_write_ab_metadata error!\n");
484*e8e29e8dSJason Zhu 		avb_ops_user_free(ops);
485*e8e29e8dSJason Zhu 		return CMD_RET_FAILURE;
486*e8e29e8dSJason Zhu 	}
487*e8e29e8dSJason Zhu 
488*e8e29e8dSJason Zhu 	data = (char *)&ab_data;
489*e8e29e8dSJason Zhu 	for (i = 0; i < 33; i++)
490*e8e29e8dSJason Zhu 		printf("%d\n", data[i]);
491*e8e29e8dSJason Zhu 
492*e8e29e8dSJason Zhu 	avb_ops_user_free(ops);
493*e8e29e8dSJason Zhu 
494*e8e29e8dSJason Zhu 	return CMD_RET_SUCCESS;
495*e8e29e8dSJason Zhu }
496*e8e29e8dSJason Zhu 
497*e8e29e8dSJason Zhu int do_avb_read_ab_metadata(cmd_tbl_t *cmdtp, int flag,
498*e8e29e8dSJason Zhu 			    int argc, char * const argv[])
499*e8e29e8dSJason Zhu {
500*e8e29e8dSJason Zhu 	AvbOps *ops;
501*e8e29e8dSJason Zhu 	AvbABData ab_data;
502*e8e29e8dSJason Zhu 
503*e8e29e8dSJason Zhu 	if (argc != 1)
504*e8e29e8dSJason Zhu 		return CMD_RET_USAGE;
505*e8e29e8dSJason Zhu 
506*e8e29e8dSJason Zhu 	ops = avb_ops_user_new();
507*e8e29e8dSJason Zhu 	if (ops == NULL) {
508*e8e29e8dSJason Zhu 		printf("avb_ops_user_new() failed!\n");
509*e8e29e8dSJason Zhu 		return CMD_RET_FAILURE;
510*e8e29e8dSJason Zhu 	}
511*e8e29e8dSJason Zhu 
512*e8e29e8dSJason Zhu 	if (ops->ab_ops->read_ab_metadata(ops->ab_ops, &ab_data) != 0) {
513*e8e29e8dSJason Zhu 		printf("do_avb_write_ab_metadata error!\n");
514*e8e29e8dSJason Zhu 		avb_ops_user_free(ops);
515*e8e29e8dSJason Zhu 		return CMD_RET_FAILURE;
516*e8e29e8dSJason Zhu 	}
517*e8e29e8dSJason Zhu 
518*e8e29e8dSJason Zhu 	avb_ops_user_free(ops);
519*e8e29e8dSJason Zhu 
520*e8e29e8dSJason Zhu 	return CMD_RET_SUCCESS;
521*e8e29e8dSJason Zhu }
522*e8e29e8dSJason Zhu 
523*e8e29e8dSJason Zhu int do_avb_write_ab_metadata(cmd_tbl_t *cmdtp, int flag,
524*e8e29e8dSJason Zhu 			     int argc, char * const argv[])
525*e8e29e8dSJason Zhu {
526*e8e29e8dSJason Zhu 	AvbOps *ops;
527*e8e29e8dSJason Zhu 	AvbABData ab_data;
528*e8e29e8dSJason Zhu 
529*e8e29e8dSJason Zhu 	if (argc != 1)
530*e8e29e8dSJason Zhu 		return CMD_RET_USAGE;
531*e8e29e8dSJason Zhu 
532*e8e29e8dSJason Zhu 	ops = avb_ops_user_new();
533*e8e29e8dSJason Zhu 	if (ops == NULL) {
534*e8e29e8dSJason Zhu 		printf("avb_ops_user_new() failed!\n");
535*e8e29e8dSJason Zhu 		return CMD_RET_FAILURE;
536*e8e29e8dSJason Zhu 	}
537*e8e29e8dSJason Zhu 
538*e8e29e8dSJason Zhu 	if (ops->ab_ops->write_ab_metadata(ops->ab_ops, &ab_data) != 0) {
539*e8e29e8dSJason Zhu 		printf("do_avb_write_ab_metadata error!\n");
540*e8e29e8dSJason Zhu 		avb_ops_user_free(ops);
541*e8e29e8dSJason Zhu 		return CMD_RET_FAILURE;
542*e8e29e8dSJason Zhu 	}
543*e8e29e8dSJason Zhu 
544*e8e29e8dSJason Zhu 	avb_ops_user_free(ops);
545*e8e29e8dSJason Zhu 
546*e8e29e8dSJason Zhu 	return CMD_RET_SUCCESS;
547*e8e29e8dSJason Zhu }
548*e8e29e8dSJason Zhu 
549*e8e29e8dSJason Zhu int do_avb_verify_partition(cmd_tbl_t *cmdtp, int flag,
550*e8e29e8dSJason Zhu 			    int argc, char * const argv[])
551*e8e29e8dSJason Zhu {
552*e8e29e8dSJason Zhu 	AvbOps *ops;
553*e8e29e8dSJason Zhu 	const char *requested_partitions[1];
554*e8e29e8dSJason Zhu 	const char * slot_suffixes[2] = {"_a", "_b"};
555*e8e29e8dSJason Zhu 	AvbSlotVerifyFlags flags;
556*e8e29e8dSJason Zhu 	AvbSlotVerifyData *slot_data[2] = {NULL, NULL};
557*e8e29e8dSJason Zhu 	AvbSlotVerifyResult verify_result;
558*e8e29e8dSJason Zhu 	size_t n;
559*e8e29e8dSJason Zhu 
560*e8e29e8dSJason Zhu 	if (argc != 3)
561*e8e29e8dSJason Zhu 		return CMD_RET_USAGE;
562*e8e29e8dSJason Zhu 
563*e8e29e8dSJason Zhu 	requested_partitions[0] = argv[1];
564*e8e29e8dSJason Zhu 	n = simple_strtoul(argv[2], NULL, 16);
565*e8e29e8dSJason Zhu 	ops = avb_ops_user_new();
566*e8e29e8dSJason Zhu 	flags = AVB_SLOT_VERIFY_FLAGS_NONE;
567*e8e29e8dSJason Zhu 	verify_result =
568*e8e29e8dSJason Zhu 		avb_slot_verify(ops,
569*e8e29e8dSJason Zhu 				requested_partitions,
570*e8e29e8dSJason Zhu 				slot_suffixes[n],
571*e8e29e8dSJason Zhu 				flags,
572*e8e29e8dSJason Zhu 				AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
573*e8e29e8dSJason Zhu 				&slot_data[n]);
574*e8e29e8dSJason Zhu 	if (verify_result != 0)
575*e8e29e8dSJason Zhu 		return CMD_RET_FAILURE;
576*e8e29e8dSJason Zhu 
577*e8e29e8dSJason Zhu 	avb_ops_user_free(ops);
578*e8e29e8dSJason Zhu 
579*e8e29e8dSJason Zhu 	return CMD_RET_SUCCESS;
580*e8e29e8dSJason Zhu }
581*e8e29e8dSJason Zhu 
582*e8e29e8dSJason Zhu int do_avb_flow(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
583*e8e29e8dSJason Zhu {
584*e8e29e8dSJason Zhu 	char slot_partition[2][20];
585*e8e29e8dSJason Zhu 	unsigned long load_address;
586*e8e29e8dSJason Zhu 	AvbOps *ops;
587*e8e29e8dSJason Zhu 	const char *avb_version;
588*e8e29e8dSJason Zhu 	AvbSlotVerifyData *slot_data;
589*e8e29e8dSJason Zhu 	AvbSlotVerifyFlags flags;
590*e8e29e8dSJason Zhu 	const char *requested_partitions[] = {"boot", "system", NULL};
591*e8e29e8dSJason Zhu 	char *command_line;
592*e8e29e8dSJason Zhu 	bool unlocked = true;
593*e8e29e8dSJason Zhu 	const char *mode_cmdline = NULL;
594*e8e29e8dSJason Zhu 	char root_data[70] = "root=PARTUUID=";
595*e8e29e8dSJason Zhu 	mode_cmdline = "skip_initramfs";
596*e8e29e8dSJason Zhu 	size_t guid_buf_size = 37;
597*e8e29e8dSJason Zhu 	char guid_buf[37];
598*e8e29e8dSJason Zhu 	char verify_flag;
599*e8e29e8dSJason Zhu 	char boot_slot_select[5];
600*e8e29e8dSJason Zhu 
601*e8e29e8dSJason Zhu 	if (argc != 2)
602*e8e29e8dSJason Zhu 		return CMD_RET_USAGE;
603*e8e29e8dSJason Zhu 	avb_version = avb_version_string();
604*e8e29e8dSJason Zhu 	printf("Android avb version is %s.\n", avb_version);
605*e8e29e8dSJason Zhu 	ops = avb_ops_user_new();
606*e8e29e8dSJason Zhu 	if (ops == NULL)
607*e8e29e8dSJason Zhu 		printf("avb_ops_user_new() failed!\n");
608*e8e29e8dSJason Zhu 
609*e8e29e8dSJason Zhu 	if (ops->read_is_device_unlocked(ops, &unlocked) != 0)
610*e8e29e8dSJason Zhu 		printf("Error determining whether device is unlocked.\n");
611*e8e29e8dSJason Zhu 
612*e8e29e8dSJason Zhu 	printf("read_is_device_unlocked() ops returned that device is %s\n",
613*e8e29e8dSJason Zhu 	       unlocked ? "UNLOCKED" : "LOCKED");
614*e8e29e8dSJason Zhu 
615*e8e29e8dSJason Zhu 	flags = AVB_SLOT_VERIFY_FLAGS_NONE;
616*e8e29e8dSJason Zhu 	if (unlocked)
617*e8e29e8dSJason Zhu 		flags |= AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR;
618*e8e29e8dSJason Zhu 
619*e8e29e8dSJason Zhu 	verify_flag = argv[1][0];
620*e8e29e8dSJason Zhu 	if (verify_flag == 'v') {
621*e8e29e8dSJason Zhu 		debug("start with verify!\n");
622*e8e29e8dSJason Zhu 		avb_ab_flow(ops->ab_ops,
623*e8e29e8dSJason Zhu 			    requested_partitions,
624*e8e29e8dSJason Zhu 			    flags,
625*e8e29e8dSJason Zhu 			    AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
626*e8e29e8dSJason Zhu 			    &slot_data);
627*e8e29e8dSJason Zhu 		strcat(slot_partition[1], requested_partitions[1]);
628*e8e29e8dSJason Zhu 		strcat(slot_partition[1], slot_data->ab_suffix);
629*e8e29e8dSJason Zhu 		ops->get_unique_guid_for_partition(ops,
630*e8e29e8dSJason Zhu 						   slot_partition[1],
631*e8e29e8dSJason Zhu 						   guid_buf,
632*e8e29e8dSJason Zhu 						   guid_buf_size);
633*e8e29e8dSJason Zhu 		strcat(root_data, guid_buf);
634*e8e29e8dSJason Zhu 		command_line = android_assemble_cmdline(slot_data->ab_suffix,
635*e8e29e8dSJason Zhu 							mode_cmdline);
636*e8e29e8dSJason Zhu 		strcat(root_data, " ");
637*e8e29e8dSJason Zhu 		strcat(root_data, command_line);
638*e8e29e8dSJason Zhu 		env_set("bootargs", root_data);
639*e8e29e8dSJason Zhu 		load_address = CONFIG_SYS_LOAD_ADDR;
640*e8e29e8dSJason Zhu 		memcpy((uint8_t*)load_address,
641*e8e29e8dSJason Zhu 		       slot_data->loaded_partitions->data,
642*e8e29e8dSJason Zhu 		       slot_data->loaded_partitions->data_size);
643*e8e29e8dSJason Zhu 		android_bootloader_boot_kernel(load_address);
644*e8e29e8dSJason Zhu 		avb_slot_verify_data_free(slot_data);
645*e8e29e8dSJason Zhu 		avb_ops_user_free(ops);
646*e8e29e8dSJason Zhu 	} else if (verify_flag == 'n') {
647*e8e29e8dSJason Zhu 		load_address = CONFIG_SYS_LOAD_ADDR;
648*e8e29e8dSJason Zhu 		avb_ab_slot_select(ops->ab_ops, boot_slot_select);
649*e8e29e8dSJason Zhu 		strcat(slot_partition[1], requested_partitions[1]);
650*e8e29e8dSJason Zhu 		strcat(slot_partition[1], boot_slot_select);
651*e8e29e8dSJason Zhu 		printf("%s\n", slot_partition[1]);
652*e8e29e8dSJason Zhu 		ops->get_unique_guid_for_partition(ops,
653*e8e29e8dSJason Zhu 						   slot_partition[1],
654*e8e29e8dSJason Zhu 						   guid_buf,
655*e8e29e8dSJason Zhu 						   guid_buf_size);
656*e8e29e8dSJason Zhu 		strcat(root_data, guid_buf);
657*e8e29e8dSJason Zhu 		command_line = android_assemble_cmdline(boot_slot_select,
658*e8e29e8dSJason Zhu 							mode_cmdline);
659*e8e29e8dSJason Zhu 		strcat(root_data, " ");
660*e8e29e8dSJason Zhu 		strcat(root_data, command_line);
661*e8e29e8dSJason Zhu 		env_set("bootargs", root_data);
662*e8e29e8dSJason Zhu 		android_avb_boot_flow(boot_slot_select, load_address);
663*e8e29e8dSJason Zhu 	} else {
664*e8e29e8dSJason Zhu 		return CMD_RET_USAGE;
665*e8e29e8dSJason Zhu 	}
666*e8e29e8dSJason Zhu 
667*e8e29e8dSJason Zhu 	return CMD_RET_SUCCESS;
668*e8e29e8dSJason Zhu }
669*e8e29e8dSJason Zhu 
670*e8e29e8dSJason Zhu static cmd_tbl_t cmd_avb[] = {
671*e8e29e8dSJason Zhu 	U_BOOT_CMD_MKENT(init, 1, 1, do_avb_init_ab_metadata, "", ""),
672*e8e29e8dSJason Zhu 	U_BOOT_CMD_MKENT(version, 1, 1, do_avb_version, "", ""),
673*e8e29e8dSJason Zhu 	U_BOOT_CMD_MKENT(slot_active, 2, 1,
674*e8e29e8dSJason Zhu 			 do_avb_ab_mark_slot_active, "", ""),
675*e8e29e8dSJason Zhu 	U_BOOT_CMD_MKENT(slot_unbootable, 2, 1,
676*e8e29e8dSJason Zhu 			 do_avb_ab_mark_slot_unbootable, "", ""),
677*e8e29e8dSJason Zhu 	U_BOOT_CMD_MKENT(slot_successful, 2, 1,
678*e8e29e8dSJason Zhu 			 do_avb_ab_mark_slot_successful, "", ""),
679*e8e29e8dSJason Zhu 	U_BOOT_CMD_MKENT(read_rollback, 2, 1,
680*e8e29e8dSJason Zhu 			 do_avb_read_rollback_index, "", ""),
681*e8e29e8dSJason Zhu 	U_BOOT_CMD_MKENT(write_rollback, 3, 1,
682*e8e29e8dSJason Zhu 			 do_avb_write_rollback_index, "", ""),
683*e8e29e8dSJason Zhu 	U_BOOT_CMD_MKENT(read_lock_status, 1, 1,
684*e8e29e8dSJason Zhu 			 do_avb_read_is_device_unlocked, "", ""),
685*e8e29e8dSJason Zhu 	U_BOOT_CMD_MKENT(write_lock_status, 2, 1,
686*e8e29e8dSJason Zhu 			 do_avb_write_is_device_unlocked, "", ""),
687*e8e29e8dSJason Zhu 	U_BOOT_CMD_MKENT(part_size, 2, 1,
688*e8e29e8dSJason Zhu 			 do_avb_get_size_of_partition, "", ""),
689*e8e29e8dSJason Zhu 	U_BOOT_CMD_MKENT(part_guid, 2, 1,
690*e8e29e8dSJason Zhu 			 do_avb_get_get_unique_guid_for_partition, "", ""),
691*e8e29e8dSJason Zhu 	U_BOOT_CMD_MKENT(read, 4, 1, do_avb_read, "", ""),
692*e8e29e8dSJason Zhu 	U_BOOT_CMD_MKENT(write, 4, 1, do_avb_write, "", ""),
693*e8e29e8dSJason Zhu 	U_BOOT_CMD_MKENT(loadabmisc, 1, 1, do_avb_load_ab_metadata, "", ""),
694*e8e29e8dSJason Zhu 	U_BOOT_CMD_MKENT(readabmisc, 1, 1, do_avb_read_ab_metadata, "", ""),
695*e8e29e8dSJason Zhu 	U_BOOT_CMD_MKENT(writeabmisc, 1, 1, do_avb_write_ab_metadata, "", ""),
696*e8e29e8dSJason Zhu 	U_BOOT_CMD_MKENT(verify, 3, 1, do_avb_verify_partition, "", ""),
697*e8e29e8dSJason Zhu 	U_BOOT_CMD_MKENT(flow, 2, 1, do_avb_flow, "", "")
698*e8e29e8dSJason Zhu };
699*e8e29e8dSJason Zhu 
700*e8e29e8dSJason Zhu static int do_boot_avb(cmd_tbl_t *cmdtp,
701*e8e29e8dSJason Zhu 		       int flag,
702*e8e29e8dSJason Zhu 		       int argc,
703*e8e29e8dSJason Zhu 		       char * const argv[])
704*e8e29e8dSJason Zhu {
705*e8e29e8dSJason Zhu 	cmd_tbl_t *cp;
706*e8e29e8dSJason Zhu 
707*e8e29e8dSJason Zhu 	cp = find_cmd_tbl(argv[1], cmd_avb, ARRAY_SIZE(cmd_avb));
708*e8e29e8dSJason Zhu 
709*e8e29e8dSJason Zhu 	argc--;
710*e8e29e8dSJason Zhu 	argv++;
711*e8e29e8dSJason Zhu 
712*e8e29e8dSJason Zhu 	if (cp == NULL || argc > cp->maxargs)
713*e8e29e8dSJason Zhu 		return CMD_RET_USAGE;
714*e8e29e8dSJason Zhu 	if (flag == CMD_FLAG_REPEAT && !cp->repeatable)
715*e8e29e8dSJason Zhu 		return CMD_RET_SUCCESS;
716*e8e29e8dSJason Zhu 
717*e8e29e8dSJason Zhu 	return cp->cmd(cmdtp, flag, argc, argv);
718*e8e29e8dSJason Zhu }
719*e8e29e8dSJason Zhu 
720*e8e29e8dSJason Zhu U_BOOT_CMD(
721*e8e29e8dSJason Zhu 	bootavb, 29, 1, do_boot_avb,
722*e8e29e8dSJason Zhu 	"Execute the Android avb a/b boot flow.",
723*e8e29e8dSJason Zhu 	"init - initialize the avbabmeta\n"
724*e8e29e8dSJason Zhu 	"bootavb version - display info of bootavb version\n"
725*e8e29e8dSJason Zhu 	"bootavb slot_active cnt\n"
726*e8e29e8dSJason Zhu 	"bootavb slot_unbootable cnt\n"
727*e8e29e8dSJason Zhu 	"bootavb slot_successful cnt\n"
728*e8e29e8dSJason Zhu 	"bootavb read_rollback rollback_index_location\n"
729*e8e29e8dSJason Zhu 	"bootavb write_rollback rollback_index_location out_rollback_index\n"
730*e8e29e8dSJason Zhu 	"bootavb read_lock_status\n"
731*e8e29e8dSJason Zhu 	"bootavb write_lock_status 0 or 1\n"
732*e8e29e8dSJason Zhu 	"bootavb part_size partitions_name\n"
733*e8e29e8dSJason Zhu 	"bootavb part_guid partitions_name\n"
734*e8e29e8dSJason Zhu 	"bootavb read partition offset_blk cnt\n"
735*e8e29e8dSJason Zhu 	"bootavb write partition offset_blk cnt\n"
736*e8e29e8dSJason Zhu 	"bootavb loadabmisc\n"
737*e8e29e8dSJason Zhu 	"bootavb readabmisc\n"
738*e8e29e8dSJason Zhu 	"bootavb writeabmisc\n"
739*e8e29e8dSJason Zhu 	"bootavb verify partition slot_cnt;partion name without '_a' or '_b'\n"
740*e8e29e8dSJason Zhu 	"bootavb flow v/n\n"
741*e8e29e8dSJason Zhu );
742*e8e29e8dSJason Zhu #endif
743