diff --git a/arch/arm/include/asm/arch-am33xx/spl.h b/arch/arm/include/asm/arch-am33xx/spl.h index f744ab0782..1d509fa904 100644 --- a/arch/arm/include/asm/arch-am33xx/spl.h +++ b/arch/arm/include/asm/arch-am33xx/spl.h @@ -47,6 +47,7 @@ #define BOOT_DEVICE_UART 0x41 #define BOOT_DEVICE_USBETH 0x44 #define BOOT_DEVICE_CPGMAC 0x46 +#define BOOT_DEVICE_JTAG 0x58 #define MMC_BOOT_DEVICES_START BOOT_DEVICE_MMC1 #define MMC_BOOT_DEVICES_END BOOT_DEVICE_MMC2 diff --git a/common/spl/spl_mmc.c b/common/spl/spl_mmc.c index ef8583a1a6..f30ec3f77c 100644 --- a/common/spl/spl_mmc.c +++ b/common/spl/spl_mmc.c @@ -18,6 +18,113 @@ DECLARE_GLOBAL_DATA_PTR; + +static int image_nm_magic(const struct nm_header *header) +{ + u32 start_tag = __be32_to_cpu(header->nm_start_tag); + u32 length = __be32_to_cpu(header->nm_length); + + printf("checking nm header. start tag = 0x%08x, length = %d\n", start_tag, length); + + if ((start_tag == 0x424c5354) && + (length > 128*1024) && (length < 2500*1024)) + { + printf("valid netmodule bootloader found\n"); + return 0; + } + else { + return -1; + } +} + +static int mmc_load_netmodule(struct mmc *mmc, ulong sector, + const struct nm_header *header) +{ + const struct image_header *im_header; + const __be32* end_tag_position; + u32 image_size_sectors; + unsigned long count; + u32 end_tag; + int ret; + + im_header = &(header->header); + printf("nm header %p\n", header); + printf("im header %p\n", im_header); + + /* decode header and fill out spl_image structure */ + ret = spl_parse_image_header(im_header); + printf("mmc_load_netmodule checking header 1: %d\n", ret); + if (ret) + return ret; + + printf("spl header: load addr 0x%08x\n", spl_image.load_addr); + printf("spl header: size %d\n", spl_image.size); + + /* convert size to sectors - round up, + * add 256 bytes for NetModule header, 4 bytes for NetModule trailer + */ + image_size_sectors = (spl_image.size + 256 + 4 + mmc->read_bl_len - 1) / + mmc->read_bl_len; + printf("mmc_load_netmodule 3: %u\n", image_size_sectors); + + /* Read the header too to avoid extra memcpy, + * compensate the load address for the NetModule header + */ + count = blk_dread(mmc_get_blk_desc(mmc), sector, image_size_sectors, + (void *)(ulong)spl_image.load_addr - 256); + debug("read %x sectors to %x\n", image_size_sectors, + spl_image.load_addr); + + if (count != image_size_sectors) + return -EIO; + + /* Check NetModule end tag to be sure image is completely written */ + end_tag_position = (const __be32*)(spl_image.load_addr + spl_image.size); + printf("end tag address %p\n", end_tag_position); + end_tag = __be32_to_cpu(*end_tag_position); + printf("end tag 0x%08x\n", end_tag); + if (end_tag != 0x424c454e) + return -EFAULT; + + return 0; +} + +static int mmc_load_image_raw_sector_netmodule(struct mmc *mmc, unsigned long sector) +{ + unsigned long count; + struct nm_header *header; + int ret = 0; + + printf("\ntrying to load NM packaged u-boot from sector %lu\n", sector); + + header = (struct nm_header *)(CONFIG_SYS_TEXT_BASE - + sizeof(struct nm_header)); + + /* read image header to find the image size & load address */ + count = blk_dread(mmc_get_blk_desc(mmc), sector, 1, header); + debug("hdr read sector %lx, count=%lu\n", sector, count); + if (count == 0) { + ret = -EIO; + goto end; + } + + printf("header loaded to %p\n", header); + + if (image_nm_magic(header) == 0) { + ret = mmc_load_netmodule(mmc, sector, header); + printf("NM image loaded, ret = %d\n", ret); + } else { + ret = -EFAULT; + } + +end: + if (ret) { + return -1; + } + + return 0; +} + static int mmc_load_legacy(struct mmc *mmc, ulong sector, struct image_header *header) { @@ -321,11 +428,41 @@ int spl_mmc_load_image(u32 boot_device) CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION); if (!err) return err; + #if defined(CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR) + if (*(u32*)0x90000004 == 0x12345678) { + printf("Testing redundancy boot\n"); + + /* Try to load NetModule packed bootloader from + * main location */ + err = mmc_load_image_raw_sector_netmodule(mmc, + CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR); + if (!err) + return err; /* found -> ok */ + + /* Try to load NetModule packed bootloader from + * alternate location */ + err = mmc_load_image_raw_sector_netmodule(mmc, + CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR_ALTERNATE); + if (!err) + return err; /* found -> ok */ + + /* Try to load regular bootloader from + * alternate location */ + err = mmc_load_image_raw_sector(mmc, + CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR_ALTERNATE); + if (!err) { + puts("starting alternate bootloader\n"); + return err; /* found -> ok */ + } + } + + /* Try to load bootloader from main location */ err = mmc_load_image_raw_sector(mmc, CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR); if (!err) - return err; + return err; /* found -> ok */ + #endif /* If RAW mode fails, try FS mode. */ case MMCSD_MODE_FS: diff --git a/include/configs/ti_armv7_common.h b/include/configs/ti_armv7_common.h index 7db08813e4..adbc8c8ab3 100644 --- a/include/configs/ti_armv7_common.h +++ b/include/configs/ti_armv7_common.h @@ -220,6 +220,7 @@ /* RAW SD card / eMMC locations. */ #define CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR 0x300 /* address 0x60000 */ +#define CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR_ALTERNATE 0x1b00 /* address 0x360000 */ #define CONFIG_SYS_U_BOOT_MAX_SIZE_SECTORS 0x200 /* 256 KB */ /* FAT sd card locations. */ diff --git a/include/image.h b/include/image.h index a8f6bd16f6..4bac7a16a8 100644 --- a/include/image.h +++ b/include/image.h @@ -286,6 +286,14 @@ typedef struct image_header { uint8_t ih_name[IH_NMLEN]; /* Image Name */ } image_header_t; +typedef struct nm_header { + __be32 nm_start_tag; /* BLST (0x424c5354) */ + __be32 nm_version; /* U-boot version number */ + __be32 nm_length; /* U-boot image length */ + uint8_t reserved[244]; /* Reserved */ + struct image_header header; +} nm_header_t; + typedef struct image_info { ulong start, end; /* start/end of blob */ ulong image_start, image_len; /* start of image within blob, len of image */