1 /* 2 * (C) Copyright 2010 3 * Texas Instruments, <www.ti.com> 4 * 5 * Aneesh V <aneesh@ti.com> 6 * 7 * SPDX-License-Identifier: GPL-2.0+ 8 */ 9 #include <common.h> 10 #include <dm.h> 11 #include <spl.h> 12 #include <linux/compiler.h> 13 #include <errno.h> 14 #include <asm/u-boot.h> 15 #include <errno.h> 16 #include <mmc.h> 17 #include <image.h> 18 19 DECLARE_GLOBAL_DATA_PTR; 20 21 static int mmc_load_legacy(struct mmc *mmc, ulong sector, 22 struct image_header *header) 23 { 24 u32 image_size_sectors; 25 unsigned long count; 26 int ret; 27 28 ret = spl_parse_image_header(header); 29 if (ret) 30 return ret; 31 32 /* convert size to sectors - round up */ 33 image_size_sectors = (spl_image.size + mmc->read_bl_len - 1) / 34 mmc->read_bl_len; 35 36 /* Read the header too to avoid extra memcpy */ 37 count = blk_dread(mmc_get_blk_desc(mmc), sector, image_size_sectors, 38 (void *)(ulong)spl_image.load_addr); 39 debug("read %x sectors to %x\n", image_size_sectors, 40 spl_image.load_addr); 41 if (count != image_size_sectors) 42 return -EIO; 43 44 return 0; 45 } 46 47 static ulong h_spl_load_read(struct spl_load_info *load, ulong sector, 48 ulong count, void *buf) 49 { 50 struct mmc *mmc = load->dev; 51 52 return blk_dread(mmc_get_blk_desc(mmc), sector, count, buf); 53 } 54 55 static int mmc_load_image_raw_sector(struct mmc *mmc, unsigned long sector) 56 { 57 unsigned long count; 58 struct image_header *header; 59 int ret = 0; 60 61 header = (struct image_header *)(CONFIG_SYS_TEXT_BASE - 62 sizeof(struct image_header)); 63 64 /* read image header to find the image size & load address */ 65 count = blk_dread(mmc_get_blk_desc(mmc), sector, 1, header); 66 debug("hdr read sector %lx, count=%lu\n", sector, count); 67 if (count == 0) { 68 ret = -EIO; 69 goto end; 70 } 71 72 if (IS_ENABLED(CONFIG_SPL_LOAD_FIT) && 73 image_get_magic(header) == FDT_MAGIC) { 74 struct spl_load_info load; 75 76 debug("Found FIT\n"); 77 load.dev = mmc; 78 load.priv = NULL; 79 load.filename = NULL; 80 load.bl_len = mmc->read_bl_len; 81 load.read = h_spl_load_read; 82 ret = spl_load_simple_fit(&load, sector, header); 83 } else { 84 ret = mmc_load_legacy(mmc, sector, header); 85 } 86 87 end: 88 if (ret) { 89 #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT 90 puts("mmc_load_image_raw_sector: mmc block read error\n"); 91 #endif 92 return -1; 93 } 94 95 return 0; 96 } 97 98 int spl_mmc_get_device_index(u32 boot_device) 99 { 100 switch (boot_device) { 101 case BOOT_DEVICE_MMC1: 102 return 0; 103 case BOOT_DEVICE_MMC2: 104 case BOOT_DEVICE_MMC2_2: 105 return 1; 106 } 107 108 #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT 109 printf("spl: unsupported mmc boot device.\n"); 110 #endif 111 112 return -ENODEV; 113 } 114 115 static int spl_mmc_find_device(struct mmc **mmcp, u32 boot_device) 116 { 117 #ifdef CONFIG_DM_MMC 118 struct udevice *dev; 119 #endif 120 int err, mmc_dev; 121 122 mmc_dev = spl_mmc_get_device_index(boot_device); 123 if (mmc_dev < 0) 124 return mmc_dev; 125 126 err = mmc_initialize(NULL); 127 if (err) { 128 #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT 129 printf("spl: could not initialize mmc. error: %d\n", err); 130 #endif 131 return err; 132 } 133 134 #ifdef CONFIG_DM_MMC 135 err = uclass_get_device(UCLASS_MMC, mmc_dev, &dev); 136 if (!err) 137 *mmcp = mmc_get_mmc_dev(dev); 138 #else 139 *mmcp = find_mmc_device(mmc_dev); 140 err = *mmcp ? 0 : -ENODEV; 141 #endif 142 if (err) { 143 #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT 144 printf("spl: could not find mmc device. error: %d\n", err); 145 #endif 146 return err; 147 } 148 149 return 0; 150 } 151 152 #ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION 153 static int mmc_load_image_raw_partition(struct mmc *mmc, int partition) 154 { 155 disk_partition_t info; 156 int err; 157 158 err = part_get_info(&mmc->block_dev, partition, &info); 159 if (err) { 160 #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT 161 puts("spl: partition error\n"); 162 #endif 163 return -1; 164 } 165 166 #ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR 167 return mmc_load_image_raw_sector(mmc, info.start + 168 CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR); 169 #else 170 return mmc_load_image_raw_sector(mmc, info.start); 171 #endif 172 } 173 #else 174 #define CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION -1 175 static int mmc_load_image_raw_partition(struct mmc *mmc, int partition) 176 { 177 return -ENOSYS; 178 } 179 #endif 180 181 #ifdef CONFIG_SPL_OS_BOOT 182 static int mmc_load_image_raw_os(struct mmc *mmc) 183 { 184 unsigned long count; 185 int ret; 186 187 count = mmc->block_dev.block_read(&mmc->block_dev, 188 CONFIG_SYS_MMCSD_RAW_MODE_ARGS_SECTOR, 189 CONFIG_SYS_MMCSD_RAW_MODE_ARGS_SECTORS, 190 (void *) CONFIG_SYS_SPL_ARGS_ADDR); 191 if (count == 0) { 192 #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT 193 puts("mmc_load_image_raw_os: mmc block read error\n"); 194 #endif 195 return -1; 196 } 197 198 ret = mmc_load_image_raw_sector(mmc, 199 CONFIG_SYS_MMCSD_RAW_MODE_KERNEL_SECTOR); 200 if (ret) 201 return ret; 202 203 if (spl_image.os != IH_OS_LINUX) { 204 puts("Expected Linux image is not found. Trying to start U-boot\n"); 205 return -ENOENT; 206 } 207 208 return 0; 209 } 210 #else 211 int spl_start_uboot(void) 212 { 213 return 1; 214 } 215 static int mmc_load_image_raw_os(struct mmc *mmc) 216 { 217 return -ENOSYS; 218 } 219 #endif 220 221 #ifdef CONFIG_SYS_MMCSD_FS_BOOT_PARTITION 222 int spl_mmc_do_fs_boot(struct mmc *mmc) 223 { 224 int err = -ENOSYS; 225 226 #ifdef CONFIG_SPL_FAT_SUPPORT 227 if (!spl_start_uboot()) { 228 err = spl_load_image_fat_os(&mmc->block_dev, 229 CONFIG_SYS_MMCSD_FS_BOOT_PARTITION); 230 if (!err) 231 return err; 232 } 233 #ifdef CONFIG_SPL_FS_LOAD_PAYLOAD_NAME 234 err = spl_load_image_fat(&mmc->block_dev, 235 CONFIG_SYS_MMCSD_FS_BOOT_PARTITION, 236 CONFIG_SPL_FS_LOAD_PAYLOAD_NAME); 237 if (!err) 238 return err; 239 #endif 240 #endif 241 #ifdef CONFIG_SPL_EXT_SUPPORT 242 if (!spl_start_uboot()) { 243 err = spl_load_image_ext_os(&mmc->block_dev, 244 CONFIG_SYS_MMCSD_FS_BOOT_PARTITION); 245 if (!err) 246 return err; 247 } 248 #ifdef CONFIG_SPL_FS_LOAD_PAYLOAD_NAME 249 err = spl_load_image_ext(&mmc->block_dev, 250 CONFIG_SYS_MMCSD_FS_BOOT_PARTITION, 251 CONFIG_SPL_FS_LOAD_PAYLOAD_NAME); 252 if (!err) 253 return err; 254 #endif 255 #endif 256 257 #if defined(CONFIG_SPL_FAT_SUPPORT) || defined(CONFIG_SPL_EXT_SUPPORT) 258 err = -ENOENT; 259 #endif 260 261 return err; 262 } 263 #else 264 int spl_mmc_do_fs_boot(struct mmc *mmc) 265 { 266 return -ENOSYS; 267 } 268 #endif 269 270 int spl_mmc_load_image(u32 boot_device) 271 { 272 struct mmc *mmc = NULL; 273 u32 boot_mode; 274 int err = 0; 275 __maybe_unused int part; 276 277 err = spl_mmc_find_device(&mmc, boot_device); 278 if (err) 279 return err; 280 281 err = mmc_init(mmc); 282 if (err) { 283 #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT 284 printf("spl: mmc init failed with error: %d\n", err); 285 #endif 286 return err; 287 } 288 289 boot_mode = spl_boot_mode(); 290 err = -EINVAL; 291 switch (boot_mode) { 292 case MMCSD_MODE_EMMCBOOT: 293 /* 294 * We need to check what the partition is configured to. 295 * 1 and 2 match up to boot0 / boot1 and 7 is user data 296 * which is the first physical partition (0). 297 */ 298 part = (mmc->part_config >> 3) & PART_ACCESS_MASK; 299 300 if (part == 7) 301 part = 0; 302 303 err = blk_dselect_hwpart(mmc_get_blk_desc(mmc), part); 304 if (err) { 305 #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT 306 puts("spl: mmc partition switch failed\n"); 307 #endif 308 return err; 309 } 310 /* Fall through */ 311 case MMCSD_MODE_RAW: 312 debug("spl: mmc boot mode: raw\n"); 313 314 if (!spl_start_uboot()) { 315 err = mmc_load_image_raw_os(mmc); 316 if (!err) 317 return err; 318 } 319 320 err = mmc_load_image_raw_partition(mmc, 321 CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION); 322 if (!err) 323 return err; 324 #if defined(CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR) 325 err = mmc_load_image_raw_sector(mmc, 326 CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR); 327 if (!err) 328 return err; 329 #endif 330 /* If RAW mode fails, try FS mode. */ 331 case MMCSD_MODE_FS: 332 debug("spl: mmc boot mode: fs\n"); 333 334 err = spl_mmc_do_fs_boot(mmc); 335 if (!err) 336 return err; 337 338 break; 339 case MMCSD_MODE_UNDEFINED: 340 #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT 341 default: 342 puts("spl: mmc: wrong boot mode\n"); 343 #endif 344 } 345 346 return err; 347 } 348