]> Pileus Git - ~andy/linux/blobdiff - arch/powerpc/boot/crt0.S
Merge branch 'for-3.9' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/wq
[~andy/linux] / arch / powerpc / boot / crt0.S
index f1c4dfc635be20380d6a718d420cb83b6e4a6068..0f7428a37efbeb247d63686d627ba260c7c03337 100644 (file)
@@ -6,16 +6,28 @@
  * as published by the Free Software Foundation; either version
  * 2 of the License, or (at your option) any later version.
  *
- * NOTE: this code runs in 32 bit mode and is packaged as ELF32.
+ * NOTE: this code runs in 32 bit mode, is position-independent,
+ * and is packaged as ELF32.
  */
 
 #include "ppc_asm.h"
 
        .text
-       /* a procedure descriptor used when booting this as a COFF file */
+       /* A procedure descriptor used when booting this as a COFF file.
+        * When making COFF, this comes first in the link and we're
+        * linked at 0x500000.
+        */
        .globl  _zimage_start_opd
 _zimage_start_opd:
-       .long   _zimage_start, 0, 0, 0
+       .long   0x500000, 0, 0, 0
+
+p_start:       .long   _start
+p_etext:       .long   _etext
+p_bss_start:   .long   __bss_start
+p_end:         .long   _end
+
+       .weak   _platform_stack_top
+p_pstack:      .long   _platform_stack_top
 
        .weak   _zimage_start
        .globl  _zimage_start
@@ -24,37 +36,65 @@ _zimage_start:
 _zimage_start_lib:
        /* Work out the offset between the address we were linked at
           and the address where we're running. */
-       bl      1f
-1:     mflr    r0
-       lis     r9,1b@ha
-       addi    r9,r9,1b@l
-       subf.   r0,r9,r0
-       beq     3f              /* if running at same address as linked */
+       bl      .+4
+p_base:        mflr    r10             /* r10 now points to runtime addr of p_base */
+       /* grab the link address of the dynamic section in r11 */
+       addis   r11,r10,(_GLOBAL_OFFSET_TABLE_-p_base)@ha
+       lwz     r11,(_GLOBAL_OFFSET_TABLE_-p_base)@l(r11)
+       cmpwi   r11,0
+       beq     3f              /* if not linked -pie */
+       /* get the runtime address of the dynamic section in r12 */
+       .weak   __dynamic_start
+       addis   r12,r10,(__dynamic_start-p_base)@ha
+       addi    r12,r12,(__dynamic_start-p_base)@l
+       subf    r11,r11,r12     /* runtime - linktime offset */
+
+       /* The dynamic section contains a series of tagged entries.
+        * We need the RELA and RELACOUNT entries. */
+RELA = 7
+RELACOUNT = 0x6ffffff9
+       li      r9,0
+       li      r0,0
+9:     lwz     r8,0(r12)       /* get tag */
+       cmpwi   r8,0
+       beq     10f             /* end of list */
+       cmpwi   r8,RELA
+       bne     11f
+       lwz     r9,4(r12)       /* get RELA pointer in r9 */
+       b       12f
+11:    addis   r8,r8,(-RELACOUNT)@ha
+       cmpwi   r8,RELACOUNT@l
+       bne     12f
+       lwz     r0,4(r12)       /* get RELACOUNT value in r0 */
+12:    addi    r12,r12,8
+       b       9b
 
-       /* The .got2 section contains a list of addresses, so add
-          the address offset onto each entry. */
-       lis     r9,__got2_start@ha
-       addi    r9,r9,__got2_start@l
-       lis     r8,__got2_end@ha
-       addi    r8,r8,__got2_end@l
-       subf.   r8,r9,r8
+       /* The relocation section contains a list of relocations.
+        * We now do the R_PPC_RELATIVE ones, which point to words
+        * which need to be initialized with addend + offset.
+        * The R_PPC_RELATIVE ones come first and there are RELACOUNT
+        * of them. */
+10:    /* skip relocation if we don't have both */
+       cmpwi   r0,0
        beq     3f
-       srwi.   r8,r8,2
-       mtctr   r8
-       add     r9,r0,r9
-2:     lwz     r8,0(r9)
-       add     r8,r8,r0
-       stw     r8,0(r9)
-       addi    r9,r9,4
+       cmpwi   r9,0
+       beq     3f
+
+       add     r9,r9,r11       /* Relocate RELA pointer */
+       mtctr   r0
+2:     lbz     r0,4+3(r9)      /* ELF32_R_INFO(reloc->r_info) */
+       cmpwi   r0,22           /* R_PPC_RELATIVE */
+       bne     3f
+       lwz     r12,0(r9)       /* reloc->r_offset */
+       lwz     r0,8(r9)        /* reloc->r_addend */
+       add     r0,r0,r11
+       stwx    r0,r11,r12
+       addi    r9,r9,12
        bdnz    2b
 
        /* Do a cache flush for our text, in case the loader didn't */
-3:     lis     r9,_start@ha
-       addi    r9,r9,_start@l
-       add     r9,r0,r9
-       lis     r8,_etext@ha
-       addi    r8,r8,_etext@l
-       add     r8,r0,r8
+3:     lwz     r9,p_start-p_base(r10)  /* note: these are relocated now */
+       lwz     r8,p_etext-p_base(r10)
 4:     dcbf    r0,r9
        icbi    r0,r9
        addi    r9,r9,0x20
@@ -64,27 +104,19 @@ _zimage_start_lib:
        isync
 
        /* Clear the BSS */
-       lis     r9,__bss_start@ha
-       addi    r9,r9,__bss_start@l
-       add     r9,r0,r9
-       lis     r8,_end@ha
-       addi    r8,r8,_end@l
-       add     r8,r0,r8
-       li      r10,0
-5:     stw     r10,0(r9)
+       lwz     r9,p_bss_start-p_base(r10)
+       lwz     r8,p_end-p_base(r10)
+       li      r0,0
+5:     stw     r0,0(r9)
        addi    r9,r9,4
        cmplw   cr0,r9,r8
        blt     5b
 
        /* Possibly set up a custom stack */
-.weak  _platform_stack_top
-       lis     r8,_platform_stack_top@ha
-       addi    r8,r8,_platform_stack_top@l
+       lwz     r8,p_pstack-p_base(r10)
        cmpwi   r8,0
        beq     6f
-       add     r8,r0,r8
        lwz     r1,0(r8)
-       add     r1,r0,r1
        li      r0,0
        stwu    r0,-16(r1)      /* establish a stack frame */
 6: