diff mbox series

[U-Boot,RFC/RFT,U-Boot] image: Add Image.gz parsing support in booti.

Message ID 20191010212317.3884-1-atish.patra@wdc.com
State Superseded
Delegated to: Tom Rini
Headers show
Series [U-Boot,RFC/RFT,U-Boot] image: Add Image.gz parsing support in booti. | expand

Commit Message

Atish Patra Oct. 10, 2019, 9:23 p.m. UTC
Add gz parsing logic so that booti can parse both Image
and Image.gz to boot Linux. Currently, it is difficult to calculate
a safe address for every board where the Image.gz 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_gz_addr_r and kernel_gz_size to make Image.gz work.

Tested on HiFive Unleashed and Qemu for RISC-V.

Signed-off-by: Atish Patra <atish.patra@wdc.com>
---
I could not test this patch on any ARM64 devices due to lack of
access to any ARM64 board. If anybody can test it on ARM64, that
would be great.
---
 cmd/booti.c                | 39 ++++++++++++++++++++++++++-
 doc/README.distro          | 11 ++++++++
 doc/board/sifive/fu540.rst | 55 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 104 insertions(+), 1 deletion(-)

Comments

Atish Patra Oct. 18, 2019, 5:25 p.m. UTC | #1
.-x-evo-quoted { -webkit-user-select: none; }a { color: #248a76; }a.-x-evo-visited-link { color: #273134; }body {
  font-family: 'Hack';
  font-size: 11pt;
  font-weight: 400;
  font-style: normal;
 -webkit-line-break: after-white-space;
 -webkit-font-smoothing: subpixel-antialiased;
}
pre,code,.pre {
  font-family: 'Hack';
  font-size: 11pt;
  font-weight: 400;
  font-style: normal;
}pre,code,address {
  margin: 0px;
}
h1,h2,h3,h4,h5,h6 {
  margin-top: 0.2em;
  margin-bottom: 0.2em;
}
td:before {
 content: "";}
