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