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> 1682ee22d4SJason Zhu #include <android_bootloader_message.h> 1737a7bc39SJason Zhu #include <android_avb/rk_avb_ops_user.h> 18*d9d5eb74SJason Zhu #include <android_avb/avb_atx_ops.h> 1906f4a874SAlex Deymo 2006f4a874SAlex Deymo static int do_boot_android(cmd_tbl_t *cmdtp, int flag, int argc, 2106f4a874SAlex Deymo char * const argv[]) 2206f4a874SAlex Deymo { 2306f4a874SAlex Deymo unsigned long load_address; 2406f4a874SAlex Deymo int ret = CMD_RET_SUCCESS; 2506f4a874SAlex Deymo char *addr_arg_endp, *addr_str; 2606f4a874SAlex Deymo struct blk_desc *dev_desc; 2706f4a874SAlex Deymo 28891380b5SKever Yang if (argc < 3) 2906f4a874SAlex Deymo return CMD_RET_USAGE; 3080622240SAlex Deymo if (argc > 5) 3106f4a874SAlex Deymo return CMD_RET_USAGE; 3206f4a874SAlex Deymo 3380622240SAlex Deymo if (argc >= 5) { 3480622240SAlex Deymo load_address = simple_strtoul(argv[4], &addr_arg_endp, 16); 3580622240SAlex Deymo if (addr_arg_endp == argv[4] || *addr_arg_endp != '\0') 3606f4a874SAlex Deymo return CMD_RET_USAGE; 3706f4a874SAlex Deymo } else { 38891380b5SKever Yang addr_str = env_get("kernel_addr_r"); 3906f4a874SAlex Deymo if (addr_str) 4006f4a874SAlex Deymo load_address = simple_strtoul(addr_str, NULL, 16); 4106f4a874SAlex Deymo else 4206f4a874SAlex Deymo load_address = CONFIG_SYS_LOAD_ADDR; 4306f4a874SAlex Deymo } 4406f4a874SAlex Deymo 453f251879SKever Yang /* ARM64 kernel load addr need to align to 0x80000, and android boot.img 463f251879SKever Yang * have a 2KB header, need to reserve space for it. 473f251879SKever Yang */ 483f251879SKever Yang load_address &= ~0x7ffff; 493f251879SKever Yang load_address -= 0x800; /* default page size for boot header */ 50891380b5SKever Yang dev_desc = blk_get_dev(argv[1], simple_strtoul(argv[2], NULL, 16)); 51891380b5SKever Yang if (!dev_desc) { 52891380b5SKever Yang printf("Could not get %s %s\n", argv[1], argv[2]); 5306f4a874SAlex Deymo return CMD_RET_FAILURE; 5406f4a874SAlex Deymo } 5506f4a874SAlex Deymo 56891380b5SKever Yang ret = android_bootloader_boot_flow(dev_desc, load_address); 5706f4a874SAlex Deymo if (ret < 0) { 5806f4a874SAlex Deymo printf("Android boot failed, error %d.\n", ret); 5906f4a874SAlex Deymo return CMD_RET_FAILURE; 6006f4a874SAlex Deymo } 6106f4a874SAlex Deymo return CMD_RET_SUCCESS; 6206f4a874SAlex Deymo } 6306f4a874SAlex Deymo 6406f4a874SAlex Deymo U_BOOT_CMD( 6580622240SAlex Deymo boot_android, 5, 0, do_boot_android, 6606f4a874SAlex Deymo "Execute the Android Bootloader flow.", 67df7cce43SAlex Deymo "<interface> <dev[:part|;part_name]> <slot> [<kernel_addr>]\n" 6806f4a874SAlex Deymo " - Load the Boot Control Block (BCB) from the partition 'part' on\n" 6906f4a874SAlex Deymo " device type 'interface' instance 'dev' to determine the boot\n" 7006f4a874SAlex Deymo " mode, and load and execute the appropriate kernel.\n" 7106f4a874SAlex Deymo " In normal and recovery mode, the kernel will be loaded from\n" 7206f4a874SAlex Deymo " the corresponding \"boot\" partition. In bootloader mode, the\n" 7306f4a874SAlex Deymo " command defined in the \"fastbootcmd\" variable will be\n" 7406f4a874SAlex Deymo " executed.\n" 7580622240SAlex Deymo " On Android devices with multiple slots, the pass 'slot' is\n" 7680622240SAlex Deymo " used to load the appropriate kernel. The standard slot names\n" 7780622240SAlex Deymo " are 'a' and 'b'.\n" 7806f4a874SAlex Deymo " - If 'part_name' is passed, preceded with a ; instead of :, the\n" 7906f4a874SAlex Deymo " partition name whose label is 'part_name' will be looked up in\n" 8006f4a874SAlex Deymo " the partition table. This is commonly the \"misc\" partition.\n" 8106f4a874SAlex Deymo ); 82e8e29e8dSJason Zhu 8337a7bc39SJason Zhu #ifdef CONFIG_RK_AVB_LIBAVB_USER 8482ee22d4SJason Zhu static int bootloader_message_read(struct android_bootloader_message *data) 8582ee22d4SJason Zhu { 8682ee22d4SJason Zhu AvbOps *ops; 8782ee22d4SJason Zhu char requested_partitions[] = "misc"; 8882ee22d4SJason Zhu size_t out_num_read; 8982ee22d4SJason Zhu char *buffer; 9082ee22d4SJason Zhu 9182ee22d4SJason Zhu ops = avb_ops_user_new(); 9282ee22d4SJason Zhu buffer = (char *)data; 9382ee22d4SJason Zhu 9482ee22d4SJason Zhu if (ops == NULL) { 9582ee22d4SJason Zhu printf("avb_ops_user_new() failed!\n"); 9682ee22d4SJason Zhu return CMD_RET_FAILURE; 9782ee22d4SJason Zhu } 9882ee22d4SJason Zhu 9982ee22d4SJason Zhu if (ops->read_from_partition(ops, requested_partitions, 10082ee22d4SJason Zhu 0, 2048, buffer, 10182ee22d4SJason Zhu &out_num_read) != 0) { 10282ee22d4SJason Zhu printf("do avb read error!\n"); 10382ee22d4SJason Zhu avb_ops_user_free(ops); 10482ee22d4SJason Zhu return CMD_RET_FAILURE; 10582ee22d4SJason Zhu } 10682ee22d4SJason Zhu 10782ee22d4SJason Zhu avb_ops_user_free(ops); 10882ee22d4SJason Zhu 10982ee22d4SJason Zhu return CMD_RET_SUCCESS; 11082ee22d4SJason Zhu } 11182ee22d4SJason Zhu 11282ee22d4SJason Zhu static int bootloader_message_write(struct android_bootloader_message *data) 11382ee22d4SJason Zhu { 11482ee22d4SJason Zhu AvbOps *ops; 11582ee22d4SJason Zhu char requested_partitions[] = "misc"; 11682ee22d4SJason Zhu char *buffer; 11782ee22d4SJason Zhu 11882ee22d4SJason Zhu ops = avb_ops_user_new(); 11982ee22d4SJason Zhu buffer = (char *)data; 12082ee22d4SJason Zhu 12182ee22d4SJason Zhu if (ops == NULL) { 12282ee22d4SJason Zhu printf("avb_ops_user_new() failed!\n"); 12382ee22d4SJason Zhu return CMD_RET_FAILURE; 12482ee22d4SJason Zhu } 12582ee22d4SJason Zhu 12682ee22d4SJason Zhu if (ops->write_to_partition(ops, requested_partitions, 12782ee22d4SJason Zhu 0, 2048, buffer) != 0) { 12882ee22d4SJason Zhu printf("do avb write error!\n"); 12982ee22d4SJason Zhu avb_ops_user_free(ops); 13082ee22d4SJason Zhu return CMD_RET_FAILURE; 13182ee22d4SJason Zhu } 13282ee22d4SJason Zhu 13382ee22d4SJason Zhu avb_ops_user_free(ops); 13482ee22d4SJason Zhu 13582ee22d4SJason Zhu return CMD_RET_SUCCESS; 13682ee22d4SJason Zhu } 13782ee22d4SJason Zhu 138e8e29e8dSJason Zhu int do_avb_init_ab_metadata(cmd_tbl_t *cmdtp, int flag, 139e8e29e8dSJason Zhu int argc, char * const argv[]) 140e8e29e8dSJason Zhu { 141e8e29e8dSJason Zhu AvbOps *ops; 142e8e29e8dSJason Zhu AvbABData ab_data; 143e8e29e8dSJason Zhu 144e8e29e8dSJason Zhu memset(&ab_data, 0, sizeof(AvbABData)); 145326572eaSJason Zhu debug("sizeof(AvbABData) = %d\n", (int)(size_t)sizeof(AvbABData)); 146e8e29e8dSJason Zhu if (argc != 1) 147e8e29e8dSJason Zhu return CMD_RET_USAGE; 148e8e29e8dSJason Zhu 149e8e29e8dSJason Zhu ops = avb_ops_user_new(); 150e8e29e8dSJason Zhu if (ops == NULL) { 151e8e29e8dSJason Zhu printf("avb_ops_user_new() failed!\n"); 152e8e29e8dSJason Zhu return CMD_RET_FAILURE; 153e8e29e8dSJason Zhu } 154e8e29e8dSJason Zhu 15537a7bc39SJason Zhu avb_ab_data_init(&ab_data); 156e8e29e8dSJason Zhu if (ops->ab_ops->write_ab_metadata(ops->ab_ops, &ab_data) != 0) { 157e8e29e8dSJason Zhu printf("do_avb_init_ab_metadata error!\n"); 158e8e29e8dSJason Zhu avb_ops_user_free(ops); 159e8e29e8dSJason Zhu return CMD_RET_FAILURE; 160e8e29e8dSJason Zhu } 161e8e29e8dSJason Zhu 162e8e29e8dSJason Zhu avb_ops_user_free(ops); 163e8e29e8dSJason Zhu 164e8e29e8dSJason Zhu return CMD_RET_SUCCESS; 165e8e29e8dSJason Zhu } 166e8e29e8dSJason Zhu 167e8e29e8dSJason Zhu int do_avb_version(cmd_tbl_t *cmdtp, int flag, int argc, 168e8e29e8dSJason Zhu char * const argv[]) 169e8e29e8dSJason Zhu { 170e8e29e8dSJason Zhu const char *avb_version; 171e8e29e8dSJason Zhu 172e8e29e8dSJason Zhu if (argc != 1) 173e8e29e8dSJason Zhu return CMD_RET_USAGE; 174e8e29e8dSJason Zhu 175e8e29e8dSJason Zhu avb_version = avb_version_string(); 176e8e29e8dSJason Zhu printf("Android avb version is %s.\n", avb_version); 177e8e29e8dSJason Zhu 178e8e29e8dSJason Zhu return CMD_RET_SUCCESS; 179e8e29e8dSJason Zhu } 180e8e29e8dSJason Zhu 181e8e29e8dSJason Zhu int do_avb_ab_mark_slot_active(cmd_tbl_t *cmdtp, int flag, 182e8e29e8dSJason Zhu int argc, char * const argv[]) 183e8e29e8dSJason Zhu { 184e8e29e8dSJason Zhu AvbOps *ops; 185e8e29e8dSJason Zhu unsigned int slot_number; 186e8e29e8dSJason Zhu 187e8e29e8dSJason Zhu if (argc != 2) 188e8e29e8dSJason Zhu return CMD_RET_USAGE; 189e8e29e8dSJason Zhu 190e8e29e8dSJason Zhu ops = avb_ops_user_new(); 191e8e29e8dSJason Zhu if (ops == NULL) { 192e8e29e8dSJason Zhu printf("avb_ops_user_new() failed!\n"); 193e8e29e8dSJason Zhu return CMD_RET_FAILURE; 194e8e29e8dSJason Zhu } 195e8e29e8dSJason Zhu 196e8e29e8dSJason Zhu slot_number = simple_strtoul(argv[1], NULL, 16); 197e8e29e8dSJason Zhu if (avb_ab_mark_slot_active(ops->ab_ops, slot_number) != 0) { 198e8e29e8dSJason Zhu printf("avb_ab_mark_slot_active error!\n"); 199e8e29e8dSJason Zhu avb_ops_user_free(ops); 200e8e29e8dSJason Zhu return CMD_RET_FAILURE; 201e8e29e8dSJason Zhu } 202e8e29e8dSJason Zhu 203e8e29e8dSJason Zhu avb_ops_user_free(ops); 204e8e29e8dSJason Zhu 205e8e29e8dSJason Zhu return CMD_RET_SUCCESS; 206e8e29e8dSJason Zhu } 207e8e29e8dSJason Zhu 208e8e29e8dSJason Zhu int do_avb_ab_mark_slot_unbootable(cmd_tbl_t *cmdtp, int flag, 209e8e29e8dSJason Zhu int argc, char * const argv[]) 210e8e29e8dSJason Zhu { 211e8e29e8dSJason Zhu AvbOps *ops; 212e8e29e8dSJason Zhu unsigned int slot_number; 213e8e29e8dSJason Zhu 214e8e29e8dSJason Zhu if (argc != 2) 215e8e29e8dSJason Zhu return CMD_RET_USAGE; 216e8e29e8dSJason Zhu 217e8e29e8dSJason Zhu ops = avb_ops_user_new(); 218e8e29e8dSJason Zhu if (ops == NULL) { 219e8e29e8dSJason Zhu printf("avb_ops_user_new() failed!\n"); 220e8e29e8dSJason Zhu return CMD_RET_FAILURE; 221e8e29e8dSJason Zhu } 222e8e29e8dSJason Zhu 223e8e29e8dSJason Zhu slot_number = simple_strtoul(argv[1], NULL, 16); 224e8e29e8dSJason Zhu if (avb_ab_mark_slot_unbootable(ops->ab_ops, slot_number) != 0) { 225e8e29e8dSJason Zhu printf("do_avb_ab_mark_slot_unbootable error!\n"); 226e8e29e8dSJason Zhu avb_ops_user_free(ops); 227e8e29e8dSJason Zhu return CMD_RET_FAILURE; 228e8e29e8dSJason Zhu } 229e8e29e8dSJason Zhu 230e8e29e8dSJason Zhu avb_ops_user_free(ops); 231e8e29e8dSJason Zhu 232e8e29e8dSJason Zhu return CMD_RET_SUCCESS; 233e8e29e8dSJason Zhu } 234e8e29e8dSJason Zhu 235e8e29e8dSJason Zhu int do_avb_ab_mark_slot_successful(cmd_tbl_t *cmdtp, int flag, 236e8e29e8dSJason Zhu int argc, char * const argv[]) 237e8e29e8dSJason Zhu { 238e8e29e8dSJason Zhu AvbOps *ops; 239e8e29e8dSJason Zhu unsigned int slot_number; 240e8e29e8dSJason Zhu 241e8e29e8dSJason Zhu if (argc != 2) 242e8e29e8dSJason Zhu return CMD_RET_USAGE; 243e8e29e8dSJason Zhu 244e8e29e8dSJason Zhu ops = avb_ops_user_new(); 245e8e29e8dSJason Zhu if (ops == NULL) { 246e8e29e8dSJason Zhu printf("avb_ops_user_new() failed!\n"); 247e8e29e8dSJason Zhu return CMD_RET_FAILURE; 248e8e29e8dSJason Zhu } 249e8e29e8dSJason Zhu 250e8e29e8dSJason Zhu slot_number = simple_strtoul(argv[1], NULL, 16); 251e8e29e8dSJason Zhu if (avb_ab_mark_slot_successful(ops->ab_ops, slot_number) != 0) { 252e8e29e8dSJason Zhu printf("do_avb_ab_mark_slot_successful error!\n"); 253e8e29e8dSJason Zhu avb_ops_user_free(ops); 254e8e29e8dSJason Zhu return CMD_RET_FAILURE; 255e8e29e8dSJason Zhu } 256e8e29e8dSJason Zhu 257e8e29e8dSJason Zhu avb_ops_user_free(ops); 258e8e29e8dSJason Zhu 259e8e29e8dSJason Zhu return CMD_RET_SUCCESS; 260e8e29e8dSJason Zhu } 261e8e29e8dSJason Zhu 262e8e29e8dSJason Zhu int do_avb_read_rollback_index(cmd_tbl_t *cmdtp, int flag, 263e8e29e8dSJason Zhu int argc, char * const argv[]) 264e8e29e8dSJason Zhu { 265e8e29e8dSJason Zhu AvbOps *ops; 266e8e29e8dSJason Zhu uint64_t out_rollback_index; 267e8e29e8dSJason Zhu size_t rollback_index_location; 268e8e29e8dSJason Zhu 269e8e29e8dSJason Zhu if (argc != 2) 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 rollback_index_location = simple_strtoul(argv[1], NULL, 16); 279e8e29e8dSJason Zhu if (ops->read_rollback_index(ops, rollback_index_location, 280e8e29e8dSJason Zhu &out_rollback_index) != 0) { 281e8e29e8dSJason Zhu printf("do_avb_read_rollback_index error!\n"); 282e8e29e8dSJason Zhu avb_ops_user_free(ops); 283e8e29e8dSJason Zhu return CMD_RET_FAILURE; 284e8e29e8dSJason Zhu } 285e8e29e8dSJason Zhu 286e8e29e8dSJason Zhu printf("out_rollback_index = %llx\n", out_rollback_index); 287e8e29e8dSJason Zhu avb_ops_user_free(ops); 288e8e29e8dSJason Zhu 289e8e29e8dSJason Zhu return CMD_RET_SUCCESS; 290e8e29e8dSJason Zhu } 291e8e29e8dSJason Zhu 292e8e29e8dSJason Zhu int do_avb_write_rollback_index(cmd_tbl_t *cmdtp, int flag, 293e8e29e8dSJason Zhu int argc, char * const argv[]) 294e8e29e8dSJason Zhu { 295e8e29e8dSJason Zhu AvbOps *ops; 296e8e29e8dSJason Zhu uint64_t out_rollback_index; 297e8e29e8dSJason Zhu size_t rollback_index_location; 298e8e29e8dSJason Zhu 299e8e29e8dSJason Zhu if (argc != 3) 300e8e29e8dSJason Zhu return CMD_RET_USAGE; 301e8e29e8dSJason Zhu 302e8e29e8dSJason Zhu rollback_index_location = simple_strtoul(argv[1], NULL, 16); 303e8e29e8dSJason Zhu out_rollback_index = simple_strtoull(argv[2], NULL, 16); 304e8e29e8dSJason Zhu debug("out_rollback_index = %llx\n", out_rollback_index); 305e8e29e8dSJason Zhu ops = avb_ops_user_new(); 306e8e29e8dSJason Zhu if (ops == NULL) { 307e8e29e8dSJason Zhu printf("avb_ops_user_new() failed!\n"); 308e8e29e8dSJason Zhu return CMD_RET_FAILURE; 309e8e29e8dSJason Zhu } 310e8e29e8dSJason Zhu 311e8e29e8dSJason Zhu if (ops->write_rollback_index(ops, rollback_index_location, 312e8e29e8dSJason Zhu out_rollback_index) != 0) { 313e8e29e8dSJason Zhu printf("do_avb_write_rollback_index error!\n"); 314e8e29e8dSJason Zhu avb_ops_user_free(ops); 315e8e29e8dSJason Zhu return CMD_RET_FAILURE; 316e8e29e8dSJason Zhu } 317e8e29e8dSJason Zhu 318e8e29e8dSJason Zhu avb_ops_user_free(ops); 319e8e29e8dSJason Zhu 320e8e29e8dSJason Zhu return CMD_RET_SUCCESS; 321e8e29e8dSJason Zhu } 322e8e29e8dSJason Zhu 323e8e29e8dSJason Zhu int do_avb_read_is_device_unlocked(cmd_tbl_t *cmdtp, int flag, 324e8e29e8dSJason Zhu int argc, char * const argv[]) 325e8e29e8dSJason Zhu { 326e8e29e8dSJason Zhu AvbOps *ops; 327e8e29e8dSJason Zhu bool out_is_unlocked; 328e8e29e8dSJason Zhu 329e8e29e8dSJason Zhu if (argc != 1) 330e8e29e8dSJason Zhu return CMD_RET_USAGE; 331e8e29e8dSJason Zhu 332e8e29e8dSJason Zhu ops = avb_ops_user_new(); 333e8e29e8dSJason Zhu if (ops == NULL) { 334e8e29e8dSJason Zhu printf("avb_ops_user_new() failed!\n"); 335e8e29e8dSJason Zhu return CMD_RET_FAILURE; 336e8e29e8dSJason Zhu } 337e8e29e8dSJason Zhu 338e8e29e8dSJason Zhu if (ops->read_is_device_unlocked(ops, &out_is_unlocked) != 0) { 339e8e29e8dSJason Zhu printf("do_avb_read_is_device_unlocked error!\n"); 340e8e29e8dSJason Zhu avb_ops_user_free(ops); 341e8e29e8dSJason Zhu return CMD_RET_FAILURE; 342e8e29e8dSJason Zhu } 343e8e29e8dSJason Zhu 344*d9d5eb74SJason Zhu printf("out_is_unlocked = %d\n", out_is_unlocked); 345e8e29e8dSJason Zhu avb_ops_user_free(ops); 346e8e29e8dSJason Zhu 347e8e29e8dSJason Zhu return CMD_RET_SUCCESS; 348e8e29e8dSJason Zhu } 349e8e29e8dSJason Zhu int do_avb_write_is_device_unlocked(cmd_tbl_t *cmdtp, int flag, 350e8e29e8dSJason Zhu int argc, char * const argv[]) 351e8e29e8dSJason Zhu { 352e8e29e8dSJason Zhu AvbOps *ops; 353e8e29e8dSJason Zhu bool out_is_unlocked; 354e8e29e8dSJason Zhu 355e8e29e8dSJason Zhu if (argc != 2) 356e8e29e8dSJason Zhu return CMD_RET_USAGE; 357e8e29e8dSJason Zhu 358e8e29e8dSJason Zhu out_is_unlocked = simple_strtoul(argv[1], NULL, 16); 359e8e29e8dSJason Zhu if ((out_is_unlocked != 0) || (out_is_unlocked != 1)) 360e8e29e8dSJason Zhu printf("enter out_is_unlocked value must is '0' or '1'\n"); 361e8e29e8dSJason Zhu 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->write_is_device_unlocked(ops, &out_is_unlocked) != 0) { 369e8e29e8dSJason Zhu printf("do_avb_write_is_device_unlocked error!\n"); 370e8e29e8dSJason Zhu avb_ops_user_free(ops); 371e8e29e8dSJason Zhu return CMD_RET_FAILURE; 372e8e29e8dSJason Zhu } 373e8e29e8dSJason Zhu 374e8e29e8dSJason Zhu debug("out_is_unlocked = %d\n", out_is_unlocked); 375e8e29e8dSJason Zhu avb_ops_user_free(ops); 376e8e29e8dSJason Zhu 377e8e29e8dSJason Zhu return CMD_RET_SUCCESS; 378e8e29e8dSJason Zhu } 379e8e29e8dSJason Zhu 380e8e29e8dSJason Zhu int do_avb_get_size_of_partition(cmd_tbl_t *cmdtp, int flag, 381e8e29e8dSJason Zhu int argc, char * const argv[]) 382e8e29e8dSJason Zhu { 383e8e29e8dSJason Zhu AvbOps *ops; 384e8e29e8dSJason Zhu char *requested_partitions; 385e8e29e8dSJason Zhu uint64_t out_size_in_bytes; 386e8e29e8dSJason Zhu 387e8e29e8dSJason Zhu if (argc != 2) 388e8e29e8dSJason Zhu return CMD_RET_USAGE; 389e8e29e8dSJason Zhu 390e8e29e8dSJason Zhu requested_partitions = argv[1]; 391e8e29e8dSJason Zhu ops = avb_ops_user_new(); 392e8e29e8dSJason Zhu if (ops == NULL) { 393e8e29e8dSJason Zhu printf("avb_ops_user_new() failed!\n"); 394e8e29e8dSJason Zhu return CMD_RET_FAILURE; 395e8e29e8dSJason Zhu } 396e8e29e8dSJason Zhu 397e8e29e8dSJason Zhu if (ops->get_size_of_partition(ops, requested_partitions, 398e8e29e8dSJason Zhu &out_size_in_bytes) != 0) { 399e8e29e8dSJason Zhu printf("do_avb_get_size_of_partition error!\n"); 400e8e29e8dSJason Zhu avb_ops_user_free(ops); 401e8e29e8dSJason Zhu return CMD_RET_FAILURE; 402e8e29e8dSJason Zhu } 403e8e29e8dSJason Zhu 404e8e29e8dSJason Zhu printf("partition size = %lld\n", out_size_in_bytes); 405e8e29e8dSJason Zhu avb_ops_user_free(ops); 406e8e29e8dSJason Zhu 407e8e29e8dSJason Zhu return CMD_RET_SUCCESS; 408e8e29e8dSJason Zhu } 409e8e29e8dSJason Zhu 410e8e29e8dSJason Zhu int do_avb_get_get_unique_guid_for_partition(cmd_tbl_t *cmdtp, int flag, 411e8e29e8dSJason Zhu int argc, char * const argv[]) 412e8e29e8dSJason Zhu { 413e8e29e8dSJason Zhu AvbOps *ops; 414e8e29e8dSJason Zhu char *requested_partitions; 415e8e29e8dSJason Zhu size_t guid_buf_size = 37; 416e8e29e8dSJason Zhu char guid_buf[37]; 417e8e29e8dSJason Zhu 418e8e29e8dSJason Zhu if (argc != 2) 419e8e29e8dSJason Zhu return CMD_RET_USAGE; 420e8e29e8dSJason Zhu 421e8e29e8dSJason Zhu requested_partitions = argv[1]; 422e8e29e8dSJason Zhu ops = avb_ops_user_new(); 423e8e29e8dSJason Zhu if (ops == NULL) { 424e8e29e8dSJason Zhu printf("avb_ops_user_new() failed!\n"); 425e8e29e8dSJason Zhu return CMD_RET_FAILURE; 426e8e29e8dSJason Zhu } 427e8e29e8dSJason Zhu 428e8e29e8dSJason Zhu if (ops->get_unique_guid_for_partition(ops, requested_partitions, 429e8e29e8dSJason Zhu guid_buf, guid_buf_size) != 0) { 430e8e29e8dSJason Zhu printf("do_avb_get_get_unique_guid_for_partition error!\n"); 431e8e29e8dSJason Zhu avb_ops_user_free(ops); 432e8e29e8dSJason Zhu return CMD_RET_FAILURE; 433e8e29e8dSJason Zhu } 434e8e29e8dSJason Zhu 435e8e29e8dSJason Zhu printf("guid = %s\n", guid_buf); 436e8e29e8dSJason Zhu avb_ops_user_free(ops); 437e8e29e8dSJason Zhu 438e8e29e8dSJason Zhu return CMD_RET_SUCCESS; 439e8e29e8dSJason Zhu } 440e8e29e8dSJason Zhu 441e8e29e8dSJason Zhu int do_avb_read(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 442e8e29e8dSJason Zhu { 443e8e29e8dSJason Zhu AvbOps *ops; 444e8e29e8dSJason Zhu char *requested_partitions; 445e8e29e8dSJason Zhu int64_t offset_blk; 446e8e29e8dSJason Zhu size_t blkcnt; 447e8e29e8dSJason Zhu size_t out_num_read; 448e8e29e8dSJason Zhu int i; 449e8e29e8dSJason Zhu char *buffer; 450e8e29e8dSJason Zhu 451e8e29e8dSJason Zhu if (argc != 4) 452e8e29e8dSJason Zhu return CMD_RET_USAGE; 453e8e29e8dSJason Zhu 454e8e29e8dSJason Zhu requested_partitions = argv[1]; 455e8e29e8dSJason Zhu offset_blk = simple_strtoul(argv[2], NULL, 16); 456e8e29e8dSJason Zhu blkcnt = simple_strtoul(argv[3], NULL, 16); 457e8e29e8dSJason Zhu ops = avb_ops_user_new(); 458e8e29e8dSJason Zhu buffer = (char *)malloc(blkcnt * 512); 459e8e29e8dSJason Zhu if (buffer == NULL) 460e8e29e8dSJason Zhu printf("malloc buffer failed!\n"); 461e8e29e8dSJason Zhu 462e8e29e8dSJason Zhu if (ops == NULL) { 463e8e29e8dSJason Zhu printf("avb_ops_user_new() failed!\n"); 464e8e29e8dSJason Zhu return CMD_RET_FAILURE; 465e8e29e8dSJason Zhu } 466e8e29e8dSJason Zhu 467e8e29e8dSJason Zhu if (ops->read_from_partition(ops, requested_partitions, 468e8e29e8dSJason Zhu offset_blk, blkcnt, buffer, 469e8e29e8dSJason Zhu &out_num_read) != 0) { 470e8e29e8dSJason Zhu printf("do avb read error!\n"); 471e8e29e8dSJason Zhu free(buffer); 472e8e29e8dSJason Zhu avb_ops_user_free(ops); 473e8e29e8dSJason Zhu return CMD_RET_FAILURE; 474e8e29e8dSJason Zhu } 475e8e29e8dSJason Zhu 476e8e29e8dSJason Zhu for (i = 0; i < 512 * blkcnt; i++) 477e8e29e8dSJason Zhu printf("buffer %d = %d\n", i, buffer[i]); 478e8e29e8dSJason Zhu 479e8e29e8dSJason Zhu free(buffer); 480e8e29e8dSJason Zhu avb_ops_user_free(ops); 481e8e29e8dSJason Zhu 482e8e29e8dSJason Zhu return CMD_RET_SUCCESS; 483e8e29e8dSJason Zhu } 484e8e29e8dSJason Zhu 485e8e29e8dSJason Zhu int do_avb_write(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 486e8e29e8dSJason Zhu { 487e8e29e8dSJason Zhu AvbOps *ops; 488e8e29e8dSJason Zhu char *requested_partitions; 489e8e29e8dSJason Zhu int64_t offset_blk; 490e8e29e8dSJason Zhu size_t blkcnt; 491e8e29e8dSJason Zhu size_t out_num_read; 492e8e29e8dSJason Zhu char *buffer; 493e8e29e8dSJason Zhu 494e8e29e8dSJason Zhu if (argc != 4) 495e8e29e8dSJason Zhu return CMD_RET_USAGE; 496e8e29e8dSJason Zhu 497e8e29e8dSJason Zhu requested_partitions = argv[1]; 498e8e29e8dSJason Zhu offset_blk = simple_strtoul(argv[2], NULL, 16); 499e8e29e8dSJason Zhu blkcnt = simple_strtoul(argv[3], NULL, 16); 500e8e29e8dSJason Zhu ops = avb_ops_user_new(); 501e8e29e8dSJason Zhu buffer = (char *)malloc(blkcnt * 512); 502e8e29e8dSJason Zhu if (buffer == NULL) { 503e8e29e8dSJason Zhu printf("malloc buffer failed!\n"); 504e8e29e8dSJason Zhu return CMD_RET_FAILURE; 505e8e29e8dSJason Zhu } 506e8e29e8dSJason Zhu 507e8e29e8dSJason Zhu if (ops == NULL) { 508e8e29e8dSJason Zhu printf("avb_ops_user_new() failed!\n"); 509e8e29e8dSJason Zhu return CMD_RET_FAILURE; 510e8e29e8dSJason Zhu } 511e8e29e8dSJason Zhu if (ops->read_from_partition(ops, requested_partitions, offset_blk, 512e8e29e8dSJason Zhu blkcnt, buffer, &out_num_read) != 0) { 513e8e29e8dSJason Zhu printf("do_avb_write error!\n"); 514e8e29e8dSJason Zhu free(buffer); 515e8e29e8dSJason Zhu avb_ops_user_free(ops); 516e8e29e8dSJason Zhu return CMD_RET_FAILURE; 517e8e29e8dSJason Zhu } 518e8e29e8dSJason Zhu 519e8e29e8dSJason Zhu free(buffer); 520e8e29e8dSJason Zhu avb_ops_user_free(ops); 521e8e29e8dSJason Zhu 522e8e29e8dSJason Zhu return CMD_RET_SUCCESS; 523e8e29e8dSJason Zhu } 524e8e29e8dSJason Zhu 525e8e29e8dSJason Zhu int do_avb_read_ab_metadata(cmd_tbl_t *cmdtp, int flag, 526e8e29e8dSJason Zhu int argc, char * const argv[]) 527e8e29e8dSJason Zhu { 528e8e29e8dSJason Zhu AvbOps *ops; 529e8e29e8dSJason Zhu AvbABData ab_data; 530e8e29e8dSJason Zhu 531e8e29e8dSJason Zhu if (argc != 1) 532e8e29e8dSJason Zhu return CMD_RET_USAGE; 533e8e29e8dSJason Zhu 534e8e29e8dSJason Zhu ops = avb_ops_user_new(); 535e8e29e8dSJason Zhu if (ops == NULL) { 536e8e29e8dSJason Zhu printf("avb_ops_user_new() failed!\n"); 537e8e29e8dSJason Zhu return CMD_RET_FAILURE; 538e8e29e8dSJason Zhu } 539e8e29e8dSJason Zhu 540e8e29e8dSJason Zhu if (ops->ab_ops->read_ab_metadata(ops->ab_ops, &ab_data) != 0) { 541e8e29e8dSJason Zhu printf("do_avb_write_ab_metadata error!\n"); 542e8e29e8dSJason Zhu avb_ops_user_free(ops); 543e8e29e8dSJason Zhu return CMD_RET_FAILURE; 544e8e29e8dSJason Zhu } 545e8e29e8dSJason Zhu 546e8e29e8dSJason Zhu avb_ops_user_free(ops); 547e8e29e8dSJason Zhu 548e8e29e8dSJason Zhu return CMD_RET_SUCCESS; 549e8e29e8dSJason Zhu } 550e8e29e8dSJason Zhu 551e8e29e8dSJason Zhu int do_avb_write_ab_metadata(cmd_tbl_t *cmdtp, int flag, 552e8e29e8dSJason Zhu int argc, char * const argv[]) 553e8e29e8dSJason Zhu { 554e8e29e8dSJason Zhu AvbOps *ops; 555e8e29e8dSJason Zhu AvbABData ab_data; 556e8e29e8dSJason Zhu 557e8e29e8dSJason Zhu if (argc != 1) 558e8e29e8dSJason Zhu return CMD_RET_USAGE; 559e8e29e8dSJason Zhu 560e8e29e8dSJason Zhu ops = avb_ops_user_new(); 561e8e29e8dSJason Zhu if (ops == NULL) { 562e8e29e8dSJason Zhu printf("avb_ops_user_new() failed!\n"); 563e8e29e8dSJason Zhu return CMD_RET_FAILURE; 564e8e29e8dSJason Zhu } 565e8e29e8dSJason Zhu 566e8e29e8dSJason Zhu if (ops->ab_ops->write_ab_metadata(ops->ab_ops, &ab_data) != 0) { 567e8e29e8dSJason Zhu printf("do_avb_write_ab_metadata error!\n"); 568e8e29e8dSJason Zhu avb_ops_user_free(ops); 569e8e29e8dSJason Zhu return CMD_RET_FAILURE; 570e8e29e8dSJason Zhu } 571e8e29e8dSJason Zhu 572e8e29e8dSJason Zhu avb_ops_user_free(ops); 573e8e29e8dSJason Zhu 574e8e29e8dSJason Zhu return CMD_RET_SUCCESS; 575e8e29e8dSJason Zhu } 576e8e29e8dSJason Zhu 577*d9d5eb74SJason Zhu int do_perm_attr_test(cmd_tbl_t *cmdtp, int flag, 578*d9d5eb74SJason Zhu int argc, char * const argv[]) 579*d9d5eb74SJason Zhu { 580*d9d5eb74SJason Zhu AvbOps *ops; 581*d9d5eb74SJason Zhu int i; 582*d9d5eb74SJason Zhu uint8_t hash[AVB_SHA256_DIGEST_SIZE]; 583*d9d5eb74SJason Zhu 584*d9d5eb74SJason Zhu if (argc != 1) 585*d9d5eb74SJason Zhu return CMD_RET_USAGE; 586*d9d5eb74SJason Zhu 587*d9d5eb74SJason Zhu ops = avb_ops_user_new(); 588*d9d5eb74SJason Zhu if (ops == NULL) { 589*d9d5eb74SJason Zhu printf("avb_ops_user_new() failed!\n"); 590*d9d5eb74SJason Zhu return CMD_RET_FAILURE; 591*d9d5eb74SJason Zhu } 592*d9d5eb74SJason Zhu 593*d9d5eb74SJason Zhu if (ops->atx_ops->read_permanent_attributes_hash(ops->atx_ops, hash) != 0) { 594*d9d5eb74SJason Zhu printf("read_permanent_attributes_hash error!\n"); 595*d9d5eb74SJason Zhu avb_ops_user_free(ops); 596*d9d5eb74SJason Zhu return CMD_RET_FAILURE; 597*d9d5eb74SJason Zhu } 598*d9d5eb74SJason Zhu 599*d9d5eb74SJason Zhu for (i = 0; i < AVB_SHA256_DIGEST_SIZE; i++) { 600*d9d5eb74SJason Zhu if (i % 4 == 0) 601*d9d5eb74SJason Zhu printf("\n"); 602*d9d5eb74SJason Zhu printf("0x%x ", hash[i]); 603*d9d5eb74SJason Zhu } 604*d9d5eb74SJason Zhu 605*d9d5eb74SJason Zhu avb_ops_user_free(ops); 606*d9d5eb74SJason Zhu 607*d9d5eb74SJason Zhu return CMD_RET_SUCCESS; 608*d9d5eb74SJason Zhu } 609*d9d5eb74SJason Zhu 610e8e29e8dSJason Zhu int do_avb_verify_partition(cmd_tbl_t *cmdtp, int flag, 611e8e29e8dSJason Zhu int argc, char * const argv[]) 612e8e29e8dSJason Zhu { 613e8e29e8dSJason Zhu AvbOps *ops; 614e8e29e8dSJason Zhu const char *requested_partitions[1]; 615e8e29e8dSJason Zhu const char * slot_suffixes[2] = {"_a", "_b"}; 616e8e29e8dSJason Zhu AvbSlotVerifyFlags flags; 617e8e29e8dSJason Zhu AvbSlotVerifyData *slot_data[2] = {NULL, NULL}; 618e8e29e8dSJason Zhu AvbSlotVerifyResult verify_result; 619e8e29e8dSJason Zhu size_t n; 620e8e29e8dSJason Zhu 621e8e29e8dSJason Zhu if (argc != 3) 622e8e29e8dSJason Zhu return CMD_RET_USAGE; 623e8e29e8dSJason Zhu 624e8e29e8dSJason Zhu requested_partitions[0] = argv[1]; 625e8e29e8dSJason Zhu n = simple_strtoul(argv[2], NULL, 16); 626e8e29e8dSJason Zhu ops = avb_ops_user_new(); 627e8e29e8dSJason Zhu flags = AVB_SLOT_VERIFY_FLAGS_NONE; 628e8e29e8dSJason Zhu verify_result = 629e8e29e8dSJason Zhu avb_slot_verify(ops, 630e8e29e8dSJason Zhu requested_partitions, 631e8e29e8dSJason Zhu slot_suffixes[n], 632e8e29e8dSJason Zhu flags, 633e8e29e8dSJason Zhu AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE, 634e8e29e8dSJason Zhu &slot_data[n]); 635e8e29e8dSJason Zhu if (verify_result != 0) 636e8e29e8dSJason Zhu return CMD_RET_FAILURE; 637e8e29e8dSJason Zhu 638e8e29e8dSJason Zhu avb_ops_user_free(ops); 639e8e29e8dSJason Zhu 640e8e29e8dSJason Zhu return CMD_RET_SUCCESS; 641e8e29e8dSJason Zhu } 642e8e29e8dSJason Zhu 643e8e29e8dSJason Zhu int do_avb_flow(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 644e8e29e8dSJason Zhu { 645f0864c7fSJason Zhu char slot_partition[2][20] = {{0}, {0}}; 646e8e29e8dSJason Zhu unsigned long load_address; 647e8e29e8dSJason Zhu AvbOps *ops; 648e8e29e8dSJason Zhu const char *avb_version; 649e8e29e8dSJason Zhu AvbSlotVerifyData *slot_data; 650e8e29e8dSJason Zhu AvbSlotVerifyFlags flags; 651e8e29e8dSJason Zhu const char *requested_partitions[] = {"boot", "system", NULL}; 652e8e29e8dSJason Zhu char *command_line; 65337a7bc39SJason Zhu bool unlocked; 654e8e29e8dSJason Zhu const char *mode_cmdline = NULL; 655e8e29e8dSJason Zhu char root_data[70] = "root=PARTUUID="; 65637a7bc39SJason Zhu char *vboot_state = "androidboot.verifiedbootstate="; 6579aed1a13SJason Zhu char avb_root_data[2000] = {0}; 658e8e29e8dSJason Zhu size_t guid_buf_size = 37; 659e8e29e8dSJason Zhu char guid_buf[37]; 660e8e29e8dSJason Zhu char verify_flag; 661e8e29e8dSJason Zhu char boot_slot_select[5]; 66282ee22d4SJason Zhu struct android_bootloader_message data; 66382ee22d4SJason Zhu const char *fastboot_cmd = env_get("fastbootcmd"); 66437a7bc39SJason Zhu AvbABFlowResult ab_result; 665e8e29e8dSJason Zhu 666e8e29e8dSJason Zhu if (argc != 2) 667e8e29e8dSJason Zhu return CMD_RET_USAGE; 66882ee22d4SJason Zhu 66982ee22d4SJason Zhu bootloader_message_read(&data); 67082ee22d4SJason Zhu if (!strcmp("bootonce-bootloader", data.command)) { 67182ee22d4SJason Zhu memset(data.command, 0, sizeof(data.command)); 67282ee22d4SJason Zhu bootloader_message_write(&data); 67382ee22d4SJason Zhu if (fastboot_cmd) { 67482ee22d4SJason Zhu printf("bootonce-bootloader!\n"); 67582ee22d4SJason Zhu return run_command(fastboot_cmd, CMD_FLAG_ENV); 67682ee22d4SJason Zhu } else { 67782ee22d4SJason Zhu printf("The fastbootcmd is NULL!\n"); 67837a7bc39SJason Zhu goto fail; 67982ee22d4SJason Zhu } 68082ee22d4SJason Zhu } else if (!strcmp("boot-recovery", data.command)) { 68182ee22d4SJason Zhu printf("Enter boot-recovery!\n"); 68282ee22d4SJason Zhu } else if(!strcmp("boot-normal", data.command)) { 68382ee22d4SJason Zhu printf("Enter boot-normal!\n"); 68482ee22d4SJason Zhu mode_cmdline = "skip_initramfs"; 68582ee22d4SJason Zhu } else { 6869f7ea89dSWenping Zhang /* 6879f7ea89dSWenping Zhang * Firstly, confirm if there is a command in misc partition in 6889f7ea89dSWenping Zhang * previous cases, and then we need to confirm whether user has 6899f7ea89dSWenping Zhang * requested to enter recovery mode by entering "reboot recovery" 6909f7ea89dSWenping Zhang * command through adb or serial console. 6919f7ea89dSWenping Zhang */ 6929f7ea89dSWenping Zhang char *env_rebootmode = env_get("reboot_mode"); 6939f7ea89dSWenping Zhang 6949f7ea89dSWenping Zhang if (env_rebootmode && !strcmp("recovery", env_rebootmode)) 6959f7ea89dSWenping Zhang printf("Enter recovery mode by command 'reboot recovery'!\n"); 6969f7ea89dSWenping Zhang else 69782ee22d4SJason Zhu mode_cmdline = "skip_initramfs"; 69882ee22d4SJason Zhu } 69982ee22d4SJason Zhu 700e8e29e8dSJason Zhu avb_version = avb_version_string(); 701e8e29e8dSJason Zhu printf("Android avb version is %s.\n", avb_version); 702e8e29e8dSJason Zhu ops = avb_ops_user_new(); 70337a7bc39SJason Zhu if (ops == NULL) { 704e8e29e8dSJason Zhu printf("avb_ops_user_new() failed!\n"); 70537a7bc39SJason Zhu goto fail; 70637a7bc39SJason Zhu } 707e8e29e8dSJason Zhu 70837a7bc39SJason Zhu if (ops->read_is_device_unlocked(ops, &unlocked) != 0) { 709e8e29e8dSJason Zhu printf("Error determining whether device is unlocked.\n"); 71037a7bc39SJason Zhu unlocked = ANDROID_VBOOT_UNLOCK; 71137a7bc39SJason Zhu if (ops->write_is_device_unlocked(ops, &unlocked) != 0) { 71237a7bc39SJason Zhu printf("Can not write lock state!\n"); 71337a7bc39SJason Zhu unlocked = ANDROID_VBOOT_LOCK; 71437a7bc39SJason Zhu } 71537a7bc39SJason Zhu if (ops->read_is_device_unlocked(ops, &unlocked) != 0) { 71637a7bc39SJason Zhu printf("Can not read lock state!\n"); 71737a7bc39SJason Zhu unlocked = ANDROID_VBOOT_LOCK; 71837a7bc39SJason Zhu } 71937a7bc39SJason Zhu } 720e8e29e8dSJason Zhu 721e8e29e8dSJason Zhu printf("read_is_device_unlocked() ops returned that device is %s\n", 722e8e29e8dSJason Zhu unlocked ? "UNLOCKED" : "LOCKED"); 723e8e29e8dSJason Zhu 724e8e29e8dSJason Zhu flags = AVB_SLOT_VERIFY_FLAGS_NONE; 725e8e29e8dSJason Zhu if (unlocked) 726e8e29e8dSJason Zhu flags |= AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR; 727e8e29e8dSJason Zhu 728e8e29e8dSJason Zhu verify_flag = argv[1][0]; 729e8e29e8dSJason Zhu if (verify_flag == 'v') { 730e8e29e8dSJason Zhu debug("start with verify!\n"); 73137a7bc39SJason Zhu ab_result = 73237a7bc39SJason Zhu avb_ab_flow(ops->ab_ops, 733e8e29e8dSJason Zhu requested_partitions, 734e8e29e8dSJason Zhu flags, 735e8e29e8dSJason Zhu AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE, 73637a7bc39SJason Zhu &slot_data); 73737a7bc39SJason Zhu if ((ab_result != AVB_AB_FLOW_RESULT_OK) && 73837a7bc39SJason Zhu (ab_result != 73937a7bc39SJason Zhu AVB_AB_FLOW_RESULT_OK_WITH_VERIFICATION_ERROR)) { 7404397fdfdSJason Zhu printf("avb_ab_flow() error!\n"); 74137a7bc39SJason Zhu avb_ops_user_free(ops); 74237a7bc39SJason Zhu goto fail; 74337a7bc39SJason Zhu } 74437a7bc39SJason Zhu 74537a7bc39SJason Zhu if (ab_result ==\ 74637a7bc39SJason Zhu AVB_AB_FLOW_RESULT_OK_WITH_VERIFICATION_ERROR) { 74737a7bc39SJason Zhu strcat(avb_root_data, vboot_state); 74837a7bc39SJason Zhu strcat(avb_root_data, "orange"); 74937a7bc39SJason Zhu } else if (ab_result == AVB_AB_FLOW_RESULT_OK) { 75037a7bc39SJason Zhu strcat(avb_root_data, vboot_state); 75137a7bc39SJason Zhu strcat(avb_root_data, "green"); 7524397fdfdSJason Zhu } 7534397fdfdSJason Zhu 754e8e29e8dSJason Zhu command_line = android_assemble_cmdline(slot_data->ab_suffix, 755e8e29e8dSJason Zhu mode_cmdline); 7569aed1a13SJason Zhu strcat(avb_root_data, " "); 7579aed1a13SJason Zhu strcat(avb_root_data, command_line); 7589aed1a13SJason Zhu strcat(avb_root_data, " "); 7599aed1a13SJason Zhu strcat(avb_root_data, slot_data->cmdline); 7609aed1a13SJason Zhu env_set("bootargs", avb_root_data); 761e8e29e8dSJason Zhu load_address = CONFIG_SYS_LOAD_ADDR; 76237a7bc39SJason Zhu if (rk_avb_close_optee_client()) 763708de143SJason Zhu printf("Can not close optee client!\n"); 764708de143SJason Zhu 765e8e29e8dSJason Zhu memcpy((uint8_t*)load_address, 766e8e29e8dSJason Zhu slot_data->loaded_partitions->data, 767e8e29e8dSJason Zhu slot_data->loaded_partitions->data_size); 768e8e29e8dSJason Zhu android_bootloader_boot_kernel(load_address); 76937a7bc39SJason Zhu avb_ops_user_free(ops); 770e8e29e8dSJason Zhu } else if (verify_flag == 'n') { 771e8e29e8dSJason Zhu load_address = CONFIG_SYS_LOAD_ADDR; 77237a7bc39SJason Zhu rk_avb_ab_slot_select(ops->ab_ops, boot_slot_select); 773e8e29e8dSJason Zhu strcat(slot_partition[1], requested_partitions[1]); 774e8e29e8dSJason Zhu strcat(slot_partition[1], boot_slot_select); 775e8e29e8dSJason Zhu printf("%s\n", slot_partition[1]); 776e8e29e8dSJason Zhu ops->get_unique_guid_for_partition(ops, 777e8e29e8dSJason Zhu slot_partition[1], 778e8e29e8dSJason Zhu guid_buf, 779e8e29e8dSJason Zhu guid_buf_size); 780e8e29e8dSJason Zhu strcat(root_data, guid_buf); 781e8e29e8dSJason Zhu command_line = android_assemble_cmdline(boot_slot_select, 782e8e29e8dSJason Zhu mode_cmdline); 783e8e29e8dSJason Zhu strcat(root_data, " "); 784e8e29e8dSJason Zhu strcat(root_data, command_line); 785e8e29e8dSJason Zhu env_set("bootargs", root_data); 78637a7bc39SJason Zhu if (android_avb_boot_flow(boot_slot_select, load_address)) { 78737a7bc39SJason Zhu printf("Cannot boot the system, goto the fastboot!\n"); 78837a7bc39SJason Zhu avb_ops_user_free(ops); 78937a7bc39SJason Zhu goto fail; 79037a7bc39SJason Zhu } 79137a7bc39SJason Zhu avb_ops_user_free(ops); 792bf17c627SJason Zhu } else if (verify_flag == 'o') { 793bf17c627SJason Zhu load_address = CONFIG_SYS_LOAD_ADDR; 794bf17c627SJason Zhu strcat(slot_partition[1], requested_partitions[1]); 795bf17c627SJason Zhu ops->get_unique_guid_for_partition(ops, 796bf17c627SJason Zhu slot_partition[1], 797bf17c627SJason Zhu guid_buf, 798bf17c627SJason Zhu guid_buf_size); 799bf17c627SJason Zhu strcat(root_data, guid_buf); 800bf17c627SJason Zhu command_line = android_assemble_cmdline(boot_slot_select, 801bf17c627SJason Zhu mode_cmdline); 802bf17c627SJason Zhu strcat(root_data, " "); 803bf17c627SJason Zhu strcat(root_data, command_line); 804bf17c627SJason Zhu env_set("bootargs", root_data); 80537a7bc39SJason Zhu if (android_boot_flow(load_address)) { 80637a7bc39SJason Zhu printf("Cannot boot the system, goto the fastboot!\n"); 80737a7bc39SJason Zhu avb_ops_user_free(ops); 80837a7bc39SJason Zhu goto fail; 80937a7bc39SJason Zhu } 81037a7bc39SJason Zhu avb_ops_user_free(ops); 811e8e29e8dSJason Zhu } else { 812e8e29e8dSJason Zhu return CMD_RET_USAGE; 813e8e29e8dSJason Zhu } 814e8e29e8dSJason Zhu 815e8e29e8dSJason Zhu return CMD_RET_SUCCESS; 81637a7bc39SJason Zhu fail: 81737a7bc39SJason Zhu if (fastboot_cmd == NULL) { 81837a7bc39SJason Zhu printf("fastboot_cmd is null, run default fastboot_cmd!\n"); 81937a7bc39SJason Zhu fastboot_cmd = "fastboot usb 0"; 82037a7bc39SJason Zhu } 82137a7bc39SJason Zhu 82237a7bc39SJason Zhu return run_command(fastboot_cmd, CMD_FLAG_ENV); 823e8e29e8dSJason Zhu } 824e8e29e8dSJason Zhu 825e8e29e8dSJason Zhu static cmd_tbl_t cmd_avb[] = { 826e8e29e8dSJason Zhu U_BOOT_CMD_MKENT(init, 1, 1, do_avb_init_ab_metadata, "", ""), 827e8e29e8dSJason Zhu U_BOOT_CMD_MKENT(version, 1, 1, do_avb_version, "", ""), 828e8e29e8dSJason Zhu U_BOOT_CMD_MKENT(slot_active, 2, 1, 829e8e29e8dSJason Zhu do_avb_ab_mark_slot_active, "", ""), 830e8e29e8dSJason Zhu U_BOOT_CMD_MKENT(slot_unbootable, 2, 1, 831e8e29e8dSJason Zhu do_avb_ab_mark_slot_unbootable, "", ""), 832e8e29e8dSJason Zhu U_BOOT_CMD_MKENT(slot_successful, 2, 1, 833e8e29e8dSJason Zhu do_avb_ab_mark_slot_successful, "", ""), 834e8e29e8dSJason Zhu U_BOOT_CMD_MKENT(read_rollback, 2, 1, 835e8e29e8dSJason Zhu do_avb_read_rollback_index, "", ""), 836e8e29e8dSJason Zhu U_BOOT_CMD_MKENT(write_rollback, 3, 1, 837e8e29e8dSJason Zhu do_avb_write_rollback_index, "", ""), 838e8e29e8dSJason Zhu U_BOOT_CMD_MKENT(read_lock_status, 1, 1, 839e8e29e8dSJason Zhu do_avb_read_is_device_unlocked, "", ""), 840e8e29e8dSJason Zhu U_BOOT_CMD_MKENT(write_lock_status, 2, 1, 841e8e29e8dSJason Zhu do_avb_write_is_device_unlocked, "", ""), 842e8e29e8dSJason Zhu U_BOOT_CMD_MKENT(part_size, 2, 1, 843e8e29e8dSJason Zhu do_avb_get_size_of_partition, "", ""), 844e8e29e8dSJason Zhu U_BOOT_CMD_MKENT(part_guid, 2, 1, 845e8e29e8dSJason Zhu do_avb_get_get_unique_guid_for_partition, "", ""), 846e8e29e8dSJason Zhu U_BOOT_CMD_MKENT(read, 4, 1, do_avb_read, "", ""), 847e8e29e8dSJason Zhu U_BOOT_CMD_MKENT(write, 4, 1, do_avb_write, "", ""), 848e8e29e8dSJason Zhu U_BOOT_CMD_MKENT(readabmisc, 1, 1, do_avb_read_ab_metadata, "", ""), 849e8e29e8dSJason Zhu U_BOOT_CMD_MKENT(writeabmisc, 1, 1, do_avb_write_ab_metadata, "", ""), 850*d9d5eb74SJason Zhu U_BOOT_CMD_MKENT(perm_attr_test, 1, 1, do_perm_attr_test, "", ""), 851e8e29e8dSJason Zhu U_BOOT_CMD_MKENT(verify, 3, 1, do_avb_verify_partition, "", ""), 852e8e29e8dSJason Zhu U_BOOT_CMD_MKENT(flow, 2, 1, do_avb_flow, "", "") 853e8e29e8dSJason Zhu }; 854e8e29e8dSJason Zhu 855e8e29e8dSJason Zhu static int do_boot_avb(cmd_tbl_t *cmdtp, 856e8e29e8dSJason Zhu int flag, 857e8e29e8dSJason Zhu int argc, 858e8e29e8dSJason Zhu char * const argv[]) 859e8e29e8dSJason Zhu { 860e8e29e8dSJason Zhu cmd_tbl_t *cp; 861e8e29e8dSJason Zhu 862e8e29e8dSJason Zhu cp = find_cmd_tbl(argv[1], cmd_avb, ARRAY_SIZE(cmd_avb)); 863e8e29e8dSJason Zhu 864e8e29e8dSJason Zhu argc--; 865e8e29e8dSJason Zhu argv++; 866e8e29e8dSJason Zhu 867e8e29e8dSJason Zhu if (cp == NULL || argc > cp->maxargs) 868e8e29e8dSJason Zhu return CMD_RET_USAGE; 869e8e29e8dSJason Zhu if (flag == CMD_FLAG_REPEAT && !cp->repeatable) 870e8e29e8dSJason Zhu return CMD_RET_SUCCESS; 871e8e29e8dSJason Zhu 872e8e29e8dSJason Zhu return cp->cmd(cmdtp, flag, argc, argv); 873e8e29e8dSJason Zhu } 874e8e29e8dSJason Zhu 875e8e29e8dSJason Zhu U_BOOT_CMD( 876e8e29e8dSJason Zhu bootavb, 29, 1, do_boot_avb, 877e8e29e8dSJason Zhu "Execute the Android avb a/b boot flow.", 878e8e29e8dSJason Zhu "init - initialize the avbabmeta\n" 879e8e29e8dSJason Zhu "bootavb version - display info of bootavb version\n" 880e8e29e8dSJason Zhu "bootavb slot_active cnt\n" 881e8e29e8dSJason Zhu "bootavb slot_unbootable cnt\n" 882e8e29e8dSJason Zhu "bootavb slot_successful cnt\n" 883e8e29e8dSJason Zhu "bootavb read_rollback rollback_index_location\n" 884e8e29e8dSJason Zhu "bootavb write_rollback rollback_index_location out_rollback_index\n" 885e8e29e8dSJason Zhu "bootavb read_lock_status\n" 886e8e29e8dSJason Zhu "bootavb write_lock_status 0 or 1\n" 887e8e29e8dSJason Zhu "bootavb part_size partitions_name\n" 888e8e29e8dSJason Zhu "bootavb part_guid partitions_name\n" 889e8e29e8dSJason Zhu "bootavb read partition offset_blk cnt\n" 890e8e29e8dSJason Zhu "bootavb write partition offset_blk cnt\n" 891e8e29e8dSJason Zhu "bootavb readabmisc\n" 892e8e29e8dSJason Zhu "bootavb writeabmisc\n" 893*d9d5eb74SJason Zhu "bootavb perm_attr_test\n" 894e8e29e8dSJason Zhu "bootavb verify partition slot_cnt;partion name without '_a' or '_b'\n" 895e8e29e8dSJason Zhu "bootavb flow v/n\n" 896e8e29e8dSJason Zhu ); 897e8e29e8dSJason Zhu #endif 898