[U-Boot] [RFC/RFT PATCH v4 3/3] image: Add compressed Image parsing support in booti.

Atish Patra Atish.Patra at wdc.com
Sat Nov 23 02:19:46 UTC 2019


On Wed, 2019-11-13 at 11:47 -0800, Atish Patra wrote:
> On Wed, 2019-11-13 at 15:36 +0200, David Abdurachmanov wrote:
> > On Sat, Nov 9, 2019 at 2:14 AM Atish Patra <atish.patra at wdc.com>
> > wrote:
> > > Add compressed Image parsing support so that booti can parse both
> > > flat and compressed Image to boot Linux. Currently, it is
> > > difficult
> > > to calculate a safe address for every board where the compressed
> > > image can be decompressed. It is also not possible to figure out
> > > the
> > > size of the compressed file as well. Thus, user need to set two
> > > additional environment variables kernel_comp_addr_r and filesize
> > > to
> > > make this work.
> > > 
> > > Following compression methods are supported for now.
> > > lzma, lzo, bzip2, gzip.
> > > 
> > > lz4 support is not added as ARM64 kernel generates a lz4
> > > compressed
> > > image with legacy header which U-Boot doesn't know how to parse
> > > and
> > > decompress.
> > > 
> > > Tested on HiFive Unleashed and Qemu for RISC-V.
> > > Tested on Qemu for ARM64.
> > > 
> > > Signed-off-by: Atish Patra <atish.patra at wdc.com>
> > > ---
> > > I could not test this patch on any ARM64 boards due to lack of
> > > access to any ARM64 board. If anybody can test it on ARM64, that
> > > would be great.
> > > ---
> > >  cmd/booti.c                | 40 ++++++++++++++++++++++++++-
> > >  doc/README.distro          | 12 +++++++++
> > >  doc/board/sifive/fu540.rst | 55
> > > ++++++++++++++++++++++++++++++++++++++
> > >  3 files changed, 106 insertions(+), 1 deletion(-)
> > > 
> > > diff --git a/cmd/booti.c b/cmd/booti.c
> > > index c36b0235df8c..cd8670a9a8db 100644
> > > --- a/cmd/booti.c
> > > +++ b/cmd/booti.c
> > > @@ -13,6 +13,7 @@
> > >  #include <linux/kernel.h>
> > >  #include <linux/sizes.h>
> > > 
> > > +DECLARE_GLOBAL_DATA_PTR;
> > >  /*
> > >   * Image booting support
> > >   */
> > > @@ -23,6 +24,12 @@ static int booti_start(cmd_tbl_t *cmdtp, int
> > > flag, int argc,
> > >         ulong ld;
> > >         ulong relocated_addr;
> > >         ulong image_size;
> > > +       uint8_t *temp;
> > > +       ulong dest;
> > > +       ulong dest_end;
> > > +       unsigned long comp_len;
> > > +       unsigned long decomp_len;
> > > +       int ctype;
> > > 
> > >         ret = do_bootm_states(cmdtp, flag, argc, argv,
> > > BOOTM_STATE_START,
> > >                               images, 1);
> > > @@ -37,6 +44,33 @@ static int booti_start(cmd_tbl_t *cmdtp, int
> > > flag, int argc,
> > >                 debug("*  kernel: cmdline image address =
> > > 0x%08lx\n", ld);
> > >         }
> > > 
> > > +       temp = map_sysmem(ld, 0);
> > > +       ctype = image_decomp_type(temp, 2);
> > > +       if (ctype > 0) {
> > > +               dest = env_get_ulong("kernel_comp_addr_r", 16,
> > > 0);
> > > +               comp_len = env_get_ulong("filesize", 16, 0);
> > > +               if (!dest || !comp_len) {
> > > +                       puts("kernel_comp_addr_r or filesize is
> > > not
> > > provided!\n");
> > > +                       return -EINVAL;
> > > +               }
> > > +               if (dest < gd->ram_base || dest > gd->ram_top) {
> > > +                       puts("kernel_comp_addr_r is outside of
> > > DRAM
> > > range!\n");
> > > +                       return -EINVAL;
> > > +               }
> > > +
> > > +               debug("kernel image compression type %d size =
> > > 0x%08lx address = 0x%08lx\n",
> > > +                       ctype, comp_len, (ulong)dest);
> > > +               decomp_len = comp_len * 10;
> > > +               ret = image_decomp(ctype, 0, ld, IH_TYPE_KERNEL,
> > > +                                (void *)dest, (void *)ld,
> > > comp_len,
> > > +                                decomp_len, &dest_end);
> > > +               if (ret)
> > > +                       return ret;
> > > +               /* dest_end contains the uncompressed Image size
> > > */
> > > +               memmove((void *) ld, (void *)dest, dest_end);
> > > +       }
> > > +       unmap_sysmem((void *)ld);
> > > +
> > >         ret = booti_setup(ld, &relocated_addr, &image_size,
> > > false);
> > >         if (ret != 0)
> > >                 return 1;
> > > @@ -96,10 +130,14 @@ int do_booti(cmd_tbl_t *cmdtp, int flag, int
> > > argc, char * const argv[])
> > >  #ifdef CONFIG_SYS_LONGHELP
> > >  static char booti_help_text[] =
> > >         "[addr [initrd[:size]] [fdt]]\n"
> > > -       "    - boot Linux 'Image' stored at 'addr'\n"
> > > +       "    - boot Linux flat or compressed 'Image' stored at
> > > 'addr'\n"
> > >         "\tThe argument 'initrd' is optional and specifies the
> > > address\n"
> > >         "\tof an initrd in memory. The optional parameter ':size'
> > > allows\n"
> > >         "\tspecifying the size of a RAW initrd.\n"
> > > +       "\tCurrently only booting from gz, bz2, lzma and lz4
> > > compression\n"
> > > +       "\ttypes are supported. In order to boot from any of
> > > these
> > > compressed\n"
> > > +       "\timages, user have to set kernel_comp_addr_r and
> > > filesize
> > > enviornment\n"
> > > +       "\tvariables beforehand.\n"
> > >  #if defined(CONFIG_OF_LIBFDT)
> > >         "\tSince booting a Linux kernel requires a flat device-
> > > tree, a\n"
> > >         "\tthird argument providing the address of the device-
> > > tree
> > > blob\n"
> > > diff --git a/doc/README.distro b/doc/README.distro
> > > index ab6e6f4e74be..67b49e1e4b6a 100644
> > > --- a/doc/README.distro
> > > +++ b/doc/README.distro
> > > @@ -246,6 +246,18 @@ kernel_addr_r:
> > > 
> > >    A size of 16MB for the kernel is likely adequate.
> > > 
> > > +kernel_comp_addr_r:
> > > +  Optional. This is only required if user wants to boot Linux
> > > from
> > > a compressed
> > > +  Image(.gz, .bz2, .lzma, .lzo) using booti command. It
> > > represents
> > > the location
> > > +  in RAM where the compressed Image will be decompressed
> > > temporarily. Once the
> > > +  decompression is complete, decompressed data will be moved
> > > kernel_addr_r for
> > > +  booting.
> > > +
> > > +filesize:
> > > +  Optional. This is only required if user wants to boot Linux
> > > from
> > > a compressed
> > > +  Image using booti command. It represents the size of the
> > > compressed file. The
> > > +  size has to at least the size of loaded image for
> > > decompression
> > > to succeed.
> > > +
> > 
> > I am not sure I like using filesize here compared to
> > kernel_gz_size.
> > It's true that $filesize will be set once your load the binary,
> > e.g.
> > from mmc.
> > But in EXTLINUX/PXE situation $filesize could be wrong.
> > 
> > The load happens in this order:
> > - initrd
> > - kernel
> > - fdt
> > 
> > So if I specify FDT in my EXTLINUX/PXE config the $filesize will be
> > wrong
> > while attempting to boot the kernel. Unless we save filesize of
> > kernel after
> > loading and set it again before calling do_booti() in pxe.c.
> > 
> > Currently I set kernel_gz_size in board environment, which is set
> > to
> > max
> > allowed size.
> > 
> > david
> > 
> 
> Ahh okay. There are two ways to fix it.
> 
> 1. Fix the pxe implementation but save the filesize to be used later.
> 
> But some other user may fall into the same issue without realizing it
> if the user loads any other image after compressed kernel Image.
> 
> We need clear documentation saying that, compressed kernel Image
> should
> be loaded last before executing booti or $filesize must be set
> manually
> before calling booti.
> 
> 2. Just change it back to kernel_comp_size (compressed kernel image
> size) to avoid any confusion.
> 
> Any preference ?
> 

Any thoughts ?

> > >  pxefile_addr_r:
> > > 
> > >    Mandatory. The location in RAM where extlinux.conf will be
> > > loaded to prior
> > > diff --git a/doc/board/sifive/fu540.rst
> > > b/doc/board/sifive/fu540.rst
> > > index 7807f5b2c128..df2c5ad8d3e3 100644
> > > --- a/doc/board/sifive/fu540.rst
> > > +++ b/doc/board/sifive/fu540.rst
> > > @@ -138,6 +138,10 @@ load uImage.
> > >     => setenv netmask 255.255.252.0
> > >     => setenv serverip 10.206.4.143
> > >     => setenv gateway 10.206.4.1
> > > +
> > > +If you want to use a flat kernel image such as Image file
> > > +
> > > +.. code-block:: none
> > >     => tftpboot ${kernel_addr_r} /sifive/fu540/Image
> > >     ethernet at 10090000: PHY present at 0
> > >     ethernet at 10090000: Starting autonegotiation...
> > > @@ -177,6 +181,57 @@ load uImage.
> > >              1.2 MiB/s
> > >     done
> > >     Bytes transferred = 8867100 (874d1c hex)
> > > +
> > > +Or if you want to use a compressed kernel image file such as
> > > Image.gz
> > > +
> > > +.. code-block:: none
> > > +   => tftpboot ${kernel_addr_r} /sifive/fu540/Image.gz
> > > +   ethernet at 10090000: PHY present at 0
> > > +   ethernet at 10090000: Starting autonegotiation...
> > > +   ethernet at 10090000: Autonegotiation complete
> > > +   ethernet at 10090000: link up, 1000Mbps full-duplex (lpa:
> > > 0x3c00)
> > > +   Using ethernet at 10090000 device
> > > +   TFTP from server 10.206.4.143; our IP address is 10.206.7.133
> > > +   Filename '/sifive/fu540/Image.gz'.
> > > +   Load address: 0x84000000
> > > +   Loading:
> > > #################################################################
> > > +            ####################################################
> > > ##
> > > ###########
> > > +            ####################################################
> > > ##
> > > ###########
> > > +            ####################################################
> > > ##
> > > ###########
> > > +            ####################################################
> > > ##
> > > ###########
> > > +            ####################################################
> > > ##
> > > ###########
> > > +            ####################################################
> > > ##
> > > ###########
> > > +            ####################################################
> > > ##
> > > ###########
> > > +            ####################################################
> > > ##
> > > ###########
> > > +            ####################################################
> > > ##
> > > ###########
> > > +            ####################################################
> > > ##
> > > ###########
> > > +            ####################################################
> > > ##
> > > ###########
> > > +            ####################################################
> > > ##
> > > ###########
> > > +            ####################################################
> > > ##
> > > ###########
> > > +            ####################################################
> > > ##
> > > ###########
> > > +            ####################################################
> > > ##
> > > ###########
> > > +            ####################################################
> > > ##
> > > ###########
> > > +            ####################################################
> > > ##
> > > ###########
> > > +            ####################################################
> > > ##
> > > ###########
> > > +            ####################################################
> > > ##
> > > ###########
> > > +            ####################################################
> > > ##
> > > ###########
> > > +            ####################################################
> > > ##
> > > ###########
> > > +            ####################################################
> > > ##
> > > ###########
> > > +            ####################################################
> > > ##
> > > ###########
> > > +            ####################################################
> > > ##
> > > ###########
> > > +            ####################################################
> > > ##
> > > ###########
> > > +            ##########################################
> > > +            1.2 MiB/s
> > > +   done
> > > +   Bytes transferred = 4809458 (4962f2 hex)
> > > +   =>setenv kernel_comp_addr_r 0x90000000
> > > +   =>setenv filesize 0x500000
> > > +
> > > +By this time, correct kernel image is loaded and required
> > > enviornment variables
> > > +are set. You can proceed to load the ramdisk and device tree
> > > from
> > > the tftp server
> > > +as well.
> > > +
> > > +.. code-block:: none
> > >     => tftpboot ${ramdisk_addr_r} /sifive/fu540/uRamdisk
> > >     ethernet at 10090000: PHY present at 0
> > >     ethernet at 10090000: Starting autonegotiation...
> > > --
> > > 2.24.0
> > > 
> > > _______________________________________________
> > > U-Boot mailing list
> > > U-Boot at lists.denx.de
> > > https://lists.denx.de/listinfo/u-boot

-- 
Regards,
Atish


More information about the U-Boot mailing list