img {
  height: inherit; 
  width: inherit; 
}
span.-x-evo-resizable-wrapper:hover {
  outline: 1px dashed red; 
  resize: both; 
  overflow: hidden; 
  display: inline-block; 
}
td:hover {
  outline: 1px dotted red;
}
body[data-evo-plain-text] {
  font-family: Monospace; 
}
body[data-evo-plain-text] img.-x-evo-smiley-img, body:not([data-evo-plain-text]) span.-x-evo-smiley-text {
  display: none 
}
[data-evo-paragraph] {
  white-space: pre-wrap; 
}
body[data-evo-plain-text] [data-evo-paragraph] {
  word-wrap: break-word; 
  word-break: break-word; 
}
.-x-evo-plaintext-table {
  border-collapse: collapse;
  width: 71ch;
}
.-x-evo-plaintext-table td {
  vertical-align: top;
}
body[data-evo-plain-text] ul {
  list-style: outside none;
  -webkit-padding-start: 3ch; 
}
body[data-evo-plain-text] ul > li {
  list-style-position: outside;
  text-indent: -2ch;
}
body[data-evo-plain-text] ul > li::before {
  content: "*&nbsp;";
}
body[data-evo-plain-text] ul.-x-evo-indented {
  -webkit-padding-start: 3ch; 
}
body:not([data-evo-plain-text]) ul > li.-x-evo-align-center,ol > li.-x-evo-align-center {
  list-style-position: inside;
}
body:not([data-evo-plain-text]) ul > li.-x-evo-align-right, ol > li.-x-evo-align-right {
  list-style-position: inside;
}
ol {
  -webkit-padding-start: 6ch; 
}
ol.-x-evo-indented {
  -webkit-padding-start: 3ch; 
}
.-x-evo-align-left {
  text-align: left; 
}
.-x-evo-align-center {
  text-align: center; 
}
.-x-evo-align-right {
  text-align: right; 
}
ol,ul {
  -webkit-margin-before: 0em; 
  -webkit-margin-after: 0em; 
}
blockquote {
  -webkit-margin-before: 0em; 
  -webkit-margin-after: 0em; 
}
blockquote[type=cite] {
  padding: 0.0ex 0ex;
  margin: 0ex;
  -webkit-margin-start: 0em; 
  -webkit-margin-end : 0em; 
  color: #737373 !important; 
}
.-x-evo-quote-character {
  color: rgb(114,159,207);
}
.-x-evo-quote-character+.-x-evo-quote-character{
  color: rgb(173,127,168);
}
.-x-evo-quote-character+.-x-evo-quote-character+.-x-evo-quote-character{
  color: rgb(138,226,52);
}
.-x-evo-quote-character+.-x-evo-quote-character+.-x-evo-quote-character+.-x-evo-quote-character{
  color: rgb(252,175,62);
}
.-x-evo-quote-character+.-x-evo-quote-character+.-x-evo-quote-character+.-x-evo-quote-character+.-x-evo-quote-character{
  color: rgb(233,185,110);
}
body:not([data-evo-plain-text]) blockquote[type=cite] {
  padding: 0ch 1ch 0ch 1ch;
  margin: 0ch;
  border-width: 0px 2px 0px 2px;
  border-style: none solid none solid;
  border-radius: 2px;
}
body:not([data-evo-plain-text]) blockquote[type=cite] {
  border-color: rgb(114,159,207);
}
body:not([data-evo-plain-text]) blockquote[type=cite] blockquote[type=cite] {
  border-color: rgb(173,127,168);
}
body:not([data-evo-plain-text]) blockquote[type=cite] blockquote[type=cite] blockquote[type=cite] {
  border-color: rgb(138,226,52);
}
body:not([data-evo-plain-text]) blockquote[type=cite] blockquote[type=cite] blockquote[type=cite] blockquote[type=cite] {
  border-color: rgb(252,175,62);
}
body:not([data-evo-plain-text]) blockquote[type=cite] blockquote[type=cite] blockquote[type=cite] blockquote[type=cite] blockquote[type=cite] {
  border-color: rgb(233,185,110);
}
On Thu, 2019-10-10 at 14:23 -0700, Atish Patra wrote:
> Add gz parsing logic so that booti can parse both Image
> and Image.gz to boot Linux. Currently, it is difficult to calculate
> a safe address for every board where the Image.gz 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_gz_addr_r and kernel_gz_size to make Image.gz work.
> 
> Tested on HiFive Unleashed and Qemu for RISC-V.
> 
> Signed-off-by: Atish Patra <atish.patra@wdc.com>
> ---
> I could not test this patch on any ARM64 devices due to lack of
> access to any ARM64 board. If anybody can test it on ARM64, that
> would be great.
> ---
>  cmd/booti.c                | 39 ++++++++++++++++++++++++++-
>  doc/README.distro          | 11 ++++++++
>  doc/board/sifive/fu540.rst | 55
> ++++++++++++++++++++++++++++++++++++++
>  3 files changed, 104 insertions(+), 1 deletion(-)
> 
> diff --git a/cmd/booti.c b/cmd/booti.c
> index c36b0235df8c..6c37f84833d0 100644
> --- a/cmd/booti.c
> +++ b/cmd/booti.c
> @@ -13,6 +13,9 @@
>  #include <linux/kernel.h>
>  #include <linux/sizes.h>
>  
> +DECLARE_GLOBAL_DATA_PTR;
> +#define GZ_HEADER_0 0x1f
> +#define GZ_HEADER_1 0x8b
>  /*
>   * Image booting support
>   */
> @@ -23,6 +26,10 @@ 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 gz_len;
>  
>  	ret = do_bootm_states(cmdtp, flag, argc, argv,
> BOOTM_STATE_START,
>  			      images, 1);
> @@ -37,6 +44,34 @@ 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);
> +
> +	if (*(temp)  == GZ_HEADER_0 && *(temp+1) == GZ_HEADER_1) {
> +		dest = env_get_ulong("kernel_gz_addr_r", 16, 0);
> +		gz_len = env_get_ulong("kernel_gz_size", 16, 0);
> +		if (!dest || !gz_len) {
> +			puts("kernel_gz_addr_r or kernel_gz_size is not
> provided for Image.gz!\n");
> +			return -EINVAL;
> +		}
> +		if (dest < gd->ram_base || dest > gd->ram_top) {
> +			puts("kernel_gz_addr_r size is outside of dram
> range!\n");
> +			return -EINVAL;
> +		}
> +
> +		debug("Image.gz of size = 0x%08lx will be decompressed
> at 0x%08lx\n",
> +		      gz_len, (ulong)dest);
> +
> +		ret = image_decomp(IH_COMP_GZIP, 0, ld, IH_TYPE_KERNEL,
> +					 (void *)dest, (void *)ld,
> gz_len,
> +					 CONFIG_SYS_BOOTM_LEN,
> &dest_end);
> +		if (ret)
> +			return ret;
> +		/* dest_end contains the uncompressed Image size */
> +		memmove((void *) ld, (void *)dest, dest_end);
> +		unmap_sysmem((void *)dest);
> +	}
> +	unmap_sysmem((void *)ld);
> +
>  	ret = booti_setup(ld, &relocated_addr, &image_size, false);
>  	if (ret != 0)
>  		return 1;
> @@ -96,10 +131,12 @@ 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 'Image' or Image.gz 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"
> +	"\tIn order to boot from Image.gz, user have to set
> kernel_gz_addr_r\n"
> +	"\tand kernel_gz_size enviornment variables 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..dbf6eef07e35 100644
> --- a/doc/README.distro
> +++ b/doc/README.distro
> @@ -246,6 +246,17 @@ kernel_addr_r:
>  
>    A size of 16MB for the kernel is likely adequate.
>  
> +kernel_gz_addr_r:
> +  Optional. This is only required if user wants to boot Linux from a
> Image.gz
> +  using booti command. It represents the location in RAM where a
> Image.gz will
> +  be decompressed temporarily. Once the decompression is complete,
> decompressed
> +  data will be moved kernel_addr_r for booting.
> +
> +kernel_gz_size:
> +  Optional. This is only required if user wants to boot Linux from a
> Image.gz
> +  using booti command. It represents the size of the Image.gz file.
> The size
> +  has to at least the size of Image.gz file for decompression to
> succeed.
> +
>  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..ad4485eb7cdb 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@10090000: PHY present at 0
>     ethernet@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
> +   ethernet@10090000: PHY present at 0
> +   ethernet@10090000: Starting autonegotiation...
> +   ethernet@10090000: Autonegotiation complete
> +   ethernet@10090000: link up, 1000Mbps full-duplex (lpa: 0x3c00)
> +   Using ethernet@10090000 device
> +   TFTP from server 10.206.4.143; our IP address is 10.206.7.133
> +   Filename '/sifive/fu540/Image'.
> +   Load address: 0x84000000
> +   Loading:
> #################################################################
> +            ########################################################
> #########
> +            ########################################################
> #########
> +            ########################################################
> #########
> +            ########################################################
> #########
> +            ########################################################
> #########
> +            ########################################################
> #########
> +            ########################################################
> #########
> +            ########################################################
> #########
> +            ########################################################
> #########
> +            ########################################################
> #########
> +            ########################################################
> #########
> +            ########################################################
> #########
> +            ########################################################
> #########
> +            ########################################################
> #########
> +            ########################################################
> #########
> +            ########################################################
> #########
> +            ########################################################
> #########
> +            ########################################################
> #########
> +            ########################################################
> #########
> +            ########################################################
> #########
> +            ########################################################
> #########
> +            ########################################################
> #########
> +            ########################################################
> #########
> +            ########################################################
> #########
> +            ########################################################
> #########
> +            ##########################################
> +            1.2 MiB/s
> +   done
> +   Bytes transferred = 4809458 (4962f2 hex)
> +   =>setenv kernel_gz_addr_r 0x90000000
> +   =>setenv kernel_gz_size 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@10090000: PHY present at 0
>     ethernet@10090000: Starting autonegotiation...

Any comments ?
Atish Patra Oct. 18, 2019, 5:56 p.m. UTC | #2
On Thu, 2019-10-10 at 14:23 -0700, Atish Patra wrote:
> Add gz parsing logic so that booti can parse both Image
> and Image.gz to boot Linux. Currently, it is difficult to calculate
> a safe address for every board where the Image.gz 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_gz_addr_r and kernel_gz_size to make Image.gz work.
> 
> Tested on HiFive Unleashed and Qemu for RISC-V.
> 
> Signed-off-by: Atish Patra <atish.patra@wdc.com>
> ---
> I could not test this patch on any ARM64 devices due to lack of
> access to any ARM64 board. If anybody can test it on ARM64, that
> would be great.
> ---
>  cmd/booti.c                | 39 ++++++++++++++++++++++++++-
>  doc/README.distro          | 11 ++++++++
>  doc/board/sifive/fu540.rst | 55
> ++++++++++++++++++++++++++++++++++++++
>  3 files changed, 104 insertions(+), 1 deletion(-)
> 
> diff --git a/cmd/booti.c b/cmd/booti.c
> index c36b0235df8c..6c37f84833d0 100644
> --- a/cmd/booti.c
> +++ b/cmd/booti.c
> @@ -13,6 +13,9 @@
>  #include <linux/kernel.h>
>  #include <linux/sizes.h>
>  
> +DECLARE_GLOBAL_DATA_PTR;
> +#define GZ_HEADER_0 0x1f
> +#define GZ_HEADER_1 0x8b
>  /*
>   * Image booting support
>   */
> @@ -23,6 +26,10 @@ 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 gz_len;
>  
>  	ret = do_bootm_states(cmdtp, flag, argc, argv,
> BOOTM_STATE_START,
>  			      images, 1);
> @@ -37,6 +44,34 @@ 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);
> +
> +	if (*(temp)  == GZ_HEADER_0 && *(temp+1) == GZ_HEADER_1) {
> +		dest = env_get_ulong("kernel_gz_addr_r", 16, 0);
> +		gz_len = env_get_ulong("kernel_gz_size", 16, 0);
> +		if (!dest || !gz_len) {
> +			puts("kernel_gz_addr_r or kernel_gz_size is not
> provided for Image.gz!\n");
> +			return -EINVAL;
> +		}
> +		if (dest < gd->ram_base || dest > gd->ram_top) {
> +			puts("kernel_gz_addr_r size is outside of dram
> range!\n");
> +			return -EINVAL;
> +		}
> +
> +		debug("Image.gz of size = 0x%08lx will be decompressed
> at 0x%08lx\n",
> +		      gz_len, (ulong)dest);
> +
> +		ret = image_decomp(IH_COMP_GZIP, 0, ld, IH_TYPE_KERNEL,
> +					 (void *)dest, (void *)ld,
> gz_len,
> +					 CONFIG_SYS_BOOTM_LEN,
> &dest_end);
> +		if (ret)
> +			return ret;
> +		/* dest_end contains the uncompressed Image size */
> +		memmove((void *) ld, (void *)dest, dest_end);
> +		unmap_sysmem((void *)dest);
> +	}
> +	unmap_sysmem((void *)ld);
> +
>  	ret = booti_setup(ld, &relocated_addr, &image_size, false);
>  	if (ret != 0)
>  		return 1;
> @@ -96,10 +131,12 @@ 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 'Image' or Image.gz 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"
> +	"\tIn order to boot from Image.gz, user have to set
> kernel_gz_addr_r\n"
> +	"\tand kernel_gz_size enviornment variables 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..dbf6eef07e35 100644
> --- a/doc/README.distro
> +++ b/doc/README.distro
> @@ -246,6 +246,17 @@ kernel_addr_r:
>  
>    A size of 16MB for the kernel is likely adequate.
>  
> +kernel_gz_addr_r:
> +  Optional. This is only required if user wants to boot Linux from a
> Image.gz
> +  using booti command. It represents the location in RAM where a
> Image.gz will
> +  be decompressed temporarily. Once the decompression is complete,
> decompressed
> +  data will be moved kernel_addr_r for booting.
> +
> +kernel_gz_size:
> +  Optional. This is only required if user wants to boot Linux from a
> Image.gz
> +  using booti command. It represents the size of the Image.gz file.
> The size
> +  has to at least the size of Image.gz file for decompression to
> succeed.
> +
>  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..ad4485eb7cdb 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@10090000: PHY present at 0
>     ethernet@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
> +   ethernet@10090000: PHY present at 0
> +   ethernet@10090000: Starting autonegotiation...
> +   ethernet@10090000: Autonegotiation complete
> +   ethernet@10090000: link up, 1000Mbps full-duplex (lpa: 0x3c00)
> +   Using ethernet@10090000 device
> +   TFTP from server 10.206.4.143; our IP address is 10.206.7.133
> +   Filename '/sifive/fu540/Image'.
> +   Load address: 0x84000000
> +   Loading:
> #################################################################
> +            ########################################################
> #########
> +            ########################################################
> #########
> +            ########################################################
> #########
> +            ########################################################
> #########
> +            ########################################################
> #########
> +            ########################################################
> #########
> +            ########################################################
> #########
> +            ########################################################
> #########
> +            ########################################################
> #########
> +            ########################################################
> #########
> +            ########################################################
> #########
> +            ########################################################
> #########
> +            ########################################################
> #########
> +            ########################################################
> #########
> +            ########################################################
> #########
> +            ########################################################
> #########
> +            ########################################################
> #########
> +            ########################################################
> #########
> +            ########################################################
> #########
> +            ########################################################
> #########
> +            ########################################################
> #########
> +            ########################################################
> #########
> +            ########################################################
> #########
> +            ########################################################
> #########
> +            ########################################################
> #########
> +            ##########################################
> +            1.2 MiB/s
> +   done
> +   Bytes transferred = 4809458 (4962f2 hex)
> +   =>setenv kernel_gz_addr_r 0x90000000
> +   =>setenv kernel_gz_size 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@10090000: PHY present at 0
>     ethernet@10090000: Starting autonegotiation...

Apologies for the previous email that added some mail headers in the
content because of my email client issue.
Tom Rini Nov. 1, 2019, 1:29 p.m. UTC | #3
On Thu, Oct 10, 2019 at 02:23:17PM -0700, Atish Patra wrote:

> Add gz parsing logic so that booti can parse both Image
> and Image.gz to boot Linux. Currently, it is difficult to calculate
> a safe address for every board where the Image.gz 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_gz_addr_r and kernel_gz_size to make Image.gz work.
> 
> Tested on HiFive Unleashed and Qemu for RISC-V.
> 
> Signed-off-by: Atish Patra <atish.patra@wdc.com>
> ---
> I could not test this patch on any ARM64 devices due to lack of
> access to any ARM64 board. If anybody can test it on ARM64, that
> would be great.

Can we do the compression check more generally?  I'd like to be able to
see Image.xz/lz4/etc be able to be handled cleanly.  When you say the
compressed file, you do mean the Image.gz (for example) itself, right?
I would suggest documenting using $filesize after loading the compressed
image as that should always be set.  Thanks!
David Abdurachmanov Nov. 1, 2019, 1:33 p.m. UTC | #4
On Fri, Oct 11, 2019 at 12:23 AM Atish Patra <atish.patra@wdc.com> wrote:
>
> Add gz parsing logic so that booti can parse both Image
> and Image.gz to boot Linux. Currently, it is difficult to calculate
> a safe address for every board where the Image.gz 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_gz_addr_r and kernel_gz_size to make Image.gz work.
>
> Tested on HiFive Unleashed and Qemu for RISC-V.
>
> Signed-off-by: Atish Patra <atish.patra@wdc.com>

Tested-by: David Abdurachmanov <david.abdurachmanov@sifive.com>

I also incl. it in Fedora/RISCV releases.

> ---
> I could not test this patch on any ARM64 devices due to lack of
> access to any ARM64 board. If anybody can test it on ARM64, that
> would be great.
> ---
>  cmd/booti.c                | 39 ++++++++++++++++++++++++++-
>  doc/README.distro          | 11 ++++++++
>  doc/board/sifive/fu540.rst | 55 ++++++++++++++++++++++++++++++++++++++
>  3 files changed, 104 insertions(+), 1 deletion(-)
>
> diff --git a/cmd/booti.c b/cmd/booti.c
> index c36b0235df8c..6c37f84833d0 100644
> --- a/cmd/booti.c
> +++ b/cmd/booti.c
> @@ -13,6 +13,9 @@
>  #include <linux/kernel.h>
>  #include <linux/sizes.h>
>
> +DECLARE_GLOBAL_DATA_PTR;
> +#define GZ_HEADER_0 0x1f
> +#define GZ_HEADER_1 0x8b
>  /*
>   * Image booting support
>   */
> @@ -23,6 +26,10 @@ 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 gz_len;
>
>         ret = do_bootm_states(cmdtp, flag, argc, argv, BOOTM_STATE_START,
>                               images, 1);
> @@ -37,6 +44,34 @@ 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);
> +
> +       if (*(temp)  == GZ_HEADER_0 && *(temp+1) == GZ_HEADER_1) {
> +               dest = env_get_ulong("kernel_gz_addr_r", 16, 0);
> +               gz_len = env_get_ulong("kernel_gz_size", 16, 0);
> +               if (!dest || !gz_len) {
> +                       puts("kernel_gz_addr_r or kernel_gz_size is not provided for Image.gz!\n");
> +                       return -EINVAL;
> +               }
> +               if (dest < gd->ram_base || dest > gd->ram_top) {
> +                       puts("kernel_gz_addr_r size is outside of dram range!\n");
> +                       return -EINVAL;
> +               }
> +
> +               debug("Image.gz of size = 0x%08lx will be decompressed at 0x%08lx\n",
> +                     gz_len, (ulong)dest);
> +
> +               ret = image_decomp(IH_COMP_GZIP, 0, ld, IH_TYPE_KERNEL,
> +                                        (void *)dest, (void *)ld, gz_len,
> +                                        CONFIG_SYS_BOOTM_LEN, &dest_end);
> +               if (ret)
> +                       return ret;
> +               /* dest_end contains the uncompressed Image size */
> +               memmove((void *) ld, (void *)dest, dest_end);
> +               unmap_sysmem((void *)dest);
> +       }
> +       unmap_sysmem((void *)ld);
> +
>         ret = booti_setup(ld, &relocated_addr, &image_size, false);
>         if (ret != 0)
>                 return 1;
> @@ -96,10 +131,12 @@ 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 'Image' or Image.gz 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"
> +       "\tIn order to boot from Image.gz, user have to set kernel_gz_addr_r\n"
> +       "\tand kernel_gz_size enviornment variables 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..dbf6eef07e35 100644
> --- a/doc/README.distro
> +++ b/doc/README.distro
> @@ -246,6 +246,17 @@ kernel_addr_r:
>
>    A size of 16MB for the kernel is likely adequate.
>
> +kernel_gz_addr_r:
> +  Optional. This is only required if user wants to boot Linux from a Image.gz
> +  using booti command. It represents the location in RAM where a Image.gz will
> +  be decompressed temporarily. Once the decompression is complete, decompressed
> +  data will be moved kernel_addr_r for booting.
> +
> +kernel_gz_size:
> +  Optional. This is only required if user wants to boot Linux from a Image.gz
> +  using booti command. It represents the size of the Image.gz file. The size
> +  has to at least the size of Image.gz file for decompression to succeed.
> +
>  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..ad4485eb7cdb 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@10090000: PHY present at 0
>     ethernet@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
> +   ethernet@10090000: PHY present at 0
> +   ethernet@10090000: Starting autonegotiation...
> +   ethernet@10090000: Autonegotiation complete
> +   ethernet@10090000: link up, 1000Mbps full-duplex (lpa: 0x3c00)
> +   Using ethernet@10090000 device
> +   TFTP from server 10.206.4.143; our IP address is 10.206.7.133
> +   Filename '/sifive/fu540/Image'.
> +   Load address: 0x84000000
> +   Loading: #################################################################
> +            #################################################################
> +            #################################################################
> +            #################################################################
> +            #################################################################
> +            #################################################################
> +            #################################################################
> +            #################################################################
> +            #################################################################
> +            #################################################################
> +            #################################################################
> +            #################################################################
> +            #################################################################
> +            #################################################################
> +            #################################################################
> +            #################################################################
> +            #################################################################
> +            #################################################################
> +            #################################################################
> +            #################################################################
> +            #################################################################
> +            #################################################################
> +            #################################################################
> +            #################################################################
> +            #################################################################
> +            #################################################################
> +            ##########################################
> +            1.2 MiB/s
> +   done
> +   Bytes transferred = 4809458 (4962f2 hex)
> +   =>setenv kernel_gz_addr_r 0x90000000
> +   =>setenv kernel_gz_size 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@10090000: PHY present at 0
>     ethernet@10090000: Starting autonegotiation...
> --
> 2.21.0
>
> _______________________________________________
> U-Boot mailing list
> U-Boot@lists.denx.de
> https://lists.denx.de/listinfo/u-boot
Atish Patra Nov. 4, 2019, 10:20 p.m. UTC | #5
On Fri, 2019-11-01 at 09:29 -0400, Tom Rini wrote:
> On Thu, Oct 10, 2019 at 02:23:17PM -0700, Atish Patra wrote:
> 
> > Add gz parsing logic so that booti can parse both Image
> > and Image.gz to boot Linux. Currently, it is difficult to calculate
> > a safe address for every board where the Image.gz 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_gz_addr_r and kernel_gz_size to make Image.gz work.
> > 
> > Tested on HiFive Unleashed and Qemu for RISC-V.
> > 
> > Signed-off-by: Atish Patra <atish.patra@wdc.com>
> > ---
> > I could not test this patch on any ARM64 devices due to lack of
> > access to any ARM64 board. If anybody can test it on ARM64, that
> > would be great.
> 
> Can we do the compression check more generally?  I'd like to be able
> to
> see Image.xz/lz4/etc be able to be handled cleanly.

This patch is intended only handle Image.gz which is a compressed
version of kernel "Image" file. That's why relevant code is only added
to booti command.

>   When you say the
> compressed file, you do mean the Image.gz (for example) itself,
> right?

Yes.

> I would suggest documenting using $filesize after loading the
> compressed
> image as that should always be set.  Thanks!
> 

ok. I will change the kernel_gz_size to filesize.
Tom Rini Nov. 4, 2019, 10:35 p.m. UTC | #6
On Mon, Nov 04, 2019 at 10:20:33PM +0000, Atish Patra wrote:
> On Fri, 2019-11-01 at 09:29 -0400, Tom Rini wrote:
> > On Thu, Oct 10, 2019 at 02:23:17PM -0700, Atish Patra wrote:
> > 
> > > Add gz parsing logic so that booti can parse both Image
> > > and Image.gz to boot Linux. Currently, it is difficult to calculate
> > > a safe address for every board where the Image.gz 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_gz_addr_r and kernel_gz_size to make Image.gz work.
> > > 
> > > Tested on HiFive Unleashed and Qemu for RISC-V.
> > > 
> > > Signed-off-by: Atish Patra <atish.patra@wdc.com>
> > > ---
> > > I could not test this patch on any ARM64 devices due to lack of
> > > access to any ARM64 board. If anybody can test it on ARM64, that
> > > would be great.

Oh, I missed this part before.  You should be able to get fairly far
with qemu :)

> > Can we do the compression check more generally?  I'd like to be able
> > to
> > see Image.xz/lz4/etc be able to be handled cleanly.
> 
> This patch is intended only handle Image.gz which is a compressed
> version of kernel "Image" file. That's why relevant code is only added
> to booti command.

Right.  But the linux kernel will happily spit out a handful of other
compressed Image files on arm64.  I see riscv is only .gz today, but I
want to be able to handle whatever the compression is, so long as we
have it available.
Atish Patra Nov. 5, 2019, 3:51 p.m. UTC | #7
On Mon, 2019-11-04 at 17:35 -0500, Tom Rini wrote:
> On Mon, Nov 04, 2019 at 10:20:33PM +0000, Atish Patra wrote:
> > On Fri, 2019-11-01 at 09:29 -0400, Tom Rini wrote:
> > > On Thu, Oct 10, 2019 at 02:23:17PM -0700, Atish Patra wrote:
> > > 
> > > > Add gz parsing logic so that booti can parse both Image
> > > > and Image.gz to boot Linux. Currently, it is difficult to
> > > > calculate
> > > > a safe address for every board where the Image.gz 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_gz_addr_r and kernel_gz_size to make Image.gz work.
> > > > 
> > > > Tested on HiFive Unleashed and Qemu for RISC-V.
> > > > 
> > > > Signed-off-by: Atish Patra <atish.patra@wdc.com>
> > > > ---
> > > > I could not test this patch on any ARM64 devices due to lack of
> > > > access to any ARM64 board. If anybody can test it on ARM64,
> > > > that
> > > > would be great.
> 
> Oh, I missed this part before.  You should be able to get fairly far
> with qemu :)
> 
I did verify with qemu. I was requesting some tested-by on ARM64
hardware. Sorry for the confusion. I will update the commit text in
next version.

