1 use alloc::{
2 string::{String, ToString},
3 sync::{Arc, Weak},
4 vec::Vec,
5 };
6 use system_error::SystemError;
7
8 use crate::{
9 driver::{
10 base::{
11 class::Class,
12 device::{bus::Bus, device_manager, driver::Driver, Device, DeviceType, IdTable},
13 kobject::{KObjType, KObject, KObjectState, LockedKObjectState},
14 kset::KSet,
15 },
16 tty::virtual_terminal::virtual_console::{CursorOperation, VcCursor, VirtualConsoleData},
17 },
18 filesystem::{
19 kernfs::KernFSInode,
20 sysfs::{file::sysfs_emit_str, Attribute, AttributeGroup, SysFSOpsSupport},
21 vfs::syscall::ModeType,
22 },
23 libs::{
24 rwlock::{RwLockReadGuard, RwLockWriteGuard},
25 spinlock::{SpinLock, SpinLockGuard},
26 },
27 };
28
29 use super::{fbmem::sys_class_graphics_instance, FbCursor, ScrollMode};
30
31 pub mod framebuffer_console;
32
33 /// framebuffer console设备管理器实例
34 static mut FB_CONSOLE_MANAGER: Option<FbConsoleManager> = None;
35
fb_console_manager() -> &'static FbConsoleManager36 pub fn fb_console_manager() -> &'static FbConsoleManager {
37 unsafe { FB_CONSOLE_MANAGER.as_ref().unwrap() }
38 }
39
40 /// 初始化framebuffer console
fb_console_init() -> Result<(), SystemError>41 pub(super) fn fb_console_init() -> Result<(), SystemError> {
42 // todo: 对全局的console信号量加锁(linux中是console_lock)
43
44 let fbcon_device: Arc<FbConsoleDevice> = FbConsoleDevice::new();
45
46 {
47 let fbcon_manager = FbConsoleManager::new(fbcon_device.clone());
48 unsafe { FB_CONSOLE_MANAGER = Some(fbcon_manager) };
49 }
50
51 device_manager().register(fbcon_device.clone() as Arc<dyn Device>)?;
52 fb_console_manager().init_device()?;
53
54 return Ok(());
55 }
56
57 /// framebuffer console设备管理器
58 #[derive(Debug)]
59 pub struct FbConsoleManager {
60 _inner: SpinLock<InnerFbConsoleManager>,
61 /// framebuffer console设备实例
62 /// (对应`/sys/class/graphics/fbcon`)
63 device: Arc<FbConsoleDevice>,
64 }
65
66 impl FbConsoleManager {
new(device: Arc<FbConsoleDevice>) -> Self67 pub fn new(device: Arc<FbConsoleDevice>) -> Self {
68 return Self {
69 _inner: SpinLock::new(InnerFbConsoleManager {}),
70 device,
71 };
72 }
73
74 #[allow(dead_code)]
75 #[inline(always)]
device(&self) -> &Arc<FbConsoleDevice>76 pub fn device(&self) -> &Arc<FbConsoleDevice> {
77 &self.device
78 }
79
80 /// 初始化设备
init_device(&self) -> Result<(), SystemError>81 fn init_device(&self) -> Result<(), SystemError> {
82 return Ok(()); // todo
83 }
84 }
85
86 #[derive(Debug)]
87 struct InnerFbConsoleManager {}
88
89 #[derive(Debug)]
90 struct InnerFbConsoleDevice {
91 kernfs_inode: Option<Arc<KernFSInode>>,
92 parent: Option<Weak<dyn KObject>>,
93 kset: Option<Arc<KSet>>,
94 bus: Option<Weak<dyn Bus>>,
95 driver: Option<Weak<dyn Driver>>,
96 ktype: Option<&'static dyn KObjType>,
97 }
98
99 /// `/sys/class/graphics/fbcon`代表的 framebuffer console 设备
100 #[derive(Debug)]
101 #[cast_to([sync] Device)]
102 pub struct FbConsoleDevice {
103 inner: SpinLock<InnerFbConsoleDevice>,
104 kobj_state: LockedKObjectState,
105 }
106
107 impl FbConsoleDevice {
108 const NAME: &'static str = "fbcon";
109
new() -> Arc<Self>110 pub fn new() -> Arc<Self> {
111 return Arc::new(Self {
112 inner: SpinLock::new(InnerFbConsoleDevice {
113 kernfs_inode: None,
114 parent: None,
115 kset: None,
116 bus: None,
117 ktype: None,
118 driver: None,
119 }),
120 kobj_state: LockedKObjectState::new(None),
121 });
122 }
123 }
124
125 impl KObject for FbConsoleDevice {
as_any_ref(&self) -> &dyn core::any::Any126 fn as_any_ref(&self) -> &dyn core::any::Any {
127 self
128 }
129
set_inode(&self, inode: Option<Arc<KernFSInode>>)130 fn set_inode(&self, inode: Option<Arc<KernFSInode>>) {
131 self.inner.lock().kernfs_inode = inode;
132 }
133
inode(&self) -> Option<Arc<KernFSInode>>134 fn inode(&self) -> Option<Arc<KernFSInode>> {
135 self.inner.lock().kernfs_inode.clone()
136 }
137
parent(&self) -> Option<Weak<dyn KObject>>138 fn parent(&self) -> Option<Weak<dyn KObject>> {
139 self.inner.lock().parent.clone()
140 }
141
set_parent(&self, parent: Option<Weak<dyn KObject>>)142 fn set_parent(&self, parent: Option<Weak<dyn KObject>>) {
143 self.inner.lock().parent = parent;
144 }
145
kset(&self) -> Option<Arc<KSet>>146 fn kset(&self) -> Option<Arc<KSet>> {
147 self.inner.lock().kset.clone()
148 }
149
set_kset(&self, kset: Option<Arc<KSet>>)150 fn set_kset(&self, kset: Option<Arc<KSet>>) {
151 self.inner.lock().kset = kset;
152 }
153
kobj_type(&self) -> Option<&'static dyn KObjType>154 fn kobj_type(&self) -> Option<&'static dyn KObjType> {
155 self.inner.lock().ktype
156 }
157
set_kobj_type(&self, ktype: Option<&'static dyn KObjType>)158 fn set_kobj_type(&self, ktype: Option<&'static dyn KObjType>) {
159 self.inner.lock().ktype = ktype;
160 }
161
name(&self) -> String162 fn name(&self) -> String {
163 Self::NAME.to_string()
164 }
165
set_name(&self, _name: String)166 fn set_name(&self, _name: String) {
167 // 不允许修改
168 kwarn!("fbcon name can not be changed");
169 }
170
kobj_state(&self) -> RwLockReadGuard<KObjectState>171 fn kobj_state(&self) -> RwLockReadGuard<KObjectState> {
172 self.kobj_state.read()
173 }
174
kobj_state_mut(&self) -> RwLockWriteGuard<KObjectState>175 fn kobj_state_mut(&self) -> RwLockWriteGuard<KObjectState> {
176 self.kobj_state.write()
177 }
178
set_kobj_state(&self, state: KObjectState)179 fn set_kobj_state(&self, state: KObjectState) {
180 *self.kobj_state.write() = state;
181 }
182 }
183 impl Device for FbConsoleDevice {
dev_type(&self) -> DeviceType184 fn dev_type(&self) -> DeviceType {
185 DeviceType::Char
186 }
187
id_table(&self) -> IdTable188 fn id_table(&self) -> IdTable {
189 IdTable::new(Self::NAME.to_string(), None)
190 }
191
set_bus(&self, bus: Option<Weak<dyn Bus>>)192 fn set_bus(&self, bus: Option<Weak<dyn Bus>>) {
193 self.inner.lock().bus = bus;
194 }
195
bus(&self) -> Option<Weak<dyn Bus>>196 fn bus(&self) -> Option<Weak<dyn Bus>> {
197 self.inner.lock().bus.clone()
198 }
199
set_class(&self, _class: Option<Arc<dyn Class>>)200 fn set_class(&self, _class: Option<Arc<dyn Class>>) {
201 // 不允许修改
202 kwarn!("fbcon's class can not be changed");
203 }
204
class(&self) -> Option<Arc<dyn Class>>205 fn class(&self) -> Option<Arc<dyn Class>> {
206 sys_class_graphics_instance().map(|ins| ins.clone() as Arc<dyn Class>)
207 }
208
driver(&self) -> Option<Arc<dyn Driver>>209 fn driver(&self) -> Option<Arc<dyn Driver>> {
210 self.inner
211 .lock()
212 .driver
213 .clone()
214 .and_then(|driver| driver.upgrade())
215 }
216
set_driver(&self, driver: Option<Weak<dyn Driver>>)217 fn set_driver(&self, driver: Option<Weak<dyn Driver>>) {
218 self.inner.lock().driver = driver;
219 }
220
is_dead(&self) -> bool221 fn is_dead(&self) -> bool {
222 todo!()
223 }
224
can_match(&self) -> bool225 fn can_match(&self) -> bool {
226 todo!()
227 }
228
set_can_match(&self, _can_match: bool)229 fn set_can_match(&self, _can_match: bool) {
230 todo!()
231 }
232
state_synced(&self) -> bool233 fn state_synced(&self) -> bool {
234 todo!()
235 }
236
attribute_groups(&self) -> Option<&'static [&'static dyn AttributeGroup]>237 fn attribute_groups(&self) -> Option<&'static [&'static dyn AttributeGroup]> {
238 return Some(&[&AnonymousAttributeGroup]);
239 }
240 }
241
242 /// framebuffer console设备的匿名属性组
243 #[derive(Debug)]
244 struct AnonymousAttributeGroup;
245
246 impl AttributeGroup for AnonymousAttributeGroup {
name(&self) -> Option<&str>247 fn name(&self) -> Option<&str> {
248 None
249 }
250
attrs(&self) -> &[&'static dyn Attribute]251 fn attrs(&self) -> &[&'static dyn Attribute] {
252 return &[&AttrRotate, &AttrRotateAll, &AttrCursorBlink];
253 }
254
is_visible( &self, _kobj: Arc<dyn KObject>, attr: &'static dyn Attribute, ) -> Option<ModeType>255 fn is_visible(
256 &self,
257 _kobj: Arc<dyn KObject>,
258 attr: &'static dyn Attribute,
259 ) -> Option<ModeType> {
260 return Some(attr.mode());
261 }
262 }
263
264 #[derive(Debug)]
265 struct AttrRotate;
266
267 impl Attribute for AttrRotate {
name(&self) -> &str268 fn name(&self) -> &str {
269 "rotate"
270 }
271
mode(&self) -> ModeType272 fn mode(&self) -> ModeType {
273 ModeType::S_IRUGO | ModeType::S_IWUSR
274 }
275
support(&self) -> SysFSOpsSupport276 fn support(&self) -> SysFSOpsSupport {
277 SysFSOpsSupport::ATTR_SHOW | SysFSOpsSupport::ATTR_STORE
278 }
279
280 /// https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/video/fbdev/core/fbcon.c#3226
show(&self, _kobj: Arc<dyn KObject>, buf: &mut [u8]) -> Result<usize, SystemError>281 fn show(&self, _kobj: Arc<dyn KObject>, buf: &mut [u8]) -> Result<usize, SystemError> {
282 kwarn!("fbcon rotate show not implemented");
283 return sysfs_emit_str(buf, "0\n");
284 }
285
286 /// https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/video/fbdev/core/fbcon.c#3182
store(&self, _kobj: Arc<dyn KObject>, _buf: &[u8]) -> Result<usize, SystemError>287 fn store(&self, _kobj: Arc<dyn KObject>, _buf: &[u8]) -> Result<usize, SystemError> {
288 kwarn!("fbcon rotate store not implemented");
289 return Err(SystemError::ENOSYS);
290 }
291 }
292
293 #[derive(Debug)]
294 struct AttrRotateAll;
295
296 impl Attribute for AttrRotateAll {
name(&self) -> &str297 fn name(&self) -> &str {
298 "rotate_all"
299 }
300
mode(&self) -> ModeType301 fn mode(&self) -> ModeType {
302 ModeType::S_IWUSR
303 }
304
support(&self) -> SysFSOpsSupport305 fn support(&self) -> SysFSOpsSupport {
306 SysFSOpsSupport::ATTR_STORE
307 }
308
309 /// https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/video/fbdev/core/fbcon.c#3204
store(&self, _kobj: Arc<dyn KObject>, _buf: &[u8]) -> Result<usize, SystemError>310 fn store(&self, _kobj: Arc<dyn KObject>, _buf: &[u8]) -> Result<usize, SystemError> {
311 kwarn!("fbcon rotate_all store not implemented");
312 return Err(SystemError::ENOSYS);
313 }
314 }
315
316 #[derive(Debug)]
317 struct AttrCursorBlink;
318
319 impl Attribute for AttrCursorBlink {
name(&self) -> &str320 fn name(&self) -> &str {
321 "cursor_blink"
322 }
323
mode(&self) -> ModeType324 fn mode(&self) -> ModeType {
325 ModeType::S_IRUGO | ModeType::S_IWUSR
326 }
327
support(&self) -> SysFSOpsSupport328 fn support(&self) -> SysFSOpsSupport {
329 SysFSOpsSupport::ATTR_SHOW | SysFSOpsSupport::ATTR_STORE
330 }
331
332 /// https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/video/fbdev/core/fbcon.c#3245
show(&self, _kobj: Arc<dyn KObject>, _buf: &mut [u8]) -> Result<usize, SystemError>333 fn show(&self, _kobj: Arc<dyn KObject>, _buf: &mut [u8]) -> Result<usize, SystemError> {
334 todo!()
335 }
336
store(&self, _kobj: Arc<dyn KObject>, _buf: &[u8]) -> Result<usize, SystemError>337 fn store(&self, _kobj: Arc<dyn KObject>, _buf: &[u8]) -> Result<usize, SystemError> {
338 todo!()
339 }
340 }
341
342 #[derive(Debug, Default)]
343 pub struct FrameBufferConsoleData {
344 /// 光标闪烁间隔
345 pub cursor_blink_jiffies: i64,
346 /// 是否刷新光标
347 pub cursor_flash: bool,
348 ///
349 pub display: FbConsoleDisplay,
350 /// 光标状态
351 pub cursor_state: FbCursor,
352 /// 重设光标?
353 pub cursor_reset: bool,
354 /// cursor 位图数据
355 pub cursor_data: Vec<u8>,
356 }
357
358 pub trait FrameBufferConsole {
fbcon_data(&self) -> SpinLockGuard<FrameBufferConsoleData>359 fn fbcon_data(&self) -> SpinLockGuard<FrameBufferConsoleData>;
360
361 /// ## 将位块移动到目标位置
362 /// 坐标均以字体为单位而不是pixel
363 /// ### 参数
364 /// ### sy: 起始位置的y坐标
365 /// ### sx: 起始位置的x坐标、
366 /// ### dy: 目标位置的y坐标
367 /// ### dx: 目标位置的x坐标
368 /// ### height: 位图高度
369 /// ### width: 位图宽度
bmove( &self, vc_data: &VirtualConsoleData, sy: i32, sx: i32, dy: i32, dx: i32, height: u32, width: u32, ) -> Result<(), SystemError>370 fn bmove(
371 &self,
372 vc_data: &VirtualConsoleData,
373 sy: i32,
374 sx: i32,
375 dy: i32,
376 dx: i32,
377 height: u32,
378 width: u32,
379 ) -> Result<(), SystemError>;
380
381 /// ## 清除位图
382 ///
383 /// ### 参数
384 /// ### sy: 原位置的y坐标
385 /// ### sx: 原位置的x坐标、
386 /// ### height: 位图高度
387 /// ### width: 位图宽度
clear( &self, vc_data: &VirtualConsoleData, sy: u32, sx: u32, height: u32, width: u32, ) -> Result<(), SystemError>388 fn clear(
389 &self,
390 vc_data: &VirtualConsoleData,
391 sy: u32,
392 sx: u32,
393 height: u32,
394 width: u32,
395 ) -> Result<(), SystemError>;
396
397 /// ## 显示字符串
398 ///
399 /// ### 参数
400 /// ### y: 起始位置y坐标
401 /// ### x: 起始位置的x坐标、
402 /// ### fg: 前景色
403 /// ### bg: 背景色
put_string( &self, vc_data: &VirtualConsoleData, data: &[u16], count: u32, y: u32, x: u32, fg: u32, bg: u32, ) -> Result<(), SystemError>404 fn put_string(
405 &self,
406 vc_data: &VirtualConsoleData,
407 data: &[u16],
408 count: u32,
409 y: u32,
410 x: u32,
411 fg: u32,
412 bg: u32,
413 ) -> Result<(), SystemError>;
414
cursor(&self, vc_data: &VirtualConsoleData, op: CursorOperation, fg: u32, bg: u32)415 fn cursor(&self, vc_data: &VirtualConsoleData, op: CursorOperation, fg: u32, bg: u32);
416 }
417
418 /// 表示 framebuffer 控制台与低级帧缓冲设备之间接口的数据结构
419 #[derive(Debug, Default)]
420 pub struct FbConsoleDisplay {
421 /// 硬件滚动的行数
422 pub yscroll: u32,
423 /// 光标
424 pub cursor_shape: VcCursor,
425 /// 滚动模式
426 pub scroll_mode: ScrollMode,
427 virt_rows: u32,
428 }
429
430 impl FbConsoleDisplay {
real_y(&self, mut ypos: u32) -> u32431 pub fn real_y(&self, mut ypos: u32) -> u32 {
432 let rows = self.virt_rows;
433 ypos += self.yscroll;
434 if ypos < rows {
435 return ypos;
436 } else {
437 return ypos - rows;
438 }
439 }
440 }
441
442 bitflags! {
443 pub struct FbConAttr:u8 {
444 const UNDERLINE = 1;
445 const REVERSE = 2;
446 const BOLD = 4;
447 }
448 }
449
450 impl FbConAttr {
get_attr(c: u16, color_depth: u32) -> Self451 pub fn get_attr(c: u16, color_depth: u32) -> Self {
452 let mut attr = Self::empty();
453 if color_depth == 1 {
454 if Self::underline(c) {
455 attr.insert(Self::UNDERLINE);
456 }
457 if Self::reverse(c) {
458 attr.intersects(Self::REVERSE);
459 }
460 if Self::blod(c) {
461 attr.insert(Self::BOLD);
462 }
463 }
464 attr
465 }
466
update_attr(&self, dst: &mut [u8], src: &[u8], vc_data: &VirtualConsoleData)467 pub fn update_attr(&self, dst: &mut [u8], src: &[u8], vc_data: &VirtualConsoleData) {
468 let mut offset = if vc_data.font.height < 10 { 1 } else { 2 } as usize;
469
470 let width = (vc_data.font.width + 7) / 8;
471 let cellsize = (vc_data.font.height * width) as usize;
472
473 // 大于offset的部分就是下划线
474 offset = cellsize - (offset * width as usize);
475 for i in 0..cellsize {
476 let mut c = src[i];
477 if self.contains(Self::UNDERLINE) && i >= offset {
478 // 下划线
479 c = 0xff;
480 }
481 if self.contains(Self::BOLD) {
482 c |= c >> 1;
483 }
484 if self.contains(Self::REVERSE) {
485 c = !c;
486 }
487
488 dst[i] = c;
489 }
490 }
491
underline(c: u16) -> bool492 pub fn underline(c: u16) -> bool {
493 c & 0x400 != 0
494 }
495
blod(c: u16) -> bool496 pub fn blod(c: u16) -> bool {
497 c & 0x200 != 0
498 }
499
reverse(c: u16) -> bool500 pub fn reverse(c: u16) -> bool {
501 c & 0x800 != 0
502 }
503 }
504