1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright 2019 NXP
4  */
5 
6 #include <common.h>
7 #include <errno.h>
8 #include <image.h>
9 #include <log.h>
10 #include <asm/global_data.h>
11 #include <linux/libfdt.h>
12 #include <spl.h>
13 #include <asm/mach-imx/image.h>
14 #include <asm/arch/sys_proto.h>
15 
16 DECLARE_GLOBAL_DATA_PTR;
17 
18 /* Caller need ensure the offset and size to align with page size */
spl_romapi_raw_seekable_read(u32 offset,u32 size,void * buf)19 ulong spl_romapi_raw_seekable_read(u32 offset, u32 size, void *buf)
20 {
21 	volatile gd_t *pgd = gd;
22 	int ret;
23 
24 	debug("%s 0x%x, size 0x%x\n", __func__, offset, size);
25 
26 	ret = g_rom_api->download_image(buf, offset, size,
27 					((uintptr_t)buf) ^ offset ^ size);
28 
29 	set_gd(pgd);
30 
31 	if (ret == ROM_API_OKAY)
32 		return size;
33 
34 	printf("%s Failure when load 0x%x, size 0x%x\n", __func__, offset, size);
35 
36 	return 0;
37 }
38 
spl_romapi_get_uboot_base(u32 image_offset,u32 rom_bt_dev)39 ulong __weak spl_romapi_get_uboot_base(u32 image_offset, u32 rom_bt_dev)
40 {
41 	u32 offset;
42 
43 	if (((rom_bt_dev >> 16) & 0xff) ==  BT_DEV_TYPE_FLEXSPINOR)
44 		offset = CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR * 512;
45 	else
46 		offset = image_offset + CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR * 512 - 0x8000;
47 
48 	return offset;
49 }
50 
is_boot_from_stream_device(u32 boot)51 static int is_boot_from_stream_device(u32 boot)
52 {
53 	u32 interface;
54 
55 	interface = boot >> 16;
56 	if (interface >= BT_DEV_TYPE_USB)
57 		return 1;
58 
59 	if (interface == BT_DEV_TYPE_MMC && (boot & 1))
60 		return 1;
61 
62 	return 0;
63 }
64 
spl_romapi_read_seekable(struct spl_load_info * load,ulong sector,ulong count,void * buf)65 static ulong spl_romapi_read_seekable(struct spl_load_info *load,
66 				      ulong sector, ulong count,
67 				      void *buf)
68 {
69 	u32 pagesize = *(u32 *)load->priv;
70 	ulong byte = count * pagesize;
71 	u32 offset;
72 
73 	offset = sector * pagesize;
74 
75 	return spl_romapi_raw_seekable_read(offset, byte, buf) / pagesize;
76 }
77 
spl_romapi_load_image_seekable(struct spl_image_info * spl_image,struct spl_boot_device * bootdev,u32 rom_bt_dev)78 static int spl_romapi_load_image_seekable(struct spl_image_info *spl_image,
79 					  struct spl_boot_device *bootdev,
80 					  u32 rom_bt_dev)
81 {
82 	volatile gd_t *pgd = gd;
83 	int ret;
84 	u32 offset;
85 	u32 pagesize, size;
86 	struct image_header *header;
87 	u32 image_offset;
88 
89 	ret = g_rom_api->query_boot_infor(QUERY_IVT_OFF, &offset,
90 					  ((uintptr_t)&offset) ^ QUERY_IVT_OFF);
91 	ret |= g_rom_api->query_boot_infor(QUERY_PAGE_SZ, &pagesize,
92 					   ((uintptr_t)&pagesize) ^ QUERY_PAGE_SZ);
93 	ret |= g_rom_api->query_boot_infor(QUERY_IMG_OFF, &image_offset,
94 					   ((uintptr_t)&image_offset) ^ QUERY_IMG_OFF);
95 
96 	set_gd(pgd);
97 
98 	if (ret != ROM_API_OKAY) {
99 		puts("ROMAPI: Failure query boot infor pagesize/offset\n");
100 		return -1;
101 	}
102 
103 	header = (struct image_header *)(CONFIG_SPL_IMX_ROMAPI_LOADADDR);
104 
105 	printf("image offset 0x%x, pagesize 0x%x, ivt offset 0x%x\n",
106 	       image_offset, pagesize, offset);
107 
108 	offset = spl_romapi_get_uboot_base(image_offset, rom_bt_dev);
109 
110 	size = ALIGN(sizeof(struct image_header), pagesize);
111 	ret = g_rom_api->download_image((u8 *)header, offset, size,
112 					((uintptr_t)header) ^ offset ^ size);
113 	set_gd(pgd);
114 
115 	if (ret != ROM_API_OKAY) {
116 		printf("ROMAPI: download failure offset 0x%x size 0x%x\n",
117 		       offset, size);
118 		return -1;
119 	}
120 
121 	if (IS_ENABLED(CONFIG_SPL_LOAD_FIT) && image_get_magic(header) == FDT_MAGIC) {
122 		struct spl_load_info load;
123 
124 		memset(&load, 0, sizeof(load));
125 		load.bl_len = pagesize;
126 		load.read = spl_romapi_read_seekable;
127 		load.priv = &pagesize;
128 		return spl_load_simple_fit(spl_image, &load, offset / pagesize, header);
129 	} else if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER)) {
130 		struct spl_load_info load;
131 
132 		memset(&load, 0, sizeof(load));
133 		load.bl_len = pagesize;
134 		load.read = spl_romapi_read_seekable;
135 		load.priv = &pagesize;
136 
137 		ret = spl_load_imx_container(spl_image, &load, offset / pagesize);
138 	} else {
139 		/* TODO */
140 		puts("Can't support legacy image\n");
141 		return -1;
142 	}
143 
144 	return 0;
145 }
146 
spl_ram_load_read(struct spl_load_info * load,ulong sector,ulong count,void * buf)147 static ulong spl_ram_load_read(struct spl_load_info *load, ulong sector,
148 			       ulong count, void *buf)
149 {
150 	memcpy(buf, (void *)(sector), count);
151 
152 	if (load->priv) {
153 		ulong *p = (ulong *)load->priv;
154 		ulong total = sector + count;
155 
156 		if (total > *p)
157 			*p = total;
158 	}
159 
160 	return count;
161 }
162 
get_fit_image_size(void * fit)163 static ulong get_fit_image_size(void *fit)
164 {
165 	struct spl_image_info spl_image;
166 	struct spl_load_info spl_load_info;
167 	ulong last = (ulong)fit;
168 
169 	memset(&spl_load_info, 0, sizeof(spl_load_info));
170 	spl_load_info.bl_len = 1;
171 	spl_load_info.read = spl_ram_load_read;
172 	spl_load_info.priv = &last;
173 
174 	spl_load_simple_fit(&spl_image, &spl_load_info,
175 			    (uintptr_t)fit, fit);
176 
177 	return last - (ulong)fit;
178 }
179 
search_fit_header(u8 * p,int size)180 static u8 *search_fit_header(u8 *p, int size)
181 {
182 	int i;
183 
184 	for (i = 0; i < size; i += 4)
185 		if (genimg_get_format(p + i) == IMAGE_FORMAT_FIT)
186 			return p + i;
187 
188 	return NULL;
189 }
190 
search_container_header(u8 * p,int size)191 static u8 *search_container_header(u8 *p, int size)
192 {
193 	int i = 0;
194 	u8 *hdr;
195 
196 	for (i = 0; i < size; i += 4) {
197 		hdr = p + i;
198 		if (*(hdr + 3) == 0x87 && *hdr == 0 && (*(hdr + 1) != 0 || *(hdr + 2) != 0))
199 			return p + i;
200 	}
201 
202 	return NULL;
203 }
204 
search_img_header(u8 * p,int size)205 static u8 *search_img_header(u8 *p, int size)
206 {
207 	if (IS_ENABLED(CONFIG_SPL_LOAD_FIT))
208 		return search_fit_header(p, size);
209 	else if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER))
210 		return search_container_header(p, size);
211 
212 	return NULL;
213 }
214 
img_header_size(void)215 static u32 img_header_size(void)
216 {
217 	if (IS_ENABLED(CONFIG_SPL_LOAD_FIT))
218 		return sizeof(struct fdt_header);
219 	else if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER))
220 		return sizeof(struct container_hdr);
221 
222 	return 0;
223 }
224 
img_info_size(void * img_hdr)225 static int img_info_size(void *img_hdr)
226 {
227 #ifdef CONFIG_SPL_LOAD_FIT
228 	return fit_get_size(img_hdr);
229 #elif defined CONFIG_SPL_LOAD_IMX_CONTAINER
230 	struct container_hdr *container = img_hdr;
231 
232 	return (container->length_lsb + (container->length_msb << 8));
233 #else
234 	return 0;
235 #endif
236 }
237 
img_total_size(void * img_hdr)238 static int img_total_size(void *img_hdr)
239 {
240 	if (IS_ENABLED(CONFIG_SPL_LOAD_FIT)) {
241 		return get_fit_image_size(img_hdr);
242 	} else if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER)) {
243 		int total = get_container_size((ulong)img_hdr, NULL);
244 
245 		if (total < 0) {
246 			printf("invalid container image\n");
247 			return 0;
248 		}
249 
250 		return total;
251 	}
252 
253 	return 0;
254 }
255 
spl_romapi_load_image_stream(struct spl_image_info * spl_image,struct spl_boot_device * bootdev)256 static int spl_romapi_load_image_stream(struct spl_image_info *spl_image,
257 					struct spl_boot_device *bootdev)
258 {
259 	struct spl_load_info load;
260 	volatile gd_t *pgd = gd;
261 	u32 pagesize, pg;
262 	int ret;
263 	int i = 0;
264 	u8 *p = (u8 *)CONFIG_SPL_IMX_ROMAPI_LOADADDR;
265 	u8 *phdr = NULL;
266 	int imagesize;
267 	int total;
268 
269 	ret = g_rom_api->query_boot_infor(QUERY_PAGE_SZ, &pagesize,
270 					  ((uintptr_t)&pagesize) ^ QUERY_PAGE_SZ);
271 	set_gd(pgd);
272 
273 	if (ret != ROM_API_OKAY)
274 		puts("failure at query_boot_info\n");
275 
276 	pg = pagesize;
277 	if (pg < 1024)
278 		pg = 1024;
279 
280 	for (i = 0; i < 640; i++) {
281 		ret = g_rom_api->download_image(p, 0, pg,
282 						((uintptr_t)p) ^ pg);
283 		set_gd(pgd);
284 
285 		if (ret != ROM_API_OKAY) {
286 			puts("Steam(USB) download failure\n");
287 			return -1;
288 		}
289 
290 		phdr = search_img_header(p, pg);
291 		p += pg;
292 
293 		if (phdr)
294 			break;
295 	}
296 
297 	if (!phdr) {
298 		puts("Can't found uboot image in 640K range\n");
299 		return -1;
300 	}
301 
302 	if (p - phdr < img_header_size()) {
303 		ret = g_rom_api->download_image(p, 0, pg,  ((uintptr_t)p) ^ pg);
304 		set_gd(pgd);
305 
306 		if (ret != ROM_API_OKAY) {
307 			puts("Steam(USB) download failure\n");
308 			return -1;
309 		}
310 
311 		p += pg;
312 	}
313 
314 	imagesize = img_info_size(phdr);
315 	printf("Find img info 0x&%p, size %d\n", phdr, imagesize);
316 
317 	if (p - phdr < imagesize) {
318 		imagesize -= p - phdr;
319 		/*need pagesize hear after ROM fix USB problme*/
320 		imagesize += pg - 1;
321 		imagesize /= pg;
322 		imagesize *= pg;
323 
324 		printf("Need continue download %d\n", imagesize);
325 
326 		ret = g_rom_api->download_image(p, 0, imagesize,
327 						((uintptr_t)p) ^ imagesize);
328 		set_gd(pgd);
329 
330 		p += imagesize;
331 
332 		if (ret != ROM_API_OKAY) {
333 			printf("Failure download %d\n", imagesize);
334 			return -1;
335 		}
336 	}
337 
338 	total = img_total_size(phdr);
339 	total += 3;
340 	total &= ~0x3;
341 
342 	imagesize = total - (p - phdr);
343 
344 	imagesize += pagesize - 1;
345 	imagesize /= pagesize;
346 	imagesize *= pagesize;
347 
348 	printf("Download %d, Total size %d\n", imagesize, total);
349 
350 	ret = g_rom_api->download_image(p, 0, imagesize,
351 					((uintptr_t)p) ^ imagesize);
352 	set_gd(pgd);
353 	if (ret != ROM_API_OKAY)
354 		printf("ROM download failure %d\n", imagesize);
355 
356 	memset(&load, 0, sizeof(load));
357 	load.bl_len = 1;
358 	load.read = spl_ram_load_read;
359 
360 	if (IS_ENABLED(CONFIG_SPL_LOAD_FIT))
361 		return spl_load_simple_fit(spl_image, &load, (ulong)phdr, phdr);
362 	else if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER))
363 		return spl_load_imx_container(spl_image, &load, (ulong)phdr);
364 
365 	return -1;
366 }
367 
board_return_to_bootrom(struct spl_image_info * spl_image,struct spl_boot_device * bootdev)368 int board_return_to_bootrom(struct spl_image_info *spl_image,
369 			    struct spl_boot_device *bootdev)
370 {
371 	volatile gd_t *pgd = gd;
372 	int ret;
373 	u32 boot;
374 
375 	ret = g_rom_api->query_boot_infor(QUERY_BT_DEV, &boot,
376 					  ((uintptr_t)&boot) ^ QUERY_BT_DEV);
377 	set_gd(pgd);
378 
379 	if (ret != ROM_API_OKAY) {
380 		puts("ROMAPI: failure at query_boot_info\n");
381 		return -1;
382 	}
383 
384 	if (is_boot_from_stream_device(boot))
385 		return spl_romapi_load_image_stream(spl_image, bootdev);
386 
387 	return spl_romapi_load_image_seekable(spl_image, bootdev, boot);
388 }
389