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));

Attachment: signature.asc
Description: Digital signature

Reply via email to