MA-18913 Load dtb according to kernel address
authorJi Luo <ji.luo@nxp.com>
Tue, 13 Apr 2021 05:03:57 +0000 (13:03 +0800)
committerJi Luo <ji.luo@nxp.com>
Thu, 13 May 2021 01:49:19 +0000 (09:49 +0800)
As the kernel image will get bigger after enabling some debug
tools, 64MB kernel max size is not enough. Load the dtb to the
address right after linux kernel instead of setting fixed offset
to the start of kernel image.

The "kernel_size" in boot image header is the physical size of
"Image" instead of the memory size which the linux requires to
boot.

Test: boots on imx8mp/imx8qm.

Change-Id: I5946c8530610ff0742f2a911aaeccf7636938b94
Signed-off-by: Ji Luo <ji.luo@nxp.com>
Reviewed-by: Wang Haoran <elven.wang@nxp.com>
(cherry picked from commit c1f83790077516a64397467fce5880be0871f615)

common/image-android.c
drivers/fastboot/fb_fsl/fb_fsl_boot.c
include/image.h

index 83ed2f0..fb32c94 100644 (file)
@@ -801,3 +801,32 @@ bool image_arm64(void *images)
                return true;
        return false;
 }
+
+uint32_t kernel_size(void *images)
+{
+       struct header_image *ih;
+       uint32_t image_size;
+
+       ih = (struct header_image *)images;
+       image_size = le64_to_cpu(ih->image_size);
+
+       return image_size;
+}
+
+ulong kernel_relocate_addr(ulong images)
+{
+       struct header_image *ih;
+       ulong relocated_addr, text_offset;
+
+       ih = (struct header_image *)images;
+       text_offset = le64_to_cpu(ih->text_offset);
+
+       if (le64_to_cpu(ih->res1) & BIT(3))
+               relocated_addr = images - text_offset;
+       else
+               relocated_addr = gd->bd->bi_dram[0].start;
+
+       relocated_addr = ALIGN(relocated_addr, SZ_2M) + text_offset;
+
+       return relocated_addr;
+}
index b1df919..500d6f0 100644 (file)
 
 #include "fb_fsl_common.h"
 
-/* max kernel image size */
-#ifdef CONFIG_ARCH_IMX8
-/* imx8q has more limitation so we assign less memory here. */
-#define MAX_KERNEL_LEN (60 * 1024 * 1024)
-#else
-#define MAX_KERNEL_LEN (64 * 1024 * 1024)
-#endif
+/* max kernel image size, used for compressed kernel image */
+#define MAX_KERNEL_LEN (96 * 1024 * 1024)
 
 /* Offset (in u32's) of start and end fields in the zImage header. */
 #define ZIMAGE_START_ADDR      10
@@ -559,6 +554,7 @@ int do_boota(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) {
 
        ulong addr = 0;
        u32 avb_metric;
+       u32 kernel_image_size = 0;
        bool check_image_arm64 =  false;
        bool is_recovery_mode = false;
        bool gki_is_supported = false;
@@ -737,6 +733,8 @@ int do_boota(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) {
                        printf("Wrong kernel image! Please check if you need to enable 'CONFIG_LZ4'\n");
                        goto fail;
                }
+
+               kernel_image_size = kernel_size((void *)((ulong)hdr_v3 + 4096));
        } else {
 #if defined (CONFIG_ARCH_IMX8) || defined (CONFIG_ARCH_IMX8M)
                if (image_arm64((void *)((ulong)hdr + hdr->page_size))) {
@@ -753,6 +751,8 @@ int do_boota(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) {
                        printf("Wrong kernel image! Please check if you need to enable 'CONFIG_LZ4'\n");
                        goto fail;
                }
+
+               kernel_image_size = kernel_size((void *)((ulong)hdr + hdr->page_size));
 #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,
@@ -785,15 +785,31 @@ int do_boota(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) {
 #endif
        }
 
+       /* Check arm64 image */
+       if (gki_is_supported)
+               check_image_arm64  = image_arm64((void *)(ulong)vendor_boot_hdr->kernel_addr);
+       else
+               check_image_arm64  = image_arm64((void *)(ulong)hdr->kernel_addr);
+
        /* Start loading the dtb file */
        u32 fdt_addr = 0;
        u32 fdt_size = 0;
        struct dt_table_header *dt_img = NULL;
 
-       if (gki_is_supported)
-               fdt_addr = (ulong)((ulong)(vendor_boot_hdr->kernel_addr) + MAX_KERNEL_LEN);
-       else
-               fdt_addr = (ulong)((ulong)(hdr->kernel_addr) + MAX_KERNEL_LEN);
+       /* Kernel addr may need relocatition, put the dtb right after the kernel image. */
+       if (check_image_arm64) {
+               ulong relocated_addr;
+
+               if (gki_is_supported)
+                       relocated_addr = kernel_relocate_addr((ulong)(vendor_boot_hdr->kernel_addr));
+               else
+                       relocated_addr = kernel_relocate_addr((ulong)(hdr->kernel_addr));
+
+               fdt_addr = relocated_addr + kernel_image_size + 1024; /* 1K gap */
+       } else {
+               /* Let's reserve 64 MB for arm32 case */
+               fdt_addr = (ulong)((ulong)(hdr->kernel_addr) + 64 * 1024 * 1024);
+       }
 
 #ifdef CONFIG_SYSTEM_RAMDISK_SUPPORT
        /* It means boot.img(recovery) do not include dtb, it need load dtb from partition */
@@ -840,21 +856,19 @@ int do_boota(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) {
 
        /* Combine cmdline and Print image info  */
        if (gki_is_supported) {
-               check_image_arm64  = image_arm64((void *)(ulong)vendor_boot_hdr->kernel_addr);
                android_image_get_kernel_v3(hdr_v3, vendor_boot_hdr);
                addr = vendor_boot_hdr->kernel_addr;
-               printf("kernel   @ %08x (%d)\n", vendor_boot_hdr->kernel_addr, hdr_v3->kernel_size);
+               printf("kernel   @ %08x (%d)\n", vendor_boot_hdr->kernel_addr, kernel_image_size);
                printf("ramdisk  @ %08x (%d)\n", vendor_boot_hdr->ramdisk_addr,
                                                vendor_boot_hdr->vendor_ramdisk_size + hdr_v3->ramdisk_size);
        } else {
-               check_image_arm64  = image_arm64((void *)(ulong)hdr->kernel_addr);
                if (check_image_arm64) {
                        android_image_get_kernel(hdr, 0, NULL, NULL);
                        addr = hdr->kernel_addr;
                } else {
                        addr = (ulong)(hdr->kernel_addr - hdr->page_size);
                }
-               printf("kernel   @ %08x (%d)\n", hdr->kernel_addr, hdr->kernel_size);
+               printf("kernel   @ %08x (%d)\n", hdr->kernel_addr, kernel_image_size);
                printf("ramdisk  @ %08x (%d)\n", hdr->ramdisk_addr, hdr->ramdisk_size);
        }
        if (fdt_size)
index 3b0d896..7ad42d7 100644 (file)
@@ -1544,6 +1544,8 @@ void android_print_contents(const struct andr_img_hdr *hdr);
 bool android_image_print_dtb_contents(ulong hdr_addr);
 #endif
 bool image_arm64(void *images);
+uint32_t kernel_size(void *images);
+ulong kernel_relocate_addr(ulong images);
 
 #endif /* CONFIG_ANDROID_BOOT_IMAGE */
 #endif /* !USE_HOSTCC */