bond/hal/boot.asm.in

214 lines
5.7 KiB
NASM

#define ASM_FILE
#include "multiboot2.h"
%define GET_PADDR(x) ((x) - KERNEL_IMAGE_VADDR + KERNEL_IMAGE_PADDR)
%define BOCHS_BREAK xchg bx,bx
extern hal_main
global hal_main_32
section .multiboot_header
bits 32
MULTIBOOT_ARCH equ 0
MULTIBOOT_CHECK_SUM equ (0xFFFFFFFF - (MULTIBOOT2_HEADER_MAGIC + MULTIBOOT_HEADER_SIZE + MULTIBOOT_ARCH) + 1)
MULTIBOOT_REQ_LOADERNAME equ 2
MULTIBOOT_REQ_MMAP equ 6
MULTIBOOT_REQ_ACPI_RSDP equ 15
;====================
;header tag
align MULTIBOOT_HEADER_ALIGN
multiboot_header_tag:
dd MULTIBOOT2_HEADER_MAGIC
dd MULTIBOOT_ARCH
dd MULTIBOOT_HEADER_SIZE
dd MULTIBOOT_CHECK_SUM
;====================
;INFO_REQUEST_TAG
align MULTIBOOT_INFO_ALIGN
multiboot_info_tag:
dw 0x1 ; type=1
dw 0x0 ; flag=0
dd MULTIBOOT_INFO_TAG_SIZE
dd MULTIBOOT_REQ_LOADERNAME
dd MULTIBOOT_REQ_MMAP
MULTIBOOT_INFO_TAG_SIZE equ ($ - multiboot_info_tag)
;====================
;MODULE ALIGNMENT TAG
align MULTIBOOT_INFO_ALIGN
dw 0x6; type=6
dw 0x0; flag=0
dd 0x8
;====================
align MULTIBOOT_INFO_ALIGN
;End_tag
dw 0x0
dw 0x0
dd 0x8
;====================
MULTIBOOT_HEADER_SIZE equ ($ - multiboot_header_tag)
section .text
bits 32
align KERNEL_PAGE_SIZE
hal_main_32:
cli
cld
cmp eax,MULTIBOOT2_BOOTLOADER_MAGIC
je .loaded_by_grub
hlt
.loaded_by_grub:
; save multiboot_info*
mov esi,ebx
call halp_check_long_mode
cmp eax,1
je .init_long_mode
hlt
.init_long_mode:
; disable paging first
mov eax, cr0 ; Set the A-register to control register 0.
and eax, 0x7FFFFFFF ; Clear the PG-bit, which is bit 31.
mov cr0, eax ; Set control register 0 to the A-register.
; identity map the first 4GB
; ATTRIBUTE = READ/WRITE + SU
mov eax, GET_PADDR(_pml4)
mov dword [eax], GET_PADDR(_pdpt) + 11b
; write values for pdpt
mov ecx, 10000011b
mov eax, GET_PADDR(_pdpt)
mov dword [eax], ecx
add eax,8
add ecx,0x40000000 ;1G
mov dword [eax], ecx
add eax,8
add ecx,0x40000000 ;1G
mov dword [eax], ecx
add eax,8
add ecx,0x40000000 ;1G
mov dword [eax], ecx
BOCHS_BREAK
; enable PAE
mov eax, cr4 ; Set the A-register to control register 4.
or eax, 1 << 5 ; Set the PAE-bit, which is the 6th bit (bit 5).
mov cr4, eax ; Set control register 4 to the A-register.
; enable long mode
mov ecx, 0xC0000080 ; Set the C-register to 0xC0000080, which is the EFER MSR.
rdmsr ; Read from the model-specific register.
or eax, 1 << 8 ; Set the LM-bit which is the 9th bit (bit 8).
wrmsr ; Write to the model-specific register.
; let cr3 point at page table
mov eax, GET_PADDR(_pml4)
mov cr3, eax
; enable paging, enter compatibility mode
mov eax, cr0 ; Set the A-register to control register 0.
or eax, 1 << 31 ; Set the PG-bit, which is bit 31.
mov cr0, eax ; Set control register 0 to the A-register.
; enter long mode
lgdt [GET_PADDR(_gdt.ptr)]
jmp _gdt.code:GET_PADDR(halp_entry_64)
hlt
halp_check_long_mode:
push ebp
mov ebp,esp
pushfd
pop eax
mov ecx, eax
xor eax, 1 << 21
push eax
popfd
pushfd
pop eax
push ecx
popfd
xor eax, ecx
jz .not_supported
mov eax, 0x80000000 ; Set the A-register to 0x80000000.
cpuid ; CPU identification.
cmp eax, 0x80000001 ; Compare the A-register with 0x80000001.
jb .not_supported ; It is less, there is no long mode.
mov eax, 0x80000001 ; Set the A-register to 0x80000001.
cpuid ; CPU identification.
test edx, 1 << 29 ; Test if the LM-bit, which is bit 29, is set in the D-register.
jz .not_supported ; They aren't, there is no long mode.
mov eax,1
jmp .end
.not_supported:
xor eax,eax
.end:
mov esp,ebp
pop ebp
ret
section .text
bits 64
halp_entry_64:
; note that we are still at the identity mapping
mov ax,_gdt.data
mov ds,ax
mov es,ax
mov fs,ax
mov gs,ax
mov ss,ax
mov rsp, GET_PADDR(_stack)
mov rdi, rsi ; multiboot_info*
call hal_write_initial_page_table
test rax,rax
jne .end
call hal_main
.end:
hlt
section .data
bits 64
align KERNEL_PAGE_SIZE
times KERNEL_PAGE_SIZE db 0
_stack:
_pml4:
align KERNEL_PAGE_SIZE
times KERNEL_PAGE_SIZE db 0
_pdpt:
align KERNEL_PAGE_SIZE
times KERNEL_PAGE_SIZE db 0
_gdt: ; Global Descriptor Table (long mode).
.null: equ $ - _gdt ; The null descriptor.
dw 0 ; Limit (low).
dw 0 ; Base (low).
db 0 ; Base (middle)
db 0 ; Access.
db 0 ; Granularity.
db 0 ; Base (high).
.code: equ $ - _gdt ; The code descriptor.
dw 0 ; Limit (low).
dw 0 ; Base (low).
db 0 ; Base (middle)
db 10011010b ; Access (exec/read).
db 00100000b ; Granularity.
db 0 ; Base (high).
.data: equ $ - _gdt ; The data descriptor.
dw 0 ; Limit (low).
dw 0 ; Base (low).
db 0 ; Base (middle)
db 10010010b ; Access (read/write).
db 00000000b ; Granularity.
db 0 ; Base (high).
.ptr:
; GDT PTR
dw $ - _gdt - 1 ; Limit.
dq GET_PADDR(_gdt) ; Base.