Code: Select all
;-----------------------------------------------------------------------------------------;
; kboot.asm: Version two of the kernel bootstrap (forms jump point for GRUB) ;
; Written by Ben Melikant 11/2014 ;
; This bootstrap sets up a basic paging directory table for the kernel so that our ;
; jump to the kernel does not result in triple-fault. ;
;-----------------------------------------------------------------------------------------;
bits 32
; paging identification info
%define PAGE_DIRECTORY_ADDR 0x9C000
%define PAGE_TABLE_0_ADDR 0x9D000
%define PAGE_TABLE_768_ADDR 0x9E000
%define PAGE_TABLE_ENTRIES 1024
%define FIRST_MEG_ENTRIES 256
%define PAGE_PRIVILEGE 3
; multiboot information definitions
MULTIBOOT_PAGE_ALIGN equ 1<<0
MULTIBOOT_MEMORY_INFO equ 1<<1
MULTIBOOT_HEADER_MAGIC equ 0x1BADB002
MULTIBOOT_HEADER_FLAGS equ MULTIBOOT_PAGE_ALIGN | MULTIBOOT_MEMORY_INFO
MULTIBOOT_CHECKSUM equ -(MULTIBOOT_HEADER_MAGIC+MULTIBOOT_HEADER_FLAGS)
; place the multiboot header in it's own section
[section .multiboot]
align 4
multiboot_hdr:
dd MULTIBOOT_HEADER_MAGIC
dd MULTIBOOT_HEADER_FLAGS
dd MULTIBOOT_CHECKSUM
; switch to the .startup section
[section .startup]
[global start]
; memory location to preserve the multiboot pointer
multiboot_ptr dd 0x00000000
; global descriptor table (to override GRUB's table)
gdt_start:
dd 0,0
db 0xff,0xff,0x00,0x00,0x00,10011010b,11001111b,0x00
db 0xff,0xff,0x00,0x00,0x00,10010010b,11001111b,0x00
gdt_table:
dw gdt_table-gdt_start-1
dd gdt_start
;------------------------------------------------------------------------------------------;
; start: Load into the operating system proper by setting up a page directory table ;
; and enabling paging. The OS is loaded at 0x10000 physical, 0xC0000000 virtual. ;
; If the OS ever returns, we have an issue. ;
;------------------------------------------------------------------------------------------;
start:
; load a new global descriptor table (override GRUB's table)
lgdt [gdt_table]
jmp 0x08:next
next:
; fix our segments
mov ax,0x10
mov ds,ax
mov es,ax
mov fs,ax
mov gs,ax
mov ss,ax
; jump to the actual start code, below the paging install routine
mov dword [multiboot_ptr],ebx
jmp start_system
;---------------------------------------------------------;
; setup_paging: Enable paging before executing OS ;
; Inputs: None, Returns: None ;
;---------------------------------------------------------;
setup_paging:
; save the registers
pusha
; identity-map addresses 0x00000000 - 0x00400000
mov eax,PAGE_TABLE_0_ADDR
mov ebx,0 | PAGE_PRIVILEGE
mov ecx,PAGE_TABLE_ENTRIES
.identity_loop:
mov dword [eax],ebx ; put the address entry into the table
add eax,4 ; queue next page entry
add ebx,4096 ; each entry is 4Kb
loop .identity_loop ; set up next entry
; next set up the address for the kernel page table
mov eax,PAGE_TABLE_768_ADDR
mov ebx,0x10000 | PAGE_PRIVILEGE
mov ecx,PAGE_TABLE_ENTRIES
.kernel_loop:
mov dword [eax],ebx ; same as above
add eax,4 ; same as above
add ebx,4096 ; same as above
loop .kernel_loop ; same as above
.already_mapped:
; install the tables into the directory
mov eax,PAGE_TABLE_0_ADDR | PAGE_PRIVILEGE
mov dword [PAGE_DIRECTORY_ADDR],eax
mov eax,PAGE_TABLE_768_ADDR | PAGE_PRIVILEGE
mov dword [PAGE_DIRECTORY_ADDR+(768*4)],eax
; install the page directory into cr3 (pdbr)
mov eax,PAGE_DIRECTORY_ADDR
mov cr3,eax
popa
ret
start_system:
; first set up the page directory table and page tables
call setup_paging
push dword [multiboot_ptr]
mov ebx,0xb8000
mov byte [ebx],'H'
; now enable the paging mechanism
mov eax,cr0
or eax,0x80000000
mov cr0,eax
mov byte [0xc0000000],'i' ; this memory access works...
jmp 0x08:paging_code
; paging is enabled. All addresses must now be translated as virtual
; switch to the .text section (regular system code, 0xC0000000 virtual)
[section .text]
[extern kmain]
paging_code:
; mov ebx,0xb8002
; mov byte [ebx],'i'
; restore the multiboot ptr
; pop ebx
; now all we need to do is call the kernel loadpoint
; mov esp,system_stack
; push ebx
; call kmain
; a safeguard. The code should never reach this point
jmp $
[section .bss]
resb 0x1000
system_stack:
; our kernel stack begins here
Code: Select all
OUTPUT_FORMAT("elf32-i386")
ENTRY(start)
SECTIONS {
. = 0x10000;
.startup :
{
*(.multiboot)
*(.startup)
}
. += 0xC0000000;
.text : AT(ADDR(.text) - 0xC0000000)
{
*(.text)
}
.data ALIGN(4096) : AT(ADDR(.data) - 0xC0000000)
{
*(.data)
*(.rodata*)
}
.bss ALIGN(4096) : AT(ADDR(.bss) - 0xC0000000)
{
*(COMMON*)
*(.bss*)
}
kernel_end=.;
}