xref: /rk3399_rockchip-uboot/arch/arm/mach-rockchip/resource_img.c (revision de479f92fac8b00a2b04c4f1fc75f40ac7407e0e)
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