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

Atish Patra atish.patra at wdc.com
Thu Oct 10 21:23:17 UTC 2019


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 at 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 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
+   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'.
+   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 at 10090000: PHY present at 0
    ethernet at 10090000: Starting autonegotiation...
-- 
2.21.0



More information about the U-Boot mailing list