232 lines
6.1 KiB
ArmAsm
232 lines
6.1 KiB
ArmAsm
// vim: ft=gas: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, %es
|
|
mov %ax, %ss
|
|
ljmp $SS_CODE16, $9f
|
|
9: .code16
|
|
.endm
|
|
|
|
.macro PROT32
|
|
.code16
|
|
mov $SS_DATA32, %ax
|
|
mov %ax, %ds
|
|
mov %ax, %es
|
|
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
|
|
|
|
// 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 bios_write
|
|
.code32
|
|
bios_write: push %ebp
|
|
mov %esp, %ebp
|
|
push %ebx
|
|
|
|
mov 8+0(%ebp), %edx
|
|
mov 8+4(%ebp), %ecx
|
|
|
|
PROT16
|
|
.code16
|
|
REAL
|
|
|
|
.bwloop: test %ecx, %ecx
|
|
jz .bwreturn
|
|
|
|
xor %bx, %bx
|
|
mov $0x0E, %ah
|
|
mov (%edx), %al
|
|
|
|
push %ecx
|
|
push %edx
|
|
int $0x10
|
|
pop %edx
|
|
pop %ecx
|
|
|
|
add $1, %edx
|
|
sub $1, %ecx
|
|
|
|
jmp .bwloop
|
|
|
|
.bwreturn: PROT
|
|
PROT32
|
|
.code32
|
|
|
|
pop %ebx
|
|
mov %ebp, %esp
|
|
pop %ebp
|
|
ret
|
|
|
|
.global bios_getmap
|
|
.code32
|
|
bios_getmap:push %ebp
|
|
mov %esp, %ebp
|
|
push %ebx
|
|
push %edi
|
|
|
|
mov 8+0(%ebp), %edi
|
|
|
|
PROT16
|
|
.code16
|
|
REAL
|
|
|
|
xor %ebx, %ebx
|
|
_gmnext: movl $0, 20(%di)
|
|
mov $0x534D4150, %edx // e820 magic number
|
|
mov $24, %ecx
|
|
mov $0xE820, %eax
|
|
int $0x15
|
|
jc _gmdone
|
|
test %ebx, %ebx
|
|
jz _gmdone
|
|
add $24, %di
|
|
jmp _gmnext
|
|
_gmdone: add $24, %di
|
|
|
|
|
|
PROT
|
|
PROT32
|
|
.code32
|
|
|
|
mov %edi, %eax
|
|
|
|
pop %edi
|
|
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
|
|
.word GDT
|
|
.word 0, 0, 0
|
|
|
|
msg_start: .asciz "Netboot via fernlader v2 ...\r\n"
|
|
msg_a20: .asciz " * Enabling A20 Gate\r\n"
|
|
msg_prot: .asciz " * Protected Mode\r\n"
|