// vim: et:sw=12:ts=12:sts=12 .global _start .text .code16 _start: cli cld // we keep our text and data close to each other xor %ax, %ax mov %ax, %ds call init_com1 mov $msg_start, %si call print mov $msg_a20, %si call print call enable_a20 mov $msg_unreal, %si call print call unreal mov $msg_memmap, %si call print call memmap mov $msg_fin, %si call print 1: hlt jmp 1b .set COM1, 0x3F8 .macro com1_write offset=0, byte mov $COM1+\offset, %dx mov $\byte, %al outb %al, %dx .endm init_com1: com1_write 1, 0x00 // clear interrupts com1_write 3, 0x80 // set DLAB to 1 com1_write 0, 0x0C // 9600 baud rate com1_write 1, 0x00 com1_write 3, 0x07 // 8 bit data + 1 parity bit ret enable_a20: // TODO more thorough implementation inb $0x92, %al or $2, %al outb %al, $0x92 ret unreal: push %ds lgdt gdt_ptr mov %cr0, %eax or $0x01, %al mov %eax, %cr0 ljmp $0x8, $1f 1: mov $0x10, %cx mov %cx, %ds and $0xFE, %al mov %eax, %cr0 ljmp $0x0, $2f 2: pop %ds ret memmap: push %bp mov %sp, %bp sub $24, %sp mov %ss, %ax mov %ax, %es mov %sp, %di xor %ebx, %ebx mov $0x534D4150, %edx mov $24, %ecx mov $0xE820, %eax int $0x15 mov %bp, %sp pop %bp ret print: xor %bx, %bx 1: mov $COM1+5, %dx inb %dx, %al test $0x20, %al jz 1b lodsb or %al, %al jz 2f mov $COM1, %dx outb %al, %dx mov $0x0E, %ah int $0x10 jmp 1b 2: ret gdt: // entry 0: null descriptor .word 0 .word 0 .byte 0 .byte 0 .byte 0 .byte 0 // entry 1: code segment .word 0xFFFF .word 0 .byte 0 .byte 0b10011010 .byte 0x8F .byte 0 // entry 2: data segment .word 0xFFFF .word 0 .byte 0 .byte 0b10010010 .byte 0x8F .byte 0 .set gdt_size, .-gdt gdt_ptr: .word gdt_size-1 .long gdt msg_start: .asciz "Netboot via fernlader v1 ...\r\n" msg_a20: .asciz " * Enabling A20\r\n" msg_unreal: .asciz " * Unreal Mode\r\n" msg_memmap: .asciz " * Fetching Memory Map\r\n" msg_fin: .asciz "Finished.\r\n"