From db99e90198a4e3fbea901db00c9a03de3703bfec Mon Sep 17 00:00:00 2001 From: Mark Date: Mon, 17 Feb 2025 17:45:56 -0800 Subject: [PATCH] Added serial driver --- Makefile | 1 + bootloader/bootloader/Cargo.lock | 66 ++++++++++++++++++++++ bootloader/bootloader/Cargo.toml | 5 ++ bootloader/bootloader/src/main.rs | 2 +- bootloader/bootloader/src/os/bios/mod.rs | 5 +- bootloader/bootloader/src/os/bios/panic.rs | 2 +- bootloader/bootloader/src/serial.rs | 56 ++++++++++++++++++ 7 files changed, 133 insertions(+), 4 deletions(-) create mode 100644 bootloader/bootloader/src/serial.rs diff --git a/Makefile b/Makefile index 2064b23..2c1cd65 100644 --- a/Makefile +++ b/Makefile @@ -33,6 +33,7 @@ qemu: $(BUILD)/disk.img -smp 1 -m 2048 \ -machine q35 \ -net none \ + -serial stdio \ -fda "$<" # -gdb tcp::26000 \ # -S diff --git a/bootloader/bootloader/Cargo.lock b/bootloader/bootloader/Cargo.lock index 5dfa25d..4fd4d08 100644 --- a/bootloader/bootloader/Cargo.lock +++ b/bootloader/bootloader/Cargo.lock @@ -8,6 +8,33 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" +[[package]] +name = "bit_field" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36" + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +dependencies = [ + "spin", +] + [[package]] name = "linked_list_allocator" version = "0.10.5" @@ -33,15 +60,32 @@ version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" +[[package]] +name = "raw-cpuid" +version = "10.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c297679cb867470fa8c9f67dbba74a78d78e3e98d7cf2b08d6d71540f797332" +dependencies = [ + "bitflags 1.3.2", +] + [[package]] name = "redox_bootloader" version = "1.0.0" dependencies = [ + "lazy_static", "linked_list_allocator", "log", "spin", + "uart_16550", ] +[[package]] +name = "rustversion" +version = "1.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4" + [[package]] name = "scopeguard" version = "1.2.0" @@ -65,3 +109,25 @@ checksum = "5b9eb1a2f4c41445a3a0ff9abc5221c5fcd28e1f13cd7c0397706f9ac938ddb0" dependencies = [ "lock_api", ] + +[[package]] +name = "uart_16550" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e492212ac378a5e00da953718dafb1340d9fbaf4f27d6f3c5cab03d931d1c049" +dependencies = [ + "bitflags 2.8.0", + "rustversion", + "x86", +] + +[[package]] +name = "x86" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2781db97787217ad2a2845c396a5efe286f87467a5810836db6d74926e94a385" +dependencies = [ + "bit_field", + "bitflags 1.3.2", + "raw-cpuid", +] diff --git a/bootloader/bootloader/Cargo.toml b/bootloader/bootloader/Cargo.toml index e693adf..6d8859e 100644 --- a/bootloader/bootloader/Cargo.toml +++ b/bootloader/bootloader/Cargo.toml @@ -67,3 +67,8 @@ multiple_crate_versions = "deny" linked_list_allocator = "0.10.5" log = "0.4.17" spin = "0.9.5" +uart_16550 = "0.3.2" + +[dependencies.lazy_static] +version = "1.0" +features = ["spin_no_std"] diff --git a/bootloader/bootloader/src/main.rs b/bootloader/bootloader/src/main.rs index 3a4e925..b0458d5 100644 --- a/bootloader/bootloader/src/main.rs +++ b/bootloader/bootloader/src/main.rs @@ -11,8 +11,8 @@ use self::os::{OsMemoryEntry, OsMemoryKind}; #[macro_use] mod os; - mod logger; +mod serial; //TODO: allocate this in a more reasonable manner static mut AREAS: [OsMemoryEntry; 1024] = [OsMemoryEntry { diff --git a/bootloader/bootloader/src/os/bios/mod.rs b/bootloader/bootloader/src/os/bios/mod.rs index 61c6284..8261440 100644 --- a/bootloader/bootloader/src/os/bios/mod.rs +++ b/bootloader/bootloader/src/os/bios/mod.rs @@ -2,7 +2,7 @@ use linked_list_allocator::LockedHeap; use spin::Mutex; use crate::logger::LOGGER; -use crate::KernelArgs; +use crate::serial_println; use self::memory_map::memory_map; use self::thunk::ThunkData; @@ -35,6 +35,8 @@ pub unsafe extern "C" fn start( thunk15: extern "C" fn(), _thunk16: extern "C" fn(), ) -> ! { + serial_println!("Entered rust; serial initialized."); + { // Make sure we are in mode 3 (80x25 text mode) let mut data = ThunkData::new(); @@ -59,7 +61,6 @@ pub unsafe extern "C" fn start( let (heap_start, heap_size) = memory_map(thunk15).expect("No memory for heap"); ALLOCATOR.lock().init(heap_start as *mut u8, heap_size); - // let (page_phys, func, args) = crate::run_main(&mut os); panic!("kernel"); } diff --git a/bootloader/bootloader/src/os/bios/panic.rs b/bootloader/bootloader/src/os/bios/panic.rs index 552521c..97b3506 100644 --- a/bootloader/bootloader/src/os/bios/panic.rs +++ b/bootloader/bootloader/src/os/bios/panic.rs @@ -13,7 +13,7 @@ pub extern "C" fn rust_eh_personality() {} #[no_mangle] pub fn rust_begin_unwind(info: &PanicInfo<'_>) -> ! { unsafe { - println!("BOOTLOADER PANIC:\n{}", info); + println!("TETRIS PANIC:\n{}", info); loop { asm!("hlt"); } diff --git a/bootloader/bootloader/src/serial.rs b/bootloader/bootloader/src/serial.rs new file mode 100644 index 0000000..5c24529 --- /dev/null +++ b/bootloader/bootloader/src/serial.rs @@ -0,0 +1,56 @@ +use core::arch::asm; + +use lazy_static::lazy_static; +use spin::Mutex; +use uart_16550::SerialPort; + +lazy_static! { + pub static ref SERIAL1: Mutex = { + let mut serial_port = unsafe { SerialPort::new(0x3F8) }; + serial_port.init(); + Mutex::new(serial_port) + }; +} + +#[doc(hidden)] +pub fn _print(args: core::fmt::Arguments<'_>) { + use core::fmt::Write; + + // TODO: preserve previous interrupt state + + // Disable interrupts to prevent deadlocks + // (we might get an interrupt while printing) + unsafe { + asm!("cli", options(preserves_flags, nostack)); + } + + SERIAL1 + .lock() + .write_fmt(args) + .expect("Printing to serial failed"); + + // TODO: + // This is broken, triple-faults right away. + // Uncomment after enabling interrupts in the bootloader & fixing idt + // + // unsafe { + // asm!("sti", options(preserves_flags, nostack)); + // } +} + +/// Prints to the host through the serial interface. +#[macro_export] +macro_rules! serial_print { + ($($arg:tt)*) => { + $crate::serial::_print(format_args!($($arg)*)); + }; +} + +/// Prints to the host through the serial interface, appending a newline. +#[macro_export] +macro_rules! serial_println { + () => ($crate::serial_print!("\n")); + ($fmt:expr) => ($crate::serial_print!(concat!($fmt, "\n"))); + ($fmt:expr, $($arg:tt)*) => ($crate::serial_print!( + concat!($fmt, "\n"), $($arg)*)); +}