diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 0000000000000000000000000000000000000000..7fa2c556c0349c0b06f51507fd62312b96326c0c --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,2 @@ +[target.x86_64-unknown-none] +runner = "echo" diff --git a/Cargo.toml b/Cargo.toml index 3ac3cd0be4bdb24ce430300ac99fd1b92b2ab8d2..f9b0039335e6475860fffe73148c6ae8f20cc2cc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,4 +6,7 @@ build = "build.rs" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +#[lib] +#crate-type = ["staticlib"] + [dependencies] diff --git a/Makefile b/Makefile index 25638cfdbed6d0b6424bbc51afc2f43421d42eb6..a589445d9908c15377c4e9d9e3f541fa547b4ffe 100644 --- a/Makefile +++ b/Makefile @@ -1,48 +1,78 @@ # target specific -TARGET = x86_64-unknown-none -QEMU = qemu-system-x86_64 -CONFIG = x86_64 -EXTRA_RUSTFLAGS = +TARGET = x86_64-unknown-none +QEMU = qemu-system-x86_64 +CONFIG = x86_64 +EXTRA_RUSTFLAGS = -KERNEL = kernel -KERNEL_ELF = target/$(TARGET)/release/$(KERNEL) -KERNEL_ELF_DEPS = $(filter-out %: ,$(file < $(KERNEL_ELF).d)) $(LD_SCRIPT_PATH)/$(LD_SCRIPT) Cargo.toml -OS_ISO = target/$(TARGET)/release/$(KERNEL).iso -LD_SCRIPT_PATH = $(shell pwd)/src/arch/x86_64 -LD_SCRIPT = kernel.ld +KERNEL = kernel +KERNEL_ELF = target/$(TARGET)/release/$(KERNEL) +DEBUG_KERNEL_ELF = target/$(TARGET)/debug/$(KERNEL) +KERNEL_LIB = target/$(TARGET)/release/lib$(KERNEL).a +DEBUG_KERNEL_LIB = target/$(TARGET)/debug/lib$(KERNEL).a +OS_ISO = target/$(TARGET)/release/$(KERNEL).iso +DEBUG_OS_ISO = target/$(TARGET)/debug/$(KERNEL).iso +LD_SCRIPT_PATH = $(shell pwd)/src/arch/x86_64 +LD_SCRIPT = kernel.ld +KERNEL_DEPS = $(filter-out %: ,$(file < $(KERNEL_ELF).d)) +DEBUG_KERNEL_DEPS= $(filter-out %: ,$(file < $(DEBUG_KERNEL_ELF).d)) +BOOT_SRC = $(shell find $(LD_SCRIPT_PATH)/boot -name *.asm) +BOOT_OBJ = $(patsubst $(LD_SCRIPT_PATH)/boot/%.asm, $(LD_SCRIPT_PATH)/boot/%.o, $(BOOT_SRC)) +CARGO_DEPS = $(LD_SCRIPT_PATH)/$(LD_SCRIPT) Cargo.toml -RUSTFLAGS = $(EXTRA_RUSTFLAGS) \ - -C link-arg=--library-path=$(LD_SCRIPT_PATH) \ - -C link-arg=--script=$(LD_SCRIPT) +RUSTFLAGS = $(EXTRA_RUSTFLAGS) \ + -C link-arg=--library-path=$(LD_SCRIPT_PATH) \ + -C link-arg=--script=$(LD_SCRIPT) +# -C relocation-model=static -CARGO_RUSTC = cargo rustc --release --target=$(TARGET) +CARGO_BUILD_DEBUG= cargo rustc --target=$(TARGET) +CARGO_BUILD = $(CARGO_BUILD_DEBUG) --release --verbose -.PHONY: run +#DEBUGGER = lldb $(DEBUG_KERNEL_ELF) -o "gdb-remote localhost:1234" +DEBUGGER = gdb $(DEBUG_KERNEL_ELF) --eval-command "target remote localhost:1234" + + +.PHONY: build run debug + +# compile asm +$(BOOT_OBJ): $(BOOT_SRC) Makefile + @echo "Compiling boot assembly" + @for asm in ${BOOT_SRC}; do nasm -f elf64 $$asm; done # compile kernel -$(KERNEL_ELF): $(KERNEL_ELF_DEPS) Makefile - @echo "Compiling kernel ELF" - @RUSTFLAGS="$(RUSTFLAGS)" cargo rustc --target=$(TARGET) - cp target/$(TARGET)/debug/$(KERNEL) target/$(TARGET)/release/$(KERNEL) +$(KERNEL_ELF): $(KERNEL_DEPS) $(CARGO_DEPS) Makefile + @echo "Compiling kernel lib" + RUSTFLAGS="$(RUSTFLAGS)" $(CARGO_BUILD) + +# compile debug kernel +$(DEBUG_KERNEL_ELF): $(DEBUG_KERNEL_DEPS) $(CARGO_DEPS) Makefile + @echo "Compiling debug kernel ELF" + @RUSTFLAGS="$(RUSTFLAGS)" $(CARGO_BUILD_DEBUG) # generate grub iso $(OS_ISO): $(KERNEL_ELF) Makefile @echo "Generate os iso" - @cp $(KERNEL_ELF) iso/boot/kernel - @grub-mkrescue /usr/lib/grub/i386-pc -o $@ iso &> /dev/null + @cp $< iso/boot/kernel + @grub-mkrescue /usr/lib/grub/i386-pc -o $@ iso > /dev/null 2>&1 + +# generate debug grub iso +$(DEBUG_OS_ISO): $(DEBUG_KERNEL_ELF) Makefile + @echo "Generate debug os iso" + @cp $< iso/boot/kernel + @grub-mkrescue /usr/lib/grub/i386-pc -o $@ iso > /dev/null 2>&1 # just compile the kernel build: $(KERNEL_ELF) Makefile - @echo "$(KERNEL_ELF)" + @echo "$<" # compile and run silently run: $(OS_ISO) Makefile @echo "Running kernel in QEMU" - @$(QEMU) $(OS_ISO) &> /dev/null + @$(QEMU) $< &> /dev/null # compile, run and start gdb -debug: $(KERNEL_ELF) $(OS_ISO) Makefile +debug: $(DEBUG_KERNEL_ELF) $(DEBUG_OS_ISO) Makefile @echo "Debugging kernel in QEMU" - @$(QEMU) $(OS_ISO) -s &> /dev/null + @$(QEMU) $(DEBUG_OS_ISO) -s -no-reboot &> /dev/null +# wait for qemu to be ready @sleep 1 - @gdb $(KERNEL_ELF) --eval-command "target remote :1234" + @$(DEBUGGER) diff --git a/src/arch/x86_64/boot.s b/src/arch/x86_64/boot.s index 2f5d549096b70e23d7f97bd6bd4d90a1d2d1b055..291433ecbe801ea2eae87bd9866705937f4f101b 100644 --- a/src/arch/x86_64/boot.s +++ b/src/arch/x86_64/boot.s @@ -1,5 +1,7 @@ // x86_64 multiboot2 kernel start +KERNEL_BASE = 0xFFFFFFFF80000000; + ; /* Multiboot header */ @@ -26,187 +28,55 @@ header_end: /* protected mode start */ - - .section .inittext + .section .inittext, "ax" .global start .code32 start: - // setup stack - mov esp, stack_top - - // checks - call check_multiboot - call check_cpuid - call check_long_mode - - // setups - call setup_page_tables - call enable_paging - - // TODO: GDT before long mode - // lgdt [gdt64.pointer] - // jmp gdt64.code: start64 - jmp start64 - - jmp halt - -error: - // print 'ERR: <err>' - mov dword ptr [0xb8000], 0x4f524f45 - mov dword ptr [0xb8004], 0x4f3a4f52 - mov dword ptr [0xb8008], 0x4f204f20 - mov byte ptr [0xb800a], al - jmp halt - -halt: - cli - // print 'ZZZ' as halting - mov word ptr [0xb8f00], 0x0f5a - mov word ptr [0xb8f02], 0x0f5a - mov word ptr [0xb8f04], 0x0f5a -halt_repeat: - hlt - jmp halt_repeat - -/* - checks -*/ - -// check if booted from a multiboot -// compliant bootloader -check_multiboot: - cmp eax, 0x36d76289 - jne .no_multiboot - ret -.no_multiboot: - mov al, 'M' - jmp error - -// check for cpuid instruction availability -// requirement for checking long mode support -check_cpuid: - pushfd - pop eax - mov ecx, eax - xor eax, 1 << 21 - push eax - popfd - - pushfd - pop eax - push ecx - popfd - - cmp eax, ecx - je .no_cpuid - ret -.no_cpuid: - mov al, 'C' - jmp error - -// check for long mode availability -// requires cpuid instruction availability -check_long_mode: - mov eax, 0x80000000 - cpuid - cmp eax, 0x80000001 - jb .no_long_mode - - mov eax, 0x80000001 - cpuid - test edx, 1 << 29 - jz .no_long_mode - - ret -.no_long_mode: - mov al, 'L' - jmp error - -/* - setups - page tables, paging, long mode -*/ - -setup_page_tables: - mov eax, p3_table - or eax, 0b11 // present, writeable - mov [p4_table], eax - - mov eax, p2_table - or eax, 0b11 // present, writeable - mov [p3_table], eax - - mov ecx, 0 // counter -.loop: - mov eax, 0x200000 // 2MiB - mul ecx - or eax, 0b10000011 // present, writeable, huge page - mov [p2_table + ecx * 8], eax - - inc ecx // inc counter - cmp ecx, 512 // check if the whole table is mapped - jne .loop // if not: continue - - ret - -enable_paging: - // pass page table location to the cpu - mov eax, p4_table - mov cr3, eax - - // enable PAE + mov multiboot_sig - KERNEL_BASE, eax + mov multiboot_ptr - KERNEL_BASE, ebx mov eax, cr4 - or eax, 1 << 5 - mov cr4, eax - - // enable long mode - mov ecx, 0xC0000080 - rdmsr - or eax, 1 << 8 - wrmsr + or eax, 0x80|0x20|0x10 + mov cr3, eax +halt: hlt + jmp halt - // enable paging - mov eax, cr0 - or eax, 1 << 31 - mov cr0, eax - - ret .section .text - .code64 + .globl start64 start64: - mov ax, 0 - mov ss, ax - mov ds, ax - mov es, ax - mov fs, ax - mov gs, ax - - // print 'OK' - mov dword ptr [0xb8000], 0x2f4b2f4f - - call kernel_main - jmp halt - -/* - memory -*/ + mov esp, stack_top .section .bss .align 4096 + .code64 // page tables -p4_table: +p4_table: // PML4 + // .quad p3_table + 3 + // .rept 512 - 3 + // .quad + // .endr + // .quad 0 + // .quad p2_table + 3 .skip 4096 -p3_table: +p3_table: // PDP + // .quad .skip 4096 -p2_table: +p2_table: // PD .skip 4096 +p1_table: // PT + // 16 KiB stack stack_bottom: .skip 4096 * 4 stack_top: + .section .data +multiboot_sig: + .long 0 +multiboot_ptr: + .long 0 // TODO: global descriptor table /*.section .rodata gdt64: diff --git a/src/arch/x86_64/boot.s_all b/src/arch/x86_64/boot.s_all new file mode 100644 index 0000000000000000000000000000000000000000..6b366d19bcc66acc4781af019c8c09ab6bfd0ce4 --- /dev/null +++ b/src/arch/x86_64/boot.s_all @@ -0,0 +1,238 @@ +// x86_64 multiboot2 kernel start + +/* + Multiboot header +*/ + + .section .multiboot_header, "a" + .align 4 + .global header_start +header_start: + // magic number (multiboot2) + .int 0xE85250D6 + // arch (protected mode i386) + .int 0 + // header length + .int header_end - header_start + // checksum + .int 0x100000000 - (0xe85250d6 + 0 + header_end - header_start) + + // end tag + .word 0 + .word 0 + .int 8 +header_end: + +/* + protected mode start +*/ + .section .inittext, "ax" + .global start + .code32 +start: + // setup stack + mov esp, stack_top + + // checks + call check_multiboot + call check_cpuid + call check_long_mode + + // setups + call setup_page_tables + call enable_paging + + // TODO: GDT before long mode + // lgdt [gdt64.pointer] + // jmp gdt64.code: start64 + jmp start64 + + jmp halt + +error: + // print 'ERR: <err>' + mov dword ptr [0xb8000], 0x4f524f45 + mov dword ptr [0xb8004], 0x4f3a4f52 + mov dword ptr [0xb8008], 0x4f204f20 + mov byte ptr [0xb800a], al + jmp halt + +halt: + cli + // print 'ZZZ' as halting + mov word ptr [0xb8f00], 0x0f5a + mov word ptr [0xb8f02], 0x0f5a + mov word ptr [0xb8f04], 0x0f5a +halt_repeat: + hlt + jmp halt_repeat + +/* + checks +*/ + +// check if booted from a multiboot +// compliant bootloader +check_multiboot: + cmp eax, 0x36d76289 + jne .no_multiboot + ret +.no_multiboot: + mov al, 'M' + jmp error + +// check for cpuid instruction availability +// requirement for checking long mode support +check_cpuid: + pushfd + pop eax + mov ecx, eax + xor eax, 1 << 21 + push eax + popfd + + pushfd + pop eax + push ecx + popfd + + cmp eax, ecx + je .no_cpuid + ret +.no_cpuid: + mov al, 'C' + jmp error + +// check for long mode availability +// requires cpuid instruction availability +check_long_mode: + mov eax, 0x80000000 + cpuid + cmp eax, 0x80000001 + jb .no_long_mode + + mov eax, 0x80000001 + cpuid + test edx, 1 << 29 + jz .no_long_mode + + ret +.no_long_mode: + mov al, 'L' + jmp error + +/* + setups - page tables, paging, long mode +*/ + +// btw without these two next lines, +// the setup_page_tables and .no_long_mode +// gets corrupted for what ever reason +// +// even tho the section is the same already +// and the bits mode is already 32 +setup_page_tables: + mov eax, p3_table + or eax, 0b11 // present, writeable + mov [p4_table], eax + + mov eax, p2_table + or eax, 0b11 // present, writeable + mov [p3_table], eax + + mov ecx, 0 // counter +.loop: + mov eax, 0x200000 // 2MiB + mul ecx + or eax, 0b10000011 // present, writeable, huge page + mov [p2_table + ecx * 8], eax + + inc ecx // inc counter + cmp ecx, 512 // check if the whole table is mapped + jne .loop // if not: continue + + hlt + ret + +enable_paging: + // pass page table location to the cpu + mov eax, p4_table + mov cr3, eax + + // enable PAE + mov eax, cr4 + or eax, 1 << 5 + mov cr4, eax + + // enable long mode + mov ecx, 0xC0000080 + rdmsr + or eax, 1 << 8 + wrmsr + + // enable paging + mov eax, cr0 + or eax, 1 << 31 + mov cr0, eax + + ret + nop + +/* + Start in long mode and jump to the + kernel_main in main.rs +*/ + + .section .text + .code64 +start64: + mov ax, 0 + mov ss, ax + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + + // print 'OK' + mov dword ptr [0xb8000], 0x2f4b2f4f + + call kernel_main + jmp halt + +/* + memory +*/ + + .section .bss + .align 4096 + .code64 +// page tables +p4_table: // PML4 + // .quad p3_table + 3 + // .rept 512 - 3 + // .quad + // .endr + // .quad 0 + // .quad p2_table + 3 + .skip 4096 +p3_table: // PDP + // .quad + .skip 4096 +p2_table: // PD + .skip 4096 +p1_table: // PT + +// 16 KiB stack +stack_bottom: + .skip 4096 * 4 +stack_top: + +// TODO: global descriptor table +/*.section .rodata +gdt64: + .long 0 ; zero entry +.code_segment: equ $ - gdt64 + .long (1 << 43) | (1 << 44) | (1 << 47) | (1 << 53) +.pointer: + .word $ - gdt64 - 1 + .long gdt64*/ diff --git a/src/arch/x86_64/boot/.gitignore b/src/arch/x86_64/boot/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..cc5bb740f142b7a2681c2e42692a4d2bb4fc18bd --- /dev/null +++ b/src/arch/x86_64/boot/.gitignore @@ -0,0 +1 @@ +/*.o diff --git a/src/arch/x86_64/boot/check.asm b/src/arch/x86_64/boot/check.asm new file mode 100644 index 0000000000000000000000000000000000000000..9a87a1d88a3e022a423dbb2121d7cd73d45c1840 --- /dev/null +++ b/src/arch/x86_64/boot/check.asm @@ -0,0 +1,54 @@ +global check_multiboot, check_cpuid, check_long_mode +extern error + +section .text +bits 32 + +; multiboot check +check_multiboot: + cmp eax, 0x36d76289 + jne .no_multiboot + ret +.no_multiboot: + mov al, "M" + jmp error + +; cpuid check +check_cpuid: + pushfd + pop eax + mov ecx, eax + xor eax, 1 << 21 + push eax + popfd + + pushfd + pop eax + push ecx + popfd + + cmp eax, ecx + je .no_cpuid + ret + +.no_cpuid: + mov al, "C" + jmp error + +; long mode check +check_long_mode: + mov eax, 0x80000000 + cpuid + cmp eax, 0x80000001 + jb .no_long_mode + + mov eax, 0x80000001 + cpuid + test edx, 1 << 29 + jz .no_long_mode + + ret + +.no_long_mode: + mov al, "L" + jmp error \ No newline at end of file diff --git a/src/arch/x86_64/boot/header.asm b/src/arch/x86_64/boot/header.asm new file mode 100644 index 0000000000000000000000000000000000000000..7f6a0f2dc38181d41f01713941008417147462ee --- /dev/null +++ b/src/arch/x86_64/boot/header.asm @@ -0,0 +1,16 @@ +section .multiboot_header +header_start: + ; magic number (multiboot2) + dd 0xe85250d6 + ; arch (protected mode i386) + dd 0 + ; header length + dd header_end - header_start + ; checksum + dd 0x100000000 - (0xe85250d6 + 0 + header_end - header_start) + + ; end tag + dw 0 + dw 0 + dd 8 +header_end: \ No newline at end of file diff --git a/src/arch/x86_64/boot/long.asm b/src/arch/x86_64/boot/long.asm new file mode 100644 index 0000000000000000000000000000000000000000..71ed3bf652865518a49daaff65f90ea8ea630159 --- /dev/null +++ b/src/arch/x86_64/boot/long.asm @@ -0,0 +1,18 @@ +global long_mode_start +extern kernel_main + +section .text +bits 64 +long_mode_start: + mov ax, 0 + mov ss, ax + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + + ; print 'OK' + mov dword [0xb8000], 0x2f4b2f4f + + call kernel_main + hlt \ No newline at end of file diff --git a/src/arch/x86_64/boot/main.asm b/src/arch/x86_64/boot/main.asm new file mode 100644 index 0000000000000000000000000000000000000000..18927b1f324ed93fda4087c2a3e861567be3e716 --- /dev/null +++ b/src/arch/x86_64/boot/main.asm @@ -0,0 +1,39 @@ +global start, error +extern check_multiboot, check_cpuid, check_long_mode +extern setup_page_tables, enable_paging +extern stack_top, gdt64.pointer, gdt64.code_segment +extern long_mode_start + +section .text +bits 32 + +start: + mov esp, stack_top + + ; checks + call check_multiboot + call check_cpuid + call check_long_mode + + ; setups + call setup_page_tables + call enable_paging + + lgdt [gdt64.pointer] + jmp gdt64.code_segment: long_mode_start + jmp halt + +error: + ; print 'ERR: <err>' + mov dword [0xb8000], 0x4f524f45 + mov dword [0xb8004], 0x4f3a4f52 + mov dword [0xb8008], 0x4f204f20 + mov byte [0xb800a], al + jmp halt + +halt: + ; halt the CPU + mov word [0xb8f00], 0x0f5a + mov word [0xb8f02], 0x0f5a + mov word [0xb8f04], 0x0f5a + hlt \ No newline at end of file diff --git a/src/arch/x86_64/boot/memory.asm b/src/arch/x86_64/boot/memory.asm new file mode 100644 index 0000000000000000000000000000000000000000..038f6b403698cb422f4bdaffc8d9d2244cabc790 --- /dev/null +++ b/src/arch/x86_64/boot/memory.asm @@ -0,0 +1,29 @@ +global page_table_l4, page_table_l3, page_table_l2 +global stack_top +global gdt64.pointer, gdt64.code_segment + +section .bss +align 4096 + +; page tables +page_table_l4: + resb 4096 +page_table_l3: + resb 4096 +page_table_l2: + resb 4096 + +; stack +stack_bottom: + resb 4096 * 4 +stack_top: + +; global descriptor table +section .rodata +gdt64: + dq 0 ; zero entry +.code_segment: equ $ - gdt64 + dq (1 << 43) | (1 << 44) | (1 << 47) | (1 << 53) +.pointer: + dw $ - gdt64 - 1 + dq gdt64 \ No newline at end of file diff --git a/src/arch/x86_64/boot/setup.asm b/src/arch/x86_64/boot/setup.asm new file mode 100644 index 0000000000000000000000000000000000000000..24fc47f475c9768fe5605af1c61a68674e4b024d --- /dev/null +++ b/src/arch/x86_64/boot/setup.asm @@ -0,0 +1,53 @@ +global setup_page_tables, enable_paging +extern page_table_l4, page_table_l3, page_table_l2 + +section .text +bits 32 + +; page tables +setup_page_tables: + mov eax, page_table_l3 + or eax, 0b11 ; present, writeable + mov [page_table_l4], eax + + mov eax, page_table_l2 + or eax, 0b11 ; present, writeable + mov [page_table_l3], eax + + mov ecx, 0 ; counter + +.loop: + mov eax, 0x200000 ; 2MiB + mul ecx, + or eax, 0b10000011 ; present, writeable, huge page + mov [page_table_l2 + ecx * 8], eax + + inc ecx ; inc counter + cmp ecx, 512 ; check if the whole table is mapped + jne .loop ; if not: continue + + ret + +; paging +enable_paging: + ; pass page table location to the cpu + mov eax, page_table_l4 + mov cr3, eax + + ; enable PAE + mov eax, cr4 + or eax, 1 << 5 + mov cr4, eax + + ; enable long mode + mov ecx, 0xC0000080 + rdmsr + or eax, 1 << 8 + wrmsr + + ; enable paging + mov eax, cr0 + or eax, 1 << 31 + mov cr0, eax + + ret \ No newline at end of file diff --git a/src/arch/x86_64/kernel.ld b/src/arch/x86_64/kernel.ld index b1ed7732c34a4037a32e7093402243c93649f43b..c14b4ae7ae4f77eae02761089e617473b5de730e 100644 --- a/src/arch/x86_64/kernel.ld +++ b/src/arch/x86_64/kernel.ld @@ -1,28 +1,43 @@ ENTRY(start) OUTPUT_FORMAT(elf64-x86-64) +KERNEL_BASE = 0xFFFFFFFF80000000; + SECTIONS { - /* 2 << 20 */ . = 0x100000; - .boot : { - KEEP(*(.multiboot_header)) + . += SIZEOF_HEADERS; + + .init : AT(ADDR(.init)) { + KEEP( *(.multiboot_header) ) *(.inittext) } - .text : { - *(.text) + . += KERNEL_BASE; + + .text ALIGN(0x1000) : AT(ADDR(.text) - KERNEL_BASE) { + *(.text .text.*) + } + + /* read-only data, page aligned to allow use of the no-execute feature */ + .rodata ALIGN(0x1000) : AT(ADDR(.rodata) - KERNEL_BASE) { + *(.rodata .rodata.*) } - .rodata : { - *(.rodata) + /* Read-write data, page aligned for the .padata section */ + .data ALIGN(0x1000) : AT(ADDR(.data) - KERNEL_BASE) { + *(.padata) + *(.data .data.*) } - .data : { - *(.data) + /* Zero-initialised data */ + .bss : AT(ADDR(.bss) - KERNEL_BASE) { + *(.bss .bss.*) } - .bss : { - *(.bss) + kernel_end = .; + + /DISCARD/ : { + *(.note .note.*) } } diff --git a/src/main.rs b/src/main.rs index df2c8ad78dcb1e3f5ca49368ea84d09897e60808..4f193bce8387fa7cecb7913db7733d7547e9cb25 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,8 @@ #![no_std] #![no_main] +#![feature(custom_test_frameworks)] +#![test_runner(crate::test_runner)] +#![reexport_test_harness_main = "test_main"] #[cfg(target_arch = "x86_64")] #[path = "arch/x86_64/boot.rs"] @@ -13,4 +16,17 @@ fn panic_handler(_: &PanicInfo) -> ! { } #[no_mangle] -fn kernel_main() {} +pub extern "C" fn kernel_main() { + let mut vmem = unsafe { &mut *(0xb8000 as *mut [u8; 4]) }; + vmem[0] = b'C'; + + #[cfg(test)] + test_main(); +} + +fn test_runner(tests: &[&dyn Fn()]) {} + +#[test_case] +fn test() { + assert_eq!(1, 0) +}