[U-Boot] [PATCH v3 1/2] spl: Add an option to load a FIT containing U-Boot from FS
Michal Simek
monstr at monstr.eu
Thu Apr 28 15:49:48 CEST 2016
Hi,
2016-04-20 16:41 GMT+02:00 Simon Glass <sjg at chromium.org>:
> On 13 April 2016 at 23:15, Lokesh Vutla <lokeshvutla at ti.com> wrote:
> > This provides a way to load a FIT containing U-Boot and a selection of
> device
> > tree files from a File system.
> >
> > Signed-off-by: Lokesh Vutla <lokeshvutla at ti.com>
> > ---
> > Changes since v2:
> > - Fixed the number of bytes being copied.
> >
> > common/spl/spl_fit.c | 148
> +++++++++++++++++++++++++++++++++++++++++++--------
> > include/spl.h | 31 +++++++++++
> > 2 files changed, 156 insertions(+), 23 deletions(-)
> >
> > diff --git a/common/spl/spl_fit.c b/common/spl/spl_fit.c
> > index 1a5c027..f5d47c5 100644
> > --- a/common/spl/spl_fit.c
> > +++ b/common/spl/spl_fit.c
> > @@ -82,12 +82,42 @@ static int spl_fit_select_fdt(const void *fdt, int
> images, int *fdt_offsetp)
> > return -ENOENT;
> > }
> >
> > +#define get_fit_size(fit) ALIGN(fdt_totalsize(fit), 4)
> > +
> > +static int spl_parse_fit_header(void *fit)
> > +{
> > + int node;
> > +
> > + spl_image.images = fdt_path_offset(fit, FIT_IMAGES_PATH);
> > + if (spl_image.images < 0) {
> > + debug("%s: Cannot find /images node: %d\n", __func__,
> > + spl_image.images);
> > + return -1;
> > + }
> > + node = fdt_first_subnode(fit, spl_image.images);
> > + if (node < 0) {
> > + debug("%s: Cannot find first image node: %d\n",
> __func__, node);
> > + return -1;
> > + }
> > +
> > + /* Get its information and set up the spl_image structure */
> > + spl_image.data_offset = fdt_getprop_u32(fit, node,
> "data-offset");
> > + spl_image.data_size = fdt_getprop_u32(fit, node, "data-size");
> > + spl_image.load_addr = fdt_getprop_u32(fit, node, "load");
> > + debug("data_offset=%x, data_size=%x\n", spl_image.data_offset,
> > + spl_image.data_size);
> > + spl_image.entry_point = spl_image.load_addr;
> > + spl_image.os = IH_OS_U_BOOT;
> > +
> > + return 0;
> > +}
> > +
> > int spl_load_simple_fit(struct spl_load_info *info, ulong sector, void
> *fit)
> > {
> > int sectors;
> > ulong size, load;
> > unsigned long count;
> > - int node, images;
> > + int images, ret;
> > void *load_ptr;
> > int fdt_offset, fdt_len;
> > int data_offset, data_size;
> > @@ -99,9 +129,8 @@ int spl_load_simple_fit(struct spl_load_info *info,
> ulong sector, void *fit)
> > * Figure out where the external images start. This is the base
> for the
> > * data-offset properties in each image.
> > */
> > - size = fdt_totalsize(fit);
> > - size = (size + 3) & ~3;
> > - base_offset = (size + 3) & ~3;
> > + size = get_fit_size(fit);
> > + base_offset = size;
> >
> > /*
> > * So far we only have one block of data from the FIT. Read the
> entire
> > @@ -125,26 +154,13 @@ int spl_load_simple_fit(struct spl_load_info
> *info, ulong sector, void *fit)
> > if (count == 0)
> > return -EIO;
> >
> > - /* find the firmware image to load */
> > - images = fdt_path_offset(fit, FIT_IMAGES_PATH);
> > - if (images < 0) {
> > - debug("%s: Cannot find /images node: %d\n", __func__,
> images);
> > + ret = spl_parse_fit_header(fit);
> > + if (ret < 0)
> > return -1;
> > - }
> > - node = fdt_first_subnode(fit, images);
> > - if (node < 0) {
> > - debug("%s: Cannot find first image node: %d\n",
> __func__, node);
> > - return -1;
> > - }
> > -
> > - /* Get its information and set up the spl_image structure */
> > - data_offset = fdt_getprop_u32(fit, node, "data-offset");
> > - data_size = fdt_getprop_u32(fit, node, "data-size");
> > - load = fdt_getprop_u32(fit, node, "load");
> > - debug("data_offset=%x, data_size=%x\n", data_offset, data_size);
> > - spl_image.load_addr = load;
> > - spl_image.entry_point = load;
> > - spl_image.os = IH_OS_U_BOOT;
> > + data_offset = spl_image.data_offset;
> > + data_size = spl_image.data_size;
> > + load = spl_image.load_addr;
> > + images = spl_image.images;
> >
> > /*
> > * Work out where to place the image. We read it so that the
> first
> > @@ -192,3 +208,89 @@ int spl_load_simple_fit(struct spl_load_info *info,
> ulong sector, void *fit)
> >
> > return 0;
> > }
> > +
> > +int spl_fs_load_simple_fit(struct spl_load_info *info, const char
> *filename,
> > + void *fit)
> > +{
> > + ulong size, load;
> > + unsigned long count;
> > + int images, ret;
> > + void *load_ptr;
> > + int fdt_offset, fdt_len;
> > + int data_offset, data_size, file_offset;
> > + int base_offset = 0, align_len;
> > + void *dst;
> > +
> > + /*
> > + * Figure out where the external images start. This is the base
> for the
> > + * data-offset properties in each image.
> > + */
> > + size = get_fit_size(fit);
> > + base_offset = size;
> > +
> > + /*
> > + * Read the entire FIT header, placing it so it finishes before
> > + * where we will load the image. Also the load address is aligned
> > + * ARCH_DMA_MINALIGN.
> > + */
> > + align_len = ARCH_DMA_MINALIGN - 1;
> > + fit = (void *)((CONFIG_SYS_TEXT_BASE - size - align_len) &
> ~align_len);
> > + debug("FIT header read: destination = 0x%p, size = %lx\n", fit,
> size);
> > + count = info->fs_read(info, filename, fit, 0, size);
> > + if (count <= 0)
> > + return -EIO;
> > +
> > + ret = spl_parse_fit_header(fit);
> > + if (ret < 0)
> > + return -1;
> > + data_offset = spl_image.data_offset;
> > + data_size = spl_image.data_size;
> > + load = spl_image.load_addr;
> > + images = spl_image.images;
> > +
> > + /*
> > + * Work out where to place the image. Assuming load addr of
> u-boot.bin
> > + * is always aligned to ARCH_DMA_MINALIGN. It is possible that
> file
> > + * offset is not aligned. In order to make sure that the file
> read is
> > + * dma aligned, align the file offset to dma with extra bytes in
> the
> > + * beginning. Then do a memcpy of image to dst.
> > + */
> > + data_offset += base_offset;
> > + file_offset = data_offset & ~align_len;
> > + load_ptr = (void *)load;
> > + dst = load_ptr;
> > +
> > + /* Read the image */
> > + debug("Temp u-boot.bin read from fit: dst = 0x%p, file offset =
> 0x%x, size = 0x%x\n",
> > + dst, file_offset, data_size);
> > + count = info->fs_read(info, filename, dst, file_offset,
> > + data_size + (data_offset & align_len));
> > + if (count <= 0)
> > + return -EIO;
> > + debug("u-boot.bin load: dst = 0x%p, size = 0x%x\n", dst,
> data_size);
> > + memcpy(dst, dst + (data_offset & align_len), data_size);
> > +
> > + /* Figure out which device tree the board wants to use */
> > + fdt_len = spl_fit_select_fdt(fit, images, &fdt_offset);
> > + if (fdt_len < 0)
> > + return fdt_len;
> > +
> > + /*
> > + * Read the device tree and place it after the image. Making
> sure that
> > + * load addr and file offset are aligned to dma.
> > + */
> > + dst = (void *)((load + data_size + align_len) & ~align_len);
> > + fdt_offset += base_offset;
> > + file_offset = fdt_offset & ~align_len;
> > + debug("Temp fdt read from fit: dst = 0x%p, file offset = 0x%x,
> size = %d\n",
> > + dst, file_offset, data_size);
> > + count = info->fs_read(info, filename, dst, file_offset,
> > + fdt_len + (fdt_offset & align_len));
> > + if (count <= 0)
> > + return -EIO;
> > + debug("fdt load: dst = 0x%p, size = 0x%x\n", load_ptr +
> data_size,
> > + data_size);
> > + memcpy(load_ptr + data_size, dst + (fdt_offset & align_len),
> fdt_len);
>
> There is still a lot of duplicated code. Can you figure out a way to
> factor this out?
>
>
There is a lot of code duplication. I have done this differently with using
file_fat_read_at and current infrastructure.
http://lists.denx.de/pipermail/u-boot/2016-April/253065.html
Cheers,
Michal
--
Michal Simek, Ing. (M.Eng), OpenPGP -> KeyID: FE3D1F91
w: www.monstr.eu p: +42-0-721842854
Maintainer of Linux kernel - Microblaze cpu - http://www.monstr.eu/fdt/
Maintainer of Linux kernel - Xilinx Zynq ARM architecture
Microblaze U-BOOT custodian and responsible for u-boot arm zynq platform
More information about the U-Boot
mailing list