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