xref: /rk3399_rockchip-uboot/cmd/boot_android.c (revision df7cce43619a94f77bb34c41cdc3d3336841d3e5)
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  *
17*df7cce43SAlex Deymo  * @dev_iface:		Device interface.
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 	char *ep;
2906f4a874SAlex Deymo 	const char *part_str;
3006f4a874SAlex Deymo 	int dev_num;
3106f4a874SAlex Deymo 
3206f4a874SAlex Deymo 	part_str = strchr(dev_part_str, ';');
3306f4a874SAlex Deymo 	if (!part_str)
3406f4a874SAlex Deymo 		return -1;
3506f4a874SAlex Deymo 
3606f4a874SAlex Deymo 	dev_num = simple_strtoul(dev_part_str, &ep, 16);
3706f4a874SAlex Deymo 	if (ep != part_str) {
3806f4a874SAlex Deymo 		/* Not all the first part before the ; was parsed. */
3906f4a874SAlex Deymo 		return -1;
4006f4a874SAlex Deymo 	}
4106f4a874SAlex Deymo 	part_str++;
4206f4a874SAlex Deymo 
43*df7cce43SAlex Deymo 	*dev_desc = blk_get_dev(dev_iface, dev_num);
4406f4a874SAlex Deymo 	if (!*dev_desc) {
45*df7cce43SAlex Deymo 		printf("Could not find %s %d\n", dev_iface, dev_num);
4606f4a874SAlex Deymo 		return -1;
4706f4a874SAlex Deymo 	}
4806f4a874SAlex Deymo 	if (part_get_info_by_name(*dev_desc, part_str, part_info) < 0) {
4906f4a874SAlex Deymo 		printf("Could not find \"%s\" partition\n", part_str);
5006f4a874SAlex Deymo 		return -1;
5106f4a874SAlex Deymo 	}
5206f4a874SAlex Deymo 	return 0;
5306f4a874SAlex Deymo }
5406f4a874SAlex Deymo 
5506f4a874SAlex Deymo static int do_boot_android(cmd_tbl_t *cmdtp, int flag, int argc,
5606f4a874SAlex Deymo 			   char * const argv[])
5706f4a874SAlex Deymo {
5806f4a874SAlex Deymo 	unsigned long load_address;
5906f4a874SAlex Deymo 	int ret = CMD_RET_SUCCESS;
6006f4a874SAlex Deymo 	char *addr_arg_endp, *addr_str;
6106f4a874SAlex Deymo 	struct blk_desc *dev_desc;
6206f4a874SAlex Deymo 	disk_partition_t part_info;
6306f4a874SAlex Deymo 	const char *misc_part_iface;
6406f4a874SAlex Deymo 	const char *misc_part_desc;
6506f4a874SAlex Deymo 
6680622240SAlex Deymo 	if (argc < 4)
6706f4a874SAlex Deymo 		return CMD_RET_USAGE;
6880622240SAlex Deymo 	if (argc > 5)
6906f4a874SAlex Deymo 		return CMD_RET_USAGE;
7006f4a874SAlex Deymo 
7180622240SAlex Deymo 	if (argc >= 5) {
7280622240SAlex Deymo 		load_address = simple_strtoul(argv[4], &addr_arg_endp, 16);
7380622240SAlex Deymo 		if (addr_arg_endp == argv[4] || *addr_arg_endp != '\0')
7406f4a874SAlex Deymo 			return CMD_RET_USAGE;
7506f4a874SAlex Deymo 	} else {
7606f4a874SAlex Deymo 		addr_str = env_get("loadaddr");
7706f4a874SAlex Deymo 		if (addr_str)
7806f4a874SAlex Deymo 			load_address = simple_strtoul(addr_str, NULL, 16);
7906f4a874SAlex Deymo 		else
8006f4a874SAlex Deymo 			load_address = CONFIG_SYS_LOAD_ADDR;
8106f4a874SAlex Deymo 	}
8206f4a874SAlex Deymo 
8306f4a874SAlex Deymo 	/* Lookup the "misc" partition from argv[1] and argv[2] */
8406f4a874SAlex Deymo 	misc_part_iface = argv[1];
8506f4a874SAlex Deymo 	misc_part_desc = argv[2];
8606f4a874SAlex Deymo 	/* Split the part_name if passed as "$dev_num;part_name". */
8706f4a874SAlex Deymo 	if (part_get_info_by_dev_and_name(misc_part_iface, misc_part_desc,
8806f4a874SAlex Deymo 					  &dev_desc, &part_info) < 0) {
8906f4a874SAlex Deymo 		/* Couldn't lookup by name from mmc, try looking up the
9006f4a874SAlex Deymo 		 * partition description directly.
9106f4a874SAlex Deymo 		 */
9206f4a874SAlex Deymo 		if (blk_get_device_part_str(misc_part_iface, misc_part_desc,
9306f4a874SAlex Deymo 					    &dev_desc, &part_info, 1) < 0) {
9406f4a874SAlex Deymo 			printf("Couldn't find partition %s %s\n",
9506f4a874SAlex Deymo 			       misc_part_iface, misc_part_desc);
9606f4a874SAlex Deymo 			return CMD_RET_FAILURE;
9706f4a874SAlex Deymo 		}
9806f4a874SAlex Deymo 	}
9906f4a874SAlex Deymo 
10080622240SAlex Deymo 	ret = android_bootloader_boot_flow(dev_desc, &part_info, argv[3],
10180622240SAlex Deymo 					   load_address);
10206f4a874SAlex Deymo 	if (ret < 0) {
10306f4a874SAlex Deymo 		printf("Android boot failed, error %d.\n", ret);
10406f4a874SAlex Deymo 		return CMD_RET_FAILURE;
10506f4a874SAlex Deymo 	}
10606f4a874SAlex Deymo 	return CMD_RET_SUCCESS;
10706f4a874SAlex Deymo }
10806f4a874SAlex Deymo 
10906f4a874SAlex Deymo U_BOOT_CMD(
11080622240SAlex Deymo 	boot_android, 5, 0, do_boot_android,
11106f4a874SAlex Deymo 	"Execute the Android Bootloader flow.",
112*df7cce43SAlex Deymo 	"<interface> <dev[:part|;part_name]> <slot> [<kernel_addr>]\n"
11306f4a874SAlex Deymo 	"    - Load the Boot Control Block (BCB) from the partition 'part' on\n"
11406f4a874SAlex Deymo 	"      device type 'interface' instance 'dev' to determine the boot\n"
11506f4a874SAlex Deymo 	"      mode, and load and execute the appropriate kernel.\n"
11606f4a874SAlex Deymo 	"      In normal and recovery mode, the kernel will be loaded from\n"
11706f4a874SAlex Deymo 	"      the corresponding \"boot\" partition. In bootloader mode, the\n"
11806f4a874SAlex Deymo 	"      command defined in the \"fastbootcmd\" variable will be\n"
11906f4a874SAlex Deymo 	"      executed.\n"
12080622240SAlex Deymo 	"      On Android devices with multiple slots, the pass 'slot' is\n"
12180622240SAlex Deymo 	"      used to load the appropriate kernel. The standard slot names\n"
12280622240SAlex Deymo 	"      are 'a' and 'b'.\n"
12306f4a874SAlex Deymo 	"    - If 'part_name' is passed, preceded with a ; instead of :, the\n"
12406f4a874SAlex Deymo 	"      partition name whose label is 'part_name' will be looked up in\n"
12506f4a874SAlex Deymo 	"      the partition table. This is commonly the \"misc\" partition.\n"
12606f4a874SAlex Deymo );
127