blob: b9ff9bb83b3ce213639ae8213f5935db276e805c [file] [log] [blame]
Peng Fan36986792019-09-16 03:09:31 +00001// 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>
Sean Anderson952ed672023-10-14 16:47:44 -04009#include <imx_container.h>
Simon Glass0f2af882020-05-10 11:40:05 -060010#include <log.h>
Simon Glass3ba929a2020-10-30 21:38:53 -060011#include <asm/global_data.h>
Peng Fan36986792019-09-16 03:09:31 +000012#include <linux/libfdt.h>
13#include <spl.h>
Peng Fan36986792019-09-16 03:09:31 +000014#include <asm/arch/sys_proto.h>
15
16DECLARE_GLOBAL_DATA_PTR;
17
Ye Li7a71c612021-08-07 16:00:39 +080018/* Caller need ensure the offset and size to align with page size */
19ulong spl_romapi_raw_seekable_read(u32 offset, u32 size, void *buf)
20{
Ye Li7a71c612021-08-07 16:00:39 +080021 int ret;
22
23 debug("%s 0x%x, size 0x%x\n", __func__, offset, size);
24
Rasmus Villemoes9bfb1ba2022-06-20 10:53:20 +020025 ret = rom_api_download_image(buf, offset, size);
Ye Li7a71c612021-08-07 16:00:39 +080026
27 if (ret == ROM_API_OKAY)
28 return size;
29
30 printf("%s Failure when load 0x%x, size 0x%x\n", __func__, offset, size);
31
32 return 0;
33}
34
35ulong __weak spl_romapi_get_uboot_base(u32 image_offset, u32 rom_bt_dev)
36{
Marek Vasut85107562022-03-09 17:09:45 +010037 return image_offset +
38 (CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR * 512 - 0x8000);
Ye Li7a71c612021-08-07 16:00:39 +080039}
40
Peng Fan36986792019-09-16 03:09:31 +000041static int is_boot_from_stream_device(u32 boot)
42{
43 u32 interface;
44
45 interface = boot >> 16;
46 if (interface >= BT_DEV_TYPE_USB)
47 return 1;
48
49 if (interface == BT_DEV_TYPE_MMC && (boot & 1))
50 return 1;
51
52 return 0;
53}
54
55static ulong spl_romapi_read_seekable(struct spl_load_info *load,
Sean Anderson7d8d6132023-11-08 11:48:40 -050056 ulong offset, ulong byte,
Peng Fan36986792019-09-16 03:09:31 +000057 void *buf)
58{
Sean Anderson7d8d6132023-11-08 11:48:40 -050059 return spl_romapi_raw_seekable_read(offset, byte, buf);
Peng Fan36986792019-09-16 03:09:31 +000060}
61
62static int spl_romapi_load_image_seekable(struct spl_image_info *spl_image,
63 struct spl_boot_device *bootdev,
64 u32 rom_bt_dev)
65{
Peng Fan36986792019-09-16 03:09:31 +000066 int ret;
67 u32 offset;
68 u32 pagesize, size;
Simon Glassbb7d3bb2022-09-06 20:26:52 -060069 struct legacy_img_hdr *header;
Peng Fan36986792019-09-16 03:09:31 +000070 u32 image_offset;
71
Rasmus Villemoes9bfb1ba2022-06-20 10:53:20 +020072 ret = rom_api_query_boot_infor(QUERY_IVT_OFF, &offset);
Marek Vasut00639162023-07-02 03:03:51 +020073 if (ret != ROM_API_OKAY)
74 goto err;
Peng Fan36986792019-09-16 03:09:31 +000075
Marek Vasut00639162023-07-02 03:03:51 +020076 ret = rom_api_query_boot_infor(QUERY_PAGE_SZ, &pagesize);
77 if (ret != ROM_API_OKAY)
78 goto err;
79
80 ret = rom_api_query_boot_infor(QUERY_IMG_OFF, &image_offset);
81 if (ret != ROM_API_OKAY)
82 goto err;
Peng Fan36986792019-09-16 03:09:31 +000083
Simon Glassbb7d3bb2022-09-06 20:26:52 -060084 header = (struct legacy_img_hdr *)(CONFIG_SPL_IMX_ROMAPI_LOADADDR);
Peng Fan36986792019-09-16 03:09:31 +000085
86 printf("image offset 0x%x, pagesize 0x%x, ivt offset 0x%x\n",
87 image_offset, pagesize, offset);
88
Ye Li7a71c612021-08-07 16:00:39 +080089 offset = spl_romapi_get_uboot_base(image_offset, rom_bt_dev);
Peng Fan36986792019-09-16 03:09:31 +000090
Simon Glassbb7d3bb2022-09-06 20:26:52 -060091 size = ALIGN(sizeof(struct legacy_img_hdr), pagesize);
Rasmus Villemoes9bfb1ba2022-06-20 10:53:20 +020092 ret = rom_api_download_image((u8 *)header, offset, size);
Peng Fan36986792019-09-16 03:09:31 +000093
94 if (ret != ROM_API_OKAY) {
95 printf("ROMAPI: download failure offset 0x%x size 0x%x\n",
96 offset, size);
97 return -1;
98 }
99
Ye Li7a71c612021-08-07 16:00:39 +0800100 if (IS_ENABLED(CONFIG_SPL_LOAD_FIT) && image_get_magic(header) == FDT_MAGIC) {
101 struct spl_load_info load;
102
103 memset(&load, 0, sizeof(load));
Sean Anderson35f15fe2023-11-08 11:48:43 -0500104 spl_set_bl_len(&load, pagesize);
Ye Li7a71c612021-08-07 16:00:39 +0800105 load.read = spl_romapi_read_seekable;
Sean Anderson7d8d6132023-11-08 11:48:40 -0500106 return spl_load_simple_fit(spl_image, &load, offset, header);
Sean Anderson952ed672023-10-14 16:47:44 -0400107 } else if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER) &&
108 valid_container_hdr((void *)header)) {
Peng Fan36986792019-09-16 03:09:31 +0000109 struct spl_load_info load;
110
111 memset(&load, 0, sizeof(load));
Sean Anderson35f15fe2023-11-08 11:48:43 -0500112 spl_set_bl_len(&load, pagesize);
Peng Fan36986792019-09-16 03:09:31 +0000113 load.read = spl_romapi_read_seekable;
Ye Li7a71c612021-08-07 16:00:39 +0800114
Sean Anderson7d8d6132023-11-08 11:48:40 -0500115 ret = spl_load_imx_container(spl_image, &load, offset);
Peng Fan36986792019-09-16 03:09:31 +0000116 } else {
117 /* TODO */
118 puts("Can't support legacy image\n");
119 return -1;
120 }
121
122 return 0;
Marek Vasut00639162023-07-02 03:03:51 +0200123
124err:
125 puts("ROMAPI: Failure query boot infor pagesize/offset\n");
126 return -1;
Peng Fan36986792019-09-16 03:09:31 +0000127}
128
Rasmus Villemoes51600f12023-09-19 15:49:31 +0200129struct stream_state {
130 u8 *base;
131 u8 *end;
132 u32 pagesize;
133};
134
135static ulong spl_romapi_read_stream(struct spl_load_info *load, ulong sector,
136 ulong count, void *buf)
137{
138 struct stream_state *ss = load->priv;
139 u8 *end = (u8*)(sector + count);
140 u32 bytes;
141 int ret;
142
143 if (end > ss->end) {
144 bytes = end - ss->end;
145 bytes += ss->pagesize - 1;
146 bytes /= ss->pagesize;
147 bytes *= ss->pagesize;
148
149 debug("downloading another 0x%x bytes\n", bytes);
150 ret = rom_api_download_image(ss->end, 0, bytes);
151
152 if (ret != ROM_API_OKAY) {
153 printf("Failure download %d\n", bytes);
154 return 0;
155 }
156
Marcel Ziswiler4bd847f2023-10-26 09:32:20 +0200157 ss->end += bytes;
Rasmus Villemoes51600f12023-09-19 15:49:31 +0200158 }
159
160 memcpy(buf, (void *)(sector), count);
161 return count;
162}
163
Peng Fan36986792019-09-16 03:09:31 +0000164static ulong spl_ram_load_read(struct spl_load_info *load, ulong sector,
165 ulong count, void *buf)
166{
167 memcpy(buf, (void *)(sector), count);
168
169 if (load->priv) {
170 ulong *p = (ulong *)load->priv;
171 ulong total = sector + count;
172
173 if (total > *p)
174 *p = total;
175 }
176
177 return count;
178}
179
Ye Li7a71c612021-08-07 16:00:39 +0800180static u8 *search_fit_header(u8 *p, int size)
Peng Fan36986792019-09-16 03:09:31 +0000181{
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;
Ye Li7a71c612021-08-07 16:00:39 +0800187
188 return NULL;
189}
190
191static 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;
Sean Andersonc5126682023-10-14 16:47:43 -0400198 if (valid_container_hdr((void *)hdr) &&
199 (*(hdr + 1) != 0 || *(hdr + 2) != 0))
Ye Li7a71c612021-08-07 16:00:39 +0800200 return p + i;
201 }
202
203 return NULL;
204}
205
206static u8 *search_img_header(u8 *p, int size)
207{
208 if (IS_ENABLED(CONFIG_SPL_LOAD_FIT))
209 return search_fit_header(p, size);
210 else if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER))
211 return search_container_header(p, size);
Peng Fan36986792019-09-16 03:09:31 +0000212
213 return NULL;
214}
215
Ye Li7a71c612021-08-07 16:00:39 +0800216static u32 img_header_size(void)
217{
218 if (IS_ENABLED(CONFIG_SPL_LOAD_FIT))
219 return sizeof(struct fdt_header);
220 else if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER))
221 return sizeof(struct container_hdr);
222
223 return 0;
224}
225
226static int img_info_size(void *img_hdr)
227{
228#ifdef CONFIG_SPL_LOAD_FIT
229 return fit_get_size(img_hdr);
230#elif defined CONFIG_SPL_LOAD_IMX_CONTAINER
231 struct container_hdr *container = img_hdr;
232
233 return (container->length_lsb + (container->length_msb << 8));
234#else
235 return 0;
236#endif
237}
238
239static int img_total_size(void *img_hdr)
240{
Rasmus Villemoes6eb4f782023-09-19 15:49:32 +0200241 if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER)) {
Ye Li7a71c612021-08-07 16:00:39 +0800242 int total = get_container_size((ulong)img_hdr, NULL);
243
244 if (total < 0) {
245 printf("invalid container image\n");
246 return 0;
247 }
248
249 return total;
250 }
251
252 return 0;
253}
254
Peng Fan36986792019-09-16 03:09:31 +0000255static int spl_romapi_load_image_stream(struct spl_image_info *spl_image,
256 struct spl_boot_device *bootdev)
257{
258 struct spl_load_info load;
Peng Fan36986792019-09-16 03:09:31 +0000259 u32 pagesize, pg;
260 int ret;
261 int i = 0;
262 u8 *p = (u8 *)CONFIG_SPL_IMX_ROMAPI_LOADADDR;
Ye Li7a71c612021-08-07 16:00:39 +0800263 u8 *phdr = NULL;
Peng Fan36986792019-09-16 03:09:31 +0000264 int imagesize;
265 int total;
266
Rasmus Villemoes9bfb1ba2022-06-20 10:53:20 +0200267 ret = rom_api_query_boot_infor(QUERY_PAGE_SZ, &pagesize);
Peng Fan36986792019-09-16 03:09:31 +0000268
269 if (ret != ROM_API_OKAY)
270 puts("failure at query_boot_info\n");
271
272 pg = pagesize;
273 if (pg < 1024)
274 pg = 1024;
275
276 for (i = 0; i < 640; i++) {
Rasmus Villemoes9bfb1ba2022-06-20 10:53:20 +0200277 ret = rom_api_download_image(p, 0, pg);
Peng Fan36986792019-09-16 03:09:31 +0000278
279 if (ret != ROM_API_OKAY) {
Marcel Ziswiler0f38fef2023-10-26 09:32:19 +0200280 puts("Stream(USB) download failure\n");
Peng Fan36986792019-09-16 03:09:31 +0000281 return -1;
282 }
283
Ye Li7a71c612021-08-07 16:00:39 +0800284 phdr = search_img_header(p, pg);
Peng Fan36986792019-09-16 03:09:31 +0000285 p += pg;
286
Ye Li7a71c612021-08-07 16:00:39 +0800287 if (phdr)
Peng Fan36986792019-09-16 03:09:31 +0000288 break;
289 }
290
Ye Li7a71c612021-08-07 16:00:39 +0800291 if (!phdr) {
292 puts("Can't found uboot image in 640K range\n");
Peng Fan36986792019-09-16 03:09:31 +0000293 return -1;
294 }
295
Ye Li7a71c612021-08-07 16:00:39 +0800296 if (p - phdr < img_header_size()) {
Rasmus Villemoes9bfb1ba2022-06-20 10:53:20 +0200297 ret = rom_api_download_image(p, 0, pg);
Peng Fan36986792019-09-16 03:09:31 +0000298
299 if (ret != ROM_API_OKAY) {
Marcel Ziswiler0f38fef2023-10-26 09:32:19 +0200300 puts("Stream(USB) download failure\n");
Peng Fan36986792019-09-16 03:09:31 +0000301 return -1;
302 }
303
304 p += pg;
305 }
306
Ye Li7a71c612021-08-07 16:00:39 +0800307 imagesize = img_info_size(phdr);
Marcel Ziswilerff110e32022-07-20 09:27:55 +0200308 printf("Find img info 0x%p, size %d\n", phdr, imagesize);
Peng Fan36986792019-09-16 03:09:31 +0000309
Ye Li7a71c612021-08-07 16:00:39 +0800310 if (p - phdr < imagesize) {
311 imagesize -= p - phdr;
Peng Fan36986792019-09-16 03:09:31 +0000312 /*need pagesize hear after ROM fix USB problme*/
313 imagesize += pg - 1;
314 imagesize /= pg;
315 imagesize *= pg;
316
317 printf("Need continue download %d\n", imagesize);
318
Rasmus Villemoes9bfb1ba2022-06-20 10:53:20 +0200319 ret = rom_api_download_image(p, 0, imagesize);
Peng Fan36986792019-09-16 03:09:31 +0000320
321 p += imagesize;
322
323 if (ret != ROM_API_OKAY) {
324 printf("Failure download %d\n", imagesize);
325 return -1;
326 }
327 }
328
Rasmus Villemoes51600f12023-09-19 15:49:31 +0200329 if (IS_ENABLED(CONFIG_SPL_LOAD_FIT)) {
330 struct stream_state ss;
331
332 ss.base = phdr;
333 ss.end = p;
334 ss.pagesize = pagesize;
335
336 memset(&load, 0, sizeof(load));
Sean Anderson35f15fe2023-11-08 11:48:43 -0500337 spl_set_bl_len(&load, 1);
Rasmus Villemoes51600f12023-09-19 15:49:31 +0200338 load.read = spl_romapi_read_stream;
339 load.priv = &ss;
340
341 return spl_load_simple_fit(spl_image, &load, (ulong)phdr, phdr);
342 }
343
Ye Li7a71c612021-08-07 16:00:39 +0800344 total = img_total_size(phdr);
Peng Fan36986792019-09-16 03:09:31 +0000345 total += 3;
346 total &= ~0x3;
347
Ye Li7a71c612021-08-07 16:00:39 +0800348 imagesize = total - (p - phdr);
Peng Fan36986792019-09-16 03:09:31 +0000349
350 imagesize += pagesize - 1;
351 imagesize /= pagesize;
352 imagesize *= pagesize;
353
Ye Li7a71c612021-08-07 16:00:39 +0800354 printf("Download %d, Total size %d\n", imagesize, total);
Peng Fan36986792019-09-16 03:09:31 +0000355
Rasmus Villemoes9bfb1ba2022-06-20 10:53:20 +0200356 ret = rom_api_download_image(p, 0, imagesize);
Peng Fan36986792019-09-16 03:09:31 +0000357 if (ret != ROM_API_OKAY)
358 printf("ROM download failure %d\n", imagesize);
359
360 memset(&load, 0, sizeof(load));
Sean Anderson35f15fe2023-11-08 11:48:43 -0500361 spl_set_bl_len(&load, 1);
Peng Fan36986792019-09-16 03:09:31 +0000362 load.read = spl_ram_load_read;
363
Rasmus Villemoes6eb4f782023-09-19 15:49:32 +0200364 if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER))
Ye Li7a71c612021-08-07 16:00:39 +0800365 return spl_load_imx_container(spl_image, &load, (ulong)phdr);
366
367 return -1;
Peng Fan36986792019-09-16 03:09:31 +0000368}
369
370int board_return_to_bootrom(struct spl_image_info *spl_image,
371 struct spl_boot_device *bootdev)
372{
Peng Fan36986792019-09-16 03:09:31 +0000373 int ret;
Ye Li504514b2023-02-03 18:21:47 +0800374 u32 boot, bstage;
Peng Fan36986792019-09-16 03:09:31 +0000375
Rasmus Villemoes9bfb1ba2022-06-20 10:53:20 +0200376 ret = rom_api_query_boot_infor(QUERY_BT_DEV, &boot);
Marek Vasut00639162023-07-02 03:03:51 +0200377 if (ret != ROM_API_OKAY)
378 goto err;
Peng Fan36986792019-09-16 03:09:31 +0000379
Marek Vasut00639162023-07-02 03:03:51 +0200380 ret = rom_api_query_boot_infor(QUERY_BT_STAGE, &bstage);
381 if (ret != ROM_API_OKAY)
382 goto err;
Peng Fan36986792019-09-16 03:09:31 +0000383
Ye Li504514b2023-02-03 18:21:47 +0800384 printf("Boot Stage: ");
385
386 switch (bstage) {
387 case BT_STAGE_PRIMARY:
388 printf("Primary boot\n");
389 break;
390 case BT_STAGE_SECONDARY:
391 printf("Secondary boot\n");
392 break;
393 case BT_STAGE_RECOVERY:
394 printf("Recovery boot\n");
395 break;
396 case BT_STAGE_USB:
397 printf("USB boot\n");
398 break;
399 default:
Peng Fanb7052db2023-04-28 12:08:08 +0800400 printf("Unknown (0x%x)\n", bstage);
Ye Li504514b2023-02-03 18:21:47 +0800401 }
402
Peng Fan36986792019-09-16 03:09:31 +0000403 if (is_boot_from_stream_device(boot))
404 return spl_romapi_load_image_stream(spl_image, bootdev);
405
406 return spl_romapi_load_image_seekable(spl_image, bootdev, boot);
Marek Vasut00639162023-07-02 03:03:51 +0200407err:
408 puts("ROMAPI: failure at query_boot_info\n");
409 return -1;
Peng Fan36986792019-09-16 03:09:31 +0000410}