DEADSOFTWARE

Kernel: initialize fpu only if it exists
[bmbb.git] / Boot486 / boot0.S
1 .text
2 .global _start
4 /*
5 * Bootloader configuration
6 */
8 .set STACK1, 0x7000
9 .set STACK2, 0xe000
10 .set BUFFER, 0x8000 # 0x80000 - 0x8000 = 480k
11 .set READBLOCKS, 1
13 /*
14 * Kernel configuration (sync with Kernel.odc!)
15 */
17 .set KernelSizeAdr, 0x7e00
18 .set BootDiskAdr, 0x7e04
19 .set BootDiskDxAdr, 0x7e06
20 .set BootDiskCxAdr, 0x7e08
21 .set MemoryMapAdr, 0x7e0A
22 .set ImageBase, 0x100000
24 _start:
26 # =========================================================================== #
27 # Setup canonical %cs:%eip, segment registers %ds, %es, %fs, %gs, %ss and
28 # stack %sp
29 # =========================================================================== #
31 .code16
33 cli
34 ljmp $0x0, $canonized_label; canonized_label:
35 xor %ax, %ax
36 mov %ax, %ds
37 mov %ax, %es
38 # mov %ax, %fs
39 # mov %ax, %gs
40 mov %ax, %ss
41 mov $STACK1, %sp
43 mov %dx, BootDiskAdr
45 # =========================================================================== #
46 # Make memory map for kernel
47 # =========================================================================== #
49 pusha
50 movl $0, MemoryMapAdr
51 xor %ebx, %ebx
52 mov $(MemoryMapAdr + 4), %di
54 mapmem_loop:
55 mov $0xe820, %eax
56 mov $20, %ecx
57 mov $0x0534D4150, %edx
58 int $0x15
59 jc mapmem_method_88
60 cmp %edx, %eax
61 jne mapmem_method_88
62 cmp $0, %ebx
63 je mapmem_done
64 add $20, %di
65 incl MemoryMapAdr
66 jmp mapmem_loop
68 mapmem_method_88:
69 #####
70 ### function:
71 ### int 0x15 + %ah = 0x88
72 ### input:
73 ### none
74 ### output:
75 ### cf clear:
76 ### %ax = available memory starting at 0x100000 in KB
77 ### cf set:
78 ### %ah = error code
79 ### note:
80 ### some bioses do not clear cf, do it manually
81 #####
83 movl $3, (MemoryMapAdr + 0) # num
84 xor %eax, %eax
85 mov $1, %ebx
86 # free low memory
87 movl %eax, (MemoryMapAdr + 4) # base (low)
88 movl %eax, (MemoryMapAdr + 8) # base (high)
89 movl $0x080000, (MemoryMapAdr + 12) # len (low)
90 movl %eax, (MemoryMapAdr + 16) # len (high)
91 movl %ebx, (MemoryMapAdr + 20) # type
92 # reserved harware memory
93 movl $0x080000, (MemoryMapAdr + 24) # base (low)
94 movl %eax, (MemoryMapAdr + 28) # base (high)
95 movl $0x080000, (MemoryMapAdr + 32) # len (low)
96 movl %eax, (MemoryMapAdr + 36) # len (high)
97 movl %eax, (MemoryMapAdr + 40) # type
98 # free high memory
99 movl $0x100000, (MemoryMapAdr + 44) # base (low)
100 movl %eax, (MemoryMapAdr + 48) # base (high)
101 #movl $0x700000, (MemoryMapAdr + 52) # len (low)
102 movl %eax, (MemoryMapAdr + 56) # len (high)
103 movl %ebx, (MemoryMapAdr + 60) # type
105 clc
106 mov $0x88, %ah
107 int $0x15
108 jc mapmem_failed
109 test %ax, %ax
110 je mapmem_failed
111 movzx %ax, %eax
112 shl $10, %eax
113 movl %eax, (MemoryMapAdr + 52) # len (low)
114 jmp mapmem_done
116 mapmem_failed:
117 mov $msg_mapmem_failed, %si
118 call print
119 hlt
121 mapmem_done:
122 popa
124 # =========================================================================== #
125 # Enable A20 Line
126 # =========================================================================== #
128 enableA20:
129 xor %cx, %cx
130 enableA20_1:
131 inc %cx
132 jz enableA20_3
133 in $0x64, %al
134 test $0x2, %al
135 jnz enableA20_1
136 mov $0xd1, %al
137 out %al, $0x64
138 enableA20_2:
139 in $0x64, %al
140 test $0x2, %al
141 jnz enableA20_2
142 mov $0xdf, %al
143 out %al, $0x60
144 enableA20_3:
146 # =========================================================================== #
147 # Reset disk controller (%dl and %dh initialized by bios) and read Kernel
148 # into buffer
149 # =========================================================================== #
150 sti
151 movl $(kernel_code_end - kernel_code_start), KernelSizeAdr
153 stage1__read:
154 mov current_sector, %ax
155 add $1, %ax
156 call lba2chs
158 mov current_sector, %ax
159 shl $5, %ax
160 add $(BUFFER / 16), %ax
161 mov %ax, %es
163 readsectors:
164 # %cx = Cylider+Sector; %es = 64k buf
165 xor %ah, %ah
166 int $0x13
168 xor %bx, %bx
169 mov $0x2, %ah
170 mov $READBLOCKS, %al
171 clc
172 int $0x13
174 jnc readsectors__success
176 /* zero if sectors not readed */
177 or %ah, %ah
178 jnz readsectors__success
180 mov $msg_kernel_read_failed, %si
181 call print
182 #cli
183 hlt
184 readsectors__success:
186 mov current_sector, %ax
187 add $READBLOCKS, %ax
188 mov %ax, current_sector
189 cmp $((kernel_code_end - kernel_code_start + 511) / 512), %ax
190 jl stage1__read
191 cli
193 # =========================================================================== #
194 # Load GDT
195 # =========================================================================== #
196 mov $msg_protected_mode, %si
197 call print
198 lgdt gdt_info
200 # =========================================================================== #
201 # Switch to protected mode
202 # =========================================================================== #
203 mov %cr0, %eax
204 or $1, %al
205 mov %eax, %cr0
206 jmp $8, $stage2
208 # =========================================================================== #
209 # 32 bit stage begins
210 # =========================================================================== #
212 .code32
214 stage2:
216 # =========================================================================== #
217 # Setup data segments %ds, %es, %fs, %gs and stack %sp
218 # =========================================================================== #
219 mov $16, %ax
220 mov %ax, %ds
221 mov %ax, %ss
222 mov %ax, %es
223 mov %ax, %fs
224 mov %ax, %gs
225 mov $STACK2, %sp
227 # =========================================================================== #
228 # Copy Kernel from buffer
229 # =========================================================================== #
231 xor %eax, %eax
232 stage2_copy_loop:
233 mov BUFFER(%eax), %bh
234 mov %bh, ImageBase(%eax)
235 inc %eax
236 cmp $(kernel_code_end - kernel_code_start), %eax
237 jne stage2_copy_loop
239 # =========================================================================== #
240 # Jump to Kernel code (never returns)
241 # =========================================================================== #
243 jmp ImageBase
245 # =========================================================================== #
246 # ================================ routines ================================= #
247 # =========================================================================== #
249 # =========================================================================== #
250 # Print asciiz string
251 # input: %si = String
252 # =========================================================================== #
254 .code16
255 print:
256 pusha
257 movb $0x0e, %ah
258 print__loop:
259 lodsb
260 orb %al, %al
261 jz print__ret
262 int $0x10
263 jmp print__loop
264 print__ret:
265 popa
266 ret
268 # =========================================================================== #
269 # Convert LBA to CHS
270 # input: %ax = LBA %dl = disk
271 # output: %ch = cylider %cl = sector %dh = head %dl = disk
272 # =========================================================================== #
274 .code16
275 lba2chs:
276 # push %es
277 # push %di
278 push %dx
279 push %ax
281 clc
282 mov $0x0, %ax
283 mov %ax, %es
284 mov %ax, %di
285 mov $0x8, %ah
286 int $0x13
287 jnc lba2chs__success
288 mov $msg_chs_error, %si
289 call print
290 hlt
291 lba2chs__success:
292 mov %dx, BootDiskDxAdr
293 mov %cx, BootDiskCxAdr
295 # SPT = %cl & 63
296 # HPC = %dh + 1
297 # CYL = LBA / ( HPC * SPT )
298 # TEMP = LBA % ( HPC * SPT )
299 # HEAD = TEMP / SPT
300 # SECT = TEMP % SPT + 1
302 # %ax = FREE %bx = FREE %cx = GSPT %dx = HPC-1
303 and $0x3F, %cl
304 movzx %cl, %cx
306 # %ax = FREE %bx = FREE %cx = SPT %dx = HPC-1
307 movzx %dh, %dx
308 inc %dx
310 # %ax = FREE %bx = FREE %cx = SPT %dx = HPC
311 mov %dx, %ax
312 mul %cx; # overflow in %dx
313 mov %ax, %dx
315 # %ax = FREE %bx = FREE %cx = SPT %dx = (HPC * SPT)
316 pop %ax # LBA
317 mov %dx, %bx
318 xor %dx, %dx
319 div %bx
320 xchg %ax, %dx
322 # %ax = TEMP %bx = FREE %cx = SPT %dx = CYL
323 mov %dx, %bx
324 xor %dx, %dx
325 div %cx
326 inc %dx
328 # %ax = HEAD %bx = CYL %cx = FREE %dx = SECT
329 mov %bl, %ch
330 mov %bh, %cl
331 shl $6, %cl
332 add %dx, %cx
334 # %ax = HEAD %bx = FREE %cx = CYL&SECT %dx = FREE
335 pop %dx
336 mov %al, %dh
338 # %ax = FREE %bx = FREE %cx = CYL&SECT %dx = HEAD&DISK
340 # pop %di
341 # pop %es
342 ret
344 # =========================================================================== #
345 # =========================================================================== #
346 # =========================================================================== #
348 msg_mapmem_failed: .asciz "1"
349 msg_chs_error: .asciz "3"
350 msg_kernel_read_failed: .asciz "4"
351 msg_protected_mode: .asciz ">5"
353 current_sector:
354 .word 0
355 gdt_begin:
356 .byte 0x00, 0x00, 0, 0, 0, 0b00000000, 0b00000000, 0 # null dsc
357 .byte 0xff, 0xff, 0, 0, 0, 0b10011010, 0b11001111, 0 # code dsc
358 .byte 0xff, 0xff, 0, 0, 0, 0b10010010, 0b11001111, 0 # data dsc
359 gdt_info:
360 .word (gdt_info - gdt_begin - 1)
361 .quad (gdt_begin)
363 .fill _start + 510 - .
364 .word 0xaa55
366 kernel_code_start:
367 .incbin "../BlackBox.bin"
368 kernel_code_end:
370 .fill _start + (1440 * 1024) - .