/* * Copyright (C) Paul Mackerras 1997. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. * * NOTE: this code runs in 32 bit mode, is position-independent, * and is packaged as ELF32. */ #include "ppc_asm.h" .text /* A procedure descriptor used when booting this as a COFF file. * When making COFF, this comes first in the link and we're * linked at 0x500000. */ .globl _zimage_start_opd _zimage_start_opd: .long 0x500000, 0, 0, 0 p_start: .long _start p_etext: .long _etext p_bss_start: .long __bss_start p_end: .long _end .weak _platform_stack_top p_pstack: .long _platform_stack_top .weak _zimage_start .globl _zimage_start _zimage_start: .globl _zimage_start_lib _zimage_start_lib: /* Work out the offset between the address we were linked at and the address where we're running. */ bl .+4 p_base: mflr r10 /* r10 now points to runtime addr of p_base */ /* grab the link address of the dynamic section in r11 */ addis r11,r10,(_GLOBAL_OFFSET_TABLE_-p_base)@ha lwz r11,(_GLOBAL_OFFSET_TABLE_-p_base)@l(r11) cmpwi r11,0 beq 3f /* if not linked -pie */ /* get the runtime address of the dynamic section in r12 */ .weak __dynamic_start addis r12,r10,(__dynamic_start-p_base)@ha addi r12,r12,(__dynamic_start-p_base)@l subf r11,r11,r12 /* runtime - linktime offset */ /* The dynamic section contains a series of tagged entries. * We need the RELA and RELACOUNT entries. */ RELA = 7 RELACOUNT = 0x6ffffff9 li r9,0 li r0,0 9: lwz r8,0(r12) /* get tag */ cmpwi r8,0 beq 10f /* end of list */ cmpwi r8,RELA bne 11f lwz r9,4(r12) /* get RELA pointer in r9 */ b 12f 11: addis r8,r8,(-RELACOUNT)@ha cmpwi r8,RELACOUNT@l bne 12f lwz r0,4(r12) /* get RELACOUNT value in r0 */ 12: addi r12,r12,8 b 9b /* The relocation section contains a list of relocations. * We now do the R_PPC_RELATIVE ones, which point to words * which need to be initialized with addend + offset. * The R_PPC_RELATIVE ones come first and there are RELACOUNT * of them. */ 10: /* skip relocation if we don't have both */ cmpwi r0,0 beq 3f cmpwi r9,0 beq 3f add r9,r9,r11 /* Relocate RELA pointer */ mtctr r0 2: lbz r0,4+3(r9) /* ELF32_R_INFO(reloc->r_info) */ cmpwi r0,22 /* R_PPC_RELATIVE */ bne 3f lwz r12,0(r9) /* reloc->r_offset */ lwz r0,8(r9) /* reloc->r_addend */ add r0,r0,r11 stwx r0,r11,r12 addi r9,r9,12 bdnz 2b /* Do a cache flush for our text, in case the loader didn't */ 3: lwz r9,p_start-p_base(r10) /* note: these are relocated now */ lwz r8,p_etext-p_base(r10) 4: dcbf r0,r9 icbi r0,r9 addi r9,r9,0x20 cmplw cr0,r9,r8 blt 4b sync isync /* Clear the BSS */ lwz r9,p_bss_start-p_base(r10) lwz r8,p_end-p_base(r10) li r0,0 5: stw r0,0(r9) addi r9,r9,4 cmplw cr0,r9,r8 blt 5b /* Possibly set up a custom stack */ lwz r8,p_pstack-p_base(r10) cmpwi r8,0 beq 6f lwz r1,0(r8) li r0,0 stwu r0,-16(r1) /* establish a stack frame */ 6: /* Call platform_init() */ bl platform_init /* Call start */ b start