boot.s 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. .section .text.loader
  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 loader_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 $16, %ax
  75. movw %ax, %ds
  76. movw %ax, %es
  77. movw %ax, %fs
  78. movw %ax, %gs
  79. movw %ax, %ss
  80. # set up early stack at 0x001000000
  81. movl $0x01000000, %ebp
  82. movl $0x01000000, %esp
  83. setup_early_kernel_page_table:
  84. # set up early kernel page table
  85. # the early kernel page directory is located at physical
  86. # address 0x00000000, size 4k, and the empty page is at
  87. # 0x5000-0x5fff, so we fill the first 6KiB
  88. movl $0x00000000, %eax
  89. movl $0x6000, %ecx
  90. call _fill_zero
  91. # map the first 16MiB identically
  92. # 0x0000-0x0fff: early kernel pd
  93. # 0x1000-0x4fff: pde 0 - 4
  94. movl $0x00000000, %eax
  95. movl $0x00001003, %ebx
  96. _fill_pde_loop:
  97. movl %ebx, (%eax)
  98. addl $4, %eax
  99. addl $0x1000, %ebx
  100. cmpl $0x5003, %ebx
  101. jne _fill_pde_loop
  102. # then, create page tables
  103. movl $0x00000003, %eax
  104. movl $0x00001000, %ecx
  105. _create_page_table_loop1:
  106. movl %eax, (%ecx)
  107. addl $4, %ecx
  108. addl $0x1000, %eax
  109. cmpl $0x4ffc, %ecx
  110. jle _create_page_table_loop1
  111. load_early_kernel_page_table:
  112. movl $0x00000000, %eax
  113. movl %eax, %cr3
  114. movl %cr0, %eax
  115. // SET PE, WP, PG
  116. orl $0x80010001, %eax
  117. movl %eax, %cr0
  118. jmp start_move_kernel
  119. # quick call
  120. # %eax: address to fill
  121. # %ecx: byte count to fill
  122. _fill_zero:
  123. movl %ecx, -4(%esp)
  124. movl %eax, -8(%esp)
  125. _fill_zero_loop:
  126. cmpl $0, %ecx
  127. jz _fill_zero_end
  128. subl $4, %ecx
  129. movl $0, (%eax)
  130. addl $4, %eax
  131. jmp _fill_zero_loop
  132. _fill_zero_end:
  133. movl -8(%esp), %eax
  134. movl -4(%esp), %ecx
  135. ret
  136. start_move_kernel:
  137. # move the kernel to 0x100000
  138. movl $__loader_end, %eax
  139. movl $__real_kernel_start, %ebx
  140. movl $__p_kernel_text_and_data_size_addr, %ecx
  141. movl (%ecx), %ecx
  142. movl (%ecx), %ecx
  143. _move_kernel:
  144. movl (%eax), %edx
  145. movl %edx, (%ebx)
  146. addl $4, %eax
  147. addl $4, %ebx
  148. subl $4, %ecx
  149. cmpl $0, %ecx
  150. jge _move_kernel
  151. call kernel_main
  152. loader_halt:
  153. hlt
  154. jmp loader_halt
  155. asm_gdt_descriptor:
  156. .word (5 * 8) - 1 # size
  157. .long asm_gdt_table # address
  158. .globl asm_gdt_descriptor
  159. .type asm_gdt_descriptor @object
  160. .size asm_gdt_descriptor, (.-asm_gdt_descriptor)
  161. asm_gdt_table:
  162. .8byte 0 # null descriptor
  163. # kernel code segment
  164. .word 0xffff # limit 0 :15
  165. .word 0x0000 # base 0 :15
  166. .byte 0x00 # base 16:23
  167. .byte 0x9a # access
  168. .byte 0b11001111 # flag and limit 16:20
  169. .byte 0x00 # base 24:31
  170. # kernel data segment
  171. .word 0xffff # limit 0 :15
  172. .word 0x0000 # base 0 :15
  173. .byte 0x00 # base 16:23
  174. .byte 0x92 # access
  175. .byte 0b11001111 # flag and limit 16:20
  176. .byte 0x00 # base 24:31
  177. # user code segment
  178. .word 0xffff # limit 0 :15
  179. .word 0x0000 # base 0 :15
  180. .byte 0x00 # base 16:23
  181. .byte 0xfa # access
  182. .byte 0b11001111 # flag and limit 16:20
  183. .byte 0x00 # base 24:31
  184. # user data segment
  185. .word 0xffff # limit 0 :15
  186. .word 0x0000 # base 0 :15
  187. .byte 0x00 # base 16:23
  188. .byte 0xf2 # access
  189. .byte 0b11001111 # flag and limit 16:20
  190. .byte 0x00 # base 24:31
  191. asm_mem_size_info:
  192. .word 0x12
  193. .word 0x34
  194. .globl asm_mem_size_info
  195. .type asm_mem_size_info @object
  196. .size asm_mem_size_info, (.-asm_mem_size_info)
  197. asm_e820_mem_map:
  198. .space 1024
  199. .globl asm_e820_mem_map
  200. .type asm_e820_mem_map @object
  201. .size asm_e820_mem_map, (.-asm_e820_mem_map)
  202. asm_e820_mem_map_count:
  203. .long 0
  204. .globl asm_e820_mem_map_count
  205. .type asm_e820_mem_map_count @object
  206. asm_e820_mem_map_entry_size:
  207. .long 0
  208. .globl asm_e820_mem_map_entry_size
  209. .type asm_e820_mem_map_entry_size @object