aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/boot
diff options
context:
space:
mode:
authorMichael Ellerman <michael@ozlabs.org>2011-04-12 16:38:55 -0400
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2011-04-20 02:59:20 -0400
commit6975a783d7b40c79be4b7a7ea450e023ff7e5e02 (patch)
tree67c07efa7ca72a24bcd5d893c83fb9b3f59dce77 /arch/powerpc/boot
parentee7a2aa3d3fd10a7157dd19f737b2bafdea0458f (diff)
powerpc/boot: Allow building the zImage wrapper as a relocatable ET_DYN
This patch adds code, linker script and makefile support to allow building the zImage wrapper around the kernel as a position independent executable. This results in an ET_DYN instead of an ET_EXEC ELF output file, which can be loaded at any location by the firmware and will process its own relocations to work correctly at the loaded address. This is of interest particularly since the standard ePAPR image format must be an ET_DYN (although this patch alone is not sufficient to produce a fully ePAPR compliant boot image). Note for now we don't enable building with -pie for anything. Signed-off-by: Paul Mackerras <paulus@samba.org> Signed-off-by: David Gibson <david@gibson.dropbear.id.au> Signed-off-by: Michael Ellerman <michael@ellerman.id.au> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc/boot')
-rw-r--r--arch/powerpc/boot/crt0.S116
-rwxr-xr-xarch/powerpc/boot/wrapper9
-rw-r--r--arch/powerpc/boot/zImage.coff.lds.S6
-rw-r--r--arch/powerpc/boot/zImage.lds.S57
4 files changed, 118 insertions, 70 deletions
diff --git a/arch/powerpc/boot/crt0.S b/arch/powerpc/boot/crt0.S
index f1c4dfc635be..0f7428a37efb 100644
--- a/arch/powerpc/boot/crt0.S
+++ b/arch/powerpc/boot/crt0.S
@@ -6,16 +6,28 @@
6 * as published by the Free Software Foundation; either version 6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version. 7 * 2 of the License, or (at your option) any later version.
8 * 8 *
9 * NOTE: this code runs in 32 bit mode and is packaged as ELF32. 9 * NOTE: this code runs in 32 bit mode, is position-independent,
10 * and is packaged as ELF32.
10 */ 11 */
11 12
12#include "ppc_asm.h" 13#include "ppc_asm.h"
13 14
14 .text 15 .text
15 /* a procedure descriptor used when booting this as a COFF file */ 16 /* A procedure descriptor used when booting this as a COFF file.
17 * When making COFF, this comes first in the link and we're
18 * linked at 0x500000.
19 */
16 .globl _zimage_start_opd 20 .globl _zimage_start_opd
17_zimage_start_opd: 21_zimage_start_opd:
18 .long _zimage_start, 0, 0, 0 22 .long 0x500000, 0, 0, 0
23
24p_start: .long _start
25p_etext: .long _etext
26p_bss_start: .long __bss_start
27p_end: .long _end
28
29 .weak _platform_stack_top
30p_pstack: .long _platform_stack_top
19 31
20 .weak _zimage_start 32 .weak _zimage_start
21 .globl _zimage_start 33 .globl _zimage_start
@@ -24,37 +36,65 @@ _zimage_start:
24_zimage_start_lib: 36_zimage_start_lib:
25 /* Work out the offset between the address we were linked at 37 /* Work out the offset between the address we were linked at
26 and the address where we're running. */ 38 and the address where we're running. */
27 bl 1f 39 bl .+4
281: mflr r0 40p_base: mflr r10 /* r10 now points to runtime addr of p_base */
29 lis r9,1b@ha 41 /* grab the link address of the dynamic section in r11 */
30 addi r9,r9,1b@l 42 addis r11,r10,(_GLOBAL_OFFSET_TABLE_-p_base)@ha
31 subf. r0,r9,r0 43 lwz r11,(_GLOBAL_OFFSET_TABLE_-p_base)@l(r11)
32 beq 3f /* if running at same address as linked */ 44 cmpwi r11,0
45 beq 3f /* if not linked -pie */
46 /* get the runtime address of the dynamic section in r12 */
47 .weak __dynamic_start
48 addis r12,r10,(__dynamic_start-p_base)@ha
49 addi r12,r12,(__dynamic_start-p_base)@l
50 subf r11,r11,r12 /* runtime - linktime offset */
51
52 /* The dynamic section contains a series of tagged entries.
53 * We need the RELA and RELACOUNT entries. */
54RELA = 7
55RELACOUNT = 0x6ffffff9
56 li r9,0
57 li r0,0
589: lwz r8,0(r12) /* get tag */
59 cmpwi r8,0
60 beq 10f /* end of list */
61 cmpwi r8,RELA
62 bne 11f
63 lwz r9,4(r12) /* get RELA pointer in r9 */
64 b 12f
6511: addis r8,r8,(-RELACOUNT)@ha
66 cmpwi r8,RELACOUNT@l
67 bne 12f
68 lwz r0,4(r12) /* get RELACOUNT value in r0 */
6912: addi r12,r12,8
70 b 9b
33 71
34 /* The .got2 section contains a list of addresses, so add 72 /* The relocation section contains a list of relocations.
35 the address offset onto each entry. */ 73 * We now do the R_PPC_RELATIVE ones, which point to words
36 lis r9,__got2_start@ha 74 * which need to be initialized with addend + offset.
37 addi r9,r9,__got2_start@l 75 * The R_PPC_RELATIVE ones come first and there are RELACOUNT
38 lis r8,__got2_end@ha 76 * of them. */
39 addi r8,r8,__got2_end@l 7710: /* skip relocation if we don't have both */
40 subf. r8,r9,r8 78 cmpwi r0,0
41 beq 3f 79 beq 3f
42 srwi. r8,r8,2 80 cmpwi r9,0
43 mtctr r8 81 beq 3f
44 add r9,r0,r9 82
452: lwz r8,0(r9) 83 add r9,r9,r11 /* Relocate RELA pointer */
46 add r8,r8,r0 84 mtctr r0
47 stw r8,0(r9) 852: lbz r0,4+3(r9) /* ELF32_R_INFO(reloc->r_info) */
48 addi r9,r9,4 86 cmpwi r0,22 /* R_PPC_RELATIVE */
87 bne 3f
88 lwz r12,0(r9) /* reloc->r_offset */
89 lwz r0,8(r9) /* reloc->r_addend */
90 add r0,r0,r11
91 stwx r0,r11,r12
92 addi r9,r9,12
49 bdnz 2b 93 bdnz 2b
50 94
51 /* Do a cache flush for our text, in case the loader didn't */ 95 /* Do a cache flush for our text, in case the loader didn't */
523: lis r9,_start@ha 963: lwz r9,p_start-p_base(r10) /* note: these are relocated now */
53 addi r9,r9,_start@l 97 lwz r8,p_etext-p_base(r10)
54 add r9,r0,r9
55 lis r8,_etext@ha
56 addi r8,r8,_etext@l
57 add r8,r0,r8
584: dcbf r0,r9 984: dcbf r0,r9
59 icbi r0,r9 99 icbi r0,r9
60 addi r9,r9,0x20 100 addi r9,r9,0x20
@@ -64,27 +104,19 @@ _zimage_start_lib:
64 isync 104 isync
65 105
66 /* Clear the BSS */ 106 /* Clear the BSS */
67 lis r9,__bss_start@ha 107 lwz r9,p_bss_start-p_base(r10)
68 addi r9,r9,__bss_start@l 108 lwz r8,p_end-p_base(r10)
69 add r9,r0,r9 109 li r0,0
70 lis r8,_end@ha 1105: stw r0,0(r9)
71 addi r8,r8,_end@l
72 add r8,r0,r8
73 li r10,0
745: stw r10,0(r9)
75 addi r9,r9,4 111 addi r9,r9,4
76 cmplw cr0,r9,r8 112 cmplw cr0,r9,r8
77 blt 5b 113 blt 5b
78 114
79 /* Possibly set up a custom stack */ 115 /* Possibly set up a custom stack */
80.weak _platform_stack_top 116 lwz r8,p_pstack-p_base(r10)
81 lis r8,_platform_stack_top@ha
82 addi r8,r8,_platform_stack_top@l
83 cmpwi r8,0 117 cmpwi r8,0
84 beq 6f 118 beq 6f
85 add r8,r0,r8
86 lwz r1,0(r8) 119 lwz r1,0(r8)
87 add r1,r0,r1
88 li r0,0 120 li r0,0
89 stwu r0,-16(r1) /* establish a stack frame */ 121 stwu r0,-16(r1) /* establish a stack frame */
906: 1226:
diff --git a/arch/powerpc/boot/wrapper b/arch/powerpc/boot/wrapper
index cb97e7511d7e..fef527867811 100755
--- a/arch/powerpc/boot/wrapper
+++ b/arch/powerpc/boot/wrapper
@@ -39,6 +39,7 @@ dts=
39cacheit= 39cacheit=
40binary= 40binary=
41gzip=.gz 41gzip=.gz
42pie=
42 43
43# cross-compilation prefix 44# cross-compilation prefix
44CROSS= 45CROSS=
@@ -157,9 +158,10 @@ pmac|chrp)
157 platformo=$object/of.o 158 platformo=$object/of.o
158 ;; 159 ;;
159coff) 160coff)
160 platformo=$object/of.o 161 platformo="$object/crt0.o $object/of.o"
161 lds=$object/zImage.coff.lds 162 lds=$object/zImage.coff.lds
162 link_address='0x500000' 163 link_address='0x500000'
164 pie=
163 ;; 165 ;;
164miboot|uboot) 166miboot|uboot)
165 # miboot and U-boot want just the bare bits, not an ELF binary 167 # miboot and U-boot want just the bare bits, not an ELF binary
@@ -208,6 +210,7 @@ ps3)
208 ksection=.kernel:vmlinux.bin 210 ksection=.kernel:vmlinux.bin
209 isection=.kernel:initrd 211 isection=.kernel:initrd
210 link_address='' 212 link_address=''
213 pie=
211 ;; 214 ;;
212ep88xc|ep405|ep8248e) 215ep88xc|ep405|ep8248e)
213 platformo="$object/fixed-head.o $object/$platform.o" 216 platformo="$object/fixed-head.o $object/$platform.o"
@@ -310,9 +313,9 @@ fi
310 313
311if [ "$platform" != "miboot" ]; then 314if [ "$platform" != "miboot" ]; then
312 if [ -n "$link_address" ] ; then 315 if [ -n "$link_address" ] ; then
313 text_start="-Ttext $link_address --defsym _start=$link_address" 316 text_start="-Ttext $link_address"
314 fi 317 fi
315 ${CROSS}ld -m elf32ppc -T $lds $text_start -o "$ofile" \ 318 ${CROSS}ld -m elf32ppc -T $lds $text_start $pie -o "$ofile" \
316 $platformo $tmp $object/wrapper.a 319 $platformo $tmp $object/wrapper.a
317 rm $tmp 320 rm $tmp
318fi 321fi
diff --git a/arch/powerpc/boot/zImage.coff.lds.S b/arch/powerpc/boot/zImage.coff.lds.S
index 856dc78b14ef..de4c9e3c9344 100644
--- a/arch/powerpc/boot/zImage.coff.lds.S
+++ b/arch/powerpc/boot/zImage.coff.lds.S
@@ -3,13 +3,13 @@ ENTRY(_zimage_start_opd)
3EXTERN(_zimage_start_opd) 3EXTERN(_zimage_start_opd)
4SECTIONS 4SECTIONS
5{ 5{
6 _start = .;
7 .text : 6 .text :
8 { 7 {
8 _start = .;
9 *(.text) 9 *(.text)
10 *(.fixup) 10 *(.fixup)
11 _etext = .;
11 } 12 }
12 _etext = .;
13 . = ALIGN(4096); 13 . = ALIGN(4096);
14 .data : 14 .data :
15 { 15 {
@@ -17,9 +17,7 @@ SECTIONS
17 *(.data*) 17 *(.data*)
18 *(__builtin_*) 18 *(__builtin_*)
19 *(.sdata*) 19 *(.sdata*)
20 __got2_start = .;
21 *(.got2) 20 *(.got2)
22 __got2_end = .;
23 21
24 _dtb_start = .; 22 _dtb_start = .;
25 *(.kernel:dtb) 23 *(.kernel:dtb)
diff --git a/arch/powerpc/boot/zImage.lds.S b/arch/powerpc/boot/zImage.lds.S
index 0962d62bdb50..2bd8731f1365 100644
--- a/arch/powerpc/boot/zImage.lds.S
+++ b/arch/powerpc/boot/zImage.lds.S
@@ -3,49 +3,64 @@ ENTRY(_zimage_start)
3EXTERN(_zimage_start) 3EXTERN(_zimage_start)
4SECTIONS 4SECTIONS
5{ 5{
6 _start = .;
7 .text : 6 .text :
8 { 7 {
8 _start = .;
9 *(.text) 9 *(.text)
10 *(.fixup) 10 *(.fixup)
11 _etext = .;
11 } 12 }
12 _etext = .;
13 . = ALIGN(4096); 13 . = ALIGN(4096);
14 .data : 14 .data :
15 { 15 {
16 *(.rodata*) 16 *(.rodata*)
17 *(.data*) 17 *(.data*)
18 *(.sdata*) 18 *(.sdata*)
19 __got2_start = .;
20 *(.got2) 19 *(.got2)
21 __got2_end = .;
22 } 20 }
21 .dynsym : { *(.dynsym) }
22 .dynstr : { *(.dynstr) }
23 .dynamic :
24 {
25 __dynamic_start = .;
26 *(.dynamic)
27 }
28 .hash : { *(.hash) }
29 .interp : { *(.interp) }
30 .rela.dyn : { *(.rela*) }
23 31
24 . = ALIGN(8); 32 . = ALIGN(8);
25 _dtb_start = .; 33 .kernel:dtb :
26 .kernel:dtb : { *(.kernel:dtb) } 34 {
27 _dtb_end = .; 35 _dtb_start = .;
28 36 *(.kernel:dtb)
29 . = ALIGN(4096); 37 _dtb_end = .;
30 _vmlinux_start = .; 38 }
31 .kernel:vmlinux.strip : { *(.kernel:vmlinux.strip) }
32 _vmlinux_end = .;
33 39
34 . = ALIGN(4096); 40 . = ALIGN(4096);
35 _initrd_start = .; 41 .kernel:vmlinux.strip :
36 .kernel:initrd : { *(.kernel:initrd) } 42 {
37 _initrd_end = .; 43 _vmlinux_start = .;
44 *(.kernel:vmlinux.strip)
45 _vmlinux_end = .;
46 }
38 47
39 . = ALIGN(4096); 48 . = ALIGN(4096);
40 _edata = .; 49 .kernel:initrd :
50 {
51 _initrd_start = .;
52 *(.kernel:initrd)
53 _initrd_end = .;
54 }
41 55
42 . = ALIGN(4096); 56 . = ALIGN(4096);
43 __bss_start = .;
44 .bss : 57 .bss :
45 { 58 {
46 *(.sbss) 59 _edata = .;
47 *(.bss) 60 __bss_start = .;
61 *(.sbss)
62 *(.bss)
63 *(COMMON)
64 _end = . ;
48 } 65 }
49 . = ALIGN(4096);
50 _end = . ;
51} 66}