Jelajahi Sumber

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

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

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

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

* 添加clear清屏程序

* 实现tty部分ioctl,更改部分问题
GnoCiYeH 1 tahun lalu
induk
melakukan
52da9a5937
62 mengubah file dengan 8803 tambahan dan 888 penghapusan
  1. 1 0
      kernel/crates/bitmap/src/bitmap_core.rs
  2. 1 0
      kernel/crates/bitmap/src/static_bitmap.rs
  3. 2 0
      kernel/crates/system_error/src/lib.rs
  4. 1 1
      kernel/src/arch/x86_64/mm/mod.rs
  5. 3 1
      kernel/src/driver/base/device/device_number.rs
  6. 2 12
      kernel/src/driver/keyboard/ps2_keyboard.rs
  7. 1 0
      kernel/src/driver/mod.rs
  8. 2 3
      kernel/src/driver/serial/mod.rs
  9. 11 42
      kernel/src/driver/serial/serial8250/mod.rs
  10. 1 1
      kernel/src/driver/serial/serial8250/serial8250_pio.rs
  11. 125 0
      kernel/src/driver/tty/console.rs
  12. 0 7
      kernel/src/driver/tty/init.rs
  13. 27 408
      kernel/src/driver/tty/mod.rs
  14. 383 0
      kernel/src/driver/tty/termios.rs
  15. 592 0
      kernel/src/driver/tty/tty_core.rs
  16. 399 224
      kernel/src/driver/tty/tty_device.rs
  17. 429 44
      kernel/src/driver/tty/tty_driver.rs
  18. 139 0
      kernel/src/driver/tty/tty_job_control.rs
  19. 117 0
      kernel/src/driver/tty/tty_ldisc/mod.rs
  20. 2016 0
      kernel/src/driver/tty/tty_ldisc/ntty.rs
  21. 113 0
      kernel/src/driver/tty/tty_port.rs
  22. 135 0
      kernel/src/driver/tty/virtual_terminal/console_map.rs
  23. 303 0
      kernel/src/driver/tty/virtual_terminal/mod.rs
  24. 2015 0
      kernel/src/driver/tty/virtual_terminal/virtual_console.rs
  25. 0 10
      kernel/src/driver/tty/vt/mod.rs
  26. 1 0
      kernel/src/driver/video/fbdev/base/fbcmap.rs
  27. 787 0
      kernel/src/driver/video/fbdev/base/fbcon/framebuffer_console.rs
  28. 176 7
      kernel/src/driver/video/fbdev/base/fbcon/mod.rs
  29. 415 8
      kernel/src/driver/video/fbdev/base/mod.rs
  30. 229 27
      kernel/src/driver/video/fbdev/vesafb.rs
  31. 4 2
      kernel/src/driver/video/mod.rs
  32. 7 2
      kernel/src/filesystem/devfs/mod.rs
  33. 6 1
      kernel/src/filesystem/kernfs/mod.rs
  34. 1 1
      kernel/src/filesystem/vfs/file.rs
  35. 6 1
      kernel/src/filesystem/vfs/mod.rs
  36. 7 2
      kernel/src/filesystem/vfs/mount.rs
  37. 3 2
      kernel/src/filesystem/vfs/syscall.rs
  38. 2 2
      kernel/src/init/init.rs
  39. TEMPAT SAMPAH
      kernel/src/libs/font/bin/VGA_8X16.bytes
  40. TEMPAT SAMPAH
      kernel/src/libs/font/bin/VGA_8X8.bytes
  41. 2 0
      kernel/src/libs/font/font_type/mod.rs
  42. 10 0
      kernel/src/libs/font/font_type/vga8x16.rs
  43. 11 0
      kernel/src/libs/font/font_type/vga8x8.rs
  44. 49 0
      kernel/src/libs/font/mod.rs
  45. 56 62
      kernel/src/libs/keyboard_parser.rs
  46. 1 3
      kernel/src/libs/lib_ui/screen_manager.rs
  47. 29 1
      kernel/src/libs/lib_ui/textui.rs
  48. 1 1
      kernel/src/libs/lib_ui/textui_no_alloc.rs
  49. 2 0
      kernel/src/libs/mod.rs
  50. 29 9
      kernel/src/libs/printk.rs
  51. 1 1
      kernel/src/mm/init.rs
  52. 12 0
      kernel/src/process/mod.rs
  53. 19 0
      kernel/src/syscall/mod.rs
  54. 6 1
      kernel/src/virt/kvm/kvm_dev.rs
  55. 6 1
      kernel/src/virt/kvm/vcpu_dev.rs
  56. 6 1
      kernel/src/virt/kvm/vm_dev.rs
  57. 3 0
      user/apps/clear/.gitignore
  58. 10 0
      user/apps/clear/Cargo.toml
  59. 56 0
      user/apps/clear/Makefile
  60. 7 0
      user/apps/clear/README.md
  61. 3 0
      user/apps/clear/src/main.rs
  62. 22 0
      user/dadk/config/clear-0.1.0.dadk

+ 1 - 0
kernel/crates/bitmap/src/bitmap_core.rs

@@ -2,6 +2,7 @@ use core::{intrinsics::unlikely, marker::PhantomData};
 
 use crate::traits::BitOps;
 
+#[derive(Debug, Clone)]
 pub(crate) struct BitMapCore<T: BitOps> {
     phantom: PhantomData<T>,
 }

+ 1 - 0
kernel/crates/bitmap/src/static_bitmap.rs

@@ -5,6 +5,7 @@ use crate::{bitmap_core::BitMapCore, traits::BitMapOps};
 /// 静态位图
 ///
 /// 该位图的大小在编译时确定,不可变
+#[derive(Debug, Clone)]
 pub struct StaticBitmap<const N: usize>
 where
     [(); (N + usize::BITS as usize - 1) / (usize::BITS as usize)]:,

+ 2 - 0
kernel/crates/system_error/src/lib.rs