> > > Can we do the compression check more generally?  I'd like to be
> > > able
> > > to
> > > see Image.xz/lz4/etc be able to be handled cleanly.
> > 
> > This patch is intended only handle Image.gz which is a compressed
> > version of kernel "Image" file. That's why relevant code is only
> > added
> > to booti command.
> 
> Right.  But the linux kernel will happily spit out a handful of other
> compressed Image files on arm64.  I see riscv is only .gz today, but
> I
> want to be able to handle whatever the compression is, so long as we
> have it available.
> 

Ahh I misunderstood that part. I could not find any existing code to
detect to different compression formats.

If I have not missed anything, I can add that code in common/image.c
and use that function in booti.c.
Tom Rini Nov. 5, 2019, 4:43 p.m. UTC | #8
On Tue, Nov 05, 2019 at 03:51:54PM +0000, Atish Patra wrote:
> On Mon, 2019-11-04 at 17:35 -0500, Tom Rini wrote:
> > On Mon, Nov 04, 2019 at 10:20:33PM +0000, Atish Patra wrote:
> > > On Fri, 2019-11-01 at 09:29 -0400, Tom Rini wrote:
> > > > On Thu, Oct 10, 2019 at 02:23:17PM -0700, Atish Patra wrote:
> > > > 
> > > > > Add gz parsing logic so that booti can parse both Image
> > > > > and Image.gz to boot Linux. Currently, it is difficult to
> > > > > calculate
> > > > > a safe address for every board where the Image.gz 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_gz_addr_r and kernel_gz_size to make Image.gz work.
> > > > > 
> > > > > Tested on HiFive Unleashed and Qemu for RISC-V.
> > > > > 
> > > > > Signed-off-by: Atish Patra <atish.patra@wdc.com>
> > > > > ---
> > > > > I could not test this patch on any ARM64 devices due to lack of
> > > > > access to any ARM64 board. If anybody can test it on ARM64,
> > > > > that
> > > > > would be great.
> > 
> > Oh, I missed this part before.  You should be able to get fairly far
> > with qemu :)
> 
> I did verify with qemu. I was requesting some tested-by on ARM64
> hardware. Sorry for the confusion. I will update the commit text in
> next version.

