/* * Copyright 2013 Freescale Semiconductor, Inc. * * SPDX-License-Identifier: GPL-2.0+ */ #include #include #include /* * The environment variables are written to just after the u-boot image * on SDCard, so we must read the MBR to get the start address and code * length of the u-boot image, then calculate the address of the env. */ #define ESDHC_BOOT_IMAGE_SIZE 0x48 #define ESDHC_BOOT_IMAGE_ADDR 0x50 #define MBRDBR_BOOT_SIG_55 0x1fe #define MBRDBR_BOOT_SIG_AA 0x1ff #define CONFIG_CFG_DATA_SECTOR 0 void mmc_spl_load_image(uint32_t offs, unsigned int size, void *vdst) { uint blk_start, blk_cnt, err; struct mmc *mmc = find_mmc_device(0); if (!mmc) { puts("spl: mmc device not found!!\n"); hang(); } if (mmc_init(mmc)) { puts("MMC init failed\n"); return; } blk_start = ALIGN(offs, mmc->read_bl_len) / mmc->read_bl_len; blk_cnt = ALIGN(size, mmc->read_bl_len) / mmc->read_bl_len; err = mmc->block_dev.block_read(&mmc->block_dev, blk_start, blk_cnt, vdst); if (err != blk_cnt) { puts("spl: mmc read failed!!\n"); hang(); } } /* * The main entry for mmc booting. It's necessary that SDRAM is already * configured and available since this code loads the main U-Boot image * from mmc into SDRAM and starts it from there. */ void __noreturn mmc_boot(void) { __attribute__((noreturn)) void (*uboot)(void); uint blk_start, blk_cnt, err; #ifndef CONFIG_FSL_CORENET uchar *tmp_buf; u32 blklen; uchar val; uint i, byte_num; #endif u32 offset, code_len; struct mmc *mmc; mmc = find_mmc_device(0); if (!mmc) { puts("spl: mmc device not found!!\n"); hang(); } #ifdef CONFIG_FSL_CORENET offset = CONFIG_SYS_MMC_U_BOOT_OFFS; code_len = CONFIG_SYS_MMC_U_BOOT_SIZE; #else blklen = mmc->read_bl_len; tmp_buf = malloc(blklen); if (!tmp_buf) { puts("spl: malloc memory failed!!\n"); hang(); } memset(tmp_buf, 0, blklen); /* * Read source addr from sd card */ err = mmc->block_dev.block_read(&mmc->block_dev, CONFIG_CFG_DATA_SECTOR, 1, tmp_buf); if (err != 1) { puts("spl: mmc read failed!!\n"); free(tmp_buf); hang(); } val = *(tmp_buf + MBRDBR_BOOT_SIG_55); if (0x55 != val) { puts("spl: mmc signature is not valid!!\n"); free(tmp_buf); hang(); } val = *(tmp_buf + MBRDBR_BOOT_SIG_AA); if (0xAA != val) { puts("spl: mmc signature is not valid!!\n"); free(tmp_buf); hang(); } byte_num = 4; offset = 0; for (i = 0; i < byte_num; i++) { val = *(tmp_buf + ESDHC_BOOT_IMAGE_ADDR + i); offset = (offset << 8) + val; } offset += CONFIG_SYS_MMC_U_BOOT_OFFS; /* Get the code size from offset 0x48 */ byte_num = 4; code_len = 0; for (i = 0; i < byte_num; i++) { val = *(tmp_buf + ESDHC_BOOT_IMAGE_SIZE + i); code_len = (code_len << 8) + val; } code_len -= CONFIG_SYS_MMC_U_BOOT_OFFS; /* * Load U-Boot image from mmc into RAM */ #endif blk_start = ALIGN(offset, mmc->read_bl_len) / mmc->read_bl_len; blk_cnt = ALIGN(code_len, mmc->read_bl_len) / mmc->read_bl_len; err = mmc->block_dev.block_read(&mmc->block_dev, blk_start, blk_cnt, (uchar *)CONFIG_SYS_MMC_U_BOOT_DST); if (err != blk_cnt) { puts("spl: mmc read failed!!\n"); #ifndef CONFIG_FSL_CORENET free(tmp_buf); #endif hang(); } /* * Clean d-cache and invalidate i-cache, to * make sure that no stale data is executed. */ flush_cache(CONFIG_SYS_MMC_U_BOOT_DST, CONFIG_SYS_MMC_U_BOOT_SIZE); /* * Jump to U-Boot image */ uboot = (void *)CONFIG_SYS_MMC_U_BOOT_START; (*uboot)(); }