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 129