xref: /openbmc/linux/arch/powerpc/boot/crt0.S (revision 6975a783)
194b212c2SPaul Mackerras/*
294b212c2SPaul Mackerras * Copyright (C) Paul Mackerras 1997.
394b212c2SPaul Mackerras *
494b212c2SPaul Mackerras * This program is free software; you can redistribute it and/or
594b212c2SPaul Mackerras * modify it under the terms of the GNU General Public License
694b212c2SPaul Mackerras * as published by the Free Software Foundation; either version
794b212c2SPaul Mackerras * 2 of the License, or (at your option) any later version.
894b212c2SPaul Mackerras *
96975a783SMichael Ellerman * NOTE: this code runs in 32 bit mode, is position-independent,
106975a783SMichael Ellerman * and is packaged as ELF32.
1194b212c2SPaul Mackerras */
1294b212c2SPaul Mackerras
1394b212c2SPaul Mackerras#include "ppc_asm.h"
1494b212c2SPaul Mackerras
1594b212c2SPaul Mackerras	.text
166975a783SMichael Ellerman	/* A procedure descriptor used when booting this as a COFF file.
176975a783SMichael Ellerman	 * When making COFF, this comes first in the link and we're
186975a783SMichael Ellerman	 * linked at 0x500000.
196975a783SMichael Ellerman	 */
20f40e524eSPaul Mackerras	.globl	_zimage_start_opd
2166a45dd3SPaul Mackerras_zimage_start_opd:
226975a783SMichael Ellerman	.long	0x500000, 0, 0, 0
236975a783SMichael Ellerman
246975a783SMichael Ellermanp_start:	.long	_start
256975a783SMichael Ellermanp_etext:	.long	_etext
266975a783SMichael Ellermanp_bss_start:	.long	__bss_start
276975a783SMichael Ellermanp_end:		.long	_end
286975a783SMichael Ellerman
296975a783SMichael Ellerman	.weak	_platform_stack_top
306975a783SMichael Ellermanp_pstack:	.long	_platform_stack_top
3166a45dd3SPaul Mackerras
32cd197ffcSDavid Gibson	.weak	_zimage_start
3394b212c2SPaul Mackerras	.globl	_zimage_start
3494b212c2SPaul Mackerras_zimage_start:
35160cc3ecSMilton Miller	.globl	_zimage_start_lib
36160cc3ecSMilton Miller_zimage_start_lib:
3766a45dd3SPaul Mackerras	/* Work out the offset between the address we were linked at
3866a45dd3SPaul Mackerras	   and the address where we're running. */
396975a783SMichael Ellerman	bl	.+4
406975a783SMichael Ellermanp_base:	mflr	r10		/* r10 now points to runtime addr of p_base */
416975a783SMichael Ellerman	/* grab the link address of the dynamic section in r11 */
426975a783SMichael Ellerman	addis	r11,r10,(_GLOBAL_OFFSET_TABLE_-p_base)@ha
436975a783SMichael Ellerman	lwz	r11,(_GLOBAL_OFFSET_TABLE_-p_base)@l(r11)
446975a783SMichael Ellerman	cmpwi	r11,0
456975a783SMichael Ellerman	beq	3f		/* if not linked -pie */
466975a783SMichael Ellerman	/* get the runtime address of the dynamic section in r12 */
476975a783SMichael Ellerman	.weak	__dynamic_start
486975a783SMichael Ellerman	addis	r12,r10,(__dynamic_start-p_base)@ha
496975a783SMichael Ellerman	addi	r12,r12,(__dynamic_start-p_base)@l
506975a783SMichael Ellerman	subf	r11,r11,r12	/* runtime - linktime offset */
5194b212c2SPaul Mackerras
526975a783SMichael Ellerman	/* The dynamic section contains a series of tagged entries.
536975a783SMichael Ellerman	 * We need the RELA and RELACOUNT entries. */
546975a783SMichael EllermanRELA = 7
556975a783SMichael EllermanRELACOUNT = 0x6ffffff9
566975a783SMichael Ellerman	li	r9,0
576975a783SMichael Ellerman	li	r0,0
586975a783SMichael Ellerman9:	lwz	r8,0(r12)	/* get tag */
596975a783SMichael Ellerman	cmpwi	r8,0
606975a783SMichael Ellerman	beq	10f		/* end of list */
616975a783SMichael Ellerman	cmpwi	r8,RELA
626975a783SMichael Ellerman	bne	11f
636975a783SMichael Ellerman	lwz	r9,4(r12)	/* get RELA pointer in r9 */
646975a783SMichael Ellerman	b	12f
656975a783SMichael Ellerman11:	addis	r8,r8,(-RELACOUNT)@ha
666975a783SMichael Ellerman	cmpwi	r8,RELACOUNT@l
676975a783SMichael Ellerman	bne	12f
686975a783SMichael Ellerman	lwz	r0,4(r12)	/* get RELACOUNT value in r0 */
696975a783SMichael Ellerman12:	addi	r12,r12,8
706975a783SMichael Ellerman	b	9b
716975a783SMichael Ellerman
726975a783SMichael Ellerman	/* The relocation section contains a list of relocations.
736975a783SMichael Ellerman	 * We now do the R_PPC_RELATIVE ones, which point to words
746975a783SMichael Ellerman	 * which need to be initialized with addend + offset.
756975a783SMichael Ellerman	 * The R_PPC_RELATIVE ones come first and there are RELACOUNT
766975a783SMichael Ellerman	 * of them. */
776975a783SMichael Ellerman10:	/* skip relocation if we don't have both */
786975a783SMichael Ellerman	cmpwi	r0,0
7968643cfbSOlaf Hering	beq	3f
806975a783SMichael Ellerman	cmpwi	r9,0
816975a783SMichael Ellerman	beq	3f
826975a783SMichael Ellerman
836975a783SMichael Ellerman	add	r9,r9,r11	/* Relocate RELA pointer */
846975a783SMichael Ellerman	mtctr	r0
856975a783SMichael Ellerman2:	lbz	r0,4+3(r9)	/* ELF32_R_INFO(reloc->r_info) */
866975a783SMichael Ellerman	cmpwi	r0,22		/* R_PPC_RELATIVE */
876975a783SMichael Ellerman	bne	3f
886975a783SMichael Ellerman	lwz	r12,0(r9)	/* reloc->r_offset */
896975a783SMichael Ellerman	lwz	r0,8(r9)	/* reloc->r_addend */
906975a783SMichael Ellerman	add	r0,r0,r11
916975a783SMichael Ellerman	stwx	r0,r11,r12
926975a783SMichael Ellerman	addi	r9,r9,12
9368643cfbSOlaf Hering	bdnz	2b
9494b212c2SPaul Mackerras
95cd197ffcSDavid Gibson	/* Do a cache flush for our text, in case the loader didn't */
966975a783SMichael Ellerman3:	lwz	r9,p_start-p_base(r10)	/* note: these are relocated now */
976975a783SMichael Ellerman	lwz	r8,p_etext-p_base(r10)
9868643cfbSOlaf Hering4:	dcbf	r0,r9
9994b212c2SPaul Mackerras	icbi	r0,r9
10094b212c2SPaul Mackerras	addi	r9,r9,0x20
101eacb1962SOlaf Hering	cmplw	cr0,r9,r8
10268643cfbSOlaf Hering	blt	4b
10394b212c2SPaul Mackerras	sync
10494b212c2SPaul Mackerras	isync
10594b212c2SPaul Mackerras
106cd197ffcSDavid Gibson	/* Clear the BSS */
1076975a783SMichael Ellerman	lwz	r9,p_bss_start-p_base(r10)
1086975a783SMichael Ellerman	lwz	r8,p_end-p_base(r10)
1096975a783SMichael Ellerman	li	r0,0
1106975a783SMichael Ellerman5:	stw	r0,0(r9)
111cd197ffcSDavid Gibson	addi	r9,r9,4
112cd197ffcSDavid Gibson	cmplw	cr0,r9,r8
113cd197ffcSDavid Gibson	blt	5b
11494b212c2SPaul Mackerras
115cd197ffcSDavid Gibson	/* Possibly set up a custom stack */
1166975a783SMichael Ellerman	lwz	r8,p_pstack-p_base(r10)
117cd197ffcSDavid Gibson	cmpwi	r8,0
118cd197ffcSDavid Gibson	beq	6f
119cd197ffcSDavid Gibson	lwz	r1,0(r8)
120cd197ffcSDavid Gibson	li	r0,0
121cd197ffcSDavid Gibson	stwu	r0,-16(r1)	/* establish a stack frame */
122cd197ffcSDavid Gibson6:
123cd197ffcSDavid Gibson
124cd197ffcSDavid Gibson	/* Call platform_init() */
125cd197ffcSDavid Gibson	bl	platform_init
126cd197ffcSDavid Gibson
127cd197ffcSDavid Gibson	/* Call start */
128cd197ffcSDavid Gibson	b	start
129