crt0.S 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  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. #include "ppc_asm.h"
  13. .text
  14. /* A procedure descriptor used when booting this as a COFF file.
  15. * When making COFF, this comes first in the link and we're
  16. * linked at 0x500000.
  17. */
  18. .globl _zimage_start_opd
  19. _zimage_start_opd:
  20. .long 0x500000, 0, 0, 0
  21. p_start: .long _start
  22. p_etext: .long _etext
  23. p_bss_start: .long __bss_start
  24. p_end: .long _end
  25. .weak _platform_stack_top
  26. p_pstack: .long _platform_stack_top
  27. .weak _zimage_start
  28. .globl _zimage_start
  29. _zimage_start:
  30. .globl _zimage_start_lib
  31. _zimage_start_lib:
  32. /* Work out the offset between the address we were linked at
  33. and the address where we're running. */
  34. bl .+4
  35. p_base: mflr r10 /* r10 now points to runtime addr of p_base */
  36. /* grab the link address of the dynamic section in r11 */
  37. addis r11,r10,(_GLOBAL_OFFSET_TABLE_-p_base)@ha
  38. lwz r11,(_GLOBAL_OFFSET_TABLE_-p_base)@l(r11)
  39. cmpwi r11,0
  40. beq 3f /* if not linked -pie */
  41. /* get the runtime address of the dynamic section in r12 */
  42. .weak __dynamic_start
  43. addis r12,r10,(__dynamic_start-p_base)@ha
  44. addi r12,r12,(__dynamic_start-p_base)@l
  45. subf r11,r11,r12 /* runtime - linktime offset */
  46. /* The dynamic section contains a series of tagged entries.
  47. * We need the RELA and RELACOUNT entries. */
  48. RELA = 7
  49. RELACOUNT = 0x6ffffff9
  50. li r9,0
  51. li r0,0
  52. 9: lwz r8,0(r12) /* get tag */
  53. cmpwi r8,0
  54. beq 10f /* end of list */
  55. cmpwi r8,RELA
  56. bne 11f
  57. lwz r9,4(r12) /* get RELA pointer in r9 */
  58. b 12f
  59. 11: addis r8,r8,(-RELACOUNT)@ha
  60. cmpwi r8,RELACOUNT@l
  61. bne 12f
  62. lwz r0,4(r12) /* get RELACOUNT value in r0 */
  63. 12: addi r12,r12,8
  64. b 9b
  65. /* The relocation section contains a list of relocations.
  66. * We now do the R_PPC_RELATIVE ones, which point to words
  67. * which need to be initialized with addend + offset.
  68. * The R_PPC_RELATIVE ones come first and there are RELACOUNT
  69. * of them. */
  70. 10: /* skip relocation if we don't have both */
  71. cmpwi r0,0
  72. beq 3f
  73. cmpwi r9,0
  74. beq 3f
  75. add r9,r9,r11 /* Relocate RELA pointer */
  76. mtctr r0
  77. 2: lbz r0,4+3(r9) /* ELF32_R_INFO(reloc->r_info) */
  78. cmpwi r0,22 /* R_PPC_RELATIVE */
  79. bne 3f
  80. lwz r12,0(r9) /* reloc->r_offset */
  81. lwz r0,8(r9) /* reloc->r_addend */
  82. add r0,r0,r11
  83. stwx r0,r11,r12
  84. addi r9,r9,12
  85. bdnz 2b
  86. /* Do a cache flush for our text, in case the loader didn't */
  87. 3: lwz r9,p_start-p_base(r10) /* note: these are relocated now */
  88. lwz r8,p_etext-p_base(r10)
  89. 4: dcbf r0,r9
  90. icbi r0,r9
  91. addi r9,r9,0x20
  92. cmplw cr0,r9,r8
  93. blt 4b
  94. sync
  95. isync
  96. /* Clear the BSS */
  97. lwz r9,p_bss_start-p_base(r10)
  98. lwz r8,p_end-p_base(r10)
  99. li r0,0
  100. 5: stw r0,0(r9)
  101. addi r9,r9,4
  102. cmplw cr0,r9,r8
  103. blt 5b
  104. /* Possibly set up a custom stack */
  105. lwz r8,p_pstack-p_base(r10)
  106. cmpwi r8,0
  107. beq 6f
  108. lwz r1,0(r8)
  109. li r0,0
  110. stwu r0,-16(r1) /* establish a stack frame */
  111. 6:
  112. /* Call platform_init() */
  113. bl platform_init
  114. /* Call start */
  115. b start