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