xref: /openbmc/u-boot/common/splash_source.c (revision e8f80a5a)
1*83d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
2f82eb2faSNikita Kiryanov /*
3f82eb2faSNikita Kiryanov  * (C) Copyright 2014 CompuLab, Ltd. <www.compulab.co.il>
4f82eb2faSNikita Kiryanov  *
5f82eb2faSNikita Kiryanov  * Authors: Igor Grinberg <grinberg@compulab.co.il>
6f82eb2faSNikita Kiryanov  */
7f82eb2faSNikita Kiryanov 
8f82eb2faSNikita Kiryanov #include <common.h>
9f82eb2faSNikita Kiryanov #include <bmp_layout.h>
107583f1f5Stomas.melin@vaisala.com #include <errno.h>
11870dd309SNikita Kiryanov #include <fs.h>
12db1b79b8Stomas.melin@vaisala.com #include <fdt_support.h>
137583f1f5Stomas.melin@vaisala.com #include <image.h>
147583f1f5Stomas.melin@vaisala.com #include <nand.h>
157583f1f5Stomas.melin@vaisala.com #include <sata.h>
167583f1f5Stomas.melin@vaisala.com #include <spi.h>
177583f1f5Stomas.melin@vaisala.com #include <spi_flash.h>
187583f1f5Stomas.melin@vaisala.com #include <splash.h>
197583f1f5Stomas.melin@vaisala.com #include <usb.h>
20f82eb2faSNikita Kiryanov 
21f82eb2faSNikita Kiryanov DECLARE_GLOBAL_DATA_PTR;
22f82eb2faSNikita Kiryanov 
23f82eb2faSNikita Kiryanov #ifdef CONFIG_SPI_FLASH
24f82eb2faSNikita Kiryanov static struct spi_flash *sf;
splash_sf_read_raw(u32 bmp_load_addr,int offset,size_t read_size)25bcbb6448SNikita Kiryanov static int splash_sf_read_raw(u32 bmp_load_addr, int offset, size_t read_size)
26f82eb2faSNikita Kiryanov {
27f82eb2faSNikita Kiryanov 	if (!sf) {
28f82eb2faSNikita Kiryanov 		sf = spi_flash_probe(CONFIG_SF_DEFAULT_BUS,
29f82eb2faSNikita Kiryanov 				     CONFIG_SF_DEFAULT_CS,
30f82eb2faSNikita Kiryanov 				     CONFIG_SF_DEFAULT_SPEED,
31f82eb2faSNikita Kiryanov 				     CONFIG_SF_DEFAULT_MODE);
32f82eb2faSNikita Kiryanov 		if (!sf)
33f82eb2faSNikita Kiryanov 			return -ENODEV;
34f82eb2faSNikita Kiryanov 	}
35f82eb2faSNikita Kiryanov 
36f82eb2faSNikita Kiryanov 	return spi_flash_read(sf, offset, read_size, (void *)bmp_load_addr);
37f82eb2faSNikita Kiryanov }
38f82eb2faSNikita Kiryanov #else
splash_sf_read_raw(u32 bmp_load_addr,int offset,size_t read_size)39bcbb6448SNikita Kiryanov static int splash_sf_read_raw(u32 bmp_load_addr, int offset, size_t read_size)
40f82eb2faSNikita Kiryanov {
41f82eb2faSNikita Kiryanov 	debug("%s: sf support not available\n", __func__);
42f82eb2faSNikita Kiryanov 	return -ENOSYS;
43f82eb2faSNikita Kiryanov }
44f82eb2faSNikita Kiryanov #endif
45f82eb2faSNikita Kiryanov 
46f82eb2faSNikita Kiryanov #ifdef CONFIG_CMD_NAND
splash_nand_read_raw(u32 bmp_load_addr,int offset,size_t read_size)47bcbb6448SNikita Kiryanov static int splash_nand_read_raw(u32 bmp_load_addr, int offset, size_t read_size)
48f82eb2faSNikita Kiryanov {
49edba8cc4SGrygorii Strashko 	struct mtd_info *mtd = get_nand_dev_by_index(nand_curr_device);
50edba8cc4SGrygorii Strashko 	return nand_read_skip_bad(mtd, offset,
51f82eb2faSNikita Kiryanov 				  &read_size, NULL,
52edba8cc4SGrygorii Strashko 				  mtd->size,
53f82eb2faSNikita Kiryanov 				  (u_char *)bmp_load_addr);
54f82eb2faSNikita Kiryanov }
55f82eb2faSNikita Kiryanov #else
splash_nand_read_raw(u32 bmp_load_addr,int offset,size_t read_size)56bcbb6448SNikita Kiryanov static int splash_nand_read_raw(u32 bmp_load_addr, int offset, size_t read_size)
57f82eb2faSNikita Kiryanov {
58f82eb2faSNikita Kiryanov 	debug("%s: nand support not available\n", __func__);
59f82eb2faSNikita Kiryanov 	return -ENOSYS;
60f82eb2faSNikita Kiryanov }
61f82eb2faSNikita Kiryanov #endif
62f82eb2faSNikita Kiryanov 
splash_storage_read_raw(struct splash_location * location,u32 bmp_load_addr,size_t read_size)63bcbb6448SNikita Kiryanov static int splash_storage_read_raw(struct splash_location *location,
64f82eb2faSNikita Kiryanov 			       u32 bmp_load_addr, size_t read_size)
65f82eb2faSNikita Kiryanov {
66f82eb2faSNikita Kiryanov 	u32 offset;
67f82eb2faSNikita Kiryanov 
68f82eb2faSNikita Kiryanov 	if (!location)
69f82eb2faSNikita Kiryanov 		return -EINVAL;
70f82eb2faSNikita Kiryanov 
71f82eb2faSNikita Kiryanov 	offset = location->offset;
72f82eb2faSNikita Kiryanov 	switch (location->storage) {
73f82eb2faSNikita Kiryanov 	case SPLASH_STORAGE_NAND:
74bcbb6448SNikita Kiryanov 		return splash_nand_read_raw(bmp_load_addr, offset, read_size);
75f82eb2faSNikita Kiryanov 	case SPLASH_STORAGE_SF:
76bcbb6448SNikita Kiryanov 		return splash_sf_read_raw(bmp_load_addr, offset, read_size);
77f82eb2faSNikita Kiryanov 	default:
78f82eb2faSNikita Kiryanov 		printf("Unknown splash location\n");
79f82eb2faSNikita Kiryanov 	}
80f82eb2faSNikita Kiryanov 
81f82eb2faSNikita Kiryanov 	return -EINVAL;
82f82eb2faSNikita Kiryanov }
83f82eb2faSNikita Kiryanov 
splash_load_raw(struct splash_location * location,u32 bmp_load_addr)84f82eb2faSNikita Kiryanov static int splash_load_raw(struct splash_location *location, u32 bmp_load_addr)
85f82eb2faSNikita Kiryanov {
86f82eb2faSNikita Kiryanov 	struct bmp_header *bmp_hdr;
87f82eb2faSNikita Kiryanov 	int res;
88f82eb2faSNikita Kiryanov 	size_t bmp_size, bmp_header_size = sizeof(struct bmp_header);
89f82eb2faSNikita Kiryanov 
90f82eb2faSNikita Kiryanov 	if (bmp_load_addr + bmp_header_size >= gd->start_addr_sp)
91f82eb2faSNikita Kiryanov 		goto splash_address_too_high;
92f82eb2faSNikita Kiryanov 
93bcbb6448SNikita Kiryanov 	res = splash_storage_read_raw(location, bmp_load_addr, bmp_header_size);
94f82eb2faSNikita Kiryanov 	if (res < 0)
95f82eb2faSNikita Kiryanov 		return res;
96f82eb2faSNikita Kiryanov 
97f82eb2faSNikita Kiryanov 	bmp_hdr = (struct bmp_header *)bmp_load_addr;
98f82eb2faSNikita Kiryanov 	bmp_size = le32_to_cpu(bmp_hdr->file_size);
99f82eb2faSNikita Kiryanov 
100f82eb2faSNikita Kiryanov 	if (bmp_load_addr + bmp_size >= gd->start_addr_sp)
101f82eb2faSNikita Kiryanov 		goto splash_address_too_high;
102f82eb2faSNikita Kiryanov 
103bcbb6448SNikita Kiryanov 	return splash_storage_read_raw(location, bmp_load_addr, bmp_size);
104f82eb2faSNikita Kiryanov 
105f82eb2faSNikita Kiryanov splash_address_too_high:
106f82eb2faSNikita Kiryanov 	printf("Error: splashimage address too high. Data overwrites U-Boot and/or placed beyond DRAM boundaries.\n");
107f82eb2faSNikita Kiryanov 
108f82eb2faSNikita Kiryanov 	return -EFAULT;
109f82eb2faSNikita Kiryanov }
110f82eb2faSNikita Kiryanov 
splash_select_fs_dev(struct splash_location * location)111870dd309SNikita Kiryanov static int splash_select_fs_dev(struct splash_location *location)
112870dd309SNikita Kiryanov {
113870dd309SNikita Kiryanov 	int res;
114870dd309SNikita Kiryanov 
115870dd309SNikita Kiryanov 	switch (location->storage) {
116870dd309SNikita Kiryanov 	case SPLASH_STORAGE_MMC:
117870dd309SNikita Kiryanov 		res = fs_set_blk_dev("mmc", location->devpart, FS_TYPE_ANY);
118870dd309SNikita Kiryanov 		break;
1199bb4e947SNikita Kiryanov 	case SPLASH_STORAGE_USB:
1209bb4e947SNikita Kiryanov 		res = fs_set_blk_dev("usb", location->devpart, FS_TYPE_ANY);
1219bb4e947SNikita Kiryanov 		break;
12250c2d2e1SNikita Kiryanov 	case SPLASH_STORAGE_SATA:
12350c2d2e1SNikita Kiryanov 		res = fs_set_blk_dev("sata", location->devpart, FS_TYPE_ANY);
12450c2d2e1SNikita Kiryanov 		break;
1251cb075c6SEran Matityahu 	case SPLASH_STORAGE_NAND:
1261cb075c6SEran Matityahu 		if (location->ubivol != NULL)
1271cb075c6SEran Matityahu 			res = fs_set_blk_dev("ubi", NULL, FS_TYPE_UBIFS);
1281cb075c6SEran Matityahu 		else
1291cb075c6SEran Matityahu 			res = -ENODEV;
1301cb075c6SEran Matityahu 		break;
131870dd309SNikita Kiryanov 	default:
132870dd309SNikita Kiryanov 		printf("Error: unsupported location storage.\n");
133870dd309SNikita Kiryanov 		return -ENODEV;
134870dd309SNikita Kiryanov 	}
135870dd309SNikita Kiryanov 
136870dd309SNikita Kiryanov 	if (res)
137870dd309SNikita Kiryanov 		printf("Error: could not access storage.\n");
138870dd309SNikita Kiryanov 
139870dd309SNikita Kiryanov 	return res;
140870dd309SNikita Kiryanov }
141870dd309SNikita Kiryanov 
1429bb4e947SNikita Kiryanov #ifdef CONFIG_USB_STORAGE
splash_init_usb(void)1439bb4e947SNikita Kiryanov static int splash_init_usb(void)
1449bb4e947SNikita Kiryanov {
1459bb4e947SNikita Kiryanov 	int err;
1469bb4e947SNikita Kiryanov 
1479bb4e947SNikita Kiryanov 	err = usb_init();
1489bb4e947SNikita Kiryanov 	if (err)
1499bb4e947SNikita Kiryanov 		return err;
1509bb4e947SNikita Kiryanov 
151d7b60fbfSAlexey Brodkin #ifndef CONFIG_DM_USB
152d7b60fbfSAlexey Brodkin 	err = usb_stor_scan(1) < 0 ? -ENODEV : 0;
153d7b60fbfSAlexey Brodkin #endif
154d7b60fbfSAlexey Brodkin 
155d7b60fbfSAlexey Brodkin 	return err;
1569bb4e947SNikita Kiryanov }
1579bb4e947SNikita Kiryanov #else
splash_init_usb(void)1589bb4e947SNikita Kiryanov static inline int splash_init_usb(void)
1599bb4e947SNikita Kiryanov {
1609bb4e947SNikita Kiryanov 	printf("Cannot load splash image: no USB support\n");
1619bb4e947SNikita Kiryanov 	return -ENOSYS;
1629bb4e947SNikita Kiryanov }
1639bb4e947SNikita Kiryanov #endif
1649bb4e947SNikita Kiryanov 
16510e40d54SSimon Glass #ifdef CONFIG_SATA
splash_init_sata(void)16650c2d2e1SNikita Kiryanov static int splash_init_sata(void)
16750c2d2e1SNikita Kiryanov {
168f19f1ecbSSimon Glass 	return sata_probe(0);
16950c2d2e1SNikita Kiryanov }
17050c2d2e1SNikita Kiryanov #else
splash_init_sata(void)17150c2d2e1SNikita Kiryanov static inline int splash_init_sata(void)
17250c2d2e1SNikita Kiryanov {
17350c2d2e1SNikita Kiryanov 	printf("Cannot load splash image: no SATA support\n");
17450c2d2e1SNikita Kiryanov 	return -ENOSYS;
17550c2d2e1SNikita Kiryanov }
17650c2d2e1SNikita Kiryanov #endif
17750c2d2e1SNikita Kiryanov 
1781cb075c6SEran Matityahu #ifdef CONFIG_CMD_UBIFS
splash_mount_ubifs(struct splash_location * location)1791cb075c6SEran Matityahu static int splash_mount_ubifs(struct splash_location *location)
1801cb075c6SEran Matityahu {
1811cb075c6SEran Matityahu 	int res;
1821cb075c6SEran Matityahu 	char cmd[32];
1831cb075c6SEran Matityahu 
1841cb075c6SEran Matityahu 	sprintf(cmd, "ubi part %s", location->mtdpart);
1851cb075c6SEran Matityahu 	res = run_command(cmd, 0);
1861cb075c6SEran Matityahu 	if (res)
1871cb075c6SEran Matityahu 		return res;
1881cb075c6SEran Matityahu 
1891cb075c6SEran Matityahu 	sprintf(cmd, "ubifsmount %s", location->ubivol);
1901cb075c6SEran Matityahu 	res = run_command(cmd, 0);
1911cb075c6SEran Matityahu 
1921cb075c6SEran Matityahu 	return res;
1931cb075c6SEran Matityahu }
1941cb075c6SEran Matityahu 
splash_umount_ubifs(void)1951cb075c6SEran Matityahu static inline int splash_umount_ubifs(void)
1961cb075c6SEran Matityahu {
1971cb075c6SEran Matityahu 	return run_command("ubifsumount", 0);
1981cb075c6SEran Matityahu }
1991cb075c6SEran Matityahu #else
splash_mount_ubifs(struct splash_location * location)2001cb075c6SEran Matityahu static inline int splash_mount_ubifs(struct splash_location *location)
2011cb075c6SEran Matityahu {
2021cb075c6SEran Matityahu 	printf("Cannot load splash image: no UBIFS support\n");
2031cb075c6SEran Matityahu 	return -ENOSYS;
2041cb075c6SEran Matityahu }
2051cb075c6SEran Matityahu 
splash_umount_ubifs(void)2061cb075c6SEran Matityahu static inline int splash_umount_ubifs(void)
2071cb075c6SEran Matityahu {
2081cb075c6SEran Matityahu 	printf("Cannot unmount UBIFS: no UBIFS support\n");
2091cb075c6SEran Matityahu 	return -ENOSYS;
2101cb075c6SEran Matityahu }
2111cb075c6SEran Matityahu #endif
2121cb075c6SEran Matityahu 
213870dd309SNikita Kiryanov #define SPLASH_SOURCE_DEFAULT_FILE_NAME		"splash.bmp"
214870dd309SNikita Kiryanov 
splash_load_fs(struct splash_location * location,u32 bmp_load_addr)215870dd309SNikita Kiryanov static int splash_load_fs(struct splash_location *location, u32 bmp_load_addr)
216870dd309SNikita Kiryanov {
2179bb4e947SNikita Kiryanov 	int res = 0;
218870dd309SNikita Kiryanov 	loff_t bmp_size;
2193cc6e707SJonathan Golder 	loff_t actread;
220870dd309SNikita Kiryanov 	char *splash_file;
221870dd309SNikita Kiryanov 
22200caae6dSSimon Glass 	splash_file = env_get("splashfile");
223870dd309SNikita Kiryanov 	if (!splash_file)
224870dd309SNikita Kiryanov 		splash_file = SPLASH_SOURCE_DEFAULT_FILE_NAME;
225870dd309SNikita Kiryanov 
2269bb4e947SNikita Kiryanov 	if (location->storage == SPLASH_STORAGE_USB)
2279bb4e947SNikita Kiryanov 		res = splash_init_usb();
2289bb4e947SNikita Kiryanov 
22950c2d2e1SNikita Kiryanov 	if (location->storage == SPLASH_STORAGE_SATA)
23050c2d2e1SNikita Kiryanov 		res = splash_init_sata();
23150c2d2e1SNikita Kiryanov 
2321cb075c6SEran Matityahu 	if (location->ubivol != NULL)
2331cb075c6SEran Matityahu 		res = splash_mount_ubifs(location);
2341cb075c6SEran Matityahu 
2359bb4e947SNikita Kiryanov 	if (res)
2369bb4e947SNikita Kiryanov 		return res;
2379bb4e947SNikita Kiryanov 
238870dd309SNikita Kiryanov 	res = splash_select_fs_dev(location);
239870dd309SNikita Kiryanov 	if (res)
2401cb075c6SEran Matityahu 		goto out;
241870dd309SNikita Kiryanov 
242870dd309SNikita Kiryanov 	res = fs_size(splash_file, &bmp_size);
243870dd309SNikita Kiryanov 	if (res) {
244870dd309SNikita Kiryanov 		printf("Error (%d): cannot determine file size\n", res);
2451cb075c6SEran Matityahu 		goto out;
246870dd309SNikita Kiryanov 	}
247870dd309SNikita Kiryanov 
248870dd309SNikita Kiryanov 	if (bmp_load_addr + bmp_size >= gd->start_addr_sp) {
249870dd309SNikita Kiryanov 		printf("Error: splashimage address too high. Data overwrites U-Boot and/or placed beyond DRAM boundaries.\n");
2501cb075c6SEran Matityahu 		res = -EFAULT;
2511cb075c6SEran Matityahu 		goto out;
252870dd309SNikita Kiryanov 	}
253870dd309SNikita Kiryanov 
254870dd309SNikita Kiryanov 	splash_select_fs_dev(location);
2553cc6e707SJonathan Golder 	res = fs_read(splash_file, bmp_load_addr, 0, 0, &actread);
2561cb075c6SEran Matityahu 
2571cb075c6SEran Matityahu out:
2581cb075c6SEran Matityahu 	if (location->ubivol != NULL)
2591cb075c6SEran Matityahu 		splash_umount_ubifs();
2601cb075c6SEran Matityahu 
2611cb075c6SEran Matityahu 	return res;
262870dd309SNikita Kiryanov }
263870dd309SNikita Kiryanov 
264f82eb2faSNikita Kiryanov /**
265f82eb2faSNikita Kiryanov  * select_splash_location - return the splash location based on board support
266f82eb2faSNikita Kiryanov  *			    and env variable "splashsource".
267f82eb2faSNikita Kiryanov  *
268f82eb2faSNikita Kiryanov  * @locations:		An array of supported splash locations.
269f82eb2faSNikita Kiryanov  * @size:		Size of splash_locations array.
270f82eb2faSNikita Kiryanov  *
271f82eb2faSNikita Kiryanov  * @return: If a null set of splash locations is given, or
272f82eb2faSNikita Kiryanov  *	    splashsource env variable is set to unsupported value
273f82eb2faSNikita Kiryanov  *			return NULL.
274f82eb2faSNikita Kiryanov  *	    If splashsource env variable is not defined
275f82eb2faSNikita Kiryanov  *			return the first entry in splash_locations as default.
276f82eb2faSNikita Kiryanov  *	    If splashsource env variable contains a supported value
277f82eb2faSNikita Kiryanov  *			return the location selected by splashsource.
278f82eb2faSNikita Kiryanov  */
select_splash_location(struct splash_location * locations,uint size)279f82eb2faSNikita Kiryanov static struct splash_location *select_splash_location(
280f82eb2faSNikita Kiryanov 			    struct splash_location *locations, uint size)
281f82eb2faSNikita Kiryanov {
282f82eb2faSNikita Kiryanov 	int i;
283f82eb2faSNikita Kiryanov 	char *env_splashsource;
284f82eb2faSNikita Kiryanov 
285f82eb2faSNikita Kiryanov 	if (!locations || size == 0)
286f82eb2faSNikita Kiryanov 		return NULL;
287f82eb2faSNikita Kiryanov 
28800caae6dSSimon Glass 	env_splashsource = env_get("splashsource");
289f82eb2faSNikita Kiryanov 	if (env_splashsource == NULL)
290f82eb2faSNikita Kiryanov 		return &locations[0];
291f82eb2faSNikita Kiryanov 
292f82eb2faSNikita Kiryanov 	for (i = 0; i < size; i++) {
293f82eb2faSNikita Kiryanov 		if (!strcmp(locations[i].name, env_splashsource))
294f82eb2faSNikita Kiryanov 			return &locations[i];
295f82eb2faSNikita Kiryanov 	}
296f82eb2faSNikita Kiryanov 
297f82eb2faSNikita Kiryanov 	printf("splashsource env variable set to unsupported value\n");
298f82eb2faSNikita Kiryanov 	return NULL;
299f82eb2faSNikita Kiryanov }
300f82eb2faSNikita Kiryanov 
301db1b79b8Stomas.melin@vaisala.com #ifdef CONFIG_FIT
splash_load_fit(struct splash_location * location,u32 bmp_load_addr)302db1b79b8Stomas.melin@vaisala.com static int splash_load_fit(struct splash_location *location, u32 bmp_load_addr)
303db1b79b8Stomas.melin@vaisala.com {
304db1b79b8Stomas.melin@vaisala.com 	int res;
305db1b79b8Stomas.melin@vaisala.com 	int node_offset;
306db1b79b8Stomas.melin@vaisala.com 	int splash_offset;
307db1b79b8Stomas.melin@vaisala.com 	int splash_size;
308db1b79b8Stomas.melin@vaisala.com 	struct image_header *img_header;
309db1b79b8Stomas.melin@vaisala.com 	const u32 *fit_header;
310db1b79b8Stomas.melin@vaisala.com 	u32 fit_size;
311db1b79b8Stomas.melin@vaisala.com 	const size_t header_size = sizeof(struct image_header);
312db1b79b8Stomas.melin@vaisala.com 
313db1b79b8Stomas.melin@vaisala.com 	/* Read in image header */
314db1b79b8Stomas.melin@vaisala.com 	res = splash_storage_read_raw(location, bmp_load_addr, header_size);
315db1b79b8Stomas.melin@vaisala.com 	if (res < 0)
316db1b79b8Stomas.melin@vaisala.com 		return res;
317db1b79b8Stomas.melin@vaisala.com 
318db1b79b8Stomas.melin@vaisala.com 	img_header = (struct image_header *)bmp_load_addr;
319a7126edcSNiko Mauno 	if (image_get_magic(img_header) != FDT_MAGIC) {
320a7126edcSNiko Mauno 		printf("Could not find FDT magic\n");
321a7126edcSNiko Mauno 		return -EINVAL;
322a7126edcSNiko Mauno 	}
323a7126edcSNiko Mauno 
324db1b79b8Stomas.melin@vaisala.com 	fit_size = fdt_totalsize(img_header);
325db1b79b8Stomas.melin@vaisala.com 
326db1b79b8Stomas.melin@vaisala.com 	/* Read in entire FIT */
327db1b79b8Stomas.melin@vaisala.com 	fit_header = (const u32 *)(bmp_load_addr + header_size);
328db1b79b8Stomas.melin@vaisala.com 	res = splash_storage_read_raw(location, (u32)fit_header, fit_size);
329db1b79b8Stomas.melin@vaisala.com 	if (res < 0)
330db1b79b8Stomas.melin@vaisala.com 		return res;
331db1b79b8Stomas.melin@vaisala.com 
332db1b79b8Stomas.melin@vaisala.com 	res = fit_check_format(fit_header);
333db1b79b8Stomas.melin@vaisala.com 	if (!res) {
334db1b79b8Stomas.melin@vaisala.com 		debug("Could not find valid FIT image\n");
335db1b79b8Stomas.melin@vaisala.com 		return -EINVAL;
336db1b79b8Stomas.melin@vaisala.com 	}
337db1b79b8Stomas.melin@vaisala.com 
338db1b79b8Stomas.melin@vaisala.com 	node_offset = fit_image_get_node(fit_header, location->name);
339db1b79b8Stomas.melin@vaisala.com 	if (node_offset < 0) {
340db1b79b8Stomas.melin@vaisala.com 		debug("Could not find splash image '%s' in FIT\n",
341db1b79b8Stomas.melin@vaisala.com 		      location->name);
342db1b79b8Stomas.melin@vaisala.com 		return -ENOENT;
343db1b79b8Stomas.melin@vaisala.com 	}
344db1b79b8Stomas.melin@vaisala.com 
345db1b79b8Stomas.melin@vaisala.com 	res = fit_image_get_data_offset(fit_header, node_offset,
346db1b79b8Stomas.melin@vaisala.com 					&splash_offset);
347db1b79b8Stomas.melin@vaisala.com 	if (res < 0) {
348db1b79b8Stomas.melin@vaisala.com 		printf("Failed to load splash image (err=%d)\n", res);
349db1b79b8Stomas.melin@vaisala.com 		return res;
350db1b79b8Stomas.melin@vaisala.com 	}
351db1b79b8Stomas.melin@vaisala.com 
352db1b79b8Stomas.melin@vaisala.com 	res = fit_image_get_data_size(fit_header, node_offset, &splash_size);
353db1b79b8Stomas.melin@vaisala.com 	if (res < 0) {
354db1b79b8Stomas.melin@vaisala.com 		printf("Failed to load splash image (err=%d)\n", res);
355db1b79b8Stomas.melin@vaisala.com 		return res;
356db1b79b8Stomas.melin@vaisala.com 	}
357db1b79b8Stomas.melin@vaisala.com 
358db1b79b8Stomas.melin@vaisala.com 	/* Align data offset to 4-byte boundrary */
359db1b79b8Stomas.melin@vaisala.com 	fit_size = fdt_totalsize(fit_header);
360db1b79b8Stomas.melin@vaisala.com 	fit_size = (fit_size + 3) & ~3;
361db1b79b8Stomas.melin@vaisala.com 
362db1b79b8Stomas.melin@vaisala.com 	/* Read in the splash data */
363db1b79b8Stomas.melin@vaisala.com 	location->offset = (location->offset + fit_size + splash_offset);
364db1b79b8Stomas.melin@vaisala.com 	res = splash_storage_read_raw(location, bmp_load_addr , splash_size);
365db1b79b8Stomas.melin@vaisala.com 	if (res < 0)
366db1b79b8Stomas.melin@vaisala.com 		return res;
367db1b79b8Stomas.melin@vaisala.com 
368db1b79b8Stomas.melin@vaisala.com 	return 0;
369db1b79b8Stomas.melin@vaisala.com }
370db1b79b8Stomas.melin@vaisala.com #endif /* CONFIG_FIT */
371db1b79b8Stomas.melin@vaisala.com 
372f82eb2faSNikita Kiryanov /**
373f82eb2faSNikita Kiryanov  * splash_source_load - load splash image from a supported location.
374f82eb2faSNikita Kiryanov  *
375f82eb2faSNikita Kiryanov  * Select a splash image location based on the value of splashsource environment
376f82eb2faSNikita Kiryanov  * variable and the board supported splash source locations, and load a
377f82eb2faSNikita Kiryanov  * splashimage to the address pointed to by splashimage environment variable.
378f82eb2faSNikita Kiryanov  *
379f82eb2faSNikita Kiryanov  * @locations:		An array of supported splash locations.
380f82eb2faSNikita Kiryanov  * @size:		Size of splash_locations array.
381f82eb2faSNikita Kiryanov  *
382f82eb2faSNikita Kiryanov  * @return: 0 on success, negative value on failure.
383f82eb2faSNikita Kiryanov  */
splash_source_load(struct splash_location * locations,uint size)384f82eb2faSNikita Kiryanov int splash_source_load(struct splash_location *locations, uint size)
385f82eb2faSNikita Kiryanov {
386f82eb2faSNikita Kiryanov 	struct splash_location *splash_location;
387f82eb2faSNikita Kiryanov 	char *env_splashimage_value;
388f82eb2faSNikita Kiryanov 	u32 bmp_load_addr;
389f82eb2faSNikita Kiryanov 
39000caae6dSSimon Glass 	env_splashimage_value = env_get("splashimage");
391f82eb2faSNikita Kiryanov 	if (env_splashimage_value == NULL)
392f82eb2faSNikita Kiryanov 		return -ENOENT;
393f82eb2faSNikita Kiryanov 
394f82eb2faSNikita Kiryanov 	bmp_load_addr = simple_strtoul(env_splashimage_value, 0, 16);
395f82eb2faSNikita Kiryanov 	if (bmp_load_addr == 0) {
396f82eb2faSNikita Kiryanov 		printf("Error: bad splashimage address specified\n");
397f82eb2faSNikita Kiryanov 		return -EFAULT;
398f82eb2faSNikita Kiryanov 	}
399f82eb2faSNikita Kiryanov 
400f82eb2faSNikita Kiryanov 	splash_location = select_splash_location(locations, size);
401f82eb2faSNikita Kiryanov 	if (!splash_location)
402f82eb2faSNikita Kiryanov 		return -EINVAL;
403f82eb2faSNikita Kiryanov 
4043b593f90Stomas.melin@vaisala.com 	if (splash_location->flags == SPLASH_STORAGE_RAW)
405f82eb2faSNikita Kiryanov 		return splash_load_raw(splash_location, bmp_load_addr);
4063b593f90Stomas.melin@vaisala.com 	else if (splash_location->flags == SPLASH_STORAGE_FS)
407870dd309SNikita Kiryanov 		return splash_load_fs(splash_location, bmp_load_addr);
408db1b79b8Stomas.melin@vaisala.com #ifdef CONFIG_FIT
409db1b79b8Stomas.melin@vaisala.com 	else if (splash_location->flags == SPLASH_STORAGE_FIT)
410db1b79b8Stomas.melin@vaisala.com 		return splash_load_fit(splash_location, bmp_load_addr);
411db1b79b8Stomas.melin@vaisala.com #endif
412870dd309SNikita Kiryanov 	return -EINVAL;
413f82eb2faSNikita Kiryanov }
414