1 use core::fmt::Formatter; 2 3 use alloc::{ 4 string::{String, ToString}, 5 sync::Arc, 6 }; 7 use hashbrown::HashMap; 8 use ida::IdAllocator; 9 use system_error::SystemError; 10 use unified_init::macros::unified_init; 11 12 use crate::{ 13 driver::{ 14 base::device::{ 15 device_number::{DeviceNumber, Major}, 16 device_register, IdTable, 17 }, 18 serial::serial8250::send_to_default_serial8250_port, 19 }, 20 filesystem::devfs::{devfs_register, devfs_unregister}, 21 init::initcall::INITCALL_LATE, 22 libs::{lazy_init::Lazy, rwlock::RwLock, spinlock::SpinLock}, 23 }; 24 25 use self::virtual_console::VirtualConsoleData; 26 27 use super::{ 28 console::ConsoleSwitch, 29 termios::{InputMode, TTY_STD_TERMIOS}, 30 tty_core::{TtyCore, TtyCoreData}, 31 tty_device::{TtyDevice, TtyType}, 32 tty_driver::{TtyDriver, TtyDriverManager, TtyDriverType, TtyOperation}, 33 tty_port::{DefaultTtyPort, TtyPort}, 34 }; 35 36 pub mod console_map; 37 pub mod virtual_console; 38 39 pub const MAX_NR_CONSOLES: u32 = 64; 40 pub const VC_MAXCOL: usize = 32767; 41 pub const VC_MAXROW: usize = 32767; 42 43 pub const DEFAULT_RED: [u16; 16] = [ 44 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x55, 0xff, 0x55, 0xff, 0x55, 0xff, 0x55, 0xff, 45 ]; 46 47 pub const DEFAULT_GREEN: [u16; 16] = [ 48 0x00, 0x00, 0xaa, 0x55, 0x00, 0x00, 0xaa, 0xaa, 0x55, 0x55, 0xff, 0xff, 0x55, 0x55, 0xff, 0xff, 49 ]; 50 51 pub const DEFAULT_BLUE: [u16; 16] = [ 52 0x00, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55, 0xff, 0xff, 0xff, 0xff, 53 ]; 54 55 pub const COLOR_TABLE: &[u8] = &[0, 4, 2, 6, 1, 5, 3, 7, 8, 12, 10, 14, 9, 13, 11, 15]; 56 57 lazy_static! { 58 static ref VC_MANAGER: VirtConsoleManager = VirtConsoleManager::new(); 59 } 60 61 /// 获取虚拟终端管理器 62 #[inline] 63 pub fn vc_manager() -> &'static VirtConsoleManager { 64 &VC_MANAGER 65 } 66 67 pub struct VirtConsole { 68 vc_data: Option<Arc<SpinLock<VirtualConsoleData>>>, 69 port: Arc<dyn TtyPort>, 70 index: Lazy<usize>, 71 inner: SpinLock<InnerVirtConsole>, 72 } 73 74 struct InnerVirtConsole { 75 vcdev: Option<Arc<TtyDevice>>, 76 } 77 78 impl VirtConsole { 79 pub fn new(vc_data: Option<Arc<SpinLock<VirtualConsoleData>>>) -> Arc<Self> { 80 Arc::new(Self { 81 vc_data, 82 port: Arc::new(DefaultTtyPort::new()), 83 index: Lazy::new(), 84 inner: SpinLock::new(InnerVirtConsole { vcdev: None }), 85 }) 86 } 87 88 pub fn vc_data(&self) -> Option<Arc<SpinLock<VirtualConsoleData>>> { 89 self.vc_data.clone() 90 } 91 92 pub fn port(&self) -> Arc<dyn TtyPort> { 93 self.port.clone() 94 } 95 96 pub fn index(&self) -> Option<usize> { 97 self.index.try_get().cloned() 98 } 99 100 pub fn devfs_setup(&self) -> Result<(), SystemError> { 101 let tty_core = self 102 .port 103 .port_data() 104 .internal_tty() 105 .ok_or(SystemError::ENODEV)?; 106 let tty_core_data = tty_core.core(); 107 let devnum = *tty_core_data.device_number(); 108 let vcname = format!("vc{}", self.index.get()); 109 110 // 注册虚拟终端设备并将虚拟终端设备加入到文件系统 111 let vcdev = TtyDevice::new( 112 vcname.clone(), 113 IdTable::new(vcname, Some(devnum)), 114 TtyType::Tty, 115 ); 116 117 device_register(vcdev.clone())?; 118 devfs_register(vcdev.name_ref(), vcdev.clone())?; 119 tty_core_data.set_vc_index(*self.index.get()); 120 self.inner.lock().vcdev = Some(vcdev); 121 122 Ok(()) 123 } 124 125 fn devfs_remove(&self) { 126 let vcdev = self.inner.lock().vcdev.take(); 127 if let Some(vcdev) = vcdev { 128 devfs_unregister(vcdev.name_ref(), vcdev.clone()) 129 .inspect_err(|e| { 130 log::error!("virt console: devfs_unregister failed: {:?}", e); 131 }) 132 .ok(); 133 } 134 } 135 } 136 137 struct InnerVirtConsoleManager { 138 consoles: HashMap<usize, Arc<VirtConsole>>, 139 ida: IdAllocator, 140 } 141 pub struct VirtConsoleManager { 142 inner: SpinLock<InnerVirtConsoleManager>, 143 144 current_vc: RwLock<Option<(Arc<VirtConsole>, usize)>>, 145 } 146 147 impl VirtConsoleManager { 148 pub const DEFAULT_VC_NAMES: [&'static str; 4] = ["tty0", "ttyS0", "tty1", "ttyS1"]; 149 150 pub fn new() -> Self { 151 let ida = IdAllocator::new(0, MAX_NR_CONSOLES as usize).unwrap(); 152 let consoles = HashMap::new(); 153 154 Self { 155 inner: SpinLock::new(InnerVirtConsoleManager { consoles, ida }), 156 current_vc: RwLock::new(None), 157 } 158 } 159 160 pub fn get(&self, index: usize) -> Option<Arc<VirtConsole>> { 161 let inner = self.inner.lock(); 162 inner.consoles.get(&index).cloned() 163 } 164 165 pub fn alloc(&self, vc: Arc<VirtConsole>) -> Option<usize> { 166 let mut inner = self.inner.lock(); 167 let index = inner.ida.alloc()?; 168 vc.index.init(index); 169 if let Some(vc_data) = vc.vc_data.as_ref() { 170 vc_data.lock().vc_index = index; 171 } 172 173 inner.consoles.insert(index, vc); 174 Some(index) 175 } 176 177 /// 释放虚拟终端 178 pub fn free(&self, index: usize) { 179 let mut inner = self.inner.lock(); 180 if let Some(vc) = inner.consoles.remove(&index) { 181 vc.devfs_remove(); 182 } 183 inner.ida.free(index); 184 } 185 186 /// 获取当前虚拟终端 187 pub fn current_vc(&self) -> Option<Arc<VirtConsole>> { 188 self.current_vc.read().as_ref().map(|(vc, _)| vc.clone()) 189 } 190 191 pub fn current_vc_index(&self) -> Option<usize> { 192 self.current_vc.read().as_ref().map(|(_, index)| *index) 193 } 194 195 pub fn current_vc_tty_name(&self) -> Option<String> { 196 self.current_vc() 197 .and_then(|vc| vc.port().port_data().internal_tty()) 198 .map(|tty| tty.core().name().to_string()) 199 } 200 201 /// 设置当前虚拟终端 202 pub fn set_current_vc(&self, vc: Arc<VirtConsole>) { 203 let index = *vc.index.get(); 204 *self.current_vc.write() = Some((vc, index)); 205 } 206 207 /// 通过tty名称查找虚拟终端 208 /// 209 /// # Arguments 210 /// 211 /// * `name` - tty名称 (如ttyS0) 212 pub fn lookup_vc_by_tty_name(&self, name: &str) -> Option<Arc<VirtConsole>> { 213 let inner = self.inner.lock(); 214 for (_index, vc) in inner.consoles.iter() { 215 let found = vc 216 .port 217 .port_data() 218 .internal_tty() 219 .map(|tty| tty.core().name().as_str() == name) 220 .unwrap_or(false); 221 222 if found { 223 return Some(vc.clone()); 224 } 225 } 226 227 None 228 } 229 230 pub fn setup_default_vc(&self) { 231 // todo: 从内核启动参数中获取 232 for name in Self::DEFAULT_VC_NAMES.iter() { 233 if let Some(vc) = self.lookup_vc_by_tty_name(name) { 234 log::info!("Set default vc with tty device: {}", name); 235 self.set_current_vc(vc); 236 return; 237 } 238 } 239 240 panic!("virt console: setup default vc failed"); 241 } 242 } 243 244 #[derive(Debug, Clone, Copy, Default)] 245 pub struct Color { 246 pub red: u16, 247 pub green: u16, 248 pub blue: u16, 249 pub transp: u16, 250 } 251 252 impl Color { 253 pub fn from_256(col: u32) -> Self { 254 let mut color = Self::default(); 255 if col < 8 { 256 color.red = if col & 1 != 0 { 0xaa } else { 0x00 }; 257 color.green = if col & 2 != 0 { 0xaa } else { 0x00 }; 258 color.blue = if col & 4 != 0 { 0xaa } else { 0x00 }; 259 } else if col < 16 { 260 color.red = if col & 1 != 0 { 0xff } else { 0x55 }; 261 color.green = if col & 2 != 0 { 0xff } else { 0x55 }; 262 color.blue = if col & 4 != 0 { 0xff } else { 0x55 }; 263 } else if col < 232 { 264 color.red = ((col - 16) / 36 * 85 / 2) as u16; 265 color.green = ((col - 16) / 6 % 6 * 85 / 2) as u16; 266 color.blue = ((col - 16) % 6 * 85 / 2) as u16; 267 } else { 268 let col = (col * 10 - 2312) as u16; 269 color.red = col; 270 color.green = col; 271 color.blue = col; 272 } 273 274 color 275 } 276 } 277 278 pub struct TtyConsoleDriverInner { 279 console: Arc<dyn ConsoleSwitch>, 280 } 281 282 impl core::fmt::Debug for TtyConsoleDriverInner { 283 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { 284 write!(f, "TtyConsoleDriverInner") 285 } 286 } 287 288 impl TtyConsoleDriverInner { 289 pub fn new() -> Result<Self, SystemError> { 290 let console = { 291 #[cfg(not(target_arch = "riscv64"))] 292 { 293 Arc::new(crate::driver::video::fbdev::base::fbcon::framebuffer_console::BlittingFbConsole::new()?) 294 } 295 296 #[cfg(target_arch = "riscv64")] 297 crate::driver::video::console::dummycon::dummy_console() 298 }; 299 300 Ok(Self { console }) 301 } 302 303 fn do_write(&self, tty: &TtyCoreData, buf: &[u8], mut nr: usize) -> Result<usize, SystemError> { 304 // 关闭中断 305 let vc_data = tty.vc_data().unwrap(); 306 let mut vc_data_guard = vc_data.lock_irqsave(); 307 308 let mut offset = 0; 309 310 // 这个参数是用来扫描unicode字符的,但是这部分目前未完成,先写着 311 let mut rescan = false; 312 let mut ch: u32 = 0; 313 314 let mut draw = DrawRegion::default(); 315 316 // 首先隐藏光标再写 317 vc_data_guard.hide_cursor(); 318 319 while nr != 0 { 320 if !rescan { 321 ch = buf[offset] as u32; 322 offset += 1; 323 nr -= 1; 324 } 325 326 let (tc, rescan_last) = vc_data_guard.translate(&mut ch); 327 if tc.is_none() { 328 // 表示未转换完成 329 continue; 330 } 331 332 let tc = tc.unwrap(); 333 rescan = rescan_last; 334 335 if vc_data_guard.is_control(tc, ch) { 336 vc_data_guard.flush(&mut draw); 337 vc_data_guard.do_control(ch); 338 continue; 339 } 340 341 if !vc_data_guard.console_write_normal(tc, ch, &mut draw) { 342 continue; 343 } 344 } 345 346 vc_data_guard.flush(&mut draw); 347 348 // TODO: notify update 349 return Ok(offset); 350 } 351 352 fn do_install(&self, tty: Arc<TtyCore>, vc: &Arc<VirtConsole>) -> Result<(), SystemError> { 353 let tty_core = tty.core(); 354 355 let binding = vc.vc_data().unwrap(); 356 let mut vc_data = binding.lock(); 357 358 self.console.con_init(vc, &mut vc_data, true)?; 359 if vc_data.complement_mask == 0 { 360 vc_data.complement_mask = if vc_data.color_mode { 0x7700 } else { 0x0800 }; 361 } 362 vc_data.s_complement_mask = vc_data.complement_mask; 363 // vc_data.bytes_per_row = vc_data.cols << 1; 364 vc_data.index = tty_core.index(); 365 vc_data.bottom = vc_data.rows; 366 vc_data.set_driver_funcs(Arc::downgrade( 367 &(self.console.clone() as Arc<dyn ConsoleSwitch>), 368 )); 369 370 // todo: unicode字符集处理? 371 372 if vc_data.cols > VC_MAXCOL || vc_data.rows > VC_MAXROW { 373 return Err(SystemError::EINVAL); 374 } 375 376 vc_data.init(None, None, true); 377 vc_data.update_attr(); 378 379 let window_size = tty_core.window_size_upgradeable(); 380 if window_size.col == 0 && window_size.row == 0 { 381 let mut window_size = window_size.upgrade(); 382 window_size.col = vc_data.cols as u16; 383 window_size.row = vc_data.rows as u16; 384 } 385 386 if vc_data.utf { 387 tty_core.termios_write().input_mode.insert(InputMode::IUTF8); 388 } else { 389 tty_core.termios_write().input_mode.remove(InputMode::IUTF8); 390 } 391 392 // 设置tty的端口为vc端口 393 vc.port().setup_internal_tty(Arc::downgrade(&tty)); 394 tty.set_port(vc.port()); 395 vc.devfs_setup()?; 396 // 加入sysfs? 397 398 Ok(()) 399 } 400 } 401 402 impl TtyOperation for TtyConsoleDriverInner { 403 fn install(&self, _driver: Arc<TtyDriver>, tty: Arc<TtyCore>) -> Result<(), SystemError> { 404 let vc = VirtConsole::new(Some(Arc::new(SpinLock::new(VirtualConsoleData::new( 405 usize::MAX, 406 ))))); 407 vc_manager().alloc(vc.clone()).ok_or(SystemError::EBUSY)?; 408 self.do_install(tty, &vc) 409 .inspect_err(|_| vc_manager().free(vc.index().unwrap()))?; 410 411 Ok(()) 412 } 413 414 fn open(&self, _tty: &TtyCoreData) -> Result<(), SystemError> { 415 Ok(()) 416 } 417 418 fn write_room(&self, _tty: &TtyCoreData) -> usize { 419 32768 420 } 421 422 /// 参考: https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/tty/vt/vt.c#2894 423 #[inline(never)] 424 fn write(&self, tty: &TtyCoreData, buf: &[u8], nr: usize) -> Result<usize, SystemError> { 425 // if String::from_utf8_lossy(buf) == "Hello world!\n" { 426 // loop {} 427 // } 428 send_to_default_serial8250_port(buf); 429 let ret = self.do_write(tty, buf, nr); 430 self.flush_chars(tty); 431 ret 432 } 433 434 #[inline(never)] 435 fn flush_chars(&self, tty: &TtyCoreData) { 436 let vc_data = tty.vc_data().unwrap(); 437 let mut vc_data_guard = vc_data.lock_irqsave(); 438 vc_data_guard.set_cursor(); 439 } 440 441 fn put_char(&self, tty: &TtyCoreData, ch: u8) -> Result<(), SystemError> { 442 self.write(tty, &[ch], 1)?; 443 Ok(()) 444 } 445 446 fn ioctl(&self, _tty: Arc<TtyCore>, _cmd: u32, _arg: usize) -> Result<(), SystemError> { 447 // TODO 448 Err(SystemError::ENOIOCTLCMD) 449 } 450 451 fn close(&self, _tty: Arc<TtyCore>) -> Result<(), SystemError> { 452 Ok(()) 453 } 454 455 fn resize( 456 &self, 457 _tty: Arc<TtyCore>, 458 _winsize: super::termios::WindowSize, 459 ) -> Result<(), SystemError> { 460 todo!() 461 } 462 } 463 464 #[derive(Debug, Clone)] 465 pub struct VtModeData { 466 mode: VtMode, 467 /// 释放请求时触发的信号 468 relsig: u16, 469 /// 获取请求时触发的信号 470 acqsig: u16, 471 } 472 473 #[allow(dead_code)] 474 #[derive(Debug, Clone)] 475 pub enum VtMode { 476 /// 自动切换模式,即在请求输入时自动切换到终端 477 Auto, 478 /// 手动切换模式,需要通过 ioctl 请求切换到终端 479 Process, 480 /// 等待终端确认,即在切换到终端时等待终端的确认信号 481 Ackacq, 482 } 483 484 /// 用于给vc确定要写入的buf位置 485 #[derive(Debug, Default)] 486 pub struct DrawRegion { 487 /// 偏移量 488 pub offset: usize, 489 /// 写入数量 490 pub size: usize, 491 pub x: Option<u32>, 492 } 493 494 // 初始化虚拟终端 495 #[inline(never)] 496 pub fn vty_init() -> Result<(), SystemError> { 497 if let Ok(tty_console_driver_inner) = TtyConsoleDriverInner::new() { 498 let console_driver = TtyDriver::new( 499 MAX_NR_CONSOLES, 500 "tty", 501 0, 502 Major::TTY_MAJOR, 503 0, 504 TtyDriverType::Console, 505 *TTY_STD_TERMIOS, 506 Arc::new(tty_console_driver_inner), 507 None, 508 ); 509 510 TtyDriverManager::tty_register_driver(console_driver).inspect(|_| { 511 log::error!("tty console: register driver failed"); 512 })?; 513 } 514 515 Ok(()) 516 } 517 518 #[unified_init(INITCALL_LATE)] 519 fn vty_late_init() -> Result<(), SystemError> { 520 let (_, console_driver) = 521 TtyDriverManager::lookup_tty_driver(DeviceNumber::new(Major::TTY_MAJOR, 0)) 522 .ok_or(SystemError::ENODEV)?; 523 console_driver.init_tty_device(None)?; 524 525 vc_manager().setup_default_vc(); 526 Ok(()) 527 } 528