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