start.S 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. /*
  2. * U-boot - i386 Startup Code
  3. *
  4. * Copyright (c) 2002 Omicron Ceti AB, Daniel Engström <denaiel@omicron.se>
  5. *
  6. * See file CREDITS for list of people who contributed to this
  7. * project.
  8. *
  9. * This program is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU General Public License as
  11. * published by the Free Software Foundation; either version 2 of
  12. * the License, or (at your option) any later version.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License
  20. * along with this program; if not, write to the Free Software
  21. * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  22. * MA 02111-1307 USA
  23. */
  24. #include <config.h>
  25. #include <version.h>
  26. .section .text
  27. .code32
  28. .globl _start
  29. .type _start, @function
  30. .globl _i386boot_start
  31. _i386boot_start:
  32. /*
  33. * This is the fail safe 32-bit bootstrap entry point. The
  34. * following code is not executed from a cold-reset (actually, a
  35. * lot of it is, but from real-mode after cold reset. It is
  36. * repeated here to put the board into a state as close to cold
  37. * reset as necessary)
  38. */
  39. cli
  40. cld
  41. /* Turn of cache (this might require a 486-class CPU) */
  42. movl %cr0, %eax
  43. orl $0x60000000,%eax
  44. movl %eax, %cr0
  45. wbinvd
  46. /* Tell 32-bit code it is being entered from an in-RAM copy */
  47. movw $0x0000, %bx
  48. _start:
  49. /* This is the 32-bit cold-reset entry point */
  50. movl $0x18,%eax /* Load our segement registes, the
  51. * gdt have already been loaded by start16.S */
  52. movw %ax,%fs
  53. movw %ax,%ds
  54. movw %ax,%gs
  55. movw %ax,%es
  56. movw %ax,%ss
  57. /* Clear the interupt vectors */
  58. lidt blank_idt_ptr
  59. /*
  60. * Skip low-level board and memory initialization if not starting
  61. * from cold-reset. This allows us to do a fail safe boot-strap
  62. * into a new build of U-Boot from a known-good boot flash
  63. */
  64. movw $0x0001, %ax
  65. cmpw %ax, %bx
  66. jne mem_init_ret
  67. /* We call a few functions in the board support package
  68. * since we have no stack yet we'll have to use %ebp
  69. * to store the return address */
  70. /* Early platform init (setup gpio, etc ) */
  71. mov $early_board_init_ret, %ebp
  72. jmp early_board_init
  73. early_board_init_ret:
  74. /* The __port80 entry-point should be usabe by now */
  75. /* so we try to indicate progress */
  76. movw $0x01, %ax
  77. movl $.progress0, %ebp
  78. jmp show_boot_progress_asm
  79. .progress0:
  80. /* size memory */
  81. mov $mem_init_ret, %ebp
  82. jmp mem_init
  83. mem_init_ret:
  84. /* fetch memory size (into %eax) */
  85. mov $get_mem_size_ret, %ebp
  86. jmp get_mem_size
  87. get_mem_size_ret:
  88. /*
  89. * We are now in 'Flat Protected Mode' and we know how much memory
  90. * the board has. The (temporary) Global Descriptor Table is not
  91. * in a 'Safe' place (it is either in Flash which can be erased or
  92. * reprogrammed or in a fail-safe boot-strap image which could be
  93. * over-written).
  94. *
  95. * Move the final gdt to a safe place (top of RAM) and load it.
  96. * This is not a trivial excercise - the lgdt instruction does not
  97. * have a register operand (memory only) and we may well be
  98. * running from Flash, so self modifying code will not work here.
  99. * To overcome this, we copy a stub into upper memory along with
  100. * the GDT.
  101. */
  102. /* Reduce upper memory limit by (Stub + GDT Pointer + GDT) */
  103. subl $(end_gdt_setup - start_gdt_setup), %eax
  104. /* Copy the GDT and Stub */
  105. movl $start_gdt_setup, %esi
  106. movl %eax, %edi
  107. movl $(end_gdt_setup - start_gdt_setup), %ecx
  108. shrl $2, %ecx
  109. cld
  110. rep movsl
  111. /* write the lgdt 'parameter' */
  112. subl $(jmp_instr - start_gdt_setup - 4), %ebp
  113. addl %eax, %ebp
  114. movl $(gdt_ptr - start_gdt_setup), %ebx
  115. addl %eax, %ebx
  116. movl %ebx, (%ebp)
  117. /* write the gdt address into the pointer */
  118. movl $(gdt_addr - start_gdt_setup), %ebp
  119. addl %eax, %ebp
  120. movl $(gdt - start_gdt_setup), %ebx
  121. addl %eax, %ebx
  122. movl %ebx, (%ebp)
  123. /* Save the return address */
  124. movl $load_gdt_ret, %ebp
  125. /* Load the new (safe) Global Descriptor Table */
  126. jmp *%eax
  127. load_gdt_ret:
  128. /* Check we have enough memory for stack */
  129. movl $CONFIG_SYS_STACK_SIZE, %ecx
  130. cmpl %ecx, %eax
  131. jae mem_ok
  132. /* indicate (lack of) progress */
  133. movw $0x81, %ax
  134. movl $.progress0a, %ebp
  135. jmp show_boot_progress_asm
  136. .progress0a:
  137. jmp die
  138. mem_ok:
  139. /* Set stack pointer to upper memory limit*/
  140. movl %eax, %esp
  141. /* indicate progress */
  142. movw $0x02, %ax
  143. movl $.progress1, %ebp
  144. jmp show_boot_progress_asm
  145. .progress1:
  146. /* Test the stack */
  147. pushl $0
  148. popl %eax
  149. cmpl $0, %eax
  150. jne no_stack
  151. push $0x55aa55aa
  152. popl %ebx
  153. cmpl $0x55aa55aa, %ebx
  154. je stack_ok
  155. no_stack:
  156. /* indicate (lack of) progress */
  157. movw $0x82, %ax
  158. movl $.progress1a, %ebp
  159. jmp show_boot_progress_asm
  160. .progress1a:
  161. jmp die
  162. stack_ok:
  163. /* indicate progress */
  164. movw $0x03, %ax
  165. movl $.progress2, %ebp
  166. jmp show_boot_progress_asm
  167. .progress2:
  168. wbinvd
  169. /* Get upper memory limit */
  170. movl %esp, %ecx
  171. subl $CONFIG_SYS_STACK_SIZE, %ecx
  172. /* Create a Stack Frame */
  173. pushl %ebp
  174. movl %esp, %ebp
  175. /* stack_limit parameter */
  176. pushl %ecx
  177. call board_init_f /* Enter, U-boot! */
  178. /* indicate (lack of) progress */
  179. movw $0x85, %ax
  180. movl $.progress4a, %ebp
  181. jmp show_boot_progress_asm
  182. .progress4a:
  183. die: hlt
  184. jmp die
  185. hlt
  186. blank_idt_ptr:
  187. .word 0 /* limit */
  188. .long 0 /* base */
  189. .align 4
  190. start_gdt_setup:
  191. lgdt gdt_ptr
  192. jmp_instr:
  193. jmp *%ebp
  194. .align 4
  195. gdt_ptr:
  196. .word 0x30 /* limit (48 bytes = 6 GDT entries) */
  197. gdt_addr:
  198. .long gdt /* base */
  199. /* The GDT table ...
  200. *
  201. * Selector Type
  202. * 0x00 NULL
  203. * 0x08 Unused
  204. * 0x10 32bit code
  205. * 0x18 32bit data/stack
  206. * 0x20 16bit code
  207. * 0x28 16bit data/stack
  208. */
  209. .align 4
  210. gdt:
  211. .word 0, 0, 0, 0 /* NULL */
  212. .word 0, 0, 0, 0 /* unused */
  213. .word 0xFFFF /* 4Gb - (0x100000*0x1000 = 4Gb) */
  214. .word 0 /* base address = 0 */
  215. .word 0x9B00 /* code read/exec */
  216. .word 0x00CF /* granularity = 4096, 386 (+5th nibble of limit) */
  217. .word 0xFFFF /* 4Gb - (0x100000*0x1000 = 4Gb) */
  218. .word 0x0 /* base address = 0 */
  219. .word 0x9300 /* data read/write */
  220. .word 0x00CF /* granularity = 4096, 386 (+5th nibble of limit) */
  221. .word 0xFFFF /* 64kb */
  222. .word 0 /* base address = 0 */
  223. .word 0x9b00 /* data read/write */
  224. .word 0x0010 /* granularity = 1 (+5th nibble of limit) */
  225. .word 0xFFFF /* 64kb */
  226. .word 0 /* base address = 0 */
  227. .word 0x9300 /* data read/write */
  228. .word 0x0010 /* granularity = 1 (+5th nibble of limit) */
  229. end_gdt_setup: