1 /* 2 * (C) Copyright 2014 CompuLab, Ltd. <www.compulab.co.il> 3 * 4 * Authors: Igor Grinberg <grinberg@compulab.co.il> 5 * 6 * SPDX-License-Identifier: GPL-2.0+ 7 */ 8 9 #include <common.h> 10 #include <nand.h> 11 #include <errno.h> 12 #include <splash.h> 13 #include <spi_flash.h> 14 #include <spi.h> 15 #include <bmp_layout.h> 16 17 DECLARE_GLOBAL_DATA_PTR; 18 19 #ifdef CONFIG_SPI_FLASH 20 static struct spi_flash *sf; 21 static int splash_sf_read(u32 bmp_load_addr, int offset, size_t read_size) 22 { 23 if (!sf) { 24 sf = spi_flash_probe(CONFIG_SF_DEFAULT_BUS, 25 CONFIG_SF_DEFAULT_CS, 26 CONFIG_SF_DEFAULT_SPEED, 27 CONFIG_SF_DEFAULT_MODE); 28 if (!sf) 29 return -ENODEV; 30 } 31 32 return spi_flash_read(sf, offset, read_size, (void *)bmp_load_addr); 33 } 34 #else 35 static int splash_sf_read(u32 bmp_load_addr, int offset, size_t read_size) 36 { 37 debug("%s: sf support not available\n", __func__); 38 return -ENOSYS; 39 } 40 #endif 41 42 #ifdef CONFIG_CMD_NAND 43 static int splash_nand_read(u32 bmp_load_addr, int offset, size_t read_size) 44 { 45 return nand_read_skip_bad(&nand_info[nand_curr_device], offset, 46 &read_size, NULL, 47 nand_info[nand_curr_device].size, 48 (u_char *)bmp_load_addr); 49 } 50 #else 51 static int splash_nand_read(u32 bmp_load_addr, int offset, size_t read_size) 52 { 53 debug("%s: nand support not available\n", __func__); 54 return -ENOSYS; 55 } 56 #endif 57 58 static int splash_storage_read(struct splash_location *location, 59 u32 bmp_load_addr, size_t read_size) 60 { 61 u32 offset; 62 63 if (!location) 64 return -EINVAL; 65 66 offset = location->offset; 67 switch (location->storage) { 68 case SPLASH_STORAGE_NAND: 69 return splash_nand_read(bmp_load_addr, offset, read_size); 70 case SPLASH_STORAGE_SF: 71 return splash_sf_read(bmp_load_addr, offset, read_size); 72 default: 73 printf("Unknown splash location\n"); 74 } 75 76 return -EINVAL; 77 } 78 79 static int splash_load_raw(struct splash_location *location, u32 bmp_load_addr) 80 { 81 struct bmp_header *bmp_hdr; 82 int res; 83 size_t bmp_size, bmp_header_size = sizeof(struct bmp_header); 84 85 if (bmp_load_addr + bmp_header_size >= gd->start_addr_sp) 86 goto splash_address_too_high; 87 88 res = splash_storage_read(location, bmp_load_addr, bmp_header_size); 89 if (res < 0) 90 return res; 91 92 bmp_hdr = (struct bmp_header *)bmp_load_addr; 93 bmp_size = le32_to_cpu(bmp_hdr->file_size); 94 95 if (bmp_load_addr + bmp_size >= gd->start_addr_sp) 96 goto splash_address_too_high; 97 98 return splash_storage_read(location, bmp_load_addr, bmp_size); 99 100 splash_address_too_high: 101 printf("Error: splashimage address too high. Data overwrites U-Boot and/or placed beyond DRAM boundaries.\n"); 102 103 return -EFAULT; 104 } 105 106 /** 107 * select_splash_location - return the splash location based on board support 108 * and env variable "splashsource". 109 * 110 * @locations: An array of supported splash locations. 111 * @size: Size of splash_locations array. 112 * 113 * @return: If a null set of splash locations is given, or 114 * splashsource env variable is set to unsupported value 115 * return NULL. 116 * If splashsource env variable is not defined 117 * return the first entry in splash_locations as default. 118 * If splashsource env variable contains a supported value 119 * return the location selected by splashsource. 120 */ 121 static struct splash_location *select_splash_location( 122 struct splash_location *locations, uint size) 123 { 124 int i; 125 char *env_splashsource; 126 127 if (!locations || size == 0) 128 return NULL; 129 130 env_splashsource = getenv("splashsource"); 131 if (env_splashsource == NULL) 132 return &locations[0]; 133 134 for (i = 0; i < size; i++) { 135 if (!strcmp(locations[i].name, env_splashsource)) 136 return &locations[i]; 137 } 138 139 printf("splashsource env variable set to unsupported value\n"); 140 return NULL; 141 } 142 143 /** 144 * splash_source_load - load splash image from a supported location. 145 * 146 * Select a splash image location based on the value of splashsource environment 147 * variable and the board supported splash source locations, and load a 148 * splashimage to the address pointed to by splashimage environment variable. 149 * 150 * @locations: An array of supported splash locations. 151 * @size: Size of splash_locations array. 152 * 153 * @return: 0 on success, negative value on failure. 154 */ 155 int splash_source_load(struct splash_location *locations, uint size) 156 { 157 struct splash_location *splash_location; 158 char *env_splashimage_value; 159 u32 bmp_load_addr; 160 161 env_splashimage_value = getenv("splashimage"); 162 if (env_splashimage_value == NULL) 163 return -ENOENT; 164 165 bmp_load_addr = simple_strtoul(env_splashimage_value, 0, 16); 166 if (bmp_load_addr == 0) { 167 printf("Error: bad splashimage address specified\n"); 168 return -EFAULT; 169 } 170 171 splash_location = select_splash_location(locations, size); 172 if (!splash_location) 173 return -EINVAL; 174 175 return splash_load_raw(splash_location, bmp_load_addr); 176 } 177