startup.S 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. /*
  2. * GRUB -- GRand Unified Bootloader
  3. * Copyright (C) 2013 Free Software Foundation, Inc.
  4. *
  5. * GRUB is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation, either version 3 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * GRUB is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. #include <grub/offsets.h>
  19. #include <grub/symbol.h>
  20. #include <grub/machine/kernel.h>
  21. /*
  22. * GRUB is called from U-Boot as a Linux Kernel type image, which
  23. * means among other things that it always enters in ARM state.
  24. *
  25. *
  26. * Overview of GRUB image layout:
  27. *
  28. * _start:
  29. * Entry point (1 ARM branch instruction, to "codestart")
  30. * grub_total_module_size:
  31. * Data field: Size of included module blob
  32. * (when generated by grub-mkimage)
  33. * codestart:
  34. * Remainder of statically-linked executable code and data.
  35. * __bss_start:
  36. * Start of included module blob.
  37. * Also where global/static variables are located.
  38. * _end:
  39. * End of bss region (but not necessarily module blob).
  40. * <stack>:
  41. * <modules>:
  42. * Loadable modules, post relocation.
  43. * <heap>:
  44. */
  45. .text
  46. .arm
  47. FUNCTION(_start)
  48. b codestart
  49. @ Size of final image integrated module blob - set by grub-mkimage
  50. .org _start + GRUB_KERNEL_MACHINE_TOTAL_MODULE_SIZE
  51. VARIABLE(grub_total_module_size)
  52. .long 0
  53. VARIABLE(grub_modbase)
  54. .long 0
  55. bss_start_ptr:
  56. .long EXT_C(__bss_start)
  57. end_ptr:
  58. .long EXT_C(_end)
  59. @ Memory map at start:
  60. @ * text+data
  61. @ * list relocations
  62. @ * modules
  63. @ Before we enter C, we need to apply the relocations
  64. @ and get following map:
  65. @ * text+data
  66. @ * BSS (cleared)
  67. @ * stack
  68. @ * modules
  69. @
  70. @ To make things easier we ensure
  71. @ that BSS+stack is larger than list of relocations
  72. @ by increasing stack if necessarry.
  73. @ This allows us to always unconditionally copy backwards
  74. @ Currently list of relocations is ~5K and stack is set
  75. @ to be at least 256K
  76. FUNCTION(codestart)
  77. @ Store context: Machine ID, atags/dtb, ...
  78. @ U-Boot API signature is stored on the U-Boot heap
  79. @ Stack pointer used as start address for signature probing
  80. mov r12, sp
  81. adr sp, entry_state
  82. push {r1-r12,lr} @ store U-Boot context (sp in r12)
  83. adr r1, _start
  84. ldr r0, bss_start_ptr @ src
  85. add r0, r0, r1
  86. add r0, r0, #(GRUB_KERNEL_MACHINE_MOD_ALIGN - 1)
  87. mvn r2, #(GRUB_KERNEL_MACHINE_MOD_ALIGN - 1)
  88. and r0, r0, r2
  89. 1:
  90. ldr r3, [r0], #4 @load next offset
  91. @ both -2 and -1 are treated the same as we have only one type of relocs
  92. @ -2 means "end of this type of relocs" and -1 means "end of all relocs"
  93. add r2, r3, #2
  94. cmp r2, #1
  95. bls reloc_done
  96. @ Adjust next offset
  97. ldr r2, [r3, r1]
  98. add r2, r2, r1
  99. str r2, [r3, r1]
  100. b 1b
  101. reloc_done:
  102. @ Modules have been stored as a blob
  103. @ they need to be manually relocated to _end
  104. add r0, r0, #(GRUB_KERNEL_MACHINE_MOD_ALIGN - 1)
  105. mvn r1, #(GRUB_KERNEL_MACHINE_MOD_ALIGN - 1)
  106. and r0, r0, r1 @ src = aligned end of relocations
  107. ldr r1, end_ptr @ dst = End of BSS
  108. ldr r2, grub_total_module_size @ blob size
  109. add r1, r1, #GRUB_KERNEL_MACHINE_STACK_SIZE
  110. and r1, r1, #~0x7 @ Ensure 8-byte alignment
  111. sub sp, r1, #8
  112. add r1, r1, #1024
  113. str r1, EXT_C(grub_modbase)
  114. add r1, r1, r2
  115. add r0, r0, r2
  116. sub r1, r1, #4
  117. sub r0, r0, #4
  118. 1: ldr r3, [r0], #-4 @ r3 = *src--
  119. str r3, [r1], #-4 @ *dst-- = r3
  120. subs r2, #4 @ remaining -= 4
  121. bne 1b @ while remaining != 0
  122. @ Since we _are_ the C run-time, we need to manually zero the BSS
  123. @ region before continuing
  124. ldr r0, bss_start_ptr @ zero from here
  125. @ If unaligned, bytewise zero until base address aligned.
  126. mov r2, #0
  127. 1: tst r0, #3
  128. beq 2f
  129. strb r2, [r0], #1
  130. b 1b
  131. 2: ldr r1, end_ptr @ to here
  132. 1: str r2, [r0], #4
  133. cmp r0, r1
  134. bne 1b
  135. b EXT_C(grub_main)
  136. /*
  137. * uboot_syscall():
  138. * This function is effectively a veneer, so it cannot
  139. * modify the stack or corrupt any registers other than
  140. * r12 (ip). Furthermore it needs to restore r8 for
  141. * U-Boot (Global Data Pointer) and preserve it for Grub.
  142. */
  143. FUNCTION(grub_uboot_syscall)
  144. str r8, transition_space
  145. str lr, transition_space + 4
  146. str r9, transition_space + 8
  147. ldr r8, gd_backup
  148. ldr r9, gd_backup + 4
  149. bl do_syscall
  150. ldr r8, transition_space
  151. ldr lr, transition_space + 4
  152. ldr r9, transition_space + 8
  153. bx lr
  154. do_syscall:
  155. ldr ip, grub_uboot_syscall_ptr
  156. bx ip
  157. FUNCTION(grub_uboot_return)
  158. adr sp, entry_state_end
  159. pop {r4-r12, lr}
  160. mov sp, r12
  161. bx lr
  162. .align 3
  163. @ U-boot context stack space
  164. entry_state_end:
  165. VARIABLE(grub_uboot_machine_type)
  166. .long 0 @ r1
  167. VARIABLE(grub_uboot_boot_data)
  168. .long 0 @ r2
  169. .long 0 @ r3
  170. .long 0 @ r4
  171. .long 0 @ r5
  172. .long 0 @ r6
  173. .long 0 @ r7
  174. gd_backup:
  175. .long 0 @ r8 - U-Boot global data pointer up to 2013-09-21
  176. .long 0 @ r9 - U-Boot global data pointer 2013-09-21 onwards
  177. .long 0 @ r10
  178. .long 0 @ r11
  179. VARIABLE(grub_uboot_search_hint)@ U-Boot stack pointer -
  180. .long 0 @ also API signature address hint.
  181. .long 0 @ lr
  182. entry_state: @ backup for U-Boot context
  183. @ GRUB context stack space
  184. transition_space:
  185. .long 0 @ r8
  186. .long 0 @ lr
  187. .long 0 @ r9
  188. VARIABLE(grub_uboot_syscall_ptr)
  189. .long 0 @
  190. END