diff --git a/common/spl/spl_mmc.c b/common/spl/spl_mmc.c index 4dff9bfd6e871f22fa43df77f19540270181cea8..212a2b0992891521e5494d61995002d9b48211fc 100644 --- a/common/spl/spl_mmc.c +++ b/common/spl/spl_mmc.c @@ -20,26 +20,40 @@ static int mmc_load_legacy(struct spl_image_info *spl_image, struct mmc *mmc, ulong sector, struct image_header *header) { + u32 image_offset_sectors; u32 image_size_sectors; unsigned long count; + u32 image_offset; int ret; ret = spl_parse_image_header(spl_image, header); if (ret) return ret; + /* convert offset to sectors - round down */ + image_offset_sectors = spl_image->offset / mmc->read_bl_len; + /* calculate remaining offset */ + image_offset = spl_image->offset % mmc->read_bl_len; + /* convert size to sectors - round up */ image_size_sectors = (spl_image->size + mmc->read_bl_len - 1) / mmc->read_bl_len; /* Read the header too to avoid extra memcpy */ - count = blk_dread(mmc_get_blk_desc(mmc), sector, image_size_sectors, + count = blk_dread(mmc_get_blk_desc(mmc), + sector + image_offset_sectors, + image_size_sectors, (void *)(ulong)spl_image->load_addr); debug("read %x sectors to %lx\n", image_size_sectors, spl_image->load_addr); if (count != image_size_sectors) return -EIO; + if (image_offset) + memmove((void *)(ulong)spl_image->load_addr, + (void *)(ulong)spl_image->load_addr + image_offset, + spl_image->size); + return 0; } diff --git a/common/spl/spl_sata.c b/common/spl/spl_sata.c index e108af0576aa971a1714a9170cc63173ae3d0bdf..535a9219efa548ef4fa8b8a720ccce96a010e00e 100644 --- a/common/spl/spl_sata.c +++ b/common/spl/spl_sata.c @@ -36,6 +36,8 @@ static int spl_sata_load_image_raw(struct spl_image_info *spl_image, struct image_header *header; unsigned long count; u32 image_size_sectors; + u32 image_offset_sectors; + u32 image_offset; int ret; header = spl_get_load_buffer(-sizeof(*header), stor_dev->blksz); @@ -48,11 +50,19 @@ static int spl_sata_load_image_raw(struct spl_image_info *spl_image, return ret; image_size_sectors = DIV_ROUND_UP(spl_image->size, stor_dev->blksz); - count = blk_dread(stor_dev, sector, image_size_sectors, + image_offset_sectors = spl_image->offset / stor_dev->blksz; + image_offset = spl_image->offset % stor_dev->blksz; + count = blk_dread(stor_dev, sector + image_offset_sectors, + image_size_sectors, (void *)spl_image->load_addr); if (count != image_size_sectors) return -EIO; + if (image_offset) + memmove((void *)spl_image->load_addr, + (void *)spl_image->load_addr + image_offset, + spl_image->size); + return 0; } diff --git a/common/spl/spl_spi.c b/common/spl/spl_spi.c index 6a4e03328709665573402a5983d7cce832b212d8..9884e7c18500ce2024ba0691d9b8e2ef629942c5 100644 --- a/common/spl/spl_spi.c +++ b/common/spl/spl_spi.c @@ -159,7 +159,7 @@ static int spl_spi_load_image(struct spl_image_info *spl_image, err = spl_parse_image_header(spl_image, header); if (err) return err; - err = spi_flash_read(flash, payload_offs, + err = spi_flash_read(flash, payload_offs + spl_image->offset, spl_image->size, (void *)spl_image->load_addr); } diff --git a/include/spl.h b/include/spl.h index 925b6f0cc6461663f20271d3be35950b747e167f..afbf39bef49f8d110927def0ed46d4c4e5374d32 100644 --- a/include/spl.h +++ b/include/spl.h @@ -219,6 +219,7 @@ struct spl_image_info { void *fdt_addr; #endif u32 boot_device; + u32 offset; u32 size; u32 flags; void *arg;