1 /* 2 * (C) Copyright 2017 Rockchip Electronics Co., Ltd 3 * 4 * SPDX-License-Identifier: GPL-2.0+ 5 */ 6 #include <common.h> 7 #include <adc.h> 8 #include <asm/io.h> 9 #include <fs.h> 10 #include <malloc.h> 11 #include <sysmem.h> 12 #include <linux/list.h> 13 #include <asm/arch/resource_img.h> 14 #include <boot_rkimg.h> 15 #include <dm/ofnode.h> 16 #ifdef CONFIG_ANDROID_AB 17 #include <android_avb/libavb_ab.h> 18 #include <android_avb/rk_avb_ops_user.h> 19 #endif 20 #ifdef CONFIG_ANDROID_BOOT_IMAGE 21 #include <android_bootloader.h> 22 #include <android_image.h> 23 #endif 24 25 DECLARE_GLOBAL_DATA_PTR; 26 27 #define PART_RESOURCE "resource" 28 #define RESOURCE_MAGIC "RSCE" 29 #define RESOURCE_MAGIC_SIZE 4 30 #define RESOURCE_VERSION 0 31 #define CONTENT_VERSION 0 32 #define ENTRY_TAG "ENTR" 33 #define ENTRY_TAG_SIZE 4 34 #define MAX_FILE_NAME_LEN 256 35 36 /* 37 * resource image structure 38 * ---------------------------------------------- 39 * | | 40 * | header (1 block) | 41 * | | 42 * ---------------------------------------------| 43 * | | | 44 * | entry0 (1 block) | | 45 * | | | 46 * ------------------------ | 47 * | | | 48 * | entry1 (1 block) | contents (n blocks) | 49 * | | | 50 * ------------------------ | 51 * | ...... | | 52 * ------------------------ | 53 * | | | 54 * | entryn (1 block) | | 55 * | | | 56 * ---------------------------------------------- 57 * | | 58 * | file0 (x blocks) | 59 * | | 60 * ---------------------------------------------- 61 * | | 62 * | file1 (y blocks) | 63 * | | 64 * ---------------------------------------------- 65 * | ...... | 66 * |--------------------------------------------- 67 * | | 68 * | filen (z blocks) | 69 * | | 70 * ---------------------------------------------- 71 */ 72 73 /** 74 * struct resource_image_header 75 * 76 * @magic: should be "RSCE" 77 * @version: resource image version, current is 0 78 * @c_version: content version, current is 0 79 * @blks: the size of the header ( 1 block = 512 bytes) 80 * @c_offset: contents offset(by block) in the image 81 * @e_blks: the size(by block) of the entry in the contents 82 * @e_num: numbers of the entrys. 83 */ 84 85 struct resource_img_hdr { 86 char magic[4]; 87 uint16_t version; 88 uint16_t c_version; 89 uint8_t blks; 90 uint8_t c_offset; 91 uint8_t e_blks; 92 uint32_t e_nums; 93 }; 94 95 struct resource_entry { 96 char tag[4]; 97 char name[MAX_FILE_NAME_LEN]; 98 uint32_t f_offset; 99 uint32_t f_size; 100 }; 101 102 struct resource_file { 103 char name[MAX_FILE_NAME_LEN]; 104 uint32_t f_offset; 105 uint32_t f_size; 106 struct list_head link; 107 uint32_t rsce_base; /* Base addr of resource */ 108 }; 109 110 static LIST_HEAD(entrys_head); 111 112 static int resource_image_check_header(const struct resource_img_hdr *hdr) 113 { 114 int ret; 115 116 ret = memcmp(RESOURCE_MAGIC, hdr->magic, RESOURCE_MAGIC_SIZE); 117 if (ret) { 118 printf("bad resource image magic: %s\n", 119 hdr->magic ? hdr->magic : "none"); 120 ret = -EINVAL; 121 } 122 debug("resource image header:\n"); 123 debug("magic:%s\n", hdr->magic); 124 debug("version:%d\n", hdr->version); 125 debug("c_version:%d\n", hdr->c_version); 126 debug("blks:%d\n", hdr->blks); 127 debug("c_offset:%d\n", hdr->c_offset); 128 debug("e_blks:%d\n", hdr->e_blks); 129 debug("e_num:%d\n", hdr->e_nums); 130 131 return ret; 132 } 133 134 static int add_file_to_list(struct resource_entry *entry, int rsce_base) 135 { 136 struct resource_file *file; 137 138 if (memcmp(entry->tag, ENTRY_TAG, ENTRY_TAG_SIZE)) { 139 printf("invalid entry tag\n"); 140 return -ENOENT; 141 } 142 file = malloc(sizeof(*file)); 143 if (!file) { 144 printf("out of memory\n"); 145 return -ENOMEM; 146 } 147 strcpy(file->name, entry->name); 148 file->rsce_base = rsce_base; 149 file->f_offset = entry->f_offset; 150 file->f_size = entry->f_size; 151 list_add_tail(&file->link, &entrys_head); 152 debug("entry:%p %s offset:%d size:%d\n", 153 entry, file->name, file->f_offset, file->f_size); 154 155 return 0; 156 } 157 158 static int init_resource_list(struct resource_img_hdr *hdr) 159 { 160 struct resource_entry *entry; 161 void *content; 162 int size; 163 int ret; 164 int e_num; 165 int offset = 0; 166 int resource_found = 0; 167 struct blk_desc *dev_desc; 168 disk_partition_t part_info; 169 char *boot_partname = PART_BOOT; 170 171 /* 172 * Primary detect AOSP format image, try to get resource image from 173 * boot/recovery partition. If not, it's an RK format image and try 174 * to get from resource partition. 175 */ 176 #ifdef CONFIG_ANDROID_BOOT_IMAGE 177 struct andr_img_hdr *andr_hdr; 178 #endif 179 180 if (hdr) { 181 if (resource_image_check_header(hdr)) 182 return -EEXIST; 183 184 content = (void *)((char *)hdr 185 + (hdr->c_offset) * RK_BLK_SIZE); 186 for (e_num = 0; e_num < hdr->e_nums; e_num++) { 187 size = e_num * hdr->e_blks * RK_BLK_SIZE; 188 entry = (struct resource_entry *)(content + size); 189 add_file_to_list(entry, offset); 190 } 191 return 0; 192 } 193 194 dev_desc = rockchip_get_bootdev(); 195 if (!dev_desc) { 196 printf("%s: dev_desc is NULL!\n", __func__); 197 return -ENODEV; 198 } 199 hdr = memalign(ARCH_DMA_MINALIGN, RK_BLK_SIZE); 200 if (!hdr) { 201 printf("%s: out of memory!\n", __func__); 202 return -ENOMEM; 203 } 204 205 #ifdef CONFIG_ANDROID_BOOT_IMAGE 206 /* Get boot mode from misc */ 207 #ifndef CONFIG_ANDROID_AB 208 if (rockchip_get_boot_mode() == BOOT_MODE_RECOVERY) 209 boot_partname = PART_RECOVERY; 210 #endif 211 212 /* Read boot/recovery and chenc if this is an AOSP img */ 213 #ifdef CONFIG_ANDROID_AB 214 char slot_suffix[3] = {0}; 215 216 if (rk_avb_get_current_slot(slot_suffix)) { 217 ret = -ENODEV; 218 goto out; 219 } 220 221 boot_partname = android_str_append(boot_partname, slot_suffix); 222 if (!boot_partname) { 223 ret = -EINVAL; 224 goto out; 225 } 226 #endif 227 ret = part_get_info_by_name(dev_desc, boot_partname, &part_info); 228 if (ret < 0) { 229 printf("%s: failed to get %s part, ret=%d\n", 230 __func__, boot_partname, ret); 231 /* RKIMG can support part table without 'boot' */ 232 goto next; 233 } 234 235 /* 236 * Only read header and check magic, is a AOSP format image? 237 * If so, get resource image from second part. 238 */ 239 andr_hdr = (void *)hdr; 240 ret = blk_dread(dev_desc, part_info.start, 1, andr_hdr); 241 if (ret != 1) { 242 printf("%s: failed to read %s hdr, ret=%d\n", 243 __func__, part_info.name, ret); 244 ret = -EIO; 245 goto out; 246 } 247 ret = android_image_check_header(andr_hdr); 248 if (!ret) { 249 debug("%s: Load resource from %s second pos\n", 250 __func__, part_info.name); 251 /* Read resource from second offset */ 252 offset = part_info.start * RK_BLK_SIZE; 253 offset += andr_hdr->page_size; 254 offset += ALIGN(andr_hdr->kernel_size, andr_hdr->page_size); 255 offset += ALIGN(andr_hdr->ramdisk_size, andr_hdr->page_size); 256 offset = offset / RK_BLK_SIZE; 257 258 resource_found = 1; 259 } 260 next: 261 #endif 262 /* 263 * If not found resource image in AOSP format images(boot/recovery part), 264 * try to read RK format images(resource part). 265 */ 266 if (!resource_found) { 267 debug("%s: Load resource from resource part\n", __func__); 268 /* Read resource from Rockchip Resource partition */ 269 boot_partname = PART_RESOURCE; 270 ret = part_get_info_by_name(dev_desc, boot_partname, &part_info); 271 if (ret < 0) { 272 printf("%s: failed to get resource part, ret=%d\n", 273 __func__, ret); 274 goto out; 275 } 276 offset = part_info.start; 277 } 278 279 /* Only read header and check magic */ 280 ret = blk_dread(dev_desc, offset, 1, hdr); 281 if (ret != 1) { 282 printf("%s: failed to read resource hdr, ret=%d\n", 283 __func__, ret); 284 ret = -EIO; 285 goto out; 286 } 287 288 ret = resource_image_check_header(hdr); 289 if (ret < 0) { 290 ret = -EINVAL; 291 goto out; 292 } 293 294 content = memalign(ARCH_DMA_MINALIGN, 295 hdr->e_blks * hdr->e_nums * RK_BLK_SIZE); 296 if (!content) { 297 printf("%s: failed to alloc memory for content\n", __func__); 298 ret = -ENOMEM; 299 goto out; 300 } 301 302 /* Read all entries from resource image */ 303 ret = blk_dread(dev_desc, offset + hdr->c_offset, 304 hdr->e_blks * hdr->e_nums, content); 305 if (ret != (hdr->e_blks * hdr->e_nums)) { 306 printf("%s: failed to read resource entries, ret=%d\n", 307 __func__, ret); 308 ret = -EIO; 309 goto err; 310 } 311 312 for (e_num = 0; e_num < hdr->e_nums; e_num++) { 313 size = e_num * hdr->e_blks * RK_BLK_SIZE; 314 entry = (struct resource_entry *)(content + size); 315 add_file_to_list(entry, offset); 316 } 317 318 ret = 0; 319 printf("Load FDT from %s part\n", boot_partname); 320 err: 321 free(content); 322 out: 323 free(hdr); 324 325 return ret; 326 } 327 328 static struct resource_file *get_file_info(struct resource_img_hdr *hdr, 329 const char *name) 330 { 331 struct resource_file *file; 332 struct list_head *node; 333 334 if (list_empty(&entrys_head)) { 335 if (init_resource_list(hdr)) 336 return NULL; 337 } 338 339 list_for_each(node, &entrys_head) { 340 file = list_entry(node, struct resource_file, link); 341 if (!strcmp(file->name, name)) 342 return file; 343 } 344 345 return NULL; 346 } 347 348 int rockchip_get_resource_file_offset(void *resc_hdr, const char *name) 349 { 350 struct resource_file *file; 351 352 file = get_file_info(resc_hdr, name); 353 if (!file) 354 return -ENFILE; 355 356 return file->f_offset; 357 } 358 359 int rockchip_get_resource_file_size(void *resc_hdr, const char *name) 360 { 361 struct resource_file *file; 362 363 file = get_file_info(resc_hdr, name); 364 if (!file) 365 return -ENFILE; 366 367 return file->f_size; 368 } 369 370 /* 371 * read file from resource partition 372 * @buf: destination buf to store file data; 373 * @name: file name 374 * @offset: blocks offset in the file, 1 block = 512 bytes 375 * @len: the size(by bytes) of file to read. 376 */ 377 int rockchip_read_resource_file(void *buf, const char *name, 378 int offset, int len) 379 { 380 struct resource_file *file; 381 int ret = 0; 382 int blks; 383 struct blk_desc *dev_desc; 384 385 file = get_file_info(NULL, name); 386 if (!file) { 387 printf("Can't find file:%s\n", name); 388 return -ENOENT; 389 } 390 391 if (len <= 0 || len > file->f_size) 392 len = file->f_size; 393 blks = DIV_ROUND_UP(len, RK_BLK_SIZE); 394 dev_desc = rockchip_get_bootdev(); 395 if (!dev_desc) { 396 printf("%s: dev_desc is NULL!\n", __func__); 397 return -ENODEV; 398 } 399 ret = blk_dread(dev_desc, file->rsce_base + file->f_offset + offset, 400 blks, buf); 401 if (ret != blks) 402 ret = -EIO; 403 else 404 ret = len; 405 406 return ret; 407 } 408 409 #define is_digit(c) ((c) >= '0' && (c) <= '9') 410 #define is_abcd(c) ((c) >= 'a' && (c) <= 'd') 411 #define is_equal(c) ((c) == '=') 412 413 #define DTB_FILE "rk-kernel.dtb" 414 #define KEY_WORDS_ADC_CTRL "#_" 415 #define KEY_WORDS_ADC_CH "_ch" 416 #define KEY_WORDS_GPIO "#gpio" 417 #define GPIO_SWPORT_DDR 0x04 418 #define GPIO_EXT_PORT 0x50 419 #define MAX_ADC_CH_NR 10 420 #define MAX_GPIO_NR 10 421 422 #ifdef CONFIG_ADC 423 /* 424 * How to make it works ? 425 * 426 * 1. pack dtb into rockchip resource.img, require: 427 * (1) file name end with ".dtb"; 428 * (2) file name contains key words, like: ...#_[controller]_ch[channel]=[value]...dtb 429 * @controller: adc controller name in dts, eg. "saradc", ...; 430 * @channel: adc channel; 431 * @value: adc value; 432 * eg: ...#_saradc_ch1=223#_saradc_ch2=650....dtb 433 * 434 * 2. U-Boot dtsi about adc controller node: 435 * (1) enable "u-boot,dm-pre-reloc;"; 436 * (2) must set status "okay"; 437 */ 438 static int rockchip_read_dtb_by_adc(const char *file_name) 439 { 440 static int cached_v[MAX_ADC_CH_NR]; 441 int offset_ctrl = strlen(KEY_WORDS_ADC_CTRL); 442 int offset_ch = strlen(KEY_WORDS_ADC_CH); 443 int ret, channel, len = 0, found = 0, margin = 30; 444 uint32_t raw_adc; 445 unsigned long dtb_adc; 446 char *stradc, *strch, *p; 447 char adc_v_string[10]; 448 char dev_name[32]; 449 450 debug("%s: %s\n", __func__, file_name); 451 452 /* Invalid format ? */ 453 stradc = strstr(file_name, KEY_WORDS_ADC_CTRL); 454 while (stradc) { 455 debug(" - substr: %s\n", stradc); 456 457 /* Parse controller name */ 458 strch = strstr(stradc, KEY_WORDS_ADC_CH); 459 len = strch - (stradc + offset_ctrl); 460 strlcpy(dev_name, stradc + offset_ctrl, len + 1); 461 462 /* Parse adc channel */ 463 p = strch + offset_ch; 464 if (is_digit(*p) && is_equal(*(p + 1))) { 465 channel = *p - '0'; 466 } else { 467 debug(" - invalid format: %s\n", stradc); 468 return -EINVAL; 469 } 470 471 /* 472 * Read raw adc value 473 * 474 * It doesn't need to read adc value every loop, reading once 475 * is enough. We use cached_v[] to save what we have read, zero 476 * means not read before. 477 */ 478 if (cached_v[channel] == 0) { 479 ret = adc_channel_single_shot(dev_name, 480 channel, &raw_adc); 481 if (ret) { 482 debug(" - failed to read adc, ret=%d\n", ret); 483 return ret; 484 } 485 cached_v[channel] = raw_adc; 486 } 487 488 /* Parse dtb adc value */ 489 p = strch + offset_ch + 2; /* 2: channel and '=' */ 490 while (*p && is_digit(*p)) { 491 len++; 492 p++; 493 } 494 strlcpy(adc_v_string, strch + offset_ch + 2, len + 1); 495 dtb_adc = simple_strtoul(adc_v_string, NULL, 10); 496 497 if (abs(dtb_adc - cached_v[channel]) <= margin) { 498 found = 1; 499 stradc = strstr(p, KEY_WORDS_ADC_CTRL); 500 } else { 501 found = 0; 502 break; 503 } 504 505 debug(" - parse: controller=%s, channel=%d, dtb_adc=%ld, read=%d %s\n", 506 dev_name, channel, dtb_adc, cached_v[channel], found ? "(Y)" : ""); 507 } 508 509 return found ? 0 : -ENOENT; 510 } 511 #else 512 static int rockchip_read_dtb_by_adc(const char *file_name) 513 { 514 return -ENOENT; 515 } 516 #endif 517 518 static int gpio_parse_base_address(fdt_addr_t *gpio_base_addr) 519 { 520 static int initial; 521 ofnode parent, node; 522 const char *name; 523 int idx, nr = 0; 524 525 if (initial) 526 return 0; 527 528 parent = ofnode_path("/pinctrl"); 529 if (!ofnode_valid(parent)) { 530 debug(" - Can't find pinctrl node\n"); 531 return -EINVAL; 532 } 533 534 ofnode_for_each_subnode(node, parent) { 535 if (!ofnode_get_property(node, "gpio-controller", NULL)) { 536 debug(" - Can't find gpio-controller\n"); 537 continue; 538 } 539 540 name = ofnode_get_name(node); 541 if (!is_digit((char)*(name + 4))) { 542 debug(" - bad gpio node name: %s\n", name); 543 continue; 544 } 545 546 nr++; 547 idx = *(name + 4) - '0'; 548 gpio_base_addr[idx] = ofnode_get_addr(node); 549 debug(" - gpio%d: 0x%x\n", idx, (uint32_t)gpio_base_addr[idx]); 550 } 551 552 if (nr == 0) { 553 debug(" - parse gpio address failed\n"); 554 return -EINVAL; 555 } 556 557 initial = 1; 558 559 return 0; 560 } 561 562 /* 563 * How to make it works ? 564 * 565 * 1. pack dtb into rockchip resource.img, require: 566 * (1) file name end with ".dtb"; 567 * (2) file name contains key words, like: ...#gpio[pin]=[value]...dtb 568 * @pin: gpio name, eg. 0a2 means GPIO0A2; 569 * @value: gpio level, 0 or 1; 570 * eg: ...#gpio0a6=1#gpio1c2=0....dtb 571 * 572 * 2. U-Boot dtsi about gpio node: 573 * (1) enable "u-boot,dm-pre-reloc;" for all gpio node; 574 * (2) set all gpio status "disabled"(Because we just want their property); 575 */ 576 static int rockchip_read_dtb_by_gpio(const char *file_name) 577 { 578 static uint32_t cached_v[MAX_GPIO_NR]; 579 fdt_addr_t gpio_base_addr[MAX_GPIO_NR]; 580 int ret, found = 0, offset = strlen(KEY_WORDS_GPIO); 581 uint8_t port, pin, bank, lvl, val; 582 char *strgpio, *p; 583 uint32_t bit; 584 585 debug("%s\n", file_name); 586 587 /* Parse gpio address */ 588 memset(gpio_base_addr, 0, sizeof(gpio_base_addr)); 589 ret = gpio_parse_base_address(gpio_base_addr); 590 if (ret) { 591 debug(" - Can't parse gpio base address: %d\n", ret); 592 return ret; 593 } 594 595 strgpio = strstr(file_name, KEY_WORDS_GPIO); 596 while (strgpio) { 597 debug(" - substr: %s\n", strgpio); 598 599 p = strgpio + offset; 600 601 /* Invalid format ? */ 602 if (!(is_digit(*(p + 0)) && is_abcd(*(p + 1)) && 603 is_digit(*(p + 2)) && is_equal(*(p + 3)) && 604 is_digit(*(p + 4)))) { 605 debug(" - invalid format: %s\n", strgpio); 606 return -EINVAL; 607 } 608 609 /* Read gpio value */ 610 port = *(p + 0) - '0'; 611 bank = *(p + 1) - 'a'; 612 pin = *(p + 2) - '0'; 613 lvl = *(p + 4) - '0'; 614 615 /* 616 * It doesn't need to read gpio value every loop, reading once 617 * is enough. We use cached_v[] to save what we have read, zero 618 * means not read before. 619 */ 620 if (cached_v[port] == 0) { 621 if (!gpio_base_addr[port]) { 622 debug(" - can't find gpio%d base address\n", port); 623 return 0; 624 } 625 626 /* Input mode */ 627 val = readl(gpio_base_addr[port] + GPIO_SWPORT_DDR); 628 val &= ~(1 << (bank * 8 + pin)); 629 writel(val, gpio_base_addr[port] + GPIO_SWPORT_DDR); 630 631 cached_v[port] = 632 readl(gpio_base_addr[port] + GPIO_EXT_PORT); 633 } 634 635 /* Verify result */ 636 bit = bank * 8 + pin; 637 val = cached_v[port] & (1 << bit) ? 1 : 0; 638 639 if (val == !!lvl) { 640 found = 1; 641 strgpio = strstr(p, KEY_WORDS_GPIO); 642 } else { 643 found = 0; 644 break; 645 } 646 647 debug(" - parse: gpio%d%c%d=%d, read=%d %s\n", 648 port, bank + 'a', pin, lvl, val, found ? "(Y)" : "(N)"); 649 } 650 651 return found ? 0 : -ENOENT; 652 } 653 654 #ifdef CONFIG_ROCKCHIP_EARLY_DISTRO_DTB 655 static int rockchip_read_distro_dtb_file(char *fdt_addr) 656 { 657 const char *cmd = "part list ${devtype} ${devnum} -bootable devplist"; 658 char *devnum, *devtype, *devplist; 659 char devnum_part[12]; 660 char fdt_hex_str[19]; 661 char *fs_argv[5]; 662 int ret; 663 664 if (!rockchip_get_bootdev() || !fdt_addr) 665 return -ENODEV; 666 667 ret = run_command_list(cmd, -1, 0); 668 if (ret) 669 return ret; 670 671 devplist = env_get("devplist"); 672 if (!devplist) 673 return -ENODEV; 674 675 devtype = env_get("devtype"); 676 devnum = env_get("devnum"); 677 sprintf(devnum_part, "%s:%s", devnum, devplist); 678 sprintf(fdt_hex_str, "0x%lx", (ulong)fdt_addr); 679 680 #ifdef CONFIG_CMD_FS_GENERIC 681 fs_argv[0] = "load"; 682 fs_argv[1] = devtype, 683 fs_argv[2] = devnum_part; 684 fs_argv[3] = fdt_hex_str; 685 fs_argv[4] = CONFIG_ROCKCHIP_EARLY_DISTRO_DTB_PATH; 686 687 if (do_load(NULL, 0, 5, fs_argv, FS_TYPE_ANY)) 688 return -EIO; 689 #endif 690 if (fdt_check_header(fdt_addr)) 691 return -EIO; 692 693 return fdt_totalsize(fdt_addr); 694 } 695 #endif 696 697 int rockchip_read_dtb_file(void *fdt_addr) 698 { 699 struct resource_file *file; 700 struct list_head *node; 701 char *dtb_name = DTB_FILE; 702 int size = -ENODEV; 703 704 if (list_empty(&entrys_head)) { 705 if (init_resource_list(NULL)) { 706 #ifdef CONFIG_ROCKCHIP_EARLY_DISTRO_DTB 707 /* Maybe a distro boot.img with dtb ? */ 708 printf("Distro DTB: %s\n", 709 CONFIG_ROCKCHIP_EARLY_DISTRO_DTB_PATH); 710 size = rockchip_read_distro_dtb_file(fdt_addr); 711 if (size < 0) 712 return size; 713 if (!sysmem_alloc_base(MEMBLK_ID_FDT, 714 (phys_addr_t)fdt_addr, 715 ALIGN(size, RK_BLK_SIZE) + CONFIG_SYS_FDT_PAD)) 716 return -ENOMEM; 717 #endif 718 return size; 719 } 720 } 721 722 list_for_each(node, &entrys_head) { 723 file = list_entry(node, struct resource_file, link); 724 if (!strstr(file->name, ".dtb")) 725 continue; 726 727 if (strstr(file->name, KEY_WORDS_ADC_CTRL) && 728 strstr(file->name, KEY_WORDS_ADC_CH) && 729 !rockchip_read_dtb_by_adc(file->name)) { 730 dtb_name = file->name; 731 break; 732 } else if (strstr(file->name, KEY_WORDS_GPIO) && 733 !rockchip_read_dtb_by_gpio(file->name)) { 734 dtb_name = file->name; 735 break; 736 } 737 } 738 739 printf("DTB: %s\n", dtb_name); 740 741 size = rockchip_get_resource_file_size((void *)fdt_addr, dtb_name); 742 if (size < 0) 743 return size; 744 745 if (!sysmem_alloc_base(MEMBLK_ID_FDT, (phys_addr_t)fdt_addr, 746 ALIGN(size, RK_BLK_SIZE) + CONFIG_SYS_FDT_PAD)) 747 return -ENOMEM; 748 749 size = rockchip_read_resource_file((void *)fdt_addr, dtb_name, 0, 0); 750 if (size < 0) 751 return size; 752 753 #if defined(CONFIG_CMD_DTIMG) && defined(CONFIG_OF_LIBFDT_OVERLAY) 754 android_fdt_overlay_apply((void *)fdt_addr); 755 #endif 756 757 return size; 758 } 759