spl: Add support to load FIT from Filesystem
v5 cover spl: Add support to load FIT from Filesystem
Some devices like MMC, USB can be formatted to a FS and can act as a boot media. Given that FIT image load support in SPL support only raw devices, SPL should also be able to support loading FIT image from a File system.
This series add support to load FIT image from a filesystem and also adding hooks to FAT FS.
Testing:
DRA74-evm:
MMC Boot: http://pastebin.ubuntu.com/16214433/
eMMC(RAW) Boot: http://pastebin.ubuntu.com/16214420/
AM57xx-evm:
MMC Boot: http://pastebin.ubuntu.com/16214374/
Changes since v4:
- Removed unnecessary else statements.
- Fixed number of bytes read when reading u-boot image from FIT.
Changes since v3:
- Use the same function for reading the fit from FS or raw device.
Lokesh Vutla (3):
spl: fit: Fix the number of bytes read when reading fdt from fit
spl: Allow to load a FIT containing U-Boot from FS
spl: Support loading a FIT from FAT FS
common/spl/spl_fat.c | 31 ++++++++++++++++++++-- common/spl/spl_fit.c | 75 ++++++++++++++++++++++++++++++++++++++++++---------- include/spl.h | 10 +++++++ 3 files changed, 100 insertions(+), 16 deletions(-)
Signature · 1 line
2.7.4
PATCH v5 1/3 spl: fit: Fix the number of bytes read when reading fdt from fit
sectors field is not being updated when reading fdt from fit image. Because of this size_of(u-boot.bin) is being read when reading fdt. Fixing it by updating the sectors field properly.
--- common/spl/spl_fit.c | 1 + 1 file changed, 1 insertion(+)
common/spl/spl_fit.c +1 -0
@@ -176,6 +176,7 @@ int spl_load_simple_fit(struct spl_load_info *info, ulong sector, void *fit)*/ dst = load_ptr + data_size; fdt_offset += base_offset; + sectors = (fdt_len + info->bl_len -1 ) / info->bl_len; count = info->read (info, sector + fdt_offset / info->bl_len, sectors, dst); debug("fit read %x sectors to %x, dst %p, data_offset %x\n",
Signature · 1 line
2.7.4
PATCH v5 1/3 spl: fit: Fix the number of bytes read when reading fdt from fit
Quoted 15 lines · Lokesh Vutla
sectors field is not being updated when reading fdt from fit image. Because of this
size_of(u-boot.bin)is being read when reading fdt. Fixing it by updating the sectors field properly.Signed-off-by Lokesh Vutla <[email protected]>--- common/spl/spl_fit.c | 1 + 1 file changed, 1 insertion(+)common/spl/spl_fit.c +0
-0
common/spl/spl_fit.c int spl_load_simple_fit(struct spl_load_info *info, ulong sector, void *fit) · line 182
Quoted 7 lines
common/spl/spl_fit.c +1
-0@@ -176,6 +176,7 @@ int spl_load_simple_fit(struct spl_load_info *info, ulong sector, void *fit)*/ dst = load_ptr + data_size; fdt_offset += base_offset; + sectors = (fdt_len + info->bl_len -1 ) / info->bl_len; count = info->read (info, sector + fdt_offset / info->bl_len, sectors, dst); debug("fit read %x sectors to %x, dst %p, data_offset %x\n",
Thanks,
Michal
PATCH v5 1/3 spl: fit: Fix the number of bytes read when reading fdt from fit
In reply to Lokesh VutlaQuoted 5 lines · Lokesh Vutla
sectors field is not being updated when reading fdt from fit image. Because of this
size_of(u-boot.bin)is being read when reading fdt. Fixing it by updating the sectors field properly.Signed-off-by Lokesh Vutla <[email protected]>
Signature · 8 lines
Tom -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: <http://lists.denx.de/pipermail/u-boot/attachments/20160506/1021b6a3/attachment.sig>
PATCH v5 1/3 spl: fit: Fix the number of bytes read when reading fdt from fit
In reply to Lokesh VutlaQuoted 22 lines · Lokesh Vutla
sectors field is not being updated when reading fdt from fit image. Because of this
size_of(u-boot.bin)is being read when reading fdt. Fixing it by updating the sectors field properly.Signed-off-by Lokesh Vutla <[email protected]>--- common/spl/spl_fit.c | 1 + 1 file changed, 1 insertion(+)common/spl/spl_fit.c +1
-1@@ -176,6 +176,7 @@ int spl_load_simple_fit(struct spl_load_info *info, ulong sector, void *fit)*/ dst = load_ptr + data_size; fdt_offset += base_offset; + sectors = (fdt_len + info->bl_len -1 ) / info->bl_len; count = info->read (info, sector + fdt_offset / info->bl_len, sectors, dst); debug("fit read %x sectors to %x, dst %p, data_offset %x\n", --
Quoted 2 lines
2.7.4
PATCH v5 2/3 spl: Allow to load a FIT containing U-Boot from FS
In reply to Lokesh VutlaThis provides a way to load a FIT containing U-Boot and a selection of device tree files from a File system. Making sure that all the reads and writes are aligned to their respective needs.
--- common/spl/spl_fit.c | 76 +++++++++++++++++++++++++++++++++++++++++----------- include/spl.h | 10 +++++++ 2 files changed, 71 insertions(+), 15 deletions(-)
common/spl/spl_fit.c +61 -15
@@ -82,6 +82,42 @@ static int spl_fit_select_fdt(const void *fdt, int images, int *fdt_offsetp)return -ENOENT ; } +static int get_aligned_image_offset (struct spl_load_info *info,int offset) +{ +/* +* If it is a FS read, get the first address before offset which is +* aligned to ARCH_DMA_MINALIGN. If it is raw read return the +* block number to which offset belongs. +*/ +if (info->priv) +return offset & ~(ARCH_DMA_MINALIGN -1 ); + +return offset / info->bl_len; +} + +static int get_aligned_image_overhead (struct spl_load_info *info,int offset) +{ +/* +* If it is a FS read, get the difference between the offset and +* the first address before offset which is aligned to +* ARCH_DMA_MINALIGN. If it is raw read return the offset within the +* block. +*/ +if (info->priv) +return offset & (ARCH_DMA_MINALIGN -1 ); + +return offset % info->bl_len; +} + +static int get_aligned_image_size (struct spl_load_info *info,int data_size, +int offset) +{ +if (info->priv) +return data_size +get_aligned_image_overhead (info, offset); + +return (data_size + info->bl_len -1 ) / info->bl_len; +} +int spl_load_simple_fit (struct spl_load_info *info,ulong sector,void *fit) {int sectors;
@@ -91,7 +127,7 @@ int spl_load_simple_fit(struct spl_load_info *info, ulong sector, void *fit)void *load_ptr;int fdt_offset, fdt_len;int data_offset, data_size; -int base_offset; +int base_offset, align_len;int src_sector;void *dst;
@@ -117,8 +153,10 @@ int spl_load_simple_fit(struct spl_load_info *info, ulong sector, void *fit)* In fact the FIT has its own load address, but we assume it cannot * be before CONFIG_SYS_TEXT_BASE. */ - fit = (void *)(CONFIG_SYS_TEXT_BASE - size - info->bl_len); - sectors = (size + info->bl_len -1 ) / info->bl_len; + align_len =ARCH_DMA_MINALIGN -1 ; + fit = (void *)((CONFIG_SYS_TEXT_BASE - size - info->bl_len - + align_len) & ~align_len); + sectors =get_aligned_image_size (info, size,0 ); count = info->read (info, sector, sectors, fit);debug ("fit read sector %lx, sectors=%d, dst=%p, count=%lu\n" , sector, sectors, fit, count);
@@ -151,19 +189,23 @@ int spl_load_simple_fit(struct spl_load_info *info, ulong sector, void *fit)* byte will be at 'load'. This may mean we need to load it starting * before then, since we can only read whole blocks. */ - sectors = (data_size + info->bl_len -1 ) / info->bl_len; data_offset += base_offset; + sectors =get_aligned_image_size (info, data_size, data_offset); load_ptr = (void *)load;debug ("U-Boot size %x, data %p\n" , data_size, load_ptr); - dst = load_ptr - (data_offset % info->bl_len); + dst = load_ptr;/* Read the image */ - src_sector = sector + data_offset / info->bl_len; -debug ("image: data_offset=%x, dst=%p, src_sector=%x, sectors=%x\n" , - data_offset, dst, src_sector, sectors); + src_sector = sector +get_aligned_image_offset (info, data_offset); +debug ("Aligned image read: dst=%p, src_sector=%x, sectors=%x\n" , + dst, src_sector, sectors); count = info->read (info, src_sector, sectors, dst);if (count != sectors)return -EIO ; +debug ("image: dst=%p, data_offset=%x, size=%x\n" , dst, data_offset, + data_size); +memcpy (dst, dst +get_aligned_image_overhead (info, data_offset), + data_size);/* Figure out which device tree the board wants to use */ fdt_len =spl_fit_select_fdt (fit, images, &fdt_offset);
@@ -173,14 +215,15 @@ int spl_load_simple_fit(struct spl_load_info *info, ulong sector, void *fit)/* * Read the device tree and place it after the image. There may be * some extra data before it since we can only read entire blocks. +* And also align the destination address to ARCH_DMA_MINALIGN. */ - dst = load_ptr + data_size; + dst = (void *)((load + data_size + align_len) & ~align_len); fdt_offset += base_offset; - sectors = (fdt_len + info->bl_len -1 ) / info->bl_len; - count = info->read (info, sector + fdt_offset / info->bl_len, sectors, - dst); -debug ("fit read %x sectors to %x, dst %p, data_offset %x\n" , - sectors, spl_image.load_addr, dst, fdt_offset); + sectors =get_aligned_image_size (info, fdt_len, fdt_offset); + src_sector = sector +get_aligned_image_offset (info, fdt_offset); + count = info->read (info, src_sector, sectors, dst); +debug ("Aligned fdt read: dst %p, src_sector = %x, sectors %x\n" , + dst, src_sector, sectors);if (count != sectors)return -EIO ;
@@ -189,7 +232,10 @@ int spl_load_simple_fit(struct spl_load_info *info, ulong sector, void *fit)* After this we will have the U-Boot image and its device tree ready * for us to start. */ -memcpy (dst, dst + fdt_offset % info->bl_len, fdt_len); +debug ("fdt: dst=%p, data_offset=%x, size=%x\n" , dst, fdt_offset, + fdt_len); +memcpy (load_ptr + data_size, + dst +get_aligned_image_overhead (info, fdt_offset), fdt_len);return 0 ; }
include/spl.h +10 -0
@@ -45,6 +45,16 @@ struct spl_load_info { void *buf); }; +/** +* spl_load_simple_fit() - Loads a fit image from a device. +* @info: Structure containing the information required to load data. +* @sector: Sector number where FIT image is located in the device +* @fdt: Pointer to the copied FIT header. +* +* Reads the FIT image @sector in the device. Loads u-boot image to +* specified load address and copies the dtb to end of u-boot image. +* Returns 0 on success. +*/ int spl_load_simple_fit (struct spl_load_info *info,ulong sector,void *fdt);#define SPL_COPY_PAYLOAD_ONLY 1
Signature · 1 line
2.7.4
PATCH v5 2/3 spl: Allow to load a FIT containing U-Boot from FS
Quoted 154 lines · Lokesh Vutla
This provides a way to load a FIT containing U-Boot and a selection of device tree files from a File system. Making sure that all the reads and writes are aligned to their respective needs.
Signed-off-by Lokesh Vutla <[email protected]>--- common/spl/spl_fit.c | 76 +++++++++++++++++++++++++++++++++++++++++----------- include/spl.h | 10 +++++++ 2 files changed, 71 insertions(+), 15 deletions(-)common/spl/spl_fit.c +61
-15@@ -82,6 +82,42 @@ static int spl_fit_select_fdt(const void *fdt, int images, int *fdt_offsetp)return -ENOENT ; } +static int get_aligned_image_offset (struct spl_load_info *info,int offset) +{ +/* +* If it is a FS read, get the first address before offset which is +* aligned to ARCH_DMA_MINALIGN. If it is raw read return the +* block number to which offset belongs. +*/ +if (info->priv) +return offset & ~(ARCH_DMA_MINALIGN -1 ); + +return offset / info->bl_len; +} + +static int get_aligned_image_overhead (struct spl_load_info *info,int offset) +{ +/* +* If it is a FS read, get the difference between the offset and +* the first address before offset which is aligned to +* ARCH_DMA_MINALIGN. If it is raw read return the offset within the +* block. +*/ +if (info->priv) +return offset & (ARCH_DMA_MINALIGN -1 ); + +return offset % info->bl_len; +} + +static int get_aligned_image_size (struct spl_load_info *info,int data_size, +int offset) +{ +if (info->priv) +return data_size +get_aligned_image_overhead (info, offset); + +return (data_size + info->bl_len -1 ) / info->bl_len; +} +int spl_load_simple_fit (struct spl_load_info *info,ulong sector,void *fit) {int sectors;@@ -91,7 +127,7 @@ int spl_load_simple_fit(struct spl_load_info *info, ulong sector, void *fit)void *load_ptr;int fdt_offset, fdt_len;int data_offset, data_size; -int base_offset; +int base_offset, align_len;int src_sector;void *dst;@@ -117,8 +153,10 @@ int spl_load_simple_fit(struct spl_load_info *info, ulong sector, void *fit)* In fact the FIT has its own load address, but we assume it cannot * be before CONFIG_SYS_TEXT_BASE. */ - fit = (void *)(CONFIG_SYS_TEXT_BASE - size - info->bl_len); - sectors = (size + info->bl_len -1 ) / info->bl_len; + align_len =ARCH_DMA_MINALIGN -1 ; + fit = (void *)((CONFIG_SYS_TEXT_BASE - size - info->bl_len - + align_len) & ~align_len); + sectors =get_aligned_image_size (info, size,0 ); count = info->read (info, sector, sectors, fit);debug ("fit read sector %lx, sectors=%d, dst=%p, count=%lu\n" , sector, sectors, fit, count);@@ -151,19 +189,23 @@ int spl_load_simple_fit(struct spl_load_info *info, ulong sector, void *fit)* byte will be at 'load'. This may mean we need to load it starting * before then, since we can only read whole blocks. */ - sectors = (data_size + info->bl_len -1 ) / info->bl_len; data_offset += base_offset; + sectors =get_aligned_image_size (info, data_size, data_offset); load_ptr = (void *)load;debug ("U-Boot size %x, data %p\n" , data_size, load_ptr); - dst = load_ptr - (data_offset % info->bl_len); + dst = load_ptr;/* Read the image */ - src_sector = sector + data_offset / info->bl_len; -debug ("image: data_offset=%x, dst=%p, src_sector=%x, sectors=%x\n" , - data_offset, dst, src_sector, sectors); + src_sector = sector +get_aligned_image_offset (info, data_offset); +debug ("Aligned image read: dst=%p, src_sector=%x, sectors=%x\n" , + dst, src_sector, sectors); count = info->read (info, src_sector, sectors, dst);if (count != sectors)return -EIO ; +debug ("image: dst=%p, data_offset=%x, size=%x\n" , dst, data_offset, + data_size); +memcpy (dst, dst +get_aligned_image_overhead (info, data_offset), + data_size);/* Figure out which device tree the board wants to use */ fdt_len =spl_fit_select_fdt (fit, images, &fdt_offset);@@ -173,14 +215,15 @@ int spl_load_simple_fit(struct spl_load_info *info, ulong sector, void *fit)/* * Read the device tree and place it after the image. There may be * some extra data before it since we can only read entire blocks. +* And also align the destination address to ARCH_DMA_MINALIGN. */ - dst = load_ptr + data_size; + dst = (void *)((load + data_size + align_len) & ~align_len); fdt_offset += base_offset; - sectors = (fdt_len + info->bl_len -1 ) / info->bl_len; - count = info->read (info, sector + fdt_offset / info->bl_len, sectors, - dst); -debug ("fit read %x sectors to %x, dst %p, data_offset %x\n" , - sectors, spl_image.load_addr, dst, fdt_offset); + sectors =get_aligned_image_size (info, fdt_len, fdt_offset); + src_sector = sector +get_aligned_image_offset (info, fdt_offset); + count = info->read (info, src_sector, sectors, dst); +debug ("Aligned fdt read: dst %p, src_sector = %x, sectors %x\n" , + dst, src_sector, sectors);if (count != sectors)return -EIO ;@@ -189,7 +232,10 @@ int spl_load_simple_fit(struct spl_load_info *info, ulong sector, void *fit)* After this we will have the U-Boot image and its device tree ready * for us to start. */ -memcpy (dst, dst + fdt_offset % info->bl_len, fdt_len); +debug ("fdt: dst=%p, data_offset=%x, size=%x\n" , dst, fdt_offset, + fdt_len); +memcpy (load_ptr + data_size, + dst +get_aligned_image_overhead (info, fdt_offset), fdt_len);return 0 ; }include/spl.h +3
-0@@ -45,6 +45,16 @@ struct spl_load_info { void *buf); }; +/** +* spl_load_simple_fit() - Loads a fit image from a device. +* @info: Structure containing the information required to load data.
include/spl.h struct spl_load_info { · line 60
Quoted 10 lines
include/spl.h +7
-0+* @sector: Sector number where FIT image is located in the device +* @fdt: Pointer to the copied FIT header. +* +* Reads the FIT image @sector in the device. Loads u-boot image to +* specified load address and copies the dtb to end of u-boot image. +* Returns 0 on success. +*/ int spl_load_simple_fit (struct spl_load_info *info,ulong sector,void *fdt);#define SPL_COPY_PAYLOAD_ONLY 1
Thanks,
Michal
PATCH v5 2/3 spl: Allow to load a FIT containing U-Boot from FS
In reply to Lokesh VutlaQuoted 5 lines · Lokesh Vutla
This provides a way to load a FIT containing U-Boot and a selection of device tree files from a File system. Making sure that all the reads and writes are aligned to their respective needs.
Signed-off-by Lokesh Vutla <[email protected]>
Signature · 8 lines
Tom -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: <http://lists.denx.de/pipermail/u-boot/attachments/20160506/8897753a/attachment.sig>
PATCH v5 2/3 spl: Allow to load a FIT containing U-Boot from FS
In reply to Lokesh VutlaQuoted 9 lines · Lokesh Vutla
This provides a way to load a FIT containing U-Boot and a selection of device tree files from a File system. Making sure that all the reads and writes are aligned to their respective needs.
Signed-off-by Lokesh Vutla <[email protected]>--- common/spl/spl_fit.c | 76 +++++++++++++++++++++++++++++++++++++++++----------- include/spl.h | 10 +++++++ 2 files changed, 71 insertions(+), 15 deletions(-)
PATCH v5 3/3 spl: Support loading a FIT from FAT FS
In reply to Lokesh VutlaDetect a FIT when loading from a FAT File system and handle it using the new FIT SPL support.
--- common/spl/spl_fat.c | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-)
common/spl/spl_fat.c +29 -2
@@ -15,6 +15,7 @@#include <fat.h> #include <errno.h> #include <image.h> +#include <libfdt.h> static int fat_registered;
@@ -39,6 +40,20 @@ static int spl_register_fat_device(struct blk_desc *block_dev, int partition)return err; } +static ulong spl_fit_read (struct spl_load_info *load,ulong file_offset, +ulong size,void *buf) +{ +loff_t actread; +int ret; +char *filename = (char *)load->priv; + + ret =fat_read_file (filename, buf, file_offset, size, &actread); +if (ret) +return ret; + +return actread; +} +int spl_load_image_fat (struct blk_desc *block_dev,int partition,const char *filename)
@@ -57,9 +72,21 @@ int spl_load_image_fat(struct blk_desc *block_dev,if (err <=0 ) goto end; -spl_parse_image_header (header); +if (IS_ENABLED (CONFIG_SPL_LOAD_FIT ) && +image_get_magic (header) ==FDT_MAGIC ) { +struct spl_load_info load; + +debug ("Found FIT\n" ); + load.read = spl_fit_read; + load.bl_len =1 ; + load.priv = (void *)filename; - err =file_fat_read (filename, (u8 *)spl_image.load_addr,0 ); +return spl_load_simple_fit (&load,0 , header); + }else { +spl_parse_image_header (header); + + err =file_fat_read (filename, (u8 *)spl_image.load_addr,0 ); + } end: #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
Signature · 1 line
2.7.4
PATCH v5 3/3 spl: Support loading a FIT from FAT FS
Quoted 56 lines · Lokesh Vutla
Detect a FIT when loading from a FAT File system and handle it using the new FIT SPL support.
Signed-off-by Lokesh Vutla <[email protected]>--- common/spl/spl_fat.c | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-)common/spl/spl_fat.c +23
-1@@ -15,6 +15,7 @@#include <fat.h> #include <errno.h> #include <image.h> +#include <libfdt.h> static int fat_registered;@@ -39,6 +40,20 @@ static int spl_register_fat_device(struct blk_desc *block_dev, int partition)return err; } +static ulong spl_fit_read (struct spl_load_info *load,ulong file_offset, +ulong size,void *buf) +{ +loff_t actread; +int ret; +char *filename = (char *)load->priv; + + ret =fat_read_file (filename, buf, file_offset, size, &actread); +if (ret) +return ret; + +return actread; +} +int spl_load_image_fat (struct blk_desc *block_dev,int partition,const char *filename)@@ -57,9 +72,21 @@ int spl_load_image_fat(struct blk_desc *block_dev,if (err <=0 ) goto end; -spl_parse_image_header (header); +if (IS_ENABLED (CONFIG_SPL_LOAD_FIT ) && +image_get_magic (header) ==FDT_MAGIC ) { +struct spl_load_info load; + +debug ("Found FIT\n" ); + load.read = spl_fit_read; + load.bl_len =1 ; + load.priv = (void *)filename;
common/spl/spl_fat.c int spl_load_image_fat(struct blk_desc *block_dev, · line 92
Quoted 10 lines
common/spl/spl_fat.c +6
-1- err =file_fat_read (filename, (u8 *)spl_image.load_addr,0 ); +return spl_load_simple_fit (&load,0 , header); + }else { +spl_parse_image_header (header); + + err =file_fat_read (filename, (u8 *)spl_image.load_addr,0 ); + } end: #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
Thanks,
Michal
PATCH v5 3/3 spl: Support loading a FIT from FAT FS
In reply to Lokesh VutlaQuoted 4 lines · Lokesh Vutla
Detect a FIT when loading from a FAT File system and handle it using the new FIT SPL support.
Signed-off-by Lokesh Vutla <[email protected]>
Signature · 8 lines
Tom -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: <http://lists.denx.de/pipermail/u-boot/attachments/20160506/eaa5ad0a/attachment.sig>
PATCH v5 3/3 spl: Support loading a FIT from FAT FS
In reply to Lokesh VutlaQuoted 7 lines · Lokesh Vutla
Detect a FIT when loading from a FAT File system and handle it using the new FIT SPL support.
Signed-off-by Lokesh Vutla <[email protected]>--- common/spl/spl_fat.c | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-)