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