boot.s 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  1. .section .stage1
  2. .code16
  3. loader_start:
  4. # set segment registers
  5. movw %cs, %ax
  6. movw %ax, %ds
  7. _clear_screen:
  8. mov $0x00, %ah
  9. mov $0x03, %al
  10. int $0x10
  11. # get memory size info and storage it
  12. _get_memory_size:
  13. xorw %cx, %cx
  14. xorw %dx, %dx
  15. movw $0xe801, %ax
  16. int $0x15
  17. jc _get_memory_size_error
  18. cmpb $0x86, %ah # unsupported function
  19. je _get_memory_size_error
  20. cmpb $0x80, %ah # invalid command
  21. je _get_memory_size_error
  22. jcxz _get_memory_size_use_ax
  23. movw %cx, %ax
  24. movw %dx, %bx
  25. _get_memory_size_use_ax:
  26. movl $asm_mem_size_info, %edx
  27. movw %ax, (%edx)
  28. addw $2, %dx
  29. movw %bx, (%edx)
  30. jmp _e820_mem_map_load
  31. _get_memory_size_error:
  32. xchgw %bx, %bx
  33. jmp __stage1_halt
  34. _e820_mem_map_load:
  35. addl $4, %esp
  36. movl $0, (%esp)
  37. # save the destination address to es:di
  38. movw %cs, %ax
  39. movw %ax, %es
  40. movl $asm_e820_mem_map, %edi
  41. # clear ebx
  42. xorl %ebx, %ebx
  43. # set the magic number to edx
  44. movl $0x534D4150, %edx
  45. _e820_mem_map_load_loop:
  46. # set function number to eax
  47. movl $0xe820, %eax
  48. # set default entry size
  49. movl $24, %ecx
  50. int $0x15
  51. incl (%esp)
  52. addl %ecx, %edi
  53. jc _e820_mem_map_load_fin
  54. cmpl $0, %ebx
  55. jz _e820_mem_map_load_fin
  56. jmp _e820_mem_map_load_loop
  57. _e820_mem_map_load_fin:
  58. movl (%esp), %eax
  59. movl $asm_e820_mem_map_count, %edi
  60. movl %eax, (%edi)
  61. movl $asm_e820_mem_map_entry_size, %edi
  62. movl %ecx, (%edi)
  63. jmp _load_gdt
  64. _load_gdt:
  65. cli
  66. lgdt asm_gdt_descriptor
  67. # enable protection enable (PE) bit
  68. movl %cr0, %eax
  69. orl $1, %eax
  70. movl %eax, %cr0
  71. ljmp $0x08, $start_32bit
  72. .code32
  73. start_32bit:
  74. movw $0x10, %ax
  75. movw %ax, %ds
  76. movw %ax, %es
  77. movw %ax, %fs
  78. movw %ax, %gs
  79. movw %ax, %ss
  80. movl $0, %esp
  81. movl $0, %ebp
  82. setup_early_kernel_page_table:
  83. # memory map:
  84. # 0x0000-0x1000: empty page
  85. # 0x1000-0x2000: early kernel pd
  86. # 0x2000-0x6000: 4 pts
  87. # 0x6000-0x8000: early kernel stack
  88. # so we fill the first 8KiB with zero
  89. movl $0x00000000, %eax
  90. movl $0x8000, %ecx
  91. _fill_zero:
  92. cmpl $0, %ecx
  93. jz _fill_zero_end
  94. subl $4, %ecx
  95. movl $0, (%eax)
  96. addl $4, %eax
  97. jmp _fill_zero
  98. _fill_zero_end:
  99. # pt#0: 0x00000000 to 0x00400000
  100. movl $0x00001000, %eax
  101. movl $0x00002003, (%eax)
  102. # pt#1: 0xc0000000 to 0xc0400000
  103. movl $0x00001c00, %eax
  104. movl $0x00003003, (%eax)
  105. # pt#2: 0xff000000 to 0xff400000
  106. movl $0x00001ff0, %eax
  107. movl $0x00004003, (%eax)
  108. # pt#3: 0xffc00000 to 0xffffffff
  109. movl $0x00001ffc, %eax
  110. movl $0x00005003, (%eax)
  111. # map early kernel page directory to 0xff000000
  112. movl $0x00004000, %eax
  113. movl $0x00001003, (%eax)
  114. # map kernel pt#2 to 0xff001000
  115. movl $0x00004004, %eax
  116. movl $0x00004003, (%eax)
  117. # map __stage1_start ---- __kinit_end identically
  118. movl $__stage1_start, %ebx
  119. movl $__kinit_end, %ecx
  120. movl %ebx, %edx
  121. shrl $12, %edx
  122. andl $0x3ff, %edx
  123. __map_stage1_kinit:
  124. leal 3(%ebx), %eax
  125. movl %eax, 0x00002000(, %edx, 4)
  126. addl $0x1000, %ebx
  127. incl %edx
  128. cmpl %ebx, %ecx
  129. jne __map_stage1_kinit
  130. # map __text_start ---- __data_end to 0xc0000000
  131. movl %ecx, %ebx
  132. movl $__text_start, %edx
  133. shrl $12, %edx
  134. andl $0x3ff, %edx
  135. movl $__data_end, %ecx
  136. subl $__text_start, %ecx
  137. addl %ebx, %ecx
  138. __map_kernel_space:
  139. leal 3(%ebx), %eax
  140. movl %eax, 0x00003000(, %edx, 4)
  141. addl $0x1000, %ebx
  142. incl %edx
  143. cmpl %ebx, %ecx
  144. jne __map_kernel_space
  145. # map __data_end ---- __bss_end from 0x100000
  146. movl $0x100000, %ebx
  147. movl $__bss_end, %ecx
  148. subl $__data_end, %ecx
  149. addl %ebx, %ecx
  150. __map_kernel_bss:
  151. leal 3(%ebx), %eax
  152. movl %eax, 0x00003000(, %edx, 4)
  153. addl $0x1000, %ebx
  154. incl %edx
  155. cmpl %ebx, %ecx
  156. jne __map_kernel_bss
  157. # map kernel stack 0xffffe000-0xffffffff
  158. movl $0x6000, %ebx
  159. movl $0x8000, %ecx
  160. movl $0x0ffffe, %edx
  161. andl $0x3ff, %edx
  162. __map_kernel_stack:
  163. leal 3(%ebx), %eax
  164. movl %eax, 0x00005000(, %edx, 4)
  165. addl $0x1000, %ebx
  166. incl %edx
  167. cmpl %ebx, %ecx
  168. jne __map_kernel_stack
  169. load_early_kernel_page_table:
  170. movl $0x00001000, %eax
  171. movl %eax, %cr3
  172. movl %cr0, %eax
  173. // SET PE, WP, PG
  174. orl $0x80010001, %eax
  175. movl %eax, %cr0
  176. # set stack pointer and clear stack bottom
  177. movl $0xfffffff0, %esp
  178. movl $0xfffffff0, %ebp
  179. movl $0x00, (%esp)
  180. movl $0x00, 4(%esp)
  181. movl $0x00, 8(%esp)
  182. movl $0x00, 12(%esp)
  183. call kernel_init
  184. __stage1_halt:
  185. hlt
  186. jmp __stage1_halt
  187. asm_gdt_descriptor:
  188. .word (5 * 8) - 1 # size
  189. .long asm_gdt_table # address
  190. asm_gdt_table:
  191. .8byte 0 # null descriptor
  192. # kernel code segment
  193. .word 0xffff # limit 0 :15
  194. .word 0x0000 # base 0 :15
  195. .byte 0x00 # base 16:23
  196. .byte 0x9a # access
  197. .byte 0b11001111 # flag and limit 16:20
  198. .byte 0x00 # base 24:31
  199. # kernel data segment
  200. .word 0xffff # limit 0 :15
  201. .word 0x0000 # base 0 :15
  202. .byte 0x00 # base 16:23
  203. .byte 0x92 # access
  204. .byte 0b11001111 # flag and limit 16:20
  205. .byte 0x00 # base 24:31
  206. # user code segment
  207. .word 0xffff # limit 0 :15
  208. .word 0x0000 # base 0 :15
  209. .byte 0x00 # base 16:23
  210. .byte 0xfa # access
  211. .byte 0b11001111 # flag and limit 16:20
  212. .byte 0x00 # base 24:31
  213. # user data segment
  214. .word 0xffff # limit 0 :15
  215. .word 0x0000 # base 0 :15
  216. .byte 0x00 # base 16:23
  217. .byte 0xf2 # access
  218. .byte 0b11001111 # flag and limit 16:20
  219. .byte 0x00 # base 24:31
  220. .globl asm_mem_size_info
  221. .type asm_mem_size_info @object
  222. .size asm_mem_size_info, (.-asm_mem_size_info)
  223. asm_mem_size_info:
  224. .word 0x12
  225. .word 0x34
  226. .globl asm_e820_mem_map
  227. .type asm_e820_mem_map @object
  228. .size asm_e820_mem_map, (.-asm_e820_mem_map)
  229. asm_e820_mem_map:
  230. .space 1024
  231. .globl asm_e820_mem_map_count
  232. .type asm_e820_mem_map_count @object
  233. asm_e820_mem_map_count:
  234. .long 0
  235. .globl asm_e820_mem_map_entry_size
  236. .type asm_e820_mem_map_entry_size @object
  237. asm_e820_mem_map_entry_size:
  238. .long 0