Ah, OK.

> > > > Can we do the compression check more generally?  I'd like to be
> > > > able
> > > > to
> > > > see Image.xz/lz4/etc be able to be handled cleanly.
> > > 
> > > This patch is intended only handle Image.gz which is a compressed
> > > version of kernel "Image" file. That's why relevant code is only
> > > added
> > > to booti command.
> > 
> > Right.  But the linux kernel will happily spit out a handful of other
> > compressed Image files on arm64.  I see riscv is only .gz today, but
> > I
> > want to be able to handle whatever the compression is, so long as we
> > have it available.
> > 
> 
> Ahh I misunderstood that part. I could not find any existing code to
> detect to different compression formats.
> 
> If I have not missed anything, I can add that code in common/image.c
> and use that function in booti.c.

Right, it's something we don't have today.  But I _think_ we have enough
of a general abstraction setup such that just like how we have "load"
and "ls" and such that will figure out the underlying filesystem we
could have "uncompress" (or perhaps something else, that might be an
alias for gunzip already) that will figure out what the compression is
based on the header and do the right thing.  Thanks!
diff mbox series

Patch

diff --git a/cmd/booti.c b/cmd/booti.c
index c36b0235df8c..6c37f84833d0 100644
--- a/cmd/booti.c
+++ b/cmd/booti.c
@@ -13,6 +13,9 @@ 
 #include <linux/kernel.h>
 #include <linux/sizes.h>
 
