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