diff options
author | Alex Deymo | 2016-12-01 16:21:51 -0600 |
---|---|---|
committer | Alistair Strachan | 2018-08-10 21:54:55 -0500 |
commit | 0ec64604e347544b09428ef7badd6ed3554a40a6 (patch) | |
tree | 4651ae3aef05aec7820e1b07169a44852eee4f4d | |
parent | 6a078de7682f595c93a7720fa447ecdd6b585610 (diff) | |
download | u-boot-0ec64604e347544b09428ef7badd6ed3554a40a6.tar.gz u-boot-0ec64604e347544b09428ef7badd6ed3554a40a6.tar.xz u-boot-0ec64604e347544b09428ef7badd6ed3554a40a6.zip |
Add "boot_android" command.
The new "boot_android" command simply executes the Android Bootloader
flow. This receives the location (interface, dev, partition) of the
Android "misc" partition which is then used to lookup and infer the
kernel and system images that should be booted.
Bug: 32707546
Test: Booted a rpi3 build with Android Things.
Signed-off-by: Alex Deymo <deymo@google.com>
Change-Id: Ibf3f31e38b159d42db7a0835b99ad7ec260fc2a7
-rw-r--r-- | README | 6 | ||||
-rw-r--r-- | cmd/Kconfig | 10 | ||||
-rw-r--r-- | cmd/Makefile | 1 | ||||
-rw-r--r-- | cmd/boot_android.c | 126 | ||||
-rw-r--r-- | common/android_bootloader.c | 23 | ||||
-rw-r--r-- | include/android_bootloader.h | 6 |
6 files changed, 167 insertions, 5 deletions
@@ -1207,6 +1207,12 @@ The following options need to be configured: | |||
1207 | sending again an USB request to the device. | 1207 | sending again an USB request to the device. |
1208 | 1208 | ||
1209 | - Android Bootloader support: | 1209 | - Android Bootloader support: |
1210 | CONFIG_CMD_BOOT_ANDROID | ||
1211 | This enables the command "boot_android" which executes the | ||
1212 | Android Bootloader flow. Enabling CONFIG_CMD_FASTBOOT is | ||
1213 | recommended to support the Android Fastboot protocol as part | ||
1214 | of the bootloader. | ||
1215 | |||
1210 | CONFIG_ANDROID_BOOTLOADER | 1216 | CONFIG_ANDROID_BOOTLOADER |
1211 | This enables support for the Android bootloader flow. Android | 1217 | This enables support for the Android bootloader flow. Android |
1212 | devices can boot in normal mode, recovery mode or bootloader | 1218 | devices can boot in normal mode, recovery mode or bootloader |
diff --git a/cmd/Kconfig b/cmd/Kconfig index aec209006d..ef8d9cba0b 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig | |||
@@ -607,6 +607,16 @@ config CMD_ADC | |||
607 | Shows ADC device info and permit printing one-shot analog converted | 607 | Shows ADC device info and permit printing one-shot analog converted |
608 | data from a named Analog to Digital Converter. | 608 | data from a named Analog to Digital Converter. |
609 | 609 | ||
610 | config CMD_BOOT_ANDROID | ||
611 | bool "boot_android" | ||
612 | default n | ||
613 | depends on ANDROID_BOOTLOADER | ||
614 | help | ||
615 | Performs the Android Bootloader boot flow, loading the appropriate | ||
616 | Android image (normal kernel, recovery kernel or "bootloader" mode) | ||
617 | and booting it. The boot mode is determined by the contents of the | ||
618 | Android Bootloader Message. | ||
619 | |||
610 | config CMD_CLK | 620 | config CMD_CLK |
611 | bool "clk - Show clock frequencies" | 621 | bool "clk - Show clock frequencies" |
612 | help | 622 | help |
diff --git a/cmd/Makefile b/cmd/Makefile index 323f1fd2c7..95508385f6 100644 --- a/cmd/Makefile +++ b/cmd/Makefile | |||
@@ -22,6 +22,7 @@ obj-$(CONFIG_CMD_BEDBUG) += bedbug.o | |||
22 | obj-$(CONFIG_CMD_BINOP) += binop.o | 22 | obj-$(CONFIG_CMD_BINOP) += binop.o |
23 | obj-$(CONFIG_CMD_BLOCK_CACHE) += blkcache.o | 23 | obj-$(CONFIG_CMD_BLOCK_CACHE) += blkcache.o |
24 | obj-$(CONFIG_CMD_BMP) += bmp.o | 24 | obj-$(CONFIG_CMD_BMP) += bmp.o |
25 | obj-$(CONFIG_CMD_BOOT_ANDROID) += boot_android.o | ||
25 | obj-$(CONFIG_CMD_BOOTCOUNT) += bootcount.o | 26 | obj-$(CONFIG_CMD_BOOTCOUNT) += bootcount.o |
26 | obj-$(CONFIG_CMD_BOOTEFI) += bootefi.o | 27 | obj-$(CONFIG_CMD_BOOTEFI) += bootefi.o |
27 | obj-$(CONFIG_CMD_BOOTMENU) += bootmenu.o | 28 | obj-$(CONFIG_CMD_BOOTMENU) += bootmenu.o |
diff --git a/cmd/boot_android.c b/cmd/boot_android.c new file mode 100644 index 0000000000..a2148e0238 --- /dev/null +++ b/cmd/boot_android.c | |||
@@ -0,0 +1,126 @@ | |||
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. | ||
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 | char *ep; | ||
29 | const char *part_str; | ||
30 | int dev_num; | ||
31 | |||
32 | part_str = strchr(dev_part_str, ';'); | ||
33 | if (!part_str) | ||
34 | return -1; | ||
35 | |||
36 | dev_num = simple_strtoul(dev_part_str, &ep, 16); | ||
37 | if (ep != part_str) { | ||
38 | /* Not all the first part before the ; was parsed. */ | ||
39 | return -1; | ||
40 | } | ||
41 | part_str++; | ||
42 | |||
43 | *dev_desc = blk_get_dev(dev_iface, dev_num); | ||
44 | if (!*dev_desc) { | ||
45 | printf("Could not find %s %d\n", dev_iface, dev_num); | ||
46 | return -1; | ||
47 | } | ||
48 | if (part_get_info_by_name(*dev_desc, part_str, part_info) < 0) { | ||
49 | printf("Could not find \"%s\" partition\n", part_str); | ||
50 | return -1; | ||
51 | } | ||
52 | return 0; | ||
53 | } | ||
54 | |||
55 | static int do_boot_android(cmd_tbl_t *cmdtp, int flag, int argc, | ||
56 | char * const argv[]) | ||
57 | { | ||
58 | unsigned long load_address; | ||
59 | int ret = CMD_RET_SUCCESS; | ||
60 | char *addr_arg_endp, *addr_str; | ||
61 | struct blk_desc *dev_desc; | ||
62 | disk_partition_t part_info; | ||
63 | const char *misc_part_iface; | ||
64 | const char *misc_part_desc; | ||
65 | |||
66 | if (argc < 4) | ||
67 | return CMD_RET_USAGE; | ||
68 | if (argc > 5) | ||
69 | return CMD_RET_USAGE; | ||
70 | |||
71 | if (argc >= 5) { | ||
72 | load_address = simple_strtoul(argv[4], &addr_arg_endp, 16); | ||
73 | if (addr_arg_endp == argv[4] || *addr_arg_endp != '\0') | ||
74 | return CMD_RET_USAGE; | ||
75 | } else { | ||
76 | addr_str = env_get("loadaddr"); | ||
77 | if (addr_str) | ||
78 | load_address = simple_strtoul(addr_str, NULL, 16); | ||
79 | else | ||
80 | load_address = CONFIG_SYS_LOAD_ADDR; | ||
81 | } | ||
82 | |||
83 | /* Lookup the "misc" partition from argv[1] and argv[2] */ | ||
84 | misc_part_iface = argv[1]; | ||
85 | misc_part_desc = argv[2]; | ||
86 | /* Split the part_name if passed as "$dev_num;part_name". */ | ||
87 | if (part_get_info_by_dev_and_name(misc_part_iface, misc_part_desc, | ||
88 | &dev_desc, &part_info) < 0) { | ||
89 | /* Couldn't lookup by name from mmc, try looking up the | ||
90 | * partition description directly. | ||
91 | */ | ||
92 | if (blk_get_device_part_str(misc_part_iface, misc_part_desc, | ||
93 | &dev_desc, &part_info, 1) < 0) { | ||
94 | printf("Couldn't find partition %s %s\n", | ||
95 | misc_part_iface, misc_part_desc); | ||
96 | return CMD_RET_FAILURE; | ||
97 | } | ||
98 | } | ||
99 | |||
100 | ret = android_bootloader_boot_flow(dev_desc, &part_info, argv[3], | ||
101 | load_address); | ||
102 | if (ret < 0) { | ||
103 | printf("Android boot failed, error %d.\n", ret); | ||
104 | return CMD_RET_FAILURE; | ||
105 | } | ||
106 | return CMD_RET_SUCCESS; | ||
107 | } | ||
108 | |||
109 | U_BOOT_CMD( | ||
110 | boot_android, 5, 0, do_boot_android, | ||
111 | "Execute the Android Bootloader flow.", | ||
112 | "<interface> <dev[:part|;part_name]> <slot> [<kernel_addr>]\n" | ||
113 | " - Load the Boot Control Block (BCB) from the partition 'part' on\n" | ||
114 | " device type 'interface' instance 'dev' to determine the boot\n" | ||
115 | " mode, and load and execute the appropriate kernel.\n" | ||
116 | " In normal and recovery mode, the kernel will be loaded from\n" | ||
117 | " the corresponding \"boot\" partition. In bootloader mode, the\n" | ||
118 | " command defined in the \"fastbootcmd\" variable will be\n" | ||
119 | " executed.\n" | ||
120 | " On Android devices with multiple slots, the pass 'slot' is\n" | ||
121 | " used to load the appropriate kernel. The standard slot names\n" | ||
122 | " are 'a' and 'b'.\n" | ||
123 | " - If 'part_name' is passed, preceded with a ; instead of :, the\n" | ||
124 | " partition name whose label is 'part_name' will be looked up in\n" | ||
125 | " the partition table. This is commonly the \"misc\" partition.\n" | ||
126 | ); | ||
diff --git a/common/android_bootloader.c b/common/android_bootloader.c index 059eb6a92d..fbfe3de50c 100644 --- a/common/android_bootloader.c +++ b/common/android_bootloader.c | |||
@@ -126,12 +126,17 @@ static int android_part_get_info_by_name_suffix(struct blk_desc *dev_desc, | |||
126 | { | 126 | { |
127 | char *part_name; | 127 | char *part_name; |
128 | int part_num; | 128 | int part_num; |
129 | size_t part_name_len; | ||
129 | 130 | ||
130 | part_name = malloc(strlen(base_name) + strlen(slot_suffix) + 1); | 131 | part_name_len = strlen(base_name) + 1; |
132 | if (slot_suffix) | ||
133 | part_name_len += strlen(slot_suffix); | ||
134 | part_name = malloc(part_name_len); | ||
131 | if (!part_name) | 135 | if (!part_name) |
132 | return -1; | 136 | return -1; |
133 | strcpy(part_name, base_name); | 137 | strcpy(part_name, base_name); |
134 | strcat(part_name, slot_suffix); | 138 | if (slot_suffix) |
139 | strcat(part_name, slot_suffix); | ||
135 | 140 | ||
136 | part_num = part_get_info_by_name(dev_desc, part_name, part_info); | 141 | part_num = part_get_info_by_name(dev_desc, part_name, part_info); |
137 | if (part_num < 0) { | 142 | if (part_num < 0) { |
@@ -156,7 +161,8 @@ static int android_bootloader_boot_kernel(unsigned long kernel_address) | |||
156 | { | 161 | { |
157 | char kernel_addr_str[12]; | 162 | char kernel_addr_str[12]; |
158 | char *fdt_addr = env_get("fdt_addr"); | 163 | char *fdt_addr = env_get("fdt_addr"); |
159 | char *bootm_args[] = { "bootm", kernel_addr_str, "-", fdt_addr, NULL }; | 164 | char *bootm_args[] = { |
165 | "bootm", kernel_addr_str, kernel_addr_str, fdt_addr, NULL }; | ||
160 | 166 | ||
161 | sprintf(kernel_addr_str, "0x%lx", kernel_address); | 167 | sprintf(kernel_addr_str, "0x%lx", kernel_address); |
162 | 168 | ||
@@ -256,6 +262,7 @@ static char *android_assemble_cmdline(const char *slot_suffix, | |||
256 | 262 | ||
257 | int android_bootloader_boot_flow(struct blk_desc *dev_desc, | 263 | int android_bootloader_boot_flow(struct blk_desc *dev_desc, |
258 | const disk_partition_t *misc_part_info, | 264 | const disk_partition_t *misc_part_info, |
265 | const char *slot, | ||
259 | unsigned long kernel_address) | 266 | unsigned long kernel_address) |
260 | { | 267 | { |
261 | enum android_boot_mode mode; | 268 | enum android_boot_mode mode; |
@@ -264,8 +271,7 @@ int android_bootloader_boot_flow(struct blk_desc *dev_desc, | |||
264 | int boot_part_num, system_part_num; | 271 | int boot_part_num, system_part_num; |
265 | int ret; | 272 | int ret; |
266 | char *command_line; | 273 | char *command_line; |
267 | /* TODO: lookup the slot_suffix based on the BCB. */ | 274 | char slot_suffix[3]; |
268 | const char *slot_suffix = "_a"; | ||
269 | const char *mode_cmdline = NULL; | 275 | const char *mode_cmdline = NULL; |
270 | 276 | ||
271 | /* Determine the boot mode and clear its value for the next boot if | 277 | /* Determine the boot mode and clear its value for the next boot if |
@@ -295,6 +301,13 @@ int android_bootloader_boot_flow(struct blk_desc *dev_desc, | |||
295 | return android_bootloader_boot_bootloader(); | 301 | return android_bootloader_boot_bootloader(); |
296 | } | 302 | } |
297 | 303 | ||
304 | slot_suffix[0] = '\0'; | ||
305 | if (slot && slot[0]) { | ||
306 | slot_suffix[0] = '_'; | ||
307 | slot_suffix[1] = slot[0]; | ||
308 | slot_suffix[2] = '\0'; | ||
309 | } | ||
310 | |||
298 | /* Load the kernel from the desired "boot" partition. */ | 311 | /* Load the kernel from the desired "boot" partition. */ |
299 | boot_part_num = | 312 | boot_part_num = |
300 | android_part_get_info_by_name_suffix(dev_desc, | 313 | android_part_get_info_by_name_suffix(dev_desc, |
diff --git a/include/android_bootloader.h b/include/android_bootloader.h index 947913e547..ddf6d76f64 100644 --- a/include/android_bootloader.h +++ b/include/android_bootloader.h | |||
@@ -33,10 +33,16 @@ enum android_boot_mode { | |||
33 | * The boot mode is determined by the contents of the Android Bootloader | 33 | * The boot mode is determined by the contents of the Android Bootloader |
34 | * Message. On success it doesn't return. | 34 | * Message. On success it doesn't return. |
35 | * | 35 | * |
36 | * @dev_desc: device where to load the kernel and system to boot from. | ||
37 | * @misc_part_info: the "misc" partition descriptor in 'dev_desc'. | ||
38 | * @slot: the boot slot to boot from. | ||
39 | * @kernel_address: address where to load the kernel if needed. | ||
40 | * | ||
36 | * @return a negative number in case of error, otherwise it doesn't return. | 41 | * @return a negative number in case of error, otherwise it doesn't return. |
37 | */ | 42 | */ |
38 | int android_bootloader_boot_flow(struct blk_desc *dev_desc, | 43 | int android_bootloader_boot_flow(struct blk_desc *dev_desc, |
39 | const disk_partition_t *misc_part_info, | 44 | const disk_partition_t *misc_part_info, |
45 | const char *slot, | ||
40 | unsigned long kernel_address); | 46 | unsigned long kernel_address); |
41 | 47 | ||
42 | #endif /* __ANDROID_BOOTLOADER_H */ | 48 | #endif /* __ANDROID_BOOTLOADER_H */ |