From 55c43547fa99d55d1fa92afa9a45947a5acb7731 Mon Sep 17 00:00:00 2001 From: Andreas Wessing Date: Tue, 23 Jun 2026 13:26:27 +0200 Subject: [PATCH 1/4] add Bochs VBE linear framebuffer support --- Cargo.toml | 4 ++ src/arch/x86_64/kernel/bga.rs | 91 +++++++++++++++++++++++++++++++++++ src/arch/x86_64/kernel/mod.rs | 2 + src/drivers/pci.rs | 14 ++++++ src/syscalls/system.rs | 15 ++++++ 5 files changed, 126 insertions(+) create mode 100644 src/arch/x86_64/kernel/bga.rs diff --git a/Cargo.toml b/Cargo.toml index 467138ff40..1aae110e1b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -216,6 +216,10 @@ virtio-vsock = ["virtio"] ## This is only useful on PCs (x86-64). vga = [] +## Enables the _Bochs Graphics Adapter_ (BGA) driver. +## +## This provides a linear framebuffer for pixel graphics and is primarily useful in QEMU/Bochs environments (x86-64). +bga = ["pci"] #! ### Performance Features ## Disables putting the CPU to sleep. diff --git a/src/arch/x86_64/kernel/bga.rs b/src/arch/x86_64/kernel/bga.rs new file mode 100644 index 0000000000..ba0c9b3541 --- /dev/null +++ b/src/arch/x86_64/kernel/bga.rs @@ -0,0 +1,91 @@ +use core::sync::atomic::{AtomicU64, Ordering}; + +use memory_addresses::{PhysAddr, VirtAddr}; +use pci_types::{Bar, CommandRegister}; +use x86_64::instructions::port::Port; + +use crate::arch::x86_64::mm::paging; +use crate::arch::x86_64::mm::paging::{BasePageSize, PageTableEntryFlags, PageTableEntryFlagsExt}; +use crate::drivers::pci::PciDevice; +use crate::kernel::pci::PciConfigRegion; + +static FRAMEBUFFER_PHYS: AtomicU64 = AtomicU64::new(0); + +const VBE_DISPI_IOPORT_INDEX: u16 = 0x01ce; +const VBE_DISPI_IOPORT_DATA: u16 = 0x01cf; + +const VBE_DISPI_INDEX_ID: u16 = 0; +const VBE_DISPI_INDEX_XRES: u16 = 1; +const VBE_DISPI_INDEX_YRES: u16 = 2; +const VBE_DISPI_INDEX_BPP: u16 = 3; +const VBE_DISPI_INDEX_ENABLE: u16 = 4; + +const VBE_DISPI_DISABLED: u16 = 0x00; +const VBE_DISPI_ENABLED: u16 = 0x01; +const VBE_DISPI_LFB_ENABLED: u16 = 0x40; +const VBE_DISPI_ID5: u16 = 0xb0c5; + +pub fn init_device(adapter: &PciDevice) { + //To Do: Detect Resolution automatically + let width: u16 = 640; + let height: u16 = 400; + let bpp: u16 = 32; + + unsafe { + let mut index_port: Port = Port::new(VBE_DISPI_IOPORT_INDEX); + let mut data_port: Port = Port::new(VBE_DISPI_IOPORT_DATA); + + index_port.write(VBE_DISPI_INDEX_ID); + let bga_version = data_port.read(); + + if bga_version != VBE_DISPI_ID5 { + error!("Unsupported BGA version: {:#06x}", bga_version); + return; + } + + index_port.write(VBE_DISPI_INDEX_ENABLE); + data_port.write(VBE_DISPI_DISABLED); + + index_port.write(VBE_DISPI_INDEX_XRES); + data_port.write(width); + + index_port.write(VBE_DISPI_INDEX_YRES); + data_port.write(height); + + index_port.write(VBE_DISPI_INDEX_BPP); + data_port.write(bpp); + + index_port.write(VBE_DISPI_INDEX_ENABLE); + data_port.write(VBE_DISPI_ENABLED | VBE_DISPI_LFB_ENABLED); + } + + adapter.set_command(CommandRegister::MEMORY_ENABLE); + + let (phys_addr, size) = match adapter.get_bar(0) { + Some(Bar::Memory32 { address, size, .. }) => (u64::from(address), size as usize), + Some(Bar::Memory64 { address, size, .. }) => (address, size as usize), + _ => return, + }; + + FRAMEBUFFER_PHYS.store(phys_addr, Ordering::Release); + + assert!( + size % 4096 == 0, + "Framebuffer size must be a multiple of 4096 bytes" + ); + let page_count = size / 4096; + + let mut flags = PageTableEntryFlags::empty(); + flags.device().writable().execute_disable(); + flags.insert(PageTableEntryFlags::USER_ACCESSIBLE); + paging::map::( + VirtAddr::new(phys_addr), + PhysAddr::new(phys_addr), + page_count, + flags, + ); +} + +pub fn get_framebuffer_address() -> u64 { + FRAMEBUFFER_PHYS.load(Ordering::Acquire) +} diff --git a/src/arch/x86_64/kernel/mod.rs b/src/arch/x86_64/kernel/mod.rs index e0696d93a6..7d44ae9979 100644 --- a/src/arch/x86_64/kernel/mod.rs +++ b/src/arch/x86_64/kernel/mod.rs @@ -15,6 +15,8 @@ use crate::env; #[cfg(feature = "acpi")] pub mod acpi; pub mod apic; +#[cfg(feature = "bga")] +pub mod bga; pub mod core_local; pub mod gdt; pub mod interrupts; diff --git a/src/drivers/pci.rs b/src/drivers/pci.rs index a59aaacfe7..924a110ec4 100644 --- a/src/drivers/pci.rs +++ b/src/drivers/pci.rs @@ -459,6 +459,20 @@ pub(crate) fn init(handlers: &mut InterruptHandlerMap) { Err(err) => error!("Could not initialize rtl8139 device: {err}"), } } + + #[cfg(all(target_arch = "x86_64", feature = "bga"))] + for adapter in PCI_DEVICES.finalize().iter().filter(|x| { + let (vendor_id, device_id) = x.id(); + vendor_id == 0x1234 && device_id == 0x1111 + }) { + info!( + "Found Bochs VGA device with device id {:#x}", + adapter.device_id() + ); + + crate::kernel::bga::init_device(adapter); + } + PCI_DRIVERS.finalize(); }); } diff --git a/src/syscalls/system.rs b/src/syscalls/system.rs index de963e3fed..dd78628d79 100644 --- a/src/syscalls/system.rs +++ b/src/syscalls/system.rs @@ -6,3 +6,18 @@ use crate::arch::mm::paging::{BasePageSize, PageSize}; pub extern "C" fn sys_getpagesize() -> i32 { BasePageSize::SIZE.try_into().unwrap() } + +/// Returns the address of the framebuffer, if available. Returns 0 if no framebuffer is available. +#[cfg(all(target_arch = "x86_64", feature = "bga"))] +#[hermit_macro::system] +#[unsafe(no_mangle)] +pub extern "C" fn sys_get_framebuffer() -> u64 { + crate::kernel::bga::get_framebuffer_address() +} + +#[cfg(not(all(target_arch = "x86_64", feature = "bga")))] +#[hermit_macro::system] +#[unsafe(no_mangle)] +pub extern "C" fn sys_get_framebuffer() -> u64 { + 0 +} From 0a53b2dad520f3a28f6e924ac5af5d46dffc187d Mon Sep 17 00:00:00 2001 From: Andreas Wessing Date: Sun, 5 Jul 2026 19:19:18 +0200 Subject: [PATCH 2/4] style: use variable in format string --- src/arch/x86_64/kernel/bga.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/arch/x86_64/kernel/bga.rs b/src/arch/x86_64/kernel/bga.rs index ba0c9b3541..333d100ec6 100644 --- a/src/arch/x86_64/kernel/bga.rs +++ b/src/arch/x86_64/kernel/bga.rs @@ -39,7 +39,7 @@ pub fn init_device(adapter: &PciDevice) { let bga_version = data_port.read(); if bga_version != VBE_DISPI_ID5 { - error!("Unsupported BGA version: {:#06x}", bga_version); + error!("Unsupported BGA version: {bga_version:#06x}"); return; } From db54639c3cfa44b6ca84e61cfd4c1f008e7acaf5 Mon Sep 17 00:00:00 2001 From: Andreas Wessing Date: Tue, 14 Jul 2026 17:42:27 +0200 Subject: [PATCH 3/4] Refactor BGA based on review feedback --- Cargo.toml | 2 + src/arch/x86_64/kernel/bga.rs | 158 +++++++++++++++++++++++++--------- src/syscalls/system.rs | 41 +++++++-- 3 files changed, 150 insertions(+), 51 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 1aae110e1b..c470e362bd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -219,7 +219,9 @@ vga = [] ## Enables the _Bochs Graphics Adapter_ (BGA) driver. ## ## This provides a linear framebuffer for pixel graphics and is primarily useful in QEMU/Bochs environments (x86-64). +## It does not enable any kernel rendering, applications need to implement their own rendering on top of the framebuffer. bga = ["pci"] + #! ### Performance Features ## Disables putting the CPU to sleep. diff --git a/src/arch/x86_64/kernel/bga.rs b/src/arch/x86_64/kernel/bga.rs index 333d100ec6..93089168f1 100644 --- a/src/arch/x86_64/kernel/bga.rs +++ b/src/arch/x86_64/kernel/bga.rs @@ -1,64 +1,132 @@ -use core::sync::atomic::{AtomicU64, Ordering}; - +//! This module contains the implementation of the Bochs Graphics Adapter (BGA) driver. +//! +//! The driver uses the Bochs VBE Extensions, which use two I/O ports to communicate with the +//! emulated VGA card instead of relying on a 16-bit VBE BIOS. The driver initializes the BGA +//! device, sets the desired resolution and bits per pixel (BPP), and maps the framebuffer +//! into the virtual address space. It also provides a function to retrieve the physical +//! address of the framebuffer. + +use hermit_sync::OnceCell; use memory_addresses::{PhysAddr, VirtAddr}; use pci_types::{Bar, CommandRegister}; -use x86_64::instructions::port::Port; +use x86_64::instructions::port::{Port, PortWriteOnly}; -use crate::arch::x86_64::mm::paging; -use crate::arch::x86_64::mm::paging::{BasePageSize, PageTableEntryFlags, PageTableEntryFlagsExt}; +use crate::arch::x86_64::mm::paging::{ + self, BasePageSize, PageTableEntryFlags, PageTableEntryFlagsExt, +}; use crate::drivers::pci::PciDevice; use crate::kernel::pci::PciConfigRegion; -static FRAMEBUFFER_PHYS: AtomicU64 = AtomicU64::new(0); +pub struct BgaInfo { + pub framebuffer: *mut u8, + pub width: u16, + pub height: u16, + pub bpp: u16, +} + +static BGA_INFO: OnceCell = OnceCell::new(); + +unsafe impl Send for BgaInfo {} +unsafe impl Sync for BgaInfo {} const VBE_DISPI_IOPORT_INDEX: u16 = 0x01ce; const VBE_DISPI_IOPORT_DATA: u16 = 0x01cf; -const VBE_DISPI_INDEX_ID: u16 = 0; -const VBE_DISPI_INDEX_XRES: u16 = 1; -const VBE_DISPI_INDEX_YRES: u16 = 2; -const VBE_DISPI_INDEX_BPP: u16 = 3; -const VBE_DISPI_INDEX_ENABLE: u16 = 4; +pub struct VbeDispiIndex; + +#[allow(dead_code)] +impl VbeDispiIndex { + #[doc(alias = "VBE_DISPI_INDEX_ID")] + pub const ID: u16 = 0; + #[doc(alias = "VBE_DISPI_INDEX_XRES")] + pub const XRES: u16 = 1; + #[doc(alias = "VBE_DISPI_INDEX_YRES")] + pub const YRES: u16 = 2; + #[doc(alias = "VBE_DISPI_INDEX_BPP")] + pub const BPP: u16 = 3; + #[doc(alias = "VBE_DISPI_INDEX_ENABLE")] + pub const ENABLE: u16 = 4; + #[doc(alias = "VBE_DISPI_INDEX_BANK")] + pub const BANK: u16 = 5; + #[doc(alias = "VBE_DISPI_INDEX_VIRT_WIDTH")] + pub const VIRT_WIDTH: u16 = 6; + #[doc(alias = "VBE_DISPI_INDEX_VIRT_HEIGHT")] + pub const VIRT_HEIGHT: u16 = 7; + #[doc(alias = "VBE_DISPI_INDEX_X_OFFSET")] + pub const X_OFFSET: u16 = 8; + #[doc(alias = "VBE_DISPI_INDEX_Y_OFFSET")] + pub const Y_OFFSET: u16 = 9; +} const VBE_DISPI_DISABLED: u16 = 0x00; const VBE_DISPI_ENABLED: u16 = 0x01; const VBE_DISPI_LFB_ENABLED: u16 = 0x40; -const VBE_DISPI_ID5: u16 = 0xb0c5; -pub fn init_device(adapter: &PciDevice) { - //To Do: Detect Resolution automatically - let width: u16 = 640; - let height: u16 = 400; - let bpp: u16 = 32; - - unsafe { - let mut index_port: Port = Port::new(VBE_DISPI_IOPORT_INDEX); - let mut data_port: Port = Port::new(VBE_DISPI_IOPORT_DATA); +#[allow(dead_code)] +const VBE_DISPI_NOCLEARMEM: u16 = 0x80; + +pub struct VbeDispiId; + +#[allow(dead_code)] +impl VbeDispiId { + #[doc(alias = "VBE_DISPI_ID0")] + pub const ID0: u16 = 0xb0c0; + #[doc(alias = "VBE_DISPI_ID1")] + pub const ID1: u16 = 0xb0c1; + #[doc(alias = "VBE_DISPI_ID2")] + pub const ID2: u16 = 0xb0c2; + #[doc(alias = "VBE_DISPI_ID3")] + pub const ID3: u16 = 0xb0c3; + #[doc(alias = "VBE_DISPI_ID4")] + pub const ID4: u16 = 0xb0c4; + #[doc(alias = "VBE_DISPI_ID5")] + pub const ID5: u16 = 0xb0c5; +} - index_port.write(VBE_DISPI_INDEX_ID); - let bga_version = data_port.read(); +struct BgaRegisters; - if bga_version != VBE_DISPI_ID5 { - error!("Unsupported BGA version: {bga_version:#06x}"); - return; +impl BgaRegisters { + pub fn read(index: u16) -> u16 { + let mut index_port: PortWriteOnly = PortWriteOnly::new(VBE_DISPI_IOPORT_INDEX); + let mut data_port: Port = Port::new(VBE_DISPI_IOPORT_DATA); + unsafe { + index_port.write(index); + data_port.read() } + } - index_port.write(VBE_DISPI_INDEX_ENABLE); - data_port.write(VBE_DISPI_DISABLED); - - index_port.write(VBE_DISPI_INDEX_XRES); - data_port.write(width); + pub fn write(index: u16, value: u16) { + let mut index_port: PortWriteOnly = PortWriteOnly::new(VBE_DISPI_IOPORT_INDEX); + let mut data_port: Port = Port::new(VBE_DISPI_IOPORT_DATA); + unsafe { + index_port.write(index); + data_port.write(value); + } + } +} - index_port.write(VBE_DISPI_INDEX_YRES); - data_port.write(height); +pub fn init_device(adapter: &PciDevice) { + //To Do: Add support for different resolutions and BPP values + let width: u16 = 640; + let height: u16 = 400; + let bpp: u16 = 32; - index_port.write(VBE_DISPI_INDEX_BPP); - data_port.write(bpp); + let bga_version = BgaRegisters::read(VbeDispiIndex::ID); - index_port.write(VBE_DISPI_INDEX_ENABLE); - data_port.write(VBE_DISPI_ENABLED | VBE_DISPI_LFB_ENABLED); + if bga_version != VbeDispiId::ID5 { + error!("Unsupported BGA version: {bga_version:#06x}"); + return; } + BgaRegisters::write(VbeDispiIndex::ENABLE, VBE_DISPI_DISABLED); + BgaRegisters::write(VbeDispiIndex::XRES, width); + BgaRegisters::write(VbeDispiIndex::YRES, height); + BgaRegisters::write(VbeDispiIndex::BPP, bpp); + BgaRegisters::write( + VbeDispiIndex::ENABLE, + VBE_DISPI_ENABLED | VBE_DISPI_LFB_ENABLED, + ); + adapter.set_command(CommandRegister::MEMORY_ENABLE); let (phys_addr, size) = match adapter.get_bar(0) { @@ -67,17 +135,23 @@ pub fn init_device(adapter: &PciDevice) { _ => return, }; - FRAMEBUFFER_PHYS.store(phys_addr, Ordering::Release); + BGA_INFO + .set(BgaInfo { + framebuffer: core::ptr::with_exposed_provenance_mut(phys_addr as usize), + width, + height, + bpp, + }) + .ok(); assert!( - size % 4096 == 0, + size.is_multiple_of(4096), "Framebuffer size must be a multiple of 4096 bytes" ); let page_count = size / 4096; let mut flags = PageTableEntryFlags::empty(); flags.device().writable().execute_disable(); - flags.insert(PageTableEntryFlags::USER_ACCESSIBLE); paging::map::( VirtAddr::new(phys_addr), PhysAddr::new(phys_addr), @@ -86,6 +160,6 @@ pub fn init_device(adapter: &PciDevice) { ); } -pub fn get_framebuffer_address() -> u64 { - FRAMEBUFFER_PHYS.load(Ordering::Acquire) +pub fn get_framebuffer_info() -> Option<&'static BgaInfo> { + BGA_INFO.get() } diff --git a/src/syscalls/system.rs b/src/syscalls/system.rs index dd78628d79..06d619d4d6 100644 --- a/src/syscalls/system.rs +++ b/src/syscalls/system.rs @@ -1,4 +1,14 @@ +#[cfg(all(target_arch = "x86_64", feature = "bga"))] +use core::ffi::c_int; + use crate::arch::mm::paging::{BasePageSize, PageSize}; +#[repr(C)] +pub struct FramebufferInfo { + pub framebuffer: *mut u8, + pub width: u32, + pub height: u32, + pub bpp: u32, +} /// Returns the base page size, in bytes, of the current system. #[hermit_macro::system] @@ -7,17 +17,30 @@ pub extern "C" fn sys_getpagesize() -> i32 { BasePageSize::SIZE.try_into().unwrap() } -/// Returns the address of the framebuffer, if available. Returns 0 if no framebuffer is available. +/// Returns the framebuffer information for the BGA device, if it has been initialized. Returns 0 +/// on success, or -1 if the BGA device has not been initialized. #[cfg(all(target_arch = "x86_64", feature = "bga"))] #[hermit_macro::system] #[unsafe(no_mangle)] -pub extern "C" fn sys_get_framebuffer() -> u64 { - crate::kernel::bga::get_framebuffer_address() -} +pub unsafe extern "C" fn sys_framebuffer(info: *mut FramebufferInfo) -> c_int { + if info.is_null() { + return -1; + }; -#[cfg(not(all(target_arch = "x86_64", feature = "bga")))] -#[hermit_macro::system] -#[unsafe(no_mangle)] -pub extern "C" fn sys_get_framebuffer() -> u64 { - 0 + let bga_info = crate::arch::kernel::bga::get_framebuffer_info(); + match bga_info { + Some(bga_info) => { + let info_c = FramebufferInfo { + framebuffer: bga_info.framebuffer, + width: u32::from(bga_info.width), + height: u32::from(bga_info.height), + bpp: u32::from(bga_info.bpp), + }; + unsafe { + info.write(info_c); + } + 0 + } + None => -1, + } } From 71aa9fe803f77d8a12ef08913907d043c418a029 Mon Sep 17 00:00:00 2001 From: Andreas Wessing Date: Tue, 4 Aug 2026 16:36:59 +0200 Subject: [PATCH 4/4] refactor: implement latest feedback, change structs to enums --- Cargo.toml | 2 +- src/arch/x86_64/kernel/bga.rs | 76 +++++++++++++++++------------------ src/drivers/pci.rs | 2 +- src/syscalls/system.rs | 20 ++++----- 4 files changed, 49 insertions(+), 51 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index c470e362bd..cac4ee499c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -219,7 +219,7 @@ vga = [] ## Enables the _Bochs Graphics Adapter_ (BGA) driver. ## ## This provides a linear framebuffer for pixel graphics and is primarily useful in QEMU/Bochs environments (x86-64). -## It does not enable any kernel rendering, applications need to implement their own rendering on top of the framebuffer. +## Any rendering has to be done by the application; the kernel itself does not output anything on the framebuffer. bga = ["pci"] #! ### Performance Features diff --git a/src/arch/x86_64/kernel/bga.rs b/src/arch/x86_64/kernel/bga.rs index 93089168f1..92b157f8d0 100644 --- a/src/arch/x86_64/kernel/bga.rs +++ b/src/arch/x86_64/kernel/bga.rs @@ -11,14 +11,15 @@ use memory_addresses::{PhysAddr, VirtAddr}; use pci_types::{Bar, CommandRegister}; use x86_64::instructions::port::{Port, PortWriteOnly}; +use crate::arch::kernel::pci::PciConfigRegion; use crate::arch::x86_64::mm::paging::{ self, BasePageSize, PageTableEntryFlags, PageTableEntryFlagsExt, }; use crate::drivers::pci::PciDevice; -use crate::kernel::pci::PciConfigRegion; +#[derive(Debug)] pub struct BgaInfo { - pub framebuffer: *mut u8, + pub framebuffer: usize, pub width: u16, pub height: u16, pub bpp: u16, @@ -26,36 +27,32 @@ pub struct BgaInfo { static BGA_INFO: OnceCell = OnceCell::new(); -unsafe impl Send for BgaInfo {} -unsafe impl Sync for BgaInfo {} - const VBE_DISPI_IOPORT_INDEX: u16 = 0x01ce; const VBE_DISPI_IOPORT_DATA: u16 = 0x01cf; -pub struct VbeDispiIndex; - #[allow(dead_code)] -impl VbeDispiIndex { +#[repr(u16)] +pub enum VbeDispiIndex { #[doc(alias = "VBE_DISPI_INDEX_ID")] - pub const ID: u16 = 0; + Id = 0, #[doc(alias = "VBE_DISPI_INDEX_XRES")] - pub const XRES: u16 = 1; + Xres = 1, #[doc(alias = "VBE_DISPI_INDEX_YRES")] - pub const YRES: u16 = 2; + Yres = 2, #[doc(alias = "VBE_DISPI_INDEX_BPP")] - pub const BPP: u16 = 3; + Bpp = 3, #[doc(alias = "VBE_DISPI_INDEX_ENABLE")] - pub const ENABLE: u16 = 4; + Enable = 4, #[doc(alias = "VBE_DISPI_INDEX_BANK")] - pub const BANK: u16 = 5; + Bank = 5, #[doc(alias = "VBE_DISPI_INDEX_VIRT_WIDTH")] - pub const VIRT_WIDTH: u16 = 6; + VirtWidth = 6, #[doc(alias = "VBE_DISPI_INDEX_VIRT_HEIGHT")] - pub const VIRT_HEIGHT: u16 = 7; + VirtHeight = 7, #[doc(alias = "VBE_DISPI_INDEX_X_OFFSET")] - pub const X_OFFSET: u16 = 8; + XOffset = 8, #[doc(alias = "VBE_DISPI_INDEX_Y_OFFSET")] - pub const Y_OFFSET: u16 = 9; + YOffset = 9, } const VBE_DISPI_DISABLED: u16 = 0x00; @@ -65,41 +62,40 @@ const VBE_DISPI_LFB_ENABLED: u16 = 0x40; #[allow(dead_code)] const VBE_DISPI_NOCLEARMEM: u16 = 0x80; -pub struct VbeDispiId; - #[allow(dead_code)] -impl VbeDispiId { +#[repr(u16)] +pub enum VbeDispiId { #[doc(alias = "VBE_DISPI_ID0")] - pub const ID0: u16 = 0xb0c0; + Id0 = 0xb0c0, #[doc(alias = "VBE_DISPI_ID1")] - pub const ID1: u16 = 0xb0c1; + Id1 = 0xb0c1, #[doc(alias = "VBE_DISPI_ID2")] - pub const ID2: u16 = 0xb0c2; + Id2 = 0xb0c2, #[doc(alias = "VBE_DISPI_ID3")] - pub const ID3: u16 = 0xb0c3; + Id3 = 0xb0c3, #[doc(alias = "VBE_DISPI_ID4")] - pub const ID4: u16 = 0xb0c4; + Id4 = 0xb0c4, #[doc(alias = "VBE_DISPI_ID5")] - pub const ID5: u16 = 0xb0c5; + Id5 = 0xb0c5, } struct BgaRegisters; impl BgaRegisters { - pub fn read(index: u16) -> u16 { + pub fn read(index: VbeDispiIndex) -> u16 { let mut index_port: PortWriteOnly = PortWriteOnly::new(VBE_DISPI_IOPORT_INDEX); let mut data_port: Port = Port::new(VBE_DISPI_IOPORT_DATA); unsafe { - index_port.write(index); + index_port.write(index as u16); data_port.read() } } - pub fn write(index: u16, value: u16) { + pub fn write(index: VbeDispiIndex, value: u16) { let mut index_port: PortWriteOnly = PortWriteOnly::new(VBE_DISPI_IOPORT_INDEX); let mut data_port: Port = Port::new(VBE_DISPI_IOPORT_DATA); unsafe { - index_port.write(index); + index_port.write(index as u16); data_port.write(value); } } @@ -111,19 +107,19 @@ pub fn init_device(adapter: &PciDevice) { let height: u16 = 400; let bpp: u16 = 32; - let bga_version = BgaRegisters::read(VbeDispiIndex::ID); + let bga_version = BgaRegisters::read(VbeDispiIndex::Id); - if bga_version != VbeDispiId::ID5 { + if bga_version != VbeDispiId::Id5 as u16 { error!("Unsupported BGA version: {bga_version:#06x}"); return; } - BgaRegisters::write(VbeDispiIndex::ENABLE, VBE_DISPI_DISABLED); - BgaRegisters::write(VbeDispiIndex::XRES, width); - BgaRegisters::write(VbeDispiIndex::YRES, height); - BgaRegisters::write(VbeDispiIndex::BPP, bpp); + BgaRegisters::write(VbeDispiIndex::Enable, VBE_DISPI_DISABLED); + BgaRegisters::write(VbeDispiIndex::Xres, width); + BgaRegisters::write(VbeDispiIndex::Yres, height); + BgaRegisters::write(VbeDispiIndex::Bpp, bpp); BgaRegisters::write( - VbeDispiIndex::ENABLE, + VbeDispiIndex::Enable, VBE_DISPI_ENABLED | VBE_DISPI_LFB_ENABLED, ); @@ -137,12 +133,12 @@ pub fn init_device(adapter: &PciDevice) { BGA_INFO .set(BgaInfo { - framebuffer: core::ptr::with_exposed_provenance_mut(phys_addr as usize), + framebuffer: phys_addr as usize, width, height, bpp, }) - .ok(); + .unwrap(); assert!( size.is_multiple_of(4096), diff --git a/src/drivers/pci.rs b/src/drivers/pci.rs index 924a110ec4..5dbc8ca3a0 100644 --- a/src/drivers/pci.rs +++ b/src/drivers/pci.rs @@ -470,7 +470,7 @@ pub(crate) fn init(handlers: &mut InterruptHandlerMap) { adapter.device_id() ); - crate::kernel::bga::init_device(adapter); + crate::arch::kernel::bga::init_device(adapter); } PCI_DRIVERS.finalize(); diff --git a/src/syscalls/system.rs b/src/syscalls/system.rs index 06d619d4d6..5a1d898cf9 100644 --- a/src/syscalls/system.rs +++ b/src/syscalls/system.rs @@ -2,13 +2,6 @@ use core::ffi::c_int; use crate::arch::mm::paging::{BasePageSize, PageSize}; -#[repr(C)] -pub struct FramebufferInfo { - pub framebuffer: *mut u8, - pub width: u32, - pub height: u32, - pub bpp: u32, -} /// Returns the base page size, in bytes, of the current system. #[hermit_macro::system] @@ -17,12 +10,21 @@ pub extern "C" fn sys_getpagesize() -> i32 { BasePageSize::SIZE.try_into().unwrap() } +#[cfg(all(target_arch = "x86_64", feature = "bga"))] +#[repr(C)] +pub struct FramebufferInfo { + pub framebuffer: *mut u8, + pub width: u32, + pub height: u32, + pub bpp: u32, +} + /// Returns the framebuffer information for the BGA device, if it has been initialized. Returns 0 /// on success, or -1 if the BGA device has not been initialized. #[cfg(all(target_arch = "x86_64", feature = "bga"))] #[hermit_macro::system] #[unsafe(no_mangle)] -pub unsafe extern "C" fn sys_framebuffer(info: *mut FramebufferInfo) -> c_int { +pub unsafe extern "C" fn sys_get_framebuffer_info(info: *mut FramebufferInfo) -> c_int { if info.is_null() { return -1; }; @@ -31,7 +33,7 @@ pub unsafe extern "C" fn sys_framebuffer(info: *mut FramebufferInfo) -> c_int { match bga_info { Some(bga_info) => { let info_c = FramebufferInfo { - framebuffer: bga_info.framebuffer, + framebuffer: core::ptr::with_exposed_provenance_mut(bga_info.framebuffer), width: u32::from(bga_info.width), height: u32::from(bga_info.height), bpp: u32::from(bga_info.bpp),