+DECLARE_GLOBAL_DATA_PTR;
+#define GZ_HEADER_0 0x1f
+#define GZ_HEADER_1 0x8b
 /*
  * Image booting support
  */
@@ -23,6 +26,10 @@  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 gz_len;
 
 	ret = do_bootm_states(cmdtp, flag, argc, argv, BOOTM_STATE_START,
 			      images, 1);
@@ -37,6 +44,34 @@  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);
+
+	if (*(temp)  == GZ_HEADER_0 && *(temp+1) == GZ_HEADER_1) {
+		dest = env_get_ulong("kernel_gz_addr_r", 16, 0);
+		gz_len = env_get_ulong("kernel_gz_size", 16, 0);
+		if (!dest || !gz_len) {
+			puts("kernel_gz_addr_r or kernel_gz_size is not provided for Image.gz!\n");
+			return -EINVAL;
+		}
+		if (dest < gd->ram_base || dest > gd->ram_top) {
+			puts("kernel_gz_addr_r size is outside of dram range!\n");
+			return -EINVAL;
+		}
+
+		debug("Image.gz of size = 0x%08lx will be decompressed at 0x%08lx\n",
+		      gz_len, (ulong)dest);
+
+		ret = image_decomp(IH_COMP_GZIP, 0, ld, IH_TYPE_KERNEL,
+					 (void *)dest, (void *)ld, gz_len,
+					 CONFIG_SYS_BOOTM_LEN, &dest_end);
+		if (ret)
+			return ret;
+		/* dest_end contains the uncompressed Image size */
+		memmove((void *) ld, (void *)dest, dest_end);
+		unmap_sysmem((void *)dest);
+	}
+	unmap_sysmem((void *)ld);
+
 	ret = booti_setup(ld, &relocated_addr, &image_size, false);
 	if (ret != 0)
 		return 1;
