Patchwork [4/4] ppc4xx: load Bamboo kernel, initrd, and fdt at fixed addresses

login
register
mail settings
Submitter Hollis Blanchard
Date Aug. 5, 2010, 12:21 a.m.
Message ID <1280967697-1875-5-git-send-email-hollis@penguinppc.org>
Download mbox | patch
Permalink /patch/60910/
State New
Headers show

Comments

Hollis Blanchard - Aug. 5, 2010, 12:21 a.m.
We can't use the return value of load_uimage() for the kernel because it
can't account for BSS size, and the PowerPC kernel does not relocate
blobs before zeroing BSS.

Instead, we now load at the fixed addresses chosen by u-boot (the normal
firmware for the board).

Signed-off-by: Hollis Blanchard <hollis@penguinppc.org>

---
 hw/ppc440_bamboo.c |   39 ++++++++++++++++++---------------------
 1 files changed, 18 insertions(+), 21 deletions(-)

This fixes a critical bug in PowerPC 440 Bamboo board emulation.
Edgar Iglesias - Aug. 5, 2010, 4:57 a.m.
On Wed, Aug 04, 2010 at 05:21:37PM -0700, Hollis Blanchard wrote:
> We can't use the return value of load_uimage() for the kernel because it
> can't account for BSS size, and the PowerPC kernel does not relocate
> blobs before zeroing BSS.
> 
> Instead, we now load at the fixed addresses chosen by u-boot (the normal
> firmware for the board).
> 
> Signed-off-by: Hollis Blanchard <hollis@penguinppc.org>


This looks good to me, thanks Hollis.

Acked-by: Edgar E. Iglesias <edgar.iglesias@gmail.com>


