relocate.S
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:5k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

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