Kernel: Rewrite i386 boot code + linker script

This commit is contained in:
Bananymous 2024-03-26 00:09:05 +02:00
parent 097d9a6479
commit fc7e96fa66
2 changed files with 211 additions and 108 deletions

View File

@ -1,61 +1,98 @@
# Declare constants for the multiboot header .set PG_PRESENT, 1<<0
.set ALIGN, 1<<0 # align loaded modules on page boundaries .set PG_READ_WRITE, 1<<1
.set MEMINFO, 1<<1 # provide memory map .set PG_PAGE_SIZE, 1<<7
.set VIDEOINFO, 1<<2 # provide video info
.set MB_FLAGS, ALIGN | MEMINFO | VIDEOINFO # this is the Multiboot 'flag' field
.set MB_MAGIC, 0x1BADB002 # 'magic number' lets bootloader find the header
.set MB_CHECKSUM, -(MB_MAGIC + MB_FLAGS) #checksum of above, to prove we are multiboot
# Multiboot header .set FB_WIDTH, 800
.set FB_HEIGHT, 600
.set FB_BPP, 32
#define KERNEL_OFFSET 0xC0000000
#define V2P(vaddr) ((vaddr) - KERNEL_OFFSET)
.code32
# multiboot2 header
.section .multiboot, "aw" .section .multiboot, "aw"
.align 4 .align 8
.long MB_MAGIC multiboot2_start:
.long MB_FLAGS .long 0xE85250D6
.long MB_CHECKSUM
.skip 20
.long 0 .long 0
.long 800 .long multiboot2_end - multiboot2_start
.long 600 .long -(0xE85250D6 + (multiboot2_end - multiboot2_start))
.long 32
# framebuffer tag
.align 8
.short 5
.short 0
.long 20
.long FB_WIDTH
.long FB_HEIGHT
.long FB_BPP
# legacy start
.align 8
.short 3
.short 0
.long 12
.long V2P(_start)
.align 8
.short 0
.short 0
.long 8
multiboot2_end:
.section .bananboot, "aw"
.align 8
bananboot_start:
.long 0xBABAB007
.long -(0xBABAB007 + FB_WIDTH + FB_HEIGHT + FB_BPP)
.long FB_WIDTH
.long FB_HEIGHT
.long FB_BPP
bananboot_end:
.section .bss, "aw", @nobits .section .bss, "aw", @nobits
# Create stack boot_stack_bottom:
.global g_boot_stack_bottom .skip 4096 * 4
g_boot_stack_bottom: boot_stack_top:
.skip 16384
.global g_boot_stack_top
g_boot_stack_top:
# 0 MiB -> 1 MiB: bootloader stuff
# 1 MiB -> : kernel
.align 32
boot_page_directory_pointer_table:
.skip 4 * 8
.align 4096
boot_page_directory1:
.skip 512 * 8
.global g_kernel_cmdline .global g_kernel_cmdline
g_kernel_cmdline: g_kernel_cmdline:
.skip 4096 .skip 4096
.global g_multiboot_info bootloader_magic:
g_multiboot_info: .skip 8
.skip 4 bootloader_info:
.global g_multiboot_magic .skip 8
g_multiboot_magic:
.skip 4
.section .text .section .data
.align 4096
boot_pml4:
boot_pdpt_lo:
boot_pdpt_hi:
boot_pd:
boot_gdt: boot_gdt:
.quad 0x0000000000000000 # null .quad 0x0000000000000000 # null descriptor
.quad 0x00CF9A000000FFFF # kernel code .quad 0x00CF9A000000FFFF # kernel code
.quad 0x00CF92000000FFFF # kernel data .quad 0x00CF92000000FFFF # kernel data
boot_gdtr: boot_gdtr:
.short . - boot_gdt - 1 .short . - boot_gdt - 1
.long boot_gdt .long V2P(boot_gdt)
.global g_ap_startup_done
g_ap_startup_done:
.byte 0
.global g_ap_running_count
g_ap_running_count:
.byte 0
.global g_ap_stack_loaded
g_ap_stack_loaded:
.byte 0
.section .text
has_cpuid: has_cpuid:
pushfl pushfl
@ -69,42 +106,13 @@ has_cpuid:
testl $0x00200000, %eax testl $0x00200000, %eax
ret ret
has_pae:
movl $0, %eax
cpuid
testl $(1 << 6), %edx
ret
has_sse:
movl $1, %eax
cpuid
testl $(1 << 25), %edx
ret
check_requirements: check_requirements:
call has_cpuid call has_cpuid
jz .exit jz .exit
call has_pae
jz .exit
call has_sse
jz .exit
ret ret
.exit: .exit:
jmp system_halt jmp system_halt
copy_kernel_commandline:
pushl %esi
pushl %edi
movl g_multiboot_info, %esi
addl $16, %esi
movl (%esi), %esi
movl $1024, %ecx
movl $g_kernel_cmdline, %edi
rep movsl
popl %edi
popl %esi
ret
enable_sse: enable_sse:
movl %cr0, %eax movl %cr0, %eax
andw $0xFFFB, %ax andw $0xFFFB, %ax
@ -116,19 +124,13 @@ enable_sse:
ret ret
initialize_paging: initialize_paging:
# identity map first 6 MiB
movl $(0x00000000 + 0x83), boot_page_directory1 + 0
movl $(0x00200000 + 0x83), boot_page_directory1 + 8
movl $(0x00400000 + 0x83), boot_page_directory1 + 16
movl $(boot_page_directory1 + 0x01), boot_page_directory_pointer_table
# enable PAE # enable PAE
movl %cr4, %ecx movl %cr4, %ecx
orl $0x20, %ecx orl $0x20, %ecx
movl %ecx, %cr4 movl %ecx, %cr4
# set address of paging structures # set address of paging structures
movl $boot_page_directory_pointer_table, %ecx movl $V2P(boot_pml4), %ecx
movl %ecx, %cr3 movl %ecx, %cr3
# enable paging # enable paging
@ -138,41 +140,52 @@ initialize_paging:
ret ret
initialize_gdt:
lgdt boot_gdtr
# flush gdt
movw $0x10, %ax
movw %ax, %ds
movw %ax, %es
movw %ax, %fs
movw %ax, %gs
movw %ax, %ss
jmp $0x08, $flush
flush:
ret
.global _start .global _start
.type _start, @function .type _start, @function
_start: _start:
# Initialize stack and multiboot info cli; cld
movl $g_boot_stack_top, %esp
movl %eax, g_multiboot_magic # Initialize stack and multiboot info
movl %ebx, g_multiboot_info movl %eax, V2P(bootloader_magic)
movl %ebx, V2P(bootloader_info)
movl $V2P(boot_stack_top), %esp
call copy_kernel_commandline
call check_requirements call check_requirements
call enable_sse call enable_sse
call initialize_paging call initialize_paging
call initialize_gdt
# flush gdt
lgdt V2P(boot_gdtr)
ljmpl $0x08, $V2P(gdt_flush)
gdt_flush:
movw $0x10, %ax
movw %ax, %ds
movw %ax, %ss
movw %ax, %es
# move stack pointer to higher half
movl %esp, %esp
addl $KERNEL_OFFSET, %esp
# jump to higher half
leal higher_half, %ecx
jmp *%ecx
higher_half:
# call global constuctors
call _init call _init
# call to the kernel itself (clear ebp for stacktrace) # call to the kernel itself (clear ebp for stacktrace)
xorl %ebp, %ebp xorl %ebp, %ebp
movl V2P(bootloader_magic), %edi
movl V2P(bootloader_info), %esi
call kernel_main call kernel_main
# call global destructors
call _fini call _fini
system_halt: system_halt:
@ -180,3 +193,76 @@ system_halt:
cli cli
1: hlt 1: hlt
jmp 1b jmp 1b
.section .ap_init, "ax"
.code16
.global ap_trampoline
ap_trampoline:
jmp 1f
.align 8
ap_stack_ptr:
.skip 4
1:
cli; cld
ljmpl $0x00, $ap_cs_clear
ap_cs_clear:
xorw %ax, %ax
movw %ax, %ds
# load ap gdt and enter protected mode
lgdt ap_gdtr
movl %cr0, %eax
orb $1, %al
movl %eax, %cr0
ljmpl $0x08, $ap_protected_mode
.code32
ap_protected_mode:
movw $0x10, %ax
movw %ax, %ds
movw %ax, %ss
movw %ax, %es
movl ap_stack_ptr, %esp
movb $1, V2P(g_ap_stack_loaded)
call V2P(enable_sse)
call V2P(initialize_paging)
# load boot gdt and enter long mode
lgdt V2P(boot_gdtr)
ljmpl $0x08, $ap_flush_gdt
ap_flush_gdt:
# move stack pointer to higher half
movl %esp, %esp
addl $KERNEL_OFFSET, %esp
# jump to higher half
leal ap_higher_half, %ecx
jmp *%ecx
ap_higher_half:
# clear rbp for stacktrace
xorl %ebp, %ebp
1: pause
cmpb $0, g_ap_startup_done
jz 1b
lock incb g_ap_running_count
call ap_main
jmp system_halt
ap_gdt:
.quad 0x0000000000000000 # null descriptor
.quad 0x00CF9A000000FFFF # 32 bit code
.quad 0x00CF92000000FFFF # 32 bit data
ap_gdtr:
.short . - ap_gdt - 1
.long ap_gdt

