On Mon, 2006-09-18 at 08:40 +0200, Sven Luther wrote:
> Hi benh, can you have a look at this patch ? It fixes the oldworld initramfs
> problem in newer kernels.

Ok, so what about that:

It looks like older OF "setprop" is bogus and isn't actually copying the
data but just taking a pointer. The LongTrail workaround also has that
problem as "property" will not copy the data. This fixes the workaround
and applies it to Apple OF 1.0.5.

Signed-off-by: Benjamin Herrenschmidt <[EMAIL PROTECTED]>
---

Paulus: Please merge if [EMAIL PROTECTED] sends a success report.

Index: linux-tika/arch/powerpc/kernel/prom_init.c
===================================================================
--- linux-tika.orig/arch/powerpc/kernel/prom_init.c     2006-09-02 
09:53:00.000000000 +1000
+++ linux-tika/arch/powerpc/kernel/prom_init.c  2006-09-18 20:55:26.000000000 
+1000
@@ -102,7 +102,7 @@
 #endif
 
 #define OF_WA_CLAIM    1       /* do phys/virt claim separately, then map */
-#define OF_WA_LONGTRAIL        2       /* work around longtrail bugs */
+#define OF_WA_SETPROP  2       /* work around setprop bugs */
 
 #define PROM_BUG() do {                                                \
         prom_printf("kernel BUG at %s line 0x%x!\n",           \
@@ -472,7 +472,7 @@
 {
        char cmd[256], *p;
 
-       if (!(OF_WORKAROUNDS & OF_WA_LONGTRAIL))
+       if (!(OF_WORKAROUNDS & OF_WA_SETPROP))
                return call_prom("setprop", 4, 1, node, ADDR(pname),
                                 (u32)(unsigned long) value, (u32) valuelen);
 
@@ -482,6 +482,7 @@
        add_string(&p, nodename);
        add_string(&p, tohex((u32)(unsigned long) value));
        add_string(&p, tohex(valuelen));
+       add_string(&p, "encode-bytes");
        add_string(&p, tohex(ADDR(pname)));
        add_string(&p, tohex(strlen(RELOC(pname))));
        add_string(&p, "property");
@@ -1466,9 +1467,9 @@
        version[sizeof(version) - 1] = 0;
        /* XXX might need to add other versions here */
        if (strcmp(version, "Open Firmware, 1.0.5") == 0)
-               of_workarounds = OF_WA_CLAIM;
+               of_workarounds = OF_WA_CLAIM | OF_WA_SETPROP;
        else if (strncmp(version, "FirmWorks,3.", 12) == 0) {
-               of_workarounds = OF_WA_CLAIM | OF_WA_LONGTRAIL;
+               of_workarounds = OF_WA_CLAIM | OF_WA_SETPROP;
                call_prom("interpret", 1, 1, "dev /memory 0 to allow-reclaim");
        } else
                return;


> Friendly,
> 
> Sven Luther
> ----- Forwarded message from Christian Aichinger <[EMAIL PROTECTED]> -----
> 
> Date: Sun, 17 Sep 2006 17:17:40 +0200
> From: Christian Aichinger <[EMAIL PROTECTED]>
> To: [EMAIL PROTECTED]
> Cc: [EMAIL PROTECTED], debian-kernel@lists.debian.org
> Subject: Re: Bug#366620: 2.6.16-1-powerpc fails to mount rootfs, 
> 2.6.15-1-powerpc works
> Message-ID: <[EMAIL PROTECTED]>
> Mail-Followup-To: Christian Aichinger <[EMAIL PROTECTED]>,
>       [EMAIL PROTECTED], [EMAIL PROTECTED],
>       debian-kernel@lists.debian.org
> 
> On Fri, Sep 15, 2006 at 11:21:33AM +0200, Christian Aichinger wrote:
> > The kernel somehow loses the information where the initrd image is
> > placed in memory. The correct data is there in
> > arch/powerpc/kernel/prom_init.c:prom_check_initrd(), but in
> > init/initramfs.c:populate_rootfs() it's wrong, initrd_{start,end}
> > are both 0.
> 
> arch/powerpc/kernel/prom_init.c:prom_check_initrd() is broken. The
> relevant part of the code is:
> 
> ,------------------
> |   unsigned long val;
> |   ...
> |   val = RELOC(prom_initrd_start);                                           
>                                                                               
>                                                                         
> |   prom_setprop(_prom->chosen, "/chosen", "linux,initrd-start",              
>                                                                               
>                                                                         
> |            &val, sizeof(val));                                              
>                                                                               
>                                                                         
> |   val = RELOC(prom_initrd_end);                                             
>                                                                               
>                                                                         
> |   prom_setprop(_prom->chosen, "/chosen", "linux,initrd-end",                
>                                                                               
>                                                                         
> |            &val, sizeof(val));                                              
>                                                                               
>                                                                         
> `------------------
> 
> As you can see it tries to store pointers to initrd start/end in the
> /chosen node, however in reality it stores the address of val, a
> local variable. Since that's long gone invalid when the values are
> read out from /chosen again, the result is undefined.
> 
> The attached is a patch fixing the problem. It would be nice if the
> bug submitters could test it to see if it fixes their problems too.
> 
> Cheers,
> Christian Aichinger
> 
> PS: arch/powerpc/platforms/powermac/bootx_init.c does something
> similar, though it looks saner, as it copies *val into it's own
> permanent memory block AFAICS.
> 
> --- a/arch/powerpc/kernel/prom_init.c 2006-09-15 18:33:50.000000000 +0200
> +++ b/arch/powerpc/kernel/prom_init.c 2006-09-15 18:33:44.000000000 +0200
> @@ -2141,17 +2141,17 @@
>               struct prom_t *_prom = &RELOC(prom);
>  
>       if (r3 && r4 && r4 != 0xdeadbeef) {
> -             unsigned long val;
> +             unsigned long *ptr;
>  
>               RELOC(prom_initrd_start) = is_kernel_addr(r3) ? __pa(r3) : r3;
>               RELOC(prom_initrd_end) = RELOC(prom_initrd_start) + r4;
>  
> -             val = RELOC(prom_initrd_start);
> +             ptr = &RELOC(prom_initrd_start);
>               prom_setprop(_prom->chosen, "/chosen", "linux,initrd-start",
> -                          &val, sizeof(val));
> -             val = RELOC(prom_initrd_end);
> +                          ptr, sizeof(prom_initrd_start));
> +             ptr = &RELOC(prom_initrd_end);
>               prom_setprop(_prom->chosen, "/chosen", "linux,initrd-end",
> -                          &val, sizeof(val));
> +                          ptr, sizeof(prom_initrd_end));
>  
>               reserve_mem(RELOC(prom_initrd_start),
>                           RELOC(prom_initrd_end) - RELOC(prom_initrd_start));
> 
> 
> 
> 
> ----- End forwarded message -----



-- 
To UNSUBSCRIBE, email to [EMAIL PROTECTED]
with a subject of "unsubscribe". Trouble? Contact [EMAIL PROTECTED]

Reply via email to