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