From c3e1be53f1269385b7f2b64442b85747e20b2412 Mon Sep 17 00:00:00 2001 From: John Tsiombikas Date: Wed, 18 Apr 2018 11:41:18 +0300 Subject: [PATCH] protected mode debugging --- Makefile | 4 +- src/boot/boot.s | 1 - src/boot/boot2.s | 356 +++++++++++++++++++++++++++++++++++++++++++++--------- 3 files changed, 301 insertions(+), 60 deletions(-) diff --git a/Makefile b/Makefile index 7e0f1b0..7fa61b9 100644 --- a/Makefile +++ b/Makefile @@ -9,8 +9,8 @@ warn = -pedantic -Wall dbg = -g inc = -Isrc -Isrc/libc -CFLAGS = $(ccarch) $(warn) $(dbg) -nostdinc -fno-builtin $(inc) $(def) -ASFLAGS = $(asarch) $(dbg) -nostdinc -fno-builtin $(inc) +CFLAGS = $(ccarch) -march=i386 $(warn) $(dbg) -nostdinc -fno-builtin $(inc) $(def) +ASFLAGS = $(asarch) -march=i386 $(dbg) -nostdinc -fno-builtin $(inc) LDFLAGS = $(ldarch) -T pcboot.ld -print-gc-sections diff --git a/src/boot/boot.s b/src/boot/boot.s index bf32820..554f5a2 100644 --- a/src/boot/boot.s +++ b/src/boot/boot.s @@ -322,7 +322,6 @@ setup_serial: ret # expects a character in al - .global ser_putchar ser_putchar: push %dx diff --git a/src/boot/boot2.s b/src/boot/boot2.s index ec6f407..0f2bbf8 100644 --- a/src/boot/boot2.s +++ b/src/boot/boot2.s @@ -18,13 +18,308 @@ .code16 .section .boot2,"a" - .extern ser_putchar + .set drive_number, 0x7bec + # reset floppy drive + xor %ax, %ax + movb drive_number, %dl + int $0x13 + + # load initial GDT/IDT + lgdt (gdt_lim) + lidt (idt_lim) + # enable protection + mov %cr0, %eax + or $1, %eax + mov %eax, %cr0 + # inter-segment jump to set cs selector to segment 1 + ljmp $0x8,$0f + + .code32 + # set all data selectors to segment 2 +0: mov $0x10, %ax + mov %ax, %ds + mov %ax, %ss + mov %ax, %es + mov %ax, %gs + mov %ax, %fs - mov $0x13, %ax - int $0x10 + mov $0x18, %ax + ltr %ax + + #movb $10, %al + #call ser_putchar + + call clearscr + + mov $hello, %esi + call putstr + + # enable A20 line + call enable_a20 + + cli + hlt + +hello: .asciz "Switched to 32bit\n" + + .align 4 +gdt_lim: .word 31 +gdt_base:.long gdt + + .align 4 +idt_lim: .word 111 +idt_base:.long idt + + + .align 8 +gdt: # 0: null segment + .long 0 + .long 0 + # 1: code - base:0, lim:4g, G:4k, 32bit, avl, pres|app, dpl:0, type:code/non-conf/rd + .long 0x0000ffff + .long 0x00cf9a00 + # 2: data - base:0, lim:4g, G:4k, 32bit, avl, pres|app, dpl:0, type:data/rw + .long 0x0000ffff + .long 0x00cf9200 + # 3: dummy TSS - base:tss, lim:103, type avail 32bit TSS, byte-granular + .short 103 + .short tss + .short 0x8900 + .short 0 + + + .align 8 +idt: .space 104 + # trap gate 13: general protection fault + .short prot_fault + .short 0x8 + # type: trap, present, default + .short 0x8f00 + .short 0 + + .align 4 +tss: .space 104 + +gpf_msg: .asciz "GPF " + +prot_fault: + mov (%esp), %eax + shr $3, %eax + call print_num + mov $64, %al + call putchar + mov 4(%esp), %eax + call print_num + mov $10, %al + call putchar + hlt + +ena20_msg: .asciz "A20 line enabled\n" +foo_msg: .asciz "Foo\n" + +enable_a20: + mov $foo_msg, %esi + call putstr + jmp .La20done + + call test_a20 + jnc .La20done + call enable_a20_kbd + call test_a20 + jnc .La20done + call enable_a20_fast + call test_a20 + jnc .La20done + # keep trying ... we can't do anything useful without A20 anyway + jmp enable_a20 +.La20done: + mov $ena20_msg, %esi + call putstr + ret + + # CF = 1 if A20 test fails (not enabled) +test_a20: + mov $0x07c000, %ebx + mov $0x17c000, %edx + movl $0xbaadf00d, (%ebx) + movl $0xaabbcc42, (%edx) + subl $0xbaadf00d, (%ebx) + ret + +ena20_fast_msg: .asciz "Attempting fast A20 enable\n" + +enable_a20_fast: + mov $ena20_fast_msg, %esi + call putstr + + in $0x92, %al + or $2, %al + out %al, $0x92 + ret + + .set KBC_DATA_PORT, 0x60 + .set KBC_CMD_PORT, 0x64 + .set KBC_STATUS_PORT, 0x64 + .set KBC_CMD_RD_OUTPORT, 0xd0 + .set KBC_CMD_WR_OUTPORT, 0xd1 + + .set KBC_STAT_OUT_RDY, 0x01 + .set KBC_STAT_IN_FULL, 0x02 + +ena20_kbd_msg: .asciz "Attempting KBD A20 enable\n" + + # enable A20 line through the keyboard controller +enable_a20_kbd: + mov $ena20_kbd_msg, %esi + call putstr + + call kbc_wait_write + mov $KBC_CMD_WR_OUTPORT, %al + out %al, $KBC_CMD_PORT + call kbc_wait_write + mov $0xdf, %al + out %al, $KBC_DATA_PORT + ret + + # wait until the keyboard controller is ready to accept another byte +kbc_wait_write: + in $KBC_STATUS_PORT, %al + and $KBC_STAT_IN_FULL, %al + jnz kbc_wait_write + ret + + # better print routines, since we're not constrainted by the 512b of + # the boot sector. +cursor_x: .long 0 +cursor_y: .long 0 + +putchar: + pusha + call ser_putchar + + cmp $10, %al + jnz 0f + call video_newline + jmp 1f + +0: push %eax + mov cursor_y, %eax + mov $80, %ecx + mul %ecx + add cursor_x, %eax + mov %eax, %ebx + pop %eax + + mov $0xb8000, %edx + + # this looks retarded. in nasm: [ebx * 2 + edx] + mov %al, (%edx, %ebx, 2) + movb $7, 1(%edx, %ebx, 2) + incl cursor_x + cmpl $80, cursor_x + jnz 1f + call video_newline + +1: popa + ret + + # expects string pointer in esi +putstr: + mov (%esi), %al + cmp $0, %al + jz 0f + call putchar + inc %esi + jmp putstr +0: ret + + # expects number in eax +print_num: + # save registers + pusha + + mov $numbuf + 16, %esi + movb $0, (%esi) + mov $10, %ebx +.Lconvloop: + xor %edx, %edx + div %ebx + add $48, %dl + dec %esi + mov %dl, (%esi) + cmp $0, %eax + jnz .Lconvloop + + call putstr + + # restore regs + popa + ret + + +video_newline: + movl $0, cursor_x + incl cursor_y + cmpl $25, cursor_y + jnz 0f + call scrollup + decl cursor_y +0: ret + +scrollup: + pusha + # move 80 * 24 lines from b8050 -> b8000 + mov $0xb8000, %edi + mov $0xb8050, %esi + mov $480, %ecx + rep movsl + # clear last line (b8780) + mov $0xb8780, %edi + xor %eax, %eax + mov $20, %ecx + rep stosl + popa + ret + +clearscr: + mov $0xb8000, %edi + xor %eax, %eax + mov $500, %ecx + rep stosl + ret - movb $10, %al + .set UART_DATA, 0x3f8 + .set UART_LSTAT, 0x3fd + .set LST_TREG_EMPTY, 0x20 + +ser_putchar: + push %dx + + cmp $10, %al + jnz 0f + push %ax + mov $13, %al call ser_putchar + pop %ax + +0: mov %al, %ah + # wait until the transmit register is empty + mov $UART_LSTAT, %dx +.Lwait: in %dx, %al + and $LST_TREG_EMPTY, %al + jz .Lwait + mov $UART_DATA, %dx + mov %ah, %al + out %al, %dx + + pop %dx + ret + + + .code16 +logohack: + mov $0x13, %ax + int $0x10 # copy palette mov $logo_pal, %si @@ -34,50 +329,22 @@ mov $0x3c8, %dx movb %cl, %al outb %al, %dx - #### DBG - call ser_print_num - mov $58, %al - call ser_putchar - mov $32, %al - call ser_putchar - xor %eax, %eax - #### inc %dx # red movb (%si), %al inc %si shr $2, %al outb %al, %dx - #### DBG - call ser_print_num - mov $32, %al - call ser_putchar - xor %eax, %eax - #### # green movb (%si), %al inc %si shr $2, %al outb %al, %dx - #### DBG - call ser_print_num - mov $32, %al - call ser_putchar - xor %eax, %eax - #### # blue movb (%si), %al inc %si shr $2, %al outb %al, %dx - #### DBG - call ser_print_num - mov $32, %al - call ser_putchar - mov $10, %al - call ser_putchar - xor %eax, %eax - #### add $1, %cl jnc 0b @@ -167,9 +434,6 @@ jz 0b jmp .Lframeloop - cli - hlt - xval: .word 0 yval: .word 0 frameno: .word 0 @@ -189,28 +453,6 @@ ser_print_str: ret - # expects number in eax -ser_print_num: - # save registers - pusha - - movw $numbuf + 16, %si - movb $0, (%si) - mov $10, %ebx -.Lconvloop: - xor %edx, %edx - div %ebx - add $48, %dl - dec %si - mov %dl, (%si) - cmp $0, %eax - jnz .Lconvloop - - call ser_print_str - - # restore regs - popa - ret numbuf: .space 16 -- 1.7.10.4