174 lines
3.7 KiB
NASM
174 lines
3.7 KiB
NASM
; File: boot.asm
|
|
[org 0x7c00] ; BIOS loads us at 0x7C00
|
|
[bits 16] ; We start in 16-bit Real Mode
|
|
|
|
start:
|
|
mov bp, 0x7c00
|
|
mov sp, bp
|
|
|
|
call clear_screen
|
|
|
|
mov si, real_msg
|
|
call print_string
|
|
|
|
cli
|
|
|
|
lgdt [gdt_descriptor]
|
|
|
|
mov eax, cr0
|
|
or eax, 0x1
|
|
mov cr0, eax
|
|
|
|
; Far jump into 32-bit mode.
|
|
jmp 0x08:init_pm
|
|
|
|
; --- Helper: Print String (BIOS INT 0x10) ---
|
|
print_string:
|
|
pusha
|
|
mov ah, 0x0e ; INT 0x10 "Teletype Output" function
|
|
.loop:
|
|
lodsb ; Load byte at [SI] into AL, increment SI
|
|
cmp al, 0 ; Check for null terminator
|
|
je .done
|
|
int 0x10 ; Call BIOS video interrupt
|
|
jmp .loop
|
|
.done:
|
|
popa
|
|
ret
|
|
|
|
; --- Helper: Clear Screen ---
|
|
clear_screen:
|
|
pusha
|
|
mov ah, 0x00 ; Set Video Mode function
|
|
mov al, 0x03 ; 80x25 Text Mode
|
|
int 0x10
|
|
popa
|
|
ret
|
|
|
|
real_msg: db '[REAL] - Loaded successfully.', 0x0D, 0x0A, 0
|
|
|
|
gdt_start:
|
|
|
|
gdt_null: ; 8 bytes of zeros
|
|
dd 0x0
|
|
dd 0x0
|
|
|
|
gdt_code: ; Code Segment (0x08)
|
|
; Base=0, Limit=0xFFFFF, Access=0x9A, Flags=0xC
|
|
dw 0xffff ; Limit (bits 0-15)
|
|
dw 0x0 ; Base (bits 0-15)
|
|
db 0x0 ; Base (bits 16-23)
|
|
db 10011010b ; Access Byte (0x9A)
|
|
db 11001111b ; Flags (0xC) + Limit (bits 16-19)
|
|
db 0x0 ; Base (bits 24-31)
|
|
|
|
gdt_data: ; Data Segment (0x10)
|
|
; Base=0, Limit=0xFFFFF, Access=0x92, Flags=0xC
|
|
dw 0xffff
|
|
dw 0x0
|
|
db 0x0
|
|
db 10010010b ; Access Byte (0x92)
|
|
db 11001111b ; Flags (0xC) + Limit
|
|
db 0x0
|
|
gdt_end:
|
|
|
|
gdt_descriptor:
|
|
dw gdt_end - gdt_start - 1 ; Size (Limit)
|
|
dd gdt_start ; Start Address
|
|
|
|
; ==================================================
|
|
; 32-BIT PROTECTED MODE
|
|
; ==================================================
|
|
[bits 32]
|
|
init_pm:
|
|
; 5. Update Segment Registers
|
|
; Now that we are in 32-bit, we must point all segment registers
|
|
; to our new Data Segment (0x10)
|
|
mov ax, 0x10
|
|
mov ds, ax
|
|
mov ss, ax
|
|
mov es, ax
|
|
mov fs, ax
|
|
mov gs, ax
|
|
|
|
mov ebp, 0x90000 ; Update stack to a safe 32-bit area
|
|
mov esp, ebp
|
|
|
|
; 2. Set up Paging
|
|
mov eax, pml4_table
|
|
mov cr3, eax
|
|
|
|
; Link PML4 -> PDPT
|
|
mov dword [pml4_table], pdpt_table + 0x3
|
|
mov dword [pml4_table + 4], 0x0
|
|
|
|
; Link PDPT -> PD
|
|
mov dword [pdpt_table], pd_table + 0x3
|
|
mov dword [pdpt_table + 4], 0x0
|
|
|
|
; Link PD -> 2MB Physical Page 0
|
|
mov dword [pd_table], 0x83
|
|
mov dword [pd_table + 4], 0x0
|
|
|
|
; 3. Enable PAE
|
|
mov eax, cr4
|
|
or eax, 0x20
|
|
mov cr4, eax
|
|
|
|
; 4. Enable Long Mode in EFER
|
|
mov ecx, 0xC0000080
|
|
rdmsr
|
|
or eax, 0x00000100
|
|
wrmsr
|
|
|
|
; 5. Enable Paging
|
|
mov eax, cr0
|
|
or eax, 0x80000000
|
|
mov cr0, eax
|
|
|
|
; 6. Print "SoraOS Protected" directly to Video Memory
|
|
; We can't use BIOS interrupts anymore! We must write to 0xB8000.
|
|
mov ebx, 0xb8000
|
|
mov byte [ebx], 'S'
|
|
mov byte [ebx+1], 0x0f ; White on Black
|
|
mov byte [ebx+2], 'O'
|
|
mov byte [ebx+3], 0x0f
|
|
mov byte [ebx+4], 'R'
|
|
mov byte [ebx+5], 0x0f
|
|
mov byte [ebx+6], 'A'
|
|
mov byte [ebx+7], 0x0f
|
|
mov byte [ebx+8], ' '
|
|
mov byte [ebx+9], 0x0f
|
|
mov byte [ebx+10], 'P'
|
|
mov byte [ebx+11], 0x0f
|
|
mov byte [ebx+12], 'M'
|
|
mov byte [ebx+13], 0x0f
|
|
|
|
jmp $
|
|
|
|
; --- The Magic Boot Sector Footer ---
|
|
; Fill the rest of the 512 bytes with zeros
|
|
times 510-($-$$) db 0
|
|
; The BIOS signature (must be at the very end)
|
|
dw 0xAA55
|
|
|
|
section .bss
|
|
align 4096
|
|
pml4_table:
|
|
resb 4096
|
|
pdpt_table:
|
|
resb 4096
|
|
pd_table:
|
|
resb 4096
|
|
|
|
section .data
|
|
gdt_ptr:
|
|
dw (gdt_end - gdt_start - 1)
|
|
dq gdt_start
|
|
gdt_start:
|
|
dq 0x0000000000000000
|
|
dq 0x00AF9A000000FFFF ; Code
|
|
dq 0x00AF92000000FFFF ; Data
|
|
gdt_end:
|
|
|