diff --git a/.gitignore b/.gitignore index fa8d85a..7bb374e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ Cargo.lock +build target diff --git a/Makefile b/Makefile index cb86d75..5edd574 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,10 @@ ARCH?=x86_64 -run: qemu +all: build/harddrive.bin + +list: build/kernel.list + +run: bochs bochs: build/harddrive.bin bochs -f bochs.$(ARCH) @@ -11,12 +15,15 @@ qemu: build/harddrive.bin FORCE: build/libkernel.a: FORCE - rustc --crate-type staticlib src/lib.rs -o $@ + rustc --crate-type staticlib -C lto -O src/lib.rs -o $@ #--target $(ARCH)-unknown-none.json build/kernel.bin: build/libkernel.a ld -m elf_$(ARCH) -o $@ -T bootloader/x86/kernel.ld -z max-page-size=0x1000 $< +build/kernel.list: build/kernel.bin + objdump -C -M intel -D $< > $@ + build/harddrive.bin: build/kernel.bin nasm -f bin -o $@ -D ARCH_$(ARCH) -ibootloader/x86/ -ibuild/ bootloader/x86/harddrive.asm diff --git a/bootloader/x86/startup-x86_64.asm b/bootloader/x86/startup-x86_64.asm index 8dd738d..05b7021 100644 --- a/bootloader/x86/startup-x86_64.asm +++ b/bootloader/x86/startup-x86_64.asm @@ -67,21 +67,13 @@ long_mode: mov gs, rax mov ss, rax - ; load long mode IDT - lidt [idtr] - mov rsp, 0x800000 - 128 - mov rax, gdt.tss - ltr ax - ;rust init + xor rax, rax mov eax, [kernel_base + 0x18] - mov [interrupts.handler], rax - mov rax, gdtr - mov rbx, idtr - mov rcx, tss - int 0xFF + mov rbx, gdtr + jmp rax .lp: sti hlt diff --git a/bootloader/x86/vesa.asm b/bootloader/x86/vesa.asm index 8dadf2a..cb22221 100644 --- a/bootloader/x86/vesa.asm +++ b/bootloader/x86/vesa.asm @@ -183,8 +183,8 @@ vesa: .minx dw 640 .miny dw 480 .required: -.requiredx dw 0 ;1024 ;USE THESE WITH CAUTION -.requiredy dw 0 ;768 +.requiredx dw 1024 ;USE THESE WITH CAUTION +.requiredy dw 768 .requiredmode dw 0 .noedidmsg db "EDID not supported.",10,13,0 diff --git a/src/arch/x86_64/gdt.rs b/src/arch/x86_64/gdt.rs new file mode 100644 index 0000000..27648bb --- /dev/null +++ b/src/arch/x86_64/gdt.rs @@ -0,0 +1,31 @@ +pub const GDT_NULL: usize = 0; +pub const GDT_KERNEL_CODE: usize = 1; +pub const GDT_KERNEL_DATA: usize = 2; +pub const GDT_USER_CODE: usize = 3; +pub const GDT_USER_DATA: usize = 4; +pub const GDT_USER_TLS: usize = 5; +pub const GDT_TSS: usize = 6; + +#[repr(packed)] +pub struct GdtDescriptor { + pub size: u16, + pub ptr: u64 +} + +#[repr(packed)] +pub struct GdtEntry { + pub limitl: u16, + pub basel: u16, + pub basem: u8, + pub attribute: u8, + pub flags_limith: u8, + pub baseh: u8 +} + +impl GdtEntry { + pub fn set_base(&mut self, base: usize) { + self.basel = base as u16; + self.basem = (base >> 16) as u8; + self.baseh = (base >> 24) as u8; + } +} diff --git a/src/arch/x86_64/idt.rs b/src/arch/x86_64/idt.rs new file mode 100644 index 0000000..7b6e021 --- /dev/null +++ b/src/arch/x86_64/idt.rs @@ -0,0 +1,53 @@ +use core::mem; + +pub static mut IDTR: IdtDescriptor = IdtDescriptor { + size: 0, + offset: 0 +}; + +pub static mut IDT: [IdtEntry; 256] = [IdtEntry::new(); 256]; + +#[repr(packed)] +pub struct IdtDescriptor { + pub size: u16, + pub offset: u64 +} + +impl IdtDescriptor { + pub fn set_slice(&mut self, slice: &'static [IdtEntry]) { + self.size = (slice.len() * mem::size_of::() - 1) as u16; + self.offset = slice.as_ptr() as u64; + } +} + +#[derive(Copy, Clone, Debug)] +#[repr(packed)] +pub struct IdtEntry { + pub offsetl: u16, + pub selector: u16, + pub zero: u8, + pub attribute: u8, + pub offsetm: u16, + pub offseth: u32, + pub zero2: u32 +} + +impl IdtEntry { + pub const fn new() -> IdtEntry { + IdtEntry { + offsetl: 0, + selector: 0, + zero: 0, + attribute: 0, + offsetm: 0, + offseth: 0, + zero2: 0 + } + } + + pub fn set_offset(&mut self, base: usize) { + self.offsetl = base as u16; + self.offsetm = (base >> 16) as u16; + self.offseth = (base >> 32) as u32; + } +} diff --git a/src/arch/x86_64/main.rs b/src/arch/x86_64/main.rs index c4ca2e4..d257f2e 100644 --- a/src/arch/x86_64/main.rs +++ b/src/arch/x86_64/main.rs @@ -2,10 +2,35 @@ /// It is increcibly unsafe, and should be minimal in nature /// It must create the IDT with the correct entries, those entries are /// defined in other files inside of the `arch` module + +use super::idt::{IDTR, IDT}; + #[naked] #[no_mangle] pub unsafe extern fn kmain() { asm!("xchg bx, bx" : : : : "intel", "volatile"); - loop{} + for entry in IDT.iter_mut() { + entry.attribute = 1 << 7 | 0xE; + entry.selector = 8; + entry.set_offset(&blank as *const _ as usize); + entry.zero = 0; + entry.zero2 = 0; + } + IDTR.set_slice(&IDT); + asm!("lidt [rax]" : : "{rax}"(&IDTR as *const _ as usize) : : "intel", "volatile"); + + asm!("xchg bx, bx" : : : : "intel", "volatile"); + + asm!("int 0xFF" : : : : "intel", "volatile"); + + loop{ + asm!("hlt" : : : : "intel", "volatile"); + } +} + +#[naked] +pub unsafe extern fn blank() { + asm!("xchg bx, bx" : : : : "intel", "volatile"); + asm!("iretq" : : : : "intel", "volatile"); } diff --git a/src/arch/x86_64/mod.rs b/src/arch/x86_64/mod.rs index 530a611..774b90f 100644 --- a/src/arch/x86_64/mod.rs +++ b/src/arch/x86_64/mod.rs @@ -1,3 +1,9 @@ +/// Global descriptor table +pub mod gdt; + +/// Interrupt descriptor table +pub mod idt; + /// IRQ Handling pub mod irq; diff --git a/src/arch/x86_64/tss.rs b/src/arch/x86_64/tss.rs new file mode 100644 index 0000000..b1034b8 --- /dev/null +++ b/src/arch/x86_64/tss.rs @@ -0,0 +1,20 @@ +#[repr(packed)] +pub struct Tss { + pub reserved1: u32, + pub sp0: u64, + pub sp1: u64, + pub sp2: u64, + pub reserved2: u32, + pub reserved3: u32, + pub ist1: u64, + pub ist2: u64, + pub ist3: u64, + pub ist4: u64, + pub ist5: u64, + pub ist6: u64, + pub ist7: u64, + pub reserved4: u32, + pub reserved5: u32, + pub reserved6: u16, + pub iomap_base: u16, +} diff --git a/src/lib.rs b/src/lib.rs index 5f7b513..b28bbe5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -65,6 +65,7 @@ //! In this case, it is recommended to add one page, 4096 bytes, to the buffer and retry. #![feature(asm)] +#![feature(const_fn)] #![feature(lang_items)] #![feature(naked_functions)] #![no_std]