MA-11385 [Android] Use compressed kernel for imx8
Use compressed kernel image instead of 'Image' for imx8 can reduce
the size of boot image which will save time in AVB to load & verify.
Lz4 compression algorithm has a very fast decompression speed so we
use lz4 compressed Image.lz4 to reduce the decompression time.
Change-Id: Id28d6c5bb1754849f15df65c40ea53551c52037f
Signed-off-by: Luo Ji <ji.luo@nxp.com>
diff --git a/drivers/usb/gadget/f_fastboot.c b/drivers/usb/gadget/f_fastboot.c
index 6e651e2..b4fec87 100755
--- a/drivers/usb/gadget/f_fastboot.c
+++ b/drivers/usb/gadget/f_fastboot.c
@@ -81,6 +81,11 @@
#define TX_ENDPOINT_MAXIMUM_PACKET_SIZE (0x0040)
#define EP_BUFFER_SIZE 4096
+
+#if defined (CONFIG_ARCH_IMX8) || defined (CONFIG_ARCH_IMX8M)
+#define DST_DECOMPRESS_LEN 1024*1024*32
+#endif
+
/*
* EP_BUFFER_SIZE must always be an integral multiple of maxpacket size
* (64 or 512 or 1024), else we break on certain controllers like DWC3
@@ -1540,11 +1545,15 @@
ulong addr = 0;
struct andr_img_hdr *hdr = NULL;
- struct andr_img_hdr *hdrload;
+ void *boot_buf = NULL;
ulong image_size;
u32 avb_metric;
bool check_image_arm64 = false;
+#if defined (CONFIG_ARCH_IMX8) || defined (CONFIG_ARCH_IMX8M)
+ size_t lz4_len = DST_DECOMPRESS_LEN;
+#endif
+
AvbABFlowResult avb_result;
AvbSlotVerifyData *avb_out_data;
AvbPartitionData *avb_loadpart;
@@ -1606,7 +1615,30 @@
}
#endif
image_size = avb_loadpart->data_size;
- memcpy((void *)(ulong)(hdr->kernel_addr - hdr->page_size), (void *)hdr, image_size);
+#if defined (CONFIG_ARCH_IMX8) || defined (CONFIG_ARCH_IMX8M)
+ /* If we are using uncompressed kernel image, copy it directly to
+ * hdr->kernel_addr, if we are using compressed lz4 kernel image,
+ * we need to decompress the kernel image first. */
+ if (image_arm64((void *)((ulong)hdr + hdr->page_size))) {
+ memcpy((void *)(long)hdr->kernel_addr,
+ (void *)((ulong)hdr + hdr->page_size), hdr->kernel_size);
+ } else {
+#ifdef CONFIG_LZ4
+ if (ulz4fn((void *)((ulong)hdr + hdr->page_size),
+ hdr->kernel_size, (void *)(ulong)hdr->kernel_addr, &lz4_len) != 0) {
+ printf("Decompress kernel fail!\n");
+ goto fail;
+ }
+#else /* CONFIG_LZ4 */
+ printf("please enable CONFIG_LZ4 if we're using compressed lz4 kernel image!\n");
+ goto fail;
+#endif /* CONFIG_LZ4 */
+ }
+#else /* CONFIG_ARCH_IMX8 || CONFIG_ARCH_IMX8M */
+ /* copy kernel image and boot header to hdr->kernel_addr - hdr->page_size */
+ memcpy((void *)(ulong)(hdr->kernel_addr - hdr->page_size), (void *)hdr,
+ hdr->page_size + ALIGN(hdr->kernel_size, hdr->page_size));
+#endif /* CONFIG_ARCH_IMX8 || CONFIG_ARCH_IMX8M */
} else if (lock_status == FASTBOOT_LOCK) { /* && verify fail */
/* if in lock state, verify enforce fail */
printf(" verify FAIL, state: LOCK\n");
@@ -1641,12 +1673,44 @@
goto fail;
}
image_size = android_image_get_end(hdr) - (ulong)hdr;
+#if defined (CONFIG_ARCH_IMX8) || defined (CONFIG_ARCH_IMX8M)
+ boot_buf = malloc(image_size);
+ /* Load boot image */
+ if (fsl_avb_ops.read_from_partition(&fsl_avb_ops, bootimg,
+ 0, image_size, boot_buf, &num_read) != AVB_IO_RESULT_OK
+ && num_read != image_size) {
+ printf("boota: read boot image error\n");
+ goto fail;
+ }
+ /* If we are using uncompressed kernel image, copy it directly to
+ * hdr->kernel_addr, if we are using compressed lz4 kernel image,
+ * we need to decompress the kernel image first. */
+ if (image_arm64((void *)((ulong)boot_buf + hdr->page_size))) {
+ memcpy((void *)(ulong)hdr->kernel_addr,
+ (void *)((ulong)boot_buf + hdr->page_size), hdr->kernel_size);
+ } else {
+#ifdef CONFIG_LZ4
+ if (ulz4fn((void *)((ulong)boot_buf + hdr->page_size),
+ hdr->kernel_size, (void *)(ulong)hdr->kernel_addr, &lz4_len) != 0) {
+ printf("Decompress kernel fail!\n");
+ goto fail;
+ }
+#else /* CONFIG_LZ4 */
+ printf("please enable CONFIG_LZ4 if we're using compressed lz4 kernel image!\n");
+ goto fail;
+#endif /* CONFIG_LZ4 */
+ }
+ hdr = (struct andr_img_hdr *)boot_buf;
+#else /* CONFIG_ARCH_IMX8 || CONFIG_ARCH_IMX8M */
if (fsl_avb_ops.read_from_partition(&fsl_avb_ops, bootimg,
0, image_size, (void *)(ulong)(hdr->kernel_addr - hdr->page_size), &num_read) != AVB_IO_RESULT_OK
&& num_read != image_size) {
printf("boota: read boot image error\n");
goto fail;
}
+ hdr = (struct andr_img_hdr *)(ulong)(hdr->kernel_addr - hdr->page_size);
+#endif /* CONFIG_ARCH_IMX8 || CONFIG_ARCH_IMX8M */
+
char bootargs_sec[ANDR_BOOT_ARGS_SIZE];
sprintf(bootargs_sec,
"androidboot.verifiedbootstate=orange androidboot.slot_suffix=%s", slot);
@@ -1660,37 +1724,34 @@
#endif
flush_cache((ulong)load_addr, image_size);
- hdrload = (struct andr_img_hdr *)(ulong)(hdr->kernel_addr - hdr->page_size);
- check_image_arm64 = image_arm64((void *)(ulong)hdrload->kernel_addr);
-
+ check_image_arm64 = image_arm64((void *)(ulong)hdr->kernel_addr);
#ifdef CONFIG_SYSTEM_RAMDISK_SUPPORT
if (is_recovery_mode)
- memcpy((void *)(ulong)hdrload->ramdisk_addr, (void *)(ulong)hdrload->kernel_addr
- + ALIGN(hdrload->kernel_size,hdrload->page_size), hdrload->ramdisk_size);
+ memcpy((void *)(ulong)hdr->ramdisk_addr, (void *)(ulong)hdr + hdr->page_size
+ + ALIGN(hdr->kernel_size, hdr->page_size), hdr->ramdisk_size);
#else
- memcpy((void *)(ulong)hdrload->ramdisk_addr, (void *)(ulong)hdrload->kernel_addr
- + ALIGN(hdrload->kernel_size,hdrload->page_size), hdrload->ramdisk_size);
+ memcpy((void *)(ulong)hdr->ramdisk_addr, (void *)(ulong)hdr + hdr->page_size
+ + ALIGN(hdr->kernel_size, hdr->page_size), hdr->ramdisk_size);
#endif
-
#ifdef CONFIG_OF_LIBFDT
/* load the dtb file */
- if (hdrload->second_size && hdrload->second_addr) {
- memcpy((void *)(ulong)hdrload->second_addr, (void *)(ulong)hdrload->kernel_addr
- + ALIGN(hdrload->kernel_size, hdrload->page_size)
- + ALIGN(hdrload->ramdisk_size, hdrload->page_size), hdr->second_size);
+ if (hdr->second_size && hdr->second_addr) {
+ memcpy((void *)(ulong)hdr->second_addr, (void *)(ulong)hdr + hdr->page_size
+ + ALIGN(hdr->kernel_size, hdr->page_size)
+ + ALIGN(hdr->ramdisk_size, hdr->page_size), hdr->second_size);
}
#endif /*CONFIG_OF_LIBFDT*/
if (check_image_arm64) {
- android_image_get_kernel(hdrload, 0, NULL, NULL);
- addr = hdrload->kernel_addr;
+ android_image_get_kernel(hdr, 0, NULL, NULL);
+ addr = hdr->kernel_addr;
} else {
- addr = (ulong)hdrload;
+ addr = (ulong)(hdr->kernel_addr - hdr->page_size);
}
- printf("kernel @ %08x (%d)\n", hdrload->kernel_addr, hdrload->kernel_size);
- printf("ramdisk @ %08x (%d)\n", hdrload->ramdisk_addr, hdrload->ramdisk_size);
+ printf("kernel @ %08x (%d)\n", hdr->kernel_addr, hdr->kernel_size);
+ printf("ramdisk @ %08x (%d)\n", hdr->ramdisk_addr, hdr->ramdisk_size);
#ifdef CONFIG_OF_LIBFDT
- if (hdrload->second_size)
- printf("fdt @ %08x (%d)\n", hdrload->second_addr, hdrload->second_size);
+ if (hdr->second_size)
+ printf("fdt @ %08x (%d)\n", hdr->second_addr, hdr->second_size);
#endif /*CONFIG_OF_LIBFDT*/
char boot_addr_start[12];
@@ -1704,8 +1765,8 @@
boot_args[0] = "bootm";
sprintf(boot_addr_start, "0x%lx", addr);
- sprintf(ramdisk_addr, "0x%x:0x%x", hdrload->ramdisk_addr, hdrload->ramdisk_size);
- sprintf(fdt_addr, "0x%x", hdrload->second_addr);
+ sprintf(ramdisk_addr, "0x%x:0x%x", hdr->ramdisk_addr, hdr->ramdisk_size);
+ sprintf(fdt_addr, "0x%x", hdr->second_addr);
/* no need to pass ramdisk addr for normal boot mode when enable CONFIG_SYSTEM_RAMDISK_SUPPORT*/
#ifdef CONFIG_SYSTEM_RAMDISK_SUPPORT
@@ -1714,6 +1775,8 @@
#endif
if (avb_out_data != NULL)
avb_slot_verify_data_free(avb_out_data);
+ if (boot_buf != NULL)
+ free(boot_buf);
#ifdef CONFIG_IMX_TRUSTY_OS
/* put ql-tipc to release resource for Linux */
@@ -1738,6 +1801,8 @@
/* avb has no recovery */
if (avb_out_data != NULL)
avb_slot_verify_data_free(avb_out_data);
+ if (boot_buf != NULL)
+ free(boot_buf);
return run_command("fastboot 0", 0);
}