108dcd37cSAndy Yan /* 208dcd37cSAndy Yan * (C) Copyright 2017 Rockchip Electronics Co., Ltd 308dcd37cSAndy Yan * 408dcd37cSAndy Yan * SPDX-License-Identifier: GPL-2.0+ 508dcd37cSAndy Yan */ 608dcd37cSAndy Yan #include <common.h> 709052952SJoseph Chen #include <boot_rkimg.h> 81d30bcc5SJoseph Chen #include <bmp_layout.h> 908dcd37cSAndy Yan #include <malloc.h> 101d30bcc5SJoseph Chen #include <asm/unaligned.h> 116ea28a6cSJoseph Chen #include <linux/libfdt.h> 1209052952SJoseph Chen #include <linux/list.h> 1309052952SJoseph Chen #include <asm/arch/resource_img.h> 14*de479f92SXuhui Lin #include <asm/arch/rk_hwid.h> 156ea28a6cSJoseph Chen #include <asm/arch/uimage.h> 166ea28a6cSJoseph Chen #include <asm/arch/fit.h> 1708dcd37cSAndy Yan 18740107bbSJoseph Chen DECLARE_GLOBAL_DATA_PTR; 19740107bbSJoseph Chen 2008dcd37cSAndy Yan #define PART_RESOURCE "resource" 2108dcd37cSAndy Yan #define RESOURCE_MAGIC "RSCE" 2208dcd37cSAndy Yan #define RESOURCE_MAGIC_SIZE 4 2308dcd37cSAndy Yan #define ENTRY_TAG "ENTR" 2408dcd37cSAndy Yan #define ENTRY_TAG_SIZE 4 25e0cee412SJoseph Chen #define MAX_FILE_NAME_LEN 220 26e0cee412SJoseph Chen #define MAX_HASH_LEN 32 27dca57e1cSJoseph Chen #define DEFAULT_DTB_FILE "rk-kernel.dtb" 2809052952SJoseph Chen 2908dcd37cSAndy Yan /* 3008dcd37cSAndy Yan * resource image structure 3108dcd37cSAndy Yan * ---------------------------------------------- 3208dcd37cSAndy Yan * | | 3308dcd37cSAndy Yan * | header (1 block) | 3408dcd37cSAndy Yan * | | 3508dcd37cSAndy Yan * ---------------------------------------------| 3608dcd37cSAndy Yan * | | | 3708dcd37cSAndy Yan * | entry0 (1 block) | | 3808dcd37cSAndy Yan * | | | 3908dcd37cSAndy Yan * ------------------------ | 4008dcd37cSAndy Yan * | | | 4108dcd37cSAndy Yan * | entry1 (1 block) | contents (n blocks) | 4208dcd37cSAndy Yan * | | | 4308dcd37cSAndy Yan * ------------------------ | 4408dcd37cSAndy Yan * | ...... | | 4508dcd37cSAndy Yan * ------------------------ | 4608dcd37cSAndy Yan * | | | 4708dcd37cSAndy Yan * | entryn (1 block) | | 4808dcd37cSAndy Yan * | | | 4908dcd37cSAndy Yan * ---------------------------------------------- 5008dcd37cSAndy Yan * | | 5108dcd37cSAndy Yan * | file0 (x blocks) | 5208dcd37cSAndy Yan * | | 5308dcd37cSAndy Yan * ---------------------------------------------- 5408dcd37cSAndy Yan * | | 5508dcd37cSAndy Yan * | file1 (y blocks) | 5608dcd37cSAndy Yan * | | 5708dcd37cSAndy Yan * ---------------------------------------------- 5808dcd37cSAndy Yan * | ...... | 5908dcd37cSAndy Yan * |--------------------------------------------- 6008dcd37cSAndy Yan * | | 6108dcd37cSAndy Yan * | filen (z blocks) | 6208dcd37cSAndy Yan * | | 6308dcd37cSAndy Yan * ---------------------------------------------- 6408dcd37cSAndy Yan */ 6508dcd37cSAndy Yan 6608dcd37cSAndy Yan /** 676ea28a6cSJoseph Chen * struct resource_img_hdr 6808dcd37cSAndy Yan * 6908dcd37cSAndy Yan * @magic: should be "RSCE" 7008dcd37cSAndy Yan * @version: resource image version, current is 0 7108dcd37cSAndy Yan * @c_version: content version, current is 0 7208dcd37cSAndy Yan * @blks: the size of the header ( 1 block = 512 bytes) 7308dcd37cSAndy Yan * @c_offset: contents offset(by block) in the image 7408dcd37cSAndy Yan * @e_blks: the size(by block) of the entry in the contents 7508dcd37cSAndy Yan * @e_num: numbers of the entrys. 7608dcd37cSAndy Yan */ 7708dcd37cSAndy Yan struct resource_img_hdr { 7808dcd37cSAndy Yan char magic[4]; 7908dcd37cSAndy Yan uint16_t version; 8008dcd37cSAndy Yan uint16_t c_version; 8108dcd37cSAndy Yan uint8_t blks; 8208dcd37cSAndy Yan uint8_t c_offset; 8308dcd37cSAndy Yan uint8_t e_blks; 8408dcd37cSAndy Yan uint32_t e_nums; 8508dcd37cSAndy Yan }; 8608dcd37cSAndy Yan 8708dcd37cSAndy Yan struct resource_entry { 8808dcd37cSAndy Yan char tag[4]; 8908dcd37cSAndy Yan char name[MAX_FILE_NAME_LEN]; 90e0cee412SJoseph Chen char hash[MAX_HASH_LEN]; 91e0cee412SJoseph Chen uint32_t hash_size; 926ea28a6cSJoseph Chen uint32_t blk_offset; 936ea28a6cSJoseph Chen uint32_t size; /* in byte */ 9408dcd37cSAndy Yan }; 9508dcd37cSAndy Yan 966ea28a6cSJoseph Chen LIST_HEAD(entry_head); 9708dcd37cSAndy Yan 986ea28a6cSJoseph Chen static int resource_check_header(struct resource_img_hdr *hdr) 9908dcd37cSAndy Yan { 1006ea28a6cSJoseph Chen return memcmp(RESOURCE_MAGIC, hdr->magic, RESOURCE_MAGIC_SIZE); 10108dcd37cSAndy Yan } 10209052952SJoseph Chen 1036ea28a6cSJoseph Chen static void resource_dump(struct resource_file *f) 10408dcd37cSAndy Yan { 1056ea28a6cSJoseph Chen printf("%s\n", f->name); 1066ea28a6cSJoseph Chen printf(" blk_start: 0x%08lx\n", (ulong)f->blk_start); 1076ea28a6cSJoseph Chen printf(" blk_offset: 0x%08lx\n", (ulong)f->blk_offset); 1086ea28a6cSJoseph Chen printf(" size: 0x%08x\n", f->size); 1096ea28a6cSJoseph Chen printf(" in_ram: %d\n", f->in_ram); 1106ea28a6cSJoseph Chen printf(" hash_size: %d\n\n", f->hash_size); 11108dcd37cSAndy Yan } 11209052952SJoseph Chen 1136ea28a6cSJoseph Chen static int resource_add_file(const char *name, u32 size, 1146ea28a6cSJoseph Chen u32 blk_start, u32 blk_offset, 1156ea28a6cSJoseph Chen char *hash, u32 hash_size, 1166ea28a6cSJoseph Chen bool in_ram) 1174ebf6738SJoseph Chen { 1186ea28a6cSJoseph Chen struct resource_file *f; 1194ebf6738SJoseph Chen struct list_head *node; 1206ea28a6cSJoseph Chen bool _new = true; 1214ebf6738SJoseph Chen 1226ea28a6cSJoseph Chen /* old one ? */ 1236ea28a6cSJoseph Chen list_for_each(node, &entry_head) { 1246ea28a6cSJoseph Chen f = list_entry(node, struct resource_file, link); 1256ea28a6cSJoseph Chen if (!strcmp(f->name, name)) { 1266ea28a6cSJoseph Chen _new = false; 1274ebf6738SJoseph Chen break; 1284ebf6738SJoseph Chen } 1294ebf6738SJoseph Chen } 1304ebf6738SJoseph Chen 1316ea28a6cSJoseph Chen if (_new) { 1326ea28a6cSJoseph Chen f = calloc(1, sizeof(*f)); 1336ea28a6cSJoseph Chen if (!f) 1346ea28a6cSJoseph Chen return -ENOMEM; 1354ebf6738SJoseph Chen 1366ea28a6cSJoseph Chen list_add_tail(&f->link, &entry_head); 1376ea28a6cSJoseph Chen } 1386ea28a6cSJoseph Chen 1396ea28a6cSJoseph Chen strcpy(f->name, name); 1406ea28a6cSJoseph Chen f->size = size; 1416ea28a6cSJoseph Chen f->in_ram = in_ram; 1426ea28a6cSJoseph Chen f->blk_start = blk_start; 1436ea28a6cSJoseph Chen f->blk_offset = blk_offset; 1446ea28a6cSJoseph Chen f->hash_size = hash_size; 1456ea28a6cSJoseph Chen memcpy(f->hash, hash, hash_size); 1466ea28a6cSJoseph Chen #ifdef DEBUG 1476ea28a6cSJoseph Chen resource_dump(f); 1486ea28a6cSJoseph Chen #endif 1494ebf6738SJoseph Chen return 0; 1504ebf6738SJoseph Chen } 1514ebf6738SJoseph Chen 15263f38f9dSJoseph Chen #ifdef CONFIG_ANDROID_BOOT_IMAGE 1536ea28a6cSJoseph Chen /* 1546ea28a6cSJoseph Chen * Add logo.bmp and logo_kernel.bmp from "logo" parititon 1556ea28a6cSJoseph Chen * 1566ea28a6cSJoseph Chen * Provide a "logo" partition for user to store logo.bmp and 1576ea28a6cSJoseph Chen * logo_kernel.bmp, so that the user can update them from 1586ea28a6cSJoseph Chen * kernel or user-space dynamically. 1596ea28a6cSJoseph Chen * 1606ea28a6cSJoseph Chen * "logo" partition layout, do not change order: 1616ea28a6cSJoseph Chen * 1626ea28a6cSJoseph Chen * |----------------------| 0x00 1636ea28a6cSJoseph Chen * | raw logo.bmp | 1646ea28a6cSJoseph Chen * |----------------------| -> 512-byte aligned 1656ea28a6cSJoseph Chen * | raw logo_kernel.bmp | 1666ea28a6cSJoseph Chen * |----------------------| 1676ea28a6cSJoseph Chen * 1686ea28a6cSJoseph Chen * N: the sector count of logo.bmp 1696ea28a6cSJoseph Chen * 1706ea28a6cSJoseph Chen * How to generate: 1716ea28a6cSJoseph Chen * cat logo.bmp > logo.img && truncate -s %512 logo.img && cat logo_kernel.bmp >> logo.img 1726ea28a6cSJoseph Chen */ 1736ea28a6cSJoseph Chen static int resource_setup_logo_bmp(struct blk_desc *desc) 17445390edfSJoseph Chen { 1756ea28a6cSJoseph Chen struct bmp_header *header; 1766ea28a6cSJoseph Chen const char *name[] = { "logo.bmp", "logo_kernel.bmp" }; 1776ea28a6cSJoseph Chen disk_partition_t part; 1786ea28a6cSJoseph Chen u32 blk_offset = 0; 1796ea28a6cSJoseph Chen u32 filesz; 1806ea28a6cSJoseph Chen int ret, i; 18145390edfSJoseph Chen 1826ea28a6cSJoseph Chen if (part_get_info_by_name(desc, PART_LOGO, &part) < 0) 1836ea28a6cSJoseph Chen return 0; 1846ea28a6cSJoseph Chen 1856ea28a6cSJoseph Chen header = memalign(ARCH_DMA_MINALIGN, desc->blksz); 1866ea28a6cSJoseph Chen if (!header) 1876ea28a6cSJoseph Chen return -ENOMEM; 1886ea28a6cSJoseph Chen 1896ea28a6cSJoseph Chen for (i = 0; i < ARRAY_SIZE(name); i++) { 1906ea28a6cSJoseph Chen if (blk_dread(desc, part.start + blk_offset, 1, header) != 1) { 1916ea28a6cSJoseph Chen ret = -EIO; 1926ea28a6cSJoseph Chen break; 1936ea28a6cSJoseph Chen } 1946ea28a6cSJoseph Chen 1956ea28a6cSJoseph Chen if (header->signature[0] != 'B' || header->signature[1] != 'M') { 19645390edfSJoseph Chen ret = -EINVAL; 1976ea28a6cSJoseph Chen break; 19845390edfSJoseph Chen } 19945390edfSJoseph Chen 2006ea28a6cSJoseph Chen filesz = get_unaligned_le32(&header->file_size); 2016ea28a6cSJoseph Chen ret = resource_add_file(name[i], filesz, part.start, blk_offset, 2026ea28a6cSJoseph Chen NULL, 0, false); 2036ea28a6cSJoseph Chen if (ret) 2046ea28a6cSJoseph Chen break; 2056ea28a6cSJoseph Chen 2066ea28a6cSJoseph Chen /* move to next file */ 2076ea28a6cSJoseph Chen blk_offset += DIV_ROUND_UP(filesz, desc->blksz); 2086ea28a6cSJoseph Chen 2096ea28a6cSJoseph Chen printf("LOGO: %s\n", name[i]); 2106ea28a6cSJoseph Chen 21145390edfSJoseph Chen } 2126ea28a6cSJoseph Chen 2136ea28a6cSJoseph Chen free(header); 21445390edfSJoseph Chen 21545390edfSJoseph Chen return ret; 21645390edfSJoseph Chen } 21707dca981SXuhui Lin #endif 21845390edfSJoseph Chen 21907dca981SXuhui Lin static int resource_setup_list(struct blk_desc *desc, ulong blk_start, 22007dca981SXuhui Lin void *resc_hdr, bool in_ram) 22107dca981SXuhui Lin { 22207dca981SXuhui Lin struct resource_img_hdr *hdr = resc_hdr; 22307dca981SXuhui Lin struct resource_entry *et; 22407dca981SXuhui Lin u32 i, stride; 22507dca981SXuhui Lin void *pos; 22607dca981SXuhui Lin 22707dca981SXuhui Lin pos = (void *)hdr + hdr->c_offset * desc->blksz; 22807dca981SXuhui Lin stride = hdr->e_blks * desc->blksz; 22907dca981SXuhui Lin 23007dca981SXuhui Lin for (i = 0; i < hdr->e_nums; i++) { 23107dca981SXuhui Lin et = pos + (i * stride); 23207dca981SXuhui Lin if (memcmp(et->tag, ENTRY_TAG, ENTRY_TAG_SIZE)) 23307dca981SXuhui Lin continue; 23407dca981SXuhui Lin 23507dca981SXuhui Lin resource_add_file(et->name, et->size, 23607dca981SXuhui Lin blk_start, et->blk_offset, 23707dca981SXuhui Lin et->hash, et->hash_size, in_ram); 23807dca981SXuhui Lin } 23907dca981SXuhui Lin #ifdef CONFIG_ANDROID_BOOT_IMAGE 24007dca981SXuhui Lin resource_setup_logo_bmp(desc); 24107dca981SXuhui Lin #endif 24207dca981SXuhui Lin return 0; 24307dca981SXuhui Lin } 24407dca981SXuhui Lin 24507dca981SXuhui Lin int resource_setup_ram_list(struct blk_desc *desc, void *hdr) 24607dca981SXuhui Lin { 24707dca981SXuhui Lin if (!desc) 24807dca981SXuhui Lin return -ENODEV; 24907dca981SXuhui Lin 25007dca981SXuhui Lin if (resource_check_header(hdr)) { 25107dca981SXuhui Lin printf("RESC: invalid\n"); 25207dca981SXuhui Lin return -EINVAL; 25307dca981SXuhui Lin } 25407dca981SXuhui Lin 25507dca981SXuhui Lin /* @blk_start: set as 'hdr' point addr, to be used in byte */ 25607dca981SXuhui Lin return resource_setup_list(desc, (ulong)hdr, hdr, true); 25707dca981SXuhui Lin } 25807dca981SXuhui Lin 25907dca981SXuhui Lin #ifdef CONFIG_ANDROID_BOOT_IMAGE 2606ea28a6cSJoseph Chen static int resource_setup_blk_list(struct blk_desc *desc, ulong blk_start) 26145390edfSJoseph Chen { 26245390edfSJoseph Chen struct resource_img_hdr *hdr; 2636ea28a6cSJoseph Chen int blk_cnt; 26445390edfSJoseph Chen int ret = 0; 2656ea28a6cSJoseph Chen void *buf; 26645390edfSJoseph Chen 2676ea28a6cSJoseph Chen hdr = memalign(ARCH_DMA_MINALIGN, desc->blksz); 26809052952SJoseph Chen if (!hdr) 26909052952SJoseph Chen return -ENOMEM; 27009052952SJoseph Chen 2716ea28a6cSJoseph Chen if (blk_dread(desc, blk_start, 1, hdr) != 1) { 272a84f21ebSJoseph Chen ret = -EIO; 2736ea28a6cSJoseph Chen goto out; 274a84f21ebSJoseph Chen } 275a84f21ebSJoseph Chen 2766ea28a6cSJoseph Chen if (resource_check_header(hdr)) { 2776ea28a6cSJoseph Chen printf("RESC: invalid\n"); 27845390edfSJoseph Chen if (fdt_check_header(hdr)) { 27901ff14b0SJoseph Chen ret = -EINVAL; 2806ea28a6cSJoseph Chen goto out; 28145390edfSJoseph Chen } else { 2826ea28a6cSJoseph Chen /* this is a dtb file */ 2836ea28a6cSJoseph Chen printf("RESC: this is dtb\n"); 2846ea28a6cSJoseph Chen ret = resource_add_file(DEFAULT_DTB_FILE, 2856ea28a6cSJoseph Chen fdt_totalsize(hdr), 2866ea28a6cSJoseph Chen blk_start, 0, NULL, 0, false); 2876ea28a6cSJoseph Chen goto out; 28845390edfSJoseph Chen } 28901ff14b0SJoseph Chen } 290b498696eSJoseph Chen 2916ea28a6cSJoseph Chen blk_cnt = hdr->e_blks * hdr->e_nums; 2926ea28a6cSJoseph Chen hdr = realloc(hdr, (1 + blk_cnt) * desc->blksz); 2936ea28a6cSJoseph Chen if (!hdr) { 29401ff14b0SJoseph Chen ret = -ENOMEM; 2956ea28a6cSJoseph Chen goto out; 29608dcd37cSAndy Yan } 297b498696eSJoseph Chen 2986ea28a6cSJoseph Chen buf = (void *)hdr + desc->blksz; 2996ea28a6cSJoseph Chen if (blk_dread(desc, blk_start + hdr->c_offset, blk_cnt, buf) != blk_cnt) { 30001ff14b0SJoseph Chen ret = -EIO; 3016ea28a6cSJoseph Chen goto out; 30210660eccSJoseph Chen } 30308dcd37cSAndy Yan 3046ea28a6cSJoseph Chen resource_setup_list(desc, blk_start, hdr, false); 3056ea28a6cSJoseph Chen out: 30608dcd37cSAndy Yan free(hdr); 30708dcd37cSAndy Yan 30801ff14b0SJoseph Chen return ret; 30908dcd37cSAndy Yan } 31008dcd37cSAndy Yan 3116ea28a6cSJoseph Chen static int resource_init(struct blk_desc *desc, 3126ea28a6cSJoseph Chen disk_partition_t *part, 3136ea28a6cSJoseph Chen ulong blk_offset) 314745aeb1aSJoseph Chen { 3156ea28a6cSJoseph Chen printf("RESC: '%s', blk@0x%08lx\n", part->name, part->start + blk_offset); 316745aeb1aSJoseph Chen 31777cf005eSJoseph Chen #ifdef CONFIG_ANDROID_AVB 31877cf005eSJoseph Chen char hdr[512]; 31963f38f9dSJoseph Chen ulong resc_buf = 0; 32077cf005eSJoseph Chen int ret; 32177cf005eSJoseph Chen 32277cf005eSJoseph Chen if (blk_dread(desc, part->start, 1, hdr) != 1) 32377cf005eSJoseph Chen return -EIO; 32477cf005eSJoseph Chen 32577cf005eSJoseph Chen /* only handle android boot/recovery.img and resource.img, ignore fit */ 32677cf005eSJoseph Chen if (!android_image_check_header((void *)hdr) || 32777cf005eSJoseph Chen !resource_check_header((void *)hdr)) { 32863f38f9dSJoseph Chen ret = android_image_verify_resource((const char *)part->name, &resc_buf); 32977cf005eSJoseph Chen if (ret) { 33077cf005eSJoseph Chen printf("RESC: '%s', avb verify fail: %d\n", part->name, ret); 33177cf005eSJoseph Chen return ret; 33277cf005eSJoseph Chen } 33377cf005eSJoseph Chen 33463f38f9dSJoseph Chen /* 33563f38f9dSJoseph Chen * unlock=0: resc_buf is valid and file was already full load in ram. 33663f38f9dSJoseph Chen * unlock=1: resc_buf is 0. 33763f38f9dSJoseph Chen */ 33863f38f9dSJoseph Chen if (resc_buf && !resource_check_header((void *)resc_buf)) 33963f38f9dSJoseph Chen return resource_setup_ram_list(desc, (void *)resc_buf); 34077cf005eSJoseph Chen } 34177cf005eSJoseph Chen #endif 34277cf005eSJoseph Chen 3436ea28a6cSJoseph Chen return resource_setup_blk_list(desc, part->start + blk_offset); 344745aeb1aSJoseph Chen } 345745aeb1aSJoseph Chen 3466ea28a6cSJoseph Chen static int resource_default(struct blk_desc *desc, 3476ea28a6cSJoseph Chen disk_partition_t *out_part, 3486ea28a6cSJoseph Chen ulong *out_blk_offset) 34945390edfSJoseph Chen { 35045390edfSJoseph Chen disk_partition_t part; 35145390edfSJoseph Chen 3526ea28a6cSJoseph Chen if (part_get_info_by_name(desc, PART_RESOURCE, &part) < 0) 35345390edfSJoseph Chen return -ENODEV; 3546ea28a6cSJoseph Chen 3556ea28a6cSJoseph Chen *out_part = part; 3566ea28a6cSJoseph Chen *out_blk_offset = 0; 3576ea28a6cSJoseph Chen 3586ea28a6cSJoseph Chen return 0; 3596ea28a6cSJoseph Chen } 36063f38f9dSJoseph Chen #endif 3616ea28a6cSJoseph Chen 3626ea28a6cSJoseph Chen static int resource_scan(void) 3636ea28a6cSJoseph Chen { 3646ea28a6cSJoseph Chen struct blk_desc *desc = rockchip_get_bootdev(); 36563f38f9dSJoseph Chen __maybe_unused int ret; 3666ea28a6cSJoseph Chen 3676ea28a6cSJoseph Chen if (!desc) { 3686ea28a6cSJoseph Chen printf("RESC: No bootdev\n"); 3696ea28a6cSJoseph Chen return -ENODEV; 3706ea28a6cSJoseph Chen } 3716ea28a6cSJoseph Chen 3726ea28a6cSJoseph Chen if (!list_empty(&entry_head)) 3736ea28a6cSJoseph Chen return 0; 3746ea28a6cSJoseph Chen 3756ea28a6cSJoseph Chen #ifdef CONFIG_ROCKCHIP_FIT_IMAGE 37663f38f9dSJoseph Chen ret = fit_image_init_resource(desc); 37763f38f9dSJoseph Chen if (!ret || ret != -EAGAIN) 37863f38f9dSJoseph Chen return ret; 3796ea28a6cSJoseph Chen #endif 3806ea28a6cSJoseph Chen #ifdef CONFIG_ROCKCHIP_UIMAGE 38163f38f9dSJoseph Chen ret = uimage_init_resource(desc); 38263f38f9dSJoseph Chen if (!ret || ret != -EAGAIN) 38363f38f9dSJoseph Chen return ret; 3846ea28a6cSJoseph Chen #endif 38563f38f9dSJoseph Chen #ifdef CONFIG_ANDROID_BOOT_IMAGE 38663f38f9dSJoseph Chen disk_partition_t part; 38763f38f9dSJoseph Chen ulong blk_offset; 38863f38f9dSJoseph Chen char hdr[512]; 38963f38f9dSJoseph Chen char name[32]; 39063f38f9dSJoseph Chen 39163f38f9dSJoseph Chen /* partition priority: boot/recovery > resource */ 39263f38f9dSJoseph Chen if (!android_image_init_resource(desc, &part, &blk_offset)) { 3936ea28a6cSJoseph Chen if (blk_dread(desc, part.start + blk_offset, 1, hdr) != 1) 3946ea28a6cSJoseph Chen return -EIO; 3956ea28a6cSJoseph Chen 3966ea28a6cSJoseph Chen if (resource_check_header((void *)hdr)) { 3976ea28a6cSJoseph Chen strcpy(name, (char *)part.name); 3986ea28a6cSJoseph Chen if (resource_default(desc, &part, &blk_offset)) 3996ea28a6cSJoseph Chen return -ENOENT; 4006ea28a6cSJoseph Chen 4016ea28a6cSJoseph Chen printf("RESC: '%s' -> '%s'\n", name, part.name); 4026ea28a6cSJoseph Chen } 403745aeb1aSJoseph Chen } else { 4046ea28a6cSJoseph Chen if (resource_default(desc, &part, &blk_offset)) 40545390edfSJoseph Chen return -ENOENT; 40645390edfSJoseph Chen } 40709052952SJoseph Chen 40863f38f9dSJoseph Chen /* now, 'part' can be boot/recovery/resource */ 4096ea28a6cSJoseph Chen return resource_init(desc, &part, blk_offset); 41063f38f9dSJoseph Chen #endif 41163f38f9dSJoseph Chen return -ENOENT; 4126ea28a6cSJoseph Chen } 4136ea28a6cSJoseph Chen 4146ea28a6cSJoseph Chen static struct resource_file *resource_get_file(const char *name) 4156ea28a6cSJoseph Chen { 4166ea28a6cSJoseph Chen struct resource_file *f; 4176ea28a6cSJoseph Chen struct list_head *node; 4186ea28a6cSJoseph Chen 4196ea28a6cSJoseph Chen if (resource_scan()) 4206ea28a6cSJoseph Chen return NULL; 4216ea28a6cSJoseph Chen 4226ea28a6cSJoseph Chen list_for_each(node, &entry_head) { 4236ea28a6cSJoseph Chen f = list_entry(node, struct resource_file, link); 4246ea28a6cSJoseph Chen if (!strcmp(f->name, name)) 4256ea28a6cSJoseph Chen return f; 4266ea28a6cSJoseph Chen } 4276ea28a6cSJoseph Chen 4286ea28a6cSJoseph Chen return NULL; 4296ea28a6cSJoseph Chen } 4306ea28a6cSJoseph Chen 4316ea28a6cSJoseph Chen int rockchip_read_resource_file(void *buf, const char *name, int blk_offset, int len) 4326ea28a6cSJoseph Chen { 4336ea28a6cSJoseph Chen struct blk_desc *desc = rockchip_get_bootdev(); 4346ea28a6cSJoseph Chen struct resource_file *f; 4356ea28a6cSJoseph Chen int blk_cnt; 4366ea28a6cSJoseph Chen ulong pos; 4376ea28a6cSJoseph Chen 4386ea28a6cSJoseph Chen if (!desc) 43909052952SJoseph Chen return -ENODEV; 4406ea28a6cSJoseph Chen 4416ea28a6cSJoseph Chen f = resource_get_file(name); 4426ea28a6cSJoseph Chen if (!f) { 4436ea28a6cSJoseph Chen printf("No resource file: %s\n", name); 4446ea28a6cSJoseph Chen return -ENOENT; 44509052952SJoseph Chen } 44608dcd37cSAndy Yan 4476ea28a6cSJoseph Chen if (len <= 0 || len > f->size) 4486ea28a6cSJoseph Chen len = f->size; 44909052952SJoseph Chen 4506ea28a6cSJoseph Chen if (f->in_ram) { 4516ea28a6cSJoseph Chen pos = f->blk_start + (f->blk_offset + blk_offset) * desc->blksz; 4526ea28a6cSJoseph Chen memcpy(buf, (char *)pos, len); 45345390edfSJoseph Chen } else { 4546ea28a6cSJoseph Chen blk_cnt = DIV_ROUND_UP(len, desc->blksz); 4556ea28a6cSJoseph Chen if (blk_dread(desc, 4566ea28a6cSJoseph Chen f->blk_start + f->blk_offset + blk_offset, 4576ea28a6cSJoseph Chen blk_cnt, buf) != blk_cnt) 4586ea28a6cSJoseph Chen len = -EIO; 45945390edfSJoseph Chen } 46008dcd37cSAndy Yan 4616ea28a6cSJoseph Chen return len; 46208dcd37cSAndy Yan } 463740107bbSJoseph Chen 464*de479f92SXuhui Lin #ifdef CONFIG_ROCKCHIP_HWID_DTB 465*de479f92SXuhui Lin static struct resource_file *resource_read_hwid_dtb(void) 466*de479f92SXuhui Lin { 467*de479f92SXuhui Lin struct resource_file *file; 468*de479f92SXuhui Lin struct list_head *node; 469*de479f92SXuhui Lin 470*de479f92SXuhui Lin hwid_init_data(); 471*de479f92SXuhui Lin 472*de479f92SXuhui Lin list_for_each(node, &entry_head) { 473*de479f92SXuhui Lin file = list_entry(node, struct resource_file, link); 474*de479f92SXuhui Lin if (!strstr(file->name, DTB_SUFFIX)) 475*de479f92SXuhui Lin continue; 476*de479f92SXuhui Lin 477*de479f92SXuhui Lin if (hwid_dtb_is_available(file->name)) 478*de479f92SXuhui Lin return file; 479*de479f92SXuhui Lin } 480*de479f92SXuhui Lin 481*de479f92SXuhui Lin return NULL; 482*de479f92SXuhui Lin } 483*de479f92SXuhui Lin #endif 4846ea28a6cSJoseph Chen 485bc4ccd53SJoseph Chen int rockchip_read_resource_dtb(void *fdt_addr, char **hash, int *hash_size) 486740107bbSJoseph Chen { 4876ea28a6cSJoseph Chen struct resource_file *f = NULL; 488a6926964SJoseph Chen int ret; 489740107bbSJoseph Chen 490ca6fb291SJoseph Chen #ifdef CONFIG_ROCKCHIP_HWID_DTB 4916ea28a6cSJoseph Chen if (resource_scan()) 4926ea28a6cSJoseph Chen return -ENOENT; 493ea513bf6SJoseph Chen 4946ea28a6cSJoseph Chen f = resource_read_hwid_dtb(); 4956ea28a6cSJoseph Chen #endif 4966ea28a6cSJoseph Chen /* If no dtb match hardware id(GPIO/ADC), use the default */ 4976ea28a6cSJoseph Chen if (!f) 4986ea28a6cSJoseph Chen f = resource_get_file(DEFAULT_DTB_FILE); 4996ea28a6cSJoseph Chen 5006ea28a6cSJoseph Chen if (!f) 5016069a2ccSJoseph Chen return -ENODEV; 502740107bbSJoseph Chen 5036ea28a6cSJoseph Chen ret = rockchip_read_resource_file(fdt_addr, f->name, 0, 0); 504a6926964SJoseph Chen if (ret < 0) 505a6926964SJoseph Chen return ret; 506b4a94719SJoseph Chen 507bc4ccd53SJoseph Chen if (fdt_check_header(fdt_addr)) 5084f74cb30SJoseph Chen return -EBADF; 5094f74cb30SJoseph Chen 5106ea28a6cSJoseph Chen *hash = f->hash; 5116ea28a6cSJoseph Chen *hash_size = f->hash_size; 512e0cee412SJoseph Chen 5136ea28a6cSJoseph Chen printf("DTB: %s\n", f->name); 514ea513bf6SJoseph Chen 515ea513bf6SJoseph Chen return 0; 516ea513bf6SJoseph Chen } 5175f63fd7aSJoseph Chen 5185f63fd7aSJoseph Chen static int do_dump_resource(cmd_tbl_t *cmdtp, int flag, 5195f63fd7aSJoseph Chen int argc, char *const argv[]) 5205f63fd7aSJoseph Chen { 5216ea28a6cSJoseph Chen struct resource_file *f; 5225f63fd7aSJoseph Chen struct list_head *node; 5235f63fd7aSJoseph Chen 5246ea28a6cSJoseph Chen list_for_each(node, &entry_head) { 5256ea28a6cSJoseph Chen f = list_entry(node, struct resource_file, link); 5266ea28a6cSJoseph Chen resource_dump(f); 5275f63fd7aSJoseph Chen } 5285f63fd7aSJoseph Chen 5295f63fd7aSJoseph Chen return 0; 5305f63fd7aSJoseph Chen } 5315f63fd7aSJoseph Chen 5325f63fd7aSJoseph Chen U_BOOT_CMD( 5335f63fd7aSJoseph Chen dump_resource, 1, 1, do_dump_resource, 5346ea28a6cSJoseph Chen "dump resource files", 5355f63fd7aSJoseph Chen "" 5365f63fd7aSJoseph Chen ); 5375f63fd7aSJoseph Chen 538