#define GLOBAL(x) .globl x ; x
.equ LOAD_ADDRESS, 0x10000
.equ INITIAL_LOAD_ADDRESS, 0x07C00
.equ INITIAL_LOAD_OFFSET, INITIAL_LOAD_ADDRESS - LOAD_ADDRESS
.text
.code16
pxe_start:
xorw %ax, %ax
movw %ax, %ds
movw %ax, %es
movw %ax, %ss
movw $0x7c00, %sp
cld
mov $kStartMessage + INITIAL_LOAD_OFFSET, %esi
call puts
cli
call enable_a20
call go_unreal
sti
movl $kUnrealMessage + INITIAL_LOAD_OFFSET, %esi
call puts
movl $_end, %ecx
addl $3, %ecx
andb $0xfc, %cl
movl %ecx, %edi
subl $LOAD_ADDRESS, %ecx
movl $INITIAL_LOAD_ADDRESS, %esi
addl %ecx, %esi
shrl $2, %ecx
_copy: subl $4, %esi
subl $4, %edi
movl (%esi), %eax
movl %eax, (%edi)
decl %ecx
jnz _copy
.code32
.byte 0x66
ljmp $0x1000, $relocated_start - LOAD_ADDRESS
.code16
relocated_start:
cli
.code32
.byte 0x66
.byte 0x67
lgdt pm_gdt_descriptor
.code16
movl %cr0, %eax
orb $0x1, %al
movl %eax, %cr0
.code32
.byte 0x66
ljmp $0x8, $pm_start
pm_start:
mov $0x10, %ax
mov %ax, %ds
mov %ax, %es
mov %ax, %fs
mov %ax, %gs
mov %ax, %ss
call _start
.code16
stop: hlt
jmp stop
puts: pushal
_puts2: lodsb
testb %al, %al
jnz putc
popal
ret
putc: movw $0x7, %bx
movb $0xe, %ah
int $0x10
jmp _puts2
enable_a20: inb $0x92, %al
testb $0x02, %al
jnz _a20_out
orb $0x02, %al
andb $0xfe, %al
outb %al, $0x92
_a20_out: ret
go_unreal: pushw %ds
pushw %es
pushw %bx
.code32
.byte 0x66
.byte 0x67
lgdt unreal_gdt_descriptor + INITIAL_LOAD_OFFSET
.code16
movl %cr0, %eax
orb $1, %al
movl %eax, %cr0
movw $8, %bx
movw %bx, %ds
movw %bx, %es
decb %al
movl %eax, %cr0
popw %bx
popw %es
popw %ds
ret
kStartMessage: .asciz "\r\nHaiku PXE bootloader version 1.0\r\n\r\n"
kUnrealMessage: .asciz "Switch to unreal mode done\r\n"
.balign 8
unreal_gdt:
.long 0
.long 0
.long 0x0000ffff
.long 0x00cf9200
unreal_gdt_descriptor:
.word 0x10
.long unreal_gdt + INITIAL_LOAD_OFFSET
.balign 8
pm_gdt:
.long 0
.long 0
.long 0x0000ffff
.long 0x00cf9e00
.long 0x0000ffff
.long 0x00cf9200
.long 0x0000ffff
.long 0x00009e01
.long 0x0000ffff
.long 0x00009201
.long 0x0000ffff
.long 0x00009200
pm_gdt_descriptor:
.word 0x2f
.long pm_gdt
.balign 8
GLOBAL(gMultiBootInfo):
.long 0
GLOBAL(gBootPartitionOffset):
.long 0xffffffff
GLOBAL(gBootedFromImage):
.byte 1
GLOBAL(gBootDriveID):
.byte 0xff
.balign 8