xref: /rk3399_rockchip-uboot/cmd/boot_android.c (revision 806222402666e6df9c63adc56ae6a22832c53b3f)
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>
806f4a874SAlex Deymo #include <common.h>
906f4a874SAlex Deymo #include <command.h>
1006f4a874SAlex Deymo 
1106f4a874SAlex Deymo /**
1206f4a874SAlex Deymo  * part_get_info_by_dev_and_name - Parse a device number and partition name
1306f4a874SAlex Deymo  * string in the form of "device_num;partition_name", for example "0;misc".
1406f4a874SAlex Deymo  * If the partition is found, sets dev_desc and part_info accordingly with the
1506f4a874SAlex Deymo  * information of the partition with the given partition_name.
1606f4a874SAlex Deymo  *
1706f4a874SAlex Deymo  * @dev_iface:		Device interface. Only "mmc" is supported at the moment.
1806f4a874SAlex Deymo  * @dev_part_str:	Input string argument, like "0;misc".
1906f4a874SAlex Deymo  * @dev_desc:		Place to put the device description pointer.
2006f4a874SAlex Deymo  * @part_info:		Place to put the partition information.
2106f4a874SAlex Deymo  * @return 0 on success, or -1 on error
2206f4a874SAlex Deymo  */
2306f4a874SAlex Deymo static int part_get_info_by_dev_and_name(const char *dev_iface,
2406f4a874SAlex Deymo 					 const char *dev_part_str,
2506f4a874SAlex Deymo 					 struct blk_desc **dev_desc,
2606f4a874SAlex Deymo 					 disk_partition_t *part_info)
2706f4a874SAlex Deymo {
2806f4a874SAlex Deymo #ifdef CONFIG_EFI_PARTITION
2906f4a874SAlex Deymo 	char *ep;
3006f4a874SAlex Deymo 	const char *part_str;
3106f4a874SAlex Deymo 	int dev_num;
3206f4a874SAlex Deymo 
3306f4a874SAlex Deymo 	/* We only support "mmc" for looking up partition names. */
3406f4a874SAlex Deymo 	if (strcmp(dev_iface, "mmc") != 0)
3506f4a874SAlex Deymo 		return -1;
3606f4a874SAlex Deymo 
3706f4a874SAlex Deymo 	part_str = strchr(dev_part_str, ';');
3806f4a874SAlex Deymo 	if (!part_str)
3906f4a874SAlex Deymo 		return -1;
4006f4a874SAlex Deymo 
4106f4a874SAlex Deymo 	dev_num = simple_strtoul(dev_part_str, &ep, 16);
4206f4a874SAlex Deymo 	if (ep != part_str) {
4306f4a874SAlex Deymo 		/* Not all the first part before the ; was parsed. */
4406f4a874SAlex Deymo 		return -1;
4506f4a874SAlex Deymo 	}
4606f4a874SAlex Deymo 	part_str++;
4706f4a874SAlex Deymo 
4806f4a874SAlex Deymo 	*dev_desc = blk_get_dev("mmc", dev_num);
4906f4a874SAlex Deymo 	if (!*dev_desc) {
5006f4a874SAlex Deymo 		printf("Could not find mmc %d\n", dev_num);
5106f4a874SAlex Deymo 		return -1;
5206f4a874SAlex Deymo 	}
5306f4a874SAlex Deymo 	if (part_get_info_by_name(*dev_desc, part_str, part_info) < 0) {
5406f4a874SAlex Deymo 		printf("Could not find \"%s\" partition\n", part_str);
5506f4a874SAlex Deymo 		return -1;
5606f4a874SAlex Deymo 	}
5706f4a874SAlex Deymo 	return 0;
5806f4a874SAlex Deymo #else
5906f4a874SAlex Deymo 	return -1;
6006f4a874SAlex Deymo #endif  /* CONFIG_EFI_PARTITION */
6106f4a874SAlex Deymo }
6206f4a874SAlex Deymo 
6306f4a874SAlex Deymo static int do_boot_android(cmd_tbl_t *cmdtp, int flag, int argc,
6406f4a874SAlex Deymo 			   char * const argv[])
6506f4a874SAlex Deymo {
6606f4a874SAlex Deymo 	unsigned long load_address;
6706f4a874SAlex Deymo 	int ret = CMD_RET_SUCCESS;
6806f4a874SAlex Deymo 	char *addr_arg_endp, *addr_str;
6906f4a874SAlex Deymo 	struct blk_desc *dev_desc;
7006f4a874SAlex Deymo 	disk_partition_t part_info;
7106f4a874SAlex Deymo 	const char *misc_part_iface;
7206f4a874SAlex Deymo 	const char *misc_part_desc;
7306f4a874SAlex Deymo 
74*80622240SAlex Deymo 	if (argc < 4)
7506f4a874SAlex Deymo 		return CMD_RET_USAGE;
76*80622240SAlex Deymo 	if (argc > 5)
7706f4a874SAlex Deymo 		return CMD_RET_USAGE;
7806f4a874SAlex Deymo 
79*80622240SAlex Deymo 	if (argc >= 5) {
80*80622240SAlex Deymo 		load_address = simple_strtoul(argv[4], &addr_arg_endp, 16);
81*80622240SAlex Deymo 		if (addr_arg_endp == argv[4] || *addr_arg_endp != '\0')
8206f4a874SAlex Deymo 			return CMD_RET_USAGE;
8306f4a874SAlex Deymo 	} else {
8406f4a874SAlex Deymo 		addr_str = env_get("loadaddr");
8506f4a874SAlex Deymo 		if (addr_str)
8606f4a874SAlex Deymo 			load_address = simple_strtoul(addr_str, NULL, 16);
8706f4a874SAlex Deymo 		else
8806f4a874SAlex Deymo 			load_address = CONFIG_SYS_LOAD_ADDR;
8906f4a874SAlex Deymo 	}
9006f4a874SAlex Deymo 
9106f4a874SAlex Deymo 	/* Lookup the "misc" partition from argv[1] and argv[2] */
9206f4a874SAlex Deymo 	misc_part_iface = argv[1];
9306f4a874SAlex Deymo 	misc_part_desc = argv[2];
9406f4a874SAlex Deymo 	/* Split the part_name if passed as "$dev_num;part_name". */
9506f4a874SAlex Deymo 	if (part_get_info_by_dev_and_name(misc_part_iface, misc_part_desc,
9606f4a874SAlex Deymo 					  &dev_desc, &part_info) < 0) {
9706f4a874SAlex Deymo 		/* Couldn't lookup by name from mmc, try looking up the
9806f4a874SAlex Deymo 		 * partition description directly.
9906f4a874SAlex Deymo 		 */
10006f4a874SAlex Deymo 		if (blk_get_device_part_str(misc_part_iface, misc_part_desc,
10106f4a874SAlex Deymo 					    &dev_desc, &part_info, 1) < 0) {
10206f4a874SAlex Deymo 			printf("Couldn't find partition %s %s\n",
10306f4a874SAlex Deymo 			       misc_part_iface, misc_part_desc);
10406f4a874SAlex Deymo 			return CMD_RET_FAILURE;
10506f4a874SAlex Deymo 		}
10606f4a874SAlex Deymo 	}
10706f4a874SAlex Deymo 
108*80622240SAlex Deymo 	ret = android_bootloader_boot_flow(dev_desc, &part_info, argv[3],
109*80622240SAlex Deymo 					   load_address);
11006f4a874SAlex Deymo 	if (ret < 0) {
11106f4a874SAlex Deymo 		printf("Android boot failed, error %d.\n", ret);
11206f4a874SAlex Deymo 		return CMD_RET_FAILURE;
11306f4a874SAlex Deymo 	}
11406f4a874SAlex Deymo 	return CMD_RET_SUCCESS;
11506f4a874SAlex Deymo }
11606f4a874SAlex Deymo 
11706f4a874SAlex Deymo U_BOOT_CMD(
118*80622240SAlex Deymo 	boot_android, 5, 0, do_boot_android,
11906f4a874SAlex Deymo 	"Execute the Android Bootloader flow.",
12006f4a874SAlex Deymo 	"<interface> <dev[:part"
12106f4a874SAlex Deymo #if defined(CONFIG_EFI_PARTITION)
12206f4a874SAlex Deymo 	/* When EFI is enabled we also support looking up a partition name. */
12306f4a874SAlex Deymo 	"|;part_name"
12406f4a874SAlex Deymo #endif	/* CONFIG_EFI_PARTITION */
125*80622240SAlex Deymo 	"]> <slot> [<kernel_addr>]\n"
12606f4a874SAlex Deymo 	"    - Load the Boot Control Block (BCB) from the partition 'part' on\n"
12706f4a874SAlex Deymo 	"      device type 'interface' instance 'dev' to determine the boot\n"
12806f4a874SAlex Deymo 	"      mode, and load and execute the appropriate kernel.\n"
12906f4a874SAlex Deymo 	"      In normal and recovery mode, the kernel will be loaded from\n"
13006f4a874SAlex Deymo 	"      the corresponding \"boot\" partition. In bootloader mode, the\n"
13106f4a874SAlex Deymo 	"      command defined in the \"fastbootcmd\" variable will be\n"
13206f4a874SAlex Deymo 	"      executed.\n"
133*80622240SAlex Deymo 	"      On Android devices with multiple slots, the pass 'slot' is\n"
134*80622240SAlex Deymo 	"      used to load the appropriate kernel. The standard slot names\n"
135*80622240SAlex Deymo 	"      are 'a' and 'b'.\n"
13606f4a874SAlex Deymo #if defined(CONFIG_EFI_PARTITION)
13706f4a874SAlex Deymo 	"    - If 'part_name' is passed, preceded with a ; instead of :, the\n"
13806f4a874SAlex Deymo 	"      partition name whose label is 'part_name' will be looked up in\n"
13906f4a874SAlex Deymo 	"      the partition table. This is commonly the \"misc\" partition.\n"
14006f4a874SAlex Deymo #endif	/* CONFIG_EFI_PARTITION */
14106f4a874SAlex Deymo );
142