// vim: et:sw=12:ts=12:sts=12 .global _start .set SS_CODE16, 0x08 .set SS_DATA16, 0x10 .set SS_CODE32, 0x18 .set SS_DATA32, 0x20 .macro PROT16 .code32 mov $SS_DATA16, %ax mov %ax, %ds mov %ax, %ss ljmp $SS_CODE16, $9f 9: .code16 .endm .macro PROT32 .code16 mov $SS_DATA32, %ax mov %ax, %ds mov %ax, %ss ljmp $SS_CODE32, $9f 9: .code32 .endm .macro REAL mov %cr0, %eax and $0xFFFE, %ax mov %eax, %cr0 xor %ax, %ax mov %ax, %ds mov %ax, %es mov real_ss, %ax mov %ax, %ss shl $4, %eax sub %eax, %esp ljmp $0x0000, $9f 9: .endm .macro PROT mov %cr0, %eax or $1, %eax mov %eax, %cr0 xor %eax, %eax mov $SS_DATA16, %ax mov %ax, %ds mov %ax, %es mov %ax, %ss mov real_ss, %ax shl $4, %eax add %eax, %esp .endm .text .code16 // _start: entry point _start: cli cld mov %sp, %bp xor %ax, %ax mov %ax, %ds mov %ax, %es mov %ss, %ax mov %ax, real_ss push $msg_start call dbgmsg add $2, %sp xor %bx, %bx mov $0x0E, %ah mov $'B', %al int $0x10 // initialize our own BSS section mov $_bss_start, %di mov $_bss_end, %cx sub %di, %cx xor %al, %al rep stosb // a20_enable: Allow use of 'high' (>1Mb) memory a20_enable: // Of all the ways to toggle A20, we only try the Fast A20 Gate. // This is known to cause problems on some ancient systems, // but as our bootloader exclusively runs on 64-bit machines, // we should not run into any of those systems. // Modern machines apparently don't even have the A20 line anymore. push $msg_a20 call dbgmsg add $2, %sp inb $0x92, %al or $2, %al outb %al, $0x92 // prot_enter: Set up GDT, switch into 32-bit protected mode. prot_enter: push $msg_prot call dbgmsg add $2, %sp lgdt GDT_PTR PROT PROT32 .code32 jmp main .code16 dbgmsg: push %bp mov %sp, %bp push %ax push %si mov 4(%bp), %si 1: lodsb test %al, %al jz 2f outb %al, $0xE9 jmp 1b 2: pop %si pop %ax pop %bp ret .global writechar .code32 writechar: push %ebp mov %esp, %ebp push %ebx PROT16 .code16 REAL xor %bx, %bx mov $0x0E, %ah mov $'A', %al int $0x10 PROT PROT32 .code32 pop %ebx mov %ebp, %esp pop %ebp ret .data real_ss: .word 0 .global GDT GDT: // entry 0: null descriptor .space 8, 0 // entry 1: 16-bit code segment .byte 0xFF, 0xFF, 0, 0, 0, 0b10011010, 0x8F, 0 // entry 2: 16-bit data segment .byte 0xFF, 0xFF, 0, 0, 0, 0b10010010, 0x8F, 0 // entry 3: 32-bit code segment .byte 0xFF, 0xFF, 0, 0, 0, 0b10011010, 0xCF, 0 // entry 4: 32-bit data segment .byte 0xFF, 0xFF, 0, 0, 0, 0b10010010, 0xCF, 0 // TODO: 32-bit TSS .set GDT_SIZE, . - GDT GDT_PTR: .word GDT_SIZE - 1 .quad GDT msg_start: .asciz "Netboot via fernlader v2 ...\r\n" msg_a20: .asciz " * Enabling A20 Gate\r\n" msg_prot: .asciz " * Protected Mode\r\n"