From c33c37b59361aaf6b188edb9dfab2e3cd88db3c4 Mon Sep 17 00:00:00 2001 From: Zhe Tang Date: Sat, 22 Nov 2025 14:24:38 +0000 Subject: [PATCH] Add the basic framework of /dev/fb0 Co-authored-by: Wei Zhang --- kernel/comps/framebuffer/src/console.rs | 6 +- kernel/comps/framebuffer/src/framebuffer.rs | 12 +-- kernel/src/device/fb.rs | 86 +++++++++++++++++++++ kernel/src/fs/file_handle.rs | 1 - kernel/src/fs/utils/ioctl.rs | 14 ++++ 5 files changed, 109 insertions(+), 10 deletions(-) create mode 100644 kernel/src/device/fb.rs diff --git a/kernel/comps/framebuffer/src/console.rs b/kernel/comps/framebuffer/src/console.rs index df0320f67..95fb8f5e2 100644 --- a/kernel/comps/framebuffer/src/console.rs +++ b/kernel/comps/framebuffer/src/console.rs @@ -8,7 +8,7 @@ use aster_console::{ AnyConsoleDevice, ConsoleCallback, ConsoleSetFontError, }; use ostd::{ - mm::VmReader, + mm::{HasSize, VmReader}, sync::{LocalIrqDisabled, SpinLock}, }; use spin::Once; @@ -108,7 +108,7 @@ impl FramebufferConsole { font: BitmapFont::new_basic8x8(), is_output_enabled: true, - bytes: alloc::vec![0u8; framebuffer.size()], + bytes: alloc::vec![0u8; framebuffer.io_mem().size()], backend: framebuffer, }; @@ -195,7 +195,7 @@ impl ConsoleState { fn shift_lines_up(&mut self) { let offset = self.backend.calc_offset(0, self.font.height()).as_usize(); self.bytes.copy_within(offset.., 0); - self.bytes[self.backend.size() - offset..].fill(0); + self.bytes[self.backend.io_mem().size() - offset..].fill(0); if self.is_output_enabled { self.backend.write_bytes_at(0, &self.bytes).unwrap(); diff --git a/kernel/comps/framebuffer/src/framebuffer.rs b/kernel/comps/framebuffer/src/framebuffer.rs index 962a79e6d..090c76e98 100644 --- a/kernel/comps/framebuffer/src/framebuffer.rs +++ b/kernel/comps/framebuffer/src/framebuffer.rs @@ -84,11 +84,6 @@ pub(crate) fn init() { } impl FrameBuffer { - /// Returns the size of the framebuffer in bytes. - pub fn size(&self) -> usize { - self.io_mem.size() - } - /// Returns the width of the framebuffer in pixels. pub fn width(&self) -> usize { self.width @@ -99,6 +94,11 @@ impl FrameBuffer { self.height } + /// Returns a reference to the `IoMem` instance of the framebuffer. + pub fn io_mem(&self) -> &IoMem { + &self.io_mem + } + /// Returns the pixel format of the framebuffer. pub fn pixel_format(&self) -> PixelFormat { self.pixel_format @@ -129,7 +129,7 @@ impl FrameBuffer { /// Clears the framebuffer with default color (black). pub fn clear(&self) { - let frame = alloc::vec![0u8; self.size()]; + let frame = alloc::vec![0u8; self.io_mem().size()]; self.write_bytes_at(0, &frame).unwrap(); } } diff --git a/kernel/src/device/fb.rs b/kernel/src/device/fb.rs new file mode 100644 index 000000000..999ba9fca --- /dev/null +++ b/kernel/src/device/fb.rs @@ -0,0 +1,86 @@ +// SPDX-License-Identifier: MPL-2.0 + +use alloc::sync::Arc; + +use aster_framebuffer::{ColorMapEntry, FrameBuffer, PixelFormat, FRAMEBUFFER, MAX_CMAP_SIZE}; +use device_id::{DeviceId, MajorId, MinorId}; +use ostd::{ + mm::{io_util::HasVmReaderWriter, HasPaddr, HasSize}, + Pod, +}; + +use super::char::{self, CharDevice, DevtmpfsName}; +use crate::{ + current_userspace, + events::IoEvents, + fs::{ + file_handle::Mappable, + inode_handle::FileIo, + utils::{InodeIo, IoctlCmd, StatusFlags}, + }, + prelude::*, + process::signal::{PollHandle, Pollable}, +}; + +#[derive(Debug)] +struct Fb; + +#[derive(Debug)] +struct FbHandle { + framebuffer: Arc, +} + +impl Pollable for FbHandle { + fn poll(&self, mask: IoEvents, _poller: Option<&mut PollHandle>) -> IoEvents { + let events = IoEvents::IN | IoEvents::OUT; + events & mask + } +} + +impl InodeIo for FbHandle { + fn read_at( + &self, + offset: usize, + writer: &mut VmWriter, + _status_flags: StatusFlags, + ) -> Result { + } + + fn write_at( + &self, + offset: usize, + reader: &mut VmReader, + _status_flags: StatusFlags, + ) -> Result { + } +} + +impl FileIo for FbHandle { + fn check_seekable(&self) -> Result<()> { + Ok(()) + } + + fn is_offset_aware(&self) -> bool { + true + } + + fn mappable(&self) -> Result { + let iomem = self.framebuffer.io_mem(); + Ok(Mappable::IoMem(iomem.clone())) + } + + fn ioctl(&self, cmd: IoctlCmd, arg: usize) -> Result { + match cmd { + _ => { + log::debug!( + "the ioctl command {:?} is not supported by framebuffer devices", + cmd + ); + return_errno_with_message!( + Errno::ENOTTY, + "the ioctl command is not supported by framebuffer devices" + ) + } + } + } +} diff --git a/kernel/src/fs/file_handle.rs b/kernel/src/fs/file_handle.rs index 9182c381a..a0524e36b 100644 --- a/kernel/src/fs/file_handle.rs +++ b/kernel/src/fs/file_handle.rs @@ -156,6 +156,5 @@ pub enum Mappable { /// An inode object. Inode(Arc), /// An MMIO region. - #[expect(dead_code)] IoMem(IoMem), } diff --git a/kernel/src/fs/utils/ioctl.rs b/kernel/src/fs/utils/ioctl.rs index 713a57518..bdfaa6681 100644 --- a/kernel/src/fs/utils/ioctl.rs +++ b/kernel/src/fs/utils/ioctl.rs @@ -58,4 +58,18 @@ pub enum IoctlCmd { KDSKBMODE = 0x4B45, /// Get tdx report using TDCALL TDXGETREPORT = 0xc4405401, + /// Get variable screen information (resolution, color depth, etc.) + GETVSCREENINFO = 0x4600, + /// Set variable screen information + PUTVSCREENINFO = 0x4601, + /// Get fixed screen information (memory layout, line length, etc.) + GETFSCREENINFO = 0x4602, + /// Get framebuffer color map + GETCMAP = 0x4604, + /// Set framebuffer color map + PUTCMAP = 0x4605, + /// Pan display to show different part of virtual screen + PANDISPLAY = 0x4606, + /// Blank or unblank the framebuffer display + FBIOBLANK = 0x4611, }