@@ -285,6 +285,8 @@ pub enum SystemError {
     EVMPRTLDFailed = 517,
     EVMLAUNCHFailed = 518,
     KVM_HVA_ERR_BAD = 519,
+    /// 没有对应的ioctlcmd
+    ENOIOCTLCMD = 520,
 }
 
 impl SystemError {

+ 1 - 1
kernel/src/arch/x86_64/mm/mod.rs

@@ -7,7 +7,7 @@ use hashbrown::HashSet;
 use x86::time::rdtsc;
 use x86_64::registers::model_specific::EferFlags;
 
-use crate::driver::tty::serial::serial8250::send_to_default_serial8250_port;
+use crate::driver::serial::serial8250::send_to_default_serial8250_port;
 use crate::include::bindings::bindings::{
     multiboot2_get_load_base, multiboot2_get_memory, multiboot2_iter, multiboot_mmap_entry_t,
     multiboot_tag_load_base_addr_t,

+ 3 - 1
kernel/src/driver/base/device/device_number.rs

@@ -1,4 +1,4 @@
-#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
+#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Default)]
 pub struct Major(u32);
 
 impl Major {
@@ -10,6 +10,8 @@ impl Major {
     pub const UNNAMED_MAJOR: Self = Self::new(0);
 
     pub const IDE0_MAJOR: Self = Self::new(3);
+    pub const TTY_MAJOR: Self = Self::new(4);
+    pub const TTYAUX_MAJOR: Self = Self::new(5);
     pub const HD_MAJOR: Self = Self::IDE0_MAJOR;
 
     pub const INPUT_MAJOR: Self = Self::new(13);

+ 2 - 12
kernel/src/driver/keyboard/ps2_keyboard.rs

@@ -3,10 +3,7 @@ use core::{ffi::c_void, sync::atomic::AtomicI32};
 use alloc::sync::{Arc, Weak};
 
 use crate::{
-    driver::{
-        base::device::device_number::{DeviceNumber, Major},
-        tty::tty_device::TTY_DEVICES,
-    },
+    driver::base::device::device_number::{DeviceNumber, Major},
     filesystem::{
         devfs::{devfs_register, DevFS, DeviceINode},
         vfs::{
@@ -23,14 +20,7 @@ use system_error::SystemError;
 pub struct LockedPS2KeyBoardInode(RwLock<PS2KeyBoardInode>, AtomicI32); // self.1 用来记录有多少个文件打开了这个inode
 
 lazy_static! {
-    static ref PS2_KEYBOARD_FSM: SpinLock<TypeOneFSM> = {
-        let tty0 = TTY_DEVICES
-            .read()
-            .get("tty0")
-            .expect("Initializing PS2_KEYBOARD_FSM: Cannot found TTY0!")
-            .clone();
-        SpinLock::new(TypeOneFSM::new(tty0))
-    };
+    static ref PS2_KEYBOARD_FSM: SpinLock<TypeOneFSM> = SpinLock::new(TypeOneFSM::new());
 }
 
 #[derive(Debug)]

+ 1 - 0
kernel/src/driver/mod.rs

@@ -7,6 +7,7 @@ pub mod keyboard;
 pub mod net;
 pub mod open_firmware;
 pub mod pci;
+pub mod serial;
 pub mod timers;
 pub mod tty;
 pub mod video;

+ 2 - 3
kernel/src/driver/tty/serial/mod.rs → kernel/src/driver/serial/mod.rs

@@ -7,11 +7,9 @@ use crate::{driver::base::device::device_number::DeviceNumber, mm::VirtAddr};
 
 use self::serial8250::serial8250_manager;
 
-use super::tty_driver::TtyDriver;
-
 pub mod serial8250;
 
-pub trait UartDriver: Debug + Send + Sync + TtyDriver {
+pub trait UartDriver: Debug + Send + Sync {
     fn device_number(&self) -> DeviceNumber;
 
     /// 获取最大的设备数量
@@ -56,6 +54,7 @@ impl UartManager {
     /// todo: 把uart设备注册到tty层
     ///
     /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/tty/serial/serial_core.c?fi=uart_register_driver#2720
+    #[allow(dead_code)]
     pub fn register_driver(&self, _driver: &Arc<dyn UartDriver>) -> Result<(), SystemError> {
         return Ok(());
     }

+ 11 - 42
kernel/src/driver/tty/serial/serial8250/mod.rs → kernel/src/driver/serial/serial8250/mod.rs

@@ -11,23 +11,17 @@ use alloc::{
 use system_error::SystemError;
 
 use crate::{
-    driver::{
-        base::{
-            class::Class,
-            device::{
-                bus::Bus, device_manager, device_number::DeviceNumber, driver::Driver, Device,
-                DeviceKObjType, DeviceState, DeviceType, IdTable,
-            },
-            kobject::{KObjType, KObject, KObjectState, LockedKObjectState},
-            kset::KSet,
-            platform::{
-                platform_device::{platform_device_manager, PlatformDevice},
-                platform_driver::{platform_driver_manager, PlatformDriver},
-            },
+    driver::base::{
+        class::Class,
+        device::{
+            bus::Bus, device_manager, device_number::DeviceNumber, driver::Driver, Device,
+            DeviceKObjType, DeviceState, DeviceType, IdTable,
         },
-        tty::{
-            tty_device::TtyDevice,
-            tty_driver::{TtyDriver, TtyDriverMetadata, TtyDriverOperations},
+        kobject::{KObjType, KObject, KObjectState, LockedKObjectState},
+        kset::KSet,
+        platform::{
+            platform_device::{platform_device_manager, PlatformDevice},
+            platform_driver::{platform_driver_manager, PlatformDriver},
         },
     },
     filesystem::kernfs::KernFSInode,
@@ -377,6 +371,7 @@ impl InnerSerial8250ISADriver {
 
 #[derive(Debug)]
 #[cast_to([sync] Driver, PlatformDriver)]
+#[allow(dead_code)]
 struct Serial8250ISADriver {
     inner: RwLock<InnerSerial8250ISADriver>,
     name: &'static str,
@@ -402,32 +397,6 @@ impl Serial8250ISADriver {
     }
 }
 
-impl TtyDriver for Serial8250ISADriver {
-    fn driver_name(&self) -> &str {
-        self.name
-    }
-
-    fn dev_name(&self) -> &str {
-        todo!()
-    }
-
-    fn metadata(&self) -> &TtyDriverMetadata {
-        todo!()
-    }
-
-    fn other(&self) -> Option<&Arc<dyn TtyDriver>> {
-        todo!()
-    }
-
-    fn ttys(&self) -> &[Arc<TtyDevice>] {
-        todo!()
-    }
-
-    fn tty_ops(&self) -> Option<&'static dyn TtyDriverOperations> {
-        None
-    }
-}
-
 impl UartDriver for Serial8250ISADriver {
     fn device_number(&self) -> DeviceNumber {
         todo!()

+ 1 - 1
kernel/src/driver/tty/serial/serial8250/serial8250_pio.rs → kernel/src/driver/serial/serial8250/serial8250_pio.rs

@@ -9,7 +9,7 @@ use alloc::sync::{Arc, Weak};
 
 use crate::{
     arch::{io::PortIOArch, CurrentPortIOArch},
-    driver::tty::serial::{AtomicBaudRate, BaudRate, DivisorFraction, UartPort},
+    driver::serial::{AtomicBaudRate, BaudRate, DivisorFraction, UartPort},
     libs::rwlock::RwLock,
 };
 use system_error::SystemError;

+ 125 - 0
kernel/src/driver/tty/console.rs

@@ -0,0 +1,125 @@
+use system_error::SystemError;
+
+use super::virtual_terminal::virtual_console::{
+    CursorOperation, ScrollDir, VirtualConsoleData, VirtualConsoleIntensity,
+};
+
+/// 终端切换相关的回调
+pub trait ConsoleSwitch: Sync + Send {
+    /// 初始化,会对vc_data进行一系列初始化操作
+    fn con_init(&self, vc_data: &mut VirtualConsoleData, init: bool) -> Result<(), SystemError>;
+
+    /// 进行释放等系列操作,目前未使用
+    fn con_deinit(&self) -> Result<(), SystemError>;
+
+    /// ## 清空console的一片区域
+    /// 该函数的所有参数对应的都是以字符为单位
+    /// ### 参数:
+    /// - vc_data: 对应的ConsoleData
+    /// - sy: 对应区域左上角的y轴
+    /// - sx: 对应区域左上角的x轴
+    /// - height: 区域高度
+    /// - width: 区域宽度
+    fn con_clear(
+        &self,
+        vc_data: &mut VirtualConsoleData,
+        sy: usize,
+        sx: usize,
+        height: usize,
+        width: usize,
+    ) -> Result<(), SystemError>;
+
+    /// ## 向console输出一个字符
+    /// ### 参数:
+    /// - vc_data: 对应的ConsoleData
+    /// - ch: 数据
+    /// - ypos: 起始y坐标
+    /// - xpos: 起始x坐标
+    fn con_putc(
+        &self,
+        vc_data: &VirtualConsoleData,
+        ch: u16,
+        ypos: u32,
+        xpos: u32,
+    ) -> Result<(), SystemError>;
+
+    /// ## 向console输出一串字符
+    /// ### 参数:
+    /// - vc_data: 对应的ConsoleData
+    /// - buf: 数据
+    /// - count: 输出字符数量
+    /// - ypos: 起始y坐标
+    /// - xpos: 起始x坐标
+    fn con_putcs(
+        &self,
+        vc_data: &VirtualConsoleData,
+        buf: &[u16],
+        count: usize,
+        ypos: u32,
+        xpos: u32,
+    ) -> Result<(), SystemError>;
+
+    /// ## 根据pos计算出对应xy
+    ///
+    /// ### 返回值: (下一行的起始偏移,x,y)
+    fn con_getxy(
+        &self,
+        _vc_data: &VirtualConsoleData,
+        _pos: usize,
+    ) -> Result<(usize, usize, usize), SystemError> {
+        return Err(SystemError::ENOSYS);
+    }
+
+    /// ## 对光标进行操作
+    /// ### 参数:
+    /// - vc_data: 对应的ConsoleData
+    /// - op: 对光标的操作
+    fn con_cursor(&self, vc_data: &VirtualConsoleData, op: CursorOperation);
+
+    /// ## 根据参数构建出对应的属性
+    /// ### 参数:
+    /// - vc_data: 对应的ConsoleData
+    /// - color: 颜色
+    /// - intensity: 字符强度
+    /// - blink: 是否闪烁
+    /// - underline: 下划线
+    /// - reverse: 颜色反转
+    /// - italic: 斜体
+    fn con_build_attr(
+        &self,
+        _vc_data: &VirtualConsoleData,
+        _color: u8,
+        _intensity: VirtualConsoleIntensity,
+        _blink: bool,
+        _underline: bool,
+        _reverse: bool,
+        _italic: bool,
+    ) -> Result<u8, SystemError> {
+        return Err(SystemError::ENOSYS);
+    }
+
+    /// ## 设置调色板
+    /// ### 参数:
+    /// - vc_data: 对应的ConsoleData
+    /// - color_table: 颜色表
+    fn con_set_palette(
+        &self,
+        vc_data: &VirtualConsoleData,
+        color_table: &[u8],
+    ) -> Result<(), SystemError>;
+
+    /// ## 滚动
+    /// ### 参数
+    /// - top:滚动范围顶部
+    /// - bottom: 滚动范围底部
+    /// - dir: 滚动方向
+    /// - nr: 滚动行数
+    fn con_scroll(
+        &self,
+        vc_data: &mut VirtualConsoleData,
+        top: usize,
+        bottom: usize,
+        dir: ScrollDir,
+        nr: usize,
+    ) -> bool;
+}

+ 0 - 7
kernel/src/driver/tty/init.rs

@@ -1,7 +0,0 @@
-use super::serial::serial_early_init;
-use system_error::SystemError;
-
-pub fn tty_early_init() -> Result<(), SystemError> {
-    serial_early_init()?;
-    return Ok(());
-}

+ 27 - 408
kernel/src/driver/tty/mod.rs

@@ -1,418 +1,37 @@
-use core::intrinsics::unlikely;
+use alloc::vec::Vec;
 
-use alloc::string::String;
-
-use kdepends::thingbuf::mpsc::{
-    self,
-    errors::{TryRecvError, TrySendError},
-};
-
-use crate::libs::rwlock::RwLock;
-
-pub mod init;
-pub mod serial;
+pub mod console;
+pub mod termios;
+pub mod tty_core;
 pub mod tty_device;
 pub mod tty_driver;
-pub mod vt;
-
-bitflags! {
-    pub struct TtyCoreState: u32{
-        /// 在读取stdin缓冲区时,由于队列为空,有读者被阻塞
-        const BLOCK_AT_STDIN_READ = (1 << 0);
-        /// 开启输入回显。
-        const ECHO_ON = (1 << 1);
-    }
-
-    #[derive(Default)]
-    pub struct TtyFileFlag:u32{
-        /// 当前文件是stdin文件
-        const STDIN = (1 << 0);
-        /// 当前文件是stdout文件
-        const STDOUT = (1 << 1);
-        /// 当前文件是stderr文件
-        const STDERR = (1 << 2);
-    }
-}
-
-/// @brief tty文件的私有信息
-#[derive(Debug, Default, Clone)]
-pub struct TtyFilePrivateData {
-    flags: TtyFileFlag,
-}
-
-/// @brief tty设备的核心功能结构体。在此结构体的基础上,衍生出TTY/PTY/PTS等
-///
-/// 每个TTY Core有5个端口:
-/// - stdin:连接到一个活动进程的stdin文件描述符
-/// - stdout:连接到多个进程的stdout文件描述符
-/// - stderr:连接到多个进程的stdout文件描述符
-/// - 输入端口:向tty设备输入数据的接口。输入到该接口的数据,将被导向stdin接口。
-///     如果开启了回显,那么,数据也将同时被导向输出端
-/// - 输出端口:tty设备对外输出数据的端口。从stdout、stderr输入的数据,将会被导向此端口。
-///             此端口可以连接到屏幕、文件、或者是另一个tty core的输入端口。如果开启了
-///             输入数据回显,那么,输入端口的数据,将会被同时导向此端口,以及stdin端口
-#[derive(Debug)]
-struct TtyCore {
-    /// stdin的mpsc队列输入输出端
-    stdin_rx: mpsc::Receiver<u8>,
-    stdin_tx: mpsc::Sender<u8>,
-    /// 输出的mpsc队列输入输出端
-    output_rx: mpsc::Receiver<u8>,
-    output_tx: mpsc::Sender<u8>,
-    // 前台进程,以后改成前台进程组
-    // front_job: Option<Pid>,
-    /// tty核心的状态
-    state: RwLock<TtyCoreState>,
-}
+pub mod tty_job_control;
+pub mod tty_ldisc;
+pub mod tty_port;
+pub mod virtual_terminal;
 
-#[derive(Debug)]
+// 下列结构体暂时放在这
+/// 键盘/显示器"(Keyboard/Display)模式
 #[allow(dead_code)]
-pub enum TtyError {
-    /// 缓冲区满,返回成功传送的字节数
-    BufferFull(usize),
-    /// 缓冲区空,返回成功传送的字节数
-    BufferEmpty(usize),
-    /// 设备已经被关闭
-    Closed,
-    /// End of file(已经读取的字符数,包含eof)
-    EOF(usize),
-    /// 接收到信号终止
-    Stopped(usize),
-    Unknown(String),
+#[derive(Debug, PartialEq, Clone)]
+pub enum KDMode {
+    KdText,
+    KdGraphics,
+    KdText0,
+    KdText1,
+    Undefined,
 }
 
-impl TtyCore {
-    // 各个缓冲区的大小
-    pub const STDIN_BUF_SIZE: usize = 4096;
-    pub const OUTPUT_BUF_SIZE: usize = 4096;
-
-    /// @brief 创建一个TTY核心组件
-    pub fn new() -> TtyCore {
-        let (stdin_tx, stdin_rx) = mpsc::channel::<u8>(Self::STDIN_BUF_SIZE);
-        let (output_tx, output_rx) = mpsc::channel::<u8>(Self::OUTPUT_BUF_SIZE);
-        let state: RwLock<TtyCoreState> = RwLock::new(TtyCoreState { bits: 0 });
-
-        return TtyCore {
-            stdin_rx,
-            stdin_tx,
-            output_rx,
-            output_tx,
-            state,
-        };
-    }
-
-    /// @brief 向tty的输入端口输入数据
-    ///
-    /// @param buf 输入数据
-    ///
-    /// @param block 是否允许阻塞
-    ///
-    /// @return Ok(成功传送的字节数)
-    /// @return Err(TtyError) 内部错误信息
-    pub fn input(&self, buf: &[u8], block: bool) -> Result<usize, TtyError> {
-        let val = self.write_stdin(buf, block)?;
-        // 如果开启了输入回显,那么就写一份到输出缓冲区
-        if self.echo_enabled() {
-            self.write_output(&buf[0..val], true)?;
-        }
-        return Ok(val);
-    }
-
-    /// @brief 从tty的输出端口读出数据
-    ///
-    /// @param buf 输出缓冲区
-    ///
-    /// @return Ok(成功传送的字节数)
-    /// @return Err(TtyError) 内部错误信息
-    #[inline]
-    pub fn output(&self, buf: &mut [u8], block: bool) -> Result<usize, TtyError> {
-        return self.read_output(buf, block);
-    }
-
-    /// @brief tty的stdout接口
-    ///
-    /// @param buf 输入缓冲区
-    ///
-    /// @return Ok(成功传送的字节数)
-    /// @return Err(TtyError) 内部错误信息
-    #[inline]
-    pub fn stdout(&self, buf: &[u8], block: bool) -> Result<usize, TtyError> {
-        return self.write_output(buf, block);
-    }
-
-    /// @brief tty的stderr接口
-    ///
-    /// @param buf 输入缓冲区
-    ///
-    /// @return Ok(成功传送的字节数)
-    /// @return Err(TtyError) 内部错误信息
-    #[inline]
-    pub fn stderr(&self, buf: &[u8], block: bool) -> Result<usize, TtyError> {
-        return self.write_output(buf, block);
-    }
-
-    /// @brief 读取TTY的stdin缓冲区
-    ///
-    /// @param buf 读取到的位置
-    /// @param block 是否阻塞读
-    ///
-    /// @return Ok(成功读取的字节数)
-    /// @return Err(TtyError) 内部错误信息
-    pub fn read_stdin(&self, buf: &mut [u8], block: bool) -> Result<usize, TtyError> {
-        // TODO: 增加对EOF的处理
-        let mut cnt = 0;
-        while cnt < buf.len() {
-            let val: Result<mpsc::RecvRef<u8>, TryRecvError> = self.stdin_rx.try_recv_ref();
-            if let Err(err) = val {
-                match err {
-                    TryRecvError::Closed => return Err(TtyError::Closed),
-                    TryRecvError::Empty => {
-                        if block {
-                            continue;
-                        } else {
-                            return Ok(cnt);
-                        }
-                    }
-                    _ => return Err(TtyError::Unknown(format!("{err:?}"))),
-                }
-            } else {
-                let x = *val.unwrap();
-                buf[cnt] = x;
-                cnt += 1;
-
-                if unlikely(self.stdin_should_return(x)) {
-                    return Ok(cnt);
-                }
-            }
-        }
-        return Ok(cnt);
-    }
-
-    fn stdin_should_return(&self, c: u8) -> bool {
-        // 如果是换行符或者是ctrl+d,那么就应该返回
-        return c == b'\n' || c == 4;
-    }
-
-    /// @brief 向stdin缓冲区内写入数据
-    ///
-    /// @param buf 输入缓冲区
-    ///
-    /// @param block 当缓冲区满的时候,是否阻塞
-    ///
-    /// @return Ok(成功传送的字节数)
-    /// @return Err(BufferFull(成功传送的字节数)) 缓冲区满,成功传送的字节数
-    /// @return Err(TtyError) 内部错误信息
-    fn write_stdin(&self, buf: &[u8], block: bool) -> Result<usize, TtyError> {
-        let mut cnt = 0;
-        while cnt < buf.len() {
-            let r: Result<mpsc::SendRef<u8>, TrySendError> = self.stdin_tx.try_send_ref();
-            if let Err(e) = r {
-                match e {
-                    TrySendError::Closed(_) => return Err(TtyError::Closed),
-                    TrySendError::Full(_) => {
-                        if block {
-                            continue;
-                        } else {
-                            return Err(TtyError::BufferFull(cnt));
-                        }
-                    }
-                    _ => return Err(TtyError::Unknown(format!("{e:?}"))),
-                }
-            } else {
-                *r.unwrap() = buf[cnt];
-                cnt += 1;
-            }
-        }
-
-        return Ok(cnt);
-    }
-
-    /// @brief 读取TTY的output缓冲区
-    ///
-    /// @param buf 读取到的位置
-    /// @param block 是否阻塞读
-    ///
-    /// @return Ok(成功读取的字节数)
-    /// @return Err(TtyError) 内部错误信息
-    fn read_output(&self, buf: &mut [u8], block: bool) -> Result<usize, TtyError> {
-        let mut cnt = 0;
-        while cnt < buf.len() {
-            let val: Result<mpsc::RecvRef<u8>, TryRecvError> = self.output_rx.try_recv_ref();
-            if let Err(err) = val {
-                match err {
-                    TryRecvError::Closed => return Err(TtyError::Closed),
-                    TryRecvError::Empty => {
-                        if block {
-                            continue;
-                        } else {
-                            return Ok(cnt);
-                        }
-                    }
-                    _ => return Err(TtyError::Unknown(format!("{err:?}"))),
-                }
-            } else {
-                buf[cnt] = *val.unwrap();
-                cnt += 1;
-            }
-        }
-        return Ok(cnt);
-    }
-
-    /// @brief 向output缓冲区内写入数据
-    ///
-    /// @param buf 输入缓冲区
-    ///
-    /// @param block 当缓冲区满的时候,是否阻塞
-    ///
-    /// @return Ok(成功传送的字节数)
-    /// @return Err(BufferFull(成功传送的字节数)) 缓冲区满,成功传送的字节数
-    /// @return Err(TtyError) 内部错误信息
-    fn write_output(&self, buf: &[u8], block: bool) -> Result<usize, TtyError> {
-        let mut cnt = 0;
-        while cnt < buf.len() {
-            let r: Result<mpsc::SendRef<u8>, TrySendError> = self.output_tx.try_send_ref();
-            if let Err(e) = r {
-                match e {
-                    TrySendError::Closed(_) => return Err(TtyError::Closed),
-                    TrySendError::Full(_) => {
-                        if block {
-                            continue;
-                        } else {
-                            return Err(TtyError::BufferFull(cnt));
-                        }
-                    }
-                    _ => return Err(TtyError::Unknown(format!("{e:?}"))),
-                }
-            } else {
-                // TODO: 在这里考虑增加对信号发送的处理
-                // if buf[cnt] == 3 {
-                //     let pid = ProcessManager::current_pcb().pid();
-                //     Signal::SIGKILL.send_signal_info(
-                //         Some(&mut SigInfo::new(
-                //             Signal::SIGKILL,
-                //             0,
-                //             SigCode::SI_USER,
-                //             SigType::Kill(pid),
-                //         )),
-                //         pid,
-                //     );
-                //     return Err(TtyError::Stopped(cnt));
-                // }
-                *r.unwrap() = buf[cnt];
-                cnt += 1;
-            }
-        }
-        return Ok(cnt);
-    }
-
-    /// @brief 开启tty输入回显(也就是将输入数据传送一份到输出缓冲区)
-    #[inline]
-    pub fn enable_echo(&self) {
-        self.state.write().set(TtyCoreState::ECHO_ON, true);
-    }
-
-    /// @brief 关闭输入回显
-    #[inline]
-    #[allow(dead_code)]
-    pub fn disable_echo(&self) {
-        self.state.write().set(TtyCoreState::ECHO_ON, false);
-    }
-
-    /// @brief 判断当前tty核心,是否开启了输入回显
-    ///
-    /// @return true 开启了输入回显
-    ///
-    /// @return false 未开启输入回显
-    #[inline]
-    #[allow(dead_code)]
-    pub fn echo_enabled(&self) -> bool {
-        return self.state.read().contains(TtyCoreState::ECHO_ON);
+impl Default for KDMode {
+    fn default() -> Self {
+        Self::Undefined
     }
 }
 
-// ======= 以下代码考虑了“缓冲区满,然后睡眠,当缓冲区有空位就唤醒”的逻辑。
-// 但是由于在开发过程中的调整,并且由于数据结构发生变化,因此暂时不实现上述优化,因此先注释。
-//
-// @brief 读取TTY的stdin缓冲区
-//
-// @param buf 读取到的位置
-// @param block 是否阻塞读
-//
-// @return Ok(成功读取的字节数)
-// @return Err(TtyError) 内部错误信息
-// pub fn read_stdin(&mut self, buf: &mut [u8], block: bool) -> Result<usize, TtyError> {
-//     let mut cnt = 0;
-//     loop{
-//         if cnt == buf.len(){
-//             break;
-//         }
-//         let val:Option<u8> = self.stdin_queue.dequeue();
-//         // 如果没读到
-//         if val.is_none() {
-//             // 如果阻塞读
-//             if block {
-//                 let state_guard: RwLockUpgradableGuard<TtyCoreState> =
-//                     self.state.upgradeable_read();
-//                 // 判断是否有进程正在stdin上睡眠,如果有,则忙等读
-//                 // 理论上,这种情况应该不存在,因为stdin是单读者的
-//                 if state_guard.contains(TtyCoreState::BLOCK_AT_STDIN_READ) {
-//                     kwarn!("Read stdin: Process {} want to read its' stdin, but previous process {} is sleeping on the stdin.", current_pcb().pid, self.stdin_waiter.read().as_ref().unwrap().pid);
-//                     drop(state_guard);
-//                     Self::ringbuf_spin_dequeue(&mut buf[cnt], &mut self.stdin_queue);
-//                     cnt += 1;
-//                 } else {
-//                     // 正常情况,阻塞读,将当前进程休眠
-//                     let mut state_guard: RwLockWriteGuard<TtyCoreState> = state_guard.upgrade();
-//                     let mut stdin_waiter_guard: RwLockWriteGuard<
-//                         Option<&mut process_control_block>,
-//                     > = self.stdin_waiter.write();
-
-//                     // 由于输入数据到stdin的时候,必须先获得state guard的读锁。而这里我们已经获取了state的写锁。
-//                     // 因此可以保证,此时没有新的数据会进入stdin_queue. 因此再次尝试读取stdin_queue
-//                     let val:Option<u8> = self.stdin_queue.dequeue();
-//                     // 读到数据,不用睡眠
-//                     if val.is_some(){
-//                         buf[cnt] = val.unwrap();
-//                         cnt += 1;
-//                         continue;
-//                     }
-//                     // 没读到数据,准备睡眠
-
-//                     // 设置等待标志位
-//                     state_guard.set(TtyCoreState::BLOCK_AT_STDIN_READ, true);
-
-//                     // 将当前进程标记为被其他机制管理
-//                     unsafe {
-//                         current_pcb().mark_sleep_interruptible();
-//                     }
-
-//                     *stdin_waiter_guard = Some(current_pcb());
-//                     drop(stdin_waiter_guard);
-//                     drop(state_guard);
-//                     sched();
-//                     continue;
-//                 }
-//             } else {
-//                 // 非阻塞读,没读到就直接返回了
-//                 return Ok(cnt);
-//             }
-//         }else{
-//             buf[cnt] = val.unwrap();
-//             cnt += 1;
-//         }
-//     }
-
-//     return Ok(cnt);
-// }
-
-// fn write_stdin(&self)
-
-// /// @brief 非休眠的,自旋地读队列,直到有元素被读出来
-// fn ringbuf_spin_dequeue(dst: &mut u8, queue: &mut AllocRingBuffer<u8>) {
-//     loop {
-//         if let Some(val) = queue.dequeue() {
-//             *dst = val;
-//             return;
-//         }
-//     }
-// }
+#[derive(Debug, Default, Clone)]
+pub struct ConsoleFont {
+    pub width: u32,
+    pub height: u32,
+    pub count: u32,
+    pub data: Vec<u8>,
+}

+ 383 - 0
kernel/src/driver/tty/termios.rs

@@ -0,0 +1,383 @@
+use super::tty_ldisc::LineDisciplineType;
+
+/// ## 窗口大小
+#[repr(C)]
+#[derive(Debug, Default, Clone, Copy)]
+pub struct WindowSize {
+    /// 行
+    pub row: u16,
+    /// 列
+    pub col: u16,
+    /// x方向像素数
+    pub xpixel: u16,
+    /// y方向像素数
+    pub ypixel: u16,
+}
+
+#[derive(Debug, Clone, Copy)]
+pub struct Termios {
+    pub input_mode: InputMode,
+    pub output_mode: OutputMode,
+    pub control_mode: ControlMode,
+    pub local_mode: LocalMode,
+    pub control_characters: [u8; CONTORL_CHARACTER_NUM],
+    pub line: LineDisciplineType,
+    pub input_speed: u32,
+    pub output_speed: u32,
+}
+
+#[derive(Clone, Copy)]
+pub struct PosixTermios {
+    pub c_iflag: u32,
+    pub c_oflag: u32,
+    pub c_cflag: u32,
+    pub c_lflag: u32,
+    pub c_cc: [u8; CONTORL_CHARACTER_NUM],
+    pub c_line: u8,
+    pub c_ispeed: u32,
+    pub c_ospeed: u32,
+}
+
+impl PosixTermios {
+    pub fn from_kernel_termios(termios: Termios) -> Self {
+        Self {
+            c_iflag: termios.input_mode.bits,
+            c_oflag: termios.output_mode.bits,
+            c_cflag: termios.control_mode.bits,
+            c_lflag: termios.local_mode.bits,
+            c_cc: termios.control_characters.clone(),
+            c_line: termios.line as u8,
+            c_ispeed: termios.input_speed,
+            c_ospeed: termios.output_speed,
+        }
+    }
+
+    #[allow(dead_code)]
+    pub fn to_kernel_termios(&self) -> Termios {
+        Termios {
+            input_mode: InputMode::from_bits_truncate(self.c_iflag),
+            output_mode: OutputMode::from_bits_truncate(self.c_oflag),
+            control_mode: ControlMode::from_bits_truncate(self.c_cflag),
+            local_mode: LocalMode::from_bits_truncate(self.c_lflag),
+            control_characters: self.c_cc.clone(),
+            line: LineDisciplineType::from_line(self.c_line),
+            input_speed: self.c_ispeed,
+            output_speed: self.c_ospeed,
+        }
+    }
+}
+
+pub const INIT_CONTORL_CHARACTERS: [u8; CONTORL_CHARACTER_NUM] = [
+    b'C' - 0x40,  // VINTR
+    b'\\' - 0x40, // VQUIT
+    0o177,        // VERASE
+    b'U' - 0x40,  // VKILL
+    b'D' - 0x40,  // VEOF
+    1,            // VMIN
+    0,            // VEOL
+    0,            // VTIME
+    0,            // VEOL2
+    0,            // VSWTC
+    b'W' - 0x40,  // VWERASE
+    b'R' - 0x40,  // VREPRINT
+    b'Z' - 0x40,  // VSUSP
+    b'Q' - 0x40,  // VSTART
+    b'S' - 0x40,  // VSTOP
+    b'V' - 0x40,  // VLNEXT
+    b'O' - 0x40,  // VDISCARD
+    0,
+    0,
+];
+
+// pub const INIT_CONTORL_CHARACTERS: [u8; CONTORL_CHARACTER_NUM] = {
+//     let mut chs: [u8; CONTORL_CHARACTER_NUM] = Default::default();
+//     chs[ControlCharIndex::VINTR] = b'C' - 0x40;
+//     chs[ControlCharIndex::VQUIT] = b'\\' - 0x40;
+//     chs[ControlCharIndex::VERASE] = 0o177;
+//     chs[ControlCharIndex::VKILL] = b'U' - 0x40;
+//     chs[ControlCharIndex::VEOF] = b'D' - 0x40;
+//     chs[ControlCharIndex::VSTART] = b'Q' - 0x40;
+//     chs[ControlCharIndex::VSTOP] = b'S' - 0x40;
+//     chs[ControlCharIndex::VSUSP] = b'Z' - 0x40;
+//     chs[ControlCharIndex::VREPRINT] = b'R' - 0x40;
+//     chs[ControlCharIndex::VDISCARD] = b'O' - 0x40;
+//     chs[ControlCharIndex::VWERASE] = b'W' - 0x40;
+//     chs[ControlCharIndex::VLNEXT] = b'V' - 0x40;
+//     // chs[ContorlCharIndex::VDSUSP] = b'Y'  - 0x40;
+//     chs[ControlCharIndex::VMIN] = 1;
+//     return chs;
+// };
+
+lazy_static! {
+    pub static ref TTY_STD_TERMIOS: Termios = {
+        Termios {
+            input_mode: InputMode::ICRNL | InputMode::IXON,
+            output_mode: OutputMode::OPOST | OutputMode::ONLCR,
+            control_mode: ControlMode::B38400
+                | ControlMode::CREAD
+                | ControlMode::HUPCL
+                | ControlMode::CS8,
+            local_mode: LocalMode::ISIG
+                | LocalMode::ICANON
+                | LocalMode::ECHO
+                | LocalMode::ECHOE
+                | LocalMode::ECHOK
+                | LocalMode::ECHOCTL
+                | LocalMode::ECHOKE
+                | LocalMode::IEXTEN,
+            control_characters: INIT_CONTORL_CHARACTERS.clone(),
+            line: LineDisciplineType::NTty,
+            input_speed: 38400,
+            output_speed: 38400,
+        }
+    };
+}
+
+pub const CONTORL_CHARACTER_NUM: usize = 19;
+
+bitflags! {
+    /// termios输入特性
+    pub struct InputMode: u32 {
+        /// 如果设置了该标志,表示启用软件流控制。
+        const IXON = 0x0200;
+        /// 如果设置了该标志,表示启用输入流控制。
+        const IXOFF = 0x0400;
+        /// Map Uppercase to Lowercase on Input 将大写转换为小写
+        /// 表示不区分大小写
+        const IUCLC = 0x1000;
+        /// 如果设置了该标志,表示当输入队列满时,产生一个响铃信号。
+        const IMAXBEL = 0x2000;
+        /// 如果设置了该标志,表示输入数据被视为 UTF-8 编码。
+        const IUTF8 = 0x4000;
+
+        /// 忽略中断信号
+        const IGNBRK	= 0x001;
+        /// 检测到中断信号时生成中断(产生中断信号)
+        const BRKINT	= 0x002;
+        /// 忽略具有奇偶校验错误的字符
+        const IGNPAR	= 0x004;
+        /// 在检测到奇偶校验错误或帧错误时,将字符以 \377 标记
+        const PARMRK	= 0x008;
+        /// 启用输入奇偶校验检查
+        const INPCK	= 0x010;
+        /// 从输入字符中剥离第 8 位,即只保留低 7 位
+        const ISTRIP	= 0x020;
+        /// 表示将输入的换行符 (\n) 映射为回车符 (\r)
+        const INLCR	= 0x040;
+        /// 表示忽略回车符 (\r)
+        const IGNCR	= 0x080;
+        /// 表示将输入的回车符 (\r) 映射为换行符 (\n)
+        const ICRNL	= 0x100;
+        /// 表示在输入被停止(Ctrl-S)后,任何字符的输入都将重新启动输入
+        const IXANY	= 0x800;
+    }
+
+    /// termios输出特性
+    pub struct OutputMode: u32 {
+        /// 在输出时将换行符替换\r\n
+        const ONLCR	= 0x00002;
+        /// Map Lowercase to Uppercase on Output 输出字符时将小写字母映射为大写字母
+        const OLCUC	= 0x00004;
+
+        /// 与NL协同 配置换行符的处理方式
+        const NLDLY	= 0x00300;
+        const   NL0	= 0x00000;  // 不延迟换行
+        const   NL1	= 0x00100;  // 延迟换行(输出回车后等待一段时间再输出换行)
+        const   NL2	= 0x00200;  // NL2 和 NL3保留,暂未使用
+        const   NL3	= 0x00300;
+
+        /// 配置水平制表符的处理方式
+        const TABDLY = 0x00c00;
+        const  TAB0 = 0x00000;  // 不延迟水平制表符
+        const  TAB1 = 0x00400;  // 在输出水平制表符时,延迟到下一个设置的水平制表符位置
+        const  TAB2 = 0x00800;  // 在输出水平制表符时,延迟到下一个设置的 8 的倍数的位置
+        const  TAB3 = 0x00c00;  // TAB3 和 XTABS(与 TAB3 等效)保留,暂未使用
+        const XTABS = 0x00c00;
+
+        /// 配置回车符的处理方式
+        const CRDLY	= 0x03000;
+        const   CR0	= 0x00000;  // 不延迟回车
+        const   CR1	= 0x01000;  //  延迟回车(输出回车后等待一段时间再输出换行)
+        const   CR2	= 0x02000;  // CR2 和 CR3保留,暂未使用
+        const   CR3	= 0x03000;
+
+        /// 配置换页符(form feed)的处理方式
+        const FFDLY	= 0x04000;
+        const   FF0	= 0x00000;  // 不延迟换页
+        const   FF1	= 0x04000;  // 延迟换页
+
+        /// 配置退格符(backspace)的处理方式
+        const BSDLY	= 0x08000;
+        const   BS0	= 0x00000;  // 不延迟退格
+        const   BS1	= 0x08000;  // 延迟退格
+
+        /// 配置垂直制表符(vertical tab)的处理方式
+        const VTDLY	= 0x10000;
+        const   VT0	= 0x00000;  // 不延迟垂直制表符
+        const   VT1	= 0x10000;  // 延迟垂直制表符
+
+        /// 表示执行输出处理,即启用输出处理函数
+        const OPOST	= 0x01;
+        /// 表示将输出的回车符 (\r) 映射为换行符 (\n)
+        const OCRNL	= 0x08;
+        /// 表示在输出时,如果光标在第 0 列,则不输出回车符 (\r)
+        const ONOCR	= 0x10;
+        /// 表示将回车符 (\r) 映射为换行符 (\n)
+        const ONLRET	= 0x20;
+        /// 表示使用填充字符进行延迟。这个填充字符的默认值是空格。
+        const OFILL	= 0x40;
+        /// 表示使用删除字符 (DEL, \177) 作为填充字符
+        const OFDEL	= 0x80;
+    }
+
+    /// 配置终端设备的基本特性和控制参数
+    pub struct ControlMode: u32 {
+        /// Baud Rate Mask 指定波特率的掩码
+        const CBAUD		= 0x000000ff;
+        /// Extra Baud Bits 指定更高的波特率位
+        const CBAUDEX	= 0x00000000;
+        /// Custom Baud Rate 指定自定义波特率 如果设置了 BOTHER,则通过以下位来设置自定义的波特率值
+        const BOTHER	= 0x0000001f;
+
+        const     B0	= 0x00000000;
+        const    B50	= 0x00000001;
+        const    B75	= 0x00000002;
+        const   B110	= 0x00000003;
+        const   B134	= 0x00000004;
+        const   B150	= 0x00000005;
+        const   B200	= 0x00000006;
+        const   B300	= 0x00000007;
+        const   B600	= 0x00000008;
+        const  B1200	= 0x00000009;
+        const  B1800	= 0x0000000a;
+        const  B2400	= 0x0000000b;
+        const  B4800	= 0x0000000c;
+        const  B9600	= 0x0000000d;
+        const B19200	= 0x0000000e;
+        const B38400	= 0x0000000f;
+
+        const    B57600	= 0x00000010;
+        const   B115200	= 0x00000011;
+        const   B230400	= 0x00000012;
+        const   B460800	= 0x00000013;
+        const   B500000	= 0x00000014;
+        const   B576000	= 0x00000015;
+        const   B921600	= 0x00000016;
+        const  B1000000	= 0x00000017;
+        const  B1152000	= 0x00000018;
+        const  B1500000	= 0x00000019;
+        const  B2000000	= 0x0000001a;
+        const  B2500000	= 0x0000001b;
+        const  B3000000	= 0x0000001c;
+        const  B3500000	= 0x0000001d;
+        const  B4000000	= 0x0000001e;
+
+        /// 指定字符大小的掩码 以下位为特定字符大小
+        const CSIZE		= 0x00000300;
+        const   CS5		= 0x00000000;
+        const   CS6		= 0x00000100;
+        const   CS7		= 0x00000200;
+        const   CS8		= 0x00000300;
+
+        /// Stop Bit Select 表示使用两个停止位;否则,表示使用一个停止位
+        const CSTOPB	= 0x00000400;
+        /// 表示启用接收器。如果未设置,则禁用接收器。
+        const CREAD		= 0x00000800;
+        /// 表示启用奇偶校验。如果未设置,则禁用奇偶校验。
+        const PARENB	= 0x00001000;
+        /// 表示启用奇校验。如果未设置,则表示启用偶校验。
+        const PARODD	= 0x00002000;
+        /// 表示在终端设备被关闭时挂断线路(执行挂断操作)
+        const HUPCL		= 0x00004000;
+        /// 表示忽略调制解调器的状态(DCD、DSR、CTS 等)
+        const CLOCAL	= 0x00008000;
+        /// 指定输入波特率的掩码
+        const CIBAUD	= 0x00ff0000;
+
+        const ADDRB = 0x20000000;
+    }
+
+    /// 配置终端设备的本地模式(local mode)或控制输入处理的行为
+    pub struct LocalMode: u32 {
+        /// 启用中断字符(Ctrl-C、Ctrl-Z)
+        const ISIG	 = 0x00000080;
+        /// 表示启用规范模式,即启用行缓冲和回显。在规范模式下,输入被缓冲,并且只有在输入回车符时才会传递给应用程序。
+        const ICANON = 0x00000100;
+        /// 表示启用大写模式,即输入输出都将被转换为大写。
+        const XCASE	 = 0x00004000;
+        /// 表示启用回显(显示用户输入的字符)
+        const ECHO	 = 0x00000008;
+        /// 表示在回显时将擦除的字符用 backspace 和空格字符显示。
+        const ECHOE	 = 0x00000002;
+        /// 表示在回显时将换行符后的字符用空格字符显示。
+        const ECHOK	 = 0x00000004;
+        /// 表示在回显时将换行符显示为换行和回车符。
+        const ECHONL = 0x00000010;
+        /// 表示在收到中断(Ctrl-C)和退出(Ctrl-\)字符后,不清空输入和输出缓冲区。
+        const NOFLSH = 0x80000000;
+        /// 表示在后台进程尝试写入终端时,发送停止信号(Ctrl-S)
+        const TOSTOP = 0x00400000;
+        /// 表示在回显时,显示控制字符为 ^ 加字符。
+        const ECHOCTL= 0x00000040;
+        /// 表示在回显时显示带有 # 的换行符(为了与 echo -n 命令兼容)。
+        const ECHOPRT= 0x00000020;
+        /// 表示在回显时将 KILL 字符(Ctrl-U)用空格字符显示。
+        const ECHOKE = 0x00000001;
+        /// 表示输出正在被冲刷(flush),通常是由于输入/输出流的状态变化。
+        const FLUSHO = 0x00800000;
+        /// 表示在规范模式下,存在需要重新打印的字符。
+        const PENDIN = 0x20000000;
+        /// 表示启用实现定义的输入处理。
+        const IEXTEN = 0x00000400;
+        /// 表示启用扩展的处理函数
+        const EXTPROC= 0x10000000;
+    }
+
+    pub struct TtySetTermiosOpt: u8 {
+        const TERMIOS_FLUSH	=1;
+        const TERMIOS_WAIT	=2;
+        const TERMIOS_TERMIO	=4;
+        const TERMIOS_OLD	=8;
+    }
+}
+
+/// 对应termios中控制字符的索引
+pub struct ControlCharIndex;
+#[allow(dead_code)]
+impl ControlCharIndex {
+    pub const DISABLE_CHAR: u8 = b'\0';
+    /// 中断信号
+    pub const VINTR: usize = 0;
+    /// 退出信号
+    pub const VQUIT: usize = 1;
+    /// 退格
+    pub const VERASE: usize = 2;
+    /// 终止输入信号
+    pub const VKILL: usize = 3;
+    /// 文件结束信号 \0?
+    pub const VEOF: usize = 4;
+    /// 指定非规范模式下的最小字符数
+    pub const VMIN: usize = 5;
+    /// 换行符
+    pub const VEOL: usize = 6;
+    /// 指定非规范模式下的超时时间
+    pub const VTIME: usize = 7;
+    /// 换行符
+    pub const VEOL2: usize = 8;
+    /// 未使用,保留
+    pub const VSWTC: usize = 9;
+    /// 擦除前一个单词
+    pub const VWERASE: usize = 10;
+    /// 重新打印整行
+    pub const VREPRINT: usize = 11;
+    /// 挂起信号
+    pub const VSUSP: usize = 12;
+    /// 启动输出信号
+    pub const VSTART: usize = 13;
+    /// 停止输出信号
+    pub const VSTOP: usize = 14;
+    /// 将下一个字符视为字面值,而不是特殊字符
+    pub const VLNEXT: usize = 15;
+    /// 对应于字符丢弃信号,用于丢弃当前输入的行
+    pub const VDISCARD: usize = 16;
+}

+ 592 - 0
kernel/src/driver/tty/tty_core.rs

@@ -0,0 +1,592 @@
+use core::{fmt::Debug, sync::atomic::AtomicBool};
+
+use alloc::{string::String, sync::Arc, vec::Vec};
+use system_error::SystemError;
+
+use crate::{
+    libs::{
+        rwlock::{RwLock, RwLockReadGuard, RwLockUpgradableGuard, RwLockWriteGuard},
+        spinlock::{SpinLock, SpinLockGuard},
+        wait_queue::EventWaitQueue,
+    },
+    mm::VirtAddr,
+    net::event_poll::EPollEventType,
+    process::Pid,
+    syscall::user_access::UserBufferWriter,
+};
+
+use super::{
+    termios::{ControlMode, PosixTermios, Termios, TtySetTermiosOpt, WindowSize},
+    tty_driver::{TtyDriver, TtyDriverSubType, TtyDriverType, TtyOperation},
+    tty_ldisc::{
+        ntty::{NTtyData, NTtyLinediscipline},
+        TtyLineDiscipline,
+    },
+    tty_port::TtyPort,
+    virtual_terminal::{virtual_console::VirtualConsoleData, VIRT_CONSOLES},
+};
+
+#[derive(Debug)]
+pub struct TtyCore {
+    core: TtyCoreData,
+    /// 线路规程函数集
+    line_discipline: Arc<dyn TtyLineDiscipline>,
+}
+
+impl TtyCore {
+    pub fn new(driver: Arc<TtyDriver>, index: usize) -> Arc<Self> {
+        let name = driver.tty_line_name(index);
+        let termios = driver.init_termios();
+        let core = TtyCoreData {
+            tty_driver: driver,
+            termios: RwLock::new(termios),
+            name,
+            flags: RwLock::new(TtyFlag::empty()),
+            count: RwLock::new(0),
+            window_size: RwLock::new(WindowSize::default()),
+            read_wq: EventWaitQueue::new(),
+            write_wq: EventWaitQueue::new(),
+            port: RwLock::new(None),
+            index,
+            ctrl: SpinLock::new(TtyContorlInfo::default()),
+            closing: AtomicBool::new(false),
+            flow: SpinLock::new(TtyFlowState::default()),
+        };
+
+        return Arc::new(Self {
+            core,
+            line_discipline: Arc::new(NTtyLinediscipline {
+                data: SpinLock::new(NTtyData::new()),
+            }),
+        });
+    }
+
+    #[inline]
+    pub fn core(&self) -> &TtyCoreData {
+        return &self.core;
+    }
+
+    #[inline]
+    pub fn ldisc(&self) -> Arc<dyn TtyLineDiscipline> {
+        self.line_discipline.clone()
+    }
+
+    pub fn reopen(&self) -> Result<(), SystemError> {
+        let tty_core = self.core();
+        let driver = tty_core.driver();
+
+        if driver.tty_driver_type() == TtyDriverType::Pty
+            && driver.tty_driver_sub_type() == TtyDriverSubType::PtyMaster
+        {
+            return Err(SystemError::EIO);
+        }
+
+        // if *tty_core.count.read() == 0 {
+        //     return Err(SystemError::EAGAIN_OR_EWOULDBLOCK);
+        // }
+
+        // TODO 判断flags
+
+        tty_core.add_count();
+
+        Ok(())
+    }
+
+    #[inline]
+    pub fn set_port(&self, port: Arc<dyn TtyPort>) {
+        *self.core.port.write() = Some(port);
+    }
+
+    pub fn tty_start(&self) {
+        let mut flow = self.core.flow.lock_irqsave();
+        if !flow.stopped || flow.tco_stopped {
+            return;
+        }
+
+        flow.stopped = false;
+        let _ = self.start(self.core());
+        self.tty_wakeup();
+    }
+
+    pub fn tty_stop(&self) {
+        let mut flow = self.core.flow.lock_irqsave();
+        if flow.stopped {
+            return;
+        }
+        flow.stopped = true;
+
+        let _ = self.stop(self.core());
+    }
+
+    pub fn tty_wakeup(&self) {
+        if self.core.flags.read().contains(TtyFlag::DO_WRITE_WAKEUP) {
+            let _ = self.ldisc().write_wakeup(self.core());
+        }
+
+        self.core()
+            .write_wq
+            .wakeup(EPollEventType::EPOLLOUT.bits() as u64);
+    }
+
+    pub fn tty_mode_ioctl(
+        &self,
+        tty: Arc<TtyCore>,
+        cmd: u32,
+        arg: usize,
+    ) -> Result<usize, SystemError> {
+        match cmd {
+            TtyIoctlCmd::TCGETS => {
+                let termios = PosixTermios::from_kernel_termios(self.core.termios().clone());
+                let mut user_writer = UserBufferWriter::new(
+                    VirtAddr::new(arg).as_ptr::<PosixTermios>(),
+                    core::mem::size_of::<PosixTermios>(),
+                    true,
+                )?;
+
+                user_writer.copy_one_to_user(&termios, 0)?;
+                return Ok(0);
+            }
+            TtyIoctlCmd::TCSETSW => {
+                return self.core_set_termios(
+                    tty,
+                    VirtAddr::new(arg),
+                    TtySetTermiosOpt::TERMIOS_WAIT | TtySetTermiosOpt::TERMIOS_OLD,
+                );
+            }
+            _ => {
+                return Err(SystemError::ENOIOCTLCMD);
+            }
+        }
+    }
+
+    pub fn core_set_termios(
+        &self,
+        tty: Arc<TtyCore>,
+        arg: VirtAddr,
+        opt: TtySetTermiosOpt,
+    ) -> Result<usize, SystemError> {
+        let tmp_termios = self.core().termios().clone();
+
+        if opt.contains(TtySetTermiosOpt::TERMIOS_TERMIO) {
+            todo!()
+        } else {
+            let mut user_writer = UserBufferWriter::new(
+                arg.as_ptr::<PosixTermios>(),
+                core::mem::size_of::<PosixTermios>(),
+                true,
+            )?;
+
+            user_writer.copy_one_to_user(&tmp_termios, 0)?;
+        }
+
+        if opt.contains(TtySetTermiosOpt::TERMIOS_FLUSH) {
+            let ld = self.ldisc();
+            let _ = ld.flush_buffer(tty.clone());
+        }
+
+        if opt.contains(TtySetTermiosOpt::TERMIOS_WAIT) {
+            // TODO
+        }
+
+        self.set_termios_next(tty, tmp_termios)?;
+        Ok(0)
+    }
+
+    pub fn set_termios_next(
+        &self,
+        tty: Arc<TtyCore>,
+        new_termios: Termios,
+    ) -> Result<(), SystemError> {
+        let mut termios = self.core().termios_write();
+
+        let old_termios = termios.clone();
+
+        *termios = new_termios;
+
+        let tmp = termios.control_mode;
+        termios.control_mode ^= (tmp ^ old_termios.control_mode) & ControlMode::ADDRB;
+
+        let ret = self.set_termios(tty.clone(), old_termios);
+        if ret.is_err() {
+            termios.control_mode &= ControlMode::HUPCL | ControlMode::CREAD | ControlMode::CLOCAL;
+            termios.control_mode |= old_termios.control_mode
+                & !(ControlMode::HUPCL | ControlMode::CREAD | ControlMode::CLOCAL);
+            termios.input_speed = old_termios.input_speed;
+            termios.output_speed = old_termios.output_speed;
+        }
+
+        drop(termios);
+        let ld = self.ldisc();
+        ld.set_termios(tty, Some(old_termios))?;
+
+        Ok(())
+    }
+}
+
+#[derive(Debug)]
+pub struct TtyContorlInfo {
+    /// 前台进程pid
+    pub session: Option<Pid>,
+    /// 前台进程组id
+    pub pgid: Option<Pid>,
+
+    /// packet模式下使用,目前未用到
+    pub pktstatus: u8,
+    pub packet: bool,
+}
+
+impl Default for TtyContorlInfo {
+    fn default() -> Self {
+        Self {
+            session: None,
+            pgid: None,
+            pktstatus: Default::default(),
+            packet: Default::default(),
+        }
+    }
+}
+
+#[derive(Debug, Default)]
+pub struct TtyCoreWriteData {
+    /// 写缓冲区
+    pub write_buf: Vec<u8>,
+    /// 写入数量
+    pub write_cnt: usize,
+}
+
+#[derive(Debug, Default)]
+pub struct TtyFlowState {
+    /// 表示流控是否被停止
+    pub stopped: bool,
+    /// 表示 TCO(Transmit Continuous Operation)流控是否被停止
+    pub tco_stopped: bool,
+}
+
+#[derive(Debug)]
+pub struct TtyCoreData {
+    tty_driver: Arc<TtyDriver>,
+    termios: RwLock<Termios>,
+    name: String,
+    flags: RwLock<TtyFlag>,
+    /// 在初始化时即确定不会更改,所以这里不用加锁
+    index: usize,
+    count: RwLock<usize>,
+    /// 窗口大小
+    window_size: RwLock<WindowSize>,
+    /// 读等待队列
+    read_wq: EventWaitQueue,
+    /// 写等待队列
+    write_wq: EventWaitQueue,
+    /// 端口
+    port: RwLock<Option<Arc<dyn TtyPort>>>,
+    /// 前台进程
+    ctrl: SpinLock<TtyContorlInfo>,
+    /// 是否正在关闭
+    closing: AtomicBool,
+    /// 流控状态
+    flow: SpinLock<TtyFlowState>,
+}
+
+impl TtyCoreData {
+    #[inline]
+    pub fn driver(&self) -> Arc<TtyDriver> {
+        self.tty_driver.clone()
+    }
+
+    #[inline]
+    pub fn flow_irqsave(&self) -> SpinLockGuard<TtyFlowState> {
+        self.flow.lock_irqsave()
+    }
+
+    #[inline]
+    pub fn port(&self) -> Option<Arc<dyn TtyPort>> {
+        self.port.read().clone()
+    }
+
+    #[inline]
+    pub fn index(&self) -> usize {
+        self.index
+    }
+
+    #[inline]
+    pub fn name(&self) -> String {
+        self.name.clone()
+    }
+
+    #[inline]
+    pub fn flags(&self) -> TtyFlag {
+        self.flags.read().clone()
+    }
+
+    #[inline]
+    pub fn termios(&self) -> RwLockReadGuard<'_, Termios> {
+        self.termios.read()
+    }
+
+    #[inline]
+    pub fn termios_write(&self) -> RwLockWriteGuard<Termios> {
+        self.termios.write()
+    }
+
+    #[inline]
+    pub fn set_termios(&self, termios: Termios) {
+        let mut termios_guard = self.termios.write();
+        *termios_guard = termios;
+    }
+
+    #[inline]
+    pub fn add_count(&self) {
+        let mut guard = self.count.write();
+        *guard += 1;
+    }
+
+    #[inline]
+    pub fn read_wq(&self) -> &EventWaitQueue {
+        &self.read_wq
+    }
+
+    #[inline]
+    pub fn write_wq(&self) -> &EventWaitQueue {
+        &self.write_wq
+    }
+
+    #[inline]
+    pub fn contorl_info_irqsave(&self) -> SpinLockGuard<TtyContorlInfo> {
+        self.ctrl.lock_irqsave()
+    }
+
+    #[inline]
+    pub fn window_size_upgradeable(&self) -> RwLockUpgradableGuard<WindowSize> {
+        self.window_size.upgradeable_read()
+    }
+
+    #[inline]
+    pub fn window_size(&self) -> RwLockReadGuard<WindowSize> {
+        self.window_size.read()
+    }
+
+    #[inline]
+    pub fn is_closing(&self) -> bool {
+        self.closing.load(core::sync::atomic::Ordering::SeqCst)
+    }
+
+    #[inline]
+    pub fn vc_data_irqsave(&self) -> SpinLockGuard<VirtualConsoleData> {
+        VIRT_CONSOLES[self.index].lock_irqsave()
+    }
+}
+
+/// TTY 核心接口,不同的tty需要各自实现这个trait
+pub trait TtyCoreFuncs: Debug + Send + Sync {}
+
+impl TtyOperation for TtyCore {
+    #[inline]
+    fn open(&self, tty: &TtyCoreData) -> Result<(), SystemError> {
+        return self.core().tty_driver.driver_funcs().open(tty);
+    }
+
+    #[inline]
+    fn write_room(&self, tty: &TtyCoreData) -> usize {
+        return self.core().tty_driver.driver_funcs().write_room(tty);
+    }
+
+    #[inline]
+    fn write(&self, tty: &TtyCoreData, buf: &[u8], nr: usize) -> Result<usize, SystemError> {
+        return self.core().tty_driver.driver_funcs().write(tty, buf, nr);
+    }
+
+    #[inline]
+    fn flush_chars(&self, tty: &TtyCoreData) {
+        self.core().tty_driver.driver_funcs().flush_chars(tty);
+    }
+
+    #[inline]
+    fn put_char(&self, tty: &TtyCoreData, ch: u8) -> Result<(), SystemError> {
+        return self.core().tty_driver.driver_funcs().put_char(tty, ch);
+    }
+
+    #[inline]
+    fn install(&self, driver: Arc<TtyDriver>, tty: Arc<TtyCore>) -> Result<(), SystemError> {
+        return self.core().tty_driver.driver_funcs().install(driver, tty);
+    }
+
+    #[inline]
+    fn start(&self, tty: &TtyCoreData) -> Result<(), SystemError> {
+        return self.core().tty_driver.driver_funcs().start(tty);
+    }
+
+    #[inline]
+    fn stop(&self, tty: &TtyCoreData) -> Result<(), SystemError> {
+        return self.core().tty_driver.driver_funcs().stop(tty);
+    }
+
+    #[inline]
+    fn ioctl(&self, tty: Arc<TtyCore>, cmd: u32, arg: usize) -> Result<(), SystemError> {
+        return self.core().tty_driver.driver_funcs().ioctl(tty, cmd, arg);
+    }
+
+    #[inline]
+    fn chars_in_buffer(&self) -> usize {
+        return self.core().tty_driver.driver_funcs().chars_in_buffer();
+    }
+
+    #[inline]
+    fn set_termios(&self, tty: Arc<TtyCore>, old_termios: Termios) -> Result<(), SystemError> {
+        return self
+            .core()
+            .tty_driver
+            .driver_funcs()
+            .set_termios(tty, old_termios);
+    }
+}
+
+bitflags! {
+    pub struct TtyFlag: u32 {
+        /// 终端被节流
+        const THROTTLED		= 1 << 0;
+        /// 终端输入输出错误状态
+        const IO_ERROR		= 1 << 1;
+        /// 终端的其他一方已关闭
+        const OTHER_CLOSED	= 1 << 2;
+        /// 终端处于独占状态
+        const EXCLUSIVE		= 1 << 3;
+        /// 终端执行写唤醒操作
+        const DO_WRITE_WAKEUP	= 1 << 5;
+        /// 终端线路驱动程序已打开
+        const LDISC_OPEN		= 1 << 11;
+        /// 终端伪终端设备已锁定
+        const PTY_LOCK		= 1 << 16;
+        /// 终端禁用写分裂操作
+        const NO_WRITE_SPLIT	= 1 << 17;
+        /// 终端挂断(挂起)状态
+        const HUPPED		= 1 << 18;
+        /// 终端正在挂断(挂起)
+        const HUPPING		= 1 << 19;
+        /// 终端线路驱动程序正在更改
+        const LDISC_CHANGING	= 1 << 20;
+        /// 终端线路驱动程序已停止
+        const LDISC_HALTED	= 1 << 22;
+    }
+}
+
+#[derive(Debug, PartialEq)]
+pub enum EchoOperation {
+    /// 开始特殊操作。
+    Start,
+    /// 向后移动光标列。
+    MoveBackCol,
+    /// 设置规范模式下的列位置。
+    SetCanonCol,
+    /// 擦除制表符。
+    EraseTab,
+
+    Undefined(u8),
+}
+
+impl EchoOperation {
+    pub fn from_u8(num: u8) -> EchoOperation {
+        match num {
+            0xff => Self::Start,
+            0x80 => Self::MoveBackCol,
+            0x81 => Self::SetCanonCol,
+            0x82 => Self::EraseTab,
+            _ => Self::Undefined(num),
+        }
+    }
+
+    pub fn to_u8(&self) -> u8 {
+        match *self {
+            EchoOperation::Start => 0xff,
+            EchoOperation::MoveBackCol => 0x80,
+            EchoOperation::SetCanonCol => 0x81,
+            EchoOperation::EraseTab => 0x82,
+            EchoOperation::Undefined(num) => num,
+        }
+    }
+}
+
+pub struct TtyIoctlCmd;
+
+#[allow(dead_code)]
+impl TtyIoctlCmd {
+    /// 获取终端参数
+    pub const TCGETS: u32 = 0x5401;
+    /// 设置终端参数
+    pub const TCSETS: u32 = 0x5402;
+    /// 设置终端参数并等待所有输出完成
+    pub const TCSETSW: u32 = 0x5403;
+    /// 设置终端参数并且等待所有输出完成,但在这之前将终端清空
+    pub const TCSETSF: u32 = 0x5404;
+    /// 获取终端参数
+    pub const TCGETA: u32 = 0x5405;
+    /// 设置终端参数
+    pub const TCSETA: u32 = 0x5406;
+    /// 设置终端参数并等待所有输出完成
+    pub const TCSETAW: u32 = 0x5407;
+    /// 设置终端参数并且等待所有输出完成,但在这之前将终端清空
+    pub const TCSETAF: u32 = 0x5408;
+    /// 发送零字节,等待所有输出完成
+    pub const TCSBRK: u32 = 0x5409;
+    /// 控制终端的流控
+    pub const TCXONC: u32 = 0x540A;
+    /// 刷新输入/输出缓冲区或者丢弃输入缓冲区
+    pub const TCFLSH: u32 = 0x540B;
+    /// 设置设备为独占模式
+    pub const TIOCEXCL: u32 = 0x540C;
+    /// 设置设备为非独占模式
+    pub const TIOCNXCL: u32 = 0x540D;
+    /// 设置当前进程的控制终端
+    pub const TIOCSCTTY: u32 = 0x540E;
+    /// 获取前台进程组
+    pub const TIOCGPGRP: u32 = 0x540F;
+    ///设置前台进程组
+    pub const TIOCSPGRP: u32 = 0x5410;
+    /// 获取输出队列的字节数
+    pub const TIOCOUTQ: u32 = 0x5411;
+    /// 模拟从终端输入字符
+    pub const TIOCSTI: u32 = 0x5412;
+    /// 获取窗口大小
+    pub const TIOCGWINSZ: u32 = 0x5413;
+    /// 设置窗口大小
+    pub const TIOCSWINSZ: u32 = 0x5414;
+    /// 获取终端控制信号的状态
+    pub const TIOCMGET: u32 = 0x5415;
+    /// 设置终端控制信号的位
+    pub const TIOCMBIS: u32 = 0x5416;
+    /// 清除终端控制信号的位
+    pub const TIOCMBIC: u32 = 0x5417;
+    /// 设置终端控制信号的状态
+    pub const TIOCMSET: u32 = 0x5418;
+    /// 获取软件载波状态
+    pub const TIOCGSOFTCAR: u32 = 0x5419;
+    /// 设置软件载波状态
+    pub const TIOCSSOFTCAR: u32 = 0x541A;
+    /// 获取输入队列的字节数
+    pub const FIONREAD: u32 = 0x541B;
+    /// Linux 特有命令
+    pub const TIOCLINUX: u32 = 0x541C;
+    /// 获取控制台设备
+    pub const TIOCCONS: u32 = 0x541D;
+    /// 获取串行设备参数
+    pub const TIOCGSERIAL: u32 = 0x541E;
+    /// 设置串行设备参数
+    pub const TIOCSSERIAL: u32 = 0x541F;
+    /// 设置套接字的报文模式
+    pub const TIOCPKT: u32 = 0x5420;
+    /// 设置非阻塞 I/O
+    pub const FIONBIO: u32 = 0x5421;
+    /// 清除控制终端
+    pub const TIOCNOTTY: u32 = 0x5422;
+    /// 设置终端线路驱动器
+    pub const TIOCSETD: u32 = 0x5423;
+    /// 获取终端线路驱动器
+    pub const TIOCGETD: u32 = 0x5424;
+    /// 发送终止条件
+    pub const TCSBRKP: u32 = 0x5425;
+    /// 开始发送零比特
+    pub const TIOCSBRK: u32 = 0x5427;
+    /// 停止发送零比特
+    pub const TIOCCBRK: u32 = 0x5428;
+    /// Return the session ID of FD
+    pub const TIOCGSID: u32 = 0x5429;
+}

+ 399 - 224
kernel/src/driver/tty/tty_device.rs

@@ -1,5 +1,4 @@
 use alloc::{
-    collections::BTreeMap,
     string::{String, ToString},
     sync::{Arc, Weak},
 };
@@ -7,143 +6,138 @@ use system_error::SystemError;
 use unified_init::macros::unified_init;
 
 use crate::{
+    arch::ipc::signal::Signal,
+    driver::{
+        base::{
+            char::CharDevice,
+            device::{
+                bus::Bus,
+                device_number::{DeviceNumber, Major},
+                device_register,
+                driver::Driver,
+                Device, DeviceKObjType, DeviceType, IdTable,
+            },
+            kobject::{KObject, LockedKObjectState},
+            kset::KSet,
+        },
+        serial::serial_init,
+    },
     filesystem::{
         devfs::{devfs_register, DevFS, DeviceINode},
-        vfs::{
-            file::FileMode, syscall::ModeType, FilePrivateData, FileType, IndexNode, Metadata,
-            ROOT_INODE,
-        },
+        kernfs::KernFSInode,
+        vfs::{file::FileMode, syscall::ModeType, FilePrivateData, FileType, IndexNode, Metadata},
     },
     init::initcall::INITCALL_DEVICE,
-    kerror,
-    libs::{
-        lib_ui::textui::{textui_putchar, FontColor},
-        rwlock::RwLock,
-    },
+    libs::rwlock::RwLock,
+    mm::VirtAddr,
+    process::ProcessManager,
+    syscall::user_access::UserBufferWriter,
+};
+
+use super::{
+    termios::WindowSize,
+    tty_core::{TtyCore, TtyFlag, TtyIoctlCmd},
+    tty_driver::{TtyDriver, TtyDriverSubType, TtyDriverType, TtyOperation},
+    tty_job_control::TtyJobCtrlManager,
+    virtual_terminal::vty_init,
 };
 
-use super::{serial::serial_init, TtyCore, TtyError, TtyFileFlag, TtyFilePrivateData};
+#[derive(Debug)]
+pub struct InnerTtyDevice {
+    /// 当前设备所述的kset
+    kset: Option<Arc<KSet>>,
+    parent_kobj: Option<Weak<dyn KObject>>,
+    /// 当前设备所述的总线
+    bus: Option<Weak<dyn Bus>>,
+    inode: Option<Arc<KernFSInode>>,
+    driver: Option<Weak<dyn Driver>>,
+    can_match: bool,
+
+    metadata: Metadata,
+}
 
-lazy_static! {
-    /// 所有TTY设备的B树。用于根据名字,找到Arc<TtyDevice>
-    /// TODO: 待设备驱动模型完善,具有类似功能的机制后,删掉这里
-    pub static ref TTY_DEVICES: RwLock<BTreeMap<String, Arc<TtyDevice>>> = RwLock::new(BTreeMap::new());
+impl InnerTtyDevice {
+    pub fn new() -> Self {
+        Self {
+            kset: None,
+            parent_kobj: None,
+            bus: None,
+            inode: None,
+            driver: None,
+            can_match: false,
+            metadata: Metadata::new(FileType::CharDevice, ModeType::from_bits_truncate(0o755)),
+        }
+    }
 }
 
-/// @brief TTY设备
 #[derive(Debug)]
+#[cast_to([sync] Device)]
 pub struct TtyDevice {
-    /// TTY核心
-    core: TtyCore,
+    name: &'static str,
+    id_table: IdTable,
+    inner: RwLock<InnerTtyDevice>,
+    kobj_state: LockedKObjectState,
     /// TTY所属的文件系统
     fs: RwLock<Weak<DevFS>>,
-    /// TTY设备私有信息
-    private_data: RwLock<TtyDevicePrivateData>,
-}
-
-#[derive(Debug)]
-struct TtyDevicePrivateData {
-    /// TTY设备名(如tty1)
-    name: String,
-    /// TTY设备文件的元数据
-    metadata: Metadata,
-    // TODO: 增加指向输出端口连接的设备的指针
 }
 
 impl TtyDevice {
-    pub fn new(name: &str) -> Arc<TtyDevice> {
-        let result = Arc::new(TtyDevice {
-            core: TtyCore::new(),
+    pub fn new(name: &'static str, id_table: IdTable) -> Arc<TtyDevice> {
+        let dev_num = id_table.device_number();
+        let dev = TtyDevice {
+            name,
+            id_table,
+            inner: RwLock::new(InnerTtyDevice::new()),
+            kobj_state: LockedKObjectState::new(None),
             fs: RwLock::new(Weak::default()),
-            private_data: TtyDevicePrivateData::new(name),
-        });
-        // 默认开启输入回显
-        result.core.enable_echo();
-        return result;
-    }
+        };
 
-    /// @brief 判断文件私有信息是否为TTY文件的私有信息
-    #[inline]
-    fn verify_file_private_data<'a>(
-        &self,
-        private_data: &'a mut FilePrivateData,
-    ) -> Result<&'a mut TtyFilePrivateData, SystemError> {
-        if let FilePrivateData::Tty(t) = private_data {
-            return Ok(t);
-        }
-        return Err(SystemError::EIO);
-    }
+        dev.inner.write().metadata.raw_dev = dev_num;
 
-    /// @brief 获取TTY设备名
-    #[inline]
-    pub fn name(&self) -> String {
-        return self.private_data.read().name.clone();
+        Arc::new(dev)
     }
+}
 
-    /// @brief 检查TTY文件的读写参数是否合法
-    #[inline]
-    pub fn check_rw_param(&self, len: usize, buf: &[u8]) -> Result<(), SystemError> {
-        if len > buf.len() {
-            return Err(SystemError::EINVAL);
-        }
-        return Ok(());
-    }
+impl IndexNode for TtyDevice {
+    fn open(
+        &self,
+        data: &mut crate::filesystem::vfs::FilePrivateData,
+        mode: &crate::filesystem::vfs::file::FileMode,
+    ) -> Result<(), SystemError> {
+        let dev_num = self.metadata()?.raw_dev;
 
-    /// @brief 向TTY的输入端口导入数据
-    pub fn input(&self, buf: &[u8]) -> Result<usize, SystemError> {
-        let r: Result<usize, TtyError> = self.core.input(buf, false);
-        if r.is_ok() {
-            return Ok(r.unwrap());
-        }
+        let tty = TtyDriver::open_tty(dev_num)?;
 
-        let r = r.unwrap_err();
-        match r {
-            TtyError::BufferFull(x) => return Ok(x),
-            TtyError::Closed => return Err(SystemError::ENODEV),
-            e => {
-                kerror!("tty error occurred while writing data to its input port, msg={e:?}");
-                return Err(SystemError::EBUSY);
+        // 设置privdata
+        *data = FilePrivateData::Tty(TtyFilePrivateData {
+            tty: tty.clone(),
+            mode: *mode,
+        });
+
+        let ret = tty.open(tty.core());
+        if ret.is_err() {
+            let err = ret.unwrap_err();
+            if err == SystemError::ENOSYS {
+                return Err(SystemError::ENODEV);
             }
+            return Err(err);
         }
-    }
-}
-
-impl DeviceINode for TtyDevice {
-    fn set_fs(&self, fs: alloc::sync::Weak<crate::filesystem::devfs::DevFS>) {
-        *self.fs.write() = fs;
-    }
-}
 
-impl IndexNode for TtyDevice {
-    /// @brief 打开TTY设备
-    ///
-    /// @param data 文件私有信息
-    /// @param mode 打开模式
-    ///
-    /// TTY设备通过mode来确定这个文件到底是stdin/stdout/stderr
-    /// - mode的值为O_RDONLY时,表示这个文件是stdin
-    /// - mode的值为O_WRONLY时,表示这个文件是stdout
-    /// - mode的值为O_WRONLY | O_SYNC时,表示这个文件是stderr
-    fn open(&self, data: &mut FilePrivateData, mode: &FileMode) -> Result<(), SystemError> {
-        let mut p = TtyFilePrivateData::default();
-
-        // 检查打开模式
-        let accmode = mode.accmode();
-        if accmode == FileMode::O_RDONLY.accmode() {
-            p.flags.insert(TtyFileFlag::STDIN);
-        } else if accmode == FileMode::O_WRONLY.accmode() {
-            if mode.contains(FileMode::O_SYNC) {
-                p.flags.insert(TtyFileFlag::STDERR);
-            } else {
-                p.flags.insert(TtyFileFlag::STDOUT);
+        let driver = tty.core().driver();
+        // 考虑noctty(当前tty)
+        if !(mode.contains(FileMode::O_NOCTTY) && dev_num == DeviceNumber::new(Major::TTY_MAJOR, 0)
+            || dev_num == DeviceNumber::new(Major::TTYAUX_MAJOR, 1)
+            || (driver.tty_driver_type() == TtyDriverType::Pty
+                && driver.tty_driver_sub_type() == TtyDriverSubType::PtyMaster))
+        {
+            let pcb = ProcessManager::current_pcb();
+            let pcb_tty = pcb.sig_info().tty();
+            if pcb_tty.is_none() && tty.core().contorl_info_irqsave().session.is_none() {
+                TtyJobCtrlManager::proc_set_tty(tty);
             }
-        } else {
-            return Err(SystemError::EINVAL);
         }
 
-        // 保存文件私有信息
-        *data = FilePrivateData::Tty(p);
-        return Ok(());
+        Ok(())
     }
 
     fn read_at(
@@ -152,32 +146,38 @@ impl IndexNode for TtyDevice {
         len: usize,
         buf: &mut [u8],
         data: &mut crate::filesystem::vfs::FilePrivateData,
-    ) -> Result<usize, SystemError> {
-        let _data: &mut TtyFilePrivateData = match self.verify_file_private_data(data) {
-            Ok(t) => t,
-            Err(e) => {
-                kerror!("Try to read tty device, but file private data type mismatch!");
-                return Err(e);
-            }
+    ) -> Result<usize, system_error::SystemError> {
+        let (tty, mode) = if let FilePrivateData::Tty(tty_priv) = data {
+            (tty_priv.tty.clone(), tty_priv.mode)
+        } else {
+            return Err(SystemError::EIO);
         };
-        self.check_rw_param(len, buf)?;
 
-        // 读取stdin队列
-        let r: Result<usize, TtyError> = self.core.read_stdin(&mut buf[0..len], true);
-        if r.is_ok() {
-            return Ok(r.unwrap());
-        }
+        let ld = tty.ldisc();
+        let mut offset = 0;
+        let mut cookie = false;
+        loop {
+            let mut size = if len > buf.len() { buf.len() } else { len };
+            size = ld.read(tty.clone(), buf, size, &mut cookie, offset, mode)?;
+            // 没有更多数据
+            if size == 0 {
+                break;
+            }
+
+            offset += size;
 
-        match r.unwrap_err() {
-            TtyError::EOF(n) => {
-                return Ok(n);
+            // 缓冲区写满
+            if offset >= len {
+                break;
             }
 
-            x => {
-                kerror!("Error occurred when reading tty, msg={x:?}");
-                return Err(SystemError::ECONNABORTED);
+            // 没有更多数据
+            if !cookie {
+                break;
             }
         }
+
+        return Ok(offset);
     }
 
     fn write_at(
@@ -186,147 +186,322 @@ impl IndexNode for TtyDevice {
         len: usize,
         buf: &[u8],
         data: &mut crate::filesystem::vfs::FilePrivateData,
-    ) -> Result<usize, SystemError> {
-        let data: &mut TtyFilePrivateData = match self.verify_file_private_data(data) {
-            Ok(t) => t,
-            Err(e) => {
-                kerror!("Try to write tty device, but file private data type mismatch!");
-                return Err(e);
-            }
+    ) -> Result<usize, system_error::SystemError> {
+        let mut count = len;
+        let (tty, mode) = if let FilePrivateData::Tty(tty_priv) = data {
+            (tty_priv.tty.clone(), tty_priv.mode)
+        } else {
+            return Err(SystemError::EIO);
         };
 
-        self.check_rw_param(len, buf)?;
-
-        let mut cnt: usize = 0;
-        // 根据当前文件是stdout还是stderr,选择不同的发送方式
-        let r: Result<usize, TtyError> = if data.flags.contains(TtyFileFlag::STDOUT) {
-            loop {
-                let r = self.core.stdout(&buf[cnt..len], false);
-                if let Err(TtyError::BufferFull(c)) = r {
-                    self.sync().expect("Failed to sync tty device!");
-                    cnt += c;
-                } else {
-                    break r;
-                }
+        let ld = tty.ldisc();
+        let core = tty.core();
+        let mut chunk = 2048;
+        if core.flags().contains(TtyFlag::NO_WRITE_SPLIT) {
+            chunk = 65536;
+        }
+        chunk = chunk.min(count);
+
+        let pcb = ProcessManager::current_pcb();
+        let mut written = 0;
+        loop {
+            // 至少需要写多少
+            let size = chunk.min(count);
+
+            // 将数据从buf拷贝到writebuf
+
+            let ret = ld.write(tty.clone(), buf, size, mode)?;
+
+            written += ret;
+            count -= ret;
+
+            if count == 0 {
+                break;
             }
-        } else if data.flags.contains(TtyFileFlag::STDERR) {
-            loop {
-                let r = self.core.stderr(&buf[cnt..len], false);
-                if let Err(TtyError::BufferFull(c)) = r {
-                    self.sync().expect("Failed to sync tty device!");
-                    cnt += c;
-                } else {
-                    break r;
-                }
+
+            if pcb.sig_info().sig_pending().has_pending() {
+                return Err(SystemError::ERESTARTSYS);
             }
-        } else {
-            return Err(SystemError::EPERM);
-        };
+        }
 
-        if r.is_ok() {
-            self.sync().expect("Failed to sync tty device!");
-            return Ok(cnt + r.unwrap());
+        if written > 0 {
+            // todo: 更新时间
         }
 
-        let r: TtyError = r.unwrap_err();
-        kerror!("Error occurred when writing tty deivce. Error msg={r:?}");
-        return Err(SystemError::EIO);
+        Ok(written)
     }
 
     fn fs(&self) -> Arc<dyn crate::filesystem::vfs::FileSystem> {
-        return self.fs.read().upgrade().unwrap();
+        todo!()
     }
 
     fn as_any_ref(&self) -> &dyn core::any::Any {
-        self
+        todo!()
     }
 
-    fn list(&self) -> Result<alloc::vec::Vec<alloc::string::String>, SystemError> {
-        return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
+    fn list(&self) -> Result<alloc::vec::Vec<alloc::string::String>, system_error::SystemError> {
+        todo!()
     }
 
-    fn metadata(&self) -> Result<Metadata, SystemError> {
-        return Ok(self.private_data.read().metadata.clone());
+    fn metadata(&self) -> Result<crate::filesystem::vfs::Metadata, SystemError> {
+        Ok(self.inner.read().metadata.clone())
     }
 
     fn close(&self, _data: &mut FilePrivateData) -> Result<(), SystemError> {
-        return Ok(());
+        Ok(())
     }
 
-    fn sync(&self) -> Result<(), SystemError> {
-        // TODO: 引入IO重定向后,需要将输出重定向到对应的设备。
-        // 目前只是简单的输出到屏幕(为了实现的简便)
+    fn resize(&self, _len: usize) -> Result<(), SystemError> {
+        Ok(())
+    }
 
-        loop {
-            let mut buf = [0u8; 512];
-            let r: Result<usize, TtyError> = self.core.output(&mut buf[0..511], false);
-            let len;
-            match r {
-                Ok(x) => {
-                    len = x;
-                }
-                Err(TtyError::EOF(x)) | Err(TtyError::BufferEmpty(x)) => {
-                    len = x;
+    fn ioctl(&self, cmd: u32, arg: usize, data: &FilePrivateData) -> Result<usize, SystemError> {
+        let (tty, _) = if let FilePrivateData::Tty(tty_priv) = data {
+            (tty_priv.tty.clone(), tty_priv.mode)
+        } else {
+            return Err(SystemError::EIO);
+        };
+
+        match cmd {
+            TtyIoctlCmd::TIOCSETD
+            | TtyIoctlCmd::TIOCSBRK
+            | TtyIoctlCmd::TIOCCBRK
+            | TtyIoctlCmd::TCSBRK
+            | TtyIoctlCmd::TCSBRKP => {
+                TtyJobCtrlManager::tty_check_change(tty.clone(), Signal::SIGTTOU)?;
+                if cmd != TtyIoctlCmd::TIOCCBRK {
+                    todo!()
                 }
-                _ => return Err(SystemError::EIO),
             }
+            _ => {}
+        }
 
-            if len == 0 {
-                break;
+        match cmd {
+            TtyIoctlCmd::TIOCGWINSZ => {
+                let core = tty.core();
+                let winsize = *core.window_size();
+
+                let mut user_writer = UserBufferWriter::new(
+                    VirtAddr::new(arg).as_ptr::<WindowSize>(),
+                    core::mem::size_of::<WindowSize>(),
+                    true,
+                )?;
+
+                let err = user_writer.copy_one_to_user(&winsize, 0);
+                if err.is_err() {
+                    return Err(SystemError::EFAULT);
+                }
+                return Ok(0);
             }
-            // 输出到屏幕
+            _ => match TtyJobCtrlManager::job_ctrl_ioctl(tty.clone(), cmd, arg) {
+                Ok(_) => {
+                    return Ok(0);
+                }
+                Err(e) => {
+                    if e != SystemError::ENOIOCTLCMD {
+                        return Err(e);
+                    }
+                }
+            },
+        }
 
-            for x in 0..len {
-                textui_putchar(buf[x] as char, FontColor::WHITE, FontColor::BLACK).ok();
+        match tty.ioctl(tty.clone(), cmd, arg) {
+            Ok(_) => {
+                return Ok(0);
+            }
+            Err(e) => {
+                if e != SystemError::ENOIOCTLCMD {
+                    return Err(e);
+                }
             }
         }
-        return Ok(());
+        tty.ldisc().ioctl(tty, cmd, arg)?;
+
+        Ok(0)
     }
-    fn resize(&self, _len: usize) -> Result<(), SystemError> {
-        return Ok(());
+}
+
+impl DeviceINode for TtyDevice {
+    fn set_fs(&self, fs: alloc::sync::Weak<crate::filesystem::devfs::DevFS>) {
+        *self.fs.write() = fs;
     }
 }
 
-impl TtyDevicePrivateData {
-    pub fn new(name: &str) -> RwLock<Self> {
-        let mut metadata = Metadata::new(FileType::CharDevice, ModeType::from_bits_truncate(0o755));
-        metadata.size = TtyCore::STDIN_BUF_SIZE as i64;
-        return RwLock::new(TtyDevicePrivateData {
-            name: name.to_string(),
-            metadata,
-        });
+impl KObject for TtyDevice {
+    fn as_any_ref(&self) -> &dyn core::any::Any {
+        self
+    }
+
+    fn set_inode(&self, inode: Option<Arc<crate::filesystem::kernfs::KernFSInode>>) {
+        self.inner.write().inode = inode;
+    }
+
+    fn inode(&self) -> Option<Arc<crate::filesystem::kernfs::KernFSInode>> {
+        self.inner.read().inode.clone()
+    }
+
+    fn parent(&self) -> Option<alloc::sync::Weak<dyn KObject>> {
+        self.inner.read().parent_kobj.clone()
+    }
+
+    fn set_parent(&self, parent: Option<alloc::sync::Weak<dyn KObject>>) {
+        self.inner.write().parent_kobj = parent
+    }
+
+    fn kset(&self) -> Option<Arc<crate::driver::base::kset::KSet>> {
+        self.inner.read().kset.clone()
+    }
+
+    fn set_kset(&self, kset: Option<Arc<crate::driver::base::kset::KSet>>) {
+        self.inner.write().kset = kset
+    }
+
+    fn kobj_type(&self) -> Option<&'static dyn crate::driver::base::kobject::KObjType> {
+        Some(&DeviceKObjType)
+    }
+
+    fn set_kobj_type(&self, _ktype: Option<&'static dyn crate::driver::base::kobject::KObjType>) {}
+
+    fn name(&self) -> alloc::string::String {
+        self.name.to_string()
+    }
+
+    fn set_name(&self, _name: alloc::string::String) {
+        // self.name = name
+    }
+
+    fn kobj_state(
+        &self,
+    ) -> crate::libs::rwlock::RwLockReadGuard<crate::driver::base::kobject::KObjectState> {
+        self.kobj_state.read()
+    }
+
+    fn kobj_state_mut(
+        &self,
+    ) -> crate::libs::rwlock::RwLockWriteGuard<crate::driver::base::kobject::KObjectState> {
+        self.kobj_state.write()
+    }
+
+    fn set_kobj_state(&self, state: crate::driver::base::kobject::KObjectState) {
+        *self.kobj_state.write() = state
     }
 }
 
-/// @brief 初始化TTY设备
-#[unified_init(INITCALL_DEVICE)]
-pub fn tty_init() -> Result<(), SystemError> {
-    let tty: Arc<TtyDevice> = TtyDevice::new("tty0");
-    let devfs_root_inode = ROOT_INODE().lookup("/dev");
-    if devfs_root_inode.is_err() {
-        return Err(devfs_root_inode.unwrap_err());
+impl Device for TtyDevice {
+    fn dev_type(&self) -> crate::driver::base::device::DeviceType {
+        DeviceType::Char
+    }
+
+    fn id_table(&self) -> crate::driver::base::device::IdTable {
+        self.id_table.clone()
+    }
+
+    fn set_bus(&self, bus: Option<alloc::sync::Weak<dyn crate::driver::base::device::bus::Bus>>) {
+        self.inner.write().bus = bus
+    }
+
+    fn set_class(&self, _class: Option<Arc<dyn crate::driver::base::class::Class>>) {
+        todo!()
+    }
+
+    fn driver(&self) -> Option<Arc<dyn crate::driver::base::device::driver::Driver>> {
+        self.inner.read().driver.clone()?.upgrade()
+    }
+
+    fn set_driver(
+        &self,
+        driver: Option<alloc::sync::Weak<dyn crate::driver::base::device::driver::Driver>>,
+    ) {
+        self.inner.write().driver = driver
+    }
+
+    fn is_dead(&self) -> bool {
+        false
     }
-    // 当前关闭键盘输入回显
-    // TODO: 完善Termios之后, 改为默认开启键盘输入回显.
-    tty.core.disable_echo();
-    let guard = TTY_DEVICES.upgradeable_read();
 
-    // 如果已经存在了这个设备
-    if guard.contains_key("tty0") {
-        return Err(SystemError::EEXIST);
+    fn can_match(&self) -> bool {
+        self.inner.read().can_match
     }
 
-    let mut guard = guard.upgrade();
+    fn set_can_match(&self, can_match: bool) {
+        self.inner.write().can_match = can_match
+    }
 
-    guard.insert("tty0".to_string(), tty.clone());
+    fn state_synced(&self) -> bool {
+        true
+    }
+}
 
-    drop(guard);
+impl CharDevice for TtyDevice {
+    fn read(&self, _len: usize, _buf: &mut [u8]) -> Result<usize, SystemError> {
+        todo!()
+    }
 
-    let r = devfs_register(&tty.name(), tty);
-    if r.is_err() {
-        return Err(devfs_root_inode.unwrap_err());
+    fn write(&self, _len: usize, _buf: &[u8]) -> Result<usize, SystemError> {
+        todo!()
     }
 
+    fn sync(&self) -> Result<(), SystemError> {
+        todo!()
+    }
+}
+
+#[derive(Debug, Clone)]
+pub struct TtyFilePrivateData {
+    tty: Arc<TtyCore>,
+    mode: FileMode,
+}
+
+/// 初始化tty设备和console子设备
+#[unified_init(INITCALL_DEVICE)]
+#[inline(never)]
+pub fn tty_init() -> Result<(), SystemError> {
+    let tty = TtyDevice::new(
+        "tty0",
+        IdTable::new(
+            String::from("tty0"),
+            Some(DeviceNumber::new(Major::TTY_MAJOR, 0)),
+        ),
+    );
+
+    let console = TtyDevice::new(
+        "console",
+        IdTable::new(
+            String::from("console"),
+            Some(DeviceNumber::new(Major::TTYAUX_MAJOR, 1)),
+        ),
+    );
+
+    // 注册tty设备
+    // CharDevOps::cdev_add(
+    //     tty.clone() as Arc<dyn CharDevice>,
+    // IdTable::new(
+    //     String::from("tty0"),
+    //     Some(DeviceNumber::new(Major::TTYAUX_MAJOR, 0)),
+    // ),
+    //     1,
+    // )?;
+
+    // CharDevOps::register_chardev_region(DeviceNumber::new(Major::TTYAUX_MAJOR, 0), 1, "/dev/tty")?;
+
+    // 注册console设备
+    // CharDevOps::cdev_add(
+    //     console.clone() as Arc<dyn CharDevice>,
+    //     IdTable::new(
+    //         String::from("console"),
+    //         Some(DeviceNumber::new(Major::TTYAUX_MAJOR, 1)),
+    //     ),
+    //     1,
+    // )?;
+
+    // CharDevOps::register_chardev_region(DeviceNumber::new(Major::TTYAUX_MAJOR, 1), 1, "/dev/tty")?;
+
+    // 将这两个设备注册到devfs,TODO:这里console设备应该与tty在一个设备group里面
+    device_register(tty.clone())?;
+    device_register(console.clone())?;
+    devfs_register(tty.name, tty)?;
+    devfs_register(console.name, console)?;
+
     serial_init()?;
-    return Ok(());
+    return vty_init();
 }

+ 429 - 44
kernel/src/driver/tty/tty_driver.rs

@@ -1,61 +1,446 @@
-use core::fmt::Debug;
+use core::{fmt::Debug, sync::atomic::Ordering};
 
-use alloc::sync::Arc;
+use alloc::{string::String, sync::Arc, vec::Vec};
+use hashbrown::HashMap;
+use system_error::SystemError;
 
-use crate::driver::base::device::driver::Driver;
+use crate::{
+    driver::{
+        base::{
+            char::CharDevOps,
+            device::{
+                device_number::{DeviceNumber, Major},
+                driver::Driver,
+            },
+            kobject::KObject,
+        },
+        tty::tty_port::TtyPortState,
+    },
+    libs::spinlock::SpinLock,
+};
 
-use super::tty_device::TtyDevice;
+use super::{
+    termios::Termios,
+    tty_core::{TtyCore, TtyCoreData},
+    tty_ldisc::TtyLdiscManager,
+    tty_port::TTY_PORTS,
+    virtual_terminal::virtual_console::CURRENT_VCNUM,
+};
 
-/// TTY 驱动
-///
-///
-/// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/tty_driver.h#434
-pub trait TtyDriver: Debug + Send + Sync + Driver {
-    fn driver_name(&self) -> &str;
-    fn dev_name(&self) -> &str;
+lazy_static! {
+    static ref TTY_DRIVERS: SpinLock<Vec<Arc<TtyDriver>>> = SpinLock::new(Vec::new());
+}
 
-    fn metadata(&self) -> &TtyDriverMetadata;
+pub struct TtyDriverManager;
+impl TtyDriverManager {
+    pub fn lookup_tty_driver(dev_num: DeviceNumber) -> Option<(usize, Arc<TtyDriver>)> {
+        let drivers_guard = TTY_DRIVERS.lock();
+        for (index, driver) in drivers_guard.iter().enumerate() {
+            let base = DeviceNumber::new(driver.major, driver.minor_start);
+            if dev_num < base || dev_num.data() > base.data() + driver.device_count {
+                continue;
+            }
+            return Some((index, driver.clone()));
+        }
 
-    fn other(&self) -> Option<&Arc<dyn TtyDriver>>;
+        None
+    }
 
-    fn ttys(&self) -> &[Arc<TtyDevice>];
+    /// ## 注册驱动
+    pub fn tty_register_driver(mut driver: TtyDriver) -> Result<(), SystemError> {
+        // 查看是否注册设备号
+        if driver.major == Major::UNNAMED_MAJOR {
+            let dev_num = CharDevOps::alloc_chardev_region(
+                driver.minor_start,
+                driver.device_count,
+                driver.name,
+            )?;
+            driver.major = dev_num.major();
+            driver.minor_start = dev_num.minor();
+        } else {
+            let dev_num = DeviceNumber::new(driver.major, driver.minor_start);
+            CharDevOps::register_chardev_region(dev_num, driver.device_count, driver.name)?;
+        }
 
-    fn tty_ops(&self) -> Option<&'static dyn TtyDriverOperations> {
-        None
+        driver.flags |= TtyDriverFlag::TTY_DRIVER_INSTALLED;
+
+        // 加入全局TtyDriver表
+        TTY_DRIVERS.lock().push(Arc::new(driver));
+
+        // TODO: 加入procfs?
+
+        Ok(())
     }
 }
 
-#[derive(Debug, Clone, Copy)]
 #[allow(dead_code)]
-pub struct TtyDriverMetadata {
-    ///  name of the driver used in /proc/tty
-    driver_name: &'static str,
-    /// used for constructing /dev node name
-    dev_name: &'static str,
-    /// used as a number base for constructing /dev node name
-    name_base: i32,
-    /// major /dev device number (zero for autoassignment)
-    major: i32,
-    /// the first minor /dev device number
-    minor_start: i32,
-    drv_type: TtyDriverType,
-    subtype: TtyDriverSubtype,
-}
-
-/// https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/tty_driver.h#411
-#[derive(Debug, Clone, Copy)]
-pub enum TtyDriverType {}
-
-/// https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/tty_driver.h#412
-#[derive(Debug, Clone, Copy)]
-pub enum TtyDriverSubtype {}
+#[derive(Debug)]
+#[cast_to([sync] Driver)]
+pub struct TtyDriver {
+    /// /proc/tty中使用的驱动程序名称
+    driver_name: String,
+    /// 用于构造/dev节点名称,例如name设置为tty,则按照name_base分配节点tty0,tty1等
+    name: &'static str,
+    /// 命名基数
+    name_base: usize,
+    /// 主设备号
+    major: Major,
+    /// 起始次设备号
+    minor_start: u32,
+    /// 最多支持的tty数量
+    device_count: u32,
+    /// tty驱动程序类型
+    tty_driver_type: TtyDriverType,
+    /// 驱动程序子类型
+    tty_driver_sub_type: TtyDriverSubType,
+    /// 每个tty的默认termios
+    init_termios: Termios,
+    /// 懒加载termios,在tty设备关闭时,会将termios按照设备的index保存进这个集合,以便下次打开使用
+    saved_termios: Vec<Termios>,
+    /// 驱动程序标志
+    flags: TtyDriverFlag,
+    /// pty链接此driver的入口
+    pty: Option<Arc<TtyDriver>>,
+    /// 具体类型的tty驱动方法
+    driver_funcs: Arc<dyn TtyOperation>,
+    /// 管理的tty设备列表
+    ttys: SpinLock<HashMap<usize, Arc<TtyCore>>>,
+    // procfs入口?
+}
 
-bitflags! {
-    /// https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/tty_driver.h?fi=SERIAL_TYPE_NORMAL#492
-    pub struct TtyDriverFlags: u64 {
+impl TtyDriver {
+    pub fn new(
+        count: u32,
+        node_name: &'static str,
+        node_name_base: usize,
+        major: Major,
+        minor_start: u32,
+        tty_driver_type: TtyDriverType,
+        default_termios: Termios,
+        driver_funcs: Arc<dyn TtyOperation>,
+    ) -> Self {
+        TtyDriver {
+            driver_name: Default::default(),
+            name: node_name,
+            name_base: node_name_base,
+            major,
+            minor_start,
+            device_count: count,
+            tty_driver_type,
+            tty_driver_sub_type: Default::default(),
+            init_termios: default_termios,
+            flags: TtyDriverFlag::empty(),
+            pty: Default::default(),
+            driver_funcs,
+            ttys: SpinLock::new(HashMap::new()),
+            saved_termios: Vec::with_capacity(count as usize),
+        }
+    }
+
+    pub fn tty_line_name(&self, index: usize) -> String {
+        if self
+            .flags
+            .contains(TtyDriverFlag::TTY_DRIVER_UNNUMBERED_NODE)
+        {
+            return format!("{}", self.name);
+        } else {
+            return format!("{}{}", self.name, index + self.name_base);
+        }
+    }
+
+    pub fn add_tty(&self, tty_core: Arc<TtyCore>) {
+        self.ttys.lock().insert(tty_core.core().index(), tty_core);
+    }
+
+    #[inline]
+    pub fn driver_funcs(&self) -> Arc<dyn TtyOperation> {
+        self.driver_funcs.clone()
+    }
 
+    #[inline]
+    pub fn flags(&self) -> TtyDriverFlag {
+        self.flags
+    }
+
+    #[inline]
+    fn lockup_tty(&self, index: usize) -> Option<Arc<TtyCore>> {
+        let device_guard = self.ttys.lock();
+        return match device_guard.get(&index) {
+            Some(tty) => Some(tty.clone()),
+            None => None,
+        };
+    }
+
+    fn standard_install(&self, tty_core: Arc<TtyCore>) -> Result<(), SystemError> {
+        let tty = tty_core.core();
+        let tty_index = tty.index();
+        // 初始化termios
+        if !self.flags.contains(TtyDriverFlag::TTY_DRIVER_RESET_TERMIOS) {
+            // 先查看是否有已经保存的termios
+            if let Some(t) = self.saved_termios.get(tty_index) {
+                let mut termios = t.clone();
+                termios.line = self.init_termios.line;
+                tty.set_termios(termios);
+            }
+        }
+        // TODO:设置termios波特率?
+
+        tty.add_count();
+
+        self.ttys.lock().insert(tty_index, tty_core);
+
+        Ok(())
+    }
+
+    fn driver_install_tty(driver: Arc<TtyDriver>, tty: Arc<TtyCore>) -> Result<(), SystemError> {
+        let res = tty.install(driver.clone(), tty.clone());
+
+        if res.is_err() {
+            let err = res.unwrap_err();
+            if err == SystemError::ENOSYS {
+                return driver.standard_install(tty);
+            } else {
+                return Err(err);
+            }
+        }
+
+        driver.add_tty(tty);
+
+        Ok(())
+    }
+
+    fn init_tty_device(driver: Arc<TtyDriver>, index: usize) -> Result<Arc<TtyCore>, SystemError> {
+        let tty = TtyCore::new(driver.clone(), index);
+
+        Self::driver_install_tty(driver.clone(), tty.clone())?;
+
+        let core = tty.core();
+
+        if core.port().is_none() {
+            TTY_PORTS[core.index()].setup_tty(Arc::downgrade(&tty));
+            tty.set_port(TTY_PORTS[core.index()].clone());
+        }
+
+        TtyLdiscManager::ldisc_setup(tty.clone(), None)?;
+
+        Ok(tty)
+    }
+
+    /// ## 通过设备号找到对应驱动并且初始化Tty
+    pub fn open_tty(dev_num: DeviceNumber) -> Result<Arc<TtyCore>, SystemError> {
+        let (index, driver) =
+            TtyDriverManager::lookup_tty_driver(dev_num).ok_or(SystemError::ENODEV)?;
+
+        let tty = match driver.lockup_tty(index) {
+            Some(tty) => {
+                // TODO: 暂时这么写,因为还没写TtyPort
+                if tty.core().port().is_none() {
+                    kwarn!("{} port is None", tty.core().name());
+                } else {
+                    if tty.core().port().unwrap().state() == TtyPortState::KOPENED {
+                        return Err(SystemError::EBUSY);
+                    }
+                }
+
+                tty.reopen()?;
+                tty
+            }
+            None => Self::init_tty_device(driver, index)?,
+        };
+
+        CURRENT_VCNUM.store(index as isize, Ordering::SeqCst);
+
+        return Ok(tty);
+    }
+
+    pub fn tty_driver_type(&self) -> TtyDriverType {
+        self.tty_driver_type
+    }
+
+    pub fn tty_driver_sub_type(&self) -> TtyDriverSubType {
+        self.tty_driver_sub_type
+    }
+
+    pub fn init_termios(&self) -> Termios {
+        self.init_termios
     }
 }
 
-/// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/tty_driver.h#350
-pub trait TtyDriverOperations {}
+impl KObject for TtyDriver {
+    fn as_any_ref(&self) -> &dyn core::any::Any {
+        todo!()
+    }
+
+    fn set_inode(&self, _inode: Option<alloc::sync::Arc<crate::filesystem::kernfs::KernFSInode>>) {
+        todo!()
+    }
+
+    fn inode(&self) -> Option<alloc::sync::Arc<crate::filesystem::kernfs::KernFSInode>> {
+        todo!()
+    }
+
+    fn parent(&self) -> Option<alloc::sync::Weak<dyn KObject>> {
+        todo!()
+    }
+
+    fn set_parent(&self, _parent: Option<alloc::sync::Weak<dyn KObject>>) {
+        todo!()
+    }
+
+    fn kset(&self) -> Option<alloc::sync::Arc<crate::driver::base::kset::KSet>> {
+        todo!()
+    }
+
+    fn set_kset(&self, _kset: Option<alloc::sync::Arc<crate::driver::base::kset::KSet>>) {
+        todo!()
+    }
+
+    fn kobj_type(&self) -> Option<&'static dyn crate::driver::base::kobject::KObjType> {
+        todo!()
+    }
+
+    fn set_kobj_type(&self, _ktype: Option<&'static dyn crate::driver::base::kobject::KObjType>) {
+        todo!()
+    }
+
+    fn name(&self) -> alloc::string::String {
+        todo!()
+    }
+
+    fn set_name(&self, _name: alloc::string::String) {
+        todo!()
+    }
+
+    fn kobj_state(
+        &self,
+    ) -> crate::libs::rwlock::RwLockReadGuard<crate::driver::base::kobject::KObjectState> {
+        todo!()
+    }
+
+    fn kobj_state_mut(
+        &self,
+    ) -> crate::libs::rwlock::RwLockWriteGuard<crate::driver::base::kobject::KObjectState> {
+        todo!()
+    }
+
+    fn set_kobj_state(&self, _state: crate::driver::base::kobject::KObjectState) {
+        todo!()
+    }
+}
+
+impl Driver for TtyDriver {
+    fn id_table(&self) -> Option<crate::driver::base::device::IdTable> {
+        todo!()
+    }
+
+    fn devices(
+        &self,
+    ) -> alloc::vec::Vec<alloc::sync::Arc<dyn crate::driver::base::device::Device>> {
+        todo!()
+    }
+
+    fn add_device(&self, _device: alloc::sync::Arc<dyn crate::driver::base::device::Device>) {
+        todo!()
+    }
+
+    fn delete_device(&self, _device: &alloc::sync::Arc<dyn crate::driver::base::device::Device>) {
+        todo!()
+    }
+
+    fn set_bus(&self, _bus: Option<alloc::sync::Weak<dyn crate::driver::base::device::bus::Bus>>) {
+        todo!()
+    }
+}
+
+pub trait TtyOperation: Sync + Send + Debug {
+    fn install(&self, _driver: Arc<TtyDriver>, _tty: Arc<TtyCore>) -> Result<(), SystemError> {
+        return Err(SystemError::ENOSYS);
+    }
+
+    fn open(&self, tty: &TtyCoreData) -> Result<(), SystemError>;
+
+    /// ## 获取可写字符数
+    fn write_room(&self, _tty: &TtyCoreData) -> usize {
+        // 默认
+        2048
+    }
+
+    fn write(&self, tty: &TtyCoreData, buf: &[u8], nr: usize) -> Result<usize, SystemError>;
+
+    fn flush_chars(&self, tty: &TtyCoreData);
+
+    fn put_char(&self, tty: &TtyCoreData, ch: u8) -> Result<(), SystemError>;
+
+    fn start(&self, _tty: &TtyCoreData) -> Result<(), SystemError> {
+        Err(SystemError::ENOSYS)
+    }
+
+    fn stop(&self, _tty: &TtyCoreData) -> Result<(), SystemError> {
+        Err(SystemError::ENOSYS)
+    }
+
+    fn flush_buffer(&self, _tty: &TtyCoreData) -> Result<(), SystemError> {
+        Err(SystemError::ENOSYS)
+    }
+
+    fn ioctl(&self, tty: Arc<TtyCore>, cmd: u32, arg: usize) -> Result<(), SystemError>;
+
+    fn chars_in_buffer(&self) -> usize {
+        0
+    }
+
+    fn set_termios(&self, _tty: Arc<TtyCore>, _old_termios: Termios) -> Result<(), SystemError> {
+        Err(SystemError::ENOSYS)
+    }
+}
+
+#[allow(dead_code)]
+#[derive(Debug, PartialEq, Copy, Clone)]
+pub enum TtyDriverType {
+    System,
+    Console,
+    Serial,
+    Pty,
+    Scc,
+    Syscons,
+}
+
+#[allow(dead_code)]
+#[derive(Debug, PartialEq, Copy, Clone)]
+pub enum TtyDriverSubType {
+    Undefined,
+    Tty,
+    Console,
+    Syscons,
+    Sysptmx,
+    PtyMaster,
+    PtySlave,
+    SerialNormal,
+}
+
+impl Default for TtyDriverSubType {
+    fn default() -> Self {
+        Self::Undefined
+    }
+}
+
+bitflags! {
+    pub struct TtyDriverFlag: u32 {
+        /// 表示 tty 驱动程序已安装
+        const TTY_DRIVER_INSTALLED		= 0x0001;
+        /// 请求 tty 层在最后一个进程关闭设备时重置 termios 设置
+        const TTY_DRIVER_RESET_TERMIOS	= 0x0002;
+        /// 表示驱动程序将保证在设置了该标志的 tty 上不设置任何特殊字符处理标志(原模式)
+        const TTY_DRIVER_REAL_RAW		    = 0x0004;
+
+        /// 以下四个标志位为内存分配相关,目前设计无需使用
+        const TTY_DRIVER_DYNAMIC_DEV		= 0x0008;
+        const TTY_DRIVER_DEVPTS_MEM		= 0x0010;
+        const TTY_DRIVER_HARDWARE_BREAK	= 0x0020;
+        const TTY_DRIVER_DYNAMIC_ALLOC	= 0x0040;
+
+        /// 表示不创建带有编号的 /dev 节点。
+        /// 例如,创建 /dev/ttyprintk 而不是 /dev/ttyprintk0。仅在为单个 tty 设备分配驱动程序时适用。
+        const TTY_DRIVER_UNNUMBERED_NODE	= 0x0080;
+    }
+}

+ 139 - 0
kernel/src/driver/tty/tty_job_control.rs

@@ -0,0 +1,139 @@
+use alloc::sync::Arc;
+use system_error::SystemError;
+
+use crate::{
+    arch::ipc::signal::{SigSet, Signal},
+    mm::VirtAddr,
+    process::{Pid, ProcessManager},
+    syscall::{user_access::UserBufferWriter, Syscall},
+};
+
+use super::tty_core::{TtyCore, TtyIoctlCmd};
+
+pub struct TtyJobCtrlManager;
+
+impl TtyJobCtrlManager {
+    /// ### 设置当前进程的tty
+    pub fn proc_set_tty(tty: Arc<TtyCore>) {
+        let core = tty.core();
+        let mut ctrl = core.contorl_info_irqsave();
+        let pcb = ProcessManager::current_pcb();
+
+        // todo 目前将pgid设置为pid
+        ctrl.pgid = Some(pcb.pid());
+        ctrl.session = Some(pcb.pid());
+
+        assert!(pcb.sig_info_irqsave().tty().is_none());
+
+        let mut singal = pcb.sig_info_mut();
+        drop(ctrl);
+        singal.set_tty(tty);
+    }
+
+    /// ### 检查tty
+    pub fn tty_check_change(tty: Arc<TtyCore>, sig: Signal) -> Result<(), SystemError> {
+        let pcb = ProcessManager::current_pcb();
+
+        if pcb.sig_info().tty().is_none() || !Arc::ptr_eq(&pcb.sig_info().tty().unwrap(), &tty) {
+            return Ok(());
+        }
+
+        let core = tty.core();
+        let ctrl = core.contorl_info_irqsave();
+
+        // todo pgid
+        let pgid = pcb.pid();
+        let tty_pgid = ctrl.pgid;
+
+        if tty_pgid.is_some() && tty_pgid.unwrap() != pgid {
+            if pcb
+                .sig_info_irqsave()
+                .sig_block()
+                .contains(SigSet::from_bits_truncate(1 << sig as u64))
+                || pcb.sig_struct_irqsave().handlers[sig as usize].is_ignore()
+            {
+                // 忽略该信号
+                if sig == Signal::SIGTTIN {
+                    return Err(SystemError::EIO);
+                }
+            } else {
+                // 暂时使用kill而不是killpg
+                Syscall::kill(pgid, sig as i32)?;
+                return Err(SystemError::ERESTART);
+            }
+        }
+
+        Ok(())
+    }
+
+    pub fn job_ctrl_ioctl(tty: Arc<TtyCore>, cmd: u32, arg: usize) -> Result<usize, SystemError> {
+        match cmd {
+            TtyIoctlCmd::TIOCSPGRP => {
+                match Self::tty_check_change(tty.clone(), Signal::SIGTTOU) {
+                    Ok(_) => {}
+                    Err(e) => {
+                        if e == SystemError::EIO {
+                            return Err(SystemError::ENOTTY);
+                        }
+                        return Err(e);
+                    }
+                };
+
+                // let user_reader = UserBufferReader::new(
+                //     VirtAddr::new(arg).as_ptr::<usize>(),
+                //     core::mem::size_of::<usize>(),
+                //     true,
+                // )?;
+
+                // let pgrp = user_reader.read_one_from_user::<usize>(0)?;
+
+                let current = ProcessManager::current_pcb();
+
+                let mut ctrl = tty.core().contorl_info_irqsave();
+
+                if current.sig_info().tty().is_none()
+                    || !Arc::ptr_eq(&current.sig_info().tty().clone().unwrap(), &tty)
+                    || ctrl.session.is_none()
+                    || ctrl.session.unwrap() != current.pid()
+                {
+                    return Err(SystemError::ENOTTY);
+                }
+
+                ctrl.pgid = Some(Pid::new(arg));
+
+                return Ok(0);
+            }
+
+            TtyIoctlCmd::TIOCGPGRP => {
+                let current = ProcessManager::current_pcb();
+                if current.sig_info().tty().is_some()
+                    && !Arc::ptr_eq(&current.sig_info().tty().unwrap(), &tty)
+                {
+                    return Err(SystemError::ENOTTY);
+                }
+
+                let mut user_writer = UserBufferWriter::new(
+                    VirtAddr::new(arg).as_ptr::<i32>(),
+                    core::mem::size_of::<i32>(),
+                    true,
+                )?;
+
+                user_writer.copy_one_to_user(
+                    &(tty
+                        .core()
+                        .contorl_info_irqsave()
+                        .pgid
+                        .unwrap_or(Pid::new(0))
+                        .data() as i32),
+                    0,
+                )?;
+
+                return Ok(0);
+            }
+
+            _ => {
+                return Err(SystemError::ENOIOCTLCMD);
+            }
+        }
+    }
+}

+ 117 - 0
kernel/src/driver/tty/tty_ldisc/mod.rs

@@ -0,0 +1,117 @@
+use core::fmt::Debug;
+
+use alloc::sync::Arc;
+use system_error::SystemError;
+
+use crate::filesystem::vfs::file::FileMode;
+
+use super::{
+    termios::Termios,
+    tty_core::{TtyCore, TtyCoreData},
+};
+
+pub mod ntty;
+
+pub trait TtyLineDiscipline: Sync + Send + Debug {
+    fn open(&self, tty: Arc<TtyCore>) -> Result<(), SystemError>;
+    fn close(&self, tty: Arc<TtyCore>) -> Result<(), SystemError>;
+    fn flush_buffer(&self, tty: Arc<TtyCore>) -> Result<(), SystemError>;
+
+    /// ## tty行规程循环读取函数
+    ///
+    /// ### 参数
+    /// - tty: 操作的tty
+    /// - buf: 数据将被读取到buf
+    /// - len: 读取的字节长度
+    /// - cookie: 表示是否是继续上次的读,第一次读取应该传入false
+    /// - offset: 读取的偏移量
+    fn read(
+        &self,
+        tty: Arc<TtyCore>,
+        buf: &mut [u8],
+        len: usize,
+        cookie: &mut bool,
+        offset: usize,
+        mode: FileMode,
+    ) -> Result<usize, SystemError>;
+    fn write(
+        &self,
+        tty: Arc<TtyCore>,
+        buf: &[u8],
+        len: usize,
+        mode: FileMode,
+    ) -> Result<usize, SystemError>;
+    fn ioctl(&self, tty: Arc<TtyCore>, cmd: u32, arg: usize) -> Result<usize, SystemError>;
+
+    /// ### 设置termios后更新行规程状态
+    ///
+    /// - old: 之前的termios,如果为None则表示第一次设置
+    fn set_termios(&self, tty: Arc<TtyCore>, old: Option<Termios>) -> Result<(), SystemError>;
+
+    fn poll(&self, tty: Arc<TtyCore>) -> Result<(), SystemError>;
+    fn hangup(&self, tty: Arc<TtyCore>) -> Result<(), SystemError>;
+
+    /// ## 接收数据
+    fn receive_buf(
+        &self,
+        tty: Arc<TtyCore>,
+        buf: &[u8],
+        flags: Option<&[u8]>,
+        count: usize,
+    ) -> Result<usize, SystemError>;
+
+    /// ## 接收数据
+    fn receive_buf2(
+        &self,
+        tty: Arc<TtyCore>,
+        buf: &[u8],
+        flags: Option<&[u8]>,
+        count: usize,
+    ) -> Result<usize, SystemError>;
+
+    /// ## 唤醒线路写者
+    fn write_wakeup(&self, _tty: &TtyCoreData) -> Result<(), SystemError> {
+        Err(SystemError::ENOSYS)
+    }
+}
+
+#[derive(Debug, Clone, Copy)]
+pub enum LineDisciplineType {
+    NTty = 0,
+}
+
+impl LineDisciplineType {
+    pub fn from_line(line: u8) -> Self {
+        match line {
+            0 => Self::NTty,
+            _ => {
+                todo!()
+            }
+        }
+    }
+}
+
+pub struct TtyLdiscManager;
+
+impl TtyLdiscManager {
+    /// ## 为tty初始化ldisc
+    ///
+    /// ### 参数
+    /// - tty:需要设置的tty
+    /// - o_tty: other tty 用于pty pair
+    pub fn ldisc_setup(tty: Arc<TtyCore>, _o_tty: Option<Arc<TtyCore>>) -> Result<(), SystemError> {
+        let ld = tty.ldisc();
+
+        let ret = ld.open(tty);
+        if ret.is_err() {
+            let err = ret.unwrap_err();
+            if err == SystemError::ENOSYS {
+                return Err(err);
+            }
+        }
+
+        // TODO: 处理PTY
+
+        Ok(())
+    }
+}

+ 2016 - 0
kernel/src/driver/tty/tty_ldisc/ntty.rs

@@ -0,0 +1,2016 @@
+use core::ops::BitXor;
+
+use bitmap::{traits::BitMapOps, StaticBitmap};
+
+use alloc::sync::{Arc, Weak};
+use system_error::SystemError;
+
+use crate::{
+    arch::ipc::signal::Signal,
+    driver::tty::{
+        termios::{ControlCharIndex, InputMode, LocalMode, OutputMode, Termios},
+        tty_core::{EchoOperation, TtyCore, TtyCoreData, TtyFlag, TtyIoctlCmd},
+        tty_driver::{TtyDriverFlag, TtyOperation},
+        tty_job_control::TtyJobCtrlManager,
+    },
+    filesystem::vfs::file::FileMode,
+    libs::{
+        rwlock::RwLockReadGuard,
+        spinlock::{SpinLock, SpinLockGuard},
+    },
+    mm::VirtAddr,
+    net::event_poll::EPollEventType,
+    process::ProcessManager,
+    syscall::{user_access::UserBufferWriter, Syscall},
+};
+
+use super::TtyLineDiscipline;
+pub const NTTY_BUFSIZE: usize = 4096;
+pub const ECHO_COMMIT_WATERMARK: usize = 256;
+pub const ECHO_BLOCK: usize = 256;
+pub const ECHO_DISCARD_WATERMARK: usize = NTTY_BUFSIZE - (ECHO_BLOCK + 32);
+
+fn ntty_buf_mask(idx: usize) -> usize {
+    return idx & (NTTY_BUFSIZE - 1);
+}
+
+#[derive(Debug)]
+pub struct NTtyLinediscipline {
+    pub data: SpinLock<NTtyData>,
+}
+
+impl NTtyLinediscipline {
+    #[inline]
+    pub fn disc_data(&self) -> SpinLockGuard<NTtyData> {
+        self.data.lock_irqsave()
+    }
+
+    #[inline]
+    pub fn disc_data_try_lock(&self) -> Result<SpinLockGuard<NTtyData>, SystemError> {
+        self.data.try_lock_irqsave()
+    }
+
+    fn ioctl_helper(&self, tty: Arc<TtyCore>, cmd: u32, arg: usize) -> Result<usize, SystemError> {
+        match cmd {
+            TtyIoctlCmd::TCXONC => {
+                todo!()
+            }
+            TtyIoctlCmd::TCFLSH => {
+                todo!()
+            }
+            _ => {
+                return tty.tty_mode_ioctl(tty.clone(), cmd, arg);
+            }
+        }
+    }
+}
+
+#[derive(Debug)]
+pub struct NTtyData {
+    /// 写者管理,tty只有一个写者,即ttydevice,所以不需要加锁
+    /// 读取缓冲区的头指针,表示下一个将要接受进buf的字符的位置
+    read_head: usize,
+    ///  提交缓冲区的头指针,用于行规程处理
+    commit_head: usize,
+    /// 规范缓冲区的头指针,用于规范模式的处理
+    canon_head: usize,
+    /// 回显缓冲区的头指针,用于存储需要回显的字符
+    echo_head: usize,
+    /// 回显过程中用于提交的头指针
+    echo_commit: usize,
+    /// 标记回显字符的起始位置
+    echo_mark: usize,
+
+    /// 读者管理
+    /// 读取字符的尾指针,即当前读取位置
+    read_tail: usize,
+    /// 行的起始位置
+    line_start: usize,
+    /// 预读字符数,用于处理控制字符
+    lookahead_count: usize,
+
+    // 更改以下六个标记时必须持有termios的锁
+    /// Line-next 标志,表示下一个输入字符应当按字面处理
+    lnext: bool,
+    /// 擦除状态的标志
+    erasing: bool,
+    /// Raw 模式的标志
+    raw: bool,
+    /// Real raw 模式的标志
+    real_raw: bool,
+    /// 规范模式的标志
+    icanon: bool,
+    /// 是否开启echo
+    echo: bool,
+    ///  标志是否正在进行推送
+    pushing: bool,
+    /// 是否没有空间可写
+    no_room: bool,
+
+    /// 光标所在列
+    cursor_column: u32,
+    /// 规范模式下光标所在列
+    canon_cursor_column: u32,
+    /// 回显缓冲区的尾指针
+    echo_tail: usize,
+
+    /// 写者与读者共享
+    read_buf: [u8; NTTY_BUFSIZE],
+    echo_buf: [u8; NTTY_BUFSIZE],
+
+    read_flags: StaticBitmap<NTTY_BUFSIZE>,
+    char_map: StaticBitmap<256>,
+
+    tty: Option<Weak<TtyCore>>,
+}
+
+impl NTtyData {
+    pub fn new() -> Self {
+        Self {
+            read_head: 0,
+            commit_head: 0,
+            canon_head: 0,
+            echo_head: 0,
+            echo_commit: 0,
+            echo_mark: 0,
+            read_tail: 0,
+            line_start: 0,
+            lookahead_count: 0,
+            lnext: false,
+            erasing: false,
+            raw: false,
+            real_raw: false,
+            icanon: false,
+            pushing: false,
+            echo: false,
+            cursor_column: 0,
+            canon_cursor_column: 0,
+            echo_tail: 0,
+            read_buf: [0; NTTY_BUFSIZE],
+            echo_buf: [0; NTTY_BUFSIZE],
+            read_flags: StaticBitmap::new(),
+            char_map: StaticBitmap::new(),
+            tty: None,
+            no_room: false,
+        }
+    }
+
+    #[inline]
+    pub fn read_cnt(&self) -> usize {
+        self.read_head - self.read_tail
+    }
+
+    #[inline]
+    pub fn read_at(&self, i: usize) -> u8 {
+        let i = i & (NTTY_BUFSIZE - 1);
+        self.read_buf[i]
+    }
+
+    /// ### 接收数据到NTTY
+    pub fn receive_buf_common(
+        &mut self,
+        tty: Arc<TtyCore>,
+        buf: &[u8],
+        flags: Option<&[u8]>,
+        mut count: usize,
+        flow: bool,
+    ) -> Result<usize, SystemError> {
+        // 获取termios读锁
+        let termios = tty.core().termios();
+        let mut overflow;
+        let mut n;
+        let mut offset = 0;
+        let mut recved = 0;
+        loop {
+            let tail = self.read_tail;
+
+            let mut room = NTTY_BUFSIZE - (self.read_head - tail);
+            if termios.input_mode.contains(InputMode::PARMRK) {
+                room = (room + 2) / 3;
+            }
+
+            room -= 1;
+            if room == 0 || room > NTTY_BUFSIZE {
+                // 可能溢出
+                overflow = self.icanon && self.canon_head == tail;
+                if room > NTTY_BUFSIZE && overflow {
+                    self.read_head -= 1;
+                }
+                self.no_room = flow && !overflow;
+                room = if overflow { !0 } else { 0 }
+            } else {
+                overflow = false;
+            }
+
+            n = count.min(room);
+            if n == 0 {
+                break;
+            }
+
+            if !overflow {
+                if flags.is_none() {
+                    self.receive_buf(tty.clone(), &buf[offset..], flags, n);
+                } else {
+                    self.receive_buf(
+                        tty.clone(),
+                        &buf[offset..],
+                        Some(&flags.unwrap()[offset..]),
+                        n,
+                    );
+                }
+            }
+
+            offset += n;
+
+            count -= n;
+
+            recved += n;
+
+            if tty.core().flags().contains(TtyFlag::LDISC_CHANGING) {
+                break;
+            }
+        }
+
+        // TODO: throttle
+
+        Ok(recved)
+    }
+
+    pub fn receive_buf(
+        &mut self,
+        tty: Arc<TtyCore>,
+        buf: &[u8],
+        flags: Option<&[u8]>,
+        count: usize,
+    ) {
+        let termios = tty.core().termios();
+        let preops = termios.input_mode.contains(InputMode::ISTRIP)
+            || termios.input_mode.contains(InputMode::IUCLC)
+            || termios.local_mode.contains(LocalMode::IEXTEN);
+
+        let look_ahead = self.lookahead_count.min(count);
+
+        if self.real_raw {
+            todo!("tty real raw mode todo");
+        } else if self.raw || (termios.local_mode.contains(LocalMode::EXTPROC) && !preops) {
+            todo!("tty raw mode todo");
+        } else if tty.core().is_closing() && !termios.local_mode.contains(LocalMode::EXTPROC) {
+            todo!()
+        } else {
+            if look_ahead > 0 {
+                self.receive_buf_standard(tty.clone(), buf, flags, look_ahead, true);
+            }
+
+            if count > look_ahead {
+                self.receive_buf_standard(tty.clone(), buf, flags, count - look_ahead, false);
+            }
+
+            // 刷新echo
+            self.flush_echoes(tty.clone());
+
+            tty.flush_chars(tty.core());
+        }
+
+        self.lookahead_count -= look_ahead;
+
+        if self.icanon && !termios.local_mode.contains(LocalMode::EXTPROC) {
+            return;
+        }
+
+        self.commit_head = self.read_head;
+
+        if self.read_cnt() > 0 {
+            tty.core()
+                .read_wq()
+                .wakeup((EPollEventType::EPOLLIN | EPollEventType::EPOLLRDBAND).bits() as u64);
+        }
+    }
+
+    pub fn flush_echoes(&mut self, tty: Arc<TtyCore>) {
+        let termios = tty.core().termios();
+        if !termios.local_mode.contains(LocalMode::ECHO)
+            && !termios.local_mode.contains(LocalMode::ECHONL)
+            || self.echo_commit == self.echo_head
+        {
+            return;
+        }
+
+        self.echo_commit = self.echo_head;
+        drop(termios);
+        let _ = self.echoes(tty);
+    }
+
+    pub fn receive_buf_standard(
+        &mut self,
+        tty: Arc<TtyCore>,
+        buf: &[u8],
+        flags: Option<&[u8]>,
+        mut count: usize,
+        lookahead_done: bool,
+    ) {
+        let termios = tty.core().termios();
+        if flags.is_some() {
+            todo!("ntty recv buf flags todo");
+        }
+
+        let mut offset = 0;
+        while count > 0 {
+            if offset >= buf.len() {
+                break;
+            }
+            let mut c = buf[offset];
+            offset += 1;
+
+            if self.lnext {
+                // 将下一个字符当做字面值处理
+                self.lnext = false;
+                if termios.input_mode.contains(InputMode::ISTRIP) {
+                    c &= 0x7f;
+                }
+
+                if termios.input_mode.contains(InputMode::IUCLC)
+                    && termios.local_mode.contains(LocalMode::IEXTEN)
+                {
+                    c = (c as char).to_ascii_lowercase() as u8;
+                    self.receive_char(c, tty.clone())
+                }
+
+                continue;
+            }
+
+            if termios.input_mode.contains(InputMode::ISTRIP) {
+                c &= 0x7f;
+            }
+
+            if termios.input_mode.contains(InputMode::IUCLC)
+                && termios.local_mode.contains(LocalMode::IEXTEN)
+            {
+                c = (c as char).to_ascii_lowercase() as u8;
+            }
+
+            if termios.local_mode.contains(LocalMode::EXTPROC) {
+                self.add_read_byte(c);
+                continue;
+            }
+
+            if self.char_map.get(c as usize).unwrap() {
+                // 特殊字符
+                self.receive_special_char(c, tty.clone(), lookahead_done)
+            } else {
+                self.receive_char(c, tty.clone());
+            }
+
+            count -= 1;
+        }
+    }
+
+    pub fn receive_special_char(&mut self, mut c: u8, tty: Arc<TtyCore>, lookahead_done: bool) {
+        let is_flow_ctrl = self.is_flow_ctrl_char(tty.clone(), c, lookahead_done);
+        let termios = tty.core().termios();
+
+        // 启用软件流控,并且该字符已经当做软件流控字符处理
+        if termios.input_mode.contains(InputMode::IXON) && is_flow_ctrl {
+            return;
+        }
+
+        if termios.local_mode.contains(LocalMode::ISIG) {
+            if c == termios.control_characters[ControlCharIndex::VINTR] {
+                self.recv_sig_char(tty.clone(), &termios, Signal::SIGINT, c);
+                return;
+            }
+
+            if c == termios.control_characters[ControlCharIndex::VQUIT] {
+                self.recv_sig_char(tty.clone(), &termios, Signal::SIGQUIT, c);
+                return;
+            }
+
+            if c == termios.control_characters[ControlCharIndex::VSUSP] {
+                self.recv_sig_char(tty.clone(), &termios, Signal::SIGTSTP, c);
+                return;
+            }
+        }
+
+        let flow = tty.core().flow_irqsave();
+        if flow.stopped
+            && !flow.tco_stopped
+            && termios.input_mode.contains(InputMode::IXON)
+            && termios.input_mode.contains(InputMode::IXANY)
+        {
+            tty.tty_start();
+            self.process_echoes(tty.clone());
+        }
+        drop(flow);
+
+        if c == b'\r' {
+            if termios.input_mode.contains(InputMode::IGNCR) {
+                // 忽略
+                return;
+            }
+            if termios.input_mode.contains(InputMode::ICRNL) {
+                // 映射为换行
+                c = b'\n';
+            }
+        } else if c == b'\n' && termios.input_mode.contains(InputMode::INLCR) {
+            // 映射为回车
+            c = b'\r';
+        }
+
+        if self.icanon {
+            if c == termios.control_characters[ControlCharIndex::VERASE]
+                || c == termios.control_characters[ControlCharIndex::VKILL]
+                || (c == termios.control_characters[ControlCharIndex::VWERASE]
+                    && termios.local_mode.contains(LocalMode::IEXTEN))
+            {
+                self.eraser(c, &termios);
+                self.commit_echoes(tty.clone());
+                return;
+            }
+            if c == termios.control_characters[ControlCharIndex::VLNEXT]
+                && termios.local_mode.contains(LocalMode::IEXTEN)
+            {
+                self.lnext = true;
+                if termios.local_mode.contains(LocalMode::ECHO) {
+                    self.finish_erasing();
+                    if termios.local_mode.contains(LocalMode::ECHOCTL) {
+                        self.echo_char_raw(b'^');
+                        self.echo_char_raw(8);
+                        self.commit_echoes(tty.clone());
+                    }
+                }
+                return;
+            }
+            if c == termios.control_characters[ControlCharIndex::VREPRINT]
+                && termios.local_mode.contains(LocalMode::ECHO)
+                && termios.local_mode.contains(LocalMode::IEXTEN)
+            {
+                let mut tail = self.canon_head;
+                self.finish_erasing();
+                self.echo_char(c, &termios);
+                self.echo_char_raw(b'\n');
+                while ntty_buf_mask(tail) != ntty_buf_mask(self.read_head) {
+                    self.echo_char(self.read_buf[ntty_buf_mask(tail)], &termios);
+                    tail += 1;
+                }
+                self.commit_echoes(tty.clone());
+                return;
+            }
+
+            if c == b'\n' {
+                if termios.local_mode.contains(LocalMode::ECHO)
+                    || termios.local_mode.contains(LocalMode::ECHONL)
+                {
+                    self.echo_char_raw(b'\n');
+                    self.commit_echoes(tty.clone());
+                }
+
+                self.read_flags.set(ntty_buf_mask(self.read_head), true);
+                self.read_buf[ntty_buf_mask(self.read_head)] = c;
+                self.read_head += 1;
+                self.canon_head = self.read_head;
+                tty.core()
+                    .read_wq()
+                    .wakeup((EPollEventType::EPOLLIN | EPollEventType::EPOLLRDNORM).bits() as u64);
+                return;
+            }
+
+            if c == termios.control_characters[ControlCharIndex::VEOF] {
+                c = ControlCharIndex::DISABLE_CHAR;
+
+                self.read_flags.set(ntty_buf_mask(self.read_head), true);
+                self.read_buf[ntty_buf_mask(self.read_head)] = c;
+                self.read_head += 1;
+                self.canon_head = self.read_head;
+                tty.core()
+                    .read_wq()
+                    .wakeup((EPollEventType::EPOLLIN | EPollEventType::EPOLLRDNORM).bits() as u64);
+                return;
+            }
+
+            if c == termios.control_characters[ControlCharIndex::VEOL]
+                || (c == termios.control_characters[ControlCharIndex::VEOL2]
+                    && termios.local_mode.contains(LocalMode::IEXTEN))
+            {
+                if termios.local_mode.contains(LocalMode::ECHO) {
+                    if self.canon_head == self.read_head {
+                        self.add_echo_byte(EchoOperation::Start.to_u8());
+                        self.add_echo_byte(EchoOperation::SetCanonCol.to_u8());
+                    }
+                    self.echo_char(c, &termios);
+                    self.commit_echoes(tty.clone());
+                }
+
+                if c == 0o377 && termios.input_mode.contains(InputMode::PARMRK) {
+                    self.read_buf[ntty_buf_mask(self.read_head)] = c;
+                    self.read_head += 1;
+                }
+
+                self.read_flags.set(ntty_buf_mask(self.read_head), true);
+                self.read_buf[ntty_buf_mask(self.read_head)] = c;
+                self.read_head += 1;
+                self.canon_head = self.read_head;
+                tty.core()
+                    .read_wq()
+                    .wakeup((EPollEventType::EPOLLIN | EPollEventType::EPOLLRDNORM).bits() as u64);
+                return;
+            }
+        }
+
+        if termios.local_mode.contains(LocalMode::ECHO) {
+            self.finish_erasing();
+            if c == b'\n' {
+                self.echo_char_raw(b'\n');
+            } else {
+                if self.canon_head == self.read_head {
+                    self.add_echo_byte(EchoOperation::Start.to_u8());
+                    self.add_echo_byte(EchoOperation::SetCanonCol.to_u8());
+                }
+                self.echo_char(c, &termios);
+            }
+
+            self.commit_echoes(tty.clone());
+        }
+
+        if c == 0o377 && termios.input_mode.contains(InputMode::PARMRK) {
+            self.read_buf[ntty_buf_mask(self.read_head)] = c;
+            self.read_head += 1;
+        }
+
+        self.read_buf[ntty_buf_mask(self.read_head)] = c;
+        self.read_head += 1;
+    }
+
+    /// ## ntty默认eraser function
+    fn eraser(&mut self, mut c: u8, termios: &RwLockReadGuard<Termios>) {
+        if self.read_head == self.canon_head {
+            return;
+        }
+
+        let erase = c == termios.control_characters[ControlCharIndex::VERASE];
+        let werase = c == termios.control_characters[ControlCharIndex::VWERASE];
+        let kill = !erase && !werase;
+
+        if kill {
+            if !termios.local_mode.contains(LocalMode::ECHO) {
+                self.read_head = self.canon_head;
+                return;
+            }
+            if !termios.local_mode.contains(LocalMode::ECHOK)
+                || !termios.local_mode.contains(LocalMode::ECHOKE)
+                || !termios.local_mode.contains(LocalMode::ECHOE)
+            {
+                self.read_head = self.canon_head;
+                if self.erasing {
+                    self.echo_char_raw(c);
+                    self.erasing = false;
+                }
+                self.echo_char(c, termios);
+
+                if termios.local_mode.contains(LocalMode::ECHOK) {
+                    // 添加新行
+                    self.echo_char_raw(b'\n');
+                }
+                return;
+            }
+        }
+
+        let mut head;
+        let mut cnt;
+        while ntty_buf_mask(self.read_head) != ntty_buf_mask(self.canon_head) {
+            head = self.read_head;
+
+            loop {
+                // 消除多字节字符
+                head -= 1;
+                c = self.read_buf[ntty_buf_mask(head)];
+
+                if !(Self::is_continuation(c, termios)
+                    && ntty_buf_mask(head) != ntty_buf_mask(self.canon_head))
+                {
+                    break;
+                }
+            }
+
+            if Self::is_continuation(c, termios) {
+                break;
+            }
+
+            if werase {
+                todo!()
+            }
+
+            cnt = self.read_head - head;
+            self.read_head = head;
+            if termios.local_mode.contains(LocalMode::ECHO) {
+                if termios.local_mode.contains(LocalMode::ECHOPRT) {
+                    if !self.erasing {
+                        self.echo_char_raw(b'\\');
+                        self.erasing = true;
+                    }
+                    self.echo_char(c, termios);
+                    cnt -= 1;
+                    while cnt > 0 {
+                        cnt -= 1;
+                        head += 1;
+                        self.echo_char_raw(self.read_buf[ntty_buf_mask(head)]);
+                        self.add_echo_byte(EchoOperation::Start.to_u8());
+                        self.add_echo_byte(EchoOperation::MoveBackCol.to_u8());
+                    }
+                } else if erase && !termios.local_mode.contains(LocalMode::ECHOE) {
+                    self.echo_char(
+                        termios.control_characters[ControlCharIndex::VERASE],
+                        termios,
+                    );
+                } else if c == b'\t' {
+                    let mut num_chars = 0;
+                    let mut after_tab = false;
+                    let mut tail = self.read_head;
+
+                    while ntty_buf_mask(tail) != ntty_buf_mask(self.canon_head) {
+                        tail -= 1;
+                        c = self.read_buf[ntty_buf_mask(tail)];
+                        if c == b'\t' {
+                            after_tab = true;
+                            break;
+                        } else if (c as char).is_control() {
+                            if termios.local_mode.contains(LocalMode::ECHOCTL) {
+                                num_chars += 2;
+                            }
+                        } else if !Self::is_continuation(c, termios) {
+                            num_chars += 1;
+                        }
+                    }
+
+                    self.echo_erase_tab(num_chars, after_tab);
+                } else {
+                    if (c as char).is_control() && termios.local_mode.contains(LocalMode::ECHOCTL) {
+                        // 8 => '\b'
+                        self.echo_char_raw(8);
+                        self.echo_char_raw(b' ');
+                        self.echo_char_raw(8);
+                    }
+
+                    if !(c as char).is_control() || termios.local_mode.contains(LocalMode::ECHOCTL)
+                    {
+                        // 8 => '\b'
+                        self.echo_char_raw(8);
+                        self.echo_char_raw(b' ');
+                        self.echo_char_raw(8);
+                    }
+                }
+            }
+
+            if erase {
+                break;
+            }
+        }
+
+        if self.read_head == self.canon_head && termios.local_mode.contains(LocalMode::ECHO) {
+            self.finish_erasing();
+        }
+    }
+
+    fn finish_erasing(&mut self) {
+        if self.erasing {
+            self.echo_char_raw(b'/');
+            self.erasing = false;
+        }
+    }
+
+    fn echo_erase_tab(&mut self, mut num: u8, after_tab: bool) {
+        self.add_echo_byte(EchoOperation::Start.to_u8());
+        self.add_echo_byte(EchoOperation::EraseTab.to_u8());
+
+        num &= 7;
+
+        if after_tab {
+            num |= 0x80;
+        }
+
+        self.add_echo_byte(num);
+    }
+
+    /// ## 多字节字符检测
+    /// 检测是否为多字节字符的后续字节
+    fn is_continuation(c: u8, termios: &RwLockReadGuard<Termios>) -> bool {
+        return termios.input_mode.contains(InputMode::IUTF8) && (c & 0xc0) == 0x80;
+    }
+
+    /// ## 该字符是否已经当做流控字符处理
+    pub fn is_flow_ctrl_char(&mut self, tty: Arc<TtyCore>, c: u8, lookahead_done: bool) -> bool {
+        let termios = tty.core().termios();
+
+        if !(termios.control_characters[ControlCharIndex::VSTART] == c
+            || termios.control_characters[ControlCharIndex::VSTOP] == c)
+        {
+            return false;
+        }
+
+        if lookahead_done {
+            return true;
+        }
+
+        if termios.control_characters[ControlCharIndex::VSTART] == c {
+            tty.tty_start();
+            self.process_echoes(tty.clone());
+            return true;
+        } else {
+            tty.tty_stop();
+            return true;
+        }
+    }
+
+    /// ## 接收到信号字符时的处理
+    fn recv_sig_char(
+        &mut self,
+        tty: Arc<TtyCore>,
+        termios: &RwLockReadGuard<Termios>,
+        signal: Signal,
+        c: u8,
+    ) {
+        self.input_signal(tty.clone(), termios, signal);
+        if termios.input_mode.contains(InputMode::IXON) {
+            tty.tty_start();
+        }
+
+        if termios.local_mode.contains(LocalMode::ECHO) {
+            self.echo_char(c, termios);
+            self.commit_echoes(tty);
+        } else {
+            self.process_echoes(tty);
+        }
+    }
+
+    /// ## 处理输入信号
+    pub fn input_signal(
+        &mut self,
+        tty: Arc<TtyCore>,
+        termios: &RwLockReadGuard<Termios>,
+        signal: Signal,
+    ) {
+        // 先处理信号
+        let mut ctrl_info = tty.core().contorl_info_irqsave();
+        let pg = ctrl_info.pgid;
+        if pg.is_some() {
+            let _ = Syscall::kill(pg.unwrap(), signal as i32);
+        }
+
+        ctrl_info.pgid = None;
+        ctrl_info.session = None;
+
+        if !termios.local_mode.contains(LocalMode::NOFLSH) {
+            // 重置
+            self.echo_head = 0;
+            self.echo_tail = 0;
+            self.echo_mark = 0;
+            self.echo_commit = 0;
+
+            let _ = tty.flush_buffer(tty.core());
+
+            self.read_head = 0;
+            self.canon_head = 0;
+            self.read_tail = 0;
+            self.line_start = 0;
+
+            self.erasing = false;
+            self.read_flags.set_all(false);
+            self.pushing = false;
+            self.lookahead_count = 0;
+        }
+    }
+
+    pub fn receive_char(&mut self, c: u8, tty: Arc<TtyCore>) {
+        let termios = tty.core().termios();
+
+        if termios.local_mode.contains(LocalMode::ECHO) {
+            if self.erasing {
+                self.add_echo_byte(b'/');
+                self.erasing = false;
+            }
+
+            if self.canon_head == self.read_head {
+                self.add_echo_byte(EchoOperation::Start.to_u8());
+                self.add_echo_byte(EchoOperation::SetCanonCol.to_u8());
+            }
+
+            self.echo_char(c, &termios);
+            self.commit_echoes(tty.clone());
+        }
+
+        if c == 0o377 && tty.core().termios().input_mode.contains(InputMode::PARMRK) {
+            self.add_read_byte(c);
+        }
+        self.add_read_byte(c);
+    }
+
+    pub fn echo_char(&mut self, c: u8, termios: &RwLockReadGuard<Termios>) {
+        if c == EchoOperation::Start.to_u8() {
+            self.add_echo_byte(EchoOperation::Start.to_u8());
+            self.add_echo_byte(EchoOperation::Start.to_u8());
+        } else {
+            if termios.local_mode.contains(LocalMode::ECHOCTL)
+                && (c as char).is_control()
+                && c != b'\t'
+            {
+                self.add_echo_byte(EchoOperation::Start.to_u8());
+            }
+            self.add_echo_byte(c);
+        }
+    }
+
+    pub fn echo_char_raw(&mut self, c: u8) {
+        if c == EchoOperation::Start.to_u8() {
+            self.add_echo_byte(EchoOperation::Start.to_u8());
+            self.add_echo_byte(EchoOperation::Start.to_u8());
+        } else {
+            self.add_echo_byte(c);
+        }
+    }
+
+    /// ## 提交echobuf里的数据显示
+    pub fn commit_echoes(&mut self, tty: Arc<TtyCore>) {
+        let head = self.echo_head;
+        self.echo_mark = head;
+        let old = self.echo_commit - self.echo_tail;
+
+        // 需要echo的字符个数
+        let nr = head - self.echo_tail;
+
+        if nr < ECHO_COMMIT_WATERMARK || nr % ECHO_BLOCK > old % ECHO_BLOCK {
+            return;
+        }
+
+        self.echo_commit = head;
+        let echoed = self.echoes(tty.clone());
+
+        if echoed.is_ok() && echoed.unwrap() > 0 {
+            tty.flush_chars(tty.core());
+        }
+    }
+
+    pub fn add_echo_byte(&mut self, c: u8) {
+        self.echo_buf[ntty_buf_mask(self.echo_head)] = c;
+        self.echo_head += 1;
+    }
+
+    pub fn add_read_byte(&mut self, c: u8) {
+        self.read_buf[ntty_buf_mask(self.read_head)] = c;
+        self.read_head += 1;
+    }
+
+    /// ### 将read_buffer的部分值置0
+    ///
+    /// 只会在规范模式和禁用echo下执行
+    #[inline]
+    pub fn zero_buffer(&mut self, offset: usize, size: usize) {
+        let offset = offset & (NTTY_BUFSIZE - 1);
+        if self.icanon && !self.echo {
+            let n = offset + size;
+            if n > NTTY_BUFSIZE {
+                for c in &mut self.read_buf[offset..NTTY_BUFSIZE] {
+                    *c = 0
+                }
+
+                for c in &mut self.read_buf[0..(n - NTTY_BUFSIZE)] {
+                    *c = 0
+                }
+            } else {
+                for c in &mut self.read_buf[offset..n] {
+                    *c = 0
+                }
+            };
+        }
+    }
+
+    /// ## 从ntty中拷贝数据
+    ///
+    /// ### 参数
+    ///
+    /// ### to: 存储数据
+    /// ### tail: 读取尾
+    pub fn ntty_copy(
+        &mut self,
+        to: &mut [u8],
+        tail: usize,
+        n: &mut usize,
+    ) -> Result<(), SystemError> {
+        if to.len() < *n {
+            *n = to.len();
+            // return Err(SystemError::EINVAL);
+        }
+        if tail > NTTY_BUFSIZE {
+            return Err(SystemError::EINVAL);
+        }
+
+        let size = NTTY_BUFSIZE - tail;
+
+        if size < *n {
+            // 有一部分数据在头部,则先拷贝后面部分,再拷贝头部
+            // TODO: tty审计?
+            to[0..size].copy_from_slice(&self.read_buf[tail..(tail + size)]);
+            to[size..].copy_from_slice(&self.read_buf[(tail + size)..(*n + tail)]);
+        } else {
+            to[..*n].copy_from_slice(&self.read_buf[tail..(tail + *n)])
+        }
+
+        self.zero_buffer(tail, *n);
+
+        Ok(())
+    }
+
+    /// ## 规范模式下跳过EOF
+    pub fn canon_skip_eof(&mut self) {
+        // 没有数据
+        if self.read_tail == self.canon_head {
+            return;
+        }
+
+        let tail = self.read_tail & (NTTY_BUFSIZE - 1);
+
+        // 查看read_flags是否读取位置为特殊字符
+        if !self.read_flags.get(tail).unwrap() {
+            return;
+        }
+
+        // 确保读取位置是'\0'字符
+        if self.read_buf[tail] != ControlCharIndex::DISABLE_CHAR {
+            return;
+        }
+
+        // 处理该字符,将read_flagsw该位清除
+        self.read_flags.set(tail, false);
+        // 读取位置+1,即跳过该字符不做处理
+        self.read_tail += 1;
+    }
+
+    /// ## 在规范模式(canonical mode)下从读缓冲中复制一行
+    ///
+    /// 一次只拷贝一行
+    ///
+    /// ## 参数
+    /// ### dst: 存放数据
+    /// ### nr: 需要拷贝的数据大小
+    ///
+    /// ## 返回值
+    /// ### true: 表示一行未结束并且还有数据可读
+    /// ### false: 一行已结束或者没有数据可读
+    pub fn canon_copy_from_read_buf(
+        &mut self,
+        dst: &mut [u8],
+        nr: &mut usize,
+        offset: &mut usize,
+    ) -> Result<bool, SystemError> {
+        if *nr == 0 {
+            return Ok(false);
+        }
+
+        let canon_head = self.canon_head;
+
+        // 取得能够读到的字符数,即canon_head - self.read_tail和nr最小值
+        let mut n = (*nr).min(canon_head - self.read_tail);
+
+        // 获得读尾index
+        let tail = self.read_tail & (NTTY_BUFSIZE - 1);
+
+        // 避免越界,这个size才是实际读取大小
+        let size = if tail + n > NTTY_BUFSIZE {
+            NTTY_BUFSIZE
+        } else {
+            tail + *nr
+        };
+
+        // 找到eol的坐标
+        let tmp = self.read_flags.next_index(tail);
+        // 找到的话即为坐标,未找到的话即为NTTY_BUFSIZE
+        let mut eol = if tmp.is_none() { size } else { tmp.unwrap() };
+        if eol > size {
+            eol = size
+        }
+
+        // 是否需要绕回缓冲区头部
+        let more = n - (size - tail);
+
+        // 是否找到eol
+        let found = if eol == NTTY_BUFSIZE && more > 0 {
+            // 需要返回头部
+            let ret = self.read_flags.first_index();
+            if ret.is_some() {
+                let tmp = ret.unwrap();
+                // 在头部范围内找到eol
+                if tmp < more {
+                    eol = tmp;
+                }
+            } else {
+                eol = more;
+            }
+            eol != more
+        } else {
+            // 不需要返回头部
+            eol != size
+        };
+
+        n = eol - tail;
+        if n > NTTY_BUFSIZE {
+            // 减法溢出则加上BUFSIZE即可限制在0-NTTY_BUFSIZE内
+            n += NTTY_BUFSIZE;
+        }
+
+        // 规范模式下实际扫描过的字符数,需要将eol计算在内
+        let count = if found { n + 1 } else { n };
+
+        // 表示这一行未结束
+        if !found || self.read_at(eol) != ControlCharIndex::DISABLE_CHAR {
+            n = count;
+        }
+
+        self.ntty_copy(&mut dst[*offset..], tail, &mut n)?;
+        *nr -= n;
+        *offset += n;
+
+        if found {
+            self.read_flags.set(eol, false);
+        }
+
+        self.read_tail += count;
+
+        if found {
+            if !self.pushing {
+                self.line_start = self.read_tail;
+            } else {
+                self.pushing = false;
+            }
+
+            // todo: 审计?
+            return Ok(false);
+        }
+
+        // 这里是表示没有找到eol,根据是否还有数据可读返回
+        Ok(self.read_tail != canon_head)
+    }
+
+    /// ## 根据终端的模式和输入缓冲区中的数据量,判断是否可读字符
+    pub fn input_available(&self, termios: RwLockReadGuard<Termios>, poll: bool) -> bool {
+        // 计算最小字符数
+        let amt = if poll
+            && termios.control_characters[ControlCharIndex::VTIME] as u32 == 0
+            && termios.control_characters[ControlCharIndex::VMIN] as u32 != 0
+        {
+            termios.control_characters[ControlCharIndex::VMIN] as usize
+        } else {
+            1
+        };
+
+        // 规范模式且非拓展
+        if self.icanon && !termios.local_mode.contains(LocalMode::EXTPROC) {
+            return self.canon_head != self.read_tail;
+        } else {
+            return (self.commit_head - self.read_tail) >= amt;
+        }
+    }
+
+    /// ## 非规范模式下从read_buf读取数据
+    ///
+    /// ## 参数
+    /// ### termios: tty对应的termioss读锁守卫
+    /// ### dst: 存储读取数据
+    /// ### nr: 读取长度
+    ///
+    /// ## 返回值
+    /// ### true: 还有更多数据可读
+    /// ### false: 无更多数据可读
+    pub fn copy_from_read_buf(
+        &mut self,
+        termios: RwLockReadGuard<Termios>,
+        dst: &mut [u8],
+        nr: &mut usize,
+        offset: &mut usize,
+    ) -> Result<bool, SystemError> {
+        let head = self.commit_head;
+        let tail = self.read_tail & (NTTY_BUFSIZE - 1);
+
+        // 计算出可读的字符数
+        let mut n = (NTTY_BUFSIZE - tail).min(self.read_tail);
+        n = n.min(*nr);
+
+        if n > 0 {
+            // 拷贝数据
+            self.ntty_copy(&mut dst[*offset..], tail, &mut n)?;
+            // todo:审计?
+            self.read_tail += n;
+
+            // 是否只读取了eof
+            let eof =
+                n == 1 && self.read_buf[tail] == termios.control_characters[ControlCharIndex::VEOF];
+
+            if termios.local_mode.contains(LocalMode::EXTPROC)
+                && self.icanon
+                && eof
+                && head == self.read_tail
+            {
+                return Ok(false);
+            }
+
+            *nr -= n;
+            *offset += n;
+
+            return Ok(head != self.read_tail);
+        }
+
+        Ok(false)
+    }
+
+    /// ## 用于处理带有 OPOST(Output Post-processing)标志的输出块的函数
+    /// OPOST 是 POSIX 终端驱动器标志之一,用于指定在写入终端设备之前对输出数据进行一些后期处理。
+    pub fn process_output_block(
+        &mut self,
+        core: &TtyCoreData,
+        termios: RwLockReadGuard<Termios>,
+        buf: &[u8],
+        nr: usize,
+    ) -> Result<usize, SystemError> {
+        let mut nr = nr;
+        let tty = self.tty.clone().unwrap().upgrade().unwrap();
+        let space = tty.write_room(tty.core());
+
+        // 如果读取数量大于了可用空间,则取最小的为真正的写入数量
+        if nr > space {
+            nr = space
+        }
+
+        let mut cnt = 0;
+        for i in 0..nr {
+            cnt = i;
+            let c = buf[i];
+            if c as usize == 8 {
+                // 表示退格
+                if self.cursor_column > 0 {
+                    self.cursor_column -= 1;
+                }
+                continue;
+            }
+            match c as char {
+                '\n' => {
+                    if termios.output_mode.contains(OutputMode::ONLRET) {
+                        // 将回车映射为\n,即将\n换为回车
+                        self.cursor_column = 0;
+                    }
+                    if termios.output_mode.contains(OutputMode::ONLCR) {
+                        // 输出时将\n换为\r\n
+                        break;
+                    }
+
+                    self.canon_cursor_column = self.cursor_column;
+                }
+                '\r' => {
+                    if termios.output_mode.contains(OutputMode::ONOCR) && self.cursor_column == 0 {
+                        // 光标已经在第0列,则不输出回车符
+                        break;
+                    }
+
+                    if termios.output_mode.contains(OutputMode::OCRNL) {
+                        break;
+                    }
+                    self.canon_cursor_column = self.cursor_column;
+                }
+                '\t' => {
+                    break;
+                }
+                _ => {
+                    // 判断是否为控制字符
+                    if !(c as char).is_control() {
+                        if termios.output_mode.contains(OutputMode::OLCUC) {
+                            break;
+                        }
+
+                        // 判断是否为utf8模式下的连续字符
+                        if !(termios.input_mode.contains(InputMode::IUTF8)
+                            && (c as usize) & 0xc0 == 0x80)
+                        {
+                            self.cursor_column += 1;
+                        }
+                    }
+                }
+            }
+        }
+
+        drop(termios);
+        return tty.write(core, buf, cnt);
+    }
+
+    /// ## 处理回显
+    pub fn process_echoes(&mut self, tty: Arc<TtyCore>) {
+        if self.echo_mark == self.echo_tail {
+            return;
+        }
+        self.echo_commit = self.echo_mark;
+        let echoed = self.echoes(tty.clone());
+
+        if echoed.is_ok() && echoed.unwrap() > 0 {
+            let _ = tty.flush_chars(tty.core());
+        }
+    }
+
+    pub fn echoes(&mut self, tty: Arc<TtyCore>) -> Result<usize, SystemError> {
+        let mut space = tty.write_room(tty.core());
+        let ospace = space;
+        let termios = tty.core().termios();
+        let core = tty.core();
+        let mut tail = self.echo_tail;
+
+        while ntty_buf_mask(self.echo_commit) != ntty_buf_mask(tail) {
+            let c = self.echo_buf[ntty_buf_mask(tail)];
+
+            if EchoOperation::from_u8(c) == EchoOperation::Start {
+                if ntty_buf_mask(self.echo_commit) == ntty_buf_mask(tail + 1) {
+                    self.echo_tail = tail;
+                    return Ok(ospace - space);
+                }
+
+                // 获取到start,之后取第一个作为op
+                let op = EchoOperation::from_u8(self.echo_buf[ntty_buf_mask(tail + 1)]);
+
+                match op {
+                    EchoOperation::Start => {
+                        if space == 0 {
+                            break;
+                        }
+
+                        if tty
+                            .put_char(tty.core(), EchoOperation::Start.to_u8())
+                            .is_err()
+                        {
+                            tty.write(core, &[EchoOperation::Start.to_u8()], 1)?;
+                        }
+
+                        self.cursor_column += 1;
+                        space -= 1;
+                        tail += 2;
+                    }
+                    EchoOperation::MoveBackCol => {
+                        if self.cursor_column > 0 {
+                            self.cursor_column -= 1;
+                        }
+                        tail += 2;
+                    }
+                    EchoOperation::SetCanonCol => {
+                        self.canon_cursor_column = self.cursor_column;
+                        tail += 2;
+                    }
+                    EchoOperation::EraseTab => {
+                        if ntty_buf_mask(self.echo_commit) == ntty_buf_mask(tail + 2) {
+                            self.echo_tail = tail;
+                            return Ok(ospace - space);
+                        }
+
+                        // 要擦除的制表符所占用的列数
+                        let mut char_num = self.echo_buf[ntty_buf_mask(tail + 2)] as usize;
+
+                        /*
+                           如果 num_chars 的最高位(0x80)未设置,
+                           表示这是从输入的起始位置而不是从先前的制表符开始计算的列数。
+                           在这种情况下,将 num_chars 与 ldata->canon_column 相加,否则,列数就是正常的制表符列数。
+                        */
+                        if char_num & 0x80 == 0 {
+                            char_num += self.canon_cursor_column as usize;
+                        }
+
+                        // 计算要回退的列数,即制表符宽度减去实际占用的列数
+                        let mut num_bs = 8 - (char_num & 7);
+                        if num_bs > space {
+                            // 表示左边没有足够空间回退
+                            break;
+                        }
+
+                        space -= num_bs;
+                        while num_bs != 0 {
+                            num_bs -= 1;
+                            // 8 => '\b'
+                            if tty.put_char(tty.core(), 8).is_err() {
+                                tty.write(core, &[8], 1)?;
+                            }
+
+                            if self.cursor_column > 0 {
+                                self.cursor_column -= 1;
+                            }
+                        }
+
+                        // 已经读取了 tail tail+1 tail+2,所以这里偏移加3
+                        tail += 3;
+                    }
+                    EchoOperation::Undefined(ch) => {
+                        match ch {
+                            8 => {
+                                if tty.put_char(tty.core(), 8).is_err() {
+                                    tty.write(core, &[8], 1)?;
+                                }
+                                if tty.put_char(tty.core(), ' ' as u8).is_err() {
+                                    tty.write(core, &[' ' as u8], 1)?;
+                                }
+                                self.cursor_column -= 1;
+                                space -= 1;
+                                tail += 1;
+                            }
+                            _ => {
+                                // 不是特殊字节码,则表示控制字符 例如 ^C
+                                if space < 2 {
+                                    break;
+                                }
+
+                                if tty.put_char(tty.core(), b'^').is_err() {
+                                    tty.write(core, &[b'^'], 1)?;
+                                }
+
+                                if tty.put_char(tty.core(), ch ^ 0o100).is_err() {
+                                    tty.write(core, &[ch ^ 0o100], 1)?;
+                                }
+
+                                self.cursor_column += 2;
+                                space -= 2;
+                                tail += 2;
+                            }
+                        }
+                    }
+                }
+            } else {
+                if termios.output_mode.contains(OutputMode::OPOST) {
+                    let ret = self.do_output_char(tty.clone(), c, space);
+
+                    if ret.is_err() {
+                        break;
+                    }
+                    space -= ret.unwrap();
+                } else {
+                    if space == 0 {
+                        break;
+                    }
+
+                    if tty.put_char(tty.core(), c).is_err() {
+                        tty.write(core, &[c], 1)?;
+                    }
+                    space -= 1;
+                }
+                tail += 1;
+            }
+        }
+
+        // 如果回显缓冲区接近满(在下一次提交之前可能会发生回显溢出的情况),则丢弃足够的尾部数据以防止随后的溢出。
+        while self.echo_commit > tail && self.echo_commit - tail >= ECHO_DISCARD_WATERMARK {
+            if self.echo_buf[ntty_buf_mask(tail)] == EchoOperation::Start.to_u8() {
+                if self.echo_buf[ntty_buf_mask(tail + 1)] == EchoOperation::EraseTab.to_u8() {
+                    tail += 3;
+                } else {
+                    tail += 2;
+                }
+            } else {
+                tail += 1;
+            }
+        }
+
+        self.echo_tail = tail;
+        return Ok(ospace - space);
+    }
+
+    /// ## 处理输出字符(带有 OPOST 处理)
+    pub fn process_output(&mut self, tty: Arc<TtyCore>, c: u8) -> bool {
+        let space = tty.write_room(tty.core());
+
+        if self.do_output_char(tty, c, space).is_err() {
+            return false;
+        }
+
+        true
+    }
+
+    // ## 设置带有 OPOST 处理的tty输出一个字符
+    pub fn do_output_char(
+        &mut self,
+        tty: Arc<TtyCore>,
+        c: u8,
+        space: usize,
+    ) -> Result<usize, SystemError> {
+        if space == 0 {
+            return Err(SystemError::ENOBUFS);
+        }
+
+        let termios = tty.core().termios();
+        let core = tty.core();
+        let mut c = c;
+        if c as usize == 8 {
+            // 表示退格
+            if self.cursor_column > 0 {
+                self.cursor_column -= 1;
+            }
+            if tty.put_char(tty.core(), c).is_err() {
+                tty.write(core, &[c], 1)?;
+            }
+            return Ok(1);
+        }
+        match c as char {
+            '\n' => {
+                if termios.output_mode.contains(OutputMode::ONLRET) {
+                    // 回车符
+                    self.cursor_column = 0;
+                }
+                if termios.output_mode.contains(OutputMode::ONLCR) {
+                    // 映射为“\r\n”
+                    if space < 2 {
+                        return Err(SystemError::ENOBUFS);
+                    }
+                    self.cursor_column = 0;
+                    self.canon_cursor_column = 0;
+
+                    // 通过驱动写入
+                    tty.write(core, "\r\n".as_bytes(), 2)?;
+                    return Ok(2);
+                }
+
+                self.canon_cursor_column = self.cursor_column;
+            }
+            '\r' => {
+                if termios.output_mode.contains(OutputMode::ONOCR) && self.cursor_column == 0 {
+                    // 光标已经在第0列,则不输出回车符
+                    return Ok(0);
+                }
+
+                if termios.output_mode.contains(OutputMode::OCRNL) {
+                    // 输出的\r映射为\n
+                    c = b'\n';
+                    if termios.output_mode.contains(OutputMode::ONLRET) {
+                        // \r映射为\n,但是保留\r特性
+                        self.cursor_column = 0;
+                        self.canon_cursor_column = 0;
+                    }
+                } else {
+                    self.cursor_column = 0;
+                    self.canon_cursor_column = 0;
+                }
+            }
+            '\t' => {
+                // 计算输出一个\t需要的空间
+                let spaces = 8 - (self.cursor_column & 7) as usize;
+                if termios.output_mode.contains(OutputMode::TABDLY) {
+                    if OutputMode::TABDLY.bits() == OutputMode::XTABS.bits() {
+                        // 配置的tab选项是真正输出空格到驱动
+                        if space < spaces {
+                            // 空间不够
+                            return Err(SystemError::ENOBUFS);
+                        }
+                        self.cursor_column += spaces as u32;
+                        // 写入sapces个空格
+                        tty.write(core, "        ".as_bytes(), spaces)?;
+                        return Ok(spaces);
+                    }
+                }
+                self.cursor_column += spaces as u32;
+            }
+            _ => {
+                // 判断是否为控制字符
+                if !(c as char).is_control() {
+                    if termios.output_mode.contains(OutputMode::OLCUC) {
+                        c = c.to_ascii_uppercase();
+                    }
+
+                    // 判断是否为utf8模式下的连续字符
+                    if !(termios.input_mode.contains(InputMode::IUTF8)
+                        && (c as usize) & 0xc0 == 0x80)
+                    {
+                        self.cursor_column += 1;
+                    }
+                }
+            }
+        }
+
+        if tty.put_char(tty.core(), c).is_err() {
+            tty.write(core, &[c], 1)?;
+        }
+        Ok(1)
+    }
+}
+
+impl TtyLineDiscipline for NTtyLinediscipline {
+    fn open(&self, tty: Arc<TtyCore>) -> Result<(), system_error::SystemError> {
+        // 反向绑定tty到disc
+        self.disc_data().tty = Some(Arc::downgrade(&tty));
+        // 特定的tty设备在这里可能需要取消端口节流
+        return self.set_termios(tty, None);
+    }
+
+    fn close(&self, _tty: Arc<TtyCore>) -> Result<(), system_error::SystemError> {
+        todo!()
+    }
+
+    /// ## 重置缓冲区的基本信息
+    fn flush_buffer(&self, tty: Arc<TtyCore>) -> Result<(), system_error::SystemError> {
+        let core = tty.core();
+        let _ = core.termios();
+        let mut ldata = self.disc_data();
+        ldata.read_head = 0;
+        ldata.canon_head = 0;
+        ldata.read_tail = 0;
+        ldata.commit_head = 0;
+        ldata.line_start = 0;
+        ldata.erasing = false;
+        ldata.read_flags.set_all(false);
+        ldata.pushing = false;
+        ldata.lookahead_count = 0;
+
+        // todo: kick worker?
+        // todo: packet mode?
+
+        Ok(())
+    }
+
+    fn read(
+        &self,
+        tty: Arc<TtyCore>,
+        buf: &mut [u8],
+        len: usize,
+        cookie: &mut bool,
+        _offset: usize,
+        mode: FileMode,
+    ) -> Result<usize, system_error::SystemError> {
+        let mut ldata;
+        if mode.contains(FileMode::O_NONBLOCK) {
+            let ret = self.disc_data_try_lock();
+            if ret.is_err() {
+                return Err(SystemError::EAGAIN_OR_EWOULDBLOCK);
+            }
+            ldata = ret.unwrap();
+        } else {
+            ldata = self.disc_data();
+        }
+        let core = tty.core();
+        let termios = core.termios();
+        let mut nr = len;
+
+        let mut offset = 0;
+
+        // 表示接着读
+        if *cookie {
+            // 规范且非拓展模式
+            if ldata.icanon && !termios.local_mode.contains(LocalMode::EXTPROC) {
+                // 跳过EOF字符
+                if len == 0 {
+                    ldata.canon_skip_eof();
+                } else if ldata.canon_copy_from_read_buf(buf, &mut nr, &mut offset)? {
+                    return Ok(len - nr);
+                }
+            } else {
+                if ldata.canon_copy_from_read_buf(buf, &mut nr, &mut offset)? {
+                    return Ok(len - nr);
+                }
+            }
+
+            // 没有数据可读
+
+            // todo: kick worker? or 关闭节流?
+
+            *cookie = false;
+            return Ok(len - nr);
+        }
+
+        drop(termios);
+
+        TtyJobCtrlManager::tty_check_change(tty.clone(), Signal::SIGTTIN)?;
+
+        let mut minimum: usize = 0;
+        if !ldata.icanon {
+            let core = tty.core();
+            let termios = core.termios();
+            minimum = termios.control_characters[ControlCharIndex::VMIN] as usize;
+            if minimum == 0 {
+                minimum = 1;
+            }
+        }
+
+        let mut ret: Result<usize, SystemError> = Ok(0);
+        // 记录读取前 的tail
+        let tail = ldata.read_tail;
+        drop(ldata);
+        while nr != 0 {
+            // todo: 处理packet模式
+            let mut ldata = self.disc_data();
+
+            let core = tty.core();
+            if !ldata.input_available(core.termios(), false) {
+                if core.flags().contains(TtyFlag::OTHER_CLOSED) {
+                    ret = Err(SystemError::EIO);
+                    break;
+                }
+
+                if core.flags().contains(TtyFlag::HUPPED) || core.flags().contains(TtyFlag::HUPPING)
+                {
+                    break;
+                }
+
+                if mode.contains(FileMode::O_NONBLOCK)
+                    || core.flags().contains(TtyFlag::LDISC_CHANGING)
+                {
+                    ret = Err(SystemError::EAGAIN_OR_EWOULDBLOCK);
+                    break;
+                }
+
+                if ProcessManager::current_pcb()
+                    .sig_info()
+                    .sig_pending()
+                    .has_pending()
+                {
+                    ret = Err(SystemError::ERESTARTSYS);
+                    break;
+                }
+
+                // 休眠一段时间
+                // 获取到termios读锁,避免termios被更改导致行为异常
+                // let termios = core.termios_preempt_enable();
+                // let helper = WakeUpHelper::new(ProcessManager::current_pcb());
+                // let wakeup_helper = Timer::new(helper, timeout);
+                // wakeup_helper.activate();
+                // drop(termios);
+                drop(ldata);
+                core.read_wq()
+                    .sleep((EPollEventType::EPOLLIN | EPollEventType::EPOLLRDNORM).bits() as u64);
+                continue;
+            }
+
+            if ldata.icanon && !core.termios().local_mode.contains(LocalMode::EXTPROC) {
+                if ldata.canon_copy_from_read_buf(buf, &mut nr, &mut offset)? {
+                    *cookie = true;
+                    offset += len - nr;
+                    return Ok(offset);
+                }
+            } else {
+                // 非标准模式
+                // todo: 处理packet模式
+
+                // 拷贝数据
+                if ldata.copy_from_read_buf(core.termios(), buf, &mut nr, &mut offset)?
+                    && offset >= minimum
+                {
+                    *cookie = true;
+                    return Ok(offset);
+                }
+            }
+
+            if offset >= minimum {
+                break;
+            }
+        }
+        let ldata = self.disc_data();
+        if tail != ldata.read_tail {
+            // todo: kick worker?
+        }
+
+        if offset > 0 {
+            return Ok(offset);
+        }
+
+        ret
+    }
+
+    fn write(
+        &self,
+        tty: Arc<TtyCore>,
+        buf: &[u8],
+        len: usize,
+        mode: FileMode,
+    ) -> Result<usize, system_error::SystemError> {
+        let mut nr = len;
+        let mut ldata = self.disc_data();
+        let pcb = ProcessManager::current_pcb();
+        let binding = tty.clone();
+        let core = binding.core();
+        let termios = core.termios().clone();
+        if termios.local_mode.contains(LocalMode::TOSTOP) {
+            TtyJobCtrlManager::tty_check_change(tty.clone(), Signal::SIGTTOU)?;
+        }
+
+        ldata.process_echoes(tty.clone());
+        // drop(ldata);
+        let mut offset = 0;
+        loop {
+            if pcb.sig_info().sig_pending().has_pending() {
+                return Err(SystemError::ERESTARTSYS);
+            }
+            if core.flags().contains(TtyFlag::HUPPED) {
+                return Err(SystemError::EIO);
+            }
+            if termios.output_mode.contains(OutputMode::OPOST) {
+                while nr > 0 {
+                    // let mut ldata = self.disc_data();
+                    // 获得一次处理后的数量
+                    let ret = ldata.process_output_block(core, core.termios(), &buf[offset..], nr);
+                    let num = match ret {
+                        Ok(num) => num,
+                        Err(e) => {
+                            if e == SystemError::EAGAIN_OR_EWOULDBLOCK {
+                                break;
+                            } else {
+                                return Err(e);
+                            }
+                        }
+                    };
+
+                    offset += num;
+                    nr -= num;
+
+                    if nr == 0 {
+                        break;
+                    }
+
+                    let c = buf[offset];
+                    if !ldata.process_output(tty.clone(), c) {
+                        break;
+                    }
+                    offset += 1;
+                    nr -= 1;
+                }
+
+                let _ = tty.flush_chars(core);
+            } else {
+                while nr > 0 {
+                    let write = tty.write(core, &buf[offset..], nr)?;
+                    if write == 0 {
+                        break;
+                    }
+                    offset += write;
+                    nr -= write;
+                }
+            }
+
+            if nr == 0 {
+                break;
+            }
+
+            if mode.contains(FileMode::O_NONBLOCK) || core.flags().contains(TtyFlag::LDISC_CHANGING)
+            {
+                return Err(SystemError::EAGAIN_OR_EWOULDBLOCK);
+            }
+
+            // 到这里表明没位置可写了
+            // 休眠一段时间
+            // 获取到termios读锁,避免termios被更改导致行为异常
+            core.write_wq()
+                .sleep(EPollEventType::EPOLLOUT.bits() as u64);
+        }
+
+        Ok(offset)
+    }
+
+    fn ioctl(
+        &self,
+        tty: Arc<TtyCore>,
+        cmd: u32,
+        arg: usize,
+    ) -> Result<usize, system_error::SystemError> {
+        match cmd {
+            TtyIoctlCmd::TIOCOUTQ => {
+                let mut user_writer = UserBufferWriter::new(
+                    VirtAddr::new(arg).as_ptr::<i32>(),
+                    core::mem::size_of::<i32>(),
+                    true,
+                )?;
+
+                let count = tty.chars_in_buffer();
+                user_writer.copy_one_to_user::<i32>(&(count as i32), 0)?;
+                return Ok(0);
+            }
+            TtyIoctlCmd::FIONREAD => {
+                let ldata = self.disc_data();
+                let termios = tty.core().termios();
+                let retval;
+                if termios.local_mode.contains(LocalMode::ICANON)
+                    && !termios.local_mode.contains(LocalMode::EXTPROC)
+                {
+                    if ldata.canon_head == ldata.read_tail {
+                        retval = 0;
+                    } else {
+                        let head = ldata.canon_head;
+                        let mut tail = ldata.read_tail;
+                        let mut nr = head - tail;
+
+                        while ntty_buf_mask(head) != ntty_buf_mask(tail) {
+                            if ldata.read_flags.get(ntty_buf_mask(tail)).unwrap()
+                                && ldata.read_buf[ntty_buf_mask(tail)]
+                                    == ControlCharIndex::DISABLE_CHAR
+                            {
+                                nr -= 1;
+                            }
+                            tail += 1;
+                        }
+
+                        retval = nr;
+                    }
+                } else {
+                    retval = ldata.read_cnt();
+                }
+
+                let mut user_writer = UserBufferWriter::new(
+                    VirtAddr::new(arg).as_ptr::<i32>(),
+                    core::mem::size_of::<i32>(),
+                    true,
+                )?;
+
+                user_writer.copy_one_to_user::<i32>(&(retval as i32), 0)?;
+                return Ok(0);
+            }
+            _ => {
+                return self.ioctl_helper(tty, cmd, arg);
+            }
+        }
+    }
+
+    fn set_termios(
+        &self,
+        tty: Arc<TtyCore>,
+        old: Option<crate::driver::tty::termios::Termios>,
+    ) -> Result<(), system_error::SystemError> {
+        let core = tty.core();
+        let termios = core.termios();
+        let mut ldata = self.disc_data();
+        let contorl_chars = termios.control_characters;
+
+        // 第一次设置或者规范模式 (ICANON) 或者扩展处理 (EXTPROC) 标志发生变化
+        if old.is_none()
+            || (old.is_some()
+                && old
+                    .unwrap()
+                    .local_mode
+                    .bitxor(termios.local_mode)
+                    .contains(LocalMode::ICANON | LocalMode::EXTPROC))
+        {
+            // 重置read_flags
+            ldata.read_flags.set_all(false);
+
+            ldata.line_start = ldata.read_tail;
+
+            // 不是规范模式或者有可读数据
+            if !termios.local_mode.contains(LocalMode::ICANON) || ldata.read_cnt() != 0 {
+                ldata.canon_head = ldata.read_tail;
+                ldata.pushing = false;
+            } else {
+                let read_head = ldata.read_head;
+                ldata
+                    .read_flags
+                    .set((read_head - 1) & (NTTY_BUFSIZE - 1), true);
+                ldata.canon_head = ldata.read_head;
+                ldata.pushing = true;
+            }
+            ldata.commit_head = ldata.read_head;
+            ldata.erasing = false;
+            ldata.lnext = false;
+        }
+
+        // 设置规范模式
+        if termios.local_mode.contains(LocalMode::ICANON) {
+            ldata.icanon = true;
+        }
+
+        // 设置回显
+        if termios.local_mode.contains(LocalMode::ECHO) {
+            ldata.echo = true;
+        }
+
+        if termios.input_mode.contains(InputMode::ISTRIP)
+            || termios.input_mode.contains(InputMode::IUCLC)
+            || termios.input_mode.contains(InputMode::IGNCR)
+            || termios.input_mode.contains(InputMode::IXON)
+            || termios.local_mode.contains(LocalMode::ISIG)
+            || termios.local_mode.contains(LocalMode::ECHO)
+            || termios.input_mode.contains(InputMode::PARMRK)
+        {
+            // 非原模式
+
+            ldata.char_map.set_all(false);
+
+            // 忽略回车符或者将回车映射为换行符
+            if termios.input_mode.contains(InputMode::IGNCR)
+                || termios.input_mode.contains(InputMode::ICRNL)
+            {
+                ldata.char_map.set('\r' as usize, true);
+            }
+
+            // 将换行映射为回车
+            if termios.input_mode.contains(InputMode::INLCR) {
+                ldata.char_map.set('\n' as usize, true);
+            }
+
+            // 规范模式
+            if termios.local_mode.contains(LocalMode::ICANON) {
+                ldata
+                    .char_map
+                    .set(contorl_chars[ControlCharIndex::VERASE] as usize, true);
+                ldata
+                    .char_map
+                    .set(contorl_chars[ControlCharIndex::VKILL] as usize, true);
+                ldata
+                    .char_map
+                    .set(contorl_chars[ControlCharIndex::VEOF] as usize, true);
+                ldata.char_map.set('\n' as usize, true);
+                ldata
+                    .char_map
+                    .set(contorl_chars[ControlCharIndex::VEOL] as usize, true);
+
+                if termios.local_mode.contains(LocalMode::IEXTEN) {
+                    ldata
+                        .char_map
+                        .set(contorl_chars[ControlCharIndex::VWERASE] as usize, true);
+                    ldata
+                        .char_map
+                        .set(contorl_chars[ControlCharIndex::VLNEXT] as usize, true);
+                    ldata
+                        .char_map
+                        .set(contorl_chars[ControlCharIndex::VEOL2] as usize, true);
+                    if termios.local_mode.contains(LocalMode::ECHO) {
+                        ldata
+                            .char_map
+                            .set(contorl_chars[ControlCharIndex::VREPRINT] as usize, true);
+                    }
+                }
+            }
+
+            // 软件流控制
+            if termios.input_mode.contains(InputMode::IXON) {
+                ldata
+                    .char_map
+                    .set(contorl_chars[ControlCharIndex::VSTART] as usize, true);
+                ldata
+                    .char_map
+                    .set(contorl_chars[ControlCharIndex::VSTOP] as usize, true);
+            }
+
+            if termios.local_mode.contains(LocalMode::ISIG) {
+                ldata
+                    .char_map
+                    .set(contorl_chars[ControlCharIndex::VINTR] as usize, true);
+                ldata
+                    .char_map
+                    .set(contorl_chars[ControlCharIndex::VQUIT] as usize, true);
+                ldata
+                    .char_map
+                    .set(contorl_chars[ControlCharIndex::VSUSP] as usize, true);
+            }
+
+            ldata
+                .char_map
+                .set(ControlCharIndex::DISABLE_CHAR as usize, true);
+            ldata.raw = false;
+            ldata.real_raw = false;
+        } else {
+            // 原模式或real_raw
+            ldata.raw = true;
+
+            if termios.input_mode.contains(InputMode::IGNBRK)
+                || (!termios.input_mode.contains(InputMode::BRKINT)
+                    && !termios.input_mode.contains(InputMode::PARMRK))
+                    && (termios.input_mode.contains(InputMode::IGNPAR)
+                        || !termios.input_mode.contains(InputMode::INPCK))
+                    && (core
+                        .driver()
+                        .flags()
+                        .contains(TtyDriverFlag::TTY_DRIVER_REAL_RAW))
+            {
+                ldata.real_raw = true;
+            } else {
+                ldata.real_raw = false;
+            }
+        }
+
+        // if !termios.input_mode.contains(InputMode::IXON)
+        //     && old.is_some()
+        //     && old.unwrap().input_mode.contains(InputMode::IXON) && !
+        // {}
+
+        core.read_wq().wakeup_all();
+        core.write_wq().wakeup_all();
+        Ok(())
+    }
+
+    fn poll(&self, _tty: Arc<TtyCore>) -> Result<(), system_error::SystemError> {
+        todo!()
+    }
+
+    fn hangup(&self, _tty: Arc<TtyCore>) -> Result<(), system_error::SystemError> {
+        todo!()
+    }
+
+    fn receive_buf(
+        &self,
+        tty: Arc<TtyCore>,
+        buf: &[u8],
+        flags: Option<&[u8]>,
+        count: usize,
+    ) -> Result<usize, SystemError> {
+        let mut ldata = self.disc_data();
+        ldata.receive_buf_common(tty, buf, flags, count, false)
+    }
+
+    fn receive_buf2(
+        &self,
+        tty: Arc<TtyCore>,
+        buf: &[u8],
+        flags: Option<&[u8]>,
+        count: usize,
+    ) -> Result<usize, SystemError> {
+        let mut ldata = self.disc_data();
+        ldata.receive_buf_common(tty, buf, flags, count, true)
+    }
+}

+ 113 - 0
kernel/src/driver/tty/tty_port.rs

@@ -0,0 +1,113 @@
+use core::fmt::Debug;
+
+use alloc::{
+    sync::{Arc, Weak},
+    vec::Vec,
+};
+use kdepends::thingbuf::mpsc;
+use system_error::SystemError;
+
+use crate::{
+    driver::tty::virtual_terminal::MAX_NR_CONSOLES,
+    libs::spinlock::{SpinLock, SpinLockGuard},
+};
+
+use super::tty_core::TtyCore;
+
+const TTY_PORT_BUFSIZE: usize = 4096;
+
+lazy_static! {
+    pub static ref TTY_PORTS: Vec<Arc<dyn TtyPort>> = {
+        let mut v: Vec<Arc<dyn TtyPort>> = Vec::with_capacity(MAX_NR_CONSOLES as usize);
+        for _ in 0..MAX_NR_CONSOLES as usize {
+            v.push(Arc::new(DefaultTtyPort::new()))
+        }
+
+        v
+    };
+}
+
+#[allow(dead_code)]
+#[derive(Debug)]
+pub struct TtyPortData {
+    flags: i32,
+    iflags: TtyPortState,
+    sender: mpsc::Sender<u8>,
+    receiver: mpsc::Receiver<u8>,
+    tty: Weak<TtyCore>,
+}
+
+impl TtyPortData {
+    pub fn new() -> Self {
+        let (sender, receiver) = mpsc::channel::<u8>(TTY_PORT_BUFSIZE);
+        Self {
+            flags: 0,
+            iflags: TtyPortState::Initialized,
+            sender,
+            receiver,
+            tty: Weak::new(),
+        }
+    }
+
+    pub fn tty(&self) -> Option<Arc<TtyCore>> {
+        self.tty.upgrade()
+    }
+}
+
+#[allow(dead_code)]
+#[derive(Debug, PartialEq, Clone, Copy)]
+pub enum TtyPortState {
+    Initialized,
+    Suspended,
+    Active,
+    CtsFlow,
+    CheckCD,
+    KOPENED,
+}
+
+pub trait TtyPort: Sync + Send + Debug {
+    fn port_data(&self) -> SpinLockGuard<TtyPortData>;
+
+    /// 获取Port的状态
+    fn state(&self) -> TtyPortState {
+        self.port_data().iflags
+    }
+
+    /// 为port设置tty
+    fn setup_tty(&self, tty: Weak<TtyCore>) {
+        self.port_data().tty = tty;
+    }
+
+    /// 作为客户端的tty ports接收数据
+    fn receive_buf(&self, buf: &[u8], _flags: &[u8], count: usize) -> Result<usize, SystemError> {
+        let tty = self.port_data().tty.upgrade().unwrap();
+
+        let ld = tty.ldisc();
+
+        let ret = ld.receive_buf2(tty.clone(), buf, None, count);
+        if ret.is_err() && ret.clone().unwrap_err() == SystemError::ENOSYS {
+            return ld.receive_buf(tty, buf, None, count);
+        }
+
+        ret
+    }
+}
+
+#[derive(Debug)]
+pub struct DefaultTtyPort {
+    port_data: SpinLock<TtyPortData>,
+}
+
+impl DefaultTtyPort {
+    pub fn new() -> Self {
+        Self {
+            port_data: SpinLock::new(TtyPortData::new()),
+        }
+    }
+}
+
+impl TtyPort for DefaultTtyPort {
+    fn port_data(&self) -> SpinLockGuard<TtyPortData> {
+        self.port_data.lock_irqsave()
+    }
+}

+ 135 - 0
kernel/src/driver/tty/virtual_terminal/console_map.rs

@@ -0,0 +1,135 @@
+///  Latin-1 字符集到 Unicode 的映射表。在这个表格中,每个位置都存储了相应 Latin-1 字符的 Unicode 编码。
+pub const LAT1_MAP: &'static [u16] = &[
+    0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b,
+    0x000c, 0x000d, 0x000e, 0x000f, 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
+    0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f, 0x0020, 0x0021, 0x0022, 0x0023,
+    0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
+    0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b,
+    0x003c, 0x003d, 0x003e, 0x003f, 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
+    0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, 0x0050, 0x0051, 0x0052, 0x0053,
+    0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
+    0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b,
+    0x006c, 0x006d, 0x006e, 0x006f, 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
+    0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f, 0x0080, 0x0081, 0x0082, 0x0083,
+    0x0084, 0x0085, 0x0086, 0x0087, 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
+    0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, 0x0098, 0x0099, 0x009a, 0x009b,
+    0x009c, 0x009d, 0x009e, 0x009f, 0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7,
+    0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af, 0x00b0, 0x00b1, 0x00b2, 0x00b3,
+    0x00b4, 0x00b5, 0x00b6, 0x00b7, 0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf,
+    0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7, 0x00c8, 0x00c9, 0x00ca, 0x00cb,
+    0x00cc, 0x00cd, 0x00ce, 0x00cf, 0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7,
+    0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df, 0x00e0, 0x00e1, 0x00e2, 0x00e3,
+    0x00e4, 0x00e5, 0x00e6, 0x00e7, 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,
+    0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7, 0x00f8, 0x00f9, 0x00fa, 0x00fb,
+    0x00fc, 0x00fd, 0x00fe, 0x00ff,
+];
+
+/// 将 VT100 图形字符映射到 Unicode 的映射表
+pub const GRAF_MAP: &'static [u16] = &[
+    0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b,
+    0x000c, 0x000d, 0x000e, 0x000f, 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
+    0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f, 0x0020, 0x0021, 0x0022, 0x0023,
+    0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x2192, 0x2190, 0x2191, 0x2193, 0x002f,
+    0x2588, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b,
+    0x003c, 0x003d, 0x003e, 0x003f, 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
+    0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, 0x0050, 0x0051, 0x0052, 0x0053,
+    0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x00a0,
+    0x25c6, 0x2592, 0x2409, 0x240c, 0x240d, 0x240a, 0x00b0, 0x00b1, 0x2591, 0x240b, 0x2518, 0x2510,
+    0x250c, 0x2514, 0x253c, 0x23ba, 0x23bb, 0x2500, 0x23bc, 0x23bd, 0x251c, 0x2524, 0x2534, 0x252c,
+    0x2502, 0x2264, 0x2265, 0x03c0, 0x2260, 0x00a3, 0x00b7, 0x007f, 0x0080, 0x0081, 0x0082, 0x0083,
+    0x0084, 0x0085, 0x0086, 0x0087, 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
+    0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, 0x0098, 0x0099, 0x009a, 0x009b,
+    0x009c, 0x009d, 0x009e, 0x009f, 0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7,
+    0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af, 0x00b0, 0x00b1, 0x00b2, 0x00b3,
+    0x00b4, 0x00b5, 0x00b6, 0x00b7, 0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf,
+    0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7, 0x00c8, 0x00c9, 0x00ca, 0x00cb,
+    0x00cc, 0x00cd, 0x00ce, 0x00cf, 0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7,
+    0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df, 0x00e0, 0x00e1, 0x00e2, 0x00e3,
+    0x00e4, 0x00e5, 0x00e6, 0x00e7, 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,
+    0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7, 0x00f8, 0x00f9, 0x00fa, 0x00fb,
+    0x00fc, 0x00fd, 0x00fe, 0x00ff,
+];
+
+/// 将 IBM Codepage 437 字符集映射到 Unicode 的映射表
+pub const IBMPC_MAP: &'static [u16] = &[
+    0x0000, 0x263a, 0x263b, 0x2665, 0x2666, 0x2663, 0x2660, 0x2022, 0x25d8, 0x25cb, 0x25d9, 0x2642,
+    0x2640, 0x266a, 0x266b, 0x263c, 0x25b6, 0x25c0, 0x2195, 0x203c, 0x00b6, 0x00a7, 0x25ac, 0x21a8,
+    0x2191, 0x2193, 0x2192, 0x2190, 0x221f, 0x2194, 0x25b2, 0x25bc, 0x0020, 0x0021, 0x0022, 0x0023,
+    0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
+    0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b,
+    0x003c, 0x003d, 0x003e, 0x003f, 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
+    0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, 0x0050, 0x0051, 0x0052, 0x0053,
+    0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
+    0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b,
+    0x006c, 0x006d, 0x006e, 0x006f, 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
+    0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x2302, 0x00c7, 0x00fc, 0x00e9, 0x00e2,
+    0x00e4, 0x00e0, 0x00e5, 0x00e7, 0x00ea, 0x00eb, 0x00e8, 0x00ef, 0x00ee, 0x00ec, 0x00c4, 0x00c5,
+    0x00c9, 0x00e6, 0x00c6, 0x00f4, 0x00f6, 0x00f2, 0x00fb, 0x00f9, 0x00ff, 0x00d6, 0x00dc, 0x00a2,
+    0x00a3, 0x00a5, 0x20a7, 0x0192, 0x00e1, 0x00ed, 0x00f3, 0x00fa, 0x00f1, 0x00d1, 0x00aa, 0x00ba,
+    0x00bf, 0x2310, 0x00ac, 0x00bd, 0x00bc, 0x00a1, 0x00ab, 0x00bb, 0x2591, 0x2592, 0x2593, 0x2502,
+    0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255d, 0x255c, 0x255b, 0x2510,
+    0x2514, 0x2534, 0x252c, 0x251c, 0x2500, 0x253c, 0x255e, 0x255f, 0x255a, 0x2554, 0x2569, 0x2566,
+    0x2560, 0x2550, 0x256c, 0x2567, 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256b,
+    0x256a, 0x2518, 0x250c, 0x2588, 0x2584, 0x258c, 0x2590, 0x2580, 0x03b1, 0x00df, 0x0393, 0x03c0,
+    0x03a3, 0x03c3, 0x00b5, 0x03c4, 0x03a6, 0x0398, 0x03a9, 0x03b4, 0x221e, 0x03c6, 0x03b5, 0x2229,
+    0x2261, 0x00b1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00f7, 0x2248, 0x00b0, 0x2219, 0x00b7, 0x221a,
+    0x207f, 0x00b2, 0x25a0, 0x00a0,
+];
+
+/// 默认直接映射表
+pub const USER_MAP: &'static [u16] = &[
+    0xf000, 0xf001, 0xf002, 0xf003, 0xf004, 0xf005, 0xf006, 0xf007, 0xf008, 0xf009, 0xf00a, 0xf00b,
+    0xf00c, 0xf00d, 0xf00e, 0xf00f, 0xf010, 0xf011, 0xf012, 0xf013, 0xf014, 0xf015, 0xf016, 0xf017,
+    0xf018, 0xf019, 0xf01a, 0xf01b, 0xf01c, 0xf01d, 0xf01e, 0xf01f, 0xf020, 0xf021, 0xf022, 0xf023,
+    0xf024, 0xf025, 0xf026, 0xf027, 0xf028, 0xf029, 0xf02a, 0xf02b, 0xf02c, 0xf02d, 0xf02e, 0xf02f,
+    0xf030, 0xf031, 0xf032, 0xf033, 0xf034, 0xf035, 0xf036, 0xf037, 0xf038, 0xf039, 0xf03a, 0xf03b,
+    0xf03c, 0xf03d, 0xf03e, 0xf03f, 0xf040, 0xf041, 0xf042, 0xf043, 0xf044, 0xf045, 0xf046, 0xf047,
+    0xf048, 0xf049, 0xf04a, 0xf04b, 0xf04c, 0xf04d, 0xf04e, 0xf04f, 0xf050, 0xf051, 0xf052, 0xf053,
+    0xf054, 0xf055, 0xf056, 0xf057, 0xf058, 0xf059, 0xf05a, 0xf05b, 0xf05c, 0xf05d, 0xf05e, 0xf05f,
+    0xf060, 0xf061, 0xf062, 0xf063, 0xf064, 0xf065, 0xf066, 0xf067, 0xf068, 0xf069, 0xf06a, 0xf06b,
+    0xf06c, 0xf06d, 0xf06e, 0xf06f, 0xf070, 0xf071, 0xf072, 0xf073, 0xf074, 0xf075, 0xf076, 0xf077,
+    0xf078, 0xf079, 0xf07a, 0xf07b, 0xf07c, 0xf07d, 0xf07e, 0xf07f, 0xf080, 0xf081, 0xf082, 0xf083,
+    0xf084, 0xf085, 0xf086, 0xf087, 0xf088, 0xf089, 0xf08a, 0xf08b, 0xf08c, 0xf08d, 0xf08e, 0xf08f,
+    0xf090, 0xf091, 0xf092, 0xf093, 0xf094, 0xf095, 0xf096, 0xf097, 0xf098, 0xf099, 0xf09a, 0xf09b,
+    0xf09c, 0xf09d, 0xf09e, 0xf09f, 0xf0a0, 0xf0a1, 0xf0a2, 0xf0a3, 0xf0a4, 0xf0a5, 0xf0a6, 0xf0a7,
+    0xf0a8, 0xf0a9, 0xf0aa, 0xf0ab, 0xf0ac, 0xf0ad, 0xf0ae, 0xf0af, 0xf0b0, 0xf0b1, 0xf0b2, 0xf0b3,
+    0xf0b4, 0xf0b5, 0xf0b6, 0xf0b7, 0xf0b8, 0xf0b9, 0xf0ba, 0xf0bb, 0xf0bc, 0xf0bd, 0xf0be, 0xf0bf,
+    0xf0c0, 0xf0c1, 0xf0c2, 0xf0c3, 0xf0c4, 0xf0c5, 0xf0c6, 0xf0c7, 0xf0c8, 0xf0c9, 0xf0ca, 0xf0cb,
+    0xf0cc, 0xf0cd, 0xf0ce, 0xf0cf, 0xf0d0, 0xf0d1, 0xf0d2, 0xf0d3, 0xf0d4, 0xf0d5, 0xf0d6, 0xf0d7,
+    0xf0d8, 0xf0d9, 0xf0da, 0xf0db, 0xf0dc, 0xf0dd, 0xf0de, 0xf0df, 0xf0e0, 0xf0e1, 0xf0e2, 0xf0e3,
+    0xf0e4, 0xf0e5, 0xf0e6, 0xf0e7, 0xf0e8, 0xf0e9, 0xf0ea, 0xf0eb, 0xf0ec, 0xf0ed, 0xf0ee, 0xf0ef,
+    0xf0f0, 0xf0f1, 0xf0f2, 0xf0f3, 0xf0f4, 0xf0f5, 0xf0f6, 0xf0f7, 0xf0f8, 0xf0f9, 0xf0fa, 0xf0fb,
+    0xf0fc, 0xf0fd, 0xf0fe, 0xf0ff,
+];
+
+#[allow(dead_code)]
+#[derive(Debug, Clone)]
+pub enum TranslationMapType {
+    Lat1Map,
+    GrafMap,
+    IbmpcMap,
+    UserMap,
+}
+
+#[derive(Debug, Clone)]
+pub struct TranslationMap {
+    pub map_type: TranslationMapType,
+    pub map: &'static [u16],
+}
+
+impl TranslationMap {
+    pub const fn new(map_type: TranslationMapType) -> Self {
+        let map = match map_type {
+            TranslationMapType::Lat1Map => LAT1_MAP,
+            TranslationMapType::GrafMap => GRAF_MAP,
+            TranslationMapType::IbmpcMap => IBMPC_MAP,
+            TranslationMapType::UserMap => USER_MAP,
+        };
+
+        Self { map_type, map }
+    }
+
+    pub fn translate(&self, c: u32) -> u16 {
+        self.map[c as usize]
+    }
+}

+ 303 - 0
kernel/src/driver/tty/virtual_terminal/mod.rs

@@ -0,0 +1,303 @@
+use core::sync::atomic::Ordering;
+
+use alloc::{string::String, sync::Arc, vec::Vec};
+use system_error::SystemError;
+
+use crate::{
+    driver::{
+        base::device::{
+            device_number::{DeviceNumber, Major},
+            device_register, IdTable,
+        },
+        video::fbdev::base::fbcon::framebuffer_console::BlittingFbConsole,
+    },
+    filesystem::devfs::devfs_register,
+    libs::spinlock::SpinLock,
+};
+
+use self::virtual_console::{VirtualConsoleData, CURRENT_VCNUM};
+
+use super::{
+    console::ConsoleSwitch,
+    termios::{InputMode, TTY_STD_TERMIOS},
+    tty_core::{TtyCore, TtyCoreData},
+    tty_device::TtyDevice,
+    tty_driver::{TtyDriver, TtyDriverManager, TtyDriverType, TtyOperation},
+};
+
+pub mod console_map;
+pub mod virtual_console;
+
+pub const MAX_NR_CONSOLES: u32 = 63;
+pub const VC_MAXCOL: usize = 32767;
+pub const VC_MAXROW: usize = 32767;
+
+pub const DEFAULT_RED: [u16; 16] = [
+    0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x55, 0xff, 0x55, 0xff, 0x55, 0xff, 0x55, 0xff,
+];
+
+pub const DEFAULT_GREEN: [u16; 16] = [
+    0x00, 0x00, 0xaa, 0x55, 0x00, 0x00, 0xaa, 0xaa, 0x55, 0x55, 0xff, 0xff, 0x55, 0x55, 0xff, 0xff,
+];
+
+pub const DEFAULT_BLUE: [u16; 16] = [
+    0x00, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55, 0xff, 0xff, 0xff, 0xff,
+];
+
+pub const COLOR_TABLE: &'static [u8] = &[0, 4, 2, 6, 1, 5, 3, 7, 8, 12, 10, 14, 9, 13, 11, 15];
+
+lazy_static! {
+    pub static ref VIRT_CONSOLES: Vec<Arc<SpinLock<VirtualConsoleData>>> = {
+        let mut v = Vec::with_capacity(MAX_NR_CONSOLES as usize);
+        for i in 0..MAX_NR_CONSOLES as usize {
+            v.push(Arc::new(SpinLock::new(VirtualConsoleData::new(i))));
+        }
+
+        v
+    };
+}
+
+#[derive(Debug, Clone, Copy, Default)]
+pub struct Color {
+    pub red: u16,
+    pub green: u16,
+    pub blue: u16,
+    pub transp: u16,
+}
+
+impl Color {
+    pub fn from_256(col: u32) -> Self {
+        let mut color = Self::default();
+        if col < 8 {
+            color.red = if col & 1 != 0 { 0xaa } else { 0x00 };
+            color.green = if col & 2 != 0 { 0xaa } else { 0x00 };
+            color.blue = if col & 4 != 0 { 0xaa } else { 0x00 };
+        } else if col < 16 {
+            color.red = if col & 1 != 0 { 0xff } else { 0x55 };
+            color.green = if col & 2 != 0 { 0xff } else { 0x55 };
+            color.blue = if col & 4 != 0 { 0xff } else { 0x55 };
+        } else if col < 232 {
+            color.red = ((col - 16) / 36 * 85 / 2) as u16;
+            color.green = ((col - 16) / 6 % 6 * 85 / 2) as u16;
+            color.blue = ((col - 16) % 6 * 85 / 2) as u16;
+        } else {
+            let col = (col * 10 - 2312) as u16;
+            color.red = col;
+            color.green = col;
+            color.blue = col;
+        }
+
+        color
+    }
+}
+
+#[derive(Debug)]
+pub struct TtyConsoleDriverInner {
+    console: Arc<BlittingFbConsole>,
+}
+
+unsafe impl Sync for TtyConsoleDriverInner {}
+
+impl TtyConsoleDriverInner {
+    pub fn new() -> Result<Self, SystemError> {
+        Ok(Self {
+            console: Arc::new(BlittingFbConsole::new()?),
+        })
+    }
+}
+
+impl TtyOperation for TtyConsoleDriverInner {
+    fn install(&self, _driver: Arc<TtyDriver>, tty: Arc<TtyCore>) -> Result<(), SystemError> {
+        let tty_core = tty.core();
+        let mut vc_data = VIRT_CONSOLES[tty_core.index()].lock();
+
+        self.console.con_init(&mut vc_data, true)?;
+        if vc_data.complement_mask == 0 {
+            vc_data.complement_mask = if vc_data.color_mode { 0x7700 } else { 0x0800 };
+        }
+        vc_data.s_complement_mask = vc_data.complement_mask;
+        // vc_data.bytes_per_row = vc_data.cols << 1;
+        vc_data.index = tty_core.index();
+        vc_data.bottom = vc_data.rows;
+        vc_data.set_driver_funcs(Arc::downgrade(
+            &(self.console.clone() as Arc<dyn ConsoleSwitch>),
+        ));
+
+        // todo: unicode字符集处理?
+
+        if vc_data.cols > VC_MAXCOL || vc_data.rows > VC_MAXROW {
+            return Err(SystemError::EINVAL);
+        }
+
+        vc_data.init(None, None, true);
+        vc_data.update_attr();
+
+        let window_size = tty_core.window_size_upgradeable();
+        if window_size.col == 0 && window_size.row == 0 {
+            let mut window_size = window_size.upgrade();
+            window_size.col = vc_data.cols as u16;
+            window_size.row = vc_data.rows as u16;
+        }
+
+        if vc_data.utf {
+            tty_core.termios_write().input_mode.insert(InputMode::IUTF8);
+        } else {
+            tty_core.termios_write().input_mode.remove(InputMode::IUTF8);
+        }
+
+        // 加入sysfs?
+
+        Ok(())
+    }
+
+    fn open(&self, _tty: &TtyCoreData) -> Result<(), SystemError> {
+        Ok(())
+    }
+
+    fn write_room(&self, _tty: &TtyCoreData) -> usize {
+        32768
+    }
+
+    /// 参考: https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/tty/vt/vt.c#2894
+    fn write(&self, tty: &TtyCoreData, buf: &[u8], mut nr: usize) -> Result<usize, SystemError> {
+        // 关闭中断
+        let mut vc_data = tty.vc_data_irqsave();
+
+        let mut offset = 0;
+
+        // 这个参数是用来扫描unicode字符的,但是这部分目前未完成,先写着
+        let mut rescan = false;
+        let mut ch: u32 = 0;
+
+        let mut draw = DrawRegion::default();
+
+        // 首先隐藏光标再写
+        vc_data.hide_cursor();
+
+        while nr != 0 {
+            if !rescan {
+                ch = buf[offset] as u32;
+                offset += 1;
+                nr -= 1;
+            }
+
+            let (tc, rescan_last) = vc_data.translate(&mut ch);
+            if tc.is_none() {
+                // 表示未转换完成
+                continue;
+            }
+
+            let tc = tc.unwrap();
+            rescan = rescan_last;
+
+            if vc_data.is_control(tc, ch) {
+                vc_data.flush(&mut draw);
+                vc_data.do_control(ch);
+                continue;
+            }
+
+            if !vc_data.console_write_normal(tc, ch, &mut draw) {
+                continue;
+            }
+        }
+
+        vc_data.flush(&mut draw);
+
+        // TODO: notify update
+        return Ok(offset);
+    }
+
+    fn flush_chars(&self, tty: &TtyCoreData) {
+        let mut vc_data = tty.vc_data_irqsave();
+        vc_data.set_cursor();
+    }
+
+    fn put_char(&self, tty: &TtyCoreData, ch: u8) -> Result<(), SystemError> {
+        self.write(tty, &[ch], 1)?;
+        Ok(())
+    }
+
+    fn ioctl(&self, _tty: Arc<TtyCore>, _cmd: u32, _arg: usize) -> Result<(), SystemError> {
+        // TODO
+        Err(SystemError::ENOIOCTLCMD)
+    }
+}
+
+#[derive(Debug, Clone)]
+pub struct VtModeData {
+    mode: VtMode,
+    /// 释放请求时触发的信号
+    relsig: u16,
+    /// 获取请求时触发的信号
+    acqsig: u16,
+}
+
+#[allow(dead_code)]
+#[derive(Debug, Clone)]
+pub enum VtMode {
+    /// 自动切换模式,即在请求输入时自动切换到终端
+    Auto,
+    /// 手动切换模式,需要通过 ioctl 请求切换到终端
+    Process,
+    /// 等待终端确认,即在切换到终端时等待终端的确认信号
+    Ackacq,
+}
+
+/// 用于给vc确定要写入的buf位置
+#[derive(Debug, Default)]
+pub struct DrawRegion {
+    /// 偏移量
+    pub offset: usize,
+    /// 写入数量
+    pub size: usize,
+    pub x: Option<u32>,
+}
+
+// 初始化虚拟终端
+#[inline(never)]
+pub fn vty_init() -> Result<(), SystemError> {
+    // 注册虚拟终端设备并将虚拟终端设备加入到文件系统
+    let vc0 = TtyDevice::new(
+        "vc0",
+        IdTable::new(
+            String::from("vc0"),
+            Some(DeviceNumber::new(Major::TTY_MAJOR, 0)),
+        ),
+    );
+    // 注册tty设备
+    // CharDevOps::cdev_add(
+    //     vc0.clone() as Arc<dyn CharDevice>,
+    //     IdTable::new(
+    //         String::from("vc0"),
+    //         Some(DeviceNumber::new(Major::TTY_MAJOR, 0)),
+    //     ),
+    //     1,
+    // )?;
+
+    // CharDevOps::register_chardev_region(DeviceNumber::new(Major::TTY_MAJOR, 0), 1, "/dev/vc/0")?;
+    device_register(vc0.clone())?;
+    devfs_register("vc0", vc0)?;
+
+    // vcs_init?
+
+    let console_driver = TtyDriver::new(
+        MAX_NR_CONSOLES,
+        "tty",
+        1,
+        Major::TTY_MAJOR,
+        0,
+        TtyDriverType::Console,
+        TTY_STD_TERMIOS.clone(),
+        Arc::new(TtyConsoleDriverInner::new()?),
+    );
+
+    TtyDriverManager::tty_register_driver(console_driver)?;
+
+    CURRENT_VCNUM.store(0, Ordering::SeqCst);
+
+    // 初始化键盘?
+
+    // TODO: 为vc
+
+    Ok(())
+}

+ 2015 - 0
kernel/src/driver/tty/virtual_terminal/virtual_console.rs

@@ -0,0 +1,2015 @@
+use core::sync::atomic::{AtomicBool, AtomicIsize, Ordering};
+
+use alloc::{
+    sync::{Arc, Weak},
+    vec::Vec,
+};
+use bitmap::{traits::BitMapOps, StaticBitmap};
+
+use crate::{
+    driver::tty::{console::ConsoleSwitch, ConsoleFont, KDMode},
+    libs::{font::FontDesc, rwlock::RwLock},
+    process::Pid,
+};
+
+use super::{
+    console_map::{TranslationMap, TranslationMapType},
+    Color, DrawRegion, VtMode, VtModeData, COLOR_TABLE, DEFAULT_BLUE, DEFAULT_GREEN, DEFAULT_RED,
+};
+
+pub(super) const NPAR: usize = 16;
+
+lazy_static! {
+    /// 是否已经添加了软光标
+    pub(super) static ref SOFTCURSOR_ORIGINAL: RwLock<Option<VcCursor>> = RwLock::new(None);
+
+    pub static ref CURRENT_VCNUM: AtomicIsize = AtomicIsize::new(-1);
+
+    pub static ref CONSOLE_BLANKED: AtomicBool = AtomicBool::new(false);
+}
+
+/// ## 虚拟控制台的信息
+#[derive(Debug, Clone)]
+pub struct VirtualConsoleData {
+    pub num: usize,
+    pub state: VirtualConsoleInfo,
+    pub saved_state: VirtualConsoleInfo,
+    /// 最大列数
+    pub cols: usize,
+    /// 最大行数
+    pub rows: usize,
+    // ///  每行的字节数
+    // pub bytes_per_row: usize,
+    /// 扫描行数
+    pub scan_lines: usize,
+    /// 字符单元高度
+    pub cell_height: u32,
+
+    // /// 实际屏幕地址的开始
+    // pub screen_base: VirtAddr,
+    // /// 实际屏幕的结束
+    // pub scr_end: u64,
+    /// 可见窗口的开始
+    pub visible_origin: usize,
+    /// 滚动窗口的顶部
+    pub top: usize,
+    /// 滚动窗口的底部
+    pub bottom: usize,
+    /// 当前读取位置
+    pub pos: usize,
+
+    /// 颜色集合
+    pub palette: [Color; 16],
+    /// 默认颜色
+    pub def_color: u8,
+    /// 下划线颜色
+    pub underline_color: u32,
+    /// 斜体颜色
+    pub italic_color: u32,
+    /// 半强度颜色
+    pub half_color: u32,
+
+    pub mode: KDMode,
+    pub vt_mode: VtModeData,
+
+    /// 是否启用颜色
+    pub color_mode: bool,
+
+    // 字符
+    pub hi_font_mask: u16,
+    pub font: ConsoleFont,
+
+    pub erase_char: u16,
+
+    pub complement_mask: u16,
+    pub s_complement_mask: u16,
+
+    pub cursor_blink_ms: u16,
+
+    pub pid: Option<Pid>,
+    pub index: usize,
+
+    pub vc_state: VirtualConsoleState,
+
+    // 一些标志
+    /// 指示是否显示 ASCII 字符小于 32 的控制字符(vc_disp_ctrl)
+    pub display_ctrl: bool,
+    /// 指示是否切换高位(meta)位。Meta 键是一个特殊的按键,用于扩展字符集。
+    pub toggle_meta: bool,
+    /// 表示屏幕模式(vc_decscnm)
+    pub screen_mode: bool,
+    /// 指定光标移动的起始位置,是相对于屏幕的左上角还是相对于当前页的左上角(vc_decom)
+    pub origin_mode: bool,
+    /// 控制光标到达行末时是否自动换行(vc_decawm)
+    pub autowrap: bool,
+    /// 控制光标的可见性(vc_deccm)
+    pub cursor_visible: bool,
+    /// 光标相关
+    pub cursor_type: VcCursor,
+    /// 控制插入或替换模式(vc_decim)
+    pub insert_mode: bool,
+    /// 表示一些私有模式或状态,通常由特定终端实现定义(vc_priv)
+    pub private: Vt102_OP,
+    /// 是否需要进行自动换行
+    pub need_wrap: bool,
+    /// 控制鼠标事件的报告方式
+    pub report_mouse: u8,
+    /// 指示终端是否使用 UTF-8 编码
+    pub utf: bool,
+    /// UTF-8 编码的字符计数,表示还需要多少个字节才能够构建完成
+    pub utf_count: u8,
+    /// UTF-8 编码的字符,表示正在构建的utf字符
+    pub utf_char: u32,
+    /// 构建utf时需要的参数,表示目前接收了多少个字节的数据来构建utf字符
+    pub npar: u32,
+    ///
+    pub par: [u32; NPAR],
+
+    /// 字符转换表 用于将输入字符映射到特定的字符
+    pub translate: TranslationMap,
+
+    pub tab_stop: StaticBitmap<256>,
+
+    pub attr: u8,
+
+    /// vc缓冲区
+    pub screen_buf: Vec<u16>,
+
+    /// 对应的Console Driver funcs
+    driver_funcs: Option<Weak<dyn ConsoleSwitch>>,
+}
+
+impl VirtualConsoleData {
+    pub fn new(num: usize) -> Self {
+        Self {
+            state: VirtualConsoleInfo::new(0, 0),
+            saved_state: Default::default(),
+            cols: Default::default(),
+            rows: Default::default(),
+            // bytes_per_row: Default::default(),
+            scan_lines: Default::default(),
+            cell_height: Default::default(),
+            // origin: Default::default(),
+            // scr_end: Default::default(),
+            visible_origin: Default::default(),
+            top: Default::default(),
+            bottom: Default::default(),
+            palette: [Default::default(); 16],
+            def_color: Default::default(),
+            underline_color: Default::default(),
+            italic_color: Default::default(),
+            half_color: Default::default(),
+            mode: Default::default(),
+            color_mode: Default::default(),
+            hi_font_mask: Default::default(),
+            erase_char: Default::default(),
+            complement_mask: Default::default(),
+            s_complement_mask: Default::default(),
+            cursor_blink_ms: 200,
+            pos: Default::default(),
+            vt_mode: VtModeData {
+                mode: VtMode::Auto,
+                relsig: 0,
+                acqsig: 0,
+            },
+            pid: None,
+            index: 0,
+            font: Default::default(),
+            vc_state: VirtualConsoleState::ESnormal,
+            display_ctrl: Default::default(),
+            toggle_meta: Default::default(),
+            screen_mode: Default::default(),
+            origin_mode: Default::default(),
+            autowrap: Default::default(),
+            cursor_visible: Default::default(),
+            insert_mode: Default::default(),
+            private: Vt102_OP::EPecma,
+            need_wrap: Default::default(),
+            report_mouse: Default::default(),
+            utf: Default::default(),
+            utf_count: Default::default(),
+            utf_char: Default::default(),
+            translate: TranslationMap::new(TranslationMapType::Lat1Map),
+            npar: Default::default(),
+            tab_stop: StaticBitmap::new(),
+            par: [0; 16],
+            attr: Default::default(),
+            screen_buf: Default::default(),
+            driver_funcs: None,
+            cursor_type: VcCursor::empty(),
+            num,
+        }
+    }
+
+    pub(super) fn init(&mut self, rows: Option<usize>, cols: Option<usize>, clear: bool) {
+        if rows.is_some() {
+            self.rows = rows.unwrap();
+        }
+        if cols.is_some() {
+            self.cols = cols.unwrap();
+        }
+
+        self.pos = self.cols * self.state.y + self.state.x;
+        // self.bytes_per_row = self.cols << 1;
+
+        self.def_color = 15; // white
+        self.italic_color = 2; // green
+        self.underline_color = 3; // cyan
+        self.half_color = 0x08; // grey
+
+        self.reset(clear);
+
+        self.screen_buf.resize(self.cols * self.rows, 0);
+    }
+
+    pub fn should_update(&self) -> bool {
+        self.is_visible() && !CONSOLE_BLANKED.load(Ordering::SeqCst)
+    }
+
+    pub fn is_visible(&self) -> bool {
+        let cur_vc = CURRENT_VCNUM.load(Ordering::SeqCst);
+        if cur_vc == -1 {
+            return false;
+        }
+
+        cur_vc as usize == self.num
+    }
+
+    fn driver_funcs(&self) -> Arc<dyn ConsoleSwitch> {
+        self.driver_funcs.as_ref().unwrap().upgrade().unwrap()
+    }
+
+    pub(super) fn set_driver_funcs(&mut self, func: Weak<dyn ConsoleSwitch>) {
+        self.driver_funcs = Some(func);
+    }
+
+    pub(super) fn reset(&mut self, do_clear: bool) {
+        self.mode = KDMode::KdText;
+        // unicode?
+        self.vt_mode.mode = VtMode::Auto;
+        self.vt_mode.acqsig = 0;
+        self.vt_mode.relsig = 0;
+        self.display_ctrl = false;
+        self.toggle_meta = false;
+        self.screen_mode = false;
+        self.origin_mode = false;
+        self.autowrap = true;
+        self.cursor_visible = true;
+        self.insert_mode = false;
+        self.need_wrap = false;
+        self.report_mouse = 0;
+        self.utf_count = 0;
+        self.translate = TranslationMap::new(TranslationMapType::Lat1Map);
+        self.utf = true;
+        self.pid = None;
+        self.vc_state = VirtualConsoleState::ESnormal;
+        self.reset_palette();
+        self.cursor_type = VcCursor::CUR_UNDERLINE;
+
+        self.default_attr();
+        self.update_attr();
+
+        self.tab_stop.set_all(false);
+
+        for i in (0..256).step_by(8) {
+            self.tab_stop.set(i, true);
+        }
+
+        self.state.x = 0;
+        self.state.y = 0;
+        self.pos = 0;
+
+        if do_clear {
+            self.csi_J(2);
+        }
+    }
+
+    fn reset_palette(&mut self) {
+        for (idx, color) in self.palette.iter_mut().enumerate() {
+            color.red = DEFAULT_RED[idx];
+            color.green = DEFAULT_GREEN[idx];
+            color.blue = DEFAULT_BLUE[idx];
+        }
+
+        self.set_palette();
+    }
+
+    fn set_palette(&self) {
+        if self.mode != KDMode::KdGraphics {
+            // todo: 通知driver层的Console
+            let _ = self.driver_funcs().con_set_palette(self, COLOR_TABLE);
+        }
+    }
+
+    /// ## 翻译字符,将字符转换为终端控制符
+    /// ### 参数
+    ///
+    /// ### c: 需要转换的字符
+    ///
+    /// ### 返回值
+    /// ### (转换后的字符:i32,是否需要更多的数据才能进行转换:bool)
+    pub(super) fn translate(&mut self, c: &mut u32) -> (Option<u32>, bool) {
+        if self.vc_state != VirtualConsoleState::ESnormal {
+            // 在控制字符状态下不需要翻译
+            return (Some(*c), false);
+        }
+        if self.utf && !self.display_ctrl {
+            // utf模式并且不显示控制字符
+            let (ret, rescan) = self.translate_unicode(*c);
+            if ret.is_some() {
+                *c = ret.unwrap();
+            }
+            return (ret, rescan);
+        }
+
+        return (Some(self.translate_ascii(*c)), false);
+    }
+
+    /// 该数组包含每个字节序列长度变化的阈值
+    /// 即如果由两个字节组成的unicode字符,则长度应该在UTF8_LENGTH_CHANGES[0] ~ UTF8_LENGTH_CHANGES[1]之间
+    const UTF8_LENGTH_CHANGES: &'static [u32] = &[
+        0x0000007f, 0x000007ff, 0x0000ffff, 0x001fffff, 0x03ffffff, 0x7fffffff,
+    ];
+
+    /// ## 翻译字符,将UTF-8 编码的字符转换为 Unicode 编码
+    /// ### 参数
+    ///
+    /// ### c: 需要转换的字符
+    ///
+    /// ### 返回值
+    /// ### (转换后的字符:i32,是否需要重新传入该字符:bool)
+    ///
+    /// !!! 注意,该函数返回true时,元组的第一个数据是无效数据(未转换完成)
+    fn translate_unicode(&mut self, c: u32) -> (Option<u32>, bool) {
+        // 收到的字符不是首个
+        if (c & 0xc8) == 0x80 {
+            // 已经不需要继续的字符了,说明这个字符是非法的
+            if self.utf_count == 0 {
+                return (Some(0xfffd), false);
+            }
+
+            self.utf_char = (self.utf_char << 6) | (c & 0x3f);
+            self.npar += 1;
+
+            self.utf_count -= 1;
+            if self.utf_count > 0 {
+                // 表示需要更多字节
+                return (None, false);
+            }
+
+            let c = self.utf_char;
+
+            // 先检查一遍是否合格
+            if c <= Self::UTF8_LENGTH_CHANGES[self.npar as usize - 1]
+                || c > Self::UTF8_LENGTH_CHANGES[self.npar as usize]
+            {
+                return (Some(0xfffd), false);
+            }
+
+            return (Some(Self::sanitize_unicode(c)), false);
+        }
+
+        // 接收到单个ASCII字符或者一个序列的首字符,且上次的未处理完,则上一个字符视为无效,则需要重新传入该字符处理
+        if self.utf_count > 0 {
+            self.utf_count = 0;
+            return (Some(0xfffd), true);
+        }
+
+        // ascii
+        if c <= 0x7f {
+            return (Some(c), false);
+        }
+
+        // 第一个字节
+        self.npar = 0;
+        if (c & 0xe0) == 0xc0 {
+            self.utf_count = 1;
+            self.utf_char = c & 0x1f;
+        } else if (c & 0xf0) == 0xe0 {
+            self.utf_count = 2;
+            self.utf_char = c & 0x0f;
+        } else if (c & 0xf8) == 0xf0 {
+            self.utf_count = 3;
+            self.utf_char = c & 0x07;
+        } else if (c & 0xfc) == 0xf8 {
+            self.utf_count = 4;
+            self.utf_char = c & 0x03;
+        } else if (c & 0xfe) == 0xfc {
+            self.utf_count = 5;
+            self.utf_char = c & 0x01;
+        } else {
+            /* 254 and 255 are invalid */
+            return (Some(0xfffd), false);
+        }
+
+        (None, false)
+    }
+
+    /// ## 翻译字符,将字符转换为Ascii
+    fn translate_ascii(&self, c: u32) -> u32 {
+        let mut c = c;
+        if self.toggle_meta {
+            c |= 0x80;
+        }
+
+        return self.translate.translate(c) as u32;
+    }
+
+    /// ## 用于替换无效的 Unicode 代码点(code points)。
+    /// Unicode 代码点的范围是从 U+0000 到 U+10FFFF,
+    /// 但是有一些特殊的代码点是无效的或者保留给特定用途的。
+    /// 这个函数的主要目的是将无效的 Unicode 代码点替换为 U+FFFD,即 Unicode 替代字符。
+    fn sanitize_unicode(c: u32) -> u32 {
+        if (c >= 0xd800 && c <= 0xdfff) || c == 0xfffe || c == 0xffff {
+            return 0xfffd;
+        }
+        return c;
+    }
+
+    /// 用于表示小于 32 的字符中,哪些字符对应的位被设置为 1,
+    /// 表示这些字符会触发一些特殊的动作,比如光标移动等。
+    /// 这些字符在 disp_ctrl 模式未开启时不应该被显示为图形符号
+    const CTRL_ACTION: u32 = 0x0d00ff81;
+    /// 用于表示哪些控制字符是始终显示的,即便 disp_ctrl 模式未开启。
+    /// 这些字符对于终端来说是必要的,显示它们是为了保证终端正常工作。
+    /// 这些字符在 disp_ctrl 模式开启或关闭时都应该显示为控制字符。
+    const CTRL_ALWAYS: u32 = 0x0800f501;
+
+    /// ## 用于判断tc(终端字符)在当前VC下是不是需要显示的控制字符
+    pub(super) fn is_control(&self, tc: u32, c: u32) -> bool {
+        // 当前vc状态机不在正常状态,即在接收特殊字符的状态,则是控制字符
+        if self.vc_state != VirtualConsoleState::ESnormal {
+            return true;
+        }
+
+        if tc == 0 {
+            return true;
+        }
+
+        if c < 32 {
+            if self.display_ctrl {
+                // 查看在位图中是否有该字符
+                return Self::CTRL_ALWAYS & (1 << c) != 0;
+            } else {
+                return self.utf || (Self::CTRL_ACTION & (1 << c) != 0);
+            }
+        }
+
+        if c == 127 && !self.display_ctrl {
+            return true;
+        }
+
+        if c == 128 + 27 {
+            return true;
+        }
+
+        false
+    }
+
+    pub(super) fn set_cursor(&mut self) {
+        if self.mode == KDMode::KdGraphics {
+            return;
+        }
+
+        if self.cursor_visible {
+            // TODO: 处理选择
+            self.add_softcursor();
+            if self.cursor_type.cursor_size() != VcCursor::CUR_NONE {
+                self.driver_funcs().con_cursor(self, CursorOperation::Draw);
+            }
+        } else {
+            self.hide_cursor();
+        }
+    }
+
+    /// ## 添加软光标
+    fn add_softcursor(&mut self) {
+        let mut i = self.screen_buf[self.pos] as u32;
+        let cursor_type = self.cursor_type;
+
+        if !cursor_type.contains(VcCursor::CUR_SW) {
+            return;
+        }
+
+        if SOFTCURSOR_ORIGINAL.read_irqsave().is_some() {
+            // 已经设置了软光标
+            return;
+        }
+
+        let mut soft_cursor_guard = SOFTCURSOR_ORIGINAL.write_irqsave();
+        *soft_cursor_guard = Some(unsafe { VcCursor::from_bits_unchecked(i as u32) });
+
+        let soft_cursor = soft_cursor_guard.unwrap();
+
+        i |= cursor_type.cursor_set();
+        i ^= cursor_type.cursor_change();
+        if cursor_type.contains(VcCursor::CUR_ALWAYS_BG)
+            && ((soft_cursor.bits & VcCursor::CUR_BG.bits) == (i & VcCursor::CUR_BG.bits))
+        {
+            i ^= VcCursor::CUR_BG.bits;
+        }
+        if cursor_type.contains(VcCursor::CUR_INVERT_FG_BG)
+            && ((i & VcCursor::CUR_FG.bits) == ((i & VcCursor::CUR_BG.bits) >> 4))
+        {
+            i ^= VcCursor::CUR_FG.bits;
+        }
+
+        self.screen_buf[self.pos] = i as u16;
+
+        let _ =
+            self.driver_funcs()
+                .con_putc(&self, i as u16, self.state.y as u32, self.state.x as u32);
+    }
+
+    pub fn hide_cursor(&mut self) {
+        // TODO: 处理选择
+
+        self.driver_funcs().con_cursor(self, CursorOperation::Erase);
+        self.hide_softcursor();
+    }
+
+    fn hide_softcursor(&mut self) {
+        let softcursor = SOFTCURSOR_ORIGINAL.upgradeable_read_irqsave();
+        if softcursor.is_some() {
+            self.screen_buf[self.pos] = softcursor.unwrap().bits as u16;
+            let _ = self.driver_funcs().con_putc(
+                &self,
+                softcursor.unwrap().bits as u16,
+                self.state.y as u32,
+                self.state.x as u32,
+            );
+
+            *softcursor.upgrade() = None;
+        }
+    }
+
+    fn gotoxay(&mut self, x: i32, y: i32) {
+        if self.origin_mode {
+            self.gotoxy(x, self.top as i32 + y);
+        } else {
+            self.gotoxy(x, y)
+        }
+    }
+
+    // ## 将当前vc的光标移动到目标位置
+    fn gotoxy(&mut self, x: i32, y: i32) {
+        if x < 0 {
+            self.state.x = 0;
+        } else {
+            if x as usize >= self.cols {
+                self.state.x = self.cols - 1;
+            } else {
+                self.state.x = x as usize;
+            }
+        }
+
+        let max_y;
+        let min_y;
+        if self.origin_mode {
+            min_y = self.top;
+            max_y = self.bottom;
+        } else {
+            min_y = 0;
+            max_y = self.rows;
+        }
+
+        if y < min_y as i32 {
+            self.state.y = min_y as usize;
+        } else if y >= max_y as i32 {
+            self.state.y = max_y as usize;
+        } else {
+            self.state.y = y as usize;
+        }
+
+        self.pos = self.state.y * self.cols + (self.state.x << 1);
+        self.need_wrap = false;
+    }
+
+    fn scroll(&mut self, dir: ScrollDir, mut nr: usize) {
+        // todo: uniscr_srceen
+        if self.top + nr >= self.bottom {
+            // 滚动超过一页,则按一页计算
+            nr = self.bottom - self.top - 1;
+        }
+
+        if nr < 1 {
+            return;
+        }
+
+        if self
+            .driver_funcs()
+            .con_scroll(self, self.top, self.bottom, dir, nr)
+        {
+            // 如果成功
+            return;
+        }
+
+        // 调整screen_buf
+        let count = nr * self.cols;
+        if dir == ScrollDir::Up {
+            for i in self.screen_buf[0..count].iter_mut() {
+                *i = self.erase_char;
+            }
+            self.screen_buf.rotate_left(count);
+        } else if dir == ScrollDir::Down {
+            todo!();
+        }
+    }
+
+    /// ## 退格
+    fn backspace(&mut self) {
+        if self.state.x > 0 {
+            self.pos -= 1;
+            self.state.x -= 1;
+            self.need_wrap = false;
+
+            // TODO: notify
+        }
+    }
+
+    /// ## 换行
+    fn line_feed(&mut self) {
+        if self.state.y + 1 == self.bottom as usize {
+            self.scroll(ScrollDir::Up, 1);
+        } else if self.state.y < self.rows - 1 {
+            self.state.y += 1;
+            self.pos += self.cols;
+        }
+
+        self.need_wrap = false;
+        // TODO: Notify write
+    }
+
+    /// ## 回车
+    fn carriage_return(&mut self) {
+        // 写入位置回退到该行最前
+        self.pos -= self.state.x;
+        self.need_wrap = false;
+        self.state.x = 0;
+    }
+
+    /// ## Del
+    fn delete(&mut self) {
+        // ignore
+    }
+
+    /// ## 向上滚动虚拟终端的内容,或者将光标上移一行
+    fn reverse_index(&mut self) {
+        if self.state.y == self.top as usize {
+            self.scroll(ScrollDir::Down, 1);
+        } else if self.state.y > 0 {
+            self.state.y -= 1;
+            self.pos -= self.cols;
+        }
+        self.need_wrap = false;
+    }
+
+    /// https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/tty/vt/vt.c#restore_cur
+    fn restore_cursor(&mut self) {
+        self.saved_state = self.state.clone();
+
+        self.gotoxy(self.state.x as i32, self.state.y as i32);
+
+        // TODO Gx_charset
+
+        self.update_attr();
+        self.need_wrap = false;
+        todo!()
+    }
+
+    /// ## 设置当前vt的各项属性
+    fn set_mode(&mut self, on_off: bool) {
+        for i in 0..self.npar as usize {
+            if self.private == Vt102_OP::EPdec {
+                match self.par[i] {
+                    1 => {
+                        todo!("kbd todo");
+                    }
+                    3 => {
+                        todo!("reisze todo");
+                    }
+                    5 => {
+                        todo!("invert_screen todo");
+                    }
+                    6 => {
+                        self.origin_mode = on_off;
+                        if on_off {
+                            self.gotoxy(0, self.top as i32);
+                        } else {
+                            self.gotoxy(0, 0);
+                        }
+                    }
+                    7 => {
+                        self.autowrap = on_off;
+                    }
+                    8 => {
+                        todo!("kbd todo");
+                    }
+                    9 => {
+                        todo!("report mouse todo");
+                    }
+                    25 => {
+                        self.cursor_visible = on_off;
+                    }
+                    1000 => {
+                        todo!("report mouse todo");
+                    }
+                    _ => {}
+                }
+            } else {
+                match self.par[i] {
+                    3 => {
+                        self.display_ctrl = on_off;
+                    }
+                    4 => {
+                        self.insert_mode = on_off;
+                    }
+                    20 => {
+                        todo!("kbd todo");
+                    }
+                    _ => {}
+                }
+            }
+        }
+    }
+
+    fn do_getpars(&mut self, c: char) {
+        if c == ';' && self.npar < (NPAR - 1) as u32 {
+            self.npar += 1;
+            return;
+        }
+
+        if c >= '0' && c <= '9' {
+            self.par[self.npar as usize] *= 10;
+            self.par[self.npar as usize] += (c as u8 - '0' as u8) as u32;
+            return;
+        }
+
+        if c as u8 >= 0x20 && c as u8 <= 0x3f {
+            self.vc_state = VirtualConsoleState::EScsiignore;
+            return;
+        }
+
+        self.vc_state = VirtualConsoleState::ESnormal;
+
+        match c {
+            'h' => {
+                if self.private <= Vt102_OP::EPdec {
+                    self.set_mode(true);
+                }
+                return;
+            }
+            'l' => {
+                if self.private <= Vt102_OP::EPdec {
+                    self.set_mode(false);
+                }
+                return;
+            }
+            'c' => {
+                if self.private == Vt102_OP::EPdec {
+                    if self.par[0] != 0 {
+                        self.cursor_type =
+                            VcCursor::make_cursor(self.par[0], self.par[1], self.par[2])
+                    } else {
+                        self.cursor_type = VcCursor::CUR_UNDERLINE;
+                    }
+                    return;
+                }
+            }
+            'm' => {
+                if self.private == Vt102_OP::EPdec {
+                    if self.par[0] != 0 {
+                        self.complement_mask = (self.par[0] << 8 | self.par[1]) as u16;
+                    } else {
+                        self.complement_mask = self.s_complement_mask;
+                    }
+                    return;
+                }
+            }
+            'n' => {
+                if self.private == Vt102_OP::EPecma {
+                    if self.par[0] == 5 {
+                        kwarn!("tty status report todo");
+                    } else if self.par[0] == 6 {
+                        kwarn!("tty cursor report todo");
+                    }
+                }
+                return;
+            }
+            _ => {}
+        }
+
+        if self.private != Vt102_OP::EPecma {
+            self.private = Vt102_OP::EPecma;
+            return;
+        }
+
+        match c {
+            'G' | '`' => {
+                if self.par[0] != 0 {
+                    self.par[0] -= 1;
+                }
+                self.gotoxy(self.par[0] as i32, self.state.y as i32);
+                return;
+            }
+            'A' => {
+                if self.par[0] == 0 {
+                    self.par[0] += 1;
+                }
+                self.gotoxy(
+                    self.state.x as i32,
+                    (self.state.y - self.par[0] as usize) as i32,
+                );
+                return;
+            }
+            'B' | 'e' => {
+                if self.par[0] == 0 {
+                    self.par[0] += 1;
+                }
+                self.gotoxy(
+                    self.state.x as i32,
+                    (self.state.y + self.par[0] as usize) as i32,
+                );
+                return;
+            }
+            'C' | 'a' => {
+                if self.par[0] == 0 {
+                    self.par[0] += 1;
+                }
+                self.gotoxy(
+                    (self.state.x + self.par[0] as usize) as i32,
+                    self.state.y as i32,
+                );
+                return;
+            }
+            'D' => {
+                if self.par[0] == 0 {
+                    self.par[0] += 1;
+                }
+                self.gotoxy(
+                    (self.state.x - self.par[0] as usize) as i32,
+                    self.state.y as i32,
+                );
+                return;
+            }
+            'E' => {
+                if self.par[0] == 0 {
+                    self.par[0] += 1;
+                }
+                self.gotoxy(0, (self.state.y + self.par[0] as usize) as i32);
+                return;
+            }
+            'F' => {
+                if self.par[0] == 0 {
+                    self.par[0] += 1;
+                }
+                self.gotoxy(0, (self.state.y - self.par[0] as usize) as i32);
+                return;
+            }
+            'd' => {
+                if self.par[0] != 0 {
+                    self.par[0] -= 1;
+                }
+                self.gotoxay(self.state.x as i32, self.par[0] as i32);
+                return;
+            }
+            'H' | 'f' => {
+                if self.par[0] != 0 {
+                    self.par[0] -= 1;
+                }
+                if self.par[1] != 0 {
+                    self.par[1] -= 1;
+                }
+                self.gotoxay(self.par[1] as i32, self.par[0] as i32);
+                return;
+            }
+            'J' => {
+                self.csi_J(self.par[0]);
+                return;
+            }
+            'K' => {
+                self.csi_K(self.par[0]);
+                return;
+            }
+            'L' => {
+                todo!("csi_L todo");
+            }
+            'M' => {
+                todo!("csi_M todo");
+            }
+            'P' => {
+                todo!("csi_P todo");
+            }
+            'c' => {
+                if self.par[0] == 0 {
+                    kwarn!("respone ID todo");
+                }
+                return;
+            }
+            'g' => {
+                if self.par[0] == 0 && self.state.x < 256 {
+                    self.tab_stop.set(self.state.x as usize, true);
+                } else if self.par[0] == 3 {
+                    self.tab_stop.set_all(false);
+                }
+                return;
+            }
+            'm' => {
+                self.csi_m();
+                return;
+            }
+            'q' => {
+                if self.par[0] < 4 {
+                    todo!("vt set led state todo");
+                }
+                return;
+            }
+            'r' => {
+                if self.par[0] == 0 {
+                    self.par[0] += 1;
+                }
+                if self.par[1] == 0 {
+                    self.par[1] = self.rows as u32;
+                }
+                if self.par[0] < self.par[1] && self.par[1] <= self.rows as u32 {
+                    self.top = self.par[0] as usize - 1;
+                    self.bottom = self.par[1] as usize;
+                    self.gotoxay(0, 0);
+                }
+                return;
+            }
+            's' => {
+                self.saved_state = self.state.clone();
+                return;
+            }
+            'u' => {
+                self.restore_cursor();
+                return;
+            }
+            '@' => {
+                todo!("csi_at todo");
+            }
+            ']' => {
+                todo!("set termial command todo");
+            }
+            _ => {}
+        }
+    }
+
+    /// ##  处理Control Sequence Introducer(控制序列引导符) m字符
+    fn csi_m(&mut self) {
+        let mut i = 0;
+        loop {
+            if i > self.npar as usize {
+                break;
+            }
+            match self.par[i] {
+                0 => {
+                    // 关闭所有属性
+                    self.default_attr();
+                }
+
+                1 => {
+                    // 设置粗体
+                    self.state.intensity = VirtualConsoleIntensity::VciBold;
+                }
+
+                2 => {
+                    // 设置半亮度(半明显
+                    self.state.intensity = VirtualConsoleIntensity::VciHalfBright;
+                }
+
+                3 => {
+                    // 斜体
+                    self.state.italic = true;
+                }
+
+                4 | 21 => {
+                    // 下划线
+
+                    // 21是设置双下划线,但是不支持,就单下划线
+                    self.state.underline = true;
+                }
+
+                5 => {
+                    // 设置闪烁
+                    self.state.blink = true;
+                }
+
+                7 => {
+                    // 设置反显(前景色与背景色对调)
+                    self.state.reverse = true;
+                }
+
+                10 => {
+                    // 选择主要字体
+                    todo!()
+                }
+
+                11 => {
+                    // 选择第一个替代字体
+                    todo!()
+                }
+
+                12 => {
+                    // 选择第二个替代字体
+                    todo!()
+                }
+
+                22 => {
+                    //  关闭粗体和半亮度,恢复正常亮度
+                    self.state.intensity = VirtualConsoleIntensity::VciNormal;
+                }
+
+                23 => {
+                    // 关闭斜体
+                    self.state.italic = false;
+                }
+
+                24 => {
+                    // 关闭下划线
+                    self.state.underline = false;
+                }
+
+                25 => {
+                    // 关闭字符闪烁
+                    self.state.blink = false;
+                }
+
+                27 => {
+                    // 关闭反显
+                    self.state.reverse = false;
+                }
+
+                38 => {
+                    // 设置前景色
+                    let (idx, color) = self.t416_color(i);
+                    i = idx;
+                    if color.is_some() {
+                        let color = color.unwrap();
+                        let mut max = color.red.max(color.green);
+                        max = max.max(color.blue);
+
+                        let mut hue = 0;
+                        if color.red > max / 2 {
+                            hue |= 4;
+                        }
+                        if color.green > max / 2 {
+                            hue |= 2;
+                        }
+                        if color.blue > max / 2 {
+                            hue |= 1;
+                        }
+
+                        if hue == 7 && max <= 0x55 {
+                            hue = 0;
+                            self.state.intensity = VirtualConsoleIntensity::VciBold;
+                        } else if max > 0xaa {
+                            self.state.intensity = VirtualConsoleIntensity::VciBold;
+                        } else {
+                            self.state.intensity = VirtualConsoleIntensity::VciNormal;
+                        }
+
+                        self.state.color = (self.state.color & 0xf0) | hue;
+                    }
+                }
+
+                48 => {
+                    // 设置背景色
+                    let (idx, color) = self.t416_color(i);
+                    i = idx;
+                    if color.is_some() {
+                        let color = color.unwrap();
+                        self.state.color = (self.state.color & 0x0f)
+                            | ((color.red as u8 & 0x80) >> 1)
+                            | ((color.green as u8 & 0x80) >> 2)
+                            | ((color.blue as u8 & 0x80) >> 3);
+                    }
+                }
+
+                39 => {
+                    // 恢复默认前景色
+                    self.state.color = (self.def_color & 0x0f) | (self.state.color & 0xf0);
+                }
+
+                49 => {
+                    // 恢复默认背景色
+                    self.state.color = (self.def_color & 0xf0) | (self.state.color & 0x0f);
+                }
+
+                _ => {
+                    if self.par[i] >= 90 && self.par[i] <= 107 {
+                        if self.par[i] < 100 {
+                            self.state.intensity = VirtualConsoleIntensity::VciBold;
+                        }
+                        self.par[i] -= 60;
+                    }
+
+                    if self.par[i] >= 30 && self.par[i] <= 37 {
+                        self.state.color =
+                            COLOR_TABLE[self.par[i] as usize - 30] | self.state.color & 0xf0;
+                    } else if self.par[i] >= 40 && self.par[i] <= 47 {
+                        self.state.color =
+                            (COLOR_TABLE[self.par[i] as usize - 40] << 4) | self.state.color & 0xf0;
+                    }
+                }
+            }
+
+            i += 1;
+        }
+
+        self.update_attr();
+    }
+
+    /// ##  处理Control Sequence Introducer(控制序列引导符) J字符
+    /// 该命令用于擦除终端显示区域的部分或全部内容。根据参数 vpar 的不同值,执行不同的擦除操作:
+    /// - vpar 为 0 时,擦除从光标位置到显示区域末尾的内容;
+    /// - vpar 为 1 时,擦除从显示区域起始位置到光标位置的内容;
+    /// - vpar 为 2 或 3 时,分别表示擦除整个显示区域的内容,其中参数 3 还会清除回滚缓冲区的内容。
+    #[allow(non_snake_case)]
+    fn csi_J(&mut self, vpar: u32) {
+        let count;
+        let start;
+
+        match vpar {
+            0 => {
+                // 擦除从光标位置到显示区域末尾的内容
+                count = self.screen_buf.len() - self.pos;
+                start = self.pos;
+            }
+            1 => {
+                // 擦除从显示区域起始位置到光标位置的内容
+                count = self.pos;
+                start = 0;
+            }
+            2 => {
+                // 擦除整个显示区域的内容
+                count = self.screen_buf.len();
+                start = 0;
+            }
+            3 => {
+                // 表示擦除整个显示区域的内容,还会清除回滚缓冲区的内容
+                // TODO:当前未实现回滚缓冲
+                count = self.screen_buf.len();
+                start = 0;
+            }
+            _ => {
+                return;
+            }
+        }
+
+        for i in self.screen_buf[start..(start + count)].iter_mut() {
+            *i = self.erase_char;
+        }
+
+        if self.should_update() {
+            self.do_update_region(start, count)
+        }
+
+        self.need_wrap = false;
+    }
+
+    /// ##  处理Control Sequence Introducer(控制序列引导符) K字符
+    /// 该命令用于擦除终端当前行的部分或全部内容。根据参数 vpar 的不同值,执行不同的擦除操作:
+    /// - vpar 为 0 时,擦除从光标位置到该行末尾的内容
+    /// - vpar 为 1 时,擦除从该行起始位置到光标位置的内容
+    /// - vpar 为 2 时,擦除整个行。
+    #[allow(non_snake_case)]
+    fn csi_K(&mut self, vpar: u32) {
+        let count;
+        let start;
+
+        match vpar {
+            0 => {
+                // 擦除从光标位置到该行末尾的内容
+                count = self.cols - self.state.x;
+                start = self.pos;
+            }
+            1 => {
+                // 擦除从该行起始位置到光标位置的内容
+                count = self.state.x + 1;
+                start = self.pos - self.state.x;
+            }
+            2 => {
+                // 擦除整个行
+                count = self.cols;
+                start = self.pos - self.state.x;
+            }
+            _ => {
+                return;
+            }
+        }
+
+        for i in self.screen_buf[start..(start + count)].iter_mut() {
+            *i = self.erase_char;
+        }
+
+        if self.should_update() {
+            self.do_update_region(start, count)
+        }
+
+        self.need_wrap = false;
+    }
+
+    fn t416_color(&mut self, mut idx: usize) -> (usize, Option<Color>) {
+        idx += 1;
+        if idx > self.npar as usize {
+            return (idx, None);
+        }
+
+        if self.par[idx] == 5 && idx + 1 <= self.npar as usize {
+            // 256色
+            idx += 1;
+            return (idx, Some(Color::from_256(self.par[idx])));
+        } else if self.par[idx] == 2 && idx + 3 <= self.npar as usize {
+            // 24位
+            let mut color = Color::default();
+            color.red = self.par[idx + 1] as u16;
+            color.green = self.par[idx + 2] as u16;
+            color.blue = self.par[idx + 3] as u16;
+            idx += 3;
+            return (idx, Some(color));
+        } else {
+            return (idx, None);
+        }
+    }
+
+    /// ## 处理终端控制字符
+    pub(super) fn do_control(&mut self, ch: u32) {
+        // 首先检查是否处于 ANSI 控制字符串状态
+        if self.vc_state.is_ansi_control_string() && ch >= 8 && ch <= 13 {
+            return;
+        }
+
+        match ch {
+            0 => {
+                return;
+            }
+            7 => {
+                // BEL
+                if self.vc_state.is_ansi_control_string() {
+                    self.vc_state = VirtualConsoleState::ESnormal;
+                }
+                // TODO: 发出声音?
+                return;
+            }
+            8 => {
+                // BS backspace
+                self.backspace();
+                return;
+            }
+            9 => {
+                // 水平制表符(Horizontal Tab)
+                self.pos -= self.state.x;
+
+                let ret = self.tab_stop.next_index(self.state.x + 1);
+
+                if ret.is_none() {
+                    self.state.x = self.cols - 1;
+                } else {
+                    self.state.x = ret.unwrap();
+                }
+
+                self.pos += self.state.x;
+                // TODO: notify
+                return;
+            }
+            10 | 11 | 12 => {
+                // LD line feed
+                self.line_feed();
+                // TODO: 检查键盘模式
+                self.carriage_return();
+                return;
+            }
+            13 => {
+                // CR 回车符
+                self.carriage_return();
+                return;
+            }
+            14 => {
+                todo!("Gx_charset todo!");
+            }
+            15 => {
+                todo!("Gx_charset todo!");
+            }
+            24 | 26 => {
+                self.vc_state = VirtualConsoleState::ESnormal;
+                return;
+            }
+            27 => {
+                // esc
+                self.vc_state = VirtualConsoleState::ESesc;
+                return;
+            }
+            127 => {
+                // delete
+                self.delete();
+                return;
+            }
+            155 => {
+                // '['
+                self.vc_state = VirtualConsoleState::ESsquare;
+                return;
+            }
+            _ => {}
+        }
+
+        match self.vc_state {
+            VirtualConsoleState::ESesc => {
+                self.vc_state = VirtualConsoleState::ESnormal;
+                match ch as u8 as char {
+                    '[' => {
+                        self.vc_state = VirtualConsoleState::ESsquare;
+                    }
+                    ']' => {
+                        self.vc_state = VirtualConsoleState::ESnonstd;
+                    }
+                    '_' => {
+                        self.vc_state = VirtualConsoleState::ESapc;
+                    }
+                    '^' => {
+                        self.vc_state = VirtualConsoleState::ESpm;
+                    }
+                    '%' => {
+                        self.vc_state = VirtualConsoleState::ESpercent;
+                    }
+                    'E' => {
+                        self.carriage_return();
+                        self.line_feed();
+                    }
+                    'M' => {
+                        self.reverse_index();
+                    }
+                    'D' => {
+                        self.line_feed();
+                    }
+                    'H' => {
+                        if self.state.x < 256 {
+                            self.tab_stop.set(self.state.x, true);
+                        }
+                    }
+                    'P' => {
+                        self.vc_state = VirtualConsoleState::ESdcs;
+                    }
+                    'Z' => {
+                        todo!("Respond ID todo!");
+                    }
+                    '7' => self.saved_state = self.state.clone(),
+                    '8' => self.restore_cursor(),
+                    '(' => {
+                        self.vc_state = VirtualConsoleState::ESsetG0;
+                    }
+                    ')' => {
+                        self.vc_state = VirtualConsoleState::ESsetG1;
+                    }
+                    '#' => {
+                        self.vc_state = VirtualConsoleState::EShash;
+                    }
+                    'c' => {
+                        self.reset(true);
+                    }
+                    '>' => {
+                        todo!("clr_kbd todo");
+                    }
+                    '=' => {
+                        todo!("set_kbd todo");
+                    }
+                    _ => {}
+                }
+            }
+            VirtualConsoleState::ESsquare => {
+                for i in self.par.iter_mut() {
+                    *i = 0;
+                }
+                self.vc_state = VirtualConsoleState::ESgetpars;
+                self.npar = 0;
+                let c = ch as u8 as char;
+                if c == '[' {
+                    self.vc_state = VirtualConsoleState::ESfunckey;
+                    return;
+                }
+
+                match c {
+                    '?' => {
+                        self.private = Vt102_OP::EPdec;
+                        return;
+                    }
+                    '>' => {
+                        self.private = Vt102_OP::EPgt;
+                        return;
+                    }
+                    '=' => {
+                        self.private = Vt102_OP::EPeq;
+                        return;
+                    }
+                    '<' => {
+                        self.private = Vt102_OP::EPlt;
+                        return;
+                    }
+                    _ => {}
+                }
+
+                self.private = Vt102_OP::EPecma;
+                self.do_getpars(c);
+            }
+            VirtualConsoleState::ESgetpars => {
+                let c = ch as u8 as char;
+                self.do_getpars(c);
+            }
+            VirtualConsoleState::ESfunckey => {
+                self.vc_state = VirtualConsoleState::ESnormal;
+                return;
+            }
+            VirtualConsoleState::EShash => {
+                self.vc_state = VirtualConsoleState::ESnormal;
+                if ch as u8 as char == '8' {
+                    self.erase_char = (self.erase_char & 0xff00) | 'E' as u16;
+                    self.csi_J(2);
+                    self.erase_char = (self.erase_char & 0xff00) | ' ' as u16;
+                    self.do_update_region(0, self.screen_buf.len());
+                }
+                return;
+            }
+            VirtualConsoleState::ESsetG0 => {
+                todo!("SetGx todo");
+            }
+            VirtualConsoleState::ESsetG1 => {
+                todo!("SetGx todo");
+            }
+            VirtualConsoleState::ESpercent => {
+                self.vc_state = VirtualConsoleState::ESnormal;
+                let c = ch as u8 as char;
+                match c {
+                    '@' => {
+                        self.utf = false;
+                        return;
+                    }
+                    'G' | '8' => {
+                        self.utf = true;
+                        return;
+                    }
+                    _ => {}
+                }
+                return;
+            }
+            VirtualConsoleState::EScsiignore => {
+                if ch >= 20 && ch <= 0x3f {
+                    return;
+                }
+                self.vc_state = VirtualConsoleState::ESnormal;
+                return;
+            }
+            VirtualConsoleState::ESnonstd => {
+                let c = ch as u8 as char;
+                if c == 'P' {
+                    for i in self.par.iter_mut() {
+                        *i = 0;
+                    }
+                    self.npar = 0;
+                    self.vc_state = VirtualConsoleState::ESpalette;
+                    return;
+                } else if c == 'R' {
+                    self.reset_palette();
+                    self.vc_state = VirtualConsoleState::ESnormal;
+                } else if c >= '0' && c <= '9' {
+                    self.vc_state = VirtualConsoleState::ESosc;
+                } else {
+                    self.vc_state = VirtualConsoleState::ESnormal;
+                }
+            }
+            VirtualConsoleState::ESpalette => {
+                let c = ch as u8 as char;
+                if c.is_digit(16) {
+                    self.npar += 1;
+                    self.par[self.npar as usize] = c.to_digit(16).unwrap();
+
+                    if self.npar == 7 {
+                        let mut i = self.par[0] as usize;
+                        let mut j = 0;
+                        self.palette[i].red = self.par[j] as u16;
+                        j += 1;
+                        self.palette[i].green = self.par[j] as u16;
+                        j += 1;
+                        self.palette[i].blue = self.par[j] as u16;
+                        j += 1;
+                        i += 1;
+                        self.palette[i].red = self.par[j] as u16;
+                        j += 1;
+                        self.palette[i].green = self.par[j] as u16;
+                        j += 1;
+                        self.palette[i].blue = self.par[j] as u16;
+                        self.set_palette();
+                        self.vc_state = VirtualConsoleState::ESnormal;
+                    }
+                }
+            }
+            VirtualConsoleState::ESosc => {}
+            VirtualConsoleState::ESapc => {}
+            VirtualConsoleState::ESpm => {}
+            VirtualConsoleState::ESdcs => {}
+            VirtualConsoleState::ESnormal => {}
+        }
+    }
+
+    pub(super) fn console_write_normal(
+        &mut self,
+        mut tc: u32,
+        c: u32,
+        draw: &mut DrawRegion,
+    ) -> bool {
+        let mut attr = self.attr;
+        let himask = self.hi_font_mask;
+        let charmask = if himask == 0 { 0xff } else { 0x1ff };
+        let mut width = 1;
+        // 表示需不需要反转
+        let mut invert = false;
+        if self.utf && !self.display_ctrl {
+            if FontDesc::is_double_width(c) {
+                width = 2;
+            }
+        }
+
+        let tmp = self.unicode_to_index(tc);
+        if tmp & (!charmask as i32) != 0 {
+            if tmp == -1 || tmp == -2 {
+                return false;
+            }
+
+            // 未找到
+            if (!self.utf || self.display_ctrl || c < 128) && c & !charmask == 0 {
+                tc = c;
+            } else {
+                let tmp = self.unicode_to_index(0xfffd);
+                if tmp < 0 {
+                    invert = true;
+                    let tmp = self.unicode_to_index('?' as u32);
+                    if tmp < 0 {
+                        tc = '?' as u32;
+                    } else {
+                        tc = tmp as u32;
+                    }
+
+                    attr = self.invert_attr();
+                    self.flush(draw);
+                }
+            }
+        }
+
+        loop {
+            if self.need_wrap || self.insert_mode {
+                self.flush(draw);
+            }
+            if self.need_wrap {
+                self.carriage_return();
+                self.line_feed();
+            }
+
+            if self.insert_mode {
+                self.insert_char(1);
+            }
+
+            // TODO: 处理unicode screen buf
+
+            if himask != 0 {
+                tc = ((if tc & 0x100 != 0 { himask as u32 } else { 0 }) | (tc & 0xff)) as u32;
+            }
+
+            tc |= ((attr as u32) << 8) & (!himask as u32);
+
+            // kwarn!(
+            //     "ch {} pos {} x {} y {} cols {}",
+            //     c as u8 as char,
+            //     self.pos,
+            //     self.state.x,
+            //     self.state.y,
+            //     self.cols,
+            // );
+            self.screen_buf[self.pos] = tc as u16;
+
+            if draw.x.is_none() {
+                // 设置draw参数
+                draw.x = Some(self.state.x as u32);
+                draw.offset = self.pos;
+            }
+
+            if self.state.x == self.cols - 1 {
+                // 需要换行?
+                self.need_wrap = self.autowrap;
+                draw.size += 1;
+            } else {
+                self.state.x += 1;
+                self.pos += 1;
+                draw.size += 1;
+            }
+
+            width -= 1;
+            if width == 0 {
+                break;
+            }
+            let tmp = self.unicode_to_index(' ' as u32);
+            tc = if tmp < 0 { ' ' as u32 } else { tmp as u32 };
+        }
+
+        if invert {
+            self.flush(draw);
+        }
+
+        true
+    }
+
+    /// ## 当前vc插入nr个字符
+    fn insert_char(&mut self, nr: usize) {
+        // TODO: 管理unicode屏幕信息
+
+        let pos = self.pos;
+        // 把当前位置以后得字符向后移动nr*2位
+        self.screen_buf[pos..].rotate_right(nr * 2);
+
+        // 把空出来的位置用erase_char填充
+        for c in &mut self.screen_buf[pos..(pos + nr * 2)] {
+            *c = self.erase_char
+        }
+
+        self.need_wrap = false;
+
+        // 更新本行后面部分
+        self.do_update_region(self.pos, self.cols - self.state.x);
+    }
+
+    /// ## 更新虚拟控制台指定区域的显示
+    fn do_update_region(&self, mut start: usize, mut count: usize) {
+        let ret = self.driver_funcs().con_getxy(self, start);
+        let (mut x, mut y) = if ret.is_err() {
+            let offset = start / 2;
+            (offset % self.cols, offset / self.cols)
+        } else {
+            let (tmp_start, tmp_x, tmp_y) = ret.unwrap();
+            start = tmp_start;
+            (tmp_x, tmp_y)
+        };
+
+        loop {
+            // 记录当前字符的属性
+            let mut attr = self.screen_buf[start] & 0xff00;
+            let mut startx = x;
+            let mut size = 0;
+
+            while count != 0 && x < self.cols {
+                // 检查属性是否变化,如果属性变了,则将前一个字符先输出
+                if attr != (self.screen_buf[start] & 0xff00) {
+                    if size > 0 {
+                        let _ = self.driver_funcs().con_putcs(
+                            self,
+                            &self.screen_buf[start..],
+                            size,
+                            y as u32,
+                            startx as u32,
+                        );
+                        startx = x;
+                        start += size;
+                        size = 0;
+                        attr = self.screen_buf[start] & 0xff00;
+                    }
+                }
+                size += 1;
+                x += 1;
+                count -= 1;
+            }
+
+            if size > 0 {
+                let _ = self.driver_funcs().con_putcs(
+                    self,
+                    &self.screen_buf[start..],
+                    size,
+                    y as u32,
+                    startx as u32,
+                );
+            }
+            if count == 0 {
+                break;
+            }
+
+            // 一行
+            x = 0;
+            y += 1;
+
+            let ret = self.driver_funcs().con_getxy(self, start);
+            if ret.is_ok() {
+                start = ret.unwrap().0;
+            }
+        }
+    }
+
+    const UNI_DIRECT_MAKS: u32 = 0x01ff;
+    const UNI_DIRECT_BASE: u32 = 0xf000;
+    /// ## unicode字符转对应的坐标,暂时这样写,还没有适配unicode
+    /// 这里是糊代码的,后面重写
+    fn unicode_to_index(&self, ch: u32) -> i32 {
+        if ch > 0xfff {
+            // 未找到
+            return -4;
+        } else if ch < 0x20 {
+            // 不可打印
+            return -1;
+        } else if ch == 0xfeff || (ch >= 0x200b && ch <= 0x200f) {
+            // 零长空格
+            return -2;
+        } else if (ch & !Self::UNI_DIRECT_MAKS) == Self::UNI_DIRECT_BASE {
+            return (ch & Self::UNI_DIRECT_MAKS) as i32;
+        }
+
+        // TODO: 暂时这样写,表示不支持
+        return -3;
+    }
+
+    fn invert_attr(&self) -> u8 {
+        if !self.color_mode {
+            return self.attr ^ 0x08;
+        }
+
+        if self.hi_font_mask == 0x100 {
+            return (self.attr & 0x11) | ((self.attr & 0xe0) >> 4) | ((self.attr & 0x0e) << 4);
+        }
+
+        return (self.attr & 0x88) | ((self.attr & 0x70) >> 4) | ((self.attr & 0x07) << 4);
+    }
+
+    pub(super) fn flush(&self, draw: &mut DrawRegion) {
+        if draw.x.is_none() {
+            return;
+        }
+
+        let _ = self.driver_funcs().con_putcs(
+            self,
+            &self.screen_buf[draw.offset..draw.offset + draw.size],
+            draw.size,
+            self.state.y as u32,
+            draw.x.unwrap() as u32,
+        );
+
+        draw.x = None;
+        draw.size = 0;
+    }
+
+    fn build_attr(
+        &self,
+        color: u8,
+        intensity: VirtualConsoleIntensity,
+        blink: bool,
+        underline: bool,
+        reverse: bool,
+        italic: bool,
+    ) -> u8 {
+        let ret = self
+            .driver_funcs()
+            .con_build_attr(self, color, intensity, blink, underline, reverse, italic);
+
+        if ret.is_ok() {
+            return ret.unwrap();
+        }
+
+        let mut ret = color;
+
+        if !self.color_mode {
+            return intensity as u8
+                | (italic as u8) << 1
+                | (underline as u8) << 2
+                | (reverse as u8) << 3
+                | (blink as u8) << 7;
+        }
+
+        if italic {
+            ret = (ret & 0xf0) | self.italic_color as u8;
+        } else if underline {
+            ret = (ret & 0xf0) | self.underline_color as u8;
+        } else if intensity == VirtualConsoleIntensity::VciHalfBright {
+            ret = (ret & 0xf0) | self.half_color as u8;
+        }
+
+        if reverse {
+            ret = (ret & 0x88) | (((ret >> 4) | (ret << 4)) & 0x77);
+        }
+
+        if blink {
+            ret ^= 0x80;
+        }
+
+        if intensity == VirtualConsoleIntensity::VciBold {
+            ret ^= 0x08;
+        }
+
+        if self.hi_font_mask == 0x100 {
+            ret <<= 1;
+        }
+
+        ret
+    }
+
+    pub(super) fn update_attr(&mut self) {
+        self.attr = self.build_attr(
+            self.state.color,
+            self.state.intensity,
+            self.state.blink,
+            self.state.underline,
+            self.state.reverse ^ self.screen_mode,
+            self.state.italic,
+        );
+
+        self.erase_char = ' ' as u16
+            | ((self.build_attr(
+                self.state.color,
+                VirtualConsoleIntensity::VciNormal,
+                self.state.blink,
+                false,
+                self.screen_mode,
+                false,
+            ) as u16)
+                << 8);
+    }
+
+    fn default_attr(&mut self) {
+        self.state.intensity = VirtualConsoleIntensity::VciNormal;
+        self.state.italic = false;
+        self.state.underline = false;
+        self.state.reverse = false;
+        self.state.blink = false;
+        self.state.color = self.def_color;
+    }
+}
+
+/// ## 虚拟控制台的状态信息
+#[derive(Debug, Default, Clone)]
+pub struct VirtualConsoleInfo {
+    // x,y表示光标坐标
+    pub x: usize,
+    pub y: usize,
+    pub color: u8,
+
+    /// 表示字符的强度
+    intensity: VirtualConsoleIntensity,
+    /// 斜体
+    italic: bool,
+    /// 下划线
+    underline: bool,
+    /// 字符闪烁
+    blink: bool,
+    /// 前景与背景色反转
+    reverse: bool,
+}
+
+impl VirtualConsoleInfo {
+    pub fn new(x: usize, y: usize) -> Self {
+        Self {
+            x,
+            y,
+            color: Default::default(),
+            intensity: Default::default(),
+            italic: Default::default(),
+            underline: Default::default(),
+            blink: Default::default(),
+            reverse: Default::default(),
+        }
+    }
+}
+
+/// 字符强度
+#[derive(Debug, Clone, PartialEq, Copy)]
+pub enum VirtualConsoleIntensity {
+    /// 暗淡
+    VciHalfBright = 0,
+    /// 正常
+    VciNormal = 1,
+    /// 粗体
+    VciBold = 2,
+}
+
+impl Default for VirtualConsoleIntensity {
+    fn default() -> Self {
+        Self::VciNormal
+    }
+}
+
+/// ## 虚拟控制台的状态
+///
+/// 可以把VC的接收字符理解为一个状态机
+#[derive(Debug, PartialEq, Clone)]
+pub enum VirtualConsoleState {
+    /// 正常状态
+    ESnormal,
+    /// 收到了转义字符 \e,即"Escape"字符
+    ESesc,
+    /// 收到了 "[" 字符,通常是 ANSI 控制序列的开始
+    ESsquare,
+    /// 解析参数状态
+    ESgetpars,
+    /// 功能键状态
+    ESfunckey,
+    /// 收到了 "#" 字符
+    EShash,
+    /// 设置 G0 字符集状态
+    ESsetG0,
+    /// 设置 G1 字符集状态
+    ESsetG1,
+    /// 收到了 "%" 字符
+    ESpercent,
+    /// 忽略 ANSI 控制序列状态
+    EScsiignore,
+    /// 非标准字符状态
+    ESnonstd,
+    /// 调色板状态
+    ESpalette,
+    /// Operating System Command (OSC) 状态
+    ESosc,
+    ///  Application Program Command (APC) 状态
+    ESapc,
+    /// Privacy Message (PM) 状态
+    ESpm,
+    /// Device Control String (DCS) 状态
+    ESdcs,
+}
+
+impl VirtualConsoleState {
+    pub fn is_ansi_control_string(&self) -> bool {
+        if *self == Self::ESosc
+            || *self == Self::ESapc
+            || *self == Self::ESpm
+            || *self == Self::ESdcs
+        {
+            return true;
+        }
+
+        false
+    }
+}
+
+#[derive(Debug, Clone, PartialEq, PartialOrd)]
+#[allow(non_camel_case_types)]
+pub enum Vt102_OP {
+    EPecma,
+    EPdec,
+    EPeq,
+    EPgt,
+    EPlt,
+}
+
+bitflags! {
+    #[derive(Default)]
+    pub struct VcCursor: u32 {
+        /// 默认
+        const CUR_DEF			=       0;
+        /// 无光标
+        const CUR_NONE			=       1;
+        /// 下划线形式
+        const CUR_UNDERLINE		=	    2;
+        /// 光标占据底部的三分之一
+        const CUR_LOWER_THIRD	=	    3;
+        /// 光标占据底部的一半
+        const CUR_LOWER_HALF	=       4;
+        ///  光标占据底部的三分之二
+        const CUR_TWO_THIRDS	=       5;
+        /// 光标为块状(方块)形式
+        const CUR_BLOCK			=       6;
+        /// 光标属性,用于指示软件光标
+        const CUR_SW			=	0x000010;
+        /// 光标属性,用于指示光标是否始终在背景上显示
+        const CUR_ALWAYS_BG		=	0x000020;
+        /// 光标属性,用于指示前景和背景是否反转
+        const CUR_INVERT_FG_BG	=	0x000040;
+        /// 光标前景色属性,用于指定光标的前景色
+        const CUR_FG			=	0x000700;
+        /// 光标背景色属性,用于指定光标的背景色
+        const CUR_BG			=	0x007000;
+    }
+}
+
+impl VcCursor {
+    pub fn make_cursor(size: u32, change: u32, set: u32) -> Self {
+        unsafe { Self::from_bits_unchecked(size | (change << 8) | (set << 16)) }
+    }
+
+    pub fn cursor_size(&self) -> Self {
+        Self::from_bits_truncate(self.bits & 0x00000f)
+    }
+
+    pub fn cursor_set(&self) -> u32 {
+        (self.bits & 0xff0000) >> 8
+    }
+
+    pub fn cursor_change(&self) -> u32 {
+        self.bits & 0x00ff00
+    }
+}
+
+#[derive(Debug, PartialEq)]
+#[allow(dead_code)]
+pub enum CursorOperation {
+    Draw,
+    Erase,
+    Move,
+}
+
+#[derive(Debug, PartialEq, Clone, Copy)]
+pub enum ScrollDir {
+    Up,
+    Down,
+}

+ 0 - 10
kernel/src/driver/tty/vt/mod.rs

@@ -1,10 +0,0 @@
-//! Virtual terminal driver.
-//!
-//! (TODO) This driver is not implemented yet.
-
-/// The minimum number of virtual terminals.
-#[allow(dead_code)]
-pub const MIN_NR_CONSOLES: usize = 1;
-/// The maximum number of virtual terminals.
-#[allow(dead_code)]
-pub const MAX_NR_CONSOLES: usize = 63;

+ 1 - 0
kernel/src/driver/video/fbdev/base/fbcmap.rs

@@ -0,0 +1 @@
+

+ 787 - 0
kernel/src/driver/video/fbdev/base/fbcon/framebuffer_console.rs

@@ -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;
+    }
+}

+ 176 - 7
kernel/src/driver/video/fbdev/base/fbcon.rs → kernel/src/driver/video/fbdev/base/fbcon/mod.rs

@@ -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
+    }
+}

+ 415 - 8
kernel/src/driver/video/fbdev/base/mod.rs

@@ -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表示XOR,false表示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>,
+}

+ 229 - 27
kernel/src/driver/video/fbdev/vesafb.rs

@@ -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;
     });

+ 4 - 2
kernel/src/driver/video/mod.rs

@@ -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()?;

+ 7 - 2
kernel/src/filesystem/devfs/mod.rs

@@ -6,7 +6,7 @@ use super::vfs::{
     core::{generate_inode_id, ROOT_INODE},
     file::FileMode,
     syscall::ModeType,
-    FileSystem, FileType, FsInfo, IndexNode, Metadata,
+    FilePrivateData, FileSystem, FileType, FsInfo, IndexNode, Metadata,
 };
 use crate::{
     driver::base::device::device_number::DeviceNumber,
@@ -461,7 +461,12 @@ impl IndexNode for LockedDevFSInode {
         }
     }
 
-    fn ioctl(&self, _cmd: u32, _data: usize) -> Result<usize, SystemError> {
+    fn ioctl(
+        &self,
+        _cmd: u32,
+        _data: usize,
+        _private_data: &FilePrivateData,
+    ) -> Result<usize, SystemError> {
         Err(SystemError::EOPNOTSUPP_OR_ENOTSUP)
     }
 

+ 6 - 1
kernel/src/filesystem/kernfs/mod.rs

@@ -258,7 +258,12 @@ impl IndexNode for KernFSInode {
         return Ok((name, entry.metadata()?));
     }
 
-    fn ioctl(&self, _cmd: u32, _data: usize) -> Result<usize, SystemError> {
+    fn ioctl(
+        &self,
+        _cmd: u32,
+        _data: usize,
+        _private_data: &FilePrivateData,
+    ) -> Result<usize, SystemError> {
         // 若文件系统没有实现此方法,则返回“不支持”
         return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
     }

+ 1 - 1
kernel/src/filesystem/vfs/file.rs

@@ -8,7 +8,7 @@ use system_error::SystemError;
 use crate::{
     driver::{
         base::{block::SeekFrom, device::DevicePrivateData},
-        tty::TtyFilePrivateData,
+        tty::tty_device::TtyFilePrivateData,
     },
     filesystem::procfs::ProcfsFilePrivateData,
     ipc::pipe::{LockedPipeInode, PipeFsPrivateData},

+ 6 - 1
kernel/src/filesystem/vfs/mod.rs

@@ -339,7 +339,12 @@ pub trait IndexNode: Any + Sync + Send + Debug {
     ///
     /// @return 成功:Ok()
     ///         失败:Err(错误码)
-    fn ioctl(&self, _cmd: u32, _data: usize) -> Result<usize, SystemError> {
+    fn ioctl(
+        &self,
+        _cmd: u32,
+        _data: usize,
+        _private_data: &FilePrivateData,
+    ) -> Result<usize, SystemError> {
         // 若文件系统没有实现此方法,则返回“不支持”
         return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
     }

+ 7 - 2
kernel/src/filesystem/vfs/mount.rs

@@ -317,8 +317,13 @@ impl IndexNode for MountFSInode {
     }
 
     #[inline]
-    fn ioctl(&self, cmd: u32, data: usize) -> Result<usize, SystemError> {
-        return self.inner_inode.ioctl(cmd, data);
+    fn ioctl(
+        &self,
+        cmd: u32,
+        data: usize,
+        private_data: &FilePrivateData,
+    ) -> Result<usize, SystemError> {
+        return self.inner_inode.ioctl(cmd, data, private_data);
     }
 
     #[inline]

+ 3 - 2
kernel/src/filesystem/vfs/syscall.rs

@@ -297,7 +297,8 @@ impl Syscall {
 
         // drop guard 以避免无法调度的问题
         drop(fd_table_guard);
-        let r = file.lock_no_preempt().inode().ioctl(cmd, data);
+        let file = file.lock_no_preempt();
+        let r = file.inode().ioctl(cmd, data, &file.private_data);
         return r;
     }
 
@@ -683,7 +684,7 @@ impl Syscall {
                 for i in arg..FileDescriptorVec::PROCESS_MAX_FD {
                     let binding = ProcessManager::current_pcb().fd_table();
                     let mut fd_table_guard = binding.write();
-                    if fd_table_guard.get_file_by_fd(fd).is_none() {
+                    if fd_table_guard.get_file_by_fd(i as i32).is_none() {
                         return Self::do_dup2(fd, i as i32, &mut fd_table_guard);
                     }
                 }

+ 2 - 2
kernel/src/init/init.rs

@@ -3,7 +3,7 @@ use crate::{
         init::{early_setup_arch, setup_arch, setup_arch_post},
         CurrentIrqArch, CurrentSMPArch, CurrentSchedArch,
     },
-    driver::{base::init::driver_init, tty::init::tty_early_init, video::VideoRefreshManager},
+    driver::{base::init::driver_init, serial::serial_early_init, video::VideoRefreshManager},
     exception::{init::irq_init, softirq::softirq_init, InterruptArch},
     filesystem::vfs::core::vfs_init,
     include::bindings::bindings::acpi_init,
@@ -81,7 +81,7 @@ fn do_start_kernel() {
 /// 在内存管理初始化之前,执行的初始化
 #[inline(never)]
 fn init_before_mem_init() {
-    tty_early_init().expect("tty early init failed");
+    serial_early_init().expect("serial early init failed");
     let video_ok = unsafe { VideoRefreshManager::video_init().is_ok() };
     scm_init(video_ok);
 }

TEMPAT SAMPAH
kernel/src/libs/font/bin/VGA_8X16.bytes


TEMPAT SAMPAH
kernel/src/libs/font/bin/VGA_8X8.bytes


+ 2 - 0
kernel/src/libs/font/font_type/mod.rs

@@ -0,0 +1,2 @@
+pub mod vga8x16;
+pub mod vga8x8;

+ 10 - 0
kernel/src/libs/font/font_type/vga8x16.rs

@@ -0,0 +1,10 @@
+use crate::libs::font::FontDesc;
+
+pub const FONT_VGA_8X16: FontDesc = FontDesc {
+    index: 1,
+    name: "VGA8x16",
+    width: 8,
+    height: 16,
+    char_count: 256,
+    data: include_bytes!("../bin/VGA_8X16.bytes"),
+};

+ 11 - 0
kernel/src/libs/font/font_type/vga8x8.rs

@@ -0,0 +1,11 @@
+use crate::libs::font::FontDesc;
+
+#[allow(dead_code)]
+pub const FONT_VGA_8X8: FontDesc = FontDesc {
+    index: 0,
+    name: "VGA8x8",
+    width: 8,
+    height: 8,
+    char_count: 256,
+    data: include_bytes!("../bin/VGA_8X8.bytes"),
+};

+ 49 - 0
kernel/src/libs/font/mod.rs

@@ -0,0 +1,49 @@
+use self::font_type::vga8x16::FONT_VGA_8X16;
+
+pub mod font_type;
+
+pub struct FontDesc {
+    pub index: usize,
+    pub name: &'static str,
+    pub width: u32,
+    pub height: u32,
+    pub char_count: u32,
+    pub data: &'static [u8],
+}
+
+impl FontDesc {
+    pub fn get_default_font(_xres: u32, _yres: u32, _font_w: u32, _font_h: u32) -> &'static Self {
+        // todo: 目前先直接返回一个字体
+        &FONT_VGA_8X16
+    }
+
+    pub const DOUBLE_WIDTH_RANGE: &'static [(u32, u32)] = &[
+        (0x1100, 0x115F),
+        (0x2329, 0x232A),
+        (0x2E80, 0x303E),
+        (0x3040, 0xA4CF),
+        (0xAC00, 0xD7A3),
+        (0xF900, 0xFAFF),
+        (0xFE10, 0xFE19),
+        (0xFE30, 0xFE6F),
+        (0xFF00, 0xFF60),
+        (0xFFE0, 0xFFE6),
+        (0x20000, 0x2FFFD),
+        (0x30000, 0x3FFFD),
+    ];
+    pub fn is_double_width(ch: u32) -> bool {
+        if ch < Self::DOUBLE_WIDTH_RANGE.first().unwrap().0
+            || ch > Self::DOUBLE_WIDTH_RANGE.last().unwrap().1
+        {
+            return false;
+        }
+
+        for (first, last) in Self::DOUBLE_WIDTH_RANGE {
+            if ch > *first && ch < *last {
+                return true;
+            }
+        }
+
+        false
+    }
+}

+ 56 - 62
kernel/src/libs/keyboard_parser.rs

@@ -1,6 +1,11 @@
+use core::sync::atomic::Ordering;
+
 use alloc::sync::Arc;
 
-use crate::driver::tty::tty_device::TtyDevice;
+use crate::driver::tty::{
+    tty_port::{TtyPort, TTY_PORTS},
+    virtual_terminal::virtual_console::CURRENT_VCNUM,
+};
 
 #[allow(dead_code)]
 pub const NUM_SCAN_CODES: u8 = 0x80;
@@ -28,25 +33,21 @@ pub enum KeyFlag {
 pub struct TypeOneFSM {
     status: ScanCodeStatus,
     current_state: TypeOneFSMState,
-    tty: Arc<TtyDevice>,
 }
 
 impl TypeOneFSM {
     #[allow(dead_code)]
-    pub fn new(tty: Arc<TtyDevice>) -> Self {
+    pub fn new() -> Self {
         Self {
             status: ScanCodeStatus::new(),
             current_state: TypeOneFSMState::Start,
-            tty,
         }
     }
 
     /// @brief 解析扫描码
     #[allow(dead_code)]
     pub fn parse(&mut self, scancode: u8) -> TypeOneFSMState {
-        self.current_state = self
-            .current_state
-            .parse(scancode, &mut self.status, &self.tty);
+        self.current_state = self.current_state.parse(scancode, &mut self.status);
         self.current_state
     }
 }
@@ -69,42 +70,30 @@ pub enum TypeOneFSMState {
 
 impl TypeOneFSMState {
     /// @brief 状态机总控程序
-    fn parse(
-        &self,
-        scancode: u8,
-        scancode_status: &mut ScanCodeStatus,
-        tty: &Arc<TtyDevice>,
-    ) -> TypeOneFSMState {
+    fn parse(&self, scancode: u8, scancode_status: &mut ScanCodeStatus) -> TypeOneFSMState {
         // kdebug!("the code is {:#x}\n", scancode);
         match self {
             TypeOneFSMState::Start => {
-                return self.handle_start(scancode, scancode_status, tty);
+                return self.handle_start(scancode, scancode_status);
             }
             TypeOneFSMState::PauseBreak(n) => {
-                return self.handle_pause_break(*n, scancode_status, tty);
+                return self.handle_pause_break(*n, scancode_status);
             }
             TypeOneFSMState::Func0 => {
-                return self.handle_func0(scancode, scancode_status, tty);
+                return self.handle_func0(scancode, scancode_status);
             }
             TypeOneFSMState::Type3 => {
-                return self.handle_type3(scancode, scancode_status, tty);
-            }
-            TypeOneFSMState::PrtscPress(n) => {
-                return self.handle_prtsc_press(*n, scancode_status, tty)
+                return self.handle_type3(scancode, scancode_status);
             }
+            TypeOneFSMState::PrtscPress(n) => return self.handle_prtsc_press(*n, scancode_status),
             TypeOneFSMState::PrtscRelease(n) => {
-                return self.handle_prtsc_release(*n, scancode_status, tty)
+                return self.handle_prtsc_release(*n, scancode_status)
             }
         }
     }
 
     /// @brief 处理起始状态
-    fn handle_start(
-        &self,
-        scancode: u8,
-        scancode_status: &mut ScanCodeStatus,
-        tty: &Arc<TtyDevice>,
-    ) -> TypeOneFSMState {
+    fn handle_start(&self, scancode: u8, scancode_status: &mut ScanCodeStatus) -> TypeOneFSMState {
         //kdebug!("in handle_start the code is {:#x}\n",scancode);
         match scancode {
             0xe1 => {
@@ -115,7 +104,7 @@ impl TypeOneFSMState {
             }
             _ => {
                 //kdebug!("in _d the code is {:#x}\n",scancode);
-                return TypeOneFSMState::Type3.handle_type3(scancode, scancode_status, tty);
+                return TypeOneFSMState::Type3.handle_type3(scancode, scancode_status);
             }
         }
     }
@@ -125,17 +114,16 @@ impl TypeOneFSMState {
         &self,
         scancode: u8,
         scancode_status: &mut ScanCodeStatus,
-        tty: &Arc<TtyDevice>,
     ) -> TypeOneFSMState {
         static PAUSE_BREAK_SCAN_CODE: [u8; 6] = [0xe1, 0x1d, 0x45, 0xe1, 0x9d, 0xc5];
         let i = match self {
             TypeOneFSMState::PauseBreak(i) => *i,
             _ => {
-                return self.handle_type3(scancode, scancode_status, tty);
+                return self.handle_type3(scancode, scancode_status);
             }
         };
         if scancode != PAUSE_BREAK_SCAN_CODE[i as usize] {
-            return self.handle_type3(scancode, scancode_status, tty);
+            return self.handle_type3(scancode, scancode_status);
         } else {
             if i == 5 {
                 // 所有Pause Break扫描码都被清除
@@ -146,12 +134,7 @@ impl TypeOneFSMState {
         }
     }
 
-    fn handle_func0(
-        &self,
-        scancode: u8,
-        scancode_status: &mut ScanCodeStatus,
-        tty: &Arc<TtyDevice>,
-    ) -> TypeOneFSMState {
+    fn handle_func0(&self, scancode: u8, scancode_status: &mut ScanCodeStatus) -> TypeOneFSMState {
         //0xE0
         match scancode {
             0x2a => {
@@ -214,7 +197,7 @@ impl TypeOneFSMState {
             }
             0x53 => {
                 scancode_status.del = true;
-                Self::emit(tty, 127);
+                Self::emit(127);
             }
             0xd3 => {
                 scancode_status.del = false;
@@ -233,32 +216,32 @@ impl TypeOneFSMState {
             }
             0x48 => {
                 scancode_status.arrow_u = true;
-                Self::emit(tty, 224);
-                Self::emit(tty, 72);
+                Self::emit(224);
+                Self::emit(72);
             }
             0xc8 => {
                 scancode_status.arrow_u = false;
             }
             0x4b => {
                 scancode_status.arrow_l = true;
-                Self::emit(tty, 224);
-                Self::emit(tty, 75);
+                Self::emit(224);
+                Self::emit(75);
             }
             0xcb => {
                 scancode_status.arrow_l = false;
             }
             0x50 => {
                 scancode_status.arrow_d = true;
-                Self::emit(tty, 224);
-                Self::emit(tty, 80);
+                Self::emit(224);
+                Self::emit(80);
             }
             0xd0 => {
                 scancode_status.arrow_d = false;
             }
             0x4d => {
                 scancode_status.arrow_r = true;
-                Self::emit(tty, 224);
-                Self::emit(tty, 77);
+                Self::emit(224);
+                Self::emit(77);
             }
             0xcd => {
                 scancode_status.arrow_r = false;
@@ -269,14 +252,14 @@ impl TypeOneFSMState {
                 scancode_status.kp_forward_slash = true;
 
                 let ch = '/' as u8;
-                Self::emit(tty, ch);
+                Self::emit(ch);
             }
             0xb5 => {
                 scancode_status.kp_forward_slash = false;
             }
             0x1c => {
                 scancode_status.kp_enter = true;
-                Self::emit(tty, '\n' as u8);
+                Self::emit('\n' as u8);
             }
             0x9c => {
                 scancode_status.kp_enter = false;
@@ -288,12 +271,7 @@ impl TypeOneFSMState {
         return TypeOneFSMState::Start;
     }
 
-    fn handle_type3(
-        &self,
-        scancode: u8,
-        scancode_status: &mut ScanCodeStatus,
-        tty: &Arc<TtyDevice>,
-    ) -> TypeOneFSMState {
+    fn handle_type3(&self, scancode: u8, scancode_status: &mut ScanCodeStatus) -> TypeOneFSMState {
         // 判断按键是被按下还是抬起
         let flag_make = if (scancode & (TYPE1_KEYCODE_FLAG_BREAK as u8)) > 0 {
             false //up
@@ -358,18 +336,36 @@ impl TypeOneFSMState {
             }
         }
 
-        let ch = TYPE1_KEY_CODE_MAPTABLE[col as usize + 2 * index as usize];
+        let mut ch = TYPE1_KEY_CODE_MAPTABLE[col as usize + 2 * index as usize];
         if key != KeyFlag::NoneFlag {
             // kdebug!("EMIT: ch is '{}', keyflag is {:?}\n", ch as char, key);
-            Self::emit(tty, ch);
+            if scancode_status.ctrl_l || scancode_status.ctrl_r {
+                ch = Self::to_ctrl(ch);
+            }
+            Self::emit(ch);
         }
         return TypeOneFSMState::Start;
     }
 
+    #[inline]
+    fn to_ctrl(ch: u8) -> u8 {
+        return match ch as char {
+            'a'..='z' => ch - 0x40,
+            'A'..='Z' => ch - 0x40,
+            '@'..='_' => ch - 0x40,
+            _ => ch,
+        };
+    }
+
     #[inline(always)]
-    fn emit(tty: &Arc<TtyDevice>, ch: u8) {
+    fn emit(ch: u8) {
         // 发送到tty
-        tty.input(&[ch]).ok();
+        let _ = Self::current_port().receive_buf(&[ch], &[], 1);
+    }
+
+    #[inline]
+    fn current_port() -> Arc<dyn TtyPort> {
+        TTY_PORTS[CURRENT_VCNUM.load(Ordering::SeqCst) as usize].clone()
     }
 
     /// @brief 处理Prtsc按下事件
@@ -377,7 +373,6 @@ impl TypeOneFSMState {
         &self,
         scancode: u8,
         scancode_status: &mut ScanCodeStatus,
-        tty: &Arc<TtyDevice>,
     ) -> TypeOneFSMState {
         static PRTSC_SCAN_CODE: [u8; 4] = [0xe0, 0x2a, 0xe0, 0x37];
         let i = match self {
@@ -389,7 +384,7 @@ impl TypeOneFSMState {
             return TypeOneFSMState::Start;
         }
         if scancode != PRTSC_SCAN_CODE[i as usize] {
-            return self.handle_type3(scancode, scancode_status, tty);
+            return self.handle_type3(scancode, scancode_status);
         } else {
             if i == 3 {
                 // 成功解析出PrtscPress
@@ -405,7 +400,6 @@ impl TypeOneFSMState {
         &self,
         scancode: u8,
         scancode_status: &mut ScanCodeStatus,
-        tty: &Arc<TtyDevice>,
     ) -> TypeOneFSMState {
         static PRTSC_SCAN_CODE: [u8; 4] = [0xe0, 0xb7, 0xe0, 0xaa];
         let i = match self {
@@ -417,7 +411,7 @@ impl TypeOneFSMState {
             return TypeOneFSMState::Start;
         }
         if scancode != PRTSC_SCAN_CODE[i as usize] {
-            return self.handle_type3(scancode, scancode_status, tty);
+            return self.handle_type3(scancode, scancode_status);
         } else {
             if i == 3 {
                 // 成功解析出PrtscRelease

+ 1 - 3
kernel/src/libs/lib_ui/screen_manager.rs

@@ -8,9 +8,7 @@ use alloc::{boxed::Box, collections::LinkedList, string::String, sync::Arc};
 use system_error::SystemError;
 
 use crate::{
-    driver::{
-        tty::serial::serial8250::send_to_default_serial8250_port, video::video_refresh_manager,
-    },
+    driver::{serial::serial8250::send_to_default_serial8250_port, video::video_refresh_manager},
     libs::{lib_ui::textui::textui_is_enable_put_to_window, rwlock::RwLock, spinlock::SpinLock},
     mm::VirtAddr,
 };

+ 29 - 1
kernel/src/libs/lib_ui/textui.rs

@@ -1,6 +1,11 @@
 use crate::{
     driver::{
-        tty::serial::serial8250::send_to_default_serial8250_port, video::video_refresh_manager,
+        serial::serial8250::send_to_default_serial8250_port,
+        tty::{
+            tty_driver::TtyOperation, tty_port::TTY_PORTS,
+            virtual_terminal::virtual_console::CURRENT_VCNUM,
+        },
+        video::video_refresh_manager,
     },
     kdebug, kinfo,
     libs::{
@@ -984,6 +989,29 @@ where
 
 #[no_mangle]
 pub extern "C" fn rs_textui_putchar(character: u8, fr_color: u32, bk_color: u32) -> i32 {
+    let current_vcnum = CURRENT_VCNUM.load(Ordering::SeqCst);
+    if current_vcnum != -1 {
+        // tty已经初始化了之后才输出到屏幕
+        let fr = (fr_color & 0x00ff0000) >> 16;
+        let fg = (fr_color & 0x0000ff00) >> 8;
+        let fb = fr_color & 0x000000ff;
+        let br = (bk_color & 0x00ff0000) >> 16;
+        let bg = (bk_color & 0x0000ff00) >> 8;
+        let bb = bk_color & 0x000000ff;
+        let buf = format!(
+            "\x1B[38;2;{fr};{fg};{fb};48;2;{br};{bg};{bb}m{}\x1B[0m",
+            character as char
+        );
+        let port = TTY_PORTS[current_vcnum as usize].clone();
+        let tty = port.port_data().tty();
+        if tty.is_some() {
+            let tty = tty.unwrap();
+            return tty
+                .write(tty.core(), buf.as_bytes(), buf.len())
+                .map(|_| 0)
+                .unwrap_or_else(|e| e.to_posix_errno());
+        }
+    }
     return textui_putchar(
         character as char,
         FontColor::from(fr_color),

+ 1 - 1
kernel/src/libs/lib_ui/textui_no_alloc.rs

@@ -6,7 +6,7 @@ use core::{
 use system_error::SystemError;
 
 use crate::driver::{
-    tty::serial::serial8250::send_to_default_serial8250_port, video::video_refresh_manager,
+    serial::serial8250::send_to_default_serial8250_port, video::video_refresh_manager,
 };
 
 use super::textui::{

+ 2 - 0
kernel/src/libs/mod.rs

@@ -25,3 +25,5 @@ pub mod volatile;
 pub mod futex;
 pub mod rand;
 pub mod wait_queue;
+
+pub mod font;

+ 29 - 9
kernel/src/libs/printk.rs

@@ -1,10 +1,20 @@
-use core::fmt::{self, Write};
+use core::{
+    fmt::{self, Write},
+    sync::atomic::Ordering,
+};
 
 use alloc::string::ToString;
 
 use super::lib_ui::textui::{textui_putstr, FontColor};
 
 use crate::{
+    driver::{
+        serial::serial8250::send_to_default_serial8250_port,
+        tty::{
+            tty_driver::TtyOperation, tty_port::TTY_PORTS,
+            virtual_terminal::virtual_console::CURRENT_VCNUM,
+        },
+    },
     filesystem::procfs::{
         kmsg::KMSG,
         log::{LogLevel, LogMessage},
@@ -57,7 +67,7 @@ macro_rules! kinfo {
 macro_rules! kwarn {
     ($($arg:tt)*) => {
         $crate::libs::printk::Logger.log(4,format_args!("({}:{})\t {}\n", file!(), line!(),format_args!($($arg)*)));
-        $crate::libs::printk::PrintkWriter.__write_string_color($crate::libs::lib_ui::textui::FontColor::YELLOW, $crate::libs::lib_ui::textui::FontColor::BLACK, "[ WARN ] ");
+        $crate::libs::printk::PrintkWriter.__write_fmt(format_args!("\x1B[1;33m[ WARN ] \x1B[0m"));
         $crate::libs::printk::PrintkWriter.__write_fmt(format_args!("({}:{})\t {}\n", file!(), line!(),format_args!($($arg)*)));
     }
 }
@@ -66,7 +76,7 @@ macro_rules! kwarn {
 macro_rules! kerror {
     ($($arg:tt)*) => {
         $crate::libs::printk::Logger.log(3,format_args!("({}:{})\t {}\n", file!(), line!(),format_args!($($arg)*)));
-        $crate::libs::printk::PrintkWriter.__write_string_color($crate::libs::lib_ui::textui::FontColor::RED, $crate::libs::lib_ui::textui::FontColor::BLACK, "[ ERROR ] ");
+        $crate::libs::printk::PrintkWriter.__write_fmt(format_args!("\x1B[41m[ ERROR ] \x1B[0m"));
         $crate::libs::printk::PrintkWriter.__write_fmt(format_args!("({}:{})\t {}\n", file!(), line!(),format_args!($($arg)*)));
     }
 }
@@ -75,7 +85,7 @@ macro_rules! kerror {
 macro_rules! kBUG {
     ($($arg:tt)*) => {
         $crate::libs::printk::Logger.log(1,format_args!("({}:{})\t {}\n", file!(), line!(),format_args!($($arg)*)));
-        $crate::libs::printk::PrintkWriter.__write_string_color($crate::libs::lib_ui::textui::FontColor::RED, $crate::libs::lib_ui::textui::FontColor::BLACK, "[ BUG ] ");
+        $crate::libs::printk::PrintkWriter.__write_fmt(format_args!("\x1B[41m[ BUG ] \x1B[0m"));
         $crate::libs::printk::PrintkWriter.__write_fmt(format_args!("({}:{})\t {}\n", file!(), line!(),format_args!($($arg)*)));
     }
 }
@@ -91,11 +101,21 @@ impl PrintkWriter {
     /// 并输出白底黑字
     /// @param str: 要写入的字符
     pub fn __write_string(&mut self, s: &str) {
-        textui_putstr(s, FontColor::WHITE, FontColor::BLACK).ok();
-    }
-
-    pub fn __write_string_color(&self, fr_color: FontColor, bk_color: FontColor, s: &str) {
-        textui_putstr(s, fr_color, bk_color).ok();
+        let current_vcnum = CURRENT_VCNUM.load(Ordering::SeqCst);
+        if current_vcnum != -1 {
+            // tty已经初始化了之后才输出到屏幕
+            let port = TTY_PORTS[current_vcnum as usize].clone();
+            let tty = port.port_data().tty();
+            if tty.is_some() {
+                let tty = tty.unwrap();
+                let _ = tty.write(tty.core(), s.as_bytes(), s.len());
+                send_to_default_serial8250_port(s.as_bytes());
+            } else {
+                let _ = textui_putstr(s, FontColor::WHITE, FontColor::BLACK);
+            }
+        } else {
+            let _ = textui_putstr(s, FontColor::WHITE, FontColor::BLACK);
+        }
     }
 }
 

+ 1 - 1
kernel/src/mm/init.rs

@@ -1,7 +1,7 @@
 use core::{fmt::Write, sync::atomic::Ordering};
 
 use crate::{
-    arch::MMArch, driver::tty::serial::serial8250::send_to_default_serial8250_port,
+    arch::MMArch, driver::serial::serial8250::send_to_default_serial8250_port,
     filesystem::procfs::kmsg::kmsg_init, libs::printk::PrintkWriter, mm::mmio_buddy::mmio_init,
 };
 

+ 12 - 0
kernel/src/process/mod.rs

@@ -21,6 +21,7 @@ use crate::{
         sched::sched,
         CurrentIrqArch,
     },
+    driver::tty::tty_core::TtyCore,
     exception::InterruptArch,
     filesystem::{
         procfs::procfs_unregister_pid,
@@ -1302,6 +1303,8 @@ pub struct ProcessSignalInfo {
     sig_pending: SigPending,
     // sig_shared_pending 中存储当前线程所属进程要处理的信号
     sig_shared_pending: SigPending,
+    // 当前进程对应的tty
+    tty: Option<Arc<TtyCore>>,
 }
 
 impl ProcessSignalInfo {
@@ -1329,6 +1332,14 @@ impl ProcessSignalInfo {
         &self.sig_shared_pending
     }
 
+    pub fn tty(&self) -> Option<Arc<TtyCore>> {
+        self.tty.clone()
+    }
+
+    pub fn set_tty(&mut self, tty: Arc<TtyCore>) {
+        self.tty = Some(tty);
+    }
+
     /// 从 pcb 的 siginfo中取出下一个要处理的信号,先处理线程信号,再处理进程信号
     ///
     /// ## 参数
@@ -1351,6 +1362,7 @@ impl Default for ProcessSignalInfo {
             sig_block: SigSet::empty(),
             sig_pending: SigPending::default(),
             sig_shared_pending: SigPending::default(),
+            tty: None,
         }
     }
 }

+ 19 - 0
kernel/src/syscall/mod.rs

@@ -12,6 +12,7 @@ use crate::{
     process::{
         fork::KernelCloneArgs,
         resource::{RLimit64, RUsage},
+        ProcessManager,
     },
 };
 
@@ -853,6 +854,11 @@ impl Syscall {
                 Ok(0)
             }
 
+            SYS_SETPGID => {
+                kwarn!("SYS_SETPGID has not yet been implemented");
+                Ok(0)
+            }
+
             SYS_RT_SIGPROCMASK => {
                 kwarn!("SYS_RT_SIGPROCMASK has not yet been implemented");
                 Ok(0)
@@ -1009,6 +1015,19 @@ impl Syscall {
                 Err(SystemError::ENOSYS)
             }
 
+            #[cfg(target_arch = "x86_64")]
+            SYS_GETRLIMIT => {
+                let resource = args[0];
+                let rlimit = args[1] as *mut RLimit64;
+
+                Self::prlimit64(
+                    ProcessManager::current_pcb().pid(),
+                    resource,
+                    0 as *const RLimit64,
+                    rlimit,
+                )
+            }
+
             SYS_SCHED_YIELD => Self::sched_yield(),
 
             _ => panic!("Unsupported syscall ID: {}", syscall_num),

+ 6 - 1
kernel/src/virt/kvm/kvm_dev.rs

@@ -128,7 +128,12 @@ impl IndexNode for LockedKvmInode {
     ///
     /// @return 成功:Ok()
     ///         失败:Err(错误码)
-    fn ioctl(&self, cmd: u32, data: usize) -> Result<usize, SystemError> {
+    fn ioctl(
+        &self,
+        cmd: u32,
+        data: usize,
+        _private_data: &FilePrivateData,
+    ) -> Result<usize, SystemError> {
         match cmd {
             0xdeadbeef => {
                 kdebug!("kvm ioctl");

+ 6 - 1
kernel/src/virt/kvm/vcpu_dev.rs

@@ -136,7 +136,12 @@ impl IndexNode for LockedVcpuInode {
     ///
     /// @return 成功:Ok()
     ///         失败:Err(错误码)
-    fn ioctl(&self, cmd: u32, data: usize) -> Result<usize, SystemError> {
+    fn ioctl(
+        &self,
+        cmd: u32,
+        data: usize,
+        _private_data: &FilePrivateData,
+    ) -> Result<usize, SystemError> {
         match cmd {
             0xdeadbeef => {
                 kdebug!("kvm_cpu ioctl");

+ 6 - 1
kernel/src/virt/kvm/vm_dev.rs

@@ -134,7 +134,12 @@ impl IndexNode for LockedVmInode {
     ///
     /// @return 成功:Ok()
     ///         失败:Err(错误码)
-    fn ioctl(&self, cmd: u32, data: usize) -> Result<usize, SystemError> {
+    fn ioctl(
+        &self,
+        cmd: u32,
+        data: usize,
+        _private_data: &FilePrivateData,
+    ) -> Result<usize, SystemError> {
         match cmd {
             0xdeadbeef => {
                 kdebug!("kvm_vm ioctl");

+ 3 - 0
user/apps/clear/.gitignore

@@ -0,0 +1,3 @@
+/target
+Cargo.lock
+/install/

+ 10 - 0
user/apps/clear/Cargo.toml

@@ -0,0 +1,10 @@
+[package]
+name = "clear"
+version = "0.1.0"
+edition = "2021"
+description = "clear screen"
+authors = [ "GnoCiYeH <[email protected]>" ]
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]

+ 56 - 0
user/apps/clear/Makefile

@@ -0,0 +1,56 @@
+TOOLCHAIN="+nightly-2023-08-15-x86_64-unknown-linux-gnu"
+# RUSTFLAGS+="-C target-feature=+crt-static -C link-arg=-no-pie"
+
+ifdef DADK_CURRENT_BUILD_DIR
+# 如果是在dadk中编译,那么安装到dadk的安装目录中
+	INSTALL_DIR = $(DADK_CURRENT_BUILD_DIR)
+else
+# 如果是在本地编译,那么安装到当前目录下的install目录中
+	INSTALL_DIR = ./install
+endif
+
+ifeq ($(ARCH), x86_64)
+	export RUST_TARGET=x86_64-unknown-linux-musl
+else ifeq ($(ARCH), riscv64)
+	export RUST_TARGET=riscv64gc-unknown-linux-gnu
+else 
+# 默认为x86_86,用于本地编译
+	export RUST_TARGET=x86_64-unknown-linux-musl
+endif
+
+run:
+	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) run --target $(RUST_TARGET)
+
+build:
+	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) build --target $(RUST_TARGET)
+
+clean:
+	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) clean --target $(RUST_TARGET)
+
+test:
+	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) test --target $(RUST_TARGET)
+
+doc:
+	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) doc --target $(RUST_TARGET)
+
+fmt:
+	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) fmt
+
+fmt-check:
+	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) fmt --check
+
+run-release:
+	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) run --target $(RUST_TARGET) --release
+
+build-release:
+	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) build --target $(RUST_TARGET) --release
+
+clean-release:
+	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) clean --target $(RUST_TARGET) --release
+
+test-release:
+	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) test --target $(RUST_TARGET) --release
+
+.PHONY: install
+install:
+	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) install --target $(RUST_TARGET) --path . --no-track --root $(INSTALL_DIR) --force

+ 7 - 0
user/apps/clear/README.md

@@ -0,0 +1,7 @@
+# DragonOS Tty Clear
+
+清屏程序:clear指令
+
+## 使用方法
+
+1. 直接运行`clear`即可

+ 3 - 0
user/apps/clear/src/main.rs

@@ -0,0 +1,3 @@
+fn main() {
+    println!("\x1Bc");
+}

+ 22 - 0
user/dadk/config/clear-0.1.0.dadk

@@ -0,0 +1,22 @@
+{
+  "name": "clear",
+  "version": "0.1.0",
+  "description": "清屏",
+  "task_type": {
+    "BuildFromSource": {
+      "Local": {
+        "path": "apps/clear"
+      }
+    }
+  },
+  "depends": [],
+  "build": {
+    "build_command": "make install"
+  },
+  "clean": {
+    "clean_command": "make clean"
+  },
+  "install": {
+    "in_dragonos_path": "/"
+  }
+}