Fixed dobule-faults: the BIOS 13h calls enabled interrupts behind my back
[bootcensus] / src / boot / boot2.s
1 # pcboot - bootable PC demo/game kernel
2 # Copyright (C) 2018  John Tsiombikas <nuclear@member.fsf.org>
3
4 # This program is free software: you can redistribute it and/or modify
5 # it under the terms of the GNU General Public License as published by
6 # the Free Software Foundation, either version 3 of the License, or
7 # (at your option) any later version.
8
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY, without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 # GNU General Public License for more details.
13
14 # You should have received a copy of the GNU General Public License
15 # along with this program.  If not, see <https://www.gnu.org/licenses/>.
16
17 # this is the second-stage boot loader
18         .code16
19         .section .boot2,"a"
20
21         # make sure any BIOS call didn't re-enable interrupts
22         cli
23
24         mov $0x13, %ax
25         int $0x10
26
27         # load initial GDT/IDT
28         lgdt (gdt_lim)
29         lidt (idt_lim)
30         # enable protection
31         mov %cr0, %eax
32         or $1, %eax
33         mov %eax, %cr0
34         # inter-segment jump to set cs selector to segment 1
35         ljmp $0x8,$0f
36
37         .code32
38         # set all data selectors to segment 2
39 0:      mov $0x10, %ax
40         mov %ax, %ds
41         mov %ax, %ss
42         mov %ax, %es
43         mov %ax, %gs
44         mov %ax, %fs
45
46         movb $10, %al
47         call ser_putchar
48
49         call clearscr
50
51         mov $hello, %esi
52         call putstr
53
54         # enable A20 line
55         call enable_a20
56
57         call logohack
58
59         cli
60         hlt
61
62 hello: .asciz "Switched to 32bit\n"
63
64         .align 4
65 gdt_lim: .word 23
66 gdt_base:.long gdt
67
68         .align 4
69 idt_lim: .word 111
70 idt_base:.long idt
71
72
73         .align 8
74 gdt:    # 0: null segment
75         .long 0
76         .long 0
77         # 1: code - base:0, lim:4g, G:4k, 32bit, avl, pres|app, dpl:0, type:code/non-conf/rd
78         .long 0x0000ffff
79         .long 0x00cf9a00
80         # 2: data - base:0, lim:4g, G:4k, 32bit, avl, pres|app, dpl:0, type:data/rw
81         .long 0x0000ffff
82         .long 0x00cf9200
83
84
85         .align 8
86 idt:    .space 104
87         # trap gate 13: general protection fault
88         .short prot_fault
89         .short 0x8
90         # type: trap, present, default
91         .short 0x8f00
92         .short 0
93
94 gpf_msg: .asciz "GP fault "
95
96 prot_fault:
97         mov (%esp), %eax
98         shr $3, %eax
99         call print_num
100         mov $64, %al
101         call putchar
102         mov 4(%esp), %eax
103         call print_num
104         mov $10, %al
105         call putchar
106         hlt
107
108 ena20_msg: .asciz "A20 line enabled\n"
109
110 enable_a20:
111         call test_a20
112         jnc a20done
113         call enable_a20_kbd
114         call test_a20
115         jnc a20done
116         call enable_a20_fast
117         call test_a20
118         jnc a20done
119         # keep trying ... we can't do anything useful without A20 anyway
120         jmp enable_a20
121 a20done:
122         mov $ena20_msg, %esi
123         call putstr
124         ret
125
126         # CF = 1 if A20 test fails (not enabled)
127 test_a20:
128         mov $0x07c000, %ebx
129         mov $0x17c000, %edx
130         movl $0xbaadf00d, (%ebx)
131         movl $0xaabbcc42, (%edx)
132         subl $0xbaadf00d, (%ebx)
133         ret
134
135         # enable A20 line through port 0x92 (fast A20)
136 enable_a20_fast:
137         mov $ena20_fast_msg, %esi
138         call putstr
139
140         in $0x92, %al
141         or $2, %al
142         out %al, $0x92
143         ret
144
145 ena20_fast_msg: .asciz "Attempting fast A20 enable\n"
146
147
148         # enable A20 line through the keyboard controller
149         .set KBC_DATA_PORT, 0x60
150         .set KBC_CMD_PORT, 0x64
151         .set KBC_STATUS_PORT, 0x64
152         .set KBC_CMD_RD_OUTPORT, 0xd0
153         .set KBC_CMD_WR_OUTPORT, 0xd1
154
155         .set KBC_STAT_OUT_RDY, 0x01
156         .set KBC_STAT_IN_FULL, 0x02
157
158 enable_a20_kbd:
159         mov $ena20_kbd_msg, %esi
160         call putstr
161
162         call kbc_wait_write
163         mov $KBC_CMD_WR_OUTPORT, %al
164         out %al, $KBC_CMD_PORT
165         call kbc_wait_write
166         mov $0xdf, %al
167         out %al, $KBC_DATA_PORT
168         ret
169
170 ena20_kbd_msg: .asciz "Attempting KBD A20 enable\n"
171
172         # wait until the keyboard controller is ready to accept another byte
173 kbc_wait_write:
174         in $KBC_STATUS_PORT, %al
175         and $KBC_STAT_IN_FULL, %al
176         jnz kbc_wait_write
177         ret
178
179         # better print routines, since we're not constrainted by the 512b of
180         # the boot sector.
181 cursor_x: .long 0
182 cursor_y: .long 0
183
184 putchar:
185         pusha
186         call ser_putchar
187
188         cmp $10, %al
189         jnz 0f
190         call video_newline
191         jmp 1f
192
193 0:      push %eax
194         mov cursor_y, %eax
195         mov $80, %ecx
196         mul %ecx
197         add cursor_x, %eax
198         mov %eax, %ebx
199         pop %eax
200
201         mov $0xb8000, %edx
202
203         # this looks retarded. in nasm: [ebx * 2 + edx]
204         mov %al, (%edx, %ebx, 2)
205         movb $7, 1(%edx, %ebx, 2)
206         incl cursor_x
207         cmpl $80, cursor_x
208         jnz 1f
209         call video_newline
210
211 1:      popa
212         ret
213         
214         # expects string pointer in esi
215 putstr:
216         mov (%esi), %al
217         cmp $0, %al
218         jz 0f
219         call putchar
220         inc %esi
221         jmp putstr
222 0:      ret
223
224         # expects number in eax
225 print_num:
226         # save registers
227         pusha
228
229         mov $numbuf + 16, %esi
230         movb $0, (%esi)
231         mov $10, %ebx
232 convloop:
233         xor %edx, %edx
234         div %ebx
235         add $48, %dl
236         dec %esi
237         mov %dl, (%esi)
238         cmp $0, %eax
239         jnz convloop
240
241         call putstr
242
243         # restore regs
244         popa
245         ret
246
247
248 video_newline:
249         movl $0, cursor_x
250         incl cursor_y
251         cmpl $25, cursor_y
252         jnz 0f
253         call scrollup
254         decl cursor_y
255 0:      ret
256
257 scrollup:
258         pusha
259         # move 80 * 24 lines from b8050 -> b8000
260         mov $0xb8000, %edi
261         mov $0xb8050, %esi
262         mov $480, %ecx
263         rep movsl
264         # clear last line (b8780)
265         mov $0xb8780, %edi
266         xor %eax, %eax
267         mov $20, %ecx
268         rep stosl
269         popa
270         ret
271
272 clearscr:
273         mov $0xb8000, %edi
274         xor %eax, %eax
275         mov $500, %ecx
276         rep stosl
277         ret
278
279         .set UART_DATA, 0x3f8
280         .set UART_LSTAT, 0x3fd
281         .set LST_TREG_EMPTY, 0x20
282
283 ser_putchar:
284         push %dx
285
286         cmp $10, %al
287         jnz 0f
288         push %ax
289         mov $13, %al
290         call ser_putchar
291         pop %ax
292
293 0:      mov %al, %ah
294         # wait until the transmit register is empty
295         mov $UART_LSTAT, %dx
296 wait:   in %dx, %al
297         and $LST_TREG_EMPTY, %al
298         jz wait
299         mov $UART_DATA, %dx
300         mov %ah, %al
301         out %al, %dx
302
303         pop %dx
304         ret
305
306
307 logohack:
308         # copy palette
309         mov $logo_pal, %esi
310         xor %cl, %cl
311
312 0:      xor %eax, %eax
313         mov $0x3c8, %dx
314         movb %cl, %al
315         outb %al, %dx
316         inc %dx
317         # red
318         movb (%esi), %al
319         inc %esi
320         shr $2, %al
321         outb %al, %dx
322         # green
323         movb (%esi), %al
324         inc %esi
325         shr $2, %al
326         outb %al, %dx
327         # blue
328         movb (%esi), %al
329         inc %esi
330         shr $2, %al
331         outb %al, %dx
332         add $1, %cl
333         jnc 0b
334
335         # copy pixels
336         mov $sintab, %ebp
337         mov $logo_pix, %esi
338 frameloop:
339         mov $0xa0000, %edi
340         movl $0, yval
341 yloop:
342         movl $0, xval
343 xloop:
344         # calc src scanline address -> ebx
345         xor %ecx, %ecx
346         mov yval, %ebx
347         shl $2, %ebx
348         add frameno, %ebx
349         and $0xff, %ebx
350         mov (%ebp, %ebx), %cl
351         shr $5, %ecx
352
353         mov yval, %eax
354         add %ecx, %eax
355         # bounds check
356         cmp $200, %eax
357         jl 0f
358         mov $199, %eax
359
360 0:      mov %eax, %ebx
361         shl $8, %eax
362         shl $6, %ebx
363         add %eax, %ebx
364
365         # calc src x offset -> eax
366         xor %ecx, %ecx
367         mov xval, %eax
368         shl $2, %eax
369         add frameno, %eax
370         and $0xff, %eax
371         mov (%ebp, %eax), %cl
372         shr $5, %ecx
373
374         mov xval, %eax
375         add %ecx, %eax
376         # bounds check
377         cmp $320, %eax
378         jl 0f
379         mov $319, %eax
380
381 0:      add %eax, %ebx
382         mov (%ebx, %esi), %al
383
384         mov %al, (%edi)
385         inc %edi
386
387         incl xval
388         cmpl $320, xval
389         jnz xloop
390
391         incl yval
392         cmpl $200, yval
393         jnz yloop
394
395         incl frameno
396
397         # wait vsync
398         mov $0x3da, %dx
399 0:      in %dx, %al
400         and $8, %al
401         jnz 0b
402 0:      in %dx, %al
403         and $8, %al
404         jz 0b
405         jmp frameloop
406
407 xval: .long 0
408 yval: .long 0
409 frameno: .long 0
410
411 numbuf: .space 16
412
413 logo_pal:
414         .incbin "logo.pal"
415
416         .align 16
417 logo_pix:
418         .incbin "logo.raw"
419
420 sintab:
421         .byte 127
422         .byte 130
423         .byte 133
424         .byte 136
425         .byte 139
426         .byte 143
427         .byte 146
428         .byte 149
429         .byte 152
430         .byte 155
431         .byte 158
432         .byte 161
433         .byte 164
434         .byte 167
435         .byte 170
436         .byte 173
437         .byte 176
438         .byte 179
439         .byte 182
440         .byte 184
441         .byte 187
442         .byte 190
443         .byte 193
444         .byte 195
445         .byte 198
446         .byte 200
447         .byte 203
448         .byte 205
449         .byte 208
450         .byte 210
451         .byte 213
452         .byte 215
453         .byte 217
454         .byte 219
455         .byte 221
456         .byte 224
457         .byte 226
458         .byte 228
459         .byte 229
460         .byte 231
461         .byte 233
462         .byte 235
463         .byte 236
464         .byte 238
465         .byte 239
466         .byte 241
467         .byte 242
468         .byte 244
469         .byte 245
470         .byte 246
471         .byte 247
472         .byte 248
473         .byte 249
474         .byte 250
475         .byte 251
476         .byte 251
477         .byte 252
478         .byte 253
479         .byte 253
480         .byte 254
481         .byte 254
482         .byte 254
483         .byte 254
484         .byte 254
485         .byte 255
486         .byte 254
487         .byte 254
488         .byte 254
489         .byte 254
490         .byte 254
491         .byte 253
492         .byte 253
493         .byte 252
494         .byte 251
495         .byte 251
496         .byte 250
497         .byte 249
498         .byte 248
499         .byte 247
500         .byte 246
501         .byte 245
502         .byte 244
503         .byte 242
504         .byte 241
505         .byte 239
506         .byte 238
507         .byte 236
508         .byte 235
509         .byte 233
510         .byte 231
511         .byte 229
512         .byte 228
513         .byte 226
514         .byte 224
515         .byte 221
516         .byte 219
517         .byte 217
518         .byte 215
519         .byte 213
520         .byte 210
521         .byte 208
522         .byte 205
523         .byte 203
524         .byte 200
525         .byte 198
526         .byte 195
527         .byte 193
528         .byte 190
529         .byte 187
530         .byte 184
531         .byte 182
532         .byte 179
533         .byte 176
534         .byte 173
535         .byte 170
536         .byte 167
537         .byte 164
538         .byte 161
539         .byte 158
540         .byte 155
541         .byte 152
542         .byte 149
543         .byte 146
544         .byte 143
545         .byte 139
546         .byte 136
547         .byte 133
548         .byte 130
549         .byte 127
550         .byte 124
551         .byte 121
552         .byte 118
553         .byte 115
554         .byte 111
555         .byte 108
556         .byte 105
557         .byte 102
558         .byte 99
559         .byte 96
560         .byte 93
561         .byte 90
562         .byte 87
563         .byte 84
564         .byte 81
565         .byte 78
566         .byte 75
567         .byte 72
568         .byte 70
569         .byte 67
570         .byte 64
571         .byte 61
572         .byte 59
573         .byte 56
574         .byte 54
575         .byte 51
576         .byte 49
577         .byte 46
578         .byte 44
579         .byte 41
580         .byte 39
581         .byte 37
582         .byte 35
583         .byte 33
584         .byte 30
585         .byte 28
586         .byte 26
587         .byte 25
588         .byte 23
589         .byte 21
590         .byte 19
591         .byte 18
592         .byte 16
593         .byte 15
594         .byte 13
595         .byte 12
596         .byte 10
597         .byte 9
598         .byte 8
599         .byte 7
600         .byte 6
601         .byte 5
602         .byte 4
603         .byte 3
604         .byte 3
605         .byte 2
606         .byte 1
607         .byte 1
608         .byte 0
609         .byte 0
610         .byte 0
611         .byte 0
612         .byte 0
613         .byte 0
614         .byte 0
615         .byte 0
616         .byte 0
617         .byte 0
618         .byte 0
619         .byte 1
620         .byte 1
621         .byte 2
622         .byte 3
623         .byte 3
624         .byte 4
625         .byte 5
626         .byte 6
627         .byte 7
628         .byte 8
629         .byte 9
630         .byte 10
631         .byte 12
632         .byte 13
633         .byte 15
634         .byte 16
635         .byte 18
636         .byte 19
637         .byte 21
638         .byte 23
639         .byte 25
640         .byte 26
641         .byte 28
642         .byte 30
643         .byte 33
644         .byte 35
645         .byte 37
646         .byte 39
647         .byte 41
648         .byte 44
649         .byte 46
650         .byte 49
651         .byte 51
652         .byte 54
653         .byte 56
654         .byte 59
655         .byte 61
656         .byte 64
657         .byte 67
658         .byte 70
659         .byte 72
660         .byte 75
661         .byte 78
662         .byte 81
663         .byte 84
664         .byte 87
665         .byte 90
666         .byte 93
667         .byte 96
668         .byte 99
669         .byte 102
670         .byte 105
671         .byte 108
672         .byte 111
673         .byte 115
674         .byte 118
675         .byte 121
676         .byte 124