diff mbox series

[v2,4/4] hw/arm/boot: Honour image size field in AArch64 Image format kernels

Message ID 20190516144733.32399-5-peter.maydell@linaro.org (mailing list archive)
State New, archived
Headers show
Series hw/arm/boot: handle large Images more gracefully | expand

Commit Message

Peter Maydell May 16, 2019, 2:47 p.m. UTC
Since Linux v3.17, the kernel's Image header includes a field image_size,
which gives the total size of the kernel including unpopulated data
sections such as the BSS). If this is present, then return it from
load_aarch64_image() as the true size of the kernel rather than
just using the size of the Image file itself. This allows the code
which calculates where to put the initrd to avoid putting it in
the kernel's BSS area.

This means that we should be able to reliably load kernel images
which are larger than 128MB without accidentally putting the
initrd or dtb in locations that clash with the kernel itself.

Fixes: https://bugs.launchpad.net/qemu/+bug/1823998
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
---
 hw/arm/boot.c | 17 +++++++++++++++--
 1 file changed, 15 insertions(+), 2 deletions(-)

Comments

Alex Bennée June 13, 2019, 12:55 p.m. UTC | #1
Peter Maydell <peter.maydell@linaro.org> writes:

> Since Linux v3.17, the kernel's Image header includes a field image_size,
> which gives the total size of the kernel including unpopulated data
> sections such as the BSS). If this is present, then return it from
> load_aarch64_image() as the true size of the kernel rather than
> just using the size of the Image file itself. This allows the code
> which calculates where to put the initrd to avoid putting it in
> the kernel's BSS area.
>
> This means that we should be able to reliably load kernel images
> which are larger than 128MB without accidentally putting the
> initrd or dtb in locations that clash with the kernel itself.
>
> Fixes: https://bugs.launchpad.net/qemu/+bug/1823998
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> Reviewed-by: Richard Henderson <richard.henderson@linaro.org>

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>

> ---
>  hw/arm/boot.c | 17 +++++++++++++++--
>  1 file changed, 15 insertions(+), 2 deletions(-)
>
> diff --git a/hw/arm/boot.c b/hw/arm/boot.c
> index e441393fdf5..fc6f37ba6cf 100644
> --- a/hw/arm/boot.c
> +++ b/hw/arm/boot.c
> @@ -910,6 +910,7 @@ static uint64_t load_aarch64_image(const char *filename, hwaddr mem_base,
>                                     hwaddr *entry, AddressSpace *as)
>  {
>      hwaddr kernel_load_offset = KERNEL64_LOAD_ADDR;
> +    uint64_t kernel_size = 0;
>      uint8_t *buffer;
>      int size;
>
> @@ -937,7 +938,10 @@ static uint64_t load_aarch64_image(const char *filename, hwaddr mem_base,
>           * is only valid if the image_size is non-zero.
>           */
>          memcpy(&hdrvals, buffer + ARM64_TEXT_OFFSET_OFFSET, sizeof(hdrvals));
> -        if (hdrvals[1] != 0) {
> +
> +        kernel_size = le64_to_cpu(hdrvals[1]);
> +
> +        if (kernel_size != 0) {
>              kernel_load_offset = le64_to_cpu(hdrvals[0]);
>
>              /*
> @@ -955,12 +959,21 @@ static uint64_t load_aarch64_image(const char *filename, hwaddr mem_base,
>          }
>      }
>
> +    /*
> +     * Kernels before v3.17 don't populate the image_size field, and
> +     * raw images have no header. For those our best guess at the size
> +     * is the size of the Image file itself.
> +     */
> +    if (kernel_size == 0) {
> +        kernel_size = size;
> +    }
> +
>      *entry = mem_base + kernel_load_offset;
>      rom_add_blob_fixed_as(filename, buffer, size, *entry, as);
>
>      g_free(buffer);
>
> -    return size;
> +    return kernel_size;
>  }
>
>  static void arm_setup_direct_kernel_boot(ARMCPU *cpu,


--
Alex Bennée
diff mbox series

Patch

diff --git a/hw/arm/boot.c b/hw/arm/boot.c
index e441393fdf5..fc6f37ba6cf 100644
--- a/hw/arm/boot.c
+++ b/hw/arm/boot.c
@@ -910,6 +910,7 @@  static uint64_t load_aarch64_image(const char *filename, hwaddr mem_base,
                                    hwaddr *entry, AddressSpace *as)
 {
     hwaddr kernel_load_offset = KERNEL64_LOAD_ADDR;
+    uint64_t kernel_size = 0;
     uint8_t *buffer;
     int size;
 
@@ -937,7 +938,10 @@  static uint64_t load_aarch64_image(const char *filename, hwaddr mem_base,
          * is only valid if the image_size is non-zero.
          */
         memcpy(&hdrvals, buffer + ARM64_TEXT_OFFSET_OFFSET, sizeof(hdrvals));
-        if (hdrvals[1] != 0) {
+
+        kernel_size = le64_to_cpu(hdrvals[1]);
+
+        if (kernel_size != 0) {
             kernel_load_offset = le64_to_cpu(hdrvals[0]);
 
             /*
@@ -955,12 +959,21 @@  static uint64_t load_aarch64_image(const char *filename, hwaddr mem_base,
         }
     }
 
+    /*
+     * Kernels before v3.17 don't populate the image_size field, and
+     * raw images have no header. For those our best guess at the size
+     * is the size of the Image file itself.
+     */
+    if (kernel_size == 0) {
+        kernel_size = size;
+    }
+
     *entry = mem_base + kernel_load_offset;
     rom_add_blob_fixed_as(filename, buffer, size, *entry, as);
 
     g_free(buffer);
 
-    return size;
+    return kernel_size;
 }
 
 static void arm_setup_direct_kernel_boot(ARMCPU *cpu,