Linux Audio

Check our new training course

Loading...
v3.1
 
  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
v5.9
  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