2020-12-02 02:41:09 +00:00
|
|
|
# Constants for multiboot
|
|
|
|
.set ALIGN, 1<<0 # align on page boundaries
|
|
|
|
.set MEMINFO, 1<<1 # memory map
|
|
|
|
.set FLAGS, ALIGN | MEMINFO # for multiboot 'flag' field
|
|
|
|
.set MAGIC, 0x1BADB002 # magic number for bootloader
|
|
|
|
.set CHECKSUM, -(MAGIC + FLAGS) # checksum to prove we're multiboot
|
|
|
|
|
|
|
|
# Declare header for multiboot
|
2022-10-29 15:03:56 +00:00
|
|
|
.section .multiboot.data, "aw"
|
2020-12-02 02:41:09 +00:00
|
|
|
.align 4
|
|
|
|
.long MAGIC
|
|
|
|
.long FLAGS
|
|
|
|
.long CHECKSUM
|
|
|
|
|
|
|
|
# Reserve stack for initial thread
|
2022-10-29 15:03:56 +00:00
|
|
|
.section .bootstrap_stack, "aw", @nobits
|
2020-12-02 02:41:09 +00:00
|
|
|
stack_bottom:
|
|
|
|
.skip 16384 # 16K
|
|
|
|
stack_top:
|
|
|
|
|
2022-10-29 15:03:56 +00:00
|
|
|
# Preallocate pages for paging
|
|
|
|
.section .bss, "aw", @nobits
|
|
|
|
.align 4096
|
|
|
|
boot_page_directory:
|
|
|
|
.skip 4096
|
|
|
|
boot_page_table1:
|
|
|
|
.skip 4096
|
|
|
|
# May need additional page for kernel > 3 MiB
|
|
|
|
|
2020-12-02 02:41:09 +00:00
|
|
|
# Kernel entry
|
2022-10-29 15:03:56 +00:00
|
|
|
.section .multiboot.text, "a"
|
2020-12-02 02:41:09 +00:00
|
|
|
.global _start
|
|
|
|
.type _start, @function
|
|
|
|
_start:
|
2022-10-29 15:03:56 +00:00
|
|
|
# Physical address of boot_page_table 1
|
|
|
|
movl $(boot_page_table1 - 0xC0000000), %edi
|
|
|
|
# Map address 0
|
|
|
|
movl $0, %esi
|
|
|
|
# Map first 1023 pages
|
|
|
|
movl $1023, %ecx
|
|
|
|
|
|
|
|
1:
|
|
|
|
# Only map the kernel
|
|
|
|
cmpl $_kernel_start, %esi
|
|
|
|
jl 2f
|
|
|
|
cmpl $(_kernel_end - 0xC0000000), %esi
|
|
|
|
jge 3f
|
|
|
|
|
|
|
|
# Map physical address as "present, writable"
|
|
|
|
# TODO: map .text and .rodata as non-writable
|
|
|
|
movl %esi, %edx
|
|
|
|
orl $0x003, %edx
|
|
|
|
movl %edx, (%edi)
|
|
|
|
|
|
|
|
2:
|
|
|
|
# Size of page is 4KiB
|
|
|
|
addl $4096, %esi
|
|
|
|
# Size of entries in boot_page_table1 is 4 bytes
|
|
|
|
addl $4, %edi
|
|
|
|
# Loop to next if not done
|
|
|
|
loop 1b
|
|
|
|
|
|
|
|
3:
|
|
|
|
# Map VGA memory to 0xC03FF000 as "present, writable"
|
|
|
|
movl $(0x000B8000 | 0x003), boot_page_table1 - 0xC0000000 + 1023 * 4
|
|
|
|
|
|
|
|
# Map page table to 0x0 and 0xC0000000
|
|
|
|
movl $(boot_page_table1 - 0xC0000000 + 0x003), boot_page_directory - 0xC0000000 + 0
|
|
|
|
movl $(boot_page_table1 - 0xC0000000 + 0x003), boot_page_directory - 0xC0000000 + 768 * 4
|
|
|
|
|
|
|
|
# Set cr3 to address of boot page directory
|
|
|
|
movl $(boot_page_directory - 0xC0000000), %ecx
|
|
|
|
movl %ecx, %cr3
|
|
|
|
|
|
|
|
# Enable paging and write-protect
|
|
|
|
movl %cr0, %ecx
|
|
|
|
orl $0x80010000, %ecx
|
|
|
|
movl %ecx, %cr0
|
|
|
|
|
|
|
|
# Jump to higher half
|
|
|
|
lea 4f, %ecx
|
|
|
|
jmp *%ecx
|
|
|
|
|
|
|
|
.section .text
|
|
|
|
|
|
|
|
4:
|
|
|
|
# Unmap identity mapping
|
|
|
|
movl $0, boot_page_directory + 0
|
|
|
|
|
|
|
|
# Reload cr3 to force TLB flush
|
|
|
|
movl %cr3, %ecx
|
|
|
|
movl %ecx, %cr3
|
|
|
|
|
|
|
|
# Set up stack
|
|
|
|
mov $stack_top, %esp
|
2020-12-02 02:41:09 +00:00
|
|
|
|
|
|
|
# Call global constructors
|
|
|
|
call _init
|
|
|
|
|
|
|
|
# Start kernel
|
|
|
|
call kern_main
|
|
|
|
|
|
|
|
# Hang if kernel returns
|
|
|
|
cli
|
|
|
|
1: hlt
|
|
|
|
jmp 1b
|