linux/arch/powerpc/boot/crt0.S
<<
>>
Prefs
   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