@@ -96,10 +131,12 @@  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 'Image' or Image.gz 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"
+	"\tIn order to boot from Image.gz, user have to set kernel_gz_addr_r\n"
+	"\tand kernel_gz_size enviornment variables 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..dbf6eef07e35 100644
--- a/doc/README.distro
+++ b/doc/README.distro
@@ -246,6 +246,17 @@  kernel_addr_r:
 
   A size of 16MB for the kernel is likely adequate.
 
+kernel_gz_addr_r:
+  Optional. This is only required if user wants to boot Linux from a Image.gz
+  using booti command. It represents the location in RAM where a Image.gz will
+  be decompressed temporarily. Once the decompression is complete, decompressed
+  data will be moved kernel_addr_r for booting.
+
+kernel_gz_size:
+  Optional. This is only required if user wants to boot Linux from a Image.gz
+  using booti command. It represents the size of the Image.gz file. The size
+  has to at least the size of Image.gz file for decompression to succeed.
+
 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..ad4485eb7cdb 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@10090000: PHY present at 0
    ethernet@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
+   ethernet@10090000: PHY present at 0
+   ethernet@10090000: Starting autonegotiation...
+   ethernet@10090000: Autonegotiation complete
+   ethernet@10090000: link up, 1000Mbps full-duplex (lpa: 0x3c00)
+   Using ethernet@10090000 device
+   TFTP from server 10.206.4.143; our IP address is 10.206.7.133
+   Filename '/sifive/fu540/Image'.
+   Load address: 0x84000000
+   Loading: #################################################################
+            #################################################################
+            #################################################################
+            #################################################################
+            #################################################################
+            #################################################################
+            #################################################################
+            #################################################################
+            #################################################################
+            #################################################################
+            #################################################################
+            #################################################################
+            #################################################################
+            #################################################################
+            #################################################################
+            #################################################################
+            #################################################################
+            #################################################################
+            #################################################################
+            #################################################################
+            #################################################################
+            #################################################################
+            #################################################################
+            #################################################################
+            #################################################################
+            #################################################################
+            ##########################################
+            1.2 MiB/s
+   done
+   Bytes transferred = 4809458 (4962f2 hex)
+   =>setenv kernel_gz_addr_r 0x90000000
+   =>setenv kernel_gz_size 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@10090000: PHY present at 0
    ethernet@10090000: Starting autonegotiation...