View File

@ -1,28 +1,45 @@
ENTRY (_start) ENTRY (_start)
KERNEL_OFFSET = 0xC0000000;
SECTIONS SECTIONS
{ {
. = 0x00100000; . = 0xF000;
.ap_init ALIGN(4K) : AT(ADDR(.ap_init))
{
g_ap_init_addr = .;
*(.ap_init)
}
. = 0x00100000 + KERNEL_OFFSET;
g_kernel_start = .; g_kernel_start = .;
.text BLOCK(4K) : ALIGN(4K) .text ALIGN(4K) : AT(ADDR(.text) - KERNEL_OFFSET)
{ {
g_kernel_execute_start = .;
*(.multiboot) *(.multiboot)
*(.text) *(.bananboot)
*(.text.*)
} }
.rodata BLOCK(4K) : ALIGN(4K) .userspace ALIGN(4K) : AT(ADDR(.userspace) - KERNEL_OFFSET)
{
g_userspace_start = .;
*(.userspace)
g_userspace_end = .;
g_kernel_execute_end = .;
}
.rodata ALIGN(4K) : AT(ADDR(.rodata) - KERNEL_OFFSET)
{ {
*(.rodata.*) *(.rodata.*)
} }
.data BLOCK(4K) : ALIGN(4K) .data ALIGN(4K) : AT(ADDR(.data) - KERNEL_OFFSET)
{ {
*(.data) *(.data)
} }
.bss BLOCK(4K) : ALIGN(4K) .bss ALIGN(4K) : AT(ADDR(.bss) - KERNEL_OFFSET)
{ {
*(COMMON) *(COMMON)
*(.bss) *(.bss)
} }
g_kernel_end = .; g_kernel_end = .;
} }