]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blob - arch/powerpc/boot/crt0.S
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394...
[mirror_ubuntu-artful-kernel.git] / arch / powerpc / boot / crt0.S
1 /*
2 * Copyright (C) Paul Mackerras 1997.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
8 *
9 * NOTE: this code runs in 32 bit mode, is position-independent,
10 * and is packaged as ELF32.
11 */
12
13 #include "ppc_asm.h"
14
15 .text
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 */
20 .globl _zimage_start_opd
21 _zimage_start_opd:
22 .long 0x500000, 0, 0, 0
23
24 p_start: .long _start
25 p_etext: .long _etext
26 p_bss_start: .long __bss_start
27 p_end: .long _end
28
29 .weak _platform_stack_top
30 p_pstack: .long _platform_stack_top
31
32 .weak _zimage_start
33 .globl _zimage_start
34 _zimage_start:
35 .globl _zimage_start_lib
36 _zimage_start_lib:
37 /* Work out the offset between the address we were linked at
38 and the address where we're running. */
39 bl .+4
40 p_base: mflr r10 /* r10 now points to runtime addr of p_base */
41 /* grab the link address of the dynamic section in r11 */
42 addis r11,r10,(_GLOBAL_OFFSET_TABLE_-p_base)@ha
43 lwz r11,(_GLOBAL_OFFSET_TABLE_-p_base)@l(r11)
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. */
54 RELA = 7
55 RELACOUNT = 0x6ffffff9
56 li r9,0
57 li r0,0
58 9: 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
65 11: addis r8,r8,(-RELACOUNT)@ha
66 cmpwi r8,RELACOUNT@l
67 bne 12f
68 lwz r0,4(r12) /* get RELACOUNT value in r0 */
69 12: addi r12,r12,8
70 b 9b
71
72 /* The relocation section contains a list of relocations.
73 * We now do the R_PPC_RELATIVE ones, which point to words
74 * which need to be initialized with addend + offset.
75 * The R_PPC_RELATIVE ones come first and there are RELACOUNT
76 * of them. */
77 10: /* skip relocation if we don't have both */
78 cmpwi r0,0
79 beq 3f
80 cmpwi r9,0
81 beq 3f
82
83 add r9,r9,r11 /* Relocate RELA pointer */
84 mtctr r0
85 2: lbz r0,4+3(r9) /* ELF32_R_INFO(reloc->r_info) */
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
93 bdnz 2b
94
95 /* Do a cache flush for our text, in case the loader didn't */
96 3: lwz r9,p_start-p_base(r10) /* note: these are relocated now */
97 lwz r8,p_etext-p_base(r10)
98 4: dcbf r0,r9
99 icbi r0,r9
100 addi r9,r9,0x20
101 cmplw cr0,r9,r8
102 blt 4b
103 sync
104 isync
105
106 /* Clear the BSS */
107 lwz r9,p_bss_start-p_base(r10)
108 lwz r8,p_end-p_base(r10)
109 li r0,0
110 5: stw r0,0(r9)
111 addi r9,r9,4
112 cmplw cr0,r9,r8
113 blt 5b
114
115 /* Possibly set up a custom stack */
116 lwz r8,p_pstack-p_base(r10)
117 cmpwi r8,0
118 beq 6f
119 lwz r1,0(r8)
120 li r0,0
121 stwu r0,-16(r1) /* establish a stack frame */
122 6:
123
124 /* Call platform_init() */
125 bl platform_init
126
127 /* Call start */
128 b start