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