xref: /rk3399_rockchip-uboot/arch/arm/mach-rockchip/resource_img.c (revision 08dcd37c063a8e4bf7d302c7b128af3d070b4e8b)
1*08dcd37cSAndy Yan /*
2*08dcd37cSAndy Yan  * (C) Copyright 2017 Rockchip Electronics Co., Ltd
3*08dcd37cSAndy Yan  *
4*08dcd37cSAndy Yan  * SPDX-License-Identifier:     GPL-2.0+
5*08dcd37cSAndy Yan  */
6*08dcd37cSAndy Yan #include <common.h>
7*08dcd37cSAndy Yan #include <malloc.h>
8*08dcd37cSAndy Yan #include <linux/list.h>
9*08dcd37cSAndy Yan #include <asm/arch/resource_img.h>
10*08dcd37cSAndy Yan #include "rockchip_parameter.h"
11*08dcd37cSAndy Yan #include "rockchip_blk.h"
12*08dcd37cSAndy Yan 
13*08dcd37cSAndy Yan #define PART_RESOURCE			"resource"
14*08dcd37cSAndy Yan #define RESOURCE_MAGIC			"RSCE"
15*08dcd37cSAndy Yan #define RESOURCE_MAGIC_SIZE		4
16*08dcd37cSAndy Yan #define RESOURCE_VERSION		0
17*08dcd37cSAndy Yan #define CONTENT_VERSION			0
18*08dcd37cSAndy Yan #define ENTRY_TAG			"ENTR"
19*08dcd37cSAndy Yan #define ENTRY_TAG_SIZE			4
20*08dcd37cSAndy Yan #define MAX_FILE_NAME_LEN		256
21*08dcd37cSAndy Yan 
22*08dcd37cSAndy Yan /*
23*08dcd37cSAndy Yan  *         resource image structure
24*08dcd37cSAndy Yan  * ----------------------------------------------
25*08dcd37cSAndy Yan  * |                                            |
26*08dcd37cSAndy Yan  * |    header  (1 block)                       |
27*08dcd37cSAndy Yan  * |                                            |
28*08dcd37cSAndy Yan  * ---------------------------------------------|
29*08dcd37cSAndy Yan  * |                      |                     |
30*08dcd37cSAndy Yan  * |    entry0  (1 block) |                     |
31*08dcd37cSAndy Yan  * |                      |                     |
32*08dcd37cSAndy Yan  * ------------------------                     |
33*08dcd37cSAndy Yan  * |                      |                     |
34*08dcd37cSAndy Yan  * |    entry1  (1 block) | contents (n blocks) |
35*08dcd37cSAndy Yan  * |                      |                     |
36*08dcd37cSAndy Yan  * ------------------------                     |
37*08dcd37cSAndy Yan  * |    ......            |                     |
38*08dcd37cSAndy Yan  * ------------------------                     |
39*08dcd37cSAndy Yan  * |                      |                     |
40*08dcd37cSAndy Yan  * |    entryn  (1 block) |                     |
41*08dcd37cSAndy Yan  * |                      |                     |
42*08dcd37cSAndy Yan  * ----------------------------------------------
43*08dcd37cSAndy Yan  * |                                            |
44*08dcd37cSAndy Yan  * |    file0  (x blocks)                       |
45*08dcd37cSAndy Yan  * |                                            |
46*08dcd37cSAndy Yan  * ----------------------------------------------
47*08dcd37cSAndy Yan  * |                                            |
48*08dcd37cSAndy Yan  * |    file1  (y blocks)                       |
49*08dcd37cSAndy Yan  * |                                            |
50*08dcd37cSAndy Yan  * ----------------------------------------------
51*08dcd37cSAndy Yan  * |                   ......                   |
52*08dcd37cSAndy Yan  * |---------------------------------------------
53*08dcd37cSAndy Yan  * |                                            |
54*08dcd37cSAndy Yan  * |    filen  (z blocks)                       |
55*08dcd37cSAndy Yan  * |                                            |
56*08dcd37cSAndy Yan  * ----------------------------------------------
57*08dcd37cSAndy Yan  */
58*08dcd37cSAndy Yan 
59*08dcd37cSAndy Yan /**
60*08dcd37cSAndy Yan  * struct resource_image_header
61*08dcd37cSAndy Yan  *
62*08dcd37cSAndy Yan  * @magic: should be "RSCE"
63*08dcd37cSAndy Yan  * @version: resource image version, current is 0
64*08dcd37cSAndy Yan  * @c_version: content version, current is 0
65*08dcd37cSAndy Yan  * @blks: the size of the header ( 1 block = 512 bytes)
66*08dcd37cSAndy Yan  * @c_offset: contents offset(by block) in the image
67*08dcd37cSAndy Yan  * @e_blks: the size(by block) of the entry in the contents
68*08dcd37cSAndy Yan  * @e_num: numbers of the entrys.
69*08dcd37cSAndy Yan  */
70*08dcd37cSAndy Yan 
71*08dcd37cSAndy Yan struct resource_img_hdr {
72*08dcd37cSAndy Yan 	char		magic[4];
73*08dcd37cSAndy Yan 	uint16_t	version;
74*08dcd37cSAndy Yan 	uint16_t	c_version;
75*08dcd37cSAndy Yan 	uint8_t		blks;
76*08dcd37cSAndy Yan 	uint8_t		c_offset;
77*08dcd37cSAndy Yan 	uint8_t		e_blks;
78*08dcd37cSAndy Yan 	uint32_t	e_nums;
79*08dcd37cSAndy Yan };
80*08dcd37cSAndy Yan 
81*08dcd37cSAndy Yan struct resource_entry {
82*08dcd37cSAndy Yan 	char		tag[4];
83*08dcd37cSAndy Yan 	char		name[MAX_FILE_NAME_LEN];
84*08dcd37cSAndy Yan 	uint32_t	f_offset;
85*08dcd37cSAndy Yan 	uint32_t	f_size;
86*08dcd37cSAndy Yan };
87*08dcd37cSAndy Yan 
88*08dcd37cSAndy Yan struct resource_file {
89*08dcd37cSAndy Yan 	char		name[MAX_FILE_NAME_LEN];
90*08dcd37cSAndy Yan 	uint32_t	f_offset;
91*08dcd37cSAndy Yan 	uint32_t	f_size;
92*08dcd37cSAndy Yan 	struct list_head link;
93*08dcd37cSAndy Yan };
94*08dcd37cSAndy Yan 
95*08dcd37cSAndy Yan static struct blk_part *rsce_blk;
96*08dcd37cSAndy Yan 
97*08dcd37cSAndy Yan static LIST_HEAD(entrys_head);
98*08dcd37cSAndy Yan 
99*08dcd37cSAndy Yan static int resource_image_check_header(const struct resource_img_hdr *hdr)
100*08dcd37cSAndy Yan {
101*08dcd37cSAndy Yan 	int ret;
102*08dcd37cSAndy Yan 
103*08dcd37cSAndy Yan 	ret = memcmp(RESOURCE_MAGIC, hdr->magic, RESOURCE_MAGIC_SIZE);
104*08dcd37cSAndy Yan 	if (ret) {
105*08dcd37cSAndy Yan 		printf("bad resource image magic\n");
106*08dcd37cSAndy Yan 		ret = -EINVAL;
107*08dcd37cSAndy Yan 	}
108*08dcd37cSAndy Yan 	debug("resource image header:\n");
109*08dcd37cSAndy Yan 	debug("magic:%s\n", hdr->magic);
110*08dcd37cSAndy Yan 	debug("version:%d\n", hdr->version);
111*08dcd37cSAndy Yan 	debug("c_version:%d\n", hdr->c_version);
112*08dcd37cSAndy Yan 	debug("blks:%d\n", hdr->blks);
113*08dcd37cSAndy Yan 	debug("c_offset:%d\n", hdr->c_offset);
114*08dcd37cSAndy Yan 	debug("e_blks:%d\n", hdr->e_blks);
115*08dcd37cSAndy Yan 	debug("e_num:%d\n", hdr->e_nums);
116*08dcd37cSAndy Yan 
117*08dcd37cSAndy Yan 	return ret;
118*08dcd37cSAndy Yan }
119*08dcd37cSAndy Yan 
120*08dcd37cSAndy Yan static int add_file_to_list(struct resource_entry *entry)
121*08dcd37cSAndy Yan {
122*08dcd37cSAndy Yan 	struct resource_file *file;
123*08dcd37cSAndy Yan 
124*08dcd37cSAndy Yan 	if (memcmp(entry->tag, ENTRY_TAG, ENTRY_TAG_SIZE)) {
125*08dcd37cSAndy Yan 		printf("invalid entry tag\n");
126*08dcd37cSAndy Yan 		return -ENOENT;
127*08dcd37cSAndy Yan 	}
128*08dcd37cSAndy Yan 	file = malloc(sizeof(*file));
129*08dcd37cSAndy Yan 	if (!file) {
130*08dcd37cSAndy Yan 		printf("out of memory\n");
131*08dcd37cSAndy Yan 		return -ENOMEM;
132*08dcd37cSAndy Yan 	}
133*08dcd37cSAndy Yan 	strcpy(file->name, entry->name);
134*08dcd37cSAndy Yan 	file->f_offset = entry->f_offset;
135*08dcd37cSAndy Yan 	file->f_size = entry->f_size;
136*08dcd37cSAndy Yan 	list_add_tail(&file->link, &entrys_head);
137*08dcd37cSAndy Yan 	debug("entry:%p  %s offset:%d size:%d\n",
138*08dcd37cSAndy Yan 	      entry, file->name, file->f_offset, file->f_size);
139*08dcd37cSAndy Yan 
140*08dcd37cSAndy Yan 	return 0;
141*08dcd37cSAndy Yan }
142*08dcd37cSAndy Yan 
143*08dcd37cSAndy Yan static int read_file_info_from_blk_dev(void)
144*08dcd37cSAndy Yan {
145*08dcd37cSAndy Yan 	struct resource_img_hdr *hdr;
146*08dcd37cSAndy Yan 	struct resource_entry *entry;
147*08dcd37cSAndy Yan 	void *content;
148*08dcd37cSAndy Yan 	int size;
149*08dcd37cSAndy Yan 	int ret;
150*08dcd37cSAndy Yan 	int e_num;
151*08dcd37cSAndy Yan 
152*08dcd37cSAndy Yan 	rsce_blk = rockchip_get_blk_part(PART_RESOURCE);
153*08dcd37cSAndy Yan 	if (!rsce_blk) {
154*08dcd37cSAndy Yan 		printf("no resource partition found\n");
155*08dcd37cSAndy Yan 		return  -ENODEV;
156*08dcd37cSAndy Yan 	}
157*08dcd37cSAndy Yan 
158*08dcd37cSAndy Yan 	hdr = memalign(ARCH_DMA_MINALIGN, RK_BLK_SIZE);
159*08dcd37cSAndy Yan 	if (!hdr) {
160*08dcd37cSAndy Yan 		printf("out of memory!\n");
161*08dcd37cSAndy Yan 		return -ENOMEM;
162*08dcd37cSAndy Yan 	}
163*08dcd37cSAndy Yan 
164*08dcd37cSAndy Yan 	ret = blkdev_read(hdr, rsce_blk->from, 1);
165*08dcd37cSAndy Yan 	if (ret < 0)
166*08dcd37cSAndy Yan 		goto out;
167*08dcd37cSAndy Yan 	ret = resource_image_check_header(hdr);
168*08dcd37cSAndy Yan 	if (ret < 0)
169*08dcd37cSAndy Yan 		goto out;
170*08dcd37cSAndy Yan 	content = memalign(ARCH_DMA_MINALIGN,
171*08dcd37cSAndy Yan 			   hdr->e_blks * hdr->e_nums * RK_BLK_SIZE);
172*08dcd37cSAndy Yan 	if (!content) {
173*08dcd37cSAndy Yan 		printf("alloc memory for content failed\n");
174*08dcd37cSAndy Yan 		goto out;
175*08dcd37cSAndy Yan 	}
176*08dcd37cSAndy Yan 	ret = blkdev_read(content, rsce_blk->from + hdr->c_offset,
177*08dcd37cSAndy Yan 			  hdr->e_blks * hdr->e_nums);
178*08dcd37cSAndy Yan 	if (ret < 0)
179*08dcd37cSAndy Yan 		goto err;
180*08dcd37cSAndy Yan 
181*08dcd37cSAndy Yan 	for (e_num = 0; e_num < hdr->e_nums; e_num++) {
182*08dcd37cSAndy Yan 		size = e_num * hdr->e_blks * RK_BLK_SIZE;
183*08dcd37cSAndy Yan 		entry = (struct resource_entry *)(content + size);
184*08dcd37cSAndy Yan 		add_file_to_list(entry);
185*08dcd37cSAndy Yan 	}
186*08dcd37cSAndy Yan 
187*08dcd37cSAndy Yan err:
188*08dcd37cSAndy Yan 	free(content);
189*08dcd37cSAndy Yan out:
190*08dcd37cSAndy Yan 	free(hdr);
191*08dcd37cSAndy Yan 
192*08dcd37cSAndy Yan 	return 0;
193*08dcd37cSAndy Yan }
194*08dcd37cSAndy Yan 
195*08dcd37cSAndy Yan static struct resource_file *get_file_info(struct resource_img_hdr *hdr,
196*08dcd37cSAndy Yan 					   const void *content,
197*08dcd37cSAndy Yan 					   const char *name)
198*08dcd37cSAndy Yan {
199*08dcd37cSAndy Yan 	struct resource_file *file;
200*08dcd37cSAndy Yan 	struct list_head *node;
201*08dcd37cSAndy Yan 
202*08dcd37cSAndy Yan 	if (list_empty(&entrys_head))
203*08dcd37cSAndy Yan 		read_file_info_from_blk_dev();
204*08dcd37cSAndy Yan 
205*08dcd37cSAndy Yan 	list_for_each(node, &entrys_head) {
206*08dcd37cSAndy Yan 		file = list_entry(node, struct resource_file, link);
207*08dcd37cSAndy Yan 		if (!strcmp(file->name, name))
208*08dcd37cSAndy Yan 			return file;
209*08dcd37cSAndy Yan 	}
210*08dcd37cSAndy Yan 
211*08dcd37cSAndy Yan 	return NULL;
212*08dcd37cSAndy Yan }
213*08dcd37cSAndy Yan 
214*08dcd37cSAndy Yan /*
215*08dcd37cSAndy Yan  * read file from resource partition
216*08dcd37cSAndy Yan  * @buf: destination buf to store file data;
217*08dcd37cSAndy Yan  * @name: file name
218*08dcd37cSAndy Yan  * @offset: blocks offset in the file, 1 block = 512 bytes
219*08dcd37cSAndy Yan  * @len: the size(by bytes) of file to read.
220*08dcd37cSAndy Yan  */
221*08dcd37cSAndy Yan int rockchip_read_resource_file(void *buf, const char *name,
222*08dcd37cSAndy Yan 				int offset, int len)
223*08dcd37cSAndy Yan {
224*08dcd37cSAndy Yan 	struct resource_file *file;
225*08dcd37cSAndy Yan 	int ret = 0;
226*08dcd37cSAndy Yan 	int blks;
227*08dcd37cSAndy Yan 
228*08dcd37cSAndy Yan 	file = get_file_info(NULL, NULL, name);
229*08dcd37cSAndy Yan 	if (!file) {
230*08dcd37cSAndy Yan 		printf("Can't find file:%s\n", name);
231*08dcd37cSAndy Yan 		return -ENOENT;
232*08dcd37cSAndy Yan 	}
233*08dcd37cSAndy Yan 
234*08dcd37cSAndy Yan 	if (len <= 0 || len > file->f_size)
235*08dcd37cSAndy Yan 		len = file->f_size;
236*08dcd37cSAndy Yan 	blks = DIV_ROUND_UP(len, RK_BLK_SIZE);
237*08dcd37cSAndy Yan 	ret = blkdev_read(buf, rsce_blk->from + file->f_offset + offset, blks);
238*08dcd37cSAndy Yan 	if (!ret)
239*08dcd37cSAndy Yan 		ret = len;
240*08dcd37cSAndy Yan 
241*08dcd37cSAndy Yan 	return ret;
242*08dcd37cSAndy Yan }
243