DEADSOFTWARE

Fix memory manager init, so now it works on more hardware. Also kernel now requires...
[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 # =========================================================================== #
25 # Stage 1
26 # =========================================================================== #
28 _start:
30 .code16
31 stage1:
32 # 1. Setup canonical %cs:%eip, segment registers %ds, %es, %fs, %gs, %ss and stack %sp
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
44 call mapmem
45 sti
47 # 2. Enable A20 gate
48 call enableA20
50 # 3. Reset disk controller (%dl and %dh initialized by bios) and read Kernel into buffer
51 movl $(kernel_code_end - kernel_code_start), KernelSizeAdr
53 stage1__read:
54 mov current_sector, %ax
55 add $1, %ax
56 call lba2chs
58 mov current_sector, %ax
59 shl $5, %ax
60 add $(BUFFER / 16), %ax
61 mov %ax, %es
62 call readsectors
64 mov current_sector, %ax
65 add $READBLOCKS, %ax
66 mov %ax, current_sector
67 cmp $((kernel_code_end - kernel_code_start + 511) / 512), %ax
68 jl stage1__read
70 # 4. Disable interrupts and load GDT
71 mov $msg_protected_mode, %si
72 call print
73 cli
74 lgdt gdt_info
76 # 5. Switch to protected mode
77 mov %cr0, %eax
78 or $1, %al
79 mov %eax, %cr0
80 jmp $8, $stage2
82 # =========================================================================== #
83 # Stage 2
84 # =========================================================================== #
86 .code32
87 stage2:
88 # 6. Setup data segments %ds, %es, %fs, %gs and stack %sp
89 mov $16, %ax
90 mov %ax, %ds
91 mov %ax, %ss
92 mov %ax, %es
93 mov %ax, %fs
94 mov %ax, %gs
95 mov $STACK2, %sp
96 # 7. Copy Kernel from buffer
97 xor %eax, %eax
98 stage2_copy_loop:
99 mov BUFFER(%eax), %bh
100 mov %bh, ImageBase(%eax)
101 inc %eax
102 cmp $(kernel_code_end - kernel_code_start), %eax
103 jne stage2_copy_loop
104 # 8. Exec Kernel
105 jmp ImageBase
108 # =========================================================================== #
109 # Print asciiz string
110 # input: %si = String
111 # =========================================================================== #
113 .code16
114 print:
115 pusha
116 movb $0x0e, %ah
117 print__loop:
118 lodsb
119 orb %al, %al
120 jz print__ret
121 int $0x10
122 jmp print__loop
123 print__ret:
124 popa
125 ret
127 # =========================================================================== #
128 # Make memory map for kernel
129 # =========================================================================== #
131 .code16
132 mapmem:
133 pusha
134 movl $0, MemoryMapAdr
135 xor %ebx, %ebx
136 mov $(MemoryMapAdr + 4), %di
137 mapmem__loop:
138 mov $0xe820, %eax
139 mov $20, %ecx
140 mov $0x0534D4150, %edx
141 int $0x15
142 jc mapmem__failed
143 cmp %edx, %eax
144 jne mapmem__failed
145 cmp $0, %ebx
146 je mapmem__done
147 add $20, %di
148 incl MemoryMapAdr
149 jmp mapmem__loop
150 mapmem__done:
151 popa
152 ret # <============
153 mapmem__failed:
154 mov $msg_mapmem_failed, %si
155 call print
156 cli
157 hlt
159 # =========================================================================== #
160 # Convert LBA to CHS
161 # input: %ax = LBA %dl = disk
162 # output: %ch = cylider %cl = sector %dh = head %dl = disk
163 # =========================================================================== #
165 .code16
166 lba2chs:
167 # push %es
168 # push %di
169 push %dx
170 push %ax
172 clc
173 mov $0x0, %ax
174 mov %ax, %es
175 mov %ax, %di
176 mov $0x8, %ah
177 int $0x13
178 jnc lba2chs__success
179 mov $msg_chs_error, %si
180 call print
181 cli
182 hlt
183 lba2chs__success:
184 mov %dx, BootDiskDxAdr
185 mov %cx, BootDiskCxAdr
187 # SPT = %cl & 63
188 # HPC = %dh + 1
189 # CYL = LBA / ( HPC * SPT )
190 # TEMP = LBA % ( HPC * SPT )
191 # HEAD = TEMP / SPT
192 # SECT = TEMP % SPT + 1
194 # %ax = FREE %bx = FREE %cx = GSPT %dx = HPC-1
195 and $0x3F, %cl
196 movzx %cl, %cx
198 # %ax = FREE %bx = FREE %cx = SPT %dx = HPC-1
199 movzx %dh, %dx
200 inc %dx
202 # %ax = FREE %bx = FREE %cx = SPT %dx = HPC
203 mov %dx, %ax
204 mul %cx; # overflow in %dx
205 mov %ax, %dx
207 # %ax = FREE %bx = FREE %cx = SPT %dx = (HPC * SPT)
208 pop %ax # LBA
209 mov %dx, %bx
210 xor %dx, %dx
211 div %bx
212 xchg %ax, %dx
214 # %ax = TEMP %bx = FREE %cx = SPT %dx = CYL
215 mov %dx, %bx
216 xor %dx, %dx
217 div %cx
218 inc %dx
220 # %ax = HEAD %bx = CYL %cx = FREE %dx = SECT
221 mov %bl, %ch
222 mov %bh, %cl
223 shl $6, %cl
224 add %dx, %cx
226 # %ax = HEAD %bx = FREE %cx = CYL&SECT %dx = FREE
227 pop %dx
228 mov %al, %dh
230 # %ax = FREE %bx = FREE %cx = CYL&SECT %dx = HEAD&DISK
232 # pop %di
233 # pop %es
234 ret
236 # =========================================================================== #
237 # Read sectors to buffer
238 # input: %cx = Cylider+Sector; %es = 64k buf
239 # =========================================================================== #
241 .code16
242 readsectors:
243 xor %ah, %ah
244 int $0x13
246 xor %bx, %bx
247 mov $0x2, %ah
248 mov $READBLOCKS, %al
249 clc
250 int $0x13
252 jnc readsectors__success
254 /* zero if sectors not readed */
255 or %ah, %ah
256 jnz readsectors__success
258 mov $msg_kernel_read_failed, %si
259 call print
260 cli
261 hlt
263 readsectors__success:
264 ret
266 # =========================================================================== #
267 # Enable A20 Line
268 # =========================================================================== #
270 .code16
272 enableA20:
273 cli
274 xor %cx, %cx
275 enableA20_1:
276 inc %cx
277 jz enableA20_3
278 in $0x64, %al
279 test $0x2, %al
280 jnz enableA20_1
281 mov $0xd1, %al
282 out %al, $0x64
283 enableA20_2:
284 in $0x64, %al
285 test $0x2, %al
286 jnz enableA20_2
287 mov $0xdf, %al
288 out %al, $0x60
289 enableA20_3:
290 sti
291 ret
293 # =========================================================================== #
294 # =========================================================================== #
295 # =========================================================================== #
297 msg_mapmem_failed: .asciz "1"
298 msg_chs_error: .asciz "3"
299 msg_kernel_read_failed: .asciz "4"
300 msg_protected_mode: .asciz ">5"
302 current_sector:
303 .word 0
304 gdt_begin:
305 .byte 0x00, 0x00, 0, 0, 0, 0b00000000, 0b00000000, 0 # null dsc
306 .byte 0xff, 0xff, 0, 0, 0, 0b10011010, 0b11001111, 0 # code dsc
307 .byte 0xff, 0xff, 0, 0, 0, 0b10010010, 0b11001111, 0 # data dsc
308 gdt_info:
309 .word (gdt_info - gdt_begin - 1)
310 .quad (gdt_begin)
312 .fill _start + 510 - .
313 .word 0xaa55
315 kernel_code_start:
316 .incbin "../BlackBox.bin"
317 kernel_code_end:
319 .fill _start + (1440 * 1024) - .