> 
> ---
>  hw/ppc440_bamboo.c |   39 ++++++++++++++++++---------------------
>  1 files changed, 18 insertions(+), 21 deletions(-)
> 
> This fixes a critical bug in PowerPC 440 Bamboo board emulation.
> 
> diff --git a/hw/ppc440_bamboo.c b/hw/ppc440_bamboo.c
> index d471d5d..34ddf45 100644
> --- a/hw/ppc440_bamboo.c
> +++ b/hw/ppc440_bamboo.c
> @@ -27,6 +27,11 @@
>  
>  #define BINARY_DEVICE_TREE_FILE "bamboo.dtb"
>  
> +/* from u-boot */
> +#define KERNEL_ADDR  0x1000000
> +#define FDT_ADDR     0x1800000
> +#define RAMDISK_ADDR 0x1900000
> +
>  static int bamboo_load_device_tree(target_phys_addr_t addr,
>                                       uint32_t ramsize,
>                                       target_phys_addr_t initrd_base,
> @@ -98,10 +103,8 @@ static void bamboo_init(ram_addr_t ram_size,
>      uint64_t elf_lowaddr;
>      target_phys_addr_t entry = 0;
>      target_phys_addr_t loadaddr = 0;
> -    target_long kernel_size = 0;
> -    target_ulong initrd_base = 0;
>      target_long initrd_size = 0;
> -    target_ulong dt_base = 0;
> +    int success;
>      int i;
>  
>      /* Setup CPU. */
> @@ -118,15 +121,15 @@ static void bamboo_init(ram_addr_t ram_size,
>  
>      /* Load kernel. */
>      if (kernel_filename) {
> -        kernel_size = load_uimage(kernel_filename, &entry, &loadaddr, NULL);
> -        if (kernel_size < 0) {
> -            kernel_size = load_elf(kernel_filename, NULL, NULL, &elf_entry,
> -                                   &elf_lowaddr, NULL, 1, ELF_MACHINE, 0);
> +        success = load_uimage(kernel_filename, &entry, &loadaddr, NULL);
> +        if (success < 0) {
> +            success = load_elf(kernel_filename, NULL, NULL, &elf_entry,
> +                               &elf_lowaddr, NULL, 1, ELF_MACHINE, 0);
>              entry = elf_entry;
>              loadaddr = elf_lowaddr;
>          }
>          /* XXX try again as binary */
> -        if (kernel_size < 0) {
> +        if (success < 0) {
>              fprintf(stderr, "qemu: could not load kernel '%s'\n",
>                      kernel_filename);
>              exit(1);
> @@ -135,26 +138,20 @@ static void bamboo_init(ram_addr_t ram_size,
>  
>      /* Load initrd. */
>      if (initrd_filename) {
> -        initrd_base = kernel_size + loadaddr;
> -        initrd_size = load_image_targphys(initrd_filename, initrd_base,
> -                                          ram_size - initrd_base);
> +        initrd_size = load_image_targphys(initrd_filename, RAMDISK_ADDR,
> +                                          ram_size - RAMDISK_ADDR);
>  
>          if (initrd_size < 0) {
> -            fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
> -                    initrd_filename);
> +            fprintf(stderr, "qemu: could not load ram disk '%s' at %x\n",
> +                    initrd_filename, RAMDISK_ADDR);
>              exit(1);
>          }
>      }
>  
>      /* If we're loading a kernel directly, we must load the device tree too. */
>      if (kernel_filename) {
> -        if (initrd_base)
> -            dt_base = initrd_base + initrd_size;
> -        else
> -            dt_base = kernel_size + loadaddr;
> -
> -        if (bamboo_load_device_tree(dt_base, ram_size,
> -                        initrd_base, initrd_size, kernel_cmdline) < 0) {
> +        if (bamboo_load_device_tree(FDT_ADDR, ram_size, RAMDISK_ADDR,
> +                                    initrd_size, kernel_cmdline) < 0) {
>              fprintf(stderr, "couldn't load device tree\n");
>              exit(1);
>          }
> @@ -163,7 +160,7 @@ static void bamboo_init(ram_addr_t ram_size,
>  
>          /* Set initial guest state. */
>          env->gpr[1] = (16<<20) - 8;
> -        env->gpr[3] = dt_base;
> +        env->gpr[3] = FDT_ADDR;
>          env->nip = entry;
>          /* XXX we currently depend on KVM to create some initial TLB entries. */
>      }
> -- 
> 1.7.2
> 
>
Liu Yu-B13201 - Aug. 6, 2010, 2:39 a.m.
> -----Original Message-----
> From: kvm-ppc-owner@vger.kernel.org 
> [mailto:kvm-ppc-owner@vger.kernel.org] On Behalf Of Hollis Blanchard
> Sent: Thursday, August 05, 2010 8:22 AM
> To: qemu-devel@nongnu.org
> Cc: kvm-ppc@vger.kernel.org
> Subject: [PATCH 4/4] ppc4xx: load Bamboo kernel, initrd, and 
> fdt at fixed addresses
> 
> We can't use the return value of load_uimage() for the kernel 
> because it
> can't account for BSS size, and the PowerPC kernel does not relocate
> blobs before zeroing BSS.
> 
> Instead, we now load at the fixed addresses chosen by u-boot 
> (the normal
> firmware for the board).
> 

Hollis,

What will us do if the uImage become bigger and fixed size is not
enough?


Yu
Hollis Blanchard - Aug. 6, 2010, 5:55 p.m.
On Thu, Aug 5, 2010 at 7:39 PM, Liu Yu-B13201 <B13201@freescale.com> wrote:
>
>
>> -----Original Message-----
>> From: kvm-ppc-owner@vger.kernel.org
>> [mailto:kvm-ppc-owner@vger.kernel.org] On Behalf Of Hollis Blanchard
>> Sent: Thursday, August 05, 2010 8:22 AM
>> To: qemu-devel@nongnu.org
>> Cc: kvm-ppc@vger.kernel.org
>> Subject: [PATCH 4/4] ppc4xx: load Bamboo kernel, initrd, and
>> fdt at fixed addresses
>>
>> We can't use the return value of load_uimage() for the kernel
>> because it
>> can't account for BSS size, and the PowerPC kernel does not relocate
>> blobs before zeroing BSS.
>>
>> Instead, we now load at the fixed addresses chosen by u-boot
>> (the normal
>> firmware for the board).
>>
>
> What will us do if the uImage become bigger and fixed size is not
> enough?

That was my question to Edgar, which was not answered. In u-boot, one
would change some environment variables. With this code in qemu, the
only recourse would be to edit ppc440_bamboo.c and rebuild.

Perhaps in the future we can do something more sophisticated by
specifying load addresses in a qemu device tree, but I don't
understand that stuff enough to know if that is an intended use.

-Hollis
Edgar Iglesias - Aug. 6, 2010, 6:12 p.m.
On Fri, Aug 06, 2010 at 10:55:36AM -0700, Hollis Blanchard wrote:
> On Thu, Aug 5, 2010 at 7:39 PM, Liu Yu-B13201 <B13201@freescale.com> wrote:
> >
> >
> >> -----Original Message-----
> >> From: kvm-ppc-owner@vger.kernel.org
> >> [mailto:kvm-ppc-owner@vger.kernel.org] On Behalf Of Hollis Blanchard
> >> Sent: Thursday, August 05, 2010 8:22 AM
> >> To: qemu-devel@nongnu.org
> >> Cc: kvm-ppc@vger.kernel.org
> >> Subject: [PATCH 4/4] ppc4xx: load Bamboo kernel, initrd, and
> >> fdt at fixed addresses
> >>
> >> We can't use the return value of load_uimage() for the kernel
> >> because it
> >> can't account for BSS size, and the PowerPC kernel does not relocate
> >> blobs before zeroing BSS.
> >>
> >> Instead, we now load at the fixed addresses chosen by u-boot
> >> (the normal
> >> firmware for the board).
> >>
> >
> > What will us do if the uImage become bigger and fixed size is not
> > enough?
> 
> That was my question to Edgar, which was not answered. In u-boot, one
> would change some environment variables. With this code in qemu, the
> only recourse would be to edit ppc440_bamboo.c and rebuild.

My objection to the first patch was mainly about putting ppc related
magics into the generic load_uimage call. If you want to do clever
things in the ppc bootloading code, that may be fine, but in IMO you
should try to mimic the uboot behaviour as much as possible when loading
uimages.

Cheers

Patch

diff --git a/hw/ppc440_bamboo.c b/hw/ppc440_bamboo.c
index d471d5d..34ddf45 100644
--- a/hw/ppc440_bamboo.c
+++ b/hw/ppc440_bamboo.c
@@ -27,6 +27,11 @@ 
 
 #define BINARY_DEVICE_TREE_FILE "bamboo.dtb"
 
+/* from u-boot */
+#define KERNEL_ADDR  0x1000000
+#define FDT_ADDR     0x1800000
+#define RAMDISK_ADDR 0x1900000
+
 static int bamboo_load_device_tree(target_phys_addr_t addr,
                                      uint32_t ramsize,
                                      target_phys_addr_t initrd_base,
@@ -98,10 +103,8 @@  static void bamboo_init(ram_addr_t ram_size,
     uint64_t elf_lowaddr;
     target_phys_addr_t entry = 0;
     target_phys_addr_t loadaddr = 0;
-    target_long kernel_size = 0;
-    target_ulong initrd_base = 0;
     target_long initrd_size = 0;
-    target_ulong dt_base = 0;
+    int success;
     int i;
 
     /* Setup CPU. */
@@ -118,15 +121,15 @@  static void bamboo_init(ram_addr_t ram_size,
 
     /* Load kernel. */
     if (kernel_filename) {
-        kernel_size = load_uimage(kernel_filename, &entry, &loadaddr, NULL);
-        if (kernel_size < 0) {
-            kernel_size = load_elf(kernel_filename, NULL, NULL, &elf_entry,
-                                   &elf_lowaddr, NULL, 1, ELF_MACHINE, 0);
+        success = load_uimage(kernel_filename, &entry, &loadaddr, NULL);
+        if (success < 0) {
+            success = load_elf(kernel_filename, NULL, NULL, &elf_entry,
+                               &elf_lowaddr, NULL, 1, ELF_MACHINE, 0);
             entry = elf_entry;
             loadaddr = elf_lowaddr;
         }
         /* XXX try again as binary */
-        if (kernel_size < 0) {
+        if (success < 0) {
             fprintf(stderr, "qemu: could not load kernel '%s'\n",
                     kernel_filename);
             exit(1);
@@ -135,26 +138,20 @@  static void bamboo_init(ram_addr_t ram_size,
 
     /* Load initrd. */
     if (initrd_filename) {
-        initrd_base = kernel_size + loadaddr;
-        initrd_size = load_image_targphys(initrd_filename, initrd_base,
-                                          ram_size - initrd_base);
+        initrd_size = load_image_targphys(initrd_filename, RAMDISK_ADDR,
+                                          ram_size - RAMDISK_ADDR);
 
         if (initrd_size < 0) {
-            fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
-                    initrd_filename);
+            fprintf(stderr, "qemu: could not load ram disk '%s' at %x\n",
+                    initrd_filename, RAMDISK_ADDR);
             exit(1);
         }
     }
 
     /* If we're loading a kernel directly, we must load the device tree too. */
     if (kernel_filename) {
-        if (initrd_base)
-            dt_base = initrd_base + initrd_size;
-        else
-            dt_base = kernel_size + loadaddr;
-
-        if (bamboo_load_device_tree(dt_base, ram_size,
-                        initrd_base, initrd_size, kernel_cmdline) < 0) {
+        if (bamboo_load_device_tree(FDT_ADDR, ram_size, RAMDISK_ADDR,
+                                    initrd_size, kernel_cmdline) < 0) {
             fprintf(stderr, "couldn't load device tree\n");
             exit(1);
         }
@@ -163,7 +160,7 @@  static void bamboo_init(ram_addr_t ram_size,
 
         /* Set initial guest state. */
         env->gpr[1] = (16<<20) - 8;
-        env->gpr[3] = dt_base;
+        env->gpr[3] = FDT_ADDR;
         env->nip = entry;
         /* XXX we currently depend on KVM to create some initial TLB entries. */
     }