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