"Das U-Boot" Source Tree
at master 902 lines 26 kB view raw
1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * Copyright (c) 2011 Sebastian Andrzej Siewior <bigeasy@linutronix.de> 4 */ 5 6#include <env.h> 7#include <image.h> 8#include <image-android-dt.h> 9#include <android_image.h> 10#include <malloc.h> 11#include <errno.h> 12#include <asm/unaligned.h> 13#include <mapmem.h> 14#include <linux/libfdt.h> 15 16#define ANDROID_IMAGE_DEFAULT_KERNEL_ADDR 0x10008000 17#define ANDROID_IMAGE_DEFAULT_RAMDISK_ADDR 0x11000000 18 19static char andr_tmp_str[ANDR_BOOT_ARGS_SIZE + 1]; 20 21static ulong checksum(const unsigned char *buffer, ulong size) 22{ 23 ulong sum = 0; 24 25 for (ulong i = 0; i < size; i++) 26 sum += buffer[i]; 27 return sum; 28} 29 30static bool is_trailer_present(ulong bootconfig_end_addr) 31{ 32 return !strncmp((char *)(bootconfig_end_addr - BOOTCONFIG_MAGIC_SIZE), 33 BOOTCONFIG_MAGIC, BOOTCONFIG_MAGIC_SIZE); 34} 35 36static ulong add_trailer(ulong bootconfig_start_addr, ulong bootconfig_size) 37{ 38 ulong end; 39 ulong sum; 40 41 if (!bootconfig_start_addr) 42 return -1; 43 if (!bootconfig_size) 44 return 0; 45 46 end = bootconfig_start_addr + bootconfig_size; 47 if (is_trailer_present(end)) 48 return 0; 49 50 memcpy((void *)(end), &bootconfig_size, BOOTCONFIG_SIZE_SIZE); 51 sum = checksum((unsigned char *)bootconfig_start_addr, bootconfig_size); 52 memcpy((void *)(end + BOOTCONFIG_SIZE_SIZE), &sum, 53 BOOTCONFIG_CHECKSUM_SIZE); 54 memcpy((void *)(end + BOOTCONFIG_SIZE_SIZE + BOOTCONFIG_CHECKSUM_SIZE), 55 BOOTCONFIG_MAGIC, BOOTCONFIG_MAGIC_SIZE); 56 57 return BOOTCONFIG_TRAILER_SIZE; 58} 59 60__weak ulong get_avendor_bootimg_addr(void) 61{ 62 return -1; 63} 64 65static void android_boot_image_v3_v4_parse_hdr(const struct andr_boot_img_hdr_v3 *hdr, 66 struct andr_image_data *data) 67{ 68 ulong end; 69 70 data->kcmdline = hdr->cmdline; 71 data->header_version = hdr->header_version; 72 73 /* 74 * The header takes a full page, the remaining components are aligned 75 * on page boundary. 76 */ 77 end = (ulong)hdr; 78 end += ANDR_GKI_PAGE_SIZE; 79 data->kernel_ptr = end; 80 data->kernel_size = hdr->kernel_size; 81 end += ALIGN(hdr->kernel_size, ANDR_GKI_PAGE_SIZE); 82 data->ramdisk_ptr = end; 83 data->ramdisk_size = hdr->ramdisk_size; 84 data->boot_ramdisk_size = hdr->ramdisk_size; 85 end += ALIGN(hdr->ramdisk_size, ANDR_GKI_PAGE_SIZE); 86 87 if (hdr->header_version > 3) 88 end += ALIGN(hdr->signature_size, ANDR_GKI_PAGE_SIZE); 89 90 data->boot_img_total_size = end - (ulong)hdr; 91} 92 93static void android_vendor_boot_image_v3_v4_parse_hdr(const struct andr_vnd_boot_img_hdr 94 *hdr, struct andr_image_data *data) 95{ 96 ulong end; 97 98 /* 99 * The header takes a full page, the remaining components are aligned 100 * on page boundary. 101 */ 102 data->kcmdline_extra = hdr->cmdline; 103 data->tags_addr = hdr->tags_addr; 104 data->image_name = hdr->name; 105 data->kernel_addr = hdr->kernel_addr; 106 data->ramdisk_addr = hdr->ramdisk_addr; 107 data->dtb_load_addr = hdr->dtb_addr; 108 data->bootconfig_size = hdr->bootconfig_size; 109 end = (ulong)hdr; 110 end += hdr->page_size; 111 if (hdr->vendor_ramdisk_size) { 112 data->vendor_ramdisk_ptr = end; 113 data->vendor_ramdisk_size = hdr->vendor_ramdisk_size; 114 data->ramdisk_size += hdr->vendor_ramdisk_size; 115 end += ALIGN(hdr->vendor_ramdisk_size, hdr->page_size); 116 } 117 118 data->dtb_ptr = end; 119 data->dtb_size = hdr->dtb_size; 120 121 end += ALIGN(hdr->dtb_size, hdr->page_size); 122 end += ALIGN(hdr->vendor_ramdisk_table_size, hdr->page_size); 123 data->bootconfig_addr = end; 124 if (hdr->bootconfig_size) { 125 data->bootconfig_size += add_trailer(data->bootconfig_addr, 126 data->bootconfig_size); 127 data->ramdisk_size += data->bootconfig_size; 128 } 129 end += ALIGN(data->bootconfig_size, hdr->page_size); 130 data->vendor_boot_img_total_size = end - (ulong)hdr; 131} 132 133static void android_boot_image_v0_v1_v2_parse_hdr(const struct andr_boot_img_hdr_v0 *hdr, 134 struct andr_image_data *data) 135{ 136 ulong end; 137 138 data->image_name = hdr->name; 139 data->kcmdline = hdr->cmdline; 140 data->kernel_addr = hdr->kernel_addr; 141 data->ramdisk_addr = hdr->ramdisk_addr; 142 data->header_version = hdr->header_version; 143 data->dtb_load_addr = hdr->dtb_addr; 144 145 end = (ulong)hdr; 146 147 /* 148 * The header takes a full page, the remaining components are aligned 149 * on page boundary 150 */ 151 152 end += hdr->page_size; 153 154 data->kernel_ptr = end; 155 data->kernel_size = hdr->kernel_size; 156 end += ALIGN(hdr->kernel_size, hdr->page_size); 157 158 data->ramdisk_ptr = end; 159 data->ramdisk_size = hdr->ramdisk_size; 160 end += ALIGN(hdr->ramdisk_size, hdr->page_size); 161 162 data->second_ptr = end; 163 data->second_size = hdr->second_size; 164 end += ALIGN(hdr->second_size, hdr->page_size); 165 166 if (hdr->header_version >= 1) { 167 data->recovery_dtbo_ptr = end; 168 data->recovery_dtbo_size = hdr->recovery_dtbo_size; 169 end += ALIGN(hdr->recovery_dtbo_size, hdr->page_size); 170 } 171 172 if (hdr->header_version >= 2) { 173 data->dtb_ptr = end; 174 data->dtb_size = hdr->dtb_size; 175 end += ALIGN(hdr->dtb_size, hdr->page_size); 176 } 177 178 data->boot_img_total_size = end - (ulong)hdr; 179} 180 181bool android_image_get_bootimg_size(const void *hdr, u32 *boot_img_size) 182{ 183 struct andr_image_data data; 184 185 if (!hdr || !boot_img_size) { 186 printf("hdr or boot_img_size can't be NULL\n"); 187 return false; 188 } 189 190 if (!is_android_boot_image_header(hdr)) { 191 printf("Incorrect boot image header\n"); 192 return false; 193 } 194 195 if (((struct andr_boot_img_hdr_v0 *)hdr)->header_version <= 2) 196 android_boot_image_v0_v1_v2_parse_hdr(hdr, &data); 197 else 198 android_boot_image_v3_v4_parse_hdr(hdr, &data); 199 200 *boot_img_size = data.boot_img_total_size; 201 202 return true; 203} 204 205bool android_image_get_vendor_bootimg_size(const void *hdr, u32 *vendor_boot_img_size) 206{ 207 struct andr_image_data data; 208 209 if (!hdr || !vendor_boot_img_size) { 210 printf("hdr or vendor_boot_img_size can't be NULL\n"); 211 return false; 212 } 213 214 if (!is_android_vendor_boot_image_header(hdr)) { 215 printf("Incorrect vendor boot image header\n"); 216 return false; 217 } 218 219 android_vendor_boot_image_v3_v4_parse_hdr(hdr, &data); 220 221 *vendor_boot_img_size = data.vendor_boot_img_total_size; 222 223 return true; 224} 225 226bool android_image_get_data(const void *boot_hdr, const void *vendor_boot_hdr, 227 struct andr_image_data *data) 228{ 229 if (!boot_hdr || !data) { 230 printf("boot_hdr or data params can't be NULL\n"); 231 return false; 232 } 233 234 if (!is_android_boot_image_header(boot_hdr)) { 235 printf("Incorrect boot image header\n"); 236 return false; 237 } 238 239 if (((struct andr_boot_img_hdr_v0 *)boot_hdr)->header_version > 2) { 240 if (!vendor_boot_hdr) { 241 printf("For boot header v3+ vendor boot image has to be provided\n"); 242 return false; 243 } 244 if (!is_android_vendor_boot_image_header(vendor_boot_hdr)) { 245 printf("Incorrect vendor boot image header\n"); 246 return false; 247 } 248 android_boot_image_v3_v4_parse_hdr(boot_hdr, data); 249 android_vendor_boot_image_v3_v4_parse_hdr(vendor_boot_hdr, data); 250 } else { 251 android_boot_image_v0_v1_v2_parse_hdr(boot_hdr, data); 252 } 253 254 return true; 255} 256 257static ulong android_image_get_kernel_addr(struct andr_image_data *img_data, 258 ulong comp) 259{ 260 /* 261 * All the Android tools that generate a boot.img use this 262 * address as the default. 263 * 264 * Even though it doesn't really make a lot of sense, and it 265 * might be valid on some platforms, we treat that adress as 266 * the default value for this field, and try to execute the 267 * kernel in place in such a case. 268 * 269 * Otherwise, we will return the actual value set by the user. 270 */ 271 if (img_data->kernel_addr == ANDROID_IMAGE_DEFAULT_KERNEL_ADDR) { 272 if (comp == IH_COMP_NONE) 273 return img_data->kernel_ptr; 274 return env_get_ulong("kernel_addr_r", 16, 0); 275 } 276 277 /* 278 * abootimg creates images where all load addresses are 0 279 * and we need to fix them. 280 */ 281 if (img_data->kernel_addr == 0 && img_data->ramdisk_addr == 0) 282 return env_get_ulong("kernel_addr_r", 16, 0); 283 284 return img_data->kernel_addr; 285} 286 287/** 288 * android_image_get_kernel() - processes kernel part of Android boot images 289 * @hdr: Pointer to boot image header, which is at the start 290 * of the image. 291 * @vendor_boot_img: Pointer to vendor boot image header, which is at the 292 * start of the image. 293 * @verify: Checksum verification flag. Currently unimplemented. 294 * @os_data: Pointer to a ulong variable, will hold os data start 295 * address. 296 * @os_len: Pointer to a ulong variable, will hold os data length. 297 * 298 * This function returns the os image's start address and length. Also, 299 * it appends the kernel command line to the bootargs env variable. 300 * 301 * Return: Zero, os start address and length on success, 302 * otherwise on failure. 303 */ 304int android_image_get_kernel(const void *hdr, 305 const void *vendor_boot_img, int verify, 306 ulong *os_data, ulong *os_len) 307{ 308 struct andr_image_data img_data = {0}; 309 ulong kernel_addr; 310 const struct legacy_img_hdr *ihdr; 311 ulong comp; 312 313 if (!android_image_get_data(hdr, vendor_boot_img, &img_data)) 314 return -EINVAL; 315 316 comp = android_image_get_kcomp(hdr, vendor_boot_img); 317 318 kernel_addr = android_image_get_kernel_addr(&img_data, comp); 319 ihdr = (const struct legacy_img_hdr *)img_data.kernel_ptr; 320 321 /* 322 * Not all Android tools use the id field for signing the image with 323 * sha1 (or anything) so we don't check it. It is not obvious that the 324 * string is null terminated so we take care of this. 325 */ 326 strlcpy(andr_tmp_str, img_data.image_name, ANDR_BOOT_NAME_SIZE); 327 andr_tmp_str[ANDR_BOOT_NAME_SIZE] = '\0'; 328 if (strlen(andr_tmp_str)) 329 printf("Android's image name: %s\n", andr_tmp_str); 330 331 printf("Kernel load addr 0x%08lx size %u KiB\n", 332 kernel_addr, DIV_ROUND_UP(img_data.kernel_size, 1024)); 333 334 int len = 0; 335 char *bootargs = env_get("bootargs"); 336 337 if (bootargs) 338 len += strlen(bootargs); 339 340 if (img_data.kcmdline && *img_data.kcmdline) { 341 printf("Kernel command line: %s\n", img_data.kcmdline); 342 len += strlen(img_data.kcmdline) + (len ? 1 : 0); /* +1 for extra space */ 343 } 344 345 if (img_data.kcmdline_extra && *img_data.kcmdline_extra) { 346 printf("Kernel extra command line: %s\n", img_data.kcmdline_extra); 347 len += strlen(img_data.kcmdline_extra) + (len ? 1 : 0); /* +1 for extra space */ 348 } 349 350 char *newbootargs = malloc(len + 1); /* +1 for the '\0' */ 351 if (!newbootargs) { 352 puts("Error: malloc in android_image_get_kernel failed!\n"); 353 return -ENOMEM; 354 } 355 *newbootargs = '\0'; /* set to Null in case no components below are present */ 356 357 if (bootargs) 358 strcpy(newbootargs, bootargs); 359 360 if (img_data.kcmdline && *img_data.kcmdline) { 361 if (*newbootargs) /* If there is something in newbootargs, a space is needed */ 362 strcat(newbootargs, " "); 363 strcat(newbootargs, img_data.kcmdline); 364 } 365 366 if (img_data.kcmdline_extra && *img_data.kcmdline_extra) { 367 if (*newbootargs) /* If there is something in newbootargs, a space is needed */ 368 strcat(newbootargs, " "); 369 strcat(newbootargs, img_data.kcmdline_extra); 370 } 371 372 env_set("bootargs", newbootargs); 373 free(newbootargs); 374 375 if (os_data) { 376 if (image_get_magic(ihdr) == IH_MAGIC) { 377 *os_data = image_get_data(ihdr); 378 } else { 379 *os_data = img_data.kernel_ptr; 380 } 381 } 382 if (os_len) { 383 if (image_get_magic(ihdr) == IH_MAGIC) 384 *os_len = image_get_data_size(ihdr); 385 else 386 *os_len = img_data.kernel_size; 387 } 388 return 0; 389} 390 391bool is_android_vendor_boot_image_header(const void *vendor_boot_img) 392{ 393 return !memcmp(VENDOR_BOOT_MAGIC, vendor_boot_img, ANDR_VENDOR_BOOT_MAGIC_SIZE); 394} 395 396bool is_android_boot_image_header(const void *hdr) 397{ 398 return !memcmp(ANDR_BOOT_MAGIC, hdr, ANDR_BOOT_MAGIC_SIZE); 399} 400 401ulong android_image_get_end(const struct andr_boot_img_hdr_v0 *hdr, 402 const void *vendor_boot_img) 403{ 404 struct andr_image_data img_data; 405 406 if (!android_image_get_data(hdr, vendor_boot_img, &img_data)) 407 return -EINVAL; 408 409 if (img_data.header_version > 2) 410 return 0; 411 412 return img_data.boot_img_total_size; 413} 414 415ulong android_image_get_kload(const void *hdr, 416 const void *vendor_boot_img) 417{ 418 struct andr_image_data img_data; 419 ulong comp; 420 421 if (!android_image_get_data(hdr, vendor_boot_img, &img_data)) 422 return -EINVAL; 423 424 comp = android_image_get_kcomp(hdr, vendor_boot_img); 425 426 return android_image_get_kernel_addr(&img_data, comp); 427} 428 429ulong android_image_get_kcomp(const void *hdr, 430 const void *vendor_boot_img) 431{ 432 struct andr_image_data img_data; 433 const void *p; 434 435 if (!android_image_get_data(hdr, vendor_boot_img, &img_data)) 436 return -EINVAL; 437 438 p = (const void *)img_data.kernel_ptr; 439 if (image_get_magic((struct legacy_img_hdr *)p) == IH_MAGIC) 440 return image_get_comp((struct legacy_img_hdr *)p); 441 else if (get_unaligned_le32(p) == LZ4F_MAGIC) 442 return IH_COMP_LZ4; 443 else 444 return image_decomp_type(p, sizeof(u32)); 445} 446 447int android_image_get_ramdisk(const void *hdr, const void *vendor_boot_img, 448 ulong *rd_data, ulong *rd_len) 449{ 450 struct andr_image_data img_data = {0}; 451 ulong ramdisk_ptr; 452 453 if (!android_image_get_data(hdr, vendor_boot_img, &img_data)) 454 return -EINVAL; 455 456 if (!img_data.ramdisk_size) 457 return -ENOENT; 458 /* 459 * Android tools can generate a boot.img with default load address 460 * or 0, even though it doesn't really make a lot of sense, and it 461 * might be valid on some platforms, we treat that address as 462 * the default value for this field, and try to pass ramdisk 463 * in place if possible. 464 */ 465 if (img_data.header_version > 2) { 466 /* Ramdisk can't be used in-place, copy it to ramdisk_addr_r */ 467 if (img_data.ramdisk_addr == ANDROID_IMAGE_DEFAULT_RAMDISK_ADDR) { 468 ramdisk_ptr = env_get_ulong("ramdisk_addr_r", 16, 0); 469 if (!ramdisk_ptr) { 470 printf("Invalid ramdisk_addr_r to copy ramdisk into\n"); 471 return -EINVAL; 472 } 473 } else { 474 ramdisk_ptr = img_data.ramdisk_addr; 475 } 476 *rd_data = ramdisk_ptr; 477 memcpy((void *)(ramdisk_ptr), (void *)img_data.vendor_ramdisk_ptr, 478 img_data.vendor_ramdisk_size); 479 ramdisk_ptr += img_data.vendor_ramdisk_size; 480 memcpy((void *)(ramdisk_ptr), (void *)img_data.ramdisk_ptr, 481 img_data.boot_ramdisk_size); 482 ramdisk_ptr += img_data.boot_ramdisk_size; 483 if (img_data.bootconfig_size) { 484 memcpy((void *) 485 (ramdisk_ptr), (void *)img_data.bootconfig_addr, 486 img_data.bootconfig_size); 487 } 488 } else { 489 /* Ramdisk can be used in-place, use current ptr */ 490 if (img_data.ramdisk_addr == 0 || 491 img_data.ramdisk_addr == ANDROID_IMAGE_DEFAULT_RAMDISK_ADDR) { 492 *rd_data = img_data.ramdisk_ptr; 493 } else { 494 ramdisk_ptr = img_data.ramdisk_addr; 495 *rd_data = ramdisk_ptr; 496 memcpy((void *)(ramdisk_ptr), (void *)img_data.ramdisk_ptr, 497 img_data.ramdisk_size); 498 } 499 } 500 501 printf("RAM disk load addr 0x%08lx size %u KiB\n", 502 *rd_data, DIV_ROUND_UP(img_data.ramdisk_size, 1024)); 503 504 *rd_len = img_data.ramdisk_size; 505 return 0; 506} 507 508int android_image_get_second(const void *hdr, ulong *second_data, ulong *second_len) 509{ 510 struct andr_image_data img_data; 511 512 if (!android_image_get_data(hdr, NULL, &img_data)) 513 return -EINVAL; 514 515 if (img_data.header_version > 2) { 516 printf("Second stage bootloader is only supported for boot image version <= 2\n"); 517 return -EOPNOTSUPP; 518 } 519 520 if (!img_data.second_size) { 521 *second_data = *second_len = 0; 522 return -1; 523 } 524 525 *second_data = img_data.second_ptr; 526 527 printf("second address is 0x%lx\n",*second_data); 528 529 *second_len = img_data.second_size; 530 return 0; 531} 532 533/** 534 * android_image_get_dtbo() - Get address and size of recovery DTBO image. 535 * @hdr_addr: Boot image header address 536 * @addr: If not NULL, will contain address of recovery DTBO image 537 * @size: If not NULL, will contain size of recovery DTBO image 538 * 539 * Get the address and size of DTBO image in "Recovery DTBO" area of Android 540 * Boot Image in RAM. The format of this image is Android DTBO (see 541 * corresponding "DTB/DTBO Partitions" AOSP documentation for details). Once 542 * the address is obtained from this function, one can use 'adtimg' U-Boot 543 * command or android_dt_*() functions to extract desired DTBO blob. 544 * 545 * This DTBO (included in boot image) is only needed for non-A/B devices, and it 546 * only can be found in recovery image. On A/B devices we can always rely on 547 * "dtbo" partition. See "Including DTBO in Recovery for Non-A/B Devices" in 548 * AOSP documentation for details. 549 * 550 * Return: true on success or false on error. 551 */ 552bool android_image_get_dtbo(ulong hdr_addr, ulong *addr, u32 *size) 553{ 554 const struct andr_boot_img_hdr_v0 *hdr; 555 ulong dtbo_img_addr; 556 bool ret = true; 557 558 hdr = map_sysmem(hdr_addr, sizeof(*hdr)); 559 if (!is_android_boot_image_header(hdr)) { 560 printf("Error: Boot Image header is incorrect\n"); 561 ret = false; 562 goto exit; 563 } 564 565 if (hdr->header_version != 1 && hdr->header_version != 2) { 566 printf("Error: header version must be >= 1 and <= 2 to get dtbo\n"); 567 ret = false; 568 goto exit; 569 } 570 571 if (hdr->recovery_dtbo_size == 0) { 572 printf("Error: recovery_dtbo_size is 0\n"); 573 ret = false; 574 goto exit; 575 } 576 577 /* Calculate the address of DTB area in boot image */ 578 dtbo_img_addr = hdr_addr; 579 dtbo_img_addr += hdr->page_size; 580 dtbo_img_addr += ALIGN(hdr->kernel_size, hdr->page_size); 581 dtbo_img_addr += ALIGN(hdr->ramdisk_size, hdr->page_size); 582 dtbo_img_addr += ALIGN(hdr->second_size, hdr->page_size); 583 584 if (addr) 585 *addr = dtbo_img_addr; 586 if (size) 587 *size = hdr->recovery_dtbo_size; 588 589exit: 590 unmap_sysmem(hdr); 591 return ret; 592} 593 594/** 595 * android_image_get_dtb_img_addr() - Get the address of DTB area in boot image. 596 * @hdr_addr: Boot image header address 597 * @vhdr_addr: Vendor Boot image header address 598 * @addr: Will contain the address of DTB area in boot image 599 * 600 * Return: true on success or false on fail. 601 */ 602static bool android_image_get_dtb_img_addr(ulong hdr_addr, ulong vhdr_addr, ulong *addr) 603{ 604 const struct andr_boot_img_hdr_v0 *hdr; 605 const struct andr_vnd_boot_img_hdr *v_hdr; 606 ulong dtb_img_addr; 607 bool ret = true; 608 609 hdr = map_sysmem(hdr_addr, sizeof(*hdr)); 610 if (!is_android_boot_image_header(hdr)) { 611 printf("Error: Boot Image header is incorrect\n"); 612 ret = false; 613 goto exit; 614 } 615 616 if (hdr->header_version < 2) { 617 printf("Error: header_version must be >= 2 to get dtb\n"); 618 ret = false; 619 goto exit; 620 } 621 622 if (hdr->header_version == 2) { 623 if (!hdr->dtb_size) { 624 printf("Error: dtb_size is 0\n"); 625 ret = false; 626 goto exit; 627 } 628 /* Calculate the address of DTB area in boot image */ 629 dtb_img_addr = hdr_addr; 630 dtb_img_addr += hdr->page_size; 631 dtb_img_addr += ALIGN(hdr->kernel_size, hdr->page_size); 632 dtb_img_addr += ALIGN(hdr->ramdisk_size, hdr->page_size); 633 dtb_img_addr += ALIGN(hdr->second_size, hdr->page_size); 634 dtb_img_addr += ALIGN(hdr->recovery_dtbo_size, hdr->page_size); 635 636 *addr = dtb_img_addr; 637 } 638 639 if (hdr->header_version > 2) { 640 v_hdr = map_sysmem(vhdr_addr, sizeof(*v_hdr)); 641 if (!v_hdr->dtb_size) { 642 printf("Error: dtb_size is 0\n"); 643 ret = false; 644 unmap_sysmem(v_hdr); 645 goto exit; 646 } 647 /* Calculate the address of DTB area in boot image */ 648 dtb_img_addr = vhdr_addr; 649 dtb_img_addr += v_hdr->page_size; 650 if (v_hdr->vendor_ramdisk_size) 651 dtb_img_addr += ALIGN(v_hdr->vendor_ramdisk_size, v_hdr->page_size); 652 *addr = dtb_img_addr; 653 unmap_sysmem(v_hdr); 654 goto exit; 655 } 656exit: 657 unmap_sysmem(hdr); 658 return ret; 659} 660 661/** 662 * android_image_get_dtb_by_index() - Get address and size of blob in DTB area. 663 * @hdr_addr: Boot image header address 664 * @vendor_boot_img: Pointer to vendor boot image header, which is at the start of the image. 665 * @index: Index of desired DTB in DTB area (starting from 0) 666 * @addr: If not NULL, will contain address to specified DTB 667 * @size: If not NULL, will contain size of specified DTB 668 * 669 * Get the address and size of DTB blob by its index in DTB area of Android 670 * Boot Image in RAM. 671 * 672 * Return: true on success or false on error. 673 */ 674bool android_image_get_dtb_by_index(ulong hdr_addr, ulong vendor_boot_img, 675 u32 index, ulong *addr, u32 *size) 676{ 677 struct andr_image_data img_data; 678 const struct andr_boot_img_hdr_v0 *hdr; 679 const struct andr_vnd_boot_img_hdr *vhdr; 680 681 hdr = map_sysmem(hdr_addr, sizeof(*hdr)); 682 if (vendor_boot_img != -1) 683 vhdr = map_sysmem(vendor_boot_img, sizeof(*vhdr)); 684 if (!android_image_get_data(hdr, vhdr, &img_data)) { 685 if (vendor_boot_img != -1) 686 unmap_sysmem(vhdr); 687 unmap_sysmem(hdr); 688 return false; 689 } 690 if (vendor_boot_img != -1) 691 unmap_sysmem(vhdr); 692 unmap_sysmem(hdr); 693 694 ulong dtb_img_addr; /* address of DTB part in boot image */ 695 u32 dtb_img_size; /* size of DTB payload in boot image */ 696 ulong dtb_addr; /* address of DTB blob with specified index */ 697 u32 i; /* index iterator */ 698 699 if (!android_image_get_dtb_img_addr(hdr_addr, vendor_boot_img, 700 &dtb_img_addr)) 701 return false; 702 703 /* Check if DTB area of boot image is in DTBO format */ 704 if (android_dt_check_header(dtb_img_addr)) { 705 return android_dt_get_fdt_by_index(dtb_img_addr, index, addr, 706 size); 707 } 708 709 /* Find out the address of DTB with specified index in concat blobs */ 710 dtb_img_size = img_data.dtb_size; 711 i = 0; 712 dtb_addr = dtb_img_addr; 713 while (dtb_addr < dtb_img_addr + dtb_img_size) { 714 const struct fdt_header *fdt; 715 u32 dtb_size; 716 717 fdt = map_sysmem(dtb_addr, sizeof(*fdt)); 718 if (fdt_check_header(fdt) != 0) { 719 unmap_sysmem(fdt); 720 printf("Error: Invalid FDT header for index %u\n", i); 721 return false; 722 } 723 724 dtb_size = fdt_totalsize(fdt); 725 unmap_sysmem(fdt); 726 727 if (i == index) { 728 if (size) 729 *size = dtb_size; 730 if (addr) 731 *addr = dtb_addr; 732 return true; 733 } 734 735 dtb_addr += dtb_size; 736 ++i; 737 } 738 739 printf("Error: Index is out of bounds (%u/%u)\n", index, i); 740 return false; 741} 742 743#if !defined(CONFIG_XPL_BUILD) 744/** 745 * android_print_contents - prints out the contents of the Android format image 746 * @hdr: pointer to the Android format image header 747 * 748 * android_print_contents() formats a multi line Android image contents 749 * description. 750 * The routine prints out Android image properties 751 * 752 * returns: 753 * no returned results 754 */ 755void android_print_contents(const struct andr_boot_img_hdr_v0 *hdr) 756{ 757 if (hdr->header_version >= 3) { 758 printf("Content print is not supported for boot image header version > 2"); 759 return; 760 } 761 const char * const p = IMAGE_INDENT_STRING; 762 /* os_version = ver << 11 | lvl */ 763 u32 os_ver = hdr->os_version >> 11; 764 u32 os_lvl = hdr->os_version & ((1U << 11) - 1); 765 766 printf("%skernel size: %x\n", p, hdr->kernel_size); 767 printf("%skernel address: %x\n", p, hdr->kernel_addr); 768 printf("%sramdisk size: %x\n", p, hdr->ramdisk_size); 769 printf("%sramdisk address: %x\n", p, hdr->ramdisk_addr); 770 printf("%ssecond size: %x\n", p, hdr->second_size); 771 printf("%ssecond address: %x\n", p, hdr->second_addr); 772 printf("%stags address: %x\n", p, hdr->tags_addr); 773 printf("%spage size: %x\n", p, hdr->page_size); 774 /* ver = A << 14 | B << 7 | C (7 bits for each of A, B, C) 775 * lvl = ((Y - 2000) & 127) << 4 | M (7 bits for Y, 4 bits for M) */ 776 printf("%sos_version: %x (ver: %u.%u.%u, level: %u.%u)\n", 777 p, hdr->os_version, 778 (os_ver >> 7) & 0x7F, (os_ver >> 14) & 0x7F, os_ver & 0x7F, 779 (os_lvl >> 4) + 2000, os_lvl & 0x0F); 780 printf("%sname: %s\n", p, hdr->name); 781 printf("%scmdline: %s\n", p, hdr->cmdline); 782 printf("%sheader_version: %d\n", p, hdr->header_version); 783 784 if (hdr->header_version >= 1) { 785 printf("%srecovery dtbo size: %x\n", p, 786 hdr->recovery_dtbo_size); 787 printf("%srecovery dtbo offset: %llx\n", p, 788 hdr->recovery_dtbo_offset); 789 printf("%sheader size: %x\n", p, 790 hdr->header_size); 791 } 792 793 if (hdr->header_version == 2) { 794 printf("%sdtb size: %x\n", p, hdr->dtb_size); 795 printf("%sdtb addr: %llx\n", p, hdr->dtb_addr); 796 } 797} 798 799/** 800 * android_image_print_dtb_info - Print info for one DTB blob in DTB area. 801 * @fdt: DTB header 802 * @index: Number of DTB blob in DTB area. 803 * 804 * Return: true on success or false on error. 805 */ 806static bool android_image_print_dtb_info(const struct fdt_header *fdt, 807 u32 index) 808{ 809 int root_node_off; 810 u32 fdt_size; 811 const char *model; 812 const char *compatible; 813 814 root_node_off = fdt_path_offset(fdt, "/"); 815 if (root_node_off < 0) { 816 printf("Error: Root node not found\n"); 817 return false; 818 } 819 820 fdt_size = fdt_totalsize(fdt); 821 compatible = fdt_getprop(fdt, root_node_off, "compatible", 822 NULL); 823 model = fdt_getprop(fdt, root_node_off, "model", NULL); 824 825 printf(" - DTB #%u:\n", index); 826 printf(" (DTB)size = %d\n", fdt_size); 827 printf(" (DTB)model = %s\n", model ? model : "(unknown)"); 828 printf(" (DTB)compatible = %s\n", 829 compatible ? compatible : "(unknown)"); 830 831 return true; 832} 833 834/** 835 * android_image_print_dtb_contents() - Print info for DTB blobs in DTB area. 836 * @hdr_addr: Boot image header address 837 * 838 * DTB payload in Android Boot Image v2+ can be in one of following formats: 839 * 1. Concatenated DTB blobs 840 * 2. Android DTBO format (see CONFIG_CMD_ADTIMG for details) 841 * 842 * This function does next: 843 * 1. Prints out the format used in DTB area 844 * 2. Iterates over all DTB blobs in DTB area and prints out the info for 845 * each blob. 846 * 847 * Return: true on success or false on error. 848 */ 849bool android_image_print_dtb_contents(ulong hdr_addr) 850{ 851 const struct andr_boot_img_hdr_v0 *hdr; 852 bool res; 853 ulong dtb_img_addr; /* address of DTB part in boot image */ 854 u32 dtb_img_size; /* size of DTB payload in boot image */ 855 ulong dtb_addr; /* address of DTB blob with specified index */ 856 u32 i; /* index iterator */ 857 858 res = android_image_get_dtb_img_addr(hdr_addr, 0, &dtb_img_addr); 859 if (!res) 860 return false; 861 862 /* Check if DTB area of boot image is in DTBO format */ 863 if (android_dt_check_header(dtb_img_addr)) { 864 printf("## DTB area contents (DTBO format):\n"); 865 android_dt_print_contents(dtb_img_addr); 866 return true; 867 } 868 869 printf("## DTB area contents (concat format):\n"); 870 871 /* Iterate over concatenated DTB blobs */ 872 hdr = map_sysmem(hdr_addr, sizeof(*hdr)); 873 dtb_img_size = hdr->dtb_size; 874 unmap_sysmem(hdr); 875 i = 0; 876 dtb_addr = dtb_img_addr; 877 while (dtb_addr < dtb_img_addr + dtb_img_size) { 878 const struct fdt_header *fdt; 879 u32 dtb_size; 880 881 fdt = map_sysmem(dtb_addr, sizeof(*fdt)); 882 if (fdt_check_header(fdt) != 0) { 883 unmap_sysmem(fdt); 884 printf("Error: Invalid FDT header for index %u\n", i); 885 return false; 886 } 887 888 res = android_image_print_dtb_info(fdt, i); 889 if (!res) { 890 unmap_sysmem(fdt); 891 return false; 892 } 893 894 dtb_size = fdt_totalsize(fdt); 895 unmap_sysmem(fdt); 896 dtb_addr += dtb_size; 897 ++i; 898 } 899 900 return true; 901} 902#endif