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