1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7 #include <android_bootloader.h> 8 #include <common.h> 9 #include <command.h> 10 11 /** 12 * part_get_info_by_dev_and_name - Parse a device number and partition name 13 * string in the form of "device_num;partition_name", for example "0;misc". 14 * If the partition is found, sets dev_desc and part_info accordingly with the 15 * information of the partition with the given partition_name. 16 * 17 * @dev_iface: Device interface. Only "mmc" is supported at the moment. 18 * @dev_part_str: Input string argument, like "0;misc". 19 * @dev_desc: Place to put the device description pointer. 20 * @part_info: Place to put the partition information. 21 * @return 0 on success, or -1 on error 22 */ 23 static int part_get_info_by_dev_and_name(const char *dev_iface, 24 const char *dev_part_str, 25 struct blk_desc **dev_desc, 26 disk_partition_t *part_info) 27 { 28 #ifdef CONFIG_EFI_PARTITION 29 char *ep; 30 const char *part_str; 31 int dev_num; 32 33 /* We only support "mmc" for looking up partition names. */ 34 if (strcmp(dev_iface, "mmc") != 0) 35 return -1; 36 37 part_str = strchr(dev_part_str, ';'); 38 if (!part_str) 39 return -1; 40 41 dev_num = simple_strtoul(dev_part_str, &ep, 16); 42 if (ep != part_str) { 43 /* Not all the first part before the ; was parsed. */ 44 return -1; 45 } 46 part_str++; 47 48 *dev_desc = blk_get_dev("mmc", dev_num); 49 if (!*dev_desc) { 50 printf("Could not find mmc %d\n", dev_num); 51 return -1; 52 } 53 if (part_get_info_by_name(*dev_desc, part_str, part_info) < 0) { 54 printf("Could not find \"%s\" partition\n", part_str); 55 return -1; 56 } 57 return 0; 58 #else 59 return -1; 60 #endif /* CONFIG_EFI_PARTITION */ 61 } 62 63 static int do_boot_android(cmd_tbl_t *cmdtp, int flag, int argc, 64 char * const argv[]) 65 { 66 unsigned long load_address; 67 int ret = CMD_RET_SUCCESS; 68 char *addr_arg_endp, *addr_str; 69 struct blk_desc *dev_desc; 70 disk_partition_t part_info; 71 const char *misc_part_iface; 72 const char *misc_part_desc; 73 74 if (argc < 3) 75 return CMD_RET_USAGE; 76 if (argc > 4) 77 return CMD_RET_USAGE; 78 79 if (argc >= 4) { 80 load_address = simple_strtoul(argv[3], &addr_arg_endp, 16); 81 if (addr_arg_endp == argv[3] || *addr_arg_endp != '\0') 82 return CMD_RET_USAGE; 83 } else { 84 addr_str = env_get("loadaddr"); 85 if (addr_str) 86 load_address = simple_strtoul(addr_str, NULL, 16); 87 else 88 load_address = CONFIG_SYS_LOAD_ADDR; 89 } 90 91 /* Lookup the "misc" partition from argv[1] and argv[2] */ 92 misc_part_iface = argv[1]; 93 misc_part_desc = argv[2]; 94 /* Split the part_name if passed as "$dev_num;part_name". */ 95 if (part_get_info_by_dev_and_name(misc_part_iface, misc_part_desc, 96 &dev_desc, &part_info) < 0) { 97 /* Couldn't lookup by name from mmc, try looking up the 98 * partition description directly. 99 */ 100 if (blk_get_device_part_str(misc_part_iface, misc_part_desc, 101 &dev_desc, &part_info, 1) < 0) { 102 printf("Couldn't find partition %s %s\n", 103 misc_part_iface, misc_part_desc); 104 return CMD_RET_FAILURE; 105 } 106 } 107 108 ret = android_bootloader_boot_flow(dev_desc, &part_info, load_address); 109 if (ret < 0) { 110 printf("Android boot failed, error %d.\n", ret); 111 return CMD_RET_FAILURE; 112 } 113 return CMD_RET_SUCCESS; 114 } 115 116 U_BOOT_CMD( 117 boot_android, 4, 0, do_boot_android, 118 "Execute the Android Bootloader flow.", 119 "<interface> <dev[:part" 120 #if defined(CONFIG_EFI_PARTITION) 121 /* When EFI is enabled we also support looking up a partition name. */ 122 "|;part_name" 123 #endif /* CONFIG_EFI_PARTITION */ 124 "]> [<kernel_addr>]\n" 125 " - Load the Boot Control Block (BCB) from the partition 'part' on\n" 126 " device type 'interface' instance 'dev' to determine the boot\n" 127 " mode, and load and execute the appropriate kernel.\n" 128 " In normal and recovery mode, the kernel will be loaded from\n" 129 " the corresponding \"boot\" partition. In bootloader mode, the\n" 130 " command defined in the \"fastbootcmd\" variable will be\n" 131 " executed.\n" 132 #if defined(CONFIG_EFI_PARTITION) 133 " - If 'part_name' is passed, preceded with a ; instead of :, the\n" 134 " partition name whose label is 'part_name' will be looked up in\n" 135 " the partition table. This is commonly the \"misc\" partition.\n" 136 #endif /* CONFIG_EFI_PARTITION */ 137 ); 138