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