Merge https://source.denx.de/u-boot/custodians/u-boot-marvell
[platform/kernel/u-boot.git] / common / splash_source.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * (C) Copyright 2014 CompuLab, Ltd. <www.compulab.co.il>
4  *
5  * Authors: Igor Grinberg <grinberg@compulab.co.il>
6  */
7
8 #include <common.h>
9 #include <bmp_layout.h>
10 #include <command.h>
11 #include <env.h>
12 #include <errno.h>
13 #include <fs.h>
14 #include <fdt_support.h>
15 #include <image.h>
16 #include <log.h>
17 #include <nand.h>
18 #include <sata.h>
19 #include <spi.h>
20 #include <spi_flash.h>
21 #include <splash.h>
22 #include <usb.h>
23 #include <virtio.h>
24 #include <asm/global_data.h>
25
26 DECLARE_GLOBAL_DATA_PTR;
27
28 #ifdef CONFIG_SPI_FLASH
29 static struct spi_flash *sf;
30 static int splash_sf_read_raw(u32 bmp_load_addr, int offset, size_t read_size)
31 {
32         if (!sf) {
33                 sf = spi_flash_probe(CONFIG_SF_DEFAULT_BUS,
34                                      CONFIG_SF_DEFAULT_CS,
35                                      CONFIG_SF_DEFAULT_SPEED,
36                                      CONFIG_SF_DEFAULT_MODE);
37                 if (!sf)
38                         return -ENODEV;
39         }
40
41         return spi_flash_read(sf, offset, read_size, (void *)(uintptr_t)bmp_load_addr);
42 }
43 #else
44 static int splash_sf_read_raw(u32 bmp_load_addr, int offset, size_t read_size)
45 {
46         debug("%s: sf support not available\n", __func__);
47         return -ENOSYS;
48 }
49 #endif
50
51 #ifdef CONFIG_CMD_NAND
52 static int splash_nand_read_raw(u32 bmp_load_addr, int offset, size_t read_size)
53 {
54         struct mtd_info *mtd = get_nand_dev_by_index(nand_curr_device);
55         return nand_read_skip_bad(mtd, offset,
56                                   &read_size, NULL,
57                                   mtd->size,
58                                   (u_char *)bmp_load_addr);
59 }
60 #else
61 static int splash_nand_read_raw(u32 bmp_load_addr, int offset, size_t read_size)
62 {
63         debug("%s: nand support not available\n", __func__);
64         return -ENOSYS;
65 }
66 #endif
67
68 static int splash_storage_read_raw(struct splash_location *location,
69                                u32 bmp_load_addr, size_t read_size)
70 {
71         u32 offset;
72
73         if (!location)
74                 return -EINVAL;
75
76         offset = location->offset;
77         switch (location->storage) {
78         case SPLASH_STORAGE_NAND:
79                 return splash_nand_read_raw(bmp_load_addr, offset, read_size);
80         case SPLASH_STORAGE_SF:
81                 return splash_sf_read_raw(bmp_load_addr, offset, read_size);
82         default:
83                 printf("Unknown splash location\n");
84         }
85
86         return -EINVAL;
87 }
88
89 static int splash_load_raw(struct splash_location *location, u32 bmp_load_addr)
90 {
91         struct bmp_header *bmp_hdr;
92         int res;
93         size_t bmp_size, bmp_header_size = sizeof(struct bmp_header);
94
95         if (bmp_load_addr + bmp_header_size >= gd->start_addr_sp)
96                 goto splash_address_too_high;
97
98         res = splash_storage_read_raw(location, bmp_load_addr, bmp_header_size);
99         if (res < 0)
100                 return res;
101
102         bmp_hdr = (struct bmp_header *)(uintptr_t)bmp_load_addr;
103         bmp_size = le32_to_cpu(bmp_hdr->file_size);
104
105         if (bmp_load_addr + bmp_size >= gd->start_addr_sp)
106                 goto splash_address_too_high;
107
108         return splash_storage_read_raw(location, bmp_load_addr, bmp_size);
109
110 splash_address_too_high:
111         printf("Error: splashimage address too high. Data overwrites U-Boot and/or placed beyond DRAM boundaries.\n");
112
113         return -EFAULT;
114 }
115
116 static int splash_select_fs_dev(struct splash_location *location)
117 {
118         int res;
119
120         switch (location->storage) {
121         case SPLASH_STORAGE_MMC:
122                 res = fs_set_blk_dev("mmc", location->devpart, FS_TYPE_ANY);
123                 break;
124         case SPLASH_STORAGE_USB:
125                 res = fs_set_blk_dev("usb", location->devpart, FS_TYPE_ANY);
126                 break;
127         case SPLASH_STORAGE_SATA:
128                 res = fs_set_blk_dev("sata", location->devpart, FS_TYPE_ANY);
129                 break;
130         case SPLASH_STORAGE_NAND:
131                 if (location->ubivol != NULL)
132                         res = fs_set_blk_dev("ubi", NULL, FS_TYPE_UBIFS);
133                 else
134                         res = -ENODEV;
135                 break;
136         default:
137                 printf("Error: unsupported location storage.\n");
138                 return -ENODEV;
139         }
140
141         if (res)
142                 printf("Error: could not access storage.\n");
143
144         return res;
145 }
146
147 #ifdef CONFIG_USB_STORAGE
148 static int splash_init_usb(void)
149 {
150         int err;
151
152         err = usb_init();
153         if (err)
154                 return err;
155
156 #ifndef CONFIG_DM_USB
157         err = usb_stor_scan(1) < 0 ? -ENODEV : 0;
158 #endif
159
160         return err;
161 }
162 #else
163 static inline int splash_init_usb(void)
164 {
165         printf("Cannot load splash image: no USB support\n");
166         return -ENOSYS;
167 }
168 #endif
169
170 #ifdef CONFIG_SATA
171 static int splash_init_sata(void)
172 {
173         return sata_probe(0);
174 }
175 #else
176 static inline int splash_init_sata(void)
177 {
178         printf("Cannot load splash image: no SATA support\n");
179         return -ENOSYS;
180 }
181 #endif
182
183 static int splash_init_virtio(void)
184 {
185         if (!IS_ENABLED(CONFIG_VIRTIO)) {
186                 printf("Cannot load splash image: no virtio support\n");
187                 return -ENOSYS;
188         } else {
189                 return virtio_init();
190         }
191 }
192
193 #ifdef CONFIG_CMD_UBIFS
194 static int splash_mount_ubifs(struct splash_location *location)
195 {
196         int res;
197         char cmd[32];
198
199         sprintf(cmd, "ubi part %s", location->mtdpart);
200         res = run_command(cmd, 0);
201         if (res)
202                 return res;
203
204         sprintf(cmd, "ubifsmount %s", location->ubivol);
205         res = run_command(cmd, 0);
206
207         return res;
208 }
209
210 static inline int splash_umount_ubifs(void)
211 {
212         return run_command("ubifsumount", 0);
213 }
214 #else
215 static inline int splash_mount_ubifs(struct splash_location *location)
216 {
217         printf("Cannot load splash image: no UBIFS support\n");
218         return -ENOSYS;
219 }
220
221 static inline int splash_umount_ubifs(void)
222 {
223         printf("Cannot unmount UBIFS: no UBIFS support\n");
224         return -ENOSYS;
225 }
226 #endif
227
228 #define SPLASH_SOURCE_DEFAULT_FILE_NAME         "splash.bmp"
229
230 static int splash_load_fs(struct splash_location *location, u32 bmp_load_addr)
231 {
232         int res = 0;
233         loff_t bmp_size;
234         loff_t actread;
235         char *splash_file;
236
237         splash_file = env_get("splashfile");
238         if (!splash_file)
239                 splash_file = SPLASH_SOURCE_DEFAULT_FILE_NAME;
240
241         if (location->storage == SPLASH_STORAGE_USB)
242                 res = splash_init_usb();
243
244         if (location->storage == SPLASH_STORAGE_SATA)
245                 res = splash_init_sata();
246
247         if (location->storage == SPLASH_STORAGE_VIRTIO)
248                 res = splash_init_virtio();
249
250         if (location->ubivol != NULL)
251                 res = splash_mount_ubifs(location);
252
253         if (res)
254                 return res;
255
256         res = splash_select_fs_dev(location);
257         if (res)
258                 goto out;
259
260         res = fs_size(splash_file, &bmp_size);
261         if (res) {
262                 printf("Error (%d): cannot determine file size\n", res);
263                 goto out;
264         }
265
266         if (bmp_load_addr + bmp_size >= gd->start_addr_sp) {
267                 printf("Error: splashimage address too high. Data overwrites U-Boot and/or placed beyond DRAM boundaries.\n");
268                 res = -EFAULT;
269                 goto out;
270         }
271
272         splash_select_fs_dev(location);
273         res = fs_read(splash_file, bmp_load_addr, 0, 0, &actread);
274
275 out:
276         if (location->ubivol != NULL)
277                 splash_umount_ubifs();
278
279         return res;
280 }
281
282 /**
283  * select_splash_location - return the splash location based on board support
284  *                          and env variable "splashsource".
285  *
286  * @locations:          An array of supported splash locations.
287  * @size:               Size of splash_locations array.
288  *
289  * @return: If a null set of splash locations is given, or
290  *          splashsource env variable is set to unsupported value
291  *                      return NULL.
292  *          If splashsource env variable is not defined
293  *                      return the first entry in splash_locations as default.
294  *          If splashsource env variable contains a supported value
295  *                      return the location selected by splashsource.
296  */
297 static struct splash_location *select_splash_location(
298                             struct splash_location *locations, uint size)
299 {
300         int i;
301         char *env_splashsource;
302
303         if (!locations || size == 0)
304                 return NULL;
305
306         env_splashsource = env_get("splashsource");
307         if (env_splashsource == NULL)
308                 return &locations[0];
309
310         for (i = 0; i < size; i++) {
311                 if (!strcmp(locations[i].name, env_splashsource))
312                         return &locations[i];
313         }
314
315         printf("splashsource env variable set to unsupported value\n");
316         return NULL;
317 }
318
319 #ifdef CONFIG_FIT
320 static int splash_load_fit(struct splash_location *location, u32 bmp_load_addr)
321 {
322         int res;
323         int node_offset;
324         const char *splash_file;
325         const void *internal_splash_data;
326         size_t internal_splash_size;
327         int external_splash_addr;
328         int external_splash_size;
329         bool is_splash_external = false;
330         struct image_header *img_header;
331         const u32 *fit_header;
332         u32 fit_size;
333         const size_t header_size = sizeof(struct image_header);
334
335         /* Read in image header */
336         res = splash_storage_read_raw(location, bmp_load_addr, header_size);
337         if (res < 0)
338                 return res;
339
340         img_header = (struct image_header *)bmp_load_addr;
341         if (image_get_magic(img_header) != FDT_MAGIC) {
342                 printf("Could not find FDT magic\n");
343                 return -EINVAL;
344         }
345
346         fit_size = fdt_totalsize(img_header);
347
348         /* Read in entire FIT */
349         fit_header = (const u32 *)(bmp_load_addr + header_size);
350         res = splash_storage_read_raw(location, (u32)fit_header, fit_size);
351         if (res < 0)
352                 return res;
353
354         res = fit_check_format(fit_header, IMAGE_SIZE_INVAL);
355         if (res) {
356                 debug("Could not find valid FIT image\n");
357                 return res;
358         }
359
360         /* Get the splash image node */
361         splash_file = env_get("splashfile");
362         if (!splash_file)
363                 splash_file = SPLASH_SOURCE_DEFAULT_FILE_NAME;
364
365         node_offset = fit_image_get_node(fit_header, splash_file);
366         if (node_offset < 0) {
367                 debug("Could not find splash image '%s' in FIT\n",
368                       splash_file);
369                 return -ENOENT;
370         }
371
372         /* Extract the splash data from FIT */
373         /* 1. Test if splash is in FIT internal data. */
374         if (!fit_image_get_data(fit_header, node_offset, &internal_splash_data, &internal_splash_size))
375                 memmove((void *)bmp_load_addr, internal_splash_data, internal_splash_size);
376         /* 2. Test if splash is in FIT external data with fixed position. */
377         else if (!fit_image_get_data_position(fit_header, node_offset, &external_splash_addr))
378                 is_splash_external = true;
379         /* 3. Test if splash is in FIT external data with offset. */
380         else if (!fit_image_get_data_offset(fit_header, node_offset, &external_splash_addr)) {
381                 /* Align data offset to 4-byte boundary */
382                 fit_size = ALIGN(fdt_totalsize(fit_header), 4);
383                 /* External splash offset means the offset by end of FIT header */
384                 external_splash_addr += location->offset + fit_size;
385                 is_splash_external = true;
386         } else {
387                 printf("Failed to get splash image from FIT\n");
388                 return -ENODATA;
389         }
390
391         if (is_splash_external) {
392                 res = fit_image_get_data_size(fit_header, node_offset, &external_splash_size);
393                 if (res < 0) {
394                         printf("Failed to get size of splash image (err=%d)\n", res);
395                         return res;
396                 }
397
398                 /* Read in the splash data */
399                 location->offset = external_splash_addr;
400                 res = splash_storage_read_raw(location, bmp_load_addr, external_splash_size);
401                 if (res < 0)
402                         return res;
403         }
404
405         return 0;
406 }
407 #endif /* CONFIG_FIT */
408
409 /**
410  * splash_source_load - load splash image from a supported location.
411  *
412  * Select a splash image location based on the value of splashsource environment
413  * variable and the board supported splash source locations, and load a
414  * splashimage to the address pointed to by splashimage environment variable.
415  *
416  * @locations:          An array of supported splash locations.
417  * @size:               Size of splash_locations array.
418  *
419  * @return: 0 on success, negative value on failure.
420  */
421 int splash_source_load(struct splash_location *locations, uint size)
422 {
423         struct splash_location *splash_location;
424         char *env_splashimage_value;
425         u32 bmp_load_addr;
426
427         env_splashimage_value = env_get("splashimage");
428         if (env_splashimage_value == NULL)
429                 return -ENOENT;
430
431         bmp_load_addr = hextoul(env_splashimage_value, 0);
432         if (bmp_load_addr == 0) {
433                 printf("Error: bad splashimage address specified\n");
434                 return -EFAULT;
435         }
436
437         splash_location = select_splash_location(locations, size);
438         if (!splash_location)
439                 return -EINVAL;
440
441         if (splash_location->flags == SPLASH_STORAGE_RAW)
442                 return splash_load_raw(splash_location, bmp_load_addr);
443         else if (splash_location->flags == SPLASH_STORAGE_FS)
444                 return splash_load_fs(splash_location, bmp_load_addr);
445 #ifdef CONFIG_FIT
446         else if (splash_location->flags == SPLASH_STORAGE_FIT)
447                 return splash_load_fit(splash_location, bmp_load_addr);
448 #endif
449         return -EINVAL;
450 }