完成与Linux兼容的Ntty (#517)

* 已经完成的功能:
- 写:printf能够正常在tty输出
- 读:与键盘驱动接上
- 信号: 能够正常通过ctrl向前台进程发送信号

* 支持目前的shell,改动printk使其与新版tty兼容。

* 删除原有tty文件夹,并更改新tty文件名

* 添加clear清屏程序

* 实现tty部分ioctl,更改部分问题
This commit is contained in:
GnoCiYeH
2024-02-26 15:27:19 +08:00
committed by GitHub
parent 9993c0fc61
commit 52da9a5937
62 changed files with 8843 additions and 928 deletions

View File

@ -0,0 +1 @@

View File

@ -0,0 +1,787 @@
use alloc::{sync::Arc, vec::Vec};
use system_error::SystemError;
use crate::{
driver::{
tty::{
console::ConsoleSwitch,
virtual_terminal::{
virtual_console::{CursorOperation, ScrollDir, VcCursor, VirtualConsoleData},
Color,
},
},
video::fbdev::base::{
CopyAreaData, FbCursor, FbCursorSetMode, FbImage, FbVisual, FillRectData, FillRectROP,
FrameBuffer, ScrollMode, FRAME_BUFFER_SET,
},
},
libs::{
font::FontDesc,
spinlock::{SpinLock, SpinLockGuard},
},
};
use super::{FbConAttr, FrameBufferConsole, FrameBufferConsoleData};
#[derive(Debug)]
pub struct BlittingFbConsole {
fb: SpinLock<Option<Arc<dyn FrameBuffer>>>,
fbcon_data: SpinLock<FrameBufferConsoleData>,
}
unsafe impl Send for BlittingFbConsole {}
unsafe impl Sync for BlittingFbConsole {}
impl BlittingFbConsole {
pub fn new() -> Result<Self, SystemError> {
Ok(Self {
fb: SpinLock::new(None),
fbcon_data: SpinLock::new(FrameBufferConsoleData::default()),
})
}
pub fn fb(&self) -> Arc<dyn FrameBuffer> {
self.fb.lock().clone().unwrap()
}
pub fn get_color(&self, vc_data: &VirtualConsoleData, c: u16, is_fg: bool) -> u32 {
let fb_info = self.fb();
let mut color = 0;
let depth = fb_info.color_depth();
if depth != 1 {
if is_fg {
let fg_shift = if vc_data.hi_font_mask != 0 { 9 } else { 8 };
color = (c as u32 >> fg_shift) & 0x0f
} else {
let bg_shift = if vc_data.hi_font_mask != 0 { 13 } else { 12 };
color = (c as u32 >> bg_shift) & 0x0f
}
}
match depth {
1 => {
let col = self.mono_color();
let fg;
let bg;
if fb_info.current_fb_fix().visual != FbVisual::Mono01 {
fg = col;
bg = 0;
} else {
fg = 0;
bg = col;
}
color = if is_fg { fg } else { bg };
}
2 => {
/*
颜色深度为2即16色
将16色的颜色值映射到4色的灰度
其中颜色0映射为黑色颜色1到6映射为白色
颜色7到8映射为灰色其他颜色映射为强烈的白色。
*/
if color >= 1 && color <= 6 {
// 白色
color = 2;
} else if color >= 7 && color <= 8 {
// 灰色
color = 1;
} else {
// 强白
color = 3;
}
}
3 => {
/*
颜色深度为3即256色仅保留颜色的低3位即颜色 0 到 7
*/
color &= 7;
}
_ => {}
}
color
}
/// ## 计算单色调的函数
pub fn mono_color(&self) -> u32 {
let fb_info = self.fb();
let mut max_len = fb_info
.current_fb_var()
.green
.length
.max(fb_info.current_fb_var().red.length);
max_len = max_len.max(fb_info.current_fb_var().blue.length);
return (!(0xfff << max_len)) & 0xff;
}
pub fn bit_put_string(
&self,
vc_data: &VirtualConsoleData,
buf: &[u16],
attr: FbConAttr,
cnt: u32,
cellsize: u32,
image: &mut FbImage,
) {
let charmask = if vc_data.hi_font_mask != 0 {
0x1ff
} else {
0xff
};
let mut offset;
let image_line_byte = image.width as usize / 8;
let byte_width = vc_data.font.width as usize / 8;
let font_height = vc_data.font.height as usize;
// let mut char_offset = 0;
for char_offset in 0..cnt as usize {
// 在字符表中的index
let ch = buf[char_offset] & charmask;
// 计算出在font表中的偏移量
let font_offset = ch as usize * cellsize as usize;
let font_offset_end = font_offset + cellsize as usize;
// 设置image的data
let src = &vc_data.font.data[font_offset..font_offset_end];
let mut dst = Vec::new();
dst.resize(src.len(), 0);
dst.copy_from_slice(src);
if !attr.is_empty() {
attr.update_attr(&mut dst, src, vc_data)
}
offset = char_offset * byte_width;
let mut dst_offset = 0;
for _ in 0..font_height {
let dst_offset_next = dst_offset + byte_width;
image.data[offset..offset + byte_width]
.copy_from_slice(&dst[dst_offset..dst_offset_next]);
offset += image_line_byte;
dst_offset = dst_offset_next;
}
}
self.fb().fb_image_blit(image);
}
}
impl ConsoleSwitch for BlittingFbConsole {
fn con_init(
&self,
vc_data: &mut VirtualConsoleData,
init: bool,
) -> Result<(), system_error::SystemError> {
let fb_set_guard = FRAME_BUFFER_SET.read();
let fb = fb_set_guard.get(vc_data.index);
if fb.is_none() {
return Err(SystemError::EINVAL);
}
let fb = fb.unwrap();
if fb.is_none() {
panic!(
"The Framebuffer with FbID {} has not been initialized yet.",
vc_data.index
)
}
let fb = fb.as_ref().unwrap().clone();
if init {
// 初始化字体
let var = fb.current_fb_var();
let font = FontDesc::get_default_font(var.xres, var.yres, 0, 0);
vc_data.font.data = font.data.to_vec();
vc_data.font.width = font.width;
vc_data.font.height = font.height;
vc_data.font.count = font.char_count;
} else {
kwarn!("The frontend Framebuffer is not implemented");
}
vc_data.color_mode = fb.color_depth() != 1;
vc_data.complement_mask = if vc_data.color_mode { 0x7700 } else { 0x0800 };
if vc_data.font.count == 256 {
// ascii
vc_data.hi_font_mask = 0;
} else {
vc_data.hi_font_mask = 0x100;
if vc_data.color_mode {
vc_data.complement_mask <<= 1;
}
}
// TODO: 考虑rotate
if init {
vc_data.cols = (fb.current_fb_var().xres / vc_data.font.width) as usize;
vc_data.rows = (fb.current_fb_var().yres / vc_data.font.height) as usize;
vc_data.pos = vc_data.state.x + vc_data.state.y * vc_data.cols;
let new_size = vc_data.cols * vc_data.rows;
vc_data.screen_buf.resize(new_size, 0);
} else {
unimplemented!("Resize is not supported at the moment!");
}
// 初始化fb
*self.fb.lock() = Some(fb);
Ok(())
}
fn con_deinit(&self) -> Result<(), system_error::SystemError> {
todo!()
}
fn con_clear(
&self,
vc_data: &mut VirtualConsoleData,
sy: usize,
sx: usize,
height: usize,
width: usize,
) -> Result<(), system_error::SystemError> {
let fb_data = self.fbcon_data();
if height == 0 || width == 0 {
return Ok(());
}
let y_break = (fb_data.display.virt_rows - fb_data.display.yscroll) as usize;
if sy < y_break && sy + height - 1 >= y_break {
// 分两次clear
let b = y_break - sy;
let _ = self.clear(
&vc_data,
fb_data.display.real_y(sy as u32),
sx as u32,
b as u32,
width as u32,
);
let _ = self.clear(
&vc_data,
fb_data.display.real_y((sy + b) as u32),
sx as u32,
(height - b) as u32,
width as u32,
);
} else {
let _ = self.clear(
&vc_data,
fb_data.display.real_y(sy as u32),
sx as u32,
height as u32,
width as u32,
);
}
Ok(())
}
fn con_putc(
&self,
vc_data: &VirtualConsoleData,
ch: u16,
xpos: u32,
ypos: u32,
) -> Result<(), system_error::SystemError> {
self.con_putcs(vc_data, &[ch], 1, ypos, xpos)
}
fn con_putcs(
&self,
vc_data: &VirtualConsoleData,
buf: &[u16],
count: usize,
ypos: u32,
xpos: u32,
) -> Result<(), SystemError> {
if count == 0 {
return Ok(());
}
let fbcon_data = self.fbcon_data();
let c = buf[0];
self.put_string(
vc_data,
buf,
count as u32,
fbcon_data.display.real_y(ypos),
xpos,
self.get_color(vc_data, c, true),
self.get_color(vc_data, c, false),
)
}
fn con_getxy(
&self,
vc_data: &VirtualConsoleData,
pos: usize,
) -> Result<(usize, usize, usize), SystemError> {
if pos < vc_data.screen_buf.len() {
let x = pos % vc_data.cols;
let y = pos / vc_data.cols;
let mut next_line_start = pos + (vc_data.cols - x);
if next_line_start >= vc_data.screen_buf.len() {
next_line_start = 0
}
return Ok((next_line_start, x, y));
} else {
return Ok((0, 0, 0));
}
}
fn con_cursor(
&self,
vc_data: &VirtualConsoleData,
op: crate::driver::tty::virtual_terminal::virtual_console::CursorOperation,
) {
let mut fbcon_data = self.fbcon_data();
let c = vc_data.screen_buf[vc_data.pos];
if vc_data.cursor_type.contains(VcCursor::CUR_SW) {
// 取消硬光标Timer但是现在没有硬光标先写在这
} else {
// 添加硬光标Timer
}
fbcon_data.cursor_flash = op != CursorOperation::Erase;
drop(fbcon_data);
self.cursor(
vc_data,
op,
self.get_color(vc_data, c, true),
self.get_color(vc_data, c, false),
);
}
fn con_set_palette(
&self,
vc_data: &VirtualConsoleData,
color_table: &[u8],
) -> Result<(), SystemError> {
let fb_info = self.fb();
let depth = fb_info.color_depth();
let mut palette = Vec::new();
palette.resize(16, Color::default());
if depth > 3 {
let vc_palette = &vc_data.palette;
for i in 0..16 {
let idx = color_table[i];
let col = palette.get_mut(idx as usize).unwrap();
col.red = (vc_palette[i].red << 8) | vc_palette[i].red;
col.green = (vc_palette[i].green << 8) | vc_palette[i].green;
col.blue = (vc_palette[i].blue << 8) | vc_palette[i].blue;
}
} else {
todo!()
}
self.fb().set_color_map(palette)?;
Ok(())
}
fn con_scroll(
&self,
vc_data: &mut VirtualConsoleData,
top: usize,
bottom: usize,
dir: crate::driver::tty::virtual_terminal::virtual_console::ScrollDir,
mut count: usize,
) -> bool {
self.con_cursor(vc_data, CursorOperation::Erase);
let fbcon_data = self.fbcon_data();
let scroll_mode = fbcon_data.display.scroll_mode;
drop(fbcon_data);
match dir {
ScrollDir::Up => {
if count > vc_data.rows {
count = vc_data.rows;
}
match scroll_mode {
ScrollMode::Move => {
let start = top * vc_data.cols;
let end = bottom * vc_data.cols;
vc_data.screen_buf[start..end].rotate_left(count * vc_data.cols);
let _ = self.bmove(
vc_data,
top as i32,
0,
top as i32 - count as i32,
0,
(bottom - top) as u32,
vc_data.cols as u32,
);
let _ = self.con_clear(vc_data, bottom - count, 0, count, vc_data.cols);
let offset = vc_data.cols * (bottom - count);
for i in
vc_data.screen_buf[offset..(offset + (vc_data.cols * count))].iter_mut()
{
*i = vc_data.erase_char;
}
return true;
}
ScrollMode::PanMove => todo!(),
ScrollMode::WrapMove => todo!(),
ScrollMode::Redraw => {
let start = top * vc_data.cols;
let end = bottom * vc_data.cols;
vc_data.screen_buf[start..end].rotate_left(count * vc_data.cols);
let data = &vc_data.screen_buf[start..(bottom - count) * vc_data.cols];
for line in top..(bottom - count) {
let mut start = line * vc_data.cols;
let end = start + vc_data.cols;
let mut offset = start;
let mut attr = 1;
let mut x = 0;
while offset < end {
let c = data[offset];
if attr != c & 0xff00 {
// 属性变化,输出完上一个的并且更新属性
attr = c & 0xff00;
let count = offset - start;
let _ = self.con_putcs(
vc_data,
&data[start..offset],
count,
line as u32,
x,
);
start = offset;
x += count as u32;
}
offset += 1;
}
let _ = self.con_putcs(
vc_data,
&data[start..offset],
offset - start,
line as u32,
x,
);
}
let _ = self.con_clear(vc_data, bottom - count, 0, count, vc_data.cols);
let offset = vc_data.cols * (bottom - count);
for i in
vc_data.screen_buf[offset..(offset + (vc_data.cols * count))].iter_mut()
{
*i = vc_data.erase_char;
}
return true;
}
ScrollMode::PanRedraw => todo!(),
}
}
ScrollDir::Down => {
if count > vc_data.rows {
count = vc_data.rows;
}
match scroll_mode {
ScrollMode::Move => todo!(),
ScrollMode::PanMove => todo!(),
ScrollMode::WrapMove => todo!(),
ScrollMode::Redraw => {
// self.scroll_redraw(
// vc_data,
// bottom - 1,
// bottom - top - count,
// count * vc_data.cols,
// false,
// );
let _ = self.con_clear(vc_data, top, 0, count, vc_data.cols);
let offset = vc_data.cols * top;
for i in
vc_data.screen_buf[offset..(offset + (vc_data.cols * count))].iter_mut()
{
*i = vc_data.erase_char;
}
return true;
}
ScrollMode::PanRedraw => todo!(),
}
}
}
}
}
impl FrameBufferConsole for BlittingFbConsole {
fn bmove(
&self,
vc_data: &VirtualConsoleData,
sy: i32,
sx: i32,
dy: i32,
dx: i32,
height: u32,
width: u32,
) -> Result<(), SystemError> {
let area = CopyAreaData::new(
dx * vc_data.font.width as i32,
dy * vc_data.font.height as i32,
width * vc_data.font.width,
height * vc_data.font.height,
sx * vc_data.font.width as i32,
sy * vc_data.font.height as i32,
);
self.fb().fb_copyarea(area)
}
fn clear(
&self,
vc_data: &VirtualConsoleData,
sy: u32,
sx: u32,
height: u32,
width: u32,
) -> Result<(), SystemError> {
let region = FillRectData::new(
sx * vc_data.font.width,
sy * vc_data.font.height,
width * vc_data.font.width,
height * vc_data.font.height,
self.get_color(vc_data, vc_data.erase_char, false),
FillRectROP::Copy,
);
self.fb().fb_fillrect(region)?;
Ok(())
}
fn put_string(
&self,
vc_data: &VirtualConsoleData,
data: &[u16],
mut count: u32,
y: u32,
x: u32,
fg: u32,
bg: u32,
) -> Result<(), SystemError> {
// 向上取整
let width = (vc_data.font.width + 7) / 8;
let cellsize = width * vc_data.font.height;
let fb_info = self.fb();
// 一次能输出的最大字数,避免帧缓冲区溢出
let max_cnt = (fb_info.current_fb_var().xres * fb_info.current_fb_var().yres) / cellsize;
let attr = FbConAttr::get_attr(data[0], fb_info.color_depth());
let mut image = FbImage {
x: x * vc_data.font.width,
y: y * vc_data.font.height,
width: 0,
height: vc_data.font.height,
fg,
bg,
depth: 1,
data: Default::default(),
};
image.data.resize(cellsize as usize * count as usize, 0);
while count > 0 {
let cnt = count.min(max_cnt);
image.width = vc_data.font.width * cnt;
self.bit_put_string(vc_data, data, attr, cnt, cellsize, &mut image);
image.x += cnt * vc_data.font.width;
count -= cnt;
}
Ok(())
}
fn fbcon_data(&self) -> SpinLockGuard<super::FrameBufferConsoleData> {
self.fbcon_data.lock()
}
fn cursor(&self, vc_data: &VirtualConsoleData, op: CursorOperation, fg: u32, bg: u32) {
let mut fbcon_data = self.fbcon_data();
let fb_info = self.fb();
let mut cursor = FbCursor::default();
let charmask = if vc_data.hi_font_mask != 0 {
0x1ff
} else {
0xff
};
// 向上取整
let w = (vc_data.font.width + 7) / 8;
let y = fbcon_data.display.real_y(vc_data.state.y as u32);
let c = vc_data.screen_buf[vc_data.pos];
let attr = FbConAttr::get_attr(c, fb_info.color_depth());
let char_offset = (c as usize & charmask) * ((w * vc_data.font.height) as usize);
if fbcon_data.cursor_state.image.data != &vc_data.font.data[char_offset..]
|| fbcon_data.cursor_reset
{
fbcon_data.cursor_state.image.data = vc_data.font.data[char_offset..].to_vec();
cursor.set_mode.insert(FbCursorSetMode::FB_CUR_SETIMAGE);
}
if !attr.is_empty() {
fbcon_data
.cursor_data
.resize(w as usize * vc_data.font.height as usize, 0);
attr.update_attr(
&mut fbcon_data.cursor_data,
&vc_data.font.data[char_offset..],
vc_data,
);
}
if fbcon_data.cursor_state.image.fg != fg
|| fbcon_data.cursor_state.image.bg != bg
|| fbcon_data.cursor_reset
{
fbcon_data.cursor_state.image.fg = fg;
fbcon_data.cursor_state.image.bg = bg;
cursor.set_mode.insert(FbCursorSetMode::FB_CUR_SETCMAP);
}
if fbcon_data.cursor_state.image.x != (vc_data.font.width * vc_data.state.x as u32)
|| fbcon_data.cursor_state.image.y != (vc_data.font.height * y)
|| fbcon_data.cursor_reset
{
fbcon_data.cursor_state.image.x = vc_data.font.width * vc_data.state.x as u32;
fbcon_data.cursor_state.image.y = vc_data.font.height * y;
cursor.set_mode.insert(FbCursorSetMode::FB_CUR_SETPOS);
}
if fbcon_data.cursor_state.image.height != vc_data.font.height
|| fbcon_data.cursor_state.image.width != vc_data.font.width
|| fbcon_data.cursor_reset
{
fbcon_data.cursor_state.image.height = vc_data.font.height;
fbcon_data.cursor_state.image.width = vc_data.font.width;
cursor.set_mode.insert(FbCursorSetMode::FB_CUR_SETSIZE);
}
if fbcon_data.cursor_state.hot_x > 0
|| fbcon_data.cursor_state.hot_y > 0
|| fbcon_data.cursor_reset
{
fbcon_data.cursor_state.hot_x = 0;
cursor.hot_y = 0;
cursor.set_mode.insert(FbCursorSetMode::FB_CUR_SETHOT);
}
if cursor.set_mode.contains(FbCursorSetMode::FB_CUR_SETSIZE)
|| vc_data.cursor_type != fbcon_data.display.cursor_shape
|| fbcon_data.cursor_state.mask.is_empty()
|| fbcon_data.cursor_reset
{
fbcon_data.display.cursor_shape = vc_data.cursor_type;
cursor.set_mode.insert(FbCursorSetMode::FB_CUR_SETSHAPE);
let cur_height;
match fbcon_data.display.cursor_shape.cursor_size() {
VcCursor::CUR_NONE => {
cur_height = 0;
}
VcCursor::CUR_UNDERLINE => {
if vc_data.font.height < 10 {
cur_height = 1;
} else {
cur_height = 2;
}
}
VcCursor::CUR_LOWER_THIRD => {
cur_height = vc_data.font.height / 3;
}
VcCursor::CUR_LOWER_HALF => {
cur_height = vc_data.font.height >> 1;
}
VcCursor::CUR_TWO_THIRDS => {
cur_height = (vc_data.font.height << 1) / 3;
}
_ => {
cur_height = vc_data.font.height;
}
}
// 表示空白部分
let mut size = (vc_data.font.height - cur_height) * w;
while size > 0 {
size -= 1;
fbcon_data.cursor_state.mask.push(0x00);
}
size = cur_height * w;
// 表示光标显示部分
while size > 0 {
size -= 1;
fbcon_data.cursor_state.mask.push(0xff);
}
}
match op {
CursorOperation::Erase => {
fbcon_data.cursor_state.enable = false;
}
_ => {
fbcon_data.cursor_state.enable = !vc_data.cursor_type.contains(VcCursor::CUR_SW);
}
}
if !attr.is_empty() {
cursor.image.data = fbcon_data.cursor_data.clone();
} else {
cursor.image.data = vc_data.font.data
[char_offset..char_offset + (w as usize * vc_data.font.height as usize)]
.to_vec();
}
cursor.image.fg = fbcon_data.cursor_state.image.fg;
cursor.image.bg = fbcon_data.cursor_state.image.bg;
cursor.image.x = fbcon_data.cursor_state.image.x;
cursor.image.y = fbcon_data.cursor_state.image.y;
cursor.image.height = fbcon_data.cursor_state.image.height;
cursor.image.width = fbcon_data.cursor_state.image.width;
cursor.hot_x = fbcon_data.cursor_state.hot_x;
cursor.hot_y = fbcon_data.cursor_state.hot_y;
cursor.mask = fbcon_data.cursor_state.mask.clone();
cursor.enable = fbcon_data.cursor_state.enable;
cursor.image.depth = 1;
cursor.rop = true;
if fb_info.fb_cursor(&cursor).is_err() {
let _ = fb_info.soft_cursor(cursor);
}
fbcon_data.cursor_reset = false;
}
}

View File

@ -1,15 +1,19 @@
use alloc::{
string::{String, ToString},
sync::{Arc, Weak},
vec::Vec,
};
use system_error::SystemError;
use crate::{
driver::base::{
class::Class,
device::{bus::Bus, device_manager, driver::Driver, Device, DeviceType, IdTable},
kobject::{KObjType, KObject, KObjectState, LockedKObjectState},
kset::KSet,
driver::{
base::{
class::Class,
device::{bus::Bus, device_manager, driver::Driver, Device, DeviceType, IdTable},
kobject::{KObjType, KObject, KObjectState, LockedKObjectState},
kset::KSet,
},
tty::virtual_terminal::virtual_console::{CursorOperation, VcCursor, VirtualConsoleData},
},
filesystem::{
kernfs::KernFSInode,
@ -18,11 +22,13 @@ use crate::{
},
libs::{
rwlock::{RwLockReadGuard, RwLockWriteGuard},
spinlock::SpinLock,
spinlock::{SpinLock, SpinLockGuard},
},
};
use super::fbmem::sys_class_graphics_instance;
use super::{fbmem::sys_class_graphics_instance, FbCursor, ScrollMode};
pub mod framebuffer_console;
/// framebuffer console设备管理器实例
static mut FB_CONSOLE_MANAGER: Option<FbConsoleManager> = None;
@ -332,3 +338,166 @@ impl Attribute for AttrCursorBlink {
todo!()
}
}
#[derive(Debug, Default)]
pub struct FrameBufferConsoleData {
/// 光标闪烁间隔
pub cursor_blink_jiffies: i64,
/// 是否刷新光标
pub cursor_flash: bool,
///
pub display: FbConsoleDisplay,
/// 光标状态
pub cursor_state: FbCursor,
/// 重设光标?
pub cursor_reset: bool,
/// cursor 位图数据
pub cursor_data: Vec<u8>,
}
pub trait FrameBufferConsole {
fn fbcon_data(&self) -> SpinLockGuard<FrameBufferConsoleData>;
/// ## 将位块移动到目标位置
/// 坐标均以字体为单位而不是pixel
/// ### 参数
/// ### sy: 起始位置的y坐标
/// ### sx: 起始位置的x坐标、
/// ### dy: 目标位置的y坐标
/// ### dx: 目标位置的x坐标
/// ### height: 位图高度
/// ### width: 位图宽度
fn bmove(
&self,
vc_data: &VirtualConsoleData,
sy: i32,
sx: i32,
dy: i32,
dx: i32,
height: u32,
width: u32,
) -> Result<(), SystemError>;
/// ## 清除位图
///
/// ### 参数
/// ### sy: 原位置的y坐标
/// ### sx: 原位置的x坐标、
/// ### height: 位图高度
/// ### width: 位图宽度
fn clear(
&self,
vc_data: &VirtualConsoleData,
sy: u32,
sx: u32,
height: u32,
width: u32,
) -> Result<(), SystemError>;
/// ## 显示字符串
///
/// ### 参数
/// ### y: 起始位置y坐标
/// ### x: 起始位置的x坐标、
/// ### fg: 前景色
/// ### bg: 背景色
fn put_string(
&self,
vc_data: &VirtualConsoleData,
data: &[u16],
count: u32,
y: u32,
x: u32,
fg: u32,
bg: u32,
) -> Result<(), SystemError>;
fn cursor(&self, vc_data: &VirtualConsoleData, op: CursorOperation, fg: u32, bg: u32);
}
/// 表示 framebuffer 控制台与低级帧缓冲设备之间接口的数据结构
#[derive(Debug, Default)]
pub struct FbConsoleDisplay {
/// 硬件滚动的行数
pub yscroll: u32,
/// 光标
pub cursor_shape: VcCursor,
/// 滚动模式
pub scroll_mode: ScrollMode,
virt_rows: u32,
}
impl FbConsoleDisplay {
pub fn real_y(&self, mut ypos: u32) -> u32 {
let rows = self.virt_rows;
ypos += self.yscroll;
if ypos < rows {
return ypos;
} else {
return ypos - rows;
}
}
}
bitflags! {
pub struct FbConAttr:u8 {
const UNDERLINE = 1;
const REVERSE = 2;
const BOLD = 4;
}
}
impl FbConAttr {
pub fn get_attr(c: u16, color_depth: u32) -> Self {
let mut attr = Self::empty();
if color_depth == 1 {
if Self::underline(c) {
attr.insert(Self::UNDERLINE);
}
if Self::reverse(c) {
attr.intersects(Self::REVERSE);
}
if Self::blod(c) {
attr.insert(Self::BOLD);
}
}
attr
}
pub fn update_attr(&self, dst: &mut [u8], src: &[u8], vc_data: &VirtualConsoleData) {
let mut offset = if vc_data.font.height < 10 { 1 } else { 2 } as usize;
let width = (vc_data.font.width + 7) / 8;
let cellsize = (vc_data.font.height * width) as usize;
// 大于offset的部分就是下划线
offset = cellsize - (offset * width as usize);
for i in 0..cellsize {
let mut c = src[i];
if self.contains(Self::UNDERLINE) && i >= offset {
// 下划线
c = 0xff;
}
if self.contains(Self::BOLD) {
c |= c >> 1;
}
if self.contains(Self::REVERSE) {
c = !c;
}
dst[i] = c;
}
}
pub fn underline(c: u16) -> bool {
c & 0x400 != 0
}
pub fn blod(c: u16) -> bool {
c & 0x200 != 0
}
pub fn reverse(c: u16) -> bool {
c & 0x800 != 0
}
}

View File

@ -1,13 +1,24 @@
use alloc::{string::String, sync::Arc};
use alloc::{string::String, sync::Arc, vec::Vec};
use system_error::SystemError;
use crate::{
driver::base::device::Device,
driver::{base::device::Device, tty::virtual_terminal::Color},
init::boot_params,
libs::rwlock::RwLock,
mm::{ucontext::LockedVMA, PhysAddr, VirtAddr},
};
use self::fbmem::{FbDevice, FrameBufferManager};
const COLOR_TABLE_8: &'static [u32] = &[
0x00000000, 0xff000000, 0x00ff0000, 0xffff0000, 0x0000ff00, 0xff00ff00, 0x00ffff00, 0xffffff00,
0x000000ff, 0xff0000ff, 0x00ff00ff, 0xffff00ff, 0x0000ffff, 0xff00ffff, 0x00ffffff, 0xffffffff,
];
const COLOR_TABLE_16: &'static [u32] = &[0x00000000, 0xffff0000, 0x0000ffff, 0xffffffff];
const COLOR_TABLE_32: &'static [u32] = &[0x00000000, 0xffffffff];
pub mod fbcon;
pub mod fbmem;
pub mod fbsysfs;
@ -16,6 +27,14 @@ pub mod modedb;
// 帧缓冲区id
int_like!(FbId, u32);
lazy_static! {
pub static ref FRAME_BUFFER_SET: RwLock<Vec<Option<Arc<dyn FrameBuffer>>>> = {
let mut ret = Vec::new();
ret.resize(FrameBufferManager::FB_MAX, None);
RwLock::new(ret)
};
}
impl FbId {
/// 帧缓冲区id的初始值无效值
pub const INIT: Self = Self::new(u32::MAX);
@ -37,10 +56,240 @@ pub trait FrameBuffer: FrameBufferInfo + FrameBufferOps + Device {
/// 设置帧缓冲区的id
fn set_fb_id(&self, id: FbId);
/// 通用的软件图像绘画
fn generic_imageblit(&self, image: &FbImage) {
let boot_param = boot_params().read();
let x = image.x;
let y = image.y;
let byte_per_pixel = core::mem::size_of::<u32>() as u32;
let bit_per_pixel = self.current_fb_var().bits_per_pixel;
// 计算图像在帧缓冲中的起始位
let mut bitstart = (y * self.current_fb_fix().line_length * 8) + (x * bit_per_pixel);
let start_index = bitstart & (32 - 1);
let pitch_index = (self.current_fb_fix().line_length & (byte_per_pixel - 1)) * 8;
// 位转字节
bitstart /= 8;
// 对齐到像素字节大小
bitstart &= !(byte_per_pixel - 1);
let dst1 = boot_param.screen_info.lfb_virt_base;
if dst1.is_none() {
return;
}
let mut dst1 = dst1.unwrap();
dst1 = dst1 + VirtAddr::new(bitstart as usize);
let _ = self.fb_sync();
if image.depth == 1 {
let fg;
let bg;
if self.current_fb_fix().visual == FbVisual::TrueColor
|| self.current_fb_fix().visual == FbVisual::DirectColor
{
let fb_info_data = self.framebuffer_info_data().read();
fg = fb_info_data.pesudo_palette[image.fg as usize];
bg = fb_info_data.pesudo_palette[image.bg as usize];
} else {
fg = image.fg;
bg = image.bg;
}
if 32 % bit_per_pixel == 0
&& start_index == 0
&& pitch_index == 0
&& image.width & (32 / bit_per_pixel - 1) == 0
&& bit_per_pixel >= 8
&& bit_per_pixel <= 32
{
unsafe { self.fast_imageblit(image, dst1, fg, bg) }
} else {
self.slow_imageblit(image, dst1, fg, bg, start_index, pitch_index)
}
} else {
todo!("color image blit todo");
}
}
/// 优化的单色图像绘制函数
///
/// 仅当 bits_per_pixel 为 8、16 或 32 时才能使用。
/// 要求 image->width 可以被像素或 dword (ppw) 整除。
/// 要求 fix->line_length 可以被 4 整除。
/// 扫描线的开始和结束都是 dword 对齐的。
unsafe fn fast_imageblit(&self, image: &FbImage, mut dst1: VirtAddr, fg: u32, bg: u32) {
let bpp = self.current_fb_var().bits_per_pixel;
let mut fgx = fg;
let mut bgx = bg;
let ppw = 32 / bpp;
let spitch = (image.width + 7) / 8;
let tab: &[u32];
let mut color_tab: [u32; 16] = [0; 16];
match bpp {
8 => {
tab = COLOR_TABLE_8;
}
16 => {
tab = COLOR_TABLE_16;
}
32 => {
tab = COLOR_TABLE_32;
}
_ => {
return;
}
}
for _ in (0..(ppw - 1)).rev() {
fgx <<= bpp;
bgx <<= bpp;
fgx |= fg;
bgx |= bg;
}
let bitmask = (1 << ppw) - 1;
let eorx = fgx ^ bgx;
let k = image.width / ppw;
for (idx, val) in tab.iter().enumerate() {
color_tab[idx] = (*val & eorx) ^ bgx;
}
let mut dst;
let mut shift;
let mut src;
let mut offset = 0;
let mut j = 0;
for _ in (0..image.height).rev() {
dst = dst1.as_ptr::<u32>();
shift = 8;
src = offset;
match ppw {
4 => {
// 8bpp
j = k;
while j >= 2 {
*dst = color_tab[(image.data[src] as usize >> 4) & bitmask];
dst = dst.add(1);
*dst = color_tab[(image.data[src] as usize >> 0) & bitmask];
dst = dst.add(1);
j -= 2;
src += 1;
}
}
2 => {
// 16bpp
j = k;
while j >= 4 {
*dst = color_tab[(image.data[src] as usize >> 6) & bitmask];
dst = dst.add(1);
*dst = color_tab[(image.data[src] as usize >> 4) & bitmask];
dst = dst.add(1);
*dst = color_tab[(image.data[src] as usize >> 2) & bitmask];
dst = dst.add(1);
*dst = color_tab[(image.data[src] as usize >> 0) & bitmask];
dst = dst.add(1);
src += 1;
j -= 4;
}
}
1 => {
// 32 bpp
j = k;
while j >= 8 {
*dst = color_tab[(image.data[src] as usize >> 7) & bitmask];
dst = dst.add(1);
*dst = color_tab[(image.data[src] as usize >> 6) & bitmask];
dst = dst.add(1);
*dst = color_tab[(image.data[src] as usize >> 5) & bitmask];
dst = dst.add(1);
*dst = color_tab[(image.data[src] as usize >> 4) & bitmask];
dst = dst.add(1);
*dst = color_tab[(image.data[src] as usize >> 3) & bitmask];
dst = dst.add(1);
*dst = color_tab[(image.data[src] as usize >> 2) & bitmask];
dst = dst.add(1);
*dst = color_tab[(image.data[src] as usize >> 1) & bitmask];
dst = dst.add(1);
*dst = color_tab[(image.data[src] as usize >> 0) & bitmask];
dst = dst.add(1);
src += 1;
j -= 8;
}
}
_ => {}
}
while j != 0 {
shift -= ppw;
*dst = color_tab[(image.data[src] as usize >> shift) & bitmask];
dst = dst.add(1);
if shift == 0 {
shift = 8;
src += 1;
}
}
dst1 += VirtAddr::new(self.current_fb_fix().line_length as usize);
offset += spitch as usize;
}
}
fn slow_imageblit(
&self,
_image: &FbImage,
_dst1: VirtAddr,
_fg: u32,
_bg: u32,
_start_index: u32,
_pitch_index: u32,
) {
todo!();
// let bpp = self.current_fb_var().bits_per_pixel;
// let pitch = self.current_fb_fix().line_length;
// let null_bits = 32 - bpp;
// let spitch = (image.width + 7) / 8;
// // TODO这里是需要计算的但是目前用不到先直接写
// let bswapmask = 0;
// let dst2 = dst1;
// // 一行一行画
// for i in image.height..0 {
// let dst = dst1;
// if start_index > 0 {
// let start_mask = !(!(0 as u32) << start_index);
// }
// }
}
}
#[derive(Debug, Default)]
pub struct FrameBufferInfoData {
/// 颜色映射
pub color_map: Vec<Color>,
/// 颜色映射表
pub pesudo_palette: Vec<u32>,
}
impl FrameBufferInfoData {
pub fn new() -> Self {
Self {
..Default::default()
}
}
}
/// 帧缓冲区信息
pub trait FrameBufferInfo {
pub trait FrameBufferInfo: FrameBufferOps {
fn framebuffer_info_data(&self) -> &RwLock<FrameBufferInfoData>;
/// Amount of ioremapped VRAM or 0
fn screen_size(&self) -> usize;
@ -61,6 +310,54 @@ pub trait FrameBufferInfo {
/// 获取帧缓冲区的状态
fn state(&self) -> FbState;
/// 颜色位深
fn color_depth(&self) -> u32 {
return 8;
// 以下逻辑没问题但是当前没有初始化好var所以先直接返回当前vasafb的8
// let var = self.current_fb_var();
// let fix = self.current_fb_fix();
// if fix.visual == FbVisual::Mono01 || fix.visual == FbVisual::Mono10 {
// return 1;
// } else {
// if var.green.length == var.blue.length
// && var.green.length == var.red.length
// && var.green.offset == var.blue.offset
// && var.green.offset == var.red.offset
// {
// kerror!("return {}", var.green.length);
// return var.green.length;
// } else {
// return var.green.length + var.blue.length + var.red.length;
// }
// }
}
/// ## 设置调色板
fn set_color_map(&self, cmap: Vec<Color>) -> Result<(), SystemError> {
let ret = self.fb_set_color_map(cmap.clone());
if ret.is_err() && ret.clone().unwrap_err() == SystemError::ENOSYS {
for (idx, color) in cmap.iter().enumerate() {
if self
.fb_set_color_register(idx as u16, color.red, color.green, color.blue)
.is_err()
{
break;
}
}
self.framebuffer_info_data().write().color_map = cmap;
} else {
if ret.is_ok() {
self.framebuffer_info_data().write().color_map = cmap;
}
return ret;
}
Ok(())
}
}
/// 帧缓冲区操作
@ -122,6 +419,45 @@ pub trait FrameBufferOps {
/// 卸载与该帧缓冲区相关的所有资源
fn fb_destroy(&self);
/// 画光标
fn fb_cursor(&self, _cursor: &FbCursor) -> Result<(), SystemError> {
return Err(SystemError::ENOSYS);
}
/// 画软光标(暂时简要实现)
fn soft_cursor(&self, cursor: FbCursor) -> Result<(), SystemError> {
let mut image = cursor.image.clone();
if cursor.enable {
match cursor.rop {
true => {
for i in 0..image.data.len() {
image.data[i] ^= cursor.mask[i];
}
}
false => {
for i in 0..image.data.len() {
image.data[i] &= cursor.mask[i];
}
}
}
}
let _ = self.fb_image_blit(&image);
Ok(())
}
fn fb_sync(&self) -> Result<(), SystemError> {
return Err(SystemError::ENOSYS);
}
/// 绘画位图
fn fb_image_blit(&self, image: &FbImage);
fn fb_set_color_map(&self, _cmap: Vec<Color>) -> Result<(), SystemError> {
return Err(SystemError::ENOSYS);
}
}
/// 帧缓冲区的状态
@ -197,25 +533,27 @@ pub enum FillRectROP {
}
/// `CopyAreaData` 结构体用于表示一个矩形区域,并指定从哪个源位置复制数据。
///
/// 注意,源位置必须是有意义的(即包围的矩形都必须得在屏幕内)
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub struct CopyAreaData {
/// 目标矩形左上角的x坐标
pub dx: u32,
pub dx: i32,
/// 目标矩形左上角的y坐标
pub dy: u32,
pub dy: i32,
/// 矩形的宽度
pub width: u32,
/// 矩形的高度
pub height: u32,
/// 源矩形左上角的x坐标
pub sx: u32,
pub sx: i32,
/// 源矩形左上角的y坐标
pub sy: u32,
pub sy: i32,
}
impl CopyAreaData {
#[allow(dead_code)]
pub fn new(dx: u32, dy: u32, width: u32, height: u32, sx: u32, sy: u32) -> Self {
pub fn new(dx: i32, dy: i32, width: u32, height: u32, sx: i32, sy: i32) -> Self {
Self {
dx,
dy,
@ -850,3 +1188,72 @@ pub enum BootTimeVideoType {
/// EFI graphic mode
Efi,
}
#[derive(Debug, Default)]
pub struct FbCursor {
/// 设置选项
pub set_mode: FbCursorSetMode,
/// 开关选项
pub enable: bool,
/// 表示光标图像的位操作,true表示XORfalse表示COPY
pub rop: bool,
/// 表示光标掩码mask的数据。掩码用于定义光标的形状指定了哪些像素是光标的一部分。
pub mask: Vec<u8>,
/// 表示光标的热点位置,即在光标图像中被认为是"焦点"的位置
pub hot_x: u32,
pub hot_y: u32,
/// 光标图像
pub image: FbImage,
}
bitflags! {
/// 硬件光标控制
#[derive(Default)]
pub struct FbCursorSetMode:u8 {
/// 设置位图
const FB_CUR_SETIMAGE = 0x01;
/// 设置位置
const FB_CUR_SETPOS = 0x02;
/// 设置热点
const FB_CUR_SETHOT = 0x04;
/// ColorMap
const FB_CUR_SETCMAP = 0x08;
/// 形状
const FB_CUR_SETSHAPE = 0x10;
/// Size
const FB_CUR_SETSIZE = 0x20;
/// 全设置
const FB_CUR_SETALL = 0xFF;
}
}
#[allow(dead_code)]
#[derive(Debug, Clone, Copy)]
pub enum ScrollMode {
Move,
PanMove,
WrapMove,
Redraw,
PanRedraw,
}
impl Default for ScrollMode {
/// ## 默认Move
fn default() -> Self {
Self::Move
}
}
#[derive(Debug, Default, Clone)]
pub struct FbImage {
pub x: u32,
pub y: u32,
pub width: u32,
pub height: u32,
pub fg: u32,
pub bg: u32,
pub depth: u8,
pub data: Vec<u8>,
}

View File

@ -28,8 +28,8 @@ use crate::{
CompatibleTable,
},
},
tty::serial::serial8250::send_to_default_serial8250_port,
video::fbdev::base::{fbmem::frame_buffer_manager, FbVisual},
serial::serial8250::send_to_default_serial8250_port,
video::fbdev::base::{fbmem::frame_buffer_manager, FbVisual, FRAME_BUFFER_SET},
},
filesystem::{
kernfs::KernFSInode,
@ -56,7 +56,7 @@ use crate::{
use super::base::{
fbmem::FbDevice, BlankMode, BootTimeVideoType, FbAccel, FbActivateFlags, FbId, FbState, FbType,
FbVModeFlags, FbVarScreenInfo, FbVideoMode, FixedScreenInfo, FrameBuffer, FrameBufferInfo,
FrameBufferOps,
FrameBufferInfoData, FrameBufferOps,
};
/// 当前机器上面是否有vesa帧缓冲区
@ -89,11 +89,14 @@ lazy_static! {
pub struct VesaFb {
inner: SpinLock<InnerVesaFb>,
kobj_state: LockedKObjectState,
fb_data: RwLock<FrameBufferInfoData>,
}
impl VesaFb {
pub const NAME: &'static str = "vesa_vga";
pub fn new() -> Self {
let mut fb_info_data = FrameBufferInfoData::new();
fb_info_data.pesudo_palette.resize(256, 0);
return Self {
inner: SpinLock::new(InnerVesaFb {
bus: None,
@ -111,6 +114,7 @@ impl VesaFb {
fb_state: FbState::Suspended,
}),
kobj_state: LockedKObjectState::new(None),
fb_data: RwLock::new(fb_info_data),
};
}
}
@ -281,12 +285,46 @@ impl FrameBufferOps for VesaFb {
fn fb_set_color_register(
&self,
_regno: u16,
_red: u16,
_green: u16,
_blue: u16,
regno: u16,
mut red: u16,
mut green: u16,
mut blue: u16,
) -> Result<(), SystemError> {
todo!()
let mut fb_data = self.framebuffer_info_data().write();
let var = self.current_fb_var();
if regno as usize >= fb_data.pesudo_palette.len() {
return Err(SystemError::E2BIG);
}
if var.bits_per_pixel == 8 {
todo!("vesa_setpalette todo");
} else if regno < 16 {
match var.bits_per_pixel {
16 => {
if var.red.offset == 10 {
// RGB 1:5:5:5
fb_data.pesudo_palette[regno as usize] = ((red as u32 & 0xf800) >> 1)
| ((green as u32 & 0xf800) >> 6)
| ((blue as u32 & 0xf800) >> 11);
} else {
fb_data.pesudo_palette[regno as usize] = (red as u32 & 0xf800)
| ((green as u32 & 0xfc00) >> 5)
| ((blue as u32 & 0xf800) >> 11);
}
}
24 | 32 => {
red >>= 8;
green >>= 8;
blue >>= 8;
fb_data.pesudo_palette[regno as usize] = ((red as u32) << var.red.offset)
| ((green as u32) << var.green.offset)
| ((blue as u32) << var.blue.offset);
}
_ => {}
}
}
Ok(())
}
fn fb_blank(&self, _blank_mode: BlankMode) -> Result<(), SystemError> {
@ -338,6 +376,138 @@ impl FrameBufferOps for VesaFb {
return Ok(len);
}
fn fb_image_blit(&self, image: &super::base::FbImage) {
self.generic_imageblit(image);
}
/// ## 填充矩形
fn fb_fillrect(&self, rect: super::base::FillRectData) -> Result<(), SystemError> {
// kwarn!("rect {rect:?}");
let boot_param = boot_params().read();
let screen_base = boot_param
.screen_info
.lfb_virt_base
.ok_or(SystemError::ENODEV)?;
let fg;
if self.current_fb_fix().visual == FbVisual::TrueColor
|| self.current_fb_fix().visual == FbVisual::DirectColor
{
fg = self.fb_data.read().pesudo_palette[rect.color as usize];
} else {
fg = rect.color;
}
let bpp = self.current_fb_var().bits_per_pixel;
// 每行像素数
let line_offset = self.current_fb_var().xres;
match bpp {
32 => {
let base = screen_base.as_ptr::<u32>();
for y in rect.dy..(rect.dy + rect.height) {
for x in rect.dx..(rect.dx + rect.width) {
unsafe { *base.add((y * line_offset + x) as usize) = fg };
}
}
}
_ => todo!(),
}
Ok(())
}
fn fb_copyarea(&self, data: super::base::CopyAreaData) -> Result<(), SystemError> {
let bp = boot_params().read();
let base = bp.screen_info.lfb_virt_base.ok_or(SystemError::ENODEV)?;
let var = self.current_fb_var();
if data.sx < 0
|| data.sy < 0
|| data.sx as u32 > var.xres
|| data.sx as u32 + data.width > var.xres
|| data.sy as u32 > var.yres
|| data.sy as u32 + data.height > var.yres
{
return Err(SystemError::EINVAL);
}
let bytes_per_pixel = var.bits_per_pixel >> 3;
let bytes_per_line = var.xres * bytes_per_pixel;
let sy = data.sy as u32;
let sx = data.sx as u32;
let dst = {
let mut dst = base;
if data.dy < 0 {
dst -= VirtAddr::new((((-data.dy) as u32) * bytes_per_line) as usize);
} else {
dst += VirtAddr::new(((data.dy as u32) * bytes_per_line) as usize);
}
if data.dx > 0 && (data.dx as u32) < var.xres {
dst += VirtAddr::new(((data.dx as u32) * bytes_per_pixel) as usize);
}
dst
};
let src = base + VirtAddr::new((sy * bytes_per_line + sx * bytes_per_pixel) as usize);
match bytes_per_pixel {
4 => {
// 32bpp
let mut dst = dst.as_ptr::<u32>();
let mut src = src.as_ptr::<u32>();
for y in 0..data.height as usize {
if (data.dy + y as i32) < 0 || (data.dy + y as i32) > var.yres as i32 {
unsafe {
// core::ptr::copy(src, dst, data.width as usize);
src = src.add(var.xres as usize);
dst = dst.add(var.xres as usize);
}
continue;
}
if data.dx < 0 {
if ((-data.dx) as u32) < data.width {
unsafe {
core::ptr::copy(
src.add((-data.dx) as usize),
dst,
(data.width as usize) - (-data.dx) as usize,
);
src = src.add(var.xres as usize);
dst = dst.add(var.xres as usize);
}
}
} else if data.dx as u32 + data.width > var.xres {
if (data.dx as u32) < var.xres {
unsafe {
core::ptr::copy(src, dst, (var.xres - data.dx as u32) as usize);
src = src.add(var.xres as usize);
dst = dst.add(var.xres as usize);
}
}
} else {
for i in 0..data.width as usize {
unsafe { *(dst.add(i)) = *(src.add(i)) }
}
unsafe {
// core::ptr::copy(src, dst, data.width as usize);
src = src.add(var.xres as usize);
dst = dst.add(var.xres as usize);
}
}
}
}
_ => {
todo!()
}
}
Ok(())
}
}
impl FrameBufferInfo for VesaFb {
@ -368,6 +538,10 @@ impl FrameBufferInfo for VesaFb {
fn state(&self) -> FbState {
self.inner.lock().fb_state
}
fn framebuffer_info_data(&self) -> &RwLock<FrameBufferInfoData> {
&self.fb_data
}
}
#[derive(Debug)]
@ -679,36 +853,54 @@ fn vesa_fb_device_init() -> Result<(), SystemError> {
static INIT: Once = Once::new();
INIT.call_once(|| {
kinfo!("vesa fb device init");
let device = Arc::new(VesaFb::new());
let mut fix_info_guard = VESAFB_FIX_INFO.write_irqsave();
let mut var_info_guard = VESAFB_DEFINED.write_irqsave();
let mut fb_fix = VESAFB_FIX_INFO.write_irqsave();
let mut fb_var = VESAFB_DEFINED.write_irqsave();
let boot_params_guard = boot_params().read();
let boottime_screen_info = &boot_params_guard.screen_info;
fix_info_guard.smem_start = Some(boottime_screen_info.lfb_base);
fix_info_guard.smem_len = boottime_screen_info.lfb_size;
fb_fix.smem_start = Some(boottime_screen_info.lfb_base);
fb_fix.smem_len = boottime_screen_info.lfb_size;
if boottime_screen_info.video_type == BootTimeVideoType::Mda {
fix_info_guard.visual = FbVisual::Mono10;
var_info_guard.bits_per_pixel = 8;
fix_info_guard.line_length = (boottime_screen_info.origin_video_cols as u32)
* (var_info_guard.bits_per_pixel / 8);
var_info_guard.xres_virtual = boottime_screen_info.origin_video_cols as u32;
var_info_guard.yres_virtual = boottime_screen_info.origin_video_lines as u32;
fb_fix.visual = FbVisual::Mono10;
fb_var.bits_per_pixel = 8;
fb_fix.line_length =
(boottime_screen_info.origin_video_cols as u32) * (fb_var.bits_per_pixel / 8);
fb_var.xres_virtual = boottime_screen_info.origin_video_cols as u32;
fb_var.yres_virtual = boottime_screen_info.origin_video_lines as u32;
} else {
fix_info_guard.visual = FbVisual::TrueColor;
var_info_guard.bits_per_pixel = boottime_screen_info.lfb_depth as u32;
fix_info_guard.line_length =
(boottime_screen_info.lfb_width as u32) * (var_info_guard.bits_per_pixel / 8);
var_info_guard.xres_virtual = boottime_screen_info.lfb_width as u32;
var_info_guard.yres_virtual = boottime_screen_info.lfb_height as u32;
fb_fix.visual = FbVisual::TrueColor;
fb_var.bits_per_pixel = boottime_screen_info.lfb_depth as u32;
fb_fix.line_length =
(boottime_screen_info.lfb_width as u32) * (fb_var.bits_per_pixel / 8);
fb_var.xres_virtual = boottime_screen_info.lfb_width as u32;
fb_var.yres_virtual = boottime_screen_info.lfb_height as u32;
fb_var.xres = boottime_screen_info.lfb_width as u32;
fb_var.yres = boottime_screen_info.lfb_height as u32;
}
drop(var_info_guard);
drop(fix_info_guard);
fb_var.red.length = boottime_screen_info.red_size as u32;
fb_var.green.length = boottime_screen_info.green_size as u32;
fb_var.blue.length = boottime_screen_info.blue_size as u32;
fb_var.red.offset = boottime_screen_info.red_pos as u32;
fb_var.green.offset = boottime_screen_info.green_pos as u32;
fb_var.blue.offset = boottime_screen_info.blue_pos as u32;
// TODO: 这里是暂时这样写的初始化为RGB888格式后续vesa初始化完善后删掉下面
fb_var.red.offset = 16;
fb_var.green.offset = 8;
fb_var.blue.offset = 0;
if fb_var.bits_per_pixel >= 1 && fb_var.bits_per_pixel <= 8 {
fb_var.red.length = fb_var.bits_per_pixel;
fb_var.green.length = fb_var.bits_per_pixel;
fb_var.blue.length = fb_var.bits_per_pixel;
}
let device = Arc::new(VesaFb::new());
device_manager().device_default_initialize(&(device.clone() as Arc<dyn Device>));
platform_device_manager()
@ -719,6 +911,16 @@ fn vesa_fb_device_init() -> Result<(), SystemError> {
.register_fb(device.clone() as Arc<dyn FrameBuffer>)
.expect("vesa_fb_device_init: frame_buffer_manager().register_fb failed");
// 加入全局fb表
let mut guard = FRAME_BUFFER_SET.write();
if guard.get(device.fb_id().data() as usize).unwrap().is_some() {
kwarn!(
"vesa_fb_device_init: There is already an element {:?} in the FRAME_BUFFER_SET",
device.fb_id()
);
}
guard[device.fb_id().data() as usize] = Some(device.clone());
// 设置vesa fb的状态为运行中
device.inner.lock().fb_state = FbState::Running;
});

View File

@ -2,7 +2,6 @@ use core::sync::atomic::{AtomicBool, Ordering};
use crate::{
arch::MMArch,
driver::tty::serial::serial8250::send_to_default_serial8250_port,
init::boot_params,
kinfo,
libs::{
@ -176,7 +175,10 @@ impl VideoRefreshManager {
pub unsafe fn video_init() -> Result<(), SystemError> {
use crate::{
arch::driver::video::arch_video_early_init,
driver::video::fbdev::base::BootTimeVideoType,
driver::{
serial::serial8250::send_to_default_serial8250_port,
video::fbdev::base::BootTimeVideoType,
},
};
arch_video_early_init()?;