some of the stuff now works with limine
This commit is contained in:
parent
600ba7163a
commit
8af40d0414
|
@ -37,3 +37,4 @@ Cargo.lock
|
||||||
/boot.o
|
/boot.o
|
||||||
/build/
|
/build/
|
||||||
/OVMF-pure-efi.fd
|
/OVMF-pure-efi.fd
|
||||||
|
/isodir
|
|
@ -3,15 +3,12 @@ name = "wukkOS"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[lib]
|
|
||||||
crate-type = ["staticlib"]
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
spin = "0.9.1"
|
spin = "0.9.1"
|
||||||
x86_64 = "0.14.10"
|
x86_64 = "0.14.10"
|
||||||
x86 = "0.52.0"
|
x86 = "0.52.0"
|
||||||
rlibc = "1.0"
|
rlibc = "1.0"
|
||||||
multiboot2 = { version = "0.14.0", optional = true }
|
limine = { version = "0.1.9", optional = true }
|
||||||
acpi = { version = "4.1.1", optional = true }
|
acpi = { version = "4.1.1", optional = true }
|
||||||
linked_list_allocator = { version = "0.9.0", optional = true }
|
linked_list_allocator = { version = "0.9.0", optional = true }
|
||||||
[dependencies.lazy_static]
|
[dependencies.lazy_static]
|
||||||
|
@ -19,7 +16,7 @@ version = "1.4.0"
|
||||||
features = ["spin_no_std"]
|
features = ["spin_no_std"]
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["f_multiboot2", "f_ll_alloc", "f_debug_verbose"]
|
default = ["f_limine", "f_ll_alloc", "f_debug_verbose"]
|
||||||
f_debug_verbose = []
|
f_debug_verbose = []
|
||||||
f_multiboot2 = ["dep:multiboot2", "dep:acpi"]
|
f_limine = ["dep:limine", "dep:acpi"]
|
||||||
f_ll_alloc = ["dep:linked_list_allocator"]
|
f_ll_alloc = ["dep:linked_list_allocator"]
|
32
Makefile
32
Makefile
|
@ -1,16 +1,14 @@
|
||||||
arch ?= x86_64
|
arch ?= x86_64
|
||||||
kernel := target/$(arch)-custom/debug/libwukkOS.a
|
kernel := target/$(arch)-custom/debug/wukkOS
|
||||||
iso := build/arch/$(arch)/wukkOS.iso
|
iso := build/arch/$(arch)/wukkOS.iso
|
||||||
target ?= $(arch)-custom
|
target ?= $(arch)-custom
|
||||||
final := build/arch/$(arch)/wukkOS.bin
|
final := build/arch/$(arch)/wukkOS.bin
|
||||||
efi_bios := build/arch/$(arch)/OVMF-pure-efi.fd
|
efi_bios := build/arch/$(arch)/OVMF-pure-efi.fd
|
||||||
gcc := x86_64-elf-gcc
|
gcc ?= gcc
|
||||||
ld := x86_64-elf-ld
|
ld ?= ld
|
||||||
# set grub-mkrescue to either $GRUB_MKRESCUE or /usr/bin/grub-mkrescue
|
|
||||||
grub-mkrescue ?= $(shell which grub-mkrescue)
|
|
||||||
|
|
||||||
linker_script := arch/$(arch)/linker.ld
|
linker_script := arch/$(arch)/linker.ld
|
||||||
grub_cfg := arch/$(arch)/grub.cfg
|
bootloader_cfg := arch/$(arch)/limine.cfg
|
||||||
assembly_source_files := $(wildcard arch/$(arch)/*.asm)
|
assembly_source_files := $(wildcard arch/$(arch)/*.asm)
|
||||||
assembly_object_files := $(patsubst arch/$(arch)/%.asm, \
|
assembly_object_files := $(patsubst arch/$(arch)/%.asm, \
|
||||||
build/arch/$(arch)/%.o, $(assembly_source_files))
|
build/arch/$(arch)/%.o, $(assembly_source_files))
|
||||||
|
@ -26,7 +24,7 @@ clean:
|
||||||
@rm -rf build
|
@rm -rf build
|
||||||
|
|
||||||
run: $(final) $(iso)
|
run: $(final) $(iso)
|
||||||
@qemu-system-$(arch) -bios $(efi_bios) -cdrom $(iso) \
|
@qemu-system-$(arch) -bios $(efi_bios) -cdrom $(iso) -d int -D qemulog.log \
|
||||||
-chardev stdio,id=char0,mux=on,logfile=serial.log,signal=off \
|
-chardev stdio,id=char0,mux=on,logfile=serial.log,signal=off \
|
||||||
-serial chardev:char0 -mon chardev=char0 -m 512M
|
-serial chardev:char0 -mon chardev=char0 -m 512M
|
||||||
|
|
||||||
|
@ -39,18 +37,26 @@ iso: $(iso)
|
||||||
|
|
||||||
$(iso): $(final) $(grub_cfg)
|
$(iso): $(final) $(grub_cfg)
|
||||||
@cp OVMF-pure-efi.fd build/arch/$(arch)/OVMF-pure-efi.fd # TODO! remove this, it's only for testing and i don't think we can distribute it
|
@cp OVMF-pure-efi.fd build/arch/$(arch)/OVMF-pure-efi.fd # TODO! remove this, it's only for testing and i don't think we can distribute it
|
||||||
@mkdir -p isodir/boot/grub
|
@mkdir -p isodir/boot
|
||||||
@cp $(final) isodir/boot/wukkOS.bin
|
@cp $(final) isodir/boot/wukkOS.bin
|
||||||
@cp $(grub_cfg) isodir/boot/grub/grub.cfg
|
@cp $(bootloader_cfg) isodir/boot/limine.cfg
|
||||||
@$(grub-mkrescue) -o $(iso) isodir
|
@cp byob/limine.sys byob/limine-cd.bin byob/limine-cd-efi.bin isodir/boot/
|
||||||
|
@xorriso -as mkisofs -b boot/limine-cd.bin \
|
||||||
|
-no-emul-boot -boot-load-size 4 -boot-info-table \
|
||||||
|
--efi-boot boot/limine-cd-efi.bin \
|
||||||
|
-efi-boot-part --efi-boot-image --protective-msdos-label \
|
||||||
|
isodir -o $(iso)
|
||||||
@rm -rf isodir
|
@rm -rf isodir
|
||||||
|
@byob/limine-deploy $(iso)
|
||||||
|
|
||||||
$(final): $(kernel) $(linker_script) $(assembly_object_files)
|
$(final): $(kernel) $(linker_script) $(assembly_object_files)
|
||||||
@$(ld) -n -T $(linker_script) -o $(final) $(assembly_object_files) $(kernel) \
|
@mkdir -p $(shell dirname $@)
|
||||||
--gc-sections -z noexecstack
|
@cp $(kernel) $(final)
|
||||||
|
#@$(ld) -n -T $(linker_script) -o $(final) $(kernel) \
|
||||||
|
# --gc-sections
|
||||||
|
|
||||||
$(kernel):
|
$(kernel):
|
||||||
@RUST_TARGET_PATH=$(shell pwd) xargo build --target $(target) -Zbuild-std=core,alloc --features "f_multiboot2"
|
@RUST_TARGET_PATH=$(shell pwd) xargo build --target $(target) -Zbuild-std=core,alloc --features "f_limine"
|
||||||
|
|
||||||
build/arch/$(arch)/%.o: arch/$(arch)/%.asm
|
build/arch/$(arch)/%.o: arch/$(arch)/%.asm
|
||||||
@mkdir -p $(shell dirname $@)
|
@mkdir -p $(shell dirname $@)
|
||||||
|
|
|
@ -1,161 +0,0 @@
|
||||||
global start
|
|
||||||
extern long_mode_start
|
|
||||||
|
|
||||||
section .text
|
|
||||||
bits 32
|
|
||||||
|
|
||||||
;; basic boilerplate stuff from blog_os, expect to be changed
|
|
||||||
|
|
||||||
start:
|
|
||||||
mov esp, stack_top
|
|
||||||
mov edi, ebx
|
|
||||||
|
|
||||||
call check_multiboot
|
|
||||||
call check_cpuid
|
|
||||||
call check_long_mode
|
|
||||||
|
|
||||||
call setup_page_tables
|
|
||||||
call enable_paging
|
|
||||||
|
|
||||||
lgdt [gdt64.pointer]
|
|
||||||
|
|
||||||
jmp gdt64.code:long_mode_start
|
|
||||||
|
|
||||||
hlt
|
|
||||||
check_multiboot:
|
|
||||||
cmp eax, 0x36d76289
|
|
||||||
jne .no_multiboot
|
|
||||||
ret
|
|
||||||
.no_multiboot:
|
|
||||||
mov al, "0"
|
|
||||||
jmp error
|
|
||||||
check_cpuid:
|
|
||||||
; Check if CPUID is supported by attempting to flip the ID bit (bit 21)
|
|
||||||
; in the FLAGS register. If we can flip it, CPUID is available.
|
|
||||||
|
|
||||||
; Copy FLAGS in to EAX via stack
|
|
||||||
pushfd
|
|
||||||
pop eax
|
|
||||||
|
|
||||||
; Copy to ECX as well for comparing later on
|
|
||||||
mov ecx, eax
|
|
||||||
|
|
||||||
; Flip the ID bit
|
|
||||||
xor eax, 1 << 21
|
|
||||||
|
|
||||||
; Copy EAX to FLAGS via the stack
|
|
||||||
push eax
|
|
||||||
popfd
|
|
||||||
|
|
||||||
; Copy FLAGS back to EAX (with the flipped bit if CPUID is supported)
|
|
||||||
pushfd
|
|
||||||
pop eax
|
|
||||||
|
|
||||||
; Restore FLAGS from the old version stored in ECX (i.e. flipping the
|
|
||||||
; ID bit back if it was ever flipped).
|
|
||||||
push ecx
|
|
||||||
popfd
|
|
||||||
|
|
||||||
; Compare EAX and ECX. If they are equal then that means the bit
|
|
||||||
; wasn't flipped, and CPUID isn't supported.
|
|
||||||
cmp eax, ecx
|
|
||||||
je .no_cpuid
|
|
||||||
ret
|
|
||||||
.no_cpuid:
|
|
||||||
mov al, "1"
|
|
||||||
jmp error
|
|
||||||
check_long_mode:
|
|
||||||
; test if extended processor info in available
|
|
||||||
mov eax, 0x80000000 ; implicit argument for cpuid
|
|
||||||
cpuid ; get highest supported argument
|
|
||||||
cmp eax, 0x80000001 ; it needs to be at least 0x80000001
|
|
||||||
jb .no_long_mode ; if it's less, the CPU is too old for long mode
|
|
||||||
|
|
||||||
; use extended info to test if long mode is available
|
|
||||||
mov eax, 0x80000001 ; argument for extended processor info
|
|
||||||
cpuid ; returns various feature bits in ecx and edx
|
|
||||||
test edx, 1 << 29 ; test if the LM-bit is set in the D-register
|
|
||||||
jz .no_long_mode ; If it's not set, there is no long mode
|
|
||||||
ret
|
|
||||||
.no_long_mode:
|
|
||||||
mov al, "2"
|
|
||||||
jmp error
|
|
||||||
setup_page_tables:
|
|
||||||
; map first P4 entry to P3 table
|
|
||||||
mov eax, p3_table
|
|
||||||
or eax, 0b11 ; present + writable
|
|
||||||
mov [p4_table], eax
|
|
||||||
|
|
||||||
; map first P3 entry to P2 table
|
|
||||||
mov eax, p2_table
|
|
||||||
or eax, 0b11 ; present + writable
|
|
||||||
mov [p3_table], eax
|
|
||||||
|
|
||||||
; map each P2 entry to a huge 2MiB page
|
|
||||||
mov ecx, 0 ; counter variable
|
|
||||||
|
|
||||||
.map_p2_table:
|
|
||||||
; map ecx-th P2 entry to a huge page that starts at address 2MiB*ecx
|
|
||||||
mov eax, 0x200000 ; 2MiB
|
|
||||||
mul ecx ; start address of ecx-th page
|
|
||||||
or eax, 0b10000011 ; present + writable + huge
|
|
||||||
mov [p2_table + ecx * 8], eax ; map ecx-th entry
|
|
||||||
|
|
||||||
inc ecx ; increase counter
|
|
||||||
cmp ecx, 512 ; if counter == 512, the whole P2 table is mapped
|
|
||||||
jne .map_p2_table ; else map the next entry
|
|
||||||
|
|
||||||
ret
|
|
||||||
|
|
||||||
enable_paging:
|
|
||||||
; load P4 to cr3 register (cpu uses this to access the P4 table)
|
|
||||||
mov eax, p4_table
|
|
||||||
mov cr3, eax
|
|
||||||
|
|
||||||
; enable PAE-flag in cr4 (Physical Address Extension)
|
|
||||||
mov eax, cr4
|
|
||||||
or eax, 1 << 5
|
|
||||||
mov cr4, eax
|
|
||||||
|
|
||||||
; set the long mode bit in the EFER MSR (model specific register)
|
|
||||||
mov ecx, 0xC0000080
|
|
||||||
rdmsr
|
|
||||||
or eax, 1 << 8
|
|
||||||
wrmsr
|
|
||||||
|
|
||||||
; enable paging in the cr0 register
|
|
||||||
mov eax, cr0
|
|
||||||
or eax, 1 << 31
|
|
||||||
mov cr0, eax
|
|
||||||
|
|
||||||
ret
|
|
||||||
|
|
||||||
; Prints `ERR: ` and the given error code to screen and hangs.
|
|
||||||
; parameter: error code (in ascii) in al
|
|
||||||
error:
|
|
||||||
mov dword [0xb8000], 0x4f524f45
|
|
||||||
mov dword [0xb8004], 0x4f3a4f52
|
|
||||||
mov dword [0xb8008], 0x4f204f20
|
|
||||||
mov byte [0xb800a], al
|
|
||||||
hlt
|
|
||||||
|
|
||||||
section .bss
|
|
||||||
align 4096
|
|
||||||
p4_table:
|
|
||||||
resb 4096
|
|
||||||
p3_table:
|
|
||||||
resb 4096
|
|
||||||
p2_table:
|
|
||||||
resb 4096
|
|
||||||
stack_bottom:
|
|
||||||
resb 4096 * 4 ;; 16 KiB
|
|
||||||
stack_top:
|
|
||||||
|
|
||||||
section .rodata
|
|
||||||
gdt64:
|
|
||||||
dq 0 ; zero entry
|
|
||||||
.code: equ $ - gdt64 ; new
|
|
||||||
dq (1<<43) | (1<<44) | (1<<47) | (1<<53) ; code segment
|
|
||||||
.pointer:
|
|
||||||
dw $ - gdt64 - 1
|
|
||||||
dq gdt64
|
|
|
@ -1,7 +0,0 @@
|
||||||
set timeout=0
|
|
||||||
set default=0
|
|
||||||
|
|
||||||
menuentry "wukkOS basic kernel" {
|
|
||||||
multiboot2 /boot/wukkOS.bin
|
|
||||||
boot
|
|
||||||
}
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
TIMEOUT=0
|
||||||
|
|
||||||
|
:wukkOS
|
||||||
|
PROTOCOL=limine
|
||||||
|
KERNEL_PATH=boot:///boot/wukkOS.bin
|
|
@ -1,26 +1,48 @@
|
||||||
ENTRY(start)
|
/* Tell the linker that we want an x86_64 ELF64 output file */
|
||||||
|
OUTPUT_FORMAT(elf64-x86-64)
|
||||||
|
OUTPUT_ARCH(i386:x86-64)
|
||||||
|
|
||||||
SECTIONS {
|
/* We want the symbol `x86_64_barebones_main` to be our entry point */
|
||||||
. = 1M;
|
ENTRY(kernel_main)
|
||||||
|
|
||||||
.boot :
|
/* Define the program headers we want so the bootloader gives us the right */
|
||||||
|
/* MMU permissions */
|
||||||
|
PHDRS
|
||||||
{
|
{
|
||||||
/* ensure that the multiboot header is at the beginning */
|
null PT_NULL FLAGS(0) ; /* Null segment */
|
||||||
KEEP(*(.multiboot_header))
|
text PT_LOAD FLAGS((1 << 0) | (1 << 2)) ; /* Execute + Read */
|
||||||
|
rodata PT_LOAD FLAGS((1 << 2)) ; /* Read only */
|
||||||
|
data PT_LOAD FLAGS((1 << 1) | (1 << 2)) ; /* Write + Read */
|
||||||
}
|
}
|
||||||
|
|
||||||
.text :
|
SECTIONS
|
||||||
{
|
{
|
||||||
|
/* We wanna be placed in the topmost 2GiB of the address space, for optimisations */
|
||||||
|
/* and because that is what the Limine spec mandates. */
|
||||||
|
/* Any address in this region will do, but often 0xffffffff80000000 is chosen as */
|
||||||
|
/* that is the beginning of the region. */
|
||||||
|
. = 0xffffffff80000000;
|
||||||
|
|
||||||
|
.text : {
|
||||||
*(.text .text.*)
|
*(.text .text.*)
|
||||||
}
|
} :text
|
||||||
|
|
||||||
.rodata :
|
/* Move to the next memory page for .rodata */
|
||||||
{
|
. += CONSTANT(MAXPAGESIZE);
|
||||||
|
|
||||||
|
.rodata : {
|
||||||
*(.rodata .rodata.*)
|
*(.rodata .rodata.*)
|
||||||
}
|
} :rodata
|
||||||
|
|
||||||
.data.rel.ro :
|
/* Move to the next memory page for .data */
|
||||||
{
|
. += CONSTANT(MAXPAGESIZE);
|
||||||
*(.data.rel.ro.local*) *(.data.rel.ro .data.rel.ro.*)
|
|
||||||
}
|
.data : {
|
||||||
|
*(.data .data.*)
|
||||||
|
} :data
|
||||||
|
|
||||||
|
.bss : {
|
||||||
|
*(COMMON)
|
||||||
|
*(.bss .bss.*)
|
||||||
|
} :data
|
||||||
}
|
}
|
|
@ -1,17 +0,0 @@
|
||||||
global long_mode_start
|
|
||||||
extern kernel_main
|
|
||||||
|
|
||||||
section .text
|
|
||||||
bits 64
|
|
||||||
long_mode_start:
|
|
||||||
mov ax, 0x00
|
|
||||||
mov ss, ax
|
|
||||||
mov ds, ax
|
|
||||||
mov es, ax
|
|
||||||
mov fs, ax
|
|
||||||
mov gs, ax
|
|
||||||
|
|
||||||
extern kernel_main
|
|
||||||
call kernel_main
|
|
||||||
|
|
||||||
hlt
|
|
|
@ -1,16 +0,0 @@
|
||||||
section .multiboot_header
|
|
||||||
header_start:
|
|
||||||
align 4
|
|
||||||
; multiboot 2 magic
|
|
||||||
dd 0xe85250d6
|
|
||||||
dd 0x00000000
|
|
||||||
dd header_end - header_start
|
|
||||||
; checksum
|
|
||||||
dd 0x100000000 - (0xe85250d6 + 0x00000000 + (header_end - header_start))
|
|
||||||
|
|
||||||
; required end tag
|
|
||||||
dw 0 ; type
|
|
||||||
dw 0 ; flags
|
|
||||||
dd 8 ; size
|
|
||||||
|
|
||||||
header_end:
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
# limine binaries
|
||||||
|
limine.sys
|
||||||
|
limine-cd.bin
|
||||||
|
limine-cd-efi.bin
|
||||||
|
limine-deploy
|
|
@ -0,0 +1,9 @@
|
||||||
|
# bring your own bootloader!
|
||||||
|
wukkOS is currently reliant on limine, and it is also currently required for you to
|
||||||
|
provide your own binaries for it. those binaries should be placed in this directory,
|
||||||
|
and the Makefile will copy them into the iso.
|
||||||
|
currently the binaries are:
|
||||||
|
- limine.sys
|
||||||
|
- limine-cd.bin
|
||||||
|
- limine-cd-efi.bin
|
||||||
|
- limine-deploy (should be for your current system)
|
49
serial.log
49
serial.log
|
@ -1,10 +1,6 @@
|
||||||
[2J[01;01H[=3h[2J[01;01HBdsDxe: loading Boot0001 "UEFI QEMU DVD-ROM QM00003 " from PciRoot(0x0)/Pci(0x1,0x1)/Ata(Secondary,Master,0x0)
|
[2J[01;01H[=3h[2J[01;01H[2J[01;01H[=3h[2J[01;01H[2J[01;01H[=3h[2J[01;01H[2J[01;01H[=3h[2J[01;01HBdsDxe: loading Boot0001 "UEFI QEMU DVD-ROM QM00003 " from PciRoot(0x0)/Pci(0x1,0x1)/Ata(Secondary,Master,0x0)
|
||||||
BdsDxe: starting Boot0001 "UEFI QEMU DVD-ROM QM00003 " from PciRoot(0x0)/Pci(0x1,0x1)/Ata(Secondary,Master,0x0)
|
BdsDxe: starting Boot0001 "UEFI QEMU DVD-ROM QM00003 " from PciRoot(0x0)/Pci(0x1,0x1)/Ata(Secondary,Master,0x0)
|
||||||
Booting `wukkOS basic kernel'
|
[2J[01;01H[01;01Husing serial port 0 as console
|
||||||
|
|
||||||
WARNING: no console will be available to OS
|
|
||||||
error: no suitable video mode found.
|
|
||||||
using serial port 0 as console
|
|
||||||
debug: setup GDT
|
debug: setup GDT
|
||||||
debug: GDT loaded
|
debug: GDT loaded
|
||||||
debug: CS set
|
debug: CS set
|
||||||
|
@ -20,44 +16,3 @@ initialising mapper...[OK]
|
||||||
initialising frame allocator...[OK]
|
initialising frame allocator...[OK]
|
||||||
initialising heap...[OK]
|
initialising heap...[OK]
|
||||||
testing heap...[OK]
|
testing heap...[OK]
|
||||||
checking for apic compatibility...[OK]
|
|
||||||
initialising apic...[debug] read_phys_memory32: addr fffe0000 not mapped
|
|
||||||
[debug] allocated frame: PhysFrame[4KiB](0x1c000)
|
|
||||||
[debug] mapped page: Page[4KiB](0xfffe0000)
|
|
||||||
[debug] map_to_result: Ok(MapperFlush(Page[4KiB](0xfffe0000)))
|
|
||||||
[debug] xapic id: 0
|
|
||||||
[debug] xapic version: 0
|
|
||||||
[OK]
|
|
||||||
setting up apic interrupts...[debug] acpi tag: RsdpV1Tag { typ: AcpiV1, size: 28, signature: [82, 83, 68, 32, 80, 84, 82, 32], checksum: 172, oem_id: [66, 79, 67, 72, 83, 32], revision: 0, rsdt_address: 532140032 }
|
|
||||||
[debug] rsdt: 532140032
|
|
||||||
[debug] read_phys_memory32: addr 1fb7d000 not mapped
|
|
||||||
[WARN] failed to unmap page
|
|
||||||
[debug] read_phys_memory32: addr 1fb7d000 not mapped
|
|
||||||
[debug] read_phys_memory32: addr 1fb7a000 not mapped
|
|
||||||
[WARN] failed to unmap page
|
|
||||||
[debug] read_phys_memory32: addr 1fb7a000 not mapped
|
|
||||||
[debug] read_phys_memory32: addr 1fb7b000 not mapped
|
|
||||||
[WARN] failed to unmap page
|
|
||||||
[WARN] failed to unmap page
|
|
||||||
[debug] read_phys_memory32: addr 1fb79000 not mapped
|
|
||||||
[WARN] failed to unmap page
|
|
||||||
[debug] read_phys_memory32: addr 1fb78000 not mapped
|
|
||||||
[WARN] failed to unmap page
|
|
||||||
[debug] read_phys_memory32: addr 1fb77000 not mapped
|
|
||||||
[WARN] failed to unmap page
|
|
||||||
[debug] read_phys_memory32: addr 1fb76000 not mapped
|
|
||||||
[WARN] failed to unmap page
|
|
||||||
[WARN] failed to unmap page
|
|
||||||
[debug] loaded rsdt
|
|
||||||
[debug] read_phys_memory32: addr 1fb7a000 not mapped
|
|
||||||
[debug] read_phys_memory32: addr 1fb79000 not mapped
|
|
||||||
[WARN] failed to unmap page
|
|
||||||
[WARN] failed to unmap page
|
|
||||||
[debug] ioapic addr: fec00000
|
|
||||||
[debug] ioapicaddr: 0xfec00000
|
|
||||||
[debug] read_phys_memory32: addr fec00000 not mapped
|
|
||||||
[debug] allocated frame: PhysFrame[4KiB](0x1f000)
|
|
||||||
[debug] mapped page: Page[4KiB](0xfec00000)
|
|
||||||
[debug] map_to_result: Ok(MapperFlush(Page[4KiB](0xfec00000)))
|
|
||||||
[debug] ioapic supported interrupts: 1
|
|
||||||
[OK]
|
|
||||||
|
|
|
@ -2,21 +2,15 @@ use alloc::sync::Arc;
|
||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
use core::ptr::NonNull;
|
use core::ptr::NonNull;
|
||||||
use acpi::{AcpiHandler, InterruptModel, PhysicalMapping};
|
use acpi::{AcpiHandler, InterruptModel, PhysicalMapping};
|
||||||
use crate::{debug, KernelArgs, println};
|
use limine::LimineTerminalResponse;
|
||||||
|
use crate::{debug, println, TERMINAL_REQUEST};
|
||||||
|
|
||||||
#[cfg(feature = "f_multiboot2")]
|
#[cfg(feature = "f_multiboot2")]
|
||||||
use multiboot2::{load, MemoryMapTag, BootInformation};
|
use multiboot2::{load, MemoryMapTag, BootInformation};
|
||||||
use x86_64::structures::paging::{FrameAllocator, Mapper, OffsetPageTable, Page, Translate};
|
use x86_64::structures::paging::{FrameAllocator, Mapper, OffsetPageTable, Page, Translate};
|
||||||
use x86_64::VirtAddr;
|
use x86_64::VirtAddr;
|
||||||
use crate::memory::{BootInfoFrameAllocator, FRAME_ALLOC, MEM_MAPPER, PageSize, read_phys_memory32};
|
use crate::memory::{BootInfoFrameAllocator, FRAME_ALLOC, MEM_MAPPER, PageSize, read_phys_memory32};
|
||||||
|
use crate::serial::terminal::ST;
|
||||||
pub struct KernelInfo {
|
|
||||||
kernel_start: u64,
|
|
||||||
kernel_end: u64,
|
|
||||||
safe_mem_start: u64,
|
|
||||||
#[cfg(feature = "f_multiboot2")]
|
|
||||||
boot_info: BootInformation,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
struct Handler;
|
struct Handler;
|
||||||
|
@ -54,73 +48,24 @@ impl AcpiHandler for Handler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl KernelInfo {
|
pub struct LimineWriter;
|
||||||
pub fn init_from_kernel_args(args: KernelArgs) -> Self {
|
|
||||||
#[cfg(feature = "f_multiboot2")]
|
|
||||||
{
|
|
||||||
let boot_info = unsafe { load(args.multiboot_information_address) }.expect("failed to load multiboot2 information");
|
|
||||||
let elf_sections = boot_info.elf_sections_tag().expect("no elf sections tag");
|
|
||||||
let kernel_start = elf_sections.sections().map(|s| s.start_address()).min().unwrap();
|
|
||||||
let kernel_end = elf_sections.sections().map(|s| s.end_address()).max().unwrap();
|
|
||||||
// get end of multiboot for safe memory
|
|
||||||
let safe_mem_start = boot_info.start_address() + boot_info.total_size();
|
|
||||||
let kernel_info = KernelInfo {
|
|
||||||
kernel_start,
|
|
||||||
kernel_end,
|
|
||||||
safe_mem_start: safe_mem_start as u64,
|
|
||||||
boot_info,
|
|
||||||
};
|
|
||||||
kernel_info
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "f_multiboot2")]
|
impl core::fmt::Write for LimineWriter {
|
||||||
pub fn get_memory_tag(&self) -> &MemoryMapTag {
|
fn write_str(&mut self, s: &str) -> core::fmt::Result {
|
||||||
let mm_tag = self.boot_info.memory_map_tag().expect("no memory map tag").clone();
|
static mut CACHED: Option<&'static LimineTerminalResponse> = None;
|
||||||
mm_tag
|
unsafe {
|
||||||
}
|
if let Some(writer) = CACHED {
|
||||||
|
let terminal = &writer.terminals()[0];
|
||||||
#[cfg(feature = "f_multiboot2")]
|
writer.write().unwrap()(terminal, s);
|
||||||
pub fn memory_areas(&self) -> impl Iterator<Item = &multiboot2::MemoryArea> {
|
|
||||||
let mm_tag = self.boot_info.memory_map_tag().expect("ERR NO MEM MAP TAG!");
|
|
||||||
mm_tag.all_memory_areas()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_safe_memory(&self, addr: u64) -> bool {
|
|
||||||
addr >= self.safe_mem_start && addr >= self.kernel_end
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn safe_memory_start(&self) -> u64 {
|
|
||||||
self.safe_mem_start
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn acpi_get_ioapic_addr(&self) -> u32 {
|
|
||||||
#[cfg(feature = "f_multiboot2")]
|
|
||||||
{
|
|
||||||
let acpi_tag = self.boot_info.rsdp_v1_tag().expect("no acpi tag");
|
|
||||||
debug!("acpi tag: {:?}", acpi_tag);
|
|
||||||
let rsdp = acpi_tag;
|
|
||||||
let rsdp = unsafe { &*rsdp };
|
|
||||||
let rsdt = rsdp.rsdt_address();
|
|
||||||
debug!("rsdt: {:?}", rsdt);
|
|
||||||
let rsdt = unsafe {
|
|
||||||
acpi::AcpiTables::from_rsdt(
|
|
||||||
Handler, 0,
|
|
||||||
rsdt)
|
|
||||||
.expect("failed to get acpi tables")
|
|
||||||
};
|
|
||||||
debug!("loaded rsdt");
|
|
||||||
let platform_info = rsdt.platform_info().expect("failed to get platform info");
|
|
||||||
let interrupt_model = platform_info.interrupt_model;
|
|
||||||
if let InterruptModel::Apic(apic) = interrupt_model {
|
|
||||||
let ioapics = apic.io_apics;
|
|
||||||
let ioapic = ioapics.first().expect("no ioapics");
|
|
||||||
let ioapic_addr = ioapic.address;
|
|
||||||
debug!("ioapic addr: {:x}", ioapic_addr);
|
|
||||||
ioapic_addr
|
|
||||||
} else {
|
} else {
|
||||||
panic!("no ioapic");
|
let response = TERMINAL_REQUEST.get_response().get().unwrap();
|
||||||
|
let terminal = &response.terminals()[0];
|
||||||
|
let writer = response.write().unwrap();
|
||||||
|
writer(terminal, s);
|
||||||
|
|
||||||
|
CACHED = Some(response);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -3,7 +3,7 @@ use x86::apic::{xapic::XAPIC, ioapic::IoApic, ApicControl};
|
||||||
use x86_64::PhysAddr;
|
use x86_64::PhysAddr;
|
||||||
use x86_64::structures::idt::InterruptStackFrame;
|
use x86_64::structures::idt::InterruptStackFrame;
|
||||||
use x86_64::structures::paging::PhysFrame;
|
use x86_64::structures::paging::PhysFrame;
|
||||||
use crate::{debug, KERN_INFO, print, println};
|
use crate::{debug, print, println};
|
||||||
use crate::memory::{BootInfoFrameAllocator, read_phys_memory32, write_phys_memory32};
|
use crate::memory::{BootInfoFrameAllocator, read_phys_memory32, write_phys_memory32};
|
||||||
use crate::serial::{command, read};
|
use crate::serial::{command, read};
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
use core::fmt;
|
use core::fmt;
|
||||||
|
use limine::LimineTerminalResponse;
|
||||||
|
use crate::boot::LimineWriter;
|
||||||
use crate::serial::terminal::ST;
|
use crate::serial::terminal::ST;
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
|
@ -21,6 +23,9 @@ macro_rules! debug {
|
||||||
pub fn _print(args: fmt::Arguments) {
|
pub fn _print(args: fmt::Arguments) {
|
||||||
use core::fmt::Write;
|
use core::fmt::Write;
|
||||||
ST.writer.lock().write_fmt(args).unwrap();
|
ST.writer.lock().write_fmt(args).unwrap();
|
||||||
|
|
||||||
|
let mut limine_writer = LimineWriter;
|
||||||
|
limine_writer.write_fmt(args).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
|
@ -31,5 +36,10 @@ pub fn _debug(args: fmt::Arguments) {
|
||||||
ST.log("[debug] ");
|
ST.log("[debug] ");
|
||||||
ST.writer.lock().write_fmt(args).unwrap();
|
ST.writer.lock().write_fmt(args).unwrap();
|
||||||
ST.logln("");
|
ST.logln("");
|
||||||
|
|
||||||
|
let mut limine_writer = LimineWriter;
|
||||||
|
limine_writer.write_str("[debug] ").unwrap();
|
||||||
|
limine_writer.write_fmt(args).unwrap();
|
||||||
|
limine_writer.write_str("\n").unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -16,7 +16,7 @@ use alloc::vec;
|
||||||
use core::arch::asm;
|
use core::arch::asm;
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use core::panic::PanicInfo;
|
use core::panic::PanicInfo;
|
||||||
use multiboot2::MemoryAreaType;
|
use limine::{LimineBootInfoRequest, LimineMemmapRequest, LimineTerminalRequest};
|
||||||
use spin::Mutex;
|
use spin::Mutex;
|
||||||
use x86_64::structures::idt::{InterruptDescriptorTable, InterruptStackFrame};
|
use x86_64::structures::idt::{InterruptDescriptorTable, InterruptStackFrame};
|
||||||
use x86_64::structures::gdt::{GlobalDescriptorTable, Descriptor};
|
use x86_64::structures::gdt::{GlobalDescriptorTable, Descriptor};
|
||||||
|
@ -24,7 +24,6 @@ use x86_64::structures::tss::TaskStateSegment;
|
||||||
use x86_64::{PhysAddr, VirtAddr};
|
use x86_64::{PhysAddr, VirtAddr};
|
||||||
use x86_64::registers::segmentation::{CS, Segment, SS};
|
use x86_64::registers::segmentation::{CS, Segment, SS};
|
||||||
use x86_64::structures::paging::Translate;
|
use x86_64::structures::paging::Translate;
|
||||||
use crate::boot::KernelInfo;
|
|
||||||
use crate::internals::WhyDoTheyCallItOvenWhenYouOfInTheColdFoodOfOutHotEatTheFood::*;
|
use crate::internals::WhyDoTheyCallItOvenWhenYouOfInTheColdFoodOfOutHotEatTheFood::*;
|
||||||
use crate::memory::{FRAME_ALLOC, MEM_MAPPER};
|
use crate::memory::{FRAME_ALLOC, MEM_MAPPER};
|
||||||
use crate::serial::terminal::ST;
|
use crate::serial::terminal::ST;
|
||||||
|
@ -37,8 +36,12 @@ mod boot;
|
||||||
mod memory;
|
mod memory;
|
||||||
mod macros;
|
mod macros;
|
||||||
|
|
||||||
|
static BOOTLOADER_INFO: LimineBootInfoRequest = LimineBootInfoRequest::new(0);
|
||||||
|
static TERMINAL_REQUEST: LimineTerminalRequest = LimineTerminalRequest::new(0);
|
||||||
|
static MEM_MAP: LimineMemmapRequest = LimineMemmapRequest::new(0);
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
pub static ref KERN_INFO: Mutex<Option<KernelInfo>> = Mutex::new(None);
|
//pub static ref KERN_INFO: Mutex<Option<KernelInfo>> = Mutex::new(None);
|
||||||
static ref GDT: Mutex<GlobalDescriptorTable> = {
|
static ref GDT: Mutex<GlobalDescriptorTable> = {
|
||||||
let mut gdt = GlobalDescriptorTable::new();
|
let mut gdt = GlobalDescriptorTable::new();
|
||||||
Mutex::new(gdt)
|
Mutex::new(gdt)
|
||||||
|
@ -82,14 +85,10 @@ fn panic(info: &PanicInfo) -> ! {
|
||||||
loop {}
|
loop {}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(C)]
|
|
||||||
pub struct KernelArgs {
|
|
||||||
#[cfg(feature = "f_multiboot2")]
|
|
||||||
multiboot_information_address: usize
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern fn kernel_main(args: KernelArgs) -> ! {
|
pub extern "C" fn kernel_main() -> ! {
|
||||||
|
debug!("entry point");
|
||||||
|
|
||||||
// initialise serial
|
// initialise serial
|
||||||
let mut serial_ports = serial::init_serial();
|
let mut serial_ports = serial::init_serial();
|
||||||
let mut console_port = None;
|
let mut console_port = None;
|
||||||
|
@ -165,7 +164,6 @@ pub extern fn kernel_main(args: KernelArgs) -> ! {
|
||||||
println!();
|
println!();
|
||||||
println!("welcome to wukkOS!");
|
println!("welcome to wukkOS!");
|
||||||
println!("(c) 2022 Real Microsoft, LLC");
|
println!("(c) 2022 Real Microsoft, LLC");
|
||||||
KERN_INFO.lock().replace(KernelInfo::init_from_kernel_args(args));
|
|
||||||
|
|
||||||
// memory stuff
|
// memory stuff
|
||||||
{
|
{
|
||||||
|
@ -194,7 +192,7 @@ pub extern fn kernel_main(args: KernelArgs) -> ! {
|
||||||
}
|
}
|
||||||
|
|
||||||
// apic stuff
|
// apic stuff
|
||||||
{
|
/*{
|
||||||
print!("checking for apic compatibility...");
|
print!("checking for apic compatibility...");
|
||||||
let apic_compatible = unsafe { internals::cpu::check_apic_compat() };
|
let apic_compatible = unsafe { internals::cpu::check_apic_compat() };
|
||||||
if apic_compatible {
|
if apic_compatible {
|
||||||
|
@ -213,7 +211,7 @@ pub extern fn kernel_main(args: KernelArgs) -> ! {
|
||||||
println!("[OK]");
|
println!("[OK]");
|
||||||
// enable interrupts
|
// enable interrupts
|
||||||
x86_64::instructions::interrupts::enable();
|
x86_64::instructions::interrupts::enable();
|
||||||
}
|
}*/
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
}
|
}
|
|
@ -46,18 +46,14 @@ unsafe fn active_level_4_table(phys_mem_offset: VirtAddr) -> &'static mut PageTa
|
||||||
unsafe { &mut *page_table_ptr } // unsafe
|
unsafe { &mut *page_table_ptr } // unsafe
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "f_multiboot2")]
|
|
||||||
use multiboot2::{MemoryMapTag, BootInformation};
|
|
||||||
use spin::Mutex;
|
use spin::Mutex;
|
||||||
use crate::boot::KernelInfo;
|
use crate::{debug, MEM_MAP, print, println};
|
||||||
use crate::{debug, KERN_INFO, print, println};
|
|
||||||
|
|
||||||
pub struct BootInfoFrameAllocator {
|
pub struct BootInfoFrameAllocator {
|
||||||
next: usize,
|
next: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BootInfoFrameAllocator {
|
impl BootInfoFrameAllocator {
|
||||||
#[cfg(feature = "f_multiboot2")]
|
|
||||||
pub unsafe fn init() -> Self {
|
pub unsafe fn init() -> Self {
|
||||||
Self {
|
Self {
|
||||||
next: 0,
|
next: 0,
|
||||||
|
@ -67,15 +63,13 @@ impl BootInfoFrameAllocator {
|
||||||
|
|
||||||
unsafe impl FrameAllocator<Size4KiB> for BootInfoFrameAllocator {
|
unsafe impl FrameAllocator<Size4KiB> for BootInfoFrameAllocator {
|
||||||
fn allocate_frame(&mut self) -> Option<PhysFrame> {
|
fn allocate_frame(&mut self) -> Option<PhysFrame> {
|
||||||
#[cfg(feature = "f_multiboot2")] {
|
#[cfg(feature = "f_limine")] {
|
||||||
let mut kern_lock = KERN_INFO.lock();
|
let mmap = MEM_MAP.get_response().get().expect("failed to get memory map")
|
||||||
let mut kern_info = kern_lock.as_mut().unwrap();
|
.memmap();
|
||||||
let mut usable_frames = kern_info
|
let mut usable_frames = mmap.iter()
|
||||||
.memory_areas();
|
|
||||||
let mut usable_frames = usable_frames
|
|
||||||
.map(|area| {
|
.map(|area| {
|
||||||
let frame_addr = area.start_address();
|
let frame_addr = area.base;
|
||||||
let frame_end = area.end_address();
|
let frame_end = area.base + area.len;
|
||||||
let frame_size = frame_end - frame_addr;
|
let frame_size = frame_end - frame_addr;
|
||||||
let num_frames = frame_size / 4096;
|
let num_frames = frame_size / 4096;
|
||||||
let start_frame = PhysFrame::containing_address(PhysAddr::new(frame_addr));
|
let start_frame = PhysFrame::containing_address(PhysAddr::new(frame_addr));
|
||||||
|
@ -85,9 +79,6 @@ unsafe impl FrameAllocator<Size4KiB> for BootInfoFrameAllocator {
|
||||||
let frame = usable_frames.nth(self.next).clone();
|
let frame = usable_frames.nth(self.next).clone();
|
||||||
self.next += 1;
|
self.next += 1;
|
||||||
|
|
||||||
// ensure unlock
|
|
||||||
unsafe { KERN_INFO.force_unlock() };
|
|
||||||
|
|
||||||
frame
|
frame
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,14 @@
|
||||||
"executables": true,
|
"executables": true,
|
||||||
"linker-flavor": "ld.lld",
|
"linker-flavor": "ld.lld",
|
||||||
"linker": "rust-lld",
|
"linker": "rust-lld",
|
||||||
"panic-strategy": "abort",
|
|
||||||
"disable-redzone": true,
|
"disable-redzone": true,
|
||||||
"features": "-mmx,-sse,+soft-float"
|
"panic-strategy": "abort",
|
||||||
|
"features": "-mmx,-sse,+soft-float",
|
||||||
|
"code-model": "kernel",
|
||||||
|
"pre-link-args": {
|
||||||
|
"ld.lld": [
|
||||||
|
"--gc-sections",
|
||||||
|
"--script=arch/x86_64/linker.ld"
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue