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 <android_bootloader_message.h> 9 10 #include <cli.h> 11 #include <common.h> 12 #include <malloc.h> 13 14 #define ANDROID_PARTITION_BOOT "boot" 15 #define ANDROID_PARTITION_SYSTEM "system" 16 17 #define ANDROID_ARG_SLOT_SUFFIX "androidboot.slot_suffix=" 18 #define ANDROID_ARG_ROOT "root=" 19 #define ANDROID_ARG_SERIALNO "androidboot.serialno=" 20 21 static int android_bootloader_message_load( 22 struct blk_desc *dev_desc, 23 const disk_partition_t *part_info, 24 struct android_bootloader_message *message) 25 { 26 ulong message_blocks = sizeof(struct android_bootloader_message) / 27 part_info->blksz; 28 if (message_blocks > part_info->size) { 29 printf("misc partition too small.\n"); 30 return -1; 31 } 32 33 if (blk_dread(dev_desc, part_info->start, message_blocks, message) != 34 message_blocks) { 35 printf("Could not read from misc partition\n"); 36 return -1; 37 } 38 debug("ANDROID: Loaded BCB, %lu blocks.\n", message_blocks); 39 return 0; 40 } 41 42 static int android_bootloader_message_write( 43 struct blk_desc *dev_desc, 44 const disk_partition_t *part_info, 45 struct android_bootloader_message *message) 46 { 47 ulong message_blocks = sizeof(struct android_bootloader_message) / 48 part_info->blksz; 49 if (message_blocks > part_info->size) { 50 printf("misc partition too small.\n"); 51 return -1; 52 } 53 54 if (blk_dwrite(dev_desc, part_info->start, message_blocks, message) != 55 message_blocks) { 56 printf("Could not write to misc partition\n"); 57 return -1; 58 } 59 debug("ANDROID: Wrote new BCB, %lu blocks.\n", message_blocks); 60 return 0; 61 } 62 63 static enum android_boot_mode android_bootloader_load_and_clear_mode( 64 struct blk_desc *dev_desc, 65 const disk_partition_t *misc_part_info) 66 { 67 struct android_bootloader_message bcb; 68 69 #ifdef CONFIG_FASTBOOT 70 char *bootloader_str; 71 72 /* Check for message from bootloader stored in RAM from a previous boot. 73 */ 74 bootloader_str = (char *)CONFIG_FASTBOOT_BUF_ADDR; 75 if (!strcmp("reboot-bootloader", bootloader_str)) { 76 bootloader_str[0] = '\0'; 77 return ANDROID_BOOT_MODE_BOOTLOADER; 78 } 79 #endif 80 81 /* Check and update the BCB message if needed. */ 82 if (android_bootloader_message_load(dev_desc, misc_part_info, &bcb) < 83 0) { 84 printf("WARNING: Unable to load the BCB.\n"); 85 return ANDROID_BOOT_MODE_NORMAL; 86 } 87 88 if (!strcmp("bootonce-bootloader", bcb.command)) { 89 /* Erase the message in the BCB since this value should be used 90 * only once. 91 */ 92 memset(bcb.command, 0, sizeof(bcb.command)); 93 android_bootloader_message_write(dev_desc, misc_part_info, 94 &bcb); 95 return ANDROID_BOOT_MODE_BOOTLOADER; 96 } 97 98 if (!strcmp("boot-recovery", bcb.command)) 99 return ANDROID_BOOT_MODE_RECOVERY; 100 101 return ANDROID_BOOT_MODE_NORMAL; 102 } 103 104 /** 105 * Return the reboot reason string for the passed boot mode. 106 * 107 * @param mode The Android Boot mode. 108 * @return a pointer to the reboot reason string for mode. 109 */ 110 static const char *android_boot_mode_str(enum android_boot_mode mode) 111 { 112 switch (mode) { 113 case ANDROID_BOOT_MODE_NORMAL: 114 return "(none)"; 115 case ANDROID_BOOT_MODE_RECOVERY: 116 return "recovery"; 117 case ANDROID_BOOT_MODE_BOOTLOADER: 118 return "bootloader"; 119 } 120 return NULL; 121 } 122 123 static int android_part_get_info_by_name_suffix(struct blk_desc *dev_desc, 124 const char *base_name, 125 const char *slot_suffix, 126 disk_partition_t *part_info) 127 { 128 char *part_name; 129 int part_num; 130 size_t part_name_len; 131 132 part_name_len = strlen(base_name) + 1; 133 if (slot_suffix) 134 part_name_len += strlen(slot_suffix); 135 part_name = malloc(part_name_len); 136 if (!part_name) 137 return -1; 138 strcpy(part_name, base_name); 139 if (slot_suffix) 140 strcat(part_name, slot_suffix); 141 142 part_num = part_get_info_by_name(dev_desc, part_name, part_info); 143 if (part_num < 0) { 144 debug("ANDROID: Could not find partition \"%s\"\n", part_name); 145 part_num = -1; 146 } 147 148 free(part_name); 149 return part_num; 150 } 151 152 static int android_bootloader_boot_bootloader(void) 153 { 154 const char *fastboot_cmd = env_get("fastbootcmd"); 155 156 if (fastboot_cmd) 157 return run_command(fastboot_cmd, CMD_FLAG_ENV); 158 return -1; 159 } 160 161 int android_bootloader_boot_kernel(unsigned long kernel_address) 162 { 163 char kernel_addr_str[12]; 164 char *fdt_addr = env_get("fdt_addr"); 165 char *bootm_args[] = { 166 "bootm", kernel_addr_str, kernel_addr_str, fdt_addr, NULL }; 167 168 sprintf(kernel_addr_str, "0x%lx", kernel_address); 169 170 printf("Booting kernel at %s with fdt at %s...\n\n\n", 171 kernel_addr_str, fdt_addr); 172 do_bootm(NULL, 0, 4, bootm_args); 173 174 return -1; 175 } 176 177 static char *strjoin(const char **chunks, char separator) 178 { 179 int len, joined_len = 0; 180 char *ret, *current; 181 const char **p; 182 183 for (p = chunks; *p; p++) 184 joined_len += strlen(*p) + 1; 185 186 if (!joined_len) { 187 ret = malloc(1); 188 if (ret) 189 ret[0] = '\0'; 190 return ret; 191 } 192 193 ret = malloc(joined_len); 194 current = ret; 195 if (!ret) 196 return ret; 197 198 for (p = chunks; *p; p++) { 199 len = strlen(*p); 200 memcpy(current, *p, len); 201 current += len; 202 *current = separator; 203 current++; 204 } 205 /* Replace the last separator by a \0. */ 206 current[-1] = '\0'; 207 return ret; 208 } 209 210 /** android_assemble_cmdline - Assemble the command line to pass to the kernel 211 * @return a newly allocated string 212 */ 213 char *android_assemble_cmdline(const char *slot_suffix, 214 const char *extra_args) 215 { 216 const char *cmdline_chunks[16]; 217 const char **current_chunk = cmdline_chunks; 218 char *env_cmdline, *cmdline, *rootdev_input, *serialno; 219 char *allocated_suffix = NULL; 220 char *allocated_serialno = NULL; 221 char *allocated_rootdev = NULL; 222 unsigned long rootdev_len; 223 224 env_cmdline = env_get("bootargs"); 225 if (env_cmdline) 226 *(current_chunk++) = env_cmdline; 227 228 /* The |slot_suffix| needs to be passed to the kernel to know what 229 * slot to boot from. 230 */ 231 if (slot_suffix) { 232 allocated_suffix = malloc(strlen(ANDROID_ARG_SLOT_SUFFIX) + 233 strlen(slot_suffix)); 234 strcpy(allocated_suffix, ANDROID_ARG_SLOT_SUFFIX); 235 strcat(allocated_suffix, slot_suffix); 236 *(current_chunk++) = allocated_suffix; 237 } 238 239 serialno = env_get("serial#"); 240 if (serialno) { 241 allocated_serialno = malloc(strlen(ANDROID_ARG_SERIALNO) + 242 strlen(serialno) + 1); 243 memset(allocated_serialno, 0, strlen(ANDROID_ARG_SERIALNO) + 244 strlen(serialno) + 1); 245 strcpy(allocated_serialno, ANDROID_ARG_SERIALNO); 246 strcat(allocated_serialno, serialno); 247 *(current_chunk++) = allocated_serialno; 248 } 249 250 rootdev_input = env_get("android_rootdev"); 251 if (rootdev_input) { 252 rootdev_len = strlen(ANDROID_ARG_ROOT) + CONFIG_SYS_CBSIZE + 1; 253 allocated_rootdev = malloc(rootdev_len); 254 strcpy(allocated_rootdev, ANDROID_ARG_ROOT); 255 cli_simple_process_macros(rootdev_input, 256 allocated_rootdev + 257 strlen(ANDROID_ARG_ROOT)); 258 /* Make sure that the string is null-terminated since the 259 * previous could not copy to the end of the input string if it 260 * is too big. 261 */ 262 allocated_rootdev[rootdev_len - 1] = '\0'; 263 *(current_chunk++) = allocated_rootdev; 264 } 265 266 if (extra_args) 267 *(current_chunk++) = extra_args; 268 269 *(current_chunk++) = NULL; 270 cmdline = strjoin(cmdline_chunks, ' '); 271 free(allocated_suffix); 272 free(allocated_rootdev); 273 return cmdline; 274 } 275 276 int android_bootloader_boot_flow(struct blk_desc *dev_desc, 277 const disk_partition_t *misc_part_info, 278 const char *slot, 279 unsigned long kernel_address) 280 { 281 enum android_boot_mode mode; 282 disk_partition_t boot_part_info; 283 disk_partition_t system_part_info; 284 int boot_part_num, system_part_num; 285 int ret; 286 char *command_line; 287 char slot_suffix[3]; 288 const char *mode_cmdline = NULL; 289 290 /* Determine the boot mode and clear its value for the next boot if 291 * needed. 292 */ 293 mode = android_bootloader_load_and_clear_mode(dev_desc, misc_part_info); 294 printf("ANDROID: reboot reason: \"%s\"\n", android_boot_mode_str(mode)); 295 296 switch (mode) { 297 case ANDROID_BOOT_MODE_NORMAL: 298 /* In normal mode, we load the kernel from "boot" but append 299 * "skip_initramfs" to the cmdline to make it ignore the 300 * recovery initramfs in the boot partition. 301 */ 302 mode_cmdline = "skip_initramfs"; 303 break; 304 case ANDROID_BOOT_MODE_RECOVERY: 305 /* In recovery mode we still boot the kernel from "boot" but 306 * don't skip the initramfs so it boots to recovery. 307 */ 308 break; 309 case ANDROID_BOOT_MODE_BOOTLOADER: 310 /* Bootloader mode enters fastboot. If this operation fails we 311 * simply return since we can't recover from this situation by 312 * switching to another slot. 313 */ 314 return android_bootloader_boot_bootloader(); 315 } 316 317 slot_suffix[0] = '\0'; 318 if (slot && slot[0]) { 319 slot_suffix[0] = '_'; 320 slot_suffix[1] = slot[0]; 321 slot_suffix[2] = '\0'; 322 } 323 324 /* Load the kernel from the desired "boot" partition. */ 325 boot_part_num = 326 android_part_get_info_by_name_suffix(dev_desc, 327 ANDROID_PARTITION_BOOT, 328 slot_suffix, &boot_part_info); 329 if (boot_part_num < 0) 330 return -1; 331 debug("ANDROID: Loading kernel from \"%s\", partition %d.\n", 332 boot_part_info.name, boot_part_num); 333 334 system_part_num = 335 android_part_get_info_by_name_suffix(dev_desc, 336 ANDROID_PARTITION_SYSTEM, 337 slot_suffix, 338 &system_part_info); 339 if (system_part_num < 0) 340 return -1; 341 debug("ANDROID: Using system image from \"%s\", partition %d.\n", 342 system_part_info.name, system_part_num); 343 344 ret = android_image_load(dev_desc, &boot_part_info, kernel_address, 345 -1UL); 346 if (ret < 0) 347 return ret; 348 349 /* Set Android root variables. */ 350 env_set_ulong("android_root_devnum", dev_desc->devnum); 351 env_set_ulong("android_root_partnum", system_part_num); 352 env_set("android_slotsufix", slot_suffix); 353 354 /* Assemble the command line */ 355 command_line = android_assemble_cmdline(slot_suffix, mode_cmdline); 356 env_set("bootargs", command_line); 357 358 debug("ANDROID: bootargs: \"%s\"\n", command_line); 359 360 android_bootloader_boot_kernel(kernel_address); 361 362 /* TODO: If the kernel doesn't boot mark the selected slot as bad. */ 363 return -1; 364 } 365 366 int android_avb_boot_flow(char *slot_suffix, unsigned long kernel_address) 367 { 368 const char *dev_iface = "mmc"; 369 int dev_num = 0; 370 struct blk_desc *dev_desc; 371 disk_partition_t boot_part_info; 372 int ret; 373 dev_desc = blk_get_dev(dev_iface, dev_num); 374 if (!dev_desc) { 375 printf("Could not find %s %d\n", dev_iface, dev_num); 376 return -1; 377 } 378 /* Load the kernel from the desired "boot" partition. */ 379 android_part_get_info_by_name_suffix(dev_desc, 380 ANDROID_PARTITION_BOOT, 381 slot_suffix, &boot_part_info); 382 ret = android_image_load(dev_desc, &boot_part_info, kernel_address, 383 -1UL); 384 if (ret < 0) 385 return ret; 386 android_bootloader_boot_kernel(kernel_address); 387 388 /* TODO: If the kernel doesn't boot mark the selected slot as bad. */ 389 return -1; 390 } 391