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