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