diff --git a/kernel/libk/src/device/display/console.rs b/kernel/libk/src/device/display/console.rs index 6d2f1333..ff616b3f 100644 --- a/kernel/libk/src/device/display/console.rs +++ b/kernel/libk/src/device/display/console.rs @@ -440,7 +440,7 @@ impl ConsoleState { } } // Move cursor to position - b'f' => { + b'f' if self.esc_args.len() >= 2 => { let row = self.esc_args[0].clamp(1, self.buffer.height) - 1; let col = self.esc_args[1].clamp(1, CONSOLE_ROW_LEN as u32) - 1; diff --git a/kernel/libk/src/task/runtime/timer.rs b/kernel/libk/src/task/runtime/timer.rs index cd37057e..a40a7de4 100644 --- a/kernel/libk/src/task/runtime/timer.rs +++ b/kernel/libk/src/task/runtime/timer.rs @@ -69,7 +69,7 @@ impl TimerWheel { } fn register_timeout(duration: Duration, waker: &Waker) { - let nticks = duration.as_millis().min(288).max(2) as u64; + let nticks = duration.as_millis().clamp(2, 288) as u64; if nticks < 32 { SHORT_TERM_SLEEPS.lock().wake_after(nticks, waker); diff --git a/kernel/src/arch/i686/boot/multiboot.rs b/kernel/src/arch/i686/boot/multiboot.rs index 701062af..c334b1ba 100644 --- a/kernel/src/arch/i686/boot/multiboot.rs +++ b/kernel/src/arch/i686/boot/multiboot.rs @@ -3,6 +3,8 @@ use libk_mm::{ phys::PhysicalMemoryRegion, }; +use crate::arch::x86::InitrdSource; + #[derive(Clone, Copy, Debug)] #[repr(C)] pub struct MultibootInfo { @@ -92,3 +94,13 @@ impl MultibootMemoryMapEntry { self.ty == 1 } } + +impl InitrdSource for MultibootModuleEntry { + fn start(&self) -> PhysicalAddress { + PhysicalAddress::from_u32(self.mod_start) + } + + fn end(&self) -> PhysicalAddress { + PhysicalAddress::from_u32(self.mod_end) + } +} diff --git a/kernel/src/arch/i686/mod.rs b/kernel/src/arch/i686/mod.rs index fff637d4..8b3744e2 100644 --- a/kernel/src/arch/i686/mod.rs +++ b/kernel/src/arch/i686/mod.rs @@ -5,18 +5,15 @@ use abi::error::Error; use alloc::sync::Arc; use boot::multiboot::MultibootInfo; use device_api::{ - device::Device, - interrupt::{IpiDeliveryTarget, IpiMessage, Irq}, + interrupt::{IpiDeliveryTarget, IpiMessage}, ResetDevice, }; -use git_version::git_version; use kernel_arch::{Architecture, ArchitectureImpl}; use kernel_arch_i686::{gdt, mem::table::L3, PerCpuData}; use kernel_arch_x86::cpuid::{self, CpuFeatures, EcxFeatures, EdxFeatures}; use libk::{ arch::Cpu, debug::{self, LogLevel}, - devfs, device::{ display::{ console::{add_console_autoflush, ConsoleWrapper}, @@ -28,55 +25,23 @@ use libk::{ vfs::{Terminal, TerminalInput}, }; use libk_mm::{ - address::{PhysicalAddress, Virtualize}, + address::PhysicalAddress, phys::{self, reserved::reserve_region, PhysicalMemoryRegion}, - table::EntryLevelExt, }; -use libk_util::sync::IrqSafeSpinlock; use peripherals::textfb::TextFramebuffer; -use ygg_driver_pci::{LegacyPciAccess, PciBusManager}; + +use crate::arch::x86; + +use super::Platform; mod boot; pub mod exception; mod peripherals; -use crate::{ - arch::x86::{ - intrinsics::IoPortAccess, - peripherals::{i8253::I8253, ps2::PS2Controller, rtc::Rtc}, - ISA_IRQ_OFFSET, - }, - fs::{Initrd, INITRD_DATA}, -}; - -use super::{ - x86::{ - intrinsics::IoPort, - peripherals::{i8259::I8259, serial::ComPort}, - }, - Platform, -}; - -struct LegacyPciInner { - address: IoPort, - data: IoPort, -} - -struct LegacyPci { - inner: IrqSafeSpinlock, -} - pub struct I686; static SWITCH_TO_GRAPHIC: AtomicBool = AtomicBool::new(false); -static PCI: LegacyPci = LegacyPci { - inner: IrqSafeSpinlock::new(LegacyPciInner { - address: IoPort::new(0xCF8), - data: IoPort::new(0xCFC), - }), -}; - pub static PLATFORM: I686 = I686; impl Platform for I686 { @@ -101,32 +66,7 @@ impl Platform for I686 { } impl I686 { - fn init_initrd(initrd_start: PhysicalAddress, initrd_end: PhysicalAddress) { - if initrd_start.is_zero() || initrd_end <= initrd_start { - log::info!("No initrd loaded"); - return; - } - - let start_aligned = initrd_start.page_align_down::(); - let end_aligned = initrd_start.page_align_up::(); - - let data = unsafe { - core::slice::from_raw_parts( - start_aligned.virtualize() as *const u8, - initrd_end - initrd_start, - ) - }; - - let initrd = Initrd { - phys_page_start: start_aligned, - phys_page_len: end_aligned - start_aligned, - data, - }; - - INITRD_DATA.init(initrd); - } - - unsafe fn init_platform(&'static self, multiboot_info: &MultibootInfo) -> Result<(), Error> { + unsafe fn init_memory_management(&self, multiboot_info: &MultibootInfo) -> Result<(), Error> { reserve_region( "lowmem", PhysicalMemoryRegion { @@ -138,34 +78,18 @@ impl I686 { let modules = multiboot_info.modules(); if !modules.is_empty() { let initrd = &modules[0]; - let start = PhysicalAddress::from_u32(initrd.mod_start); - let end = PhysicalAddress::from_u32(initrd.mod_end); - - if initrd.mod_start < initrd.mod_end { - let size = initrd.mod_end - initrd.mod_start; - - reserve_region( - "initrd", - PhysicalMemoryRegion { - base: start, - size: size as _, - }, - ); - } - - Self::init_initrd(start, end); + x86::set_initrd(initrd, true); } // Initialize physical memory phys::init_from_iter(multiboot_info.memory_map_iter(), |_, _, _| Ok(()))?; - debug::init(); - devfs::init(); + Ok(()) + } - let com1_3 = ComPort::setup(0x3F8, 0x3E8, Irq::External(ISA_IRQ_OFFSET + 4))?; - - unsafe { init_gdt() }; - unsafe { exception::init_exceptions() }; + unsafe fn init_cpu(&self) -> Result<(), Error> { + init_gdt(); + exception::init_exceptions(); let (have_features, will_features) = cpuid::setup_features( CpuFeatures { @@ -185,38 +109,10 @@ impl I686 { }; Cpu::init_local(Some(0), cpu_data); - runtime::init_task_queue(); - - // Register the PCI drivers - // TODO make this implicit init - // TODO AHCI hangs inside interrupt handler in i686 - // ygg_driver_pci::register_class_driver( - // "AHCI SATA Controller", - // 0x01, - // Some(0x06), - // Some(0x01), - // ygg_driver_ahci::probe, - // ); - ygg_driver_pci::register_class_driver( - "USB xHCI", - 0x0C, - Some(0x03), - Some(0x30), - ygg_driver_usb_xhci::probe, - ); - ygg_driver_pci::register_vendor_driver( - "Virtio PCI GPU Device", - 0x1AF4, - 0x1050, - ygg_driver_virtio_gpu::probe, - ); - ygg_driver_pci::register_vendor_driver( - "Virtio PCI Network Device", - 0x1AF4, - 0x1000, - ygg_driver_virtio_net::probe, - ); + Ok(()) + } + unsafe fn init_framebuffer(&self) -> Result<(), Error> { DEVICE_REGISTRY.display.set_callback(|device, _| { log::info!("Display registered: {:?}", device.display_name()); if device @@ -227,21 +123,6 @@ impl I686 { } }); - let i8259 = I8259::setup().expect("Could not initialize i8259 PIC"); - let i8253 = I8253::setup().expect("Could not initialize i8253 Timer"); - - i8259.set_i8253(i8253); - - if let Err(error) = PS2Controller::setup() { - log::error!("Could not initialize PS/2 Controller: {error:?}"); - } - if let Err(error) = Rtc::setup() { - log::error!("RTC init error: {error:?}"); - } - if let Err(error) = unsafe { com1_3.port_a().clone().init_irq() } { - log::error!("COM port IRQ init error: {error:?}"); - } - // Setup text framebuffer // TODO check if video mode is set from boot info let textfb = Arc::new(TextFramebuffer::new( @@ -254,7 +135,7 @@ impl I686 { let textfb_console = Arc::new(Terminal::from_parts( Default::default(), - TerminalInput::with_capacity(256).unwrap(), + TerminalInput::with_capacity(256)?, ConsoleWrapper(textfb), )); let keyboard_input = ygg_driver_input::setup(); @@ -267,43 +148,27 @@ impl I686 { .ok(); DEVICE_REGISTRY.terminal.register(textfb_console).ok(); - log::info!( - "Yggdrasil v{} ({})", - env!("CARGO_PKG_VERSION"), - git_version!() - ); - - PciBusManager::add_legacy_segment(&PCI)?; - PciBusManager::setup_bus_devices()?; - Ok(()) } -} -impl LegacyPciAccess for LegacyPci { - fn write_u32(&self, bus: u8, slot: u8, func: u8, offset: u8, value: u32) { - assert_eq!(offset & 0x3, 0); - let inner = self.inner.lock(); - inner.address.write(Self::addr(bus, slot, func, offset)); - inner.data.write(value); - } + unsafe fn init_platform(&'static self, multiboot_info: &MultibootInfo) -> Result<(), Error> { + self.init_memory_management(multiboot_info) + .expect("Could not initialize memory management"); - fn read_u32(&self, bus: u8, slot: u8, func: u8, offset: u8) -> u32 { - assert_eq!(offset & 0x3, 0); - let inner = self.inner.lock(); - inner.address.write(Self::addr(bus, slot, func, offset)); - inner.data.read() - } -} + self.init_cpu().expect("Could not initialize CPU"); -impl LegacyPci { - #[inline] - const fn addr(bus: u8, slot: u8, func: u8, offset: u8) -> u32 { - ((bus as u32) << 16) - | ((slot as u32) << 11) - | ((func as u32) << 8) - | (offset as u32 & 0xFC) - | (1 << 31) + x86::register_pci_drivers(); + + let early = x86::init_platform_devices_early()?; + + if let Err(error) = self.init_framebuffer() { + log::error!("Could not initialize boot framebuffer: {error:?}"); + } + + x86::add_legacy_pci(); + x86::init_platform_devices(early); + + Ok(()) } } diff --git a/kernel/src/arch/x86/mod.rs b/kernel/src/arch/x86/mod.rs index 1006c48d..1ce4ea5f 100644 --- a/kernel/src/arch/x86/mod.rs +++ b/kernel/src/arch/x86/mod.rs @@ -2,6 +2,22 @@ #![allow(missing_docs)] +use abi::error::Error; +use alloc::sync::Arc; +use device_api::{device::Device, interrupt::Irq}; +use libk::{debug, devfs, task::runtime}; +use libk_mm::{ + address::{PhysicalAddress, Virtualize}, + phys::{self, PhysicalMemoryRegion}, + table::EntryLevelExt, +}; +use peripherals::{i8253::I8253, i8259::I8259, ps2::PS2Controller, rtc::Rtc, serial::ComPort}; +use ygg_driver_pci::PciBusManager; + +use crate::fs::{Initrd, INITRD_DATA}; + +use super::L3; + #[cfg(any(target_arch = "x86_64", rust_analyzer))] pub const ISA_IRQ_OFFSET: u32 = crate::arch::x86_64::ISA_IRQ_OFFSET; @@ -9,4 +25,156 @@ pub const ISA_IRQ_OFFSET: u32 = crate::arch::x86_64::ISA_IRQ_OFFSET; pub const ISA_IRQ_OFFSET: u32 = 0; pub mod intrinsics; +mod pci; pub mod peripherals; + +pub trait InitrdSource { + fn start(&self) -> PhysicalAddress; + fn end(&self) -> PhysicalAddress; +} + +pub struct EarlyPlatformDevices { + pub com1_3: Arc, + pub i8259: Arc, +} + +// TODO move this to some sort of .init_array-style implicit thing +pub fn register_pci_drivers() { + // XXX: Only works with MSI-X, so no i686 + #[cfg(any(target_arch = "x86_64", rust_analyzer))] + ygg_driver_pci::register_class_driver( + "NVMe Host Controller", + 0x01, + Some(0x08), + Some(0x02), + ygg_driver_nvme::probe, + ); + // XXX: i686 hangs in interrupt handler + #[cfg(any(target_arch = "x86_64", rust_analyzer))] + ygg_driver_pci::register_class_driver( + "AHCI Controller", + 0x01, + Some(0x06), + Some(0x01), + ygg_driver_ahci::probe, + ); + ygg_driver_pci::register_class_driver( + "USB xHCI", + 0x0C, + Some(0x03), + Some(0x30), + ygg_driver_usb_xhci::probe, + ); + ygg_driver_pci::register_vendor_driver( + "Virtio PCI GPU Device", + 0x1AF4, + 0x1050, + ygg_driver_virtio_gpu::probe, + ); + ygg_driver_pci::register_vendor_driver( + "Virtio PCI Network Device", + 0x1AF4, + 0x1000, + ygg_driver_virtio_net::probe, + ); +} + +// Initialize the bare minimum required to: +// * Allocate/manage interrupts +// * Print debug output +pub fn init_platform_devices_early() -> Result { + devfs::init(); + debug::init(); + + // Initialize async executor queue + runtime::init_task_queue(); + + let com1_3 = ComPort::setup(0x3F8, 0x3E8, Irq::External(ISA_IRQ_OFFSET + 4))?; + let i8259 = I8259::setup().expect("Could not initialize i8259 PIC"); + + #[cfg(any(target_arch = "x86", rust_analyzer))] + { + use libk::device::register_external_interrupt_controller; + + // No other interrupt handling options + unsafe { i8259.clone().init() }?; + register_external_interrupt_controller(i8259.clone()); + } + + #[cfg(any(target_arch = "x86_64", rust_analyzer))] + { + i8259.disable(); + } + + Ok(EarlyPlatformDevices { i8259, com1_3 }) +} + +pub fn add_legacy_pci() { + if let Err(error) = PciBusManager::add_legacy_segment(&pci::PCI) { + log::error!("Couldn't add legacy x86 PCI: {error:?}"); + } +} + +pub fn init_platform_devices(early: EarlyPlatformDevices) { + // TODO clocksource can be selected here + match I8253::setup() { + Ok(i8253) => { + early.i8259.set_i8253(i8253); + } + Err(error) => { + log::error!("Couldn't setup i8253: {error:?}"); + } + } + if let Err(error) = PS2Controller::setup() { + log::error!("PS/2 controller init error: {error:?}"); + } + if let Err(error) = Rtc::setup() { + log::error!("RTC init error: {error:?}"); + } + if let Err(error) = unsafe { early.com1_3.port_a().clone().init_irq() } { + log::error!("COM port IRQ init error: {error:?}"); + } + + if let Err(error) = PciBusManager::setup_bus_devices() { + log::error!("PCI bus device setup error(s): {error:?}"); + } +} + +pub fn set_initrd(initrd: &impl InitrdSource, reserve: bool) { + let initrd_start = initrd.start(); + let initrd_end = initrd.end(); + + if initrd_start.is_zero() || initrd_end <= initrd_start { + log::info!("No initrd loaded"); + return; + } + + let start_aligned = initrd_start.page_align_down::(); + let end_aligned = initrd_end.page_align_up::(); + let size = end_aligned - start_aligned; + + if reserve { + phys::reserved::reserve_region( + "initrd", + PhysicalMemoryRegion { + base: start_aligned, + size, + }, + ); + } + + let data = unsafe { + core::slice::from_raw_parts( + start_aligned.virtualize() as *const u8, + initrd_end - initrd_start, + ) + }; + + let initrd = Initrd { + phys_page_start: start_aligned, + phys_page_len: end_aligned - start_aligned, + data, + }; + + INITRD_DATA.init(initrd); +} diff --git a/kernel/src/arch/x86/pci.rs b/kernel/src/arch/x86/pci.rs new file mode 100644 index 00000000..39d5d23f --- /dev/null +++ b/kernel/src/arch/x86/pci.rs @@ -0,0 +1,49 @@ +use libk_util::sync::IrqSafeSpinlock; +use ygg_driver_pci::LegacyPciAccess; + +use crate::arch::x86::intrinsics::IoPortAccess; + +use super::intrinsics::IoPort; + +struct LegacyPciInner { + address: IoPort, + data: IoPort, +} + +pub(super) struct LegacyPci { + inner: IrqSafeSpinlock, +} + +pub(super) static PCI: LegacyPci = LegacyPci { + inner: IrqSafeSpinlock::new(LegacyPciInner { + address: IoPort::new(0xCF8), + data: IoPort::new(0xCFC), + }), +}; + +impl LegacyPciAccess for LegacyPci { + fn write_u32(&self, bus: u8, slot: u8, func: u8, offset: u8, value: u32) { + assert_eq!(offset & 0x3, 0); + let inner = self.inner.lock(); + inner.address.write(Self::addr(bus, slot, func, offset)); + inner.data.write(value); + } + + fn read_u32(&self, bus: u8, slot: u8, func: u8, offset: u8) -> u32 { + assert_eq!(offset & 0x3, 0); + let inner = self.inner.lock(); + inner.address.write(Self::addr(bus, slot, func, offset)); + inner.data.read() + } +} + +impl LegacyPci { + #[inline] + const fn addr(bus: u8, slot: u8, func: u8, offset: u8) -> u32 { + ((bus as u32) << 16) + | ((slot as u32) << 11) + | ((func as u32) << 8) + | (offset as u32 & 0xFC) + | (1 << 31) + } +} diff --git a/kernel/src/arch/x86/peripherals/i8259.rs b/kernel/src/arch/x86/peripherals/i8259.rs index 69a1fc2e..30dcdb5e 100644 --- a/kernel/src/arch/x86/peripherals/i8259.rs +++ b/kernel/src/arch/x86/peripherals/i8259.rs @@ -9,7 +9,6 @@ use device_api::{ IrqOptions, }, }; -use libk::device::register_external_interrupt_controller; use libk_util::{sync::IrqSafeSpinlock, OneTimeInit}; use crate::arch::x86::intrinsics::{IoPort, IoPortAccess}; @@ -124,8 +123,6 @@ impl I8259 { pub fn setup() -> Result, Error> { let this = Arc::new(Self::new()); - unsafe { this.clone().init() }?; - register_external_interrupt_controller(this.clone()); I8259.init(this.clone()); Ok(this) } @@ -134,9 +131,8 @@ impl I8259 { self.i8253.init(i8253); } - pub fn disable() { - let inner = Self::new_inner(); - + pub fn disable(&self) { + let inner = self.inner.lock(); log::info!("Disabling i8259 PIC"); // Remap PIC IRQ vectors to 32.. diff --git a/kernel/src/arch/x86/peripherals/rtc.rs b/kernel/src/arch/x86/peripherals/rtc.rs index 215fa474..27d5b442 100644 --- a/kernel/src/arch/x86/peripherals/rtc.rs +++ b/kernel/src/arch/x86/peripherals/rtc.rs @@ -54,7 +54,7 @@ impl Inner { self.wait_for_update(); let mut last = self.try_read_time(); - let time = loop { + loop { self.wait_for_update(); let now = self.try_read_time(); @@ -62,9 +62,7 @@ impl Inner { break now; } last = now; - }; - - time + } } fn wait_for_update(&mut self) { diff --git a/kernel/src/arch/x86_64/boot/mod.rs b/kernel/src/arch/x86_64/boot/mod.rs index c0436e2e..1f8ef5e6 100644 --- a/kernel/src/arch/x86_64/boot/mod.rs +++ b/kernel/src/arch/x86_64/boot/mod.rs @@ -3,7 +3,6 @@ use core::{arch::global_asm, sync::atomic::Ordering}; use kernel_arch_x86::registers::MSR_IA32_KERNEL_GS_BASE; use kernel_arch_x86_64::CPU_COUNT; -use libk::{devfs, task::runtime}; use tock_registers::interfaces::Writeable; use yboot_proto::{ v1::{FramebufferOption, MemoryMap}, @@ -12,7 +11,7 @@ use yboot_proto::{ use crate::{kernel_main, kernel_secondary_main, mem::KERNEL_VIRT_OFFSET}; -use super::{exception, syscall, PLATFORM}; +use super::PLATFORM; pub enum BootData { YBoot(&'static LoadProtocolV1), @@ -79,23 +78,6 @@ extern "C" fn __x86_64_upper_entry() -> ! { PLATFORM.set_boot_data(BootData::YBoot(&YBOOT_DATA)); - // Setup memory management: kernel virtual memory tables, physical page manager and heap - unsafe { - PLATFORM - .init_memory_management() - .expect("Could not initialize memory management"); - } - - unsafe { - exception::init_exceptions(0); - } - - // Initialize async executor queue - runtime::init_task_queue(); - - devfs::init(); - - // Initializes: local CPU, platform devices (timers/serials/etc), debug output unsafe { PLATFORM .init_platform(0) @@ -113,13 +95,7 @@ pub extern "C" fn __x86_64_ap_entry() -> ! { init_dummy_cpu(); } - // Still not initialized: GDT, IDT, CPU features, syscall, kernel_gs_base - unsafe { - // Cpu::init_local(LocalApic::new(), cpu_id as u32); - syscall::init_syscall(); - exception::init_exceptions(cpu_id); - PLATFORM .init_platform(cpu_id) .expect("Could not initialize the platform (AP)"); diff --git a/kernel/src/arch/x86_64/mod.rs b/kernel/src/arch/x86_64/mod.rs index eacbce66..535b2885 100644 --- a/kernel/src/arch/x86_64/mod.rs +++ b/kernel/src/arch/x86_64/mod.rs @@ -6,8 +6,6 @@ use abi::error::Error; use acpi::{AcpiAllocator, AcpiHandlerImpl}; use alloc::{boxed::Box, sync::Arc}; use apic::{ioapic::IoApic, local::LocalApic}; -use device_api::{device::Device, interrupt::Irq}; -use git_version::git_version; use kernel_arch_x86::{ cpuid::{self, CpuFeatures, EcxFeatures, EdxFeatures}, gdt, @@ -31,7 +29,7 @@ use libk::{ }, }; use libk_mm::{ - address::{PhysicalAddress, Virtualize}, + address::PhysicalAddress, phys::{self, reserved::reserve_region, PhysicalMemoryRegion}, table::{EntryLevel, EntryLevelExt}, }; @@ -49,19 +47,12 @@ mod exception; mod smp; mod syscall; -use crate::{ - arch::x86::peripherals::{i8253::I8253, ps2::PS2Controller, rtc::Rtc}, - device::display::linear_fb::LinearFramebuffer, - fs::{Initrd, INITRD_DATA}, -}; +use crate::{arch::x86, device::display::linear_fb::LinearFramebuffer}; use self::boot::BootData; use super::{ - x86::{ - intrinsics, - peripherals::{i8259::I8259, serial::ComPort}, - }, + x86::{intrinsics, InitrdSource}, Platform, }; @@ -251,8 +242,39 @@ impl X86_64 { } unsafe fn init_platform(&'static self, cpu_id: usize) -> Result<(), Error> { + if cpu_id == 0 { + PLATFORM + .init_memory_management() + .expect("Could not initialize memory management"); + } + + self.init_local_cpu(cpu_id); + + if cpu_id == 0 { + x86::register_pci_drivers(); + + self.setup_from_boot_data()?; + + let early = x86::init_platform_devices_early()?; + + if let Err(error) = self.init_framebuffer() { + log::error!("Could not initialize boot framebuffer: {error:?}"); + } + + if let Some(acpi) = self.acpi.try_get() { + self.init_platform_from_acpi(acpi)?; + } + + x86::init_platform_devices(early); + } + + Ok(()) + } + + unsafe fn init_local_cpu(&self, cpu_id: usize) { let local_apic = Box::new(LocalApic::new()); let tss_address = gdt::init(); + exception::init_exceptions(cpu_id); let (have_features, will_features) = cpuid::setup_features( CpuFeatures { @@ -285,119 +307,16 @@ impl X86_64 { Cpu::init_local(Some(cpu_id as _), cpu_data); syscall::init_syscall(); - - if cpu_id == 0 { - // Register the PCI drivers - // TODO make this implicit init - ygg_driver_pci::register_class_driver( - "NVMe Host Controller", - 0x01, - Some(0x08), - Some(0x02), - ygg_driver_nvme::probe, - ); - ygg_driver_pci::register_class_driver( - "AHCI Controller", - 0x01, - Some(0x06), - Some(0x01), - ygg_driver_ahci::probe, - ); - ygg_driver_pci::register_class_driver( - "USB xHCI", - 0x0C, - Some(0x03), - Some(0x30), - ygg_driver_usb_xhci::probe, - ); - ygg_driver_pci::register_vendor_driver( - "Virtio PCI GPU Device", - 0x1AF4, - 0x1050, - ygg_driver_virtio_gpu::probe, - ); - ygg_driver_pci::register_vendor_driver( - "Virtio PCI Network Device", - 0x1AF4, - 0x1000, - ygg_driver_virtio_net::probe, - ); - - match self.boot_data.get() { - &BootData::YBoot(data) => { - let start = PhysicalAddress::from_u64(data.initrd_address); - Self::init_initrd(start, start.add(data.initrd_size as usize)); - } - } - - self.init_acpi_from_boot_data()?; - - I8259::disable(); - - debug::init(); - - let com1_3 = ComPort::setup(0x3F8, 0x3E8, Irq::External(ISA_IRQ_OFFSET + 4))?; - // TODO register platform devices - - DEVICE_REGISTRY.display.set_callback(|device, node| { - log::info!("Display registered: {:?}", device.display_name()); - // let node = devfs::add_block_device(device, BlockDeviceType::Framebuffer); - - if device - .driver_flags() - .contains(DriverFlags::REPLACES_BOOT_FRAMEBUFFER) - { - // Switch fbconsole to the new framebuffer - if let Some(fbconsole) = PLATFORM.fbconsole.try_get() - && fbconsole.uses_boot_framebuffer() - { - if let Err(error) = fbconsole.set_display(device.clone()) { - log::error!("Couldn't set fb console display: {error:?}"); - } - } - - // Switch /dev/fb0 to the new node - if let Some(node) = node { - devfs::set_node("fb0", node).ok(); - } - } - }); - self.init_framebuffer()?; - - log::info!( - "Yggdrasil v{} ({})", - env!("CARGO_PKG_VERSION"), - git_version!() - ); - - // RTC.init()?; - - if let Some(acpi) = self.acpi.try_get() { - self.init_platform_from_acpi(acpi)?; - } - - if let Err(error) = I8253::setup() { - log::error!("Couldn't setup i8253: {error:?}"); - } - if let Err(error) = PS2Controller::setup() { - log::error!("PS/2 controller init error: {error:?}"); - } - if let Err(error) = Rtc::setup() { - log::error!("RTC init error: {error:?}"); - } - if let Err(error) = unsafe { com1_3.port_a().clone().init_irq() } { - log::error!("COM port IRQ init error: {error:?}"); - } - - PciBusManager::setup_bus_devices()?; - } - - Ok(()) } - unsafe fn init_acpi_from_boot_data(&self) -> Result<(), Error> { + unsafe fn setup_from_boot_data(&self) -> Result<(), Error> { match self.boot_data.get() { - &BootData::YBoot(data) => self.init_acpi_from_rsdp(data.rsdp_address as usize), + &BootData::YBoot(data) => { + // Already reserved in set_boot_data() + x86::set_initrd(data, false); + + self.init_acpi_from_rsdp(data.rsdp_address as usize) + } } } @@ -420,16 +339,19 @@ impl X86_64 { })?; let InterruptModel::Apic(apic_info) = platform_info.interrupt_model else { - panic!("The processor does not support APIC"); + unreachable!("The processor does not support APIC"); }; let ioapic = IoApic::from_acpi(&apic_info)?; register_external_interrupt_controller(ioapic); // acpi::init_acpi(acpi).unwrap(); + if let Ok(mcfg) = acpi.find_table::() { for entry in mcfg.entries() { - PciBusManager::add_segment_from_mcfg(entry)?; + if let Err(error) = PciBusManager::add_segment_from_mcfg(entry) { + log::error!("Could not add PCI bus segment: {error:?}"); + } } } @@ -437,6 +359,29 @@ impl X86_64 { } unsafe fn init_framebuffer(&'static self) -> Result<(), Error> { + DEVICE_REGISTRY.display.set_callback(|device, node| { + log::info!("Display registered: {:?}", device.display_name()); + + if device + .driver_flags() + .contains(DriverFlags::REPLACES_BOOT_FRAMEBUFFER) + { + // Switch fbconsole to the new framebuffer + if let Some(fbconsole) = PLATFORM.fbconsole.try_get() + && fbconsole.uses_boot_framebuffer() + { + if let Err(error) = fbconsole.set_display(device.clone()) { + log::error!("Couldn't set fb console display: {error:?}"); + } + } + + // Switch /dev/fb0 to the new node + if let Some(node) = node { + devfs::set_node("fb0", node).ok(); + } + } + }); + let display = match self.boot_data.get() { &BootData::YBoot(data) => { let info = &data.opt_framebuffer; @@ -465,9 +410,7 @@ impl X86_64 { }; // Register boot display - // let display = Box::leak(Box::new(DisplayDeviceWrapper::new(display))); DEVICE_REGISTRY.display.register(display.clone(), true)?; - // register_display_device(display); let fbconsole = self .fbconsole @@ -482,28 +425,38 @@ impl X86_64 { Ok(()) } - fn init_initrd(initrd_start: PhysicalAddress, initrd_end: PhysicalAddress) { - if initrd_start.is_zero() || initrd_end <= initrd_start { - log::info!("No initrd loaded"); - return; - } + // fn init_initrd(initrd_start: PhysicalAddress, initrd_end: PhysicalAddress) { + // if initrd_start.is_zero() || initrd_end <= initrd_start { + // log::info!("No initrd loaded"); + // return; + // } - let start_aligned = initrd_start.page_align_down::(); - let end_aligned = initrd_start.page_align_up::(); + // let start_aligned = initrd_start.page_align_down::(); + // let end_aligned = initrd_start.page_align_up::(); - let data = unsafe { - core::slice::from_raw_parts( - start_aligned.virtualize() as *const u8, - initrd_end - initrd_start, - ) - }; + // let data = unsafe { + // core::slice::from_raw_parts( + // start_aligned.virtualize() as *const u8, + // initrd_end - initrd_start, + // ) + // }; - let initrd = Initrd { - phys_page_start: start_aligned, - phys_page_len: end_aligned - start_aligned, - data, - }; + // let initrd = Initrd { + // phys_page_start: start_aligned, + // phys_page_len: end_aligned - start_aligned, + // data, + // }; - INITRD_DATA.init(initrd); + // INITRD_DATA.init(initrd); + // } +} + +impl InitrdSource for LoadProtocolV1 { + fn start(&self) -> PhysicalAddress { + PhysicalAddress::from_u64(self.initrd_address) + } + + fn end(&self) -> PhysicalAddress { + PhysicalAddress::from_u64(self.initrd_address + self.initrd_size) } } diff --git a/kernel/src/main.rs b/kernel/src/main.rs index 570c4ff8..2f3fb418 100644 --- a/kernel/src/main.rs +++ b/kernel/src/main.rs @@ -38,6 +38,7 @@ use alloc::borrow::ToOwned; use arch::Platform; use fs::sysfs; +use git_version::git_version; use kernel_arch::{Architecture, ArchitectureImpl}; use libk::{arch::Cpu, devfs}; use libk_util::sync::SpinFence; @@ -87,6 +88,12 @@ pub fn kernel_secondary_main() -> ! { /// * Basic debugging facilities /// * Initrd pub fn kernel_main() -> ! { + log::info!( + "Yggdrasil v{} ({})", + env!("CARGO_PKG_VERSION"), + git_version!() + ); + libk::panic::set_handler(panic::panic_handler); // Setup the sysfs