relocate.S 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. /*
  2. * arch/ppc/boot/simple/relocate.S
  3. *
  4. * This is the common part of the loader relocation and initialization
  5. * process. All of the board/processor specific initialization is
  6. * done before we get here.
  7. *
  8. * Author: Tom Rini
  9. * trini@mvista.com
  10. * Derived from arch/ppc/boot/prep/head.S (Cort Dougan, many others).
  11. *
  12. * 2001-2004 (c) MontaVista, Software, Inc. This file is licensed under
  13. * the terms of the GNU General Public License version 2. This program
  14. * is licensed "as is" without any warranty of any kind, whether express
  15. * or implied.
  16. */
  17. #include <linux/config.h>
  18. #include <asm/cache.h>
  19. #include <asm/ppc_asm.h>
  20. #define GETSYM(reg, sym) \
  21. lis reg, sym@h; ori reg, reg, sym@l
  22. .text
  23. /* We get called from the early initialization code.
  24. * Register 3 has the address where we were loaded,
  25. * Register 4 contains any residual data passed from the
  26. * boot rom.
  27. */
  28. .globl relocate
  29. relocate:
  30. /* Save r3, r4 for later.
  31. * The r8/r11 are legacy registers so I don't have to
  32. * rewrite the code below :-).
  33. */
  34. mr r8, r3
  35. mr r11, r4
  36. /* compute the size of the whole image in words. */
  37. GETSYM(r4,start)
  38. GETSYM(r5,end)
  39. addi r5,r5,3 /* round up */
  40. sub r5,r5,r4 /* end - start */
  41. srwi r5,r5,2
  42. mr r7,r5 /* Save for later use. */
  43. /*
  44. * Check if we need to relocate ourselves to the link addr or were
  45. * we loaded there to begin with.
  46. */
  47. cmpw cr0,r3,r4
  48. beq start_ldr /* If 0, we don't need to relocate */
  49. /* Move this code somewhere safe. This is max(load + size, end)
  50. * r8 == load address
  51. */
  52. GETSYM(r4, start)
  53. GETSYM(r5, end)
  54. sub r6,r5,r4
  55. add r6,r8,r6 /* r6 == phys(load + size) */
  56. cmpw r5,r6
  57. bgt 1f
  58. b 2f
  59. 1:
  60. mr r6, r5
  61. 2:
  62. /* dest is in r6 */
  63. /* Ensure alignment --- this code is precautionary */
  64. addi r6,r6,4
  65. li r5,0x0003
  66. andc r6,r6,r5
  67. /* Find physical address and size of do_relocate */
  68. GETSYM(r5, __relocate_start)
  69. GETSYM(r4, __relocate_end)
  70. GETSYM(r3, start)
  71. /* Size to copy */
  72. sub r4,r4,r5
  73. srwi r4,r4,2
  74. /* Src addr to copy (= __relocate_start - start + where_loaded) */
  75. sub r3,r5,r3
  76. add r5,r8,r3
  77. /* Save dest */
  78. mr r3, r6
  79. /* Do the copy */
  80. mtctr r4
  81. 3: lwz r4,0(r5)
  82. stw r4,0(r3)
  83. addi r3,r3,4
  84. addi r5,r5,4
  85. bdnz 3b
  86. GETSYM(r4, __relocate_start)
  87. GETSYM(r5, do_relocate)
  88. sub r4,r5,r4 /* Get entry point for do_relocate in */
  89. add r6,r6,r4 /* relocated section */
  90. /* This will return to the relocated do_relocate */
  91. mtlr r6
  92. b flush_instruction_cache
  93. .section ".relocate_code","xa"
  94. do_relocate:
  95. /* We have 2 cases --- start < load, or start > load
  96. * This determines whether we copy from the end, or the start.
  97. * Its easier to have 2 loops than to have paramaterised
  98. * loops. Sigh.
  99. */
  100. li r6,0 /* Clear checksum */
  101. mtctr r7 /* Setup for a loop */
  102. GETSYM(r4, start)
  103. mr r3,r8 /* Get the load addr */
  104. cmpw cr0,r4,r3 /* If we need to copy from the end, do so */
  105. bgt do_relocate_from_end
  106. do_relocate_from_start:
  107. 1: lwz r5,0(r3) /* Load and decrement */
  108. stw r5,0(r4) /* Store and decrement */
  109. addi r3,r3,4
  110. addi r4,r4,4
  111. xor r6,r6,r5 /* Update checksum */
  112. bdnz 1b /* Are we done? */
  113. b do_relocate_out /* Finished */
  114. do_relocate_from_end:
  115. GETSYM(r3, end)
  116. slwi r4,r7,2
  117. add r4,r8,r4 /* Get the physical end */
  118. 1: lwzu r5,-4(r4)
  119. stwu r5, -4(r3)
  120. xor r6,r6,r5
  121. bdnz 1b
  122. do_relocate_out:
  123. GETSYM(r3,start_ldr)
  124. mtlr r3 /* Easiest way to do an absolute jump */
  125. /* Some boards don't boot up with the I-cache enabled. Do that
  126. * now because the decompress runs much faster that way.
  127. * As a side effect, we have to ensure the data cache is not enabled
  128. * so we can access the serial I/O without trouble.
  129. */
  130. b flush_instruction_cache
  131. .previous
  132. start_ldr:
  133. /* Clear all of BSS and set up stack for C calls */
  134. lis r3,edata@h
  135. ori r3,r3,edata@l
  136. lis r4,end@h
  137. ori r4,r4,end@l
  138. subi r3,r3,4
  139. subi r4,r4,4
  140. li r0,0
  141. 50: stwu r0,4(r3)
  142. cmpw cr0,r3,r4
  143. bne 50b
  144. 90: mr r9,r1 /* Save old stack pointer (in case it matters) */
  145. lis r1,.stack@h
  146. ori r1,r1,.stack@l
  147. addi r1,r1,4096*2
  148. subi r1,r1,256
  149. li r2,0x000F /* Mask pointer to 16-byte boundary */
  150. andc r1,r1,r2
  151. /*
  152. * Exec kernel loader
  153. */
  154. mr r3,r8 /* Load point */
  155. mr r4,r7 /* Program length */
  156. mr r5,r6 /* Checksum */
  157. mr r6,r11 /* Residual data */
  158. mr r7,r25 /* Validated OFW interface */
  159. bl load_kernel
  160. /*
  161. * Make sure the kernel knows we don't have things set in
  162. * registers. -- Tom
  163. */
  164. li r4,0
  165. li r5,0
  166. li r6,0
  167. /*
  168. * Start at the begining.
  169. */
  170. #ifdef CONFIG_PPC_MULTIPLATFORM
  171. li r9,0xc
  172. mtlr r9
  173. /* tell kernel we're prep, by putting 0xdeadc0de at KERNELLOAD,
  174. * and tell the kernel to start on the 4th instruction since we
  175. * overwrite the first 3 sometimes (which are 'nop').
  176. */
  177. lis r10,0xdeadc0de@h
  178. ori r10,r10,0xdeadc0de@l
  179. li r9,0
  180. stw r10,0(r9)
  181. #else
  182. li r9,0
  183. mtlr r9
  184. #endif
  185. blr
  186. .comm .stack,4096*2,4