xref: /OK3568_Linux_fs/u-boot/arch/arm/mach-rockchip/resource_img.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * (C) Copyright 2017 Rockchip Electronics Co., Ltd
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * SPDX-License-Identifier:     GPL-2.0+
5*4882a593Smuzhiyun  */
6*4882a593Smuzhiyun #include <common.h>
7*4882a593Smuzhiyun #include <boot_rkimg.h>
8*4882a593Smuzhiyun #include <bmp_layout.h>
9*4882a593Smuzhiyun #include <malloc.h>
10*4882a593Smuzhiyun #include <asm/unaligned.h>
11*4882a593Smuzhiyun #include <linux/libfdt.h>
12*4882a593Smuzhiyun #include <linux/list.h>
13*4882a593Smuzhiyun #include <asm/arch/resource_img.h>
14*4882a593Smuzhiyun #include <asm/arch/uimage.h>
15*4882a593Smuzhiyun #include <asm/arch/fit.h>
16*4882a593Smuzhiyun 
17*4882a593Smuzhiyun DECLARE_GLOBAL_DATA_PTR;
18*4882a593Smuzhiyun 
19*4882a593Smuzhiyun #define PART_RESOURCE			"resource"
20*4882a593Smuzhiyun #define RESOURCE_MAGIC			"RSCE"
21*4882a593Smuzhiyun #define RESOURCE_MAGIC_SIZE		4
22*4882a593Smuzhiyun #define ENTRY_TAG			"ENTR"
23*4882a593Smuzhiyun #define ENTRY_TAG_SIZE			4
24*4882a593Smuzhiyun #define MAX_FILE_NAME_LEN		220
25*4882a593Smuzhiyun #define MAX_HASH_LEN			32
26*4882a593Smuzhiyun #define DEFAULT_DTB_FILE		"rk-kernel.dtb"
27*4882a593Smuzhiyun 
28*4882a593Smuzhiyun /*
29*4882a593Smuzhiyun  *         resource image structure
30*4882a593Smuzhiyun  * ----------------------------------------------
31*4882a593Smuzhiyun  * |                                            |
32*4882a593Smuzhiyun  * |    header  (1 block)                       |
33*4882a593Smuzhiyun  * |                                            |
34*4882a593Smuzhiyun  * ---------------------------------------------|
35*4882a593Smuzhiyun  * |                      |                     |
36*4882a593Smuzhiyun  * |    entry0  (1 block) |                     |
37*4882a593Smuzhiyun  * |                      |                     |
38*4882a593Smuzhiyun  * ------------------------                     |
39*4882a593Smuzhiyun  * |                      |                     |
40*4882a593Smuzhiyun  * |    entry1  (1 block) | contents (n blocks) |
41*4882a593Smuzhiyun  * |                      |                     |
42*4882a593Smuzhiyun  * ------------------------                     |
43*4882a593Smuzhiyun  * |    ......            |                     |
44*4882a593Smuzhiyun  * ------------------------                     |
45*4882a593Smuzhiyun  * |                      |                     |
46*4882a593Smuzhiyun  * |    entryn  (1 block) |                     |
47*4882a593Smuzhiyun  * |                      |                     |
48*4882a593Smuzhiyun  * ----------------------------------------------
49*4882a593Smuzhiyun  * |                                            |
50*4882a593Smuzhiyun  * |    file0  (x blocks)                       |
51*4882a593Smuzhiyun  * |                                            |
52*4882a593Smuzhiyun  * ----------------------------------------------
53*4882a593Smuzhiyun  * |                                            |
54*4882a593Smuzhiyun  * |    file1  (y blocks)                       |
55*4882a593Smuzhiyun  * |                                            |
56*4882a593Smuzhiyun  * ----------------------------------------------
57*4882a593Smuzhiyun  * |                   ......                   |
58*4882a593Smuzhiyun  * |---------------------------------------------
59*4882a593Smuzhiyun  * |                                            |
60*4882a593Smuzhiyun  * |    filen  (z blocks)                       |
61*4882a593Smuzhiyun  * |                                            |
62*4882a593Smuzhiyun  * ----------------------------------------------
63*4882a593Smuzhiyun  */
64*4882a593Smuzhiyun 
65*4882a593Smuzhiyun /**
66*4882a593Smuzhiyun  * struct resource_img_hdr
67*4882a593Smuzhiyun  *
68*4882a593Smuzhiyun  * @magic: should be "RSCE"
69*4882a593Smuzhiyun  * @version: resource image version, current is 0
70*4882a593Smuzhiyun  * @c_version: content version, current is 0
71*4882a593Smuzhiyun  * @blks: the size of the header ( 1 block = 512 bytes)
72*4882a593Smuzhiyun  * @c_offset: contents offset(by block) in the image
73*4882a593Smuzhiyun  * @e_blks: the size(by block) of the entry in the contents
74*4882a593Smuzhiyun  * @e_num: numbers of the entrys.
75*4882a593Smuzhiyun  */
76*4882a593Smuzhiyun struct resource_img_hdr {
77*4882a593Smuzhiyun 	char		magic[4];
78*4882a593Smuzhiyun 	uint16_t	version;
79*4882a593Smuzhiyun 	uint16_t	c_version;
80*4882a593Smuzhiyun 	uint8_t		blks;
81*4882a593Smuzhiyun 	uint8_t		c_offset;
82*4882a593Smuzhiyun 	uint8_t		e_blks;
83*4882a593Smuzhiyun 	uint32_t	e_nums;
84*4882a593Smuzhiyun };
85*4882a593Smuzhiyun 
86*4882a593Smuzhiyun struct resource_entry {
87*4882a593Smuzhiyun 	char		tag[4];
88*4882a593Smuzhiyun 	char		name[MAX_FILE_NAME_LEN];
89*4882a593Smuzhiyun 	char		hash[MAX_HASH_LEN];
90*4882a593Smuzhiyun 	uint32_t	hash_size;
91*4882a593Smuzhiyun 	uint32_t	blk_offset;
92*4882a593Smuzhiyun 	uint32_t	size;		/* in byte */
93*4882a593Smuzhiyun };
94*4882a593Smuzhiyun 
95*4882a593Smuzhiyun LIST_HEAD(entry_head);
96*4882a593Smuzhiyun 
resource_check_header(struct resource_img_hdr * hdr)97*4882a593Smuzhiyun static int resource_check_header(struct resource_img_hdr *hdr)
98*4882a593Smuzhiyun {
99*4882a593Smuzhiyun 	return memcmp(RESOURCE_MAGIC, hdr->magic, RESOURCE_MAGIC_SIZE);
100*4882a593Smuzhiyun }
101*4882a593Smuzhiyun 
resource_dump(struct resource_file * f)102*4882a593Smuzhiyun static void resource_dump(struct resource_file *f)
103*4882a593Smuzhiyun {
104*4882a593Smuzhiyun 	printf("%s\n", f->name);
105*4882a593Smuzhiyun 	printf("  blk_start:  0x%08lx\n", (ulong)f->blk_start);
106*4882a593Smuzhiyun 	printf("  blk_offset: 0x%08lx\n", (ulong)f->blk_offset);
107*4882a593Smuzhiyun 	printf("  size:       0x%08x\n", f->size);
108*4882a593Smuzhiyun 	printf("  in_ram:     %d\n", f->in_ram);
109*4882a593Smuzhiyun 	printf("  hash_size:  %d\n\n", f->hash_size);
110*4882a593Smuzhiyun }
111*4882a593Smuzhiyun 
resource_add_file(const char * name,u32 size,u32 blk_start,u32 blk_offset,char * hash,u32 hash_size,bool in_ram)112*4882a593Smuzhiyun static int resource_add_file(const char *name, u32 size,
113*4882a593Smuzhiyun 			     u32 blk_start,  u32 blk_offset,
114*4882a593Smuzhiyun 			     char *hash, u32 hash_size,
115*4882a593Smuzhiyun 			     bool in_ram)
116*4882a593Smuzhiyun {
117*4882a593Smuzhiyun 	struct resource_file *f;
118*4882a593Smuzhiyun 	struct list_head *node;
119*4882a593Smuzhiyun 	bool _new = true;
120*4882a593Smuzhiyun 
121*4882a593Smuzhiyun 	/* old one ? */
122*4882a593Smuzhiyun 	list_for_each(node, &entry_head) {
123*4882a593Smuzhiyun 		f = list_entry(node, struct resource_file, link);
124*4882a593Smuzhiyun 		if (!strcmp(f->name, name)) {
125*4882a593Smuzhiyun 			_new = false;
126*4882a593Smuzhiyun 			break;
127*4882a593Smuzhiyun 		}
128*4882a593Smuzhiyun 	}
129*4882a593Smuzhiyun 
130*4882a593Smuzhiyun 	if (_new) {
131*4882a593Smuzhiyun 		f = calloc(1, sizeof(*f));
132*4882a593Smuzhiyun 		if (!f)
133*4882a593Smuzhiyun 			return -ENOMEM;
134*4882a593Smuzhiyun 
135*4882a593Smuzhiyun 		list_add_tail(&f->link, &entry_head);
136*4882a593Smuzhiyun 	}
137*4882a593Smuzhiyun 
138*4882a593Smuzhiyun 	strcpy(f->name, name);
139*4882a593Smuzhiyun 	f->size       = size;
140*4882a593Smuzhiyun 	f->in_ram     = in_ram;
141*4882a593Smuzhiyun 	f->blk_start  = blk_start;
142*4882a593Smuzhiyun 	f->blk_offset = blk_offset;
143*4882a593Smuzhiyun 	f->hash_size  = hash_size;
144*4882a593Smuzhiyun 	memcpy(f->hash, hash, hash_size);
145*4882a593Smuzhiyun #ifdef DEBUG
146*4882a593Smuzhiyun 	resource_dump(f);
147*4882a593Smuzhiyun #endif
148*4882a593Smuzhiyun 	return 0;
149*4882a593Smuzhiyun }
150*4882a593Smuzhiyun 
resource_setup_list(struct blk_desc * desc,ulong blk_start,void * resc_hdr,bool in_ram)151*4882a593Smuzhiyun static int resource_setup_list(struct blk_desc *desc, ulong blk_start,
152*4882a593Smuzhiyun 			       void *resc_hdr, bool in_ram)
153*4882a593Smuzhiyun {
154*4882a593Smuzhiyun 	struct resource_img_hdr *hdr = resc_hdr;
155*4882a593Smuzhiyun 	struct resource_entry *et;
156*4882a593Smuzhiyun 	u32 i, stride;
157*4882a593Smuzhiyun 	void *pos;
158*4882a593Smuzhiyun 
159*4882a593Smuzhiyun 	pos = (void *)hdr + hdr->c_offset * desc->blksz;
160*4882a593Smuzhiyun 	stride = hdr->e_blks * desc->blksz;
161*4882a593Smuzhiyun 
162*4882a593Smuzhiyun 	for (i = 0; i < hdr->e_nums; i++) {
163*4882a593Smuzhiyun 		et = pos + (i * stride);
164*4882a593Smuzhiyun 		if (memcmp(et->tag, ENTRY_TAG, ENTRY_TAG_SIZE))
165*4882a593Smuzhiyun 			continue;
166*4882a593Smuzhiyun 
167*4882a593Smuzhiyun 		resource_add_file(et->name, et->size,
168*4882a593Smuzhiyun 				  blk_start, et->blk_offset,
169*4882a593Smuzhiyun 				  et->hash, et->hash_size, in_ram);
170*4882a593Smuzhiyun 	}
171*4882a593Smuzhiyun 
172*4882a593Smuzhiyun 	return 0;
173*4882a593Smuzhiyun }
174*4882a593Smuzhiyun 
resource_setup_ram_list(struct blk_desc * desc,void * hdr)175*4882a593Smuzhiyun int resource_setup_ram_list(struct blk_desc *desc, void *hdr)
176*4882a593Smuzhiyun {
177*4882a593Smuzhiyun 	if (!desc)
178*4882a593Smuzhiyun 		return -ENODEV;
179*4882a593Smuzhiyun 
180*4882a593Smuzhiyun 	if (resource_check_header(hdr)) {
181*4882a593Smuzhiyun 		printf("RESC: invalid\n");
182*4882a593Smuzhiyun 		return -EINVAL;
183*4882a593Smuzhiyun 	}
184*4882a593Smuzhiyun 
185*4882a593Smuzhiyun 	/* @blk_start: set as 'hdr' point addr, to be used in byte */
186*4882a593Smuzhiyun 	return resource_setup_list(desc, (ulong)hdr, hdr, true);
187*4882a593Smuzhiyun }
188*4882a593Smuzhiyun 
189*4882a593Smuzhiyun #ifdef CONFIG_ANDROID_BOOT_IMAGE
190*4882a593Smuzhiyun /*
191*4882a593Smuzhiyun  * Add logo.bmp and logo_kernel.bmp from "logo" parititon
192*4882a593Smuzhiyun  *
193*4882a593Smuzhiyun  * Provide a "logo" partition for user to store logo.bmp and
194*4882a593Smuzhiyun  * logo_kernel.bmp, so that the user can update them from
195*4882a593Smuzhiyun  * kernel or user-space dynamically.
196*4882a593Smuzhiyun  *
197*4882a593Smuzhiyun  * "logo" partition layout, do not change order:
198*4882a593Smuzhiyun  *
199*4882a593Smuzhiyun  *   |----------------------| 0x00
200*4882a593Smuzhiyun  *   | raw logo.bmp	    |
201*4882a593Smuzhiyun  *   |----------------------| -> 512-byte aligned
202*4882a593Smuzhiyun  *   | raw logo_kernel.bmp  |
203*4882a593Smuzhiyun  *   |----------------------|
204*4882a593Smuzhiyun  *
205*4882a593Smuzhiyun  * N: the sector count of logo.bmp
206*4882a593Smuzhiyun  *
207*4882a593Smuzhiyun  * How to generate:
208*4882a593Smuzhiyun  * 	cat logo.bmp > logo.img && truncate -s %512 logo.img && cat logo_kernel.bmp >> logo.img
209*4882a593Smuzhiyun  */
resource_setup_logo_bmp(struct blk_desc * desc)210*4882a593Smuzhiyun static int resource_setup_logo_bmp(struct blk_desc *desc)
211*4882a593Smuzhiyun {
212*4882a593Smuzhiyun 	struct bmp_header *header;
213*4882a593Smuzhiyun 	const char *name[] = { "logo.bmp", "logo_kernel.bmp" };
214*4882a593Smuzhiyun 	disk_partition_t part;
215*4882a593Smuzhiyun 	u32 blk_offset = 0;
216*4882a593Smuzhiyun 	u32 filesz;
217*4882a593Smuzhiyun 	int ret, i;
218*4882a593Smuzhiyun 
219*4882a593Smuzhiyun 	if (part_get_info_by_name(desc, PART_LOGO, &part) < 0)
220*4882a593Smuzhiyun 		return 0;
221*4882a593Smuzhiyun 
222*4882a593Smuzhiyun 	header = memalign(ARCH_DMA_MINALIGN, desc->blksz);
223*4882a593Smuzhiyun 	if (!header)
224*4882a593Smuzhiyun 		return -ENOMEM;
225*4882a593Smuzhiyun 
226*4882a593Smuzhiyun 	for (i = 0; i < ARRAY_SIZE(name); i++) {
227*4882a593Smuzhiyun 		if (blk_dread(desc, part.start + blk_offset, 1, header) != 1) {
228*4882a593Smuzhiyun 			ret = -EIO;
229*4882a593Smuzhiyun 			break;
230*4882a593Smuzhiyun 		}
231*4882a593Smuzhiyun 
232*4882a593Smuzhiyun 		if (header->signature[0] != 'B' || header->signature[1] != 'M') {
233*4882a593Smuzhiyun 			ret = -EINVAL;
234*4882a593Smuzhiyun 			break;
235*4882a593Smuzhiyun 		}
236*4882a593Smuzhiyun 
237*4882a593Smuzhiyun 		filesz = get_unaligned_le32(&header->file_size);
238*4882a593Smuzhiyun 		ret = resource_add_file(name[i], filesz, part.start, blk_offset,
239*4882a593Smuzhiyun 					NULL, 0, false);
240*4882a593Smuzhiyun 		if (ret)
241*4882a593Smuzhiyun 			break;
242*4882a593Smuzhiyun 
243*4882a593Smuzhiyun 		/* move to next file */
244*4882a593Smuzhiyun 		blk_offset += DIV_ROUND_UP(filesz, desc->blksz);
245*4882a593Smuzhiyun 
246*4882a593Smuzhiyun 		printf("LOGO: %s\n", name[i]);
247*4882a593Smuzhiyun 
248*4882a593Smuzhiyun 	}
249*4882a593Smuzhiyun 
250*4882a593Smuzhiyun 	free(header);
251*4882a593Smuzhiyun 
252*4882a593Smuzhiyun 	return ret;
253*4882a593Smuzhiyun }
254*4882a593Smuzhiyun 
resource_setup_blk_list(struct blk_desc * desc,ulong blk_start)255*4882a593Smuzhiyun static int resource_setup_blk_list(struct blk_desc *desc, ulong blk_start)
256*4882a593Smuzhiyun {
257*4882a593Smuzhiyun 	struct resource_img_hdr *hdr;
258*4882a593Smuzhiyun 	int blk_cnt;
259*4882a593Smuzhiyun 	int ret = 0;
260*4882a593Smuzhiyun 	void *buf;
261*4882a593Smuzhiyun 
262*4882a593Smuzhiyun 	hdr = memalign(ARCH_DMA_MINALIGN, desc->blksz);
263*4882a593Smuzhiyun 	if (!hdr)
264*4882a593Smuzhiyun 		return -ENOMEM;
265*4882a593Smuzhiyun 
266*4882a593Smuzhiyun 	if (blk_dread(desc, blk_start, 1, hdr) != 1) {
267*4882a593Smuzhiyun 		ret = -EIO;
268*4882a593Smuzhiyun 		goto out;
269*4882a593Smuzhiyun 	}
270*4882a593Smuzhiyun 
271*4882a593Smuzhiyun 	if (resource_check_header(hdr)) {
272*4882a593Smuzhiyun 		printf("RESC: invalid\n");
273*4882a593Smuzhiyun 		if (fdt_check_header(hdr)) {
274*4882a593Smuzhiyun 			ret = -EINVAL;
275*4882a593Smuzhiyun 			goto out;
276*4882a593Smuzhiyun 		} else {
277*4882a593Smuzhiyun 			/* this is a dtb file */
278*4882a593Smuzhiyun 			printf("RESC: this is dtb\n");
279*4882a593Smuzhiyun 			ret = resource_add_file(DEFAULT_DTB_FILE,
280*4882a593Smuzhiyun 						fdt_totalsize(hdr),
281*4882a593Smuzhiyun 						blk_start, 0, NULL, 0, false);
282*4882a593Smuzhiyun 			goto out;
283*4882a593Smuzhiyun 		}
284*4882a593Smuzhiyun 	}
285*4882a593Smuzhiyun 
286*4882a593Smuzhiyun 	blk_cnt = hdr->e_blks * hdr->e_nums;
287*4882a593Smuzhiyun 	hdr = realloc(hdr, (1 + blk_cnt) * desc->blksz);
288*4882a593Smuzhiyun 	if (!hdr) {
289*4882a593Smuzhiyun 		ret = -ENOMEM;
290*4882a593Smuzhiyun 		goto out;
291*4882a593Smuzhiyun 	}
292*4882a593Smuzhiyun 
293*4882a593Smuzhiyun 	buf = (void *)hdr + desc->blksz;
294*4882a593Smuzhiyun 	if (blk_dread(desc, blk_start + hdr->c_offset, blk_cnt, buf) != blk_cnt) {
295*4882a593Smuzhiyun 		ret = -EIO;
296*4882a593Smuzhiyun 		goto out;
297*4882a593Smuzhiyun 	}
298*4882a593Smuzhiyun 
299*4882a593Smuzhiyun 	resource_setup_list(desc, blk_start, hdr, false);
300*4882a593Smuzhiyun 	resource_setup_logo_bmp(desc);
301*4882a593Smuzhiyun out:
302*4882a593Smuzhiyun 	free(hdr);
303*4882a593Smuzhiyun 
304*4882a593Smuzhiyun 	return ret;
305*4882a593Smuzhiyun }
306*4882a593Smuzhiyun 
resource_init(struct blk_desc * desc,disk_partition_t * part,ulong blk_offset)307*4882a593Smuzhiyun static int resource_init(struct blk_desc *desc,
308*4882a593Smuzhiyun 			 disk_partition_t *part,
309*4882a593Smuzhiyun 			 ulong blk_offset)
310*4882a593Smuzhiyun {
311*4882a593Smuzhiyun 	printf("RESC: '%s', blk@0x%08lx\n", part->name, part->start + blk_offset);
312*4882a593Smuzhiyun 
313*4882a593Smuzhiyun #ifdef CONFIG_ANDROID_AVB
314*4882a593Smuzhiyun 	char hdr[512];
315*4882a593Smuzhiyun 	ulong resc_buf = 0;
316*4882a593Smuzhiyun 	int ret;
317*4882a593Smuzhiyun 
318*4882a593Smuzhiyun 	if (blk_dread(desc, part->start, 1, hdr) != 1)
319*4882a593Smuzhiyun 		return -EIO;
320*4882a593Smuzhiyun 
321*4882a593Smuzhiyun 	/* only handle android boot/recovery.img and resource.img, ignore fit */
322*4882a593Smuzhiyun 	if (!android_image_check_header((void *)hdr) ||
323*4882a593Smuzhiyun 	    !resource_check_header((void *)hdr)) {
324*4882a593Smuzhiyun 		ret = android_image_verify_resource((const char *)part->name, &resc_buf);
325*4882a593Smuzhiyun 		if (ret) {
326*4882a593Smuzhiyun 			printf("RESC: '%s', avb verify fail: %d\n", part->name, ret);
327*4882a593Smuzhiyun 			return ret;
328*4882a593Smuzhiyun 		}
329*4882a593Smuzhiyun 
330*4882a593Smuzhiyun 		/*
331*4882a593Smuzhiyun 		 * unlock=0: resc_buf is valid and file was already full load in ram.
332*4882a593Smuzhiyun 		 * unlock=1: resc_buf is 0.
333*4882a593Smuzhiyun 		 */
334*4882a593Smuzhiyun 		if (resc_buf && !resource_check_header((void *)resc_buf))
335*4882a593Smuzhiyun 			return resource_setup_ram_list(desc, (void *)resc_buf);
336*4882a593Smuzhiyun 	}
337*4882a593Smuzhiyun #endif
338*4882a593Smuzhiyun 
339*4882a593Smuzhiyun 	return resource_setup_blk_list(desc, part->start + blk_offset);
340*4882a593Smuzhiyun }
341*4882a593Smuzhiyun 
resource_default(struct blk_desc * desc,disk_partition_t * out_part,ulong * out_blk_offset)342*4882a593Smuzhiyun static int resource_default(struct blk_desc *desc,
343*4882a593Smuzhiyun 			    disk_partition_t *out_part,
344*4882a593Smuzhiyun 			    ulong *out_blk_offset)
345*4882a593Smuzhiyun {
346*4882a593Smuzhiyun 	disk_partition_t part;
347*4882a593Smuzhiyun 
348*4882a593Smuzhiyun 	if (part_get_info_by_name(desc, PART_RESOURCE, &part) < 0)
349*4882a593Smuzhiyun 		return -ENODEV;
350*4882a593Smuzhiyun 
351*4882a593Smuzhiyun 	*out_part = part;
352*4882a593Smuzhiyun 	*out_blk_offset = 0;
353*4882a593Smuzhiyun 
354*4882a593Smuzhiyun 	return 0;
355*4882a593Smuzhiyun }
356*4882a593Smuzhiyun #endif
357*4882a593Smuzhiyun 
resource_scan(void)358*4882a593Smuzhiyun static int resource_scan(void)
359*4882a593Smuzhiyun {
360*4882a593Smuzhiyun 	struct blk_desc *desc = rockchip_get_bootdev();
361*4882a593Smuzhiyun 	__maybe_unused int ret;
362*4882a593Smuzhiyun 
363*4882a593Smuzhiyun 	if (!desc) {
364*4882a593Smuzhiyun 		printf("RESC: No bootdev\n");
365*4882a593Smuzhiyun 		return -ENODEV;
366*4882a593Smuzhiyun 	}
367*4882a593Smuzhiyun 
368*4882a593Smuzhiyun 	if (!list_empty(&entry_head))
369*4882a593Smuzhiyun 		return 0;
370*4882a593Smuzhiyun 
371*4882a593Smuzhiyun #ifdef CONFIG_ROCKCHIP_FIT_IMAGE
372*4882a593Smuzhiyun 	ret = fit_image_init_resource(desc);
373*4882a593Smuzhiyun 	if (!ret || ret != -EAGAIN)
374*4882a593Smuzhiyun 		return ret;
375*4882a593Smuzhiyun #endif
376*4882a593Smuzhiyun #ifdef CONFIG_ROCKCHIP_UIMAGE
377*4882a593Smuzhiyun 	ret = uimage_init_resource(desc);
378*4882a593Smuzhiyun 	if (!ret || ret != -EAGAIN)
379*4882a593Smuzhiyun 		return ret;
380*4882a593Smuzhiyun #endif
381*4882a593Smuzhiyun #ifdef CONFIG_ANDROID_BOOT_IMAGE
382*4882a593Smuzhiyun 	disk_partition_t part;
383*4882a593Smuzhiyun 	ulong blk_offset;
384*4882a593Smuzhiyun 	char hdr[512];
385*4882a593Smuzhiyun 	char name[32];
386*4882a593Smuzhiyun 
387*4882a593Smuzhiyun 	/* partition priority: boot/recovery > resource */
388*4882a593Smuzhiyun 	if (!android_image_init_resource(desc, &part, &blk_offset)) {
389*4882a593Smuzhiyun 		if (blk_dread(desc, part.start + blk_offset, 1, hdr) != 1)
390*4882a593Smuzhiyun 			return -EIO;
391*4882a593Smuzhiyun 
392*4882a593Smuzhiyun 		if (resource_check_header((void *)hdr)) {
393*4882a593Smuzhiyun 			strcpy(name, (char *)part.name);
394*4882a593Smuzhiyun 			if (resource_default(desc, &part, &blk_offset))
395*4882a593Smuzhiyun 				return -ENOENT;
396*4882a593Smuzhiyun 
397*4882a593Smuzhiyun 			printf("RESC: '%s' -> '%s'\n", name, part.name);
398*4882a593Smuzhiyun 		}
399*4882a593Smuzhiyun 	} else {
400*4882a593Smuzhiyun 		if (resource_default(desc, &part, &blk_offset))
401*4882a593Smuzhiyun 			return -ENOENT;
402*4882a593Smuzhiyun 	}
403*4882a593Smuzhiyun 
404*4882a593Smuzhiyun 	/* now, 'part' can be boot/recovery/resource */
405*4882a593Smuzhiyun 	return resource_init(desc, &part, blk_offset);
406*4882a593Smuzhiyun #endif
407*4882a593Smuzhiyun 	return -ENOENT;
408*4882a593Smuzhiyun }
409*4882a593Smuzhiyun 
resource_get_file(const char * name)410*4882a593Smuzhiyun static struct resource_file *resource_get_file(const char *name)
411*4882a593Smuzhiyun {
412*4882a593Smuzhiyun 	struct resource_file *f;
413*4882a593Smuzhiyun 	struct list_head *node;
414*4882a593Smuzhiyun 
415*4882a593Smuzhiyun 	if (resource_scan())
416*4882a593Smuzhiyun 		return NULL;
417*4882a593Smuzhiyun 
418*4882a593Smuzhiyun 	list_for_each(node, &entry_head) {
419*4882a593Smuzhiyun 		f = list_entry(node, struct resource_file, link);
420*4882a593Smuzhiyun 		if (!strcmp(f->name, name))
421*4882a593Smuzhiyun 			return f;
422*4882a593Smuzhiyun 	}
423*4882a593Smuzhiyun 
424*4882a593Smuzhiyun 	return NULL;
425*4882a593Smuzhiyun }
426*4882a593Smuzhiyun 
rockchip_read_resource_file(void * buf,const char * name,int blk_offset,int len)427*4882a593Smuzhiyun int rockchip_read_resource_file(void *buf, const char *name, int blk_offset, int len)
428*4882a593Smuzhiyun {
429*4882a593Smuzhiyun 	struct blk_desc *desc = rockchip_get_bootdev();
430*4882a593Smuzhiyun 	struct resource_file *f;
431*4882a593Smuzhiyun 	int blk_cnt;
432*4882a593Smuzhiyun 	ulong pos;
433*4882a593Smuzhiyun 
434*4882a593Smuzhiyun 	if (!desc)
435*4882a593Smuzhiyun 		return -ENODEV;
436*4882a593Smuzhiyun 
437*4882a593Smuzhiyun 	f = resource_get_file(name);
438*4882a593Smuzhiyun 	if (!f) {
439*4882a593Smuzhiyun 		printf("No resource file: %s\n", name);
440*4882a593Smuzhiyun 		return -ENOENT;
441*4882a593Smuzhiyun 	}
442*4882a593Smuzhiyun 
443*4882a593Smuzhiyun 	if (len <= 0 || len > f->size)
444*4882a593Smuzhiyun 		len = f->size;
445*4882a593Smuzhiyun 
446*4882a593Smuzhiyun 	if (f->in_ram) {
447*4882a593Smuzhiyun 		pos = f->blk_start + (f->blk_offset + blk_offset) * desc->blksz;
448*4882a593Smuzhiyun 		memcpy(buf, (char *)pos, len);
449*4882a593Smuzhiyun 	} else {
450*4882a593Smuzhiyun 		blk_cnt = DIV_ROUND_UP(len, desc->blksz);
451*4882a593Smuzhiyun 		if (blk_dread(desc,
452*4882a593Smuzhiyun 			      f->blk_start + f->blk_offset + blk_offset,
453*4882a593Smuzhiyun 			      blk_cnt, buf) != blk_cnt)
454*4882a593Smuzhiyun 			len = -EIO;
455*4882a593Smuzhiyun 	}
456*4882a593Smuzhiyun 
457*4882a593Smuzhiyun 	return len;
458*4882a593Smuzhiyun }
459*4882a593Smuzhiyun 
460*4882a593Smuzhiyun extern struct resource_file *resource_read_hwid_dtb(void);
461*4882a593Smuzhiyun 
rockchip_read_resource_dtb(void * fdt_addr,char ** hash,int * hash_size)462*4882a593Smuzhiyun int rockchip_read_resource_dtb(void *fdt_addr, char **hash, int *hash_size)
463*4882a593Smuzhiyun {
464*4882a593Smuzhiyun 	struct resource_file *f = NULL;
465*4882a593Smuzhiyun 	int ret;
466*4882a593Smuzhiyun 
467*4882a593Smuzhiyun #ifdef CONFIG_ROCKCHIP_HWID_DTB
468*4882a593Smuzhiyun 	if (resource_scan())
469*4882a593Smuzhiyun 		return -ENOENT;
470*4882a593Smuzhiyun 
471*4882a593Smuzhiyun 	f = resource_read_hwid_dtb();
472*4882a593Smuzhiyun #endif
473*4882a593Smuzhiyun 	/* If no dtb match hardware id(GPIO/ADC), use the default */
474*4882a593Smuzhiyun 	if (!f)
475*4882a593Smuzhiyun 		f = resource_get_file(DEFAULT_DTB_FILE);
476*4882a593Smuzhiyun 
477*4882a593Smuzhiyun 	if (!f)
478*4882a593Smuzhiyun 		return -ENODEV;
479*4882a593Smuzhiyun 
480*4882a593Smuzhiyun 	ret = rockchip_read_resource_file(fdt_addr, f->name, 0, 0);
481*4882a593Smuzhiyun 	if (ret < 0)
482*4882a593Smuzhiyun 		return ret;
483*4882a593Smuzhiyun 
484*4882a593Smuzhiyun 	if (fdt_check_header(fdt_addr))
485*4882a593Smuzhiyun 		return -EBADF;
486*4882a593Smuzhiyun 
487*4882a593Smuzhiyun 	*hash = f->hash;
488*4882a593Smuzhiyun 	*hash_size = f->hash_size;
489*4882a593Smuzhiyun 
490*4882a593Smuzhiyun 	printf("DTB: %s\n", f->name);
491*4882a593Smuzhiyun 
492*4882a593Smuzhiyun 	return 0;
493*4882a593Smuzhiyun }
494*4882a593Smuzhiyun 
do_dump_resource(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])495*4882a593Smuzhiyun static int do_dump_resource(cmd_tbl_t *cmdtp, int flag,
496*4882a593Smuzhiyun 			    int argc, char *const argv[])
497*4882a593Smuzhiyun {
498*4882a593Smuzhiyun 	struct resource_file *f;
499*4882a593Smuzhiyun 	struct list_head *node;
500*4882a593Smuzhiyun 
501*4882a593Smuzhiyun 	list_for_each(node, &entry_head) {
502*4882a593Smuzhiyun 		f = list_entry(node, struct resource_file, link);
503*4882a593Smuzhiyun 		resource_dump(f);
504*4882a593Smuzhiyun 	}
505*4882a593Smuzhiyun 
506*4882a593Smuzhiyun 	return 0;
507*4882a593Smuzhiyun }
508*4882a593Smuzhiyun 
509*4882a593Smuzhiyun U_BOOT_CMD(
510*4882a593Smuzhiyun 	dump_resource, 1, 1, do_dump_resource,
511*4882a593Smuzhiyun 	"dump resource files",
512*4882a593Smuzhiyun 	""
513*4882a593Smuzhiyun );
514*4882a593Smuzhiyun 
515