Loading...
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
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
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
40p_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. */
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
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. */
7710: /* 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
852: 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 */
963: lwz r9,p_start-p_base(r10) /* note: these are relocated now */
97 lwz r8,p_etext-p_base(r10)
984: 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
1105: 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 */
1226:
123
124 /* Call platform_init() */
125 bl platform_init
126
127 /* Call start */
128 b start
1/* SPDX-License-Identifier: GPL-2.0-or-later */
2/*
3 * Copyright (C) Paul Mackerras 1997.
4 *
5 * Adapted for 64 bit LE PowerPC by Andrew Tauferner
6 */
7
8#include "ppc_asm.h"
9
10RELA = 7
11RELACOUNT = 0x6ffffff9
12
13 .data
14 /* A procedure descriptor used when booting this as a COFF file.
15 * When making COFF, this comes first in the link and we're
16 * linked at 0x500000.
17 */
18 .globl _zimage_start_opd
19_zimage_start_opd:
20 .long 0x500000, 0, 0, 0
21 .text
22 b _zimage_start
23
24#ifdef __powerpc64__
25.balign 8
26p_start: .8byte _start
27p_etext: .8byte _etext
28p_bss_start: .8byte __bss_start
29p_end: .8byte _end
30
31p_toc: .8byte __toc_start + 0x8000 - p_base
32p_dyn: .8byte __dynamic_start - p_base
33p_rela: .8byte __rela_dyn_start - p_base
34p_prom: .8byte 0
35 .weak _platform_stack_top
36p_pstack: .8byte _platform_stack_top
37#else
38p_start: .long _start
39p_etext: .long _etext
40p_bss_start: .long __bss_start
41p_end: .long _end
42
43 .weak _platform_stack_top
44p_pstack: .long _platform_stack_top
45#endif
46
47 .weak _zimage_start
48_zimage_start:
49 .globl _zimage_start_lib
50_zimage_start_lib:
51 /* Work out the offset between the address we were linked at
52 and the address where we're running. */
53 bl .+4
54p_base: mflr r10 /* r10 now points to runtime addr of p_base */
55#ifndef __powerpc64__
56 /* grab the link address of the dynamic section in r11 */
57 addis r11,r10,(_GLOBAL_OFFSET_TABLE_-p_base)@ha
58 lwz r11,(_GLOBAL_OFFSET_TABLE_-p_base)@l(r11)
59 cmpwi r11,0
60 beq 3f /* if not linked -pie */
61 /* get the runtime address of the dynamic section in r12 */
62 .weak __dynamic_start
63 addis r12,r10,(__dynamic_start-p_base)@ha
64 addi r12,r12,(__dynamic_start-p_base)@l
65 subf r11,r11,r12 /* runtime - linktime offset */
66
67 /* The dynamic section contains a series of tagged entries.
68 * We need the RELA and RELACOUNT entries. */
69 li r9,0
70 li r0,0
719: lwz r8,0(r12) /* get tag */
72 cmpwi r8,0
73 beq 10f /* end of list */
74 cmpwi r8,RELA
75 bne 11f
76 lwz r9,4(r12) /* get RELA pointer in r9 */
77 b 12f
7811: addis r8,r8,(-RELACOUNT)@ha
79 cmpwi r8,RELACOUNT@l
80 bne 12f
81 lwz r0,4(r12) /* get RELACOUNT value in r0 */
8212: addi r12,r12,8
83 b 9b
84
85 /* The relocation section contains a list of relocations.
86 * We now do the R_PPC_RELATIVE ones, which point to words
87 * which need to be initialized with addend + offset.
88 * The R_PPC_RELATIVE ones come first and there are RELACOUNT
89 * of them. */
9010: /* skip relocation if we don't have both */
91 cmpwi r0,0
92 beq 3f
93 cmpwi r9,0
94 beq 3f
95
96 add r9,r9,r11 /* Relocate RELA pointer */
97 mtctr r0
982: lbz r0,4+3(r9) /* ELF32_R_INFO(reloc->r_info) */
99 cmpwi r0,22 /* R_PPC_RELATIVE */
100 bne 3f
101 lwz r12,0(r9) /* reloc->r_offset */
102 lwz r0,8(r9) /* reloc->r_addend */
103 add r0,r0,r11
104 stwx r0,r11,r12
105 addi r9,r9,12
106 bdnz 2b
107
108 /* Do a cache flush for our text, in case the loader didn't */
1093: lwz r9,p_start-p_base(r10) /* note: these are relocated now */
110 lwz r8,p_etext-p_base(r10)
1114: dcbf r0,r9
112 icbi r0,r9
113 addi r9,r9,0x20
114 cmplw cr0,r9,r8
115 blt 4b
116 sync
117 isync
118
119 /* Clear the BSS */
120 lwz r9,p_bss_start-p_base(r10)
121 lwz r8,p_end-p_base(r10)
122 li r0,0
1235: stw r0,0(r9)
124 addi r9,r9,4
125 cmplw cr0,r9,r8
126 blt 5b
127
128 /* Possibly set up a custom stack */
129 lwz r8,p_pstack-p_base(r10)
130 cmpwi r8,0
131 beq 6f
132 lwz r1,0(r8)
133 li r0,0
134 stwu r0,-16(r1) /* establish a stack frame */
1356:
136#else /* __powerpc64__ */
137 /* Save the prom pointer at p_prom. */
138 std r5,(p_prom-p_base)(r10)
139
140 /* Set r2 to the TOC. */
141 ld r2,(p_toc-p_base)(r10)
142 add r2,r2,r10
143
144 /* Grab the link address of the dynamic section in r11. */
145 ld r11,-32768(r2)
146 cmpwi r11,0
147 beq 3f /* if not linked -pie then no dynamic section */
148
149 ld r11,(p_dyn-p_base)(r10)
150 add r11,r11,r10
151 ld r9,(p_rela-p_base)(r10)
152 add r9,r9,r10
153
154 li r13,0
155 li r8,0
1569: ld r12,0(r11) /* get tag */
157 cmpdi r12,0
158 beq 12f /* end of list */
159 cmpdi r12,RELA
160 bne 10f
161 ld r13,8(r11) /* get RELA pointer in r13 */
162 b 11f
16310: addis r12,r12,(-RELACOUNT)@ha
164 cmpdi r12,RELACOUNT@l
165 bne 11f
166 ld r8,8(r11) /* get RELACOUNT value in r8 */
16711: addi r11,r11,16
168 b 9b
16912:
170 cmpdi r13,0 /* check we have both RELA and RELACOUNT */
171 cmpdi cr1,r8,0
172 beq 3f
173 beq cr1,3f
174
175 /* Calcuate the runtime offset. */
176 subf r13,r13,r9
177
178 /* Run through the list of relocations and process the
179 * R_PPC64_RELATIVE ones. */
180 mtctr r8
18113: ld r0,8(r9) /* ELF64_R_TYPE(reloc->r_info) */
182 cmpdi r0,22 /* R_PPC64_RELATIVE */
183 bne 3f
184 ld r12,0(r9) /* reloc->r_offset */
185 ld r0,16(r9) /* reloc->r_addend */
186 add r0,r0,r13
187 stdx r0,r13,r12
188 addi r9,r9,24
189 bdnz 13b
190
191 /* Do a cache flush for our text, in case the loader didn't */
1923: ld r9,p_start-p_base(r10) /* note: these are relocated now */
193 ld r8,p_etext-p_base(r10)
1944: dcbf r0,r9
195 icbi r0,r9
196 addi r9,r9,0x20
197 cmpld cr0,r9,r8
198 blt 4b
199 sync
200 isync
201
202 /* Clear the BSS */
203 ld r9,p_bss_start-p_base(r10)
204 ld r8,p_end-p_base(r10)
205 li r0,0
2065: std r0,0(r9)
207 addi r9,r9,8
208 cmpld cr0,r9,r8
209 blt 5b
210
211 /* Possibly set up a custom stack */
212 ld r8,p_pstack-p_base(r10)
213 cmpdi r8,0
214 beq 6f
215 ld r1,0(r8)
216 li r0,0
217 stdu r0,-112(r1) /* establish a stack frame */
2186:
219#endif /* __powerpc64__ */
220 /* Call platform_init() */
221 bl platform_init
222
223 /* Call start */
224 b start
225
226#ifdef __powerpc64__
227
228#define PROM_FRAME_SIZE 512
229#define SAVE_GPR(n, base) std n,8*(n)(base)
230#define REST_GPR(n, base) ld n,8*(n)(base)
231#define SAVE_2GPRS(n, base) SAVE_GPR(n, base); SAVE_GPR(n+1, base)
232#define SAVE_4GPRS(n, base) SAVE_2GPRS(n, base); SAVE_2GPRS(n+2, base)
233#define SAVE_8GPRS(n, base) SAVE_4GPRS(n, base); SAVE_4GPRS(n+4, base)
234#define SAVE_10GPRS(n, base) SAVE_8GPRS(n, base); SAVE_2GPRS(n+8, base)
235#define REST_2GPRS(n, base) REST_GPR(n, base); REST_GPR(n+1, base)
236#define REST_4GPRS(n, base) REST_2GPRS(n, base); REST_2GPRS(n+2, base)
237#define REST_8GPRS(n, base) REST_4GPRS(n, base); REST_4GPRS(n+4, base)
238#define REST_10GPRS(n, base) REST_8GPRS(n, base); REST_2GPRS(n+8, base)
239
240/* prom handles the jump into and return from firmware. The prom args pointer
241 is loaded in r3. */
242.globl prom
243prom:
244 mflr r0
245 std r0,16(r1)
246 stdu r1,-PROM_FRAME_SIZE(r1) /* Save SP and create stack space */
247
248 SAVE_GPR(2, r1)
249 SAVE_GPR(13, r1)
250 SAVE_8GPRS(14, r1)
251 SAVE_10GPRS(22, r1)
252 mfcr r10
253 std r10,8*32(r1)
254 mfmsr r10
255 std r10,8*33(r1)
256
257 /* remove MSR_LE from msr but keep MSR_SF */
258 mfmsr r10
259 rldicr r10,r10,0,62
260 mtsrr1 r10
261
262 /* Load FW address, set LR to label 1, and jump to FW */
263 bl 0f
2640: mflr r10
265 addi r11,r10,(1f-0b)
266 mtlr r11
267
268 ld r10,(p_prom-0b)(r10)
269 mtsrr0 r10
270
271 rfid
272
2731: /* Return from OF */
274 FIXUP_ENDIAN
275
276 /* Restore registers and return. */
277 rldicl r1,r1,0,32
278
279 /* Restore the MSR (back to 64 bits) */
280 ld r10,8*(33)(r1)
281 mtmsr r10
282 isync
283
284 /* Restore other registers */
285 REST_GPR(2, r1)
286 REST_GPR(13, r1)
287 REST_8GPRS(14, r1)
288 REST_10GPRS(22, r1)
289 ld r10,8*32(r1)
290 mtcr r10
291
292 addi r1,r1,PROM_FRAME_SIZE
293 ld r0,16(r1)
294 mtlr r0
295 blr
296#endif