boot.s 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. [bits 16]
  2. main:
  3. jmp far 0x000:0x7c05
  4. main2:
  5. mov ax, 0x0000
  6. mov ds, ax
  7. mov ss, ax
  8. mov ax, 0x7b00
  9. mov sp, ax
  10. mov ax, 0x0500
  11. mov es, ax
  12. clc
  13. int 0x12
  14. mov [lower_mem], ax
  15. ; memory scan
  16. mov di, 0x0
  17. call do_e820
  18. jc hang
  19. cli
  20. ; a20
  21. in al, 0x92
  22. or al, 2
  23. out 0x92, al
  24. ; basic flat GDT
  25. xor eax, eax
  26. mov ax, ds
  27. shl eax, 4
  28. add eax, gdt_base
  29. mov [gdtr+2], eax
  30. mov eax, gdt_end
  31. sub eax, gdt_base
  32. mov [gdtr], ax
  33. lgdt [gdtr]
  34. ; protected mode enable flag
  35. mov eax, cr0
  36. or eax, 1
  37. mov cr0, eax
  38. ; set segments
  39. mov ax, 0x10
  40. mov ds, ax
  41. mov es, ax
  42. mov fs, ax
  43. mov gs, ax
  44. mov ss, ax
  45. ; jump to protected mode entry
  46. extern kmain
  47. jmp far 0x08:(kmain)
  48. hang:
  49. jmp hang
  50. do_e820:
  51. xor ebx, ebx ; ebx must be 0 to start
  52. xor bp, bp ; keep an entry count in bp
  53. mov edx, 0x0534D4150 ; Place "SMAP" into edx
  54. mov eax, 0xe820
  55. mov [es:di + 20], dword 1 ; force a valid ACPI 3.X entry
  56. mov ecx, 24 ; ask for 24 bytes
  57. int 0x15
  58. jc short .failed ; carry set on first call means "unsupported function"
  59. mov edx, 0x0534D4150 ; Some BIOSes apparently trash this register?
  60. cmp eax, edx ; on success, eax must have been reset to "SMAP"
  61. jne short .failed
  62. test ebx, ebx ; ebx = 0 implies list is only 1 entry long (worthless)
  63. je short .failed
  64. jmp short .jmpin
  65. .e820lp:
  66. mov eax, 0xe820 ; eax, ecx get trashed on every int 0x15 call
  67. mov [es:di + 20], dword 1 ; force a valid ACPI 3.X entry
  68. mov ecx, 24 ; ask for 24 bytes again
  69. int 0x15
  70. jc short .e820f ; carry set means "end of list already reached"
  71. mov edx, 0x0534D4150 ; repair potentially trashed register
  72. .jmpin:
  73. jcxz .skipent ; skip any 0 length entries
  74. cmp cl, 20 ; got a 24 byte ACPI 3.X response?
  75. jbe short .notext
  76. test byte [es:di + 20], 1 ; if so: is the "ignore this data" bit clear?
  77. je short .skipent
  78. .notext:
  79. mov ecx, [es:di + 8] ; get lower uint32_t of memory region length
  80. or ecx, [es:di + 12] ; "or" it with upper uint32_t to test for zero
  81. jz .skipent ; if length uint64_t is 0, skip entry
  82. inc bp ; got a good entry: ++count, move to next storage spot
  83. add di, 24
  84. .skipent:
  85. test ebx, ebx ; if ebx resets to 0, list is complete
  86. jne short .e820lp
  87. .e820f:
  88. mov [mmap_ent], bp ; store the entry count
  89. clc ; there is "jc" on end of list to this point, so the carry must be cleared
  90. ret
  91. .failed:
  92. stc ; "function unsupported" error exit
  93. ret
  94. align 8
  95. ; GDT pointer
  96. gdtr
  97. dw 0
  98. dd 0
  99. ; GDT (null, code, data)
  100. gdt_base
  101. ; null
  102. dq 0
  103. ; code
  104. dw 0xFFFF
  105. dw 0
  106. db 0
  107. db 0x9a
  108. db 0xcf
  109. db 0
  110. ; data
  111. dw 0xffff
  112. dw 0
  113. db 0
  114. db 0x92
  115. db 0xcf
  116. db 0
  117. gdt_end
  118. ; memory map entry count
  119. global mmap_ent
  120. mmap_ent db 0, 0
  121. global lower_mem
  122. lower_mem db 0, 0