; boot.asm ; Author: Josh Holtrop ; Date: 2009-06-25 ; Adapted from HOS 0.16 source %define MULTIBOOT_HEADER_MAGIC 0x1BADB002 %define MULTIBOOT_HEADER_FLAGS 0x00010003 %define VIRTUAL_OFFSET 0xE0000000 ; kernel virtual addr %define CONSOLE_MEMORY 0xB8000 %define PAGE_SIZE 0x1000 ; 4KB pages ; Symbols from the linker extern _end, _bss ; Symbols from C extern k_bootstrap, bootstrap_stack, mm_gdtr ;------------------------------------------------------- [section .text] ;************************************************************************** ;* This is the first symbol in the .text section * ;************************************************************************** [global start] start: ;************************************************************************** ;* Multiboot header data block * ;************************************************************************** align 4 multiboot_header: dd MULTIBOOT_HEADER_MAGIC ; magic dd MULTIBOOT_HEADER_FLAGS ; flags dd -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS) ; checksum dd multiboot_header - VIRTUAL_OFFSET ; header_addr dd start - VIRTUAL_OFFSET ; load_addr dd _bss - VIRTUAL_OFFSET ; load_end_addr dd _end - VIRTUAL_OFFSET ; bss_end_addr dd multiboot_entry - VIRTUAL_OFFSET ; entry_addr ;************************************************************************** ;* Resume execution * ;************************************************************************** multiboot_entry: mov cx, 0x0700 + 'a' mov [CONSOLE_MEMORY+160*8+0*2], cx lgdt [gdtr_tmp32-VIRTUAL_OFFSET] ; load temporary GDTR jmp KERNEL_CODE_32_TMP_SEG:segmented_start ;************************************************************************** ;* At this point address 0xE000_0000 is mapped to physical address 0x0 * ;************************************************************************** segmented_start: mov cx, KERNEL_DATA_32_TMP_SEG mov ss, cx mov ds, cx mov es, cx mov gs, cx mov fs, cx mov esp, bootstrap_stack+4096-4 ; set up temporary stack space mov cx, 0x0700 + 'b' mov [CONSOLE_MEMORY+VIRTUAL_OFFSET+160*8+1*2], cx add ebx, VIRTUAL_OFFSET push eax ; multiboot bootloader magic value push ebx ; pointer to multiboot info struct call k_bootstrap add esp, 8 mov cx, 0x0700 + 'e' mov [CONSOLE_MEMORY+VIRTUAL_OFFSET+160*8+4*2], cx lgdt [mm_gdtr] ; load permanent GDTR jmp 0x8:segmentation_disabled-VIRTUAL_OFFSET ;************************************************************************** ;* At this point both segmentation and paging are disabled but we can * ;* now enable paging * ;************************************************************************** segmentation_disabled: mov cx, 0x10 mov ss, cx mov ds, cx mov es, cx mov gs, cx mov fs, cx ; at this point paging is still disabled but the PDBR is valid and ; points to a page directory that has all of RAM mapped to the ; beginning of the kernel's virtual address space, and the entire ; kernel mapped in above 0xE000_0000. ; turn on paging mov eax, cr0 bts eax, 31 mov cr0, eax ; OK, segmentation is disabled and paging is active! mov cx, 0x0700 + 'f' mov [CONSOLE_MEMORY+160*8+5*2], cx idle_loop: hlt jmp idle_loop ;------------------------------------------------------- [section .rodata] gdtr_tmp32: dw gdt_end_tmp32-gdt_tmp32-1 dd gdt_tmp32-VIRTUAL_OFFSET gdt_tmp32: ; 0 = null descriptor dd 0 dd 0 ; a base of 0x2000_0000, when added to 0xE000_0000 will produce ; 0x0000_0000 physical before paging in effect KERNEL_CODE_32_TMP_SEG equ $-gdt_tmp32 ; 8 db 0xff ; limit 7:0 db 0xff ; limit 15:8 db 0x00 ; base 7:0 db 0x00 ; base 15:8 db 0x00 ; base 23:16 db 0x9a ; access db 0xcf ; flags / limit 19:16 db 0x20 ; base 31:24 KERNEL_DATA_32_TMP_SEG equ $-gdt_tmp32 ; 16 db 0xff ; limit 7:0 db 0xff ; limit 15:8 db 0x00 ; base 7:0 db 0x00 ; base 15:8 db 0x00 ; base 23:16 db 0x92 ; access db 0xcf ; flags / limit 19:16 db 0x20 ; base 31:24 gdt_end_tmp32: