diff --git a/kernel/src/arch/x86_64/apic/mod.rs b/kernel/src/arch/x86_64/apic/mod.rs index 2679f19..f6e84d4 100644 --- a/kernel/src/arch/x86_64/apic/mod.rs +++ b/kernel/src/arch/x86_64/apic/mod.rs @@ -1,6 +1,7 @@ #![expect(unused)] use core::arch::x86_64::__cpuid; +use spin::Lazy; // use libk::drivers::memory::{FRAME_ALLOCATOR, FoundryOSFrameAllocator, // OFFSET_PAGE_TABLE}; use x86_64::{ @@ -19,12 +20,11 @@ const IA32_APIC_BASE_MSR_DISABLE: u64 = !IA32_APIC_BASE_MSR_ENABLE; const CPUID_FEAT_EDX_APIC: u64 = 1 << 9; // the cpuid instruction will return this flag if it supports APIC -// const APIC_VIRTUAL_ADDRESS: Lazy = Lazy::new(|| { -// let apic_base = get_apic_base(); -// let virt_addr = unsafe { phys_to_virt(apic_base) }; +static APIC_VIRTUAL_ADDRESS: Lazy = Lazy::new(|| { + let apic_base = get_apic_base(); -// virt_addr -// }); + unsafe { phys_to_virt(apic_base) } +}); fn set_apic_base_enable(apic: PhysAddr) { let rax = (apic.as_u64() & 0xfffff0000) | IA32_APIC_BASE_MSR_ENABLE; @@ -92,7 +92,7 @@ pub fn enable_apic() { // // FIXME: this causes a page fault // // TODO: map to virtual memor - let reg = read_apic_register(&apic_virt, 0xF0); + let reg = read_apic_register(&APIC_VIRTUAL_ADDRESS, 0xF0); // serial_print!("ok2"); diff --git a/kernel/src/arch/x86_64/interrupts.rs b/kernel/src/arch/x86_64/interrupts.rs index 47e1d27..c78fc2c 100644 --- a/kernel/src/arch/x86_64/interrupts.rs +++ b/kernel/src/arch/x86_64/interrupts.rs @@ -1,8 +1,12 @@ use pic8259::ChainedPics; -use x86_64::structures::idt::{InterruptDescriptorTable, InterruptStackFrame}; +use x86_64::structures::idt::{ + InterruptDescriptorTable, InterruptStackFrame, PageFaultErrorCode, +}; use spin::{Lazy, Mutex}; +use crate::print_log; + use super::gdt; static IDT: Lazy = Lazy::new(|| { @@ -17,7 +21,7 @@ static IDT: Lazy = Lazy::new(|| { idt.general_protection_fault .set_handler_fn(general_protection_fault_handler); - // idt.page_fault.set_handler_fn(page_fault_handler); + idt.page_fault.set_handler_fn(page_fault_handler); idt[InterruptIndex::Timer.as_u8()].set_handler_fn(timer_interrupt_handler); idt[InterruptIndex::Keyboard.as_u8()].set_handler_fn(keyboard_interrupt_handler); @@ -119,13 +123,17 @@ extern "x86-interrupt" fn keyboard_interrupt_handler( extern "x86-interrupt" fn timer_interrupt_handler( _stack_frame: InterruptStackFrame, ) { + x86_64::instructions::interrupts::without_interrupts(|| { + print_log!("{:?}", _stack_frame) + }); + unsafe { PICS.lock() .notify_end_of_interrupt(InterruptIndex::Timer.as_u8()); } } -/* extern "x86-interrupt" fn page_fault_handler( +const extern "x86-interrupt" fn page_fault_handler( _stack_frame: InterruptStackFrame, _error_code: PageFaultErrorCode, ) { @@ -134,24 +142,24 @@ extern "x86-interrupt" fn timer_interrupt_handler( // serial_println!("Error Code: {:?}", _error_code); // serial_println!("{:#?}", _stack_frame); - if let Some(frame_allocator) = - FRAME_ALLOCATOR.get() { - let mut f = frame_allocator.lock(); + /* if let Some(frame_allocator) = FRAME_ALLOCATOR.get() { + let mut f = frame_allocator.lock(); - let frame = f.allocate_frame().unwrap(); - let flags = PageTableFlags::PRESENT | PageTableFlags::WRITABLE; - let page: Page = Page::containing_address(Cr2::read().unwrap()); + let frame = f.allocate_frame().unwrap(); + let flags = PageTableFlags::PRESENT | PageTableFlags::WRITABLE; + let page: Page = Page::containing_address(Cr2::read().unwrap()); - unsafe { - let mut mapper = OFFSET_PAGE_TABLE.get().unwrap().lock(); + unsafe { + let mut mapper = OFFSET_PAGE_TABLE.get().unwrap().lock(); - match mapper.map_to(page, frame, flags, &mut *f) { - Ok(_) => {} - Err(why) => panic!("failed to map page: {:?}", why), - } - } - MapperFlushAll::new().flush_all(); - } else { - panic!("failed to get frame allocator"); - } -} */ + match mapper.map_to(page, frame, flags, &mut *f) { + Ok(_) => {} + Err(why) => panic!("failed to map page: {:?}", why), + } + } + MapperFlushAll::new().flush_all(); + } else { + panic!("failed to get frame allocator"); + } + */ +} diff --git a/kernel/src/graphics/ascii.rs b/kernel/src/graphics/ascii.rs deleted file mode 100644 index 196a8da..0000000 --- a/kernel/src/graphics/ascii.rs +++ /dev/null @@ -1,236 +0,0 @@ -/* use core::fmt; -use spin::{Lazy, Mutex}; -use x86_64::instructions::interrupts; - -use super::framebuffer::{colour::Colour, display::FRAMEBUFFER_WRITER}; - -// use crate::resources::font::{FONT_SPLEEN_8X16, Font}; - -static FONT_WIDTH: u32 = 8; -static FONT_HEIGHT: u32 = 16; - -pub static WRITER: Lazy> = Lazy::new(|| Mutex::new(Writer::new())); - -pub fn screensize_chars() -> (u32, u32) { - let writer = WRITER.lock(); - (writer.screen_width, writer.screen_height) -} - -pub struct Writer { - font: &'static Font, - /// Measured in chars not pixels. - screen_width: u32, - /// Measured in chars not pixels. - screen_height: u32, - /// 16 pixels tall. - text_line: u32, - /// 8 pixels wide. - text_col: u32, - - fg_color: Colour, - bg_color: Colour, -} - -impl Default for Writer { - fn default() -> Self { - Self::new() - } -} - -impl Writer { - pub fn new() -> Self { - FRAMEBUFFER_WRITER.lock().as_mut().map_or_else( - || { - panic!("Framebuffer writer not initialized."); - }, - |writer| Self { - font: &FONT_SPLEEN_8X16, - screen_width: writer.width() / 8, - screen_height: writer.height() / 16, - text_line: 0, - text_col: 0, - fg_color: Colour::White, - bg_color: Colour::Black, - }, - ) - } - - pub const fn set_font(&mut self, font: &'static Font) { - self.font = font; - } - - /// This is sent when the user types a backspace. - const BACKSPACE: u8 = 8; - - pub fn write_glyph(&mut self, c: u8) { - if c == b'\n' { - self.newline(); - return; - } else if c == Self::BACKSPACE { - self.backspace(); - return; - } - - // Get the character data from the font array. -- each byte is a row of pixels - let data: &[u8] = self.font.glyph_for(c as u16); - - if let Some(writer) = FRAMEBUFFER_WRITER.lock().as_mut() { - for (row, line) in data.iter().enumerate().take(16) { - for col in 0..8 { - let pixel_x: u32 = self.text_col * FONT_WIDTH + col; - let pixel_y: u32 = self.text_line * FONT_HEIGHT + row as u32; - - if line & (0x80 >> col) != 0 { - // Write the foreground color - writer.write_pixel(pixel_x as usize, pixel_y as usize, self.fg_color); - } else { - // Write the background color - writer.write_pixel(pixel_x as usize, pixel_y as usize, self.bg_color); - } - } - } - } - - // Go to next position - if self.text_col + 1 >= self.screen_width { - self.newline(); - } else { - self.text_col += 1; - } - } - - pub const fn dimensions(&self) -> (u32, u32) { - (self.screen_width, self.screen_height) - } - - pub const fn next_char(&mut self) { - self.text_col += 1; - } - - pub const fn newline(&mut self) { - self.text_col = 0; - - if self.text_line + 1 >= self.screen_height { - self.text_line = 0; - } else { - self.text_line += 1; - } - } - - /// Handles the backspace character. TODO: Implement VT-100 style terminal control - /// codes alongside a shell. Not simple. - pub fn backspace(&mut self) { - if self.text_col > 0 { - self.text_col -= 1; - // Blank out the previous char. - self.write_glyph(b' '); - self.text_col -= 1; - } - } - - pub fn write_string(&mut self, s: &str) { - for c in s.chars() { - self.write_glyph(c as u8); - } - } - - pub const fn set_colour(&mut self, fg: Colour, bg: Colour) { - self.fg_color = fg; - self.bg_color = bg; - } - - pub const fn reset_colour(&mut self) { - self.fg_color = Colour::White; - self.bg_color = Colour::Black; - } -} - -impl core::fmt::Write for Writer { - fn write_str(&mut self, s: &str) -> core::fmt::Result { - self.write_string(s); - Ok(()) - } -} - -fn write(args: fmt::Arguments, fg: Colour, bg: Colour) { - use core::fmt::Write; - - interrupts::without_interrupts(|| { - let mut writer = WRITER.lock(); - writer.set_colour(fg, bg); - writer.write_fmt(args).unwrap(); - writer.reset_colour(); - }); -} - -pub fn _print(args: fmt::Arguments) { - x86_64::instructions::interrupts::without_interrupts(|| { - write(args, Colour::White, Colour::Black); - }) -} - -pub fn _print_err(args: fmt::Arguments) { - x86_64::instructions::interrupts::without_interrupts(|| { - write(args, Colour::Red, Colour::Black); - }) -} - -pub fn _print_log(args: fmt::Arguments) { - x86_64::instructions::interrupts::without_interrupts(|| { - write(args, Colour::Yellow, Colour::Black); - }) -} - -pub fn clear_screen() { - interrupts::without_interrupts(|| { - let mut writer = WRITER.lock(); - writer.text_line = 0; - writer.text_col = 0; - - if let Some(writer) = FRAMEBUFFER_WRITER.lock().as_mut() { - writer.clear(); - } - }); -} - -pub fn reset_cursor() { - interrupts::without_interrupts(|| { - let mut writer = WRITER.lock(); - writer.text_line = 0; - writer.text_col = 0; - }); -} - -#[macro_export] -macro_rules! println_log { - () => ($crate::print_log!("\n")); - ($($arg:tt)*) => ($crate::print_log!("{}\n", format_args!($($arg)*))); -} - -#[macro_export] -macro_rules! print_log { - ($($arg:tt)*) => ($crate::_print_log(format_args!($($arg)*))); -} - -#[macro_export] -macro_rules! println { - () => ($crate::print!("\n")); - ($($arg:tt)*) => ($crate::print!("{}\n", format_args!($($arg)*))); -} - -#[macro_export] -macro_rules! print { - ($($arg:tt)*) => ($crate::_print(format_args!($($arg)*))); -} - -#[macro_export] -macro_rules! printlnerr { - () => ($crate::printerr!("\n")); - ($($arg:tt)*) => ($crate::printerr!("{}\n", format_args!($($arg)*))); -} - -#[macro_export] -macro_rules! printerr { - ($($arg:tt)*) => ($crate::_print_err(format_args!($($arg)*))); -} - */ diff --git a/kernel/src/graphics/mod.rs b/kernel/src/graphics/mod.rs index 8265f60..1c29ec8 100644 --- a/kernel/src/graphics/mod.rs +++ b/kernel/src/graphics/mod.rs @@ -1,4 +1,3 @@ -pub mod ascii; pub mod colour; pub mod font; pub mod framebuffer; diff --git a/kernel/src/graphics/writer.rs b/kernel/src/graphics/writer.rs index e1abeb6..a60b0f0 100644 --- a/kernel/src/graphics/writer.rs +++ b/kernel/src/graphics/writer.rs @@ -1,3 +1,6 @@ +//! Formerly called ascii.rs, this file defines helper functions for drawing +//! characters to the screen. + use core::fmt; use spin::{Lazy, Mutex}; use x86_64::instructions::interrupts; @@ -219,7 +222,7 @@ macro_rules! println_log { #[macro_export] macro_rules! print_log { - ($($arg:tt)*) => ($crate::_print_log(format_args!($($arg)*))); + ($($arg:tt)*) => ($crate::graphics::writer::_print_log(format_args!($($arg)*))); } #[macro_export] diff --git a/kernel/src/io/serial.rs b/kernel/src/io/serial.rs index b6be41e..63cbdaa 100644 --- a/kernel/src/io/serial.rs +++ b/kernel/src/io/serial.rs @@ -1,12 +1,14 @@ -/* use core::{ +use crate::arch::x86_64::cpu::port::{inb, outb}; +use core::{ fmt, sync::atomic::{AtomicUsize, Ordering}, }; use spin::{Lazy, Mutex}; +use x86_64::instructions::interrupts; #[macro_export] macro_rules! serial_print { - ($($arg:tt)*) => ($crate::_serial_write(format_args!($($arg)*))); + ($($arg:tt)*) => ($crate::io::serial::_serial_write(format_args!($($arg)*))); } #[macro_export] @@ -15,10 +17,6 @@ macro_rules! serial_println { ($($arg:tt)*) => (serial_print!("{}\n", format_args!($($arg)*))); } -use super::port::{inb, outb}; - -use x86_64::instructions::interrupts; - pub fn _serial_write(args: fmt::Arguments) { use core::fmt::Write; @@ -77,7 +75,7 @@ impl fmt::Write for Writer { impl Writer { unsafe fn write_success(&self) -> bool { - inb(PORT + 5) & 0x20 != 0 + unsafe { inb(PORT + 5) & 0x20 != 0 } } pub fn write_byte(&self, data: u8) { @@ -103,21 +101,21 @@ pub fn init() -> Result<(), &'static str> { } pub fn test() -> Result<(), &'static str> { - outb(PORT + 1, 0x00); // Disable all interrupts - outb(PORT + 3, 0x80); // Enable DLAB (set baud rate divisor) - outb(PORT, 0x03); // Set divisor to 3 (lo byte) 38400 baud - outb(PORT + 1, 0x00); // (hi byte) - outb(PORT + 3, 0x03); // 8 bits, no parity, one stop bit - outb(PORT + 2, 0xC7); // Enable FIFO, clear them, with 14-bytethreshold - outb(PORT + 4, 0x0B); // IRQs enabled, RTS/DSR set - outb(PORT + 4, 0x1E); // Set in loopback mode, test the serial chip - outb(PORT, 0xAE); // Test serial chip (send byte 0xAE and check if serial returns same byte) + unsafe { outb(PORT + 1, 0x00) }; // Disable all interrupts + unsafe { outb(PORT + 3, 0x80) }; // Enable DLAB (set baud rate divisor) + unsafe { outb(PORT, 0x03) }; // Set divisor to 3 (lo byte) 38400 baud + unsafe { outb(PORT + 1, 0x00) }; // (hi byte) + unsafe { outb(PORT + 3, 0x03) }; // 8 bits, no parity, one stop bit + unsafe { outb(PORT + 2, 0xC7) }; // Enable FIFO, clear them, with 14-bytethreshold + unsafe { outb(PORT + 4, 0x0B) }; // IRQs enabled, RTS/DSR set + unsafe { outb(PORT + 4, 0x1E) }; // Set in loopback mode, test the serial chip + unsafe { outb(PORT, 0xAE) }; // Test serial chip (send byte 0xAE and check if serial returns same byte) - if inb(PORT) != 0xAE { - return Err("serial test failed"); + if unsafe { inb(PORT) } != 0xAE { + return Err("Serial test failed"); } - outb(PORT + 4, 0x0F); + unsafe { outb(PORT + 4, 0x0F) }; Ok(()) } @@ -143,7 +141,7 @@ impl Reader { } unsafe fn read_ready(&self) -> bool { - inb(PORT + 5) & 1 != 0 + unsafe { inb(PORT + 5) & 1 != 0 } } pub fn read(&self) -> u8 { @@ -153,4 +151,3 @@ impl Reader { } } } - */ diff --git a/kernel/src/lib.rs b/kernel/src/lib.rs index 238d92d..71be9fc 100644 --- a/kernel/src/lib.rs +++ b/kernel/src/lib.rs @@ -11,8 +11,10 @@ rustdoc::missing_panics_doc )] +use arch::x86_64::{gdt, interrupts}; use core::arch::asm; use graphics::font::{FONT_SPLEEN_8X16, Font}; +use io::serial; use limine::BaseRevision; pub mod arch; @@ -45,11 +47,28 @@ pub fn hcf() -> ! { } pub fn boot() -> Result<(), &'static str> { - println!("Test!"); - if !BASE_REVISION.is_supported() { return Err("Base Revision was not supported."); } + print_log!(" Setting up Serial Communication... "); + + if serial::init().is_err() { + println_log!("[Not Detected]") + } else { + println_log!("[Success]") + } + + print_log!(" Setting up GDT... "); + gdt::init(); + println_log!("[Success]"); + + interrupts::enable_pic(); + // interrupts::disable_pic(); + + print_log!(" Initialising interrupts... "); + interrupts::init_idt(); + println_log!("[Success]"); + Ok(()) }