Browse Source

feat: 添加serial console,支持non-graphic启动 (#947)

Signed-off-by: longjin <[email protected]>
LoGin 5 months ago
parent
commit
d031d46fd9

+ 5 - 0
Makefile

@@ -91,6 +91,11 @@ write_diskimage-uefi:
 # 不编译,直接启动QEMU
 qemu:
 	sh -c "cd tools && bash run-qemu.sh --bios=legacy --display=window && cd .."
+
+# 不编译,直接启动QEMU,不显示图像
+qemu-nographic:
+	sh -c "cd tools && bash run-qemu.sh --bios=legacy --display=nographic && cd .."
+
 # 不编译,直接启动QEMU(UEFI)
 qemu-uefi:
 	sh -c "cd tools && bash run-qemu.sh --bios=uefi --display=window && cd .."

+ 1 - 0
docs/introduction/build_system.md

@@ -242,6 +242,7 @@ make run-docker
 - Docker编译,并写入磁盘镜像,: `make docker`
 - Docker编译,写入磁盘镜像,并在QEMU中运行: `make run-docker`
 - 不编译,直接从已有的磁盘镜像启动: `make qemu`
+- 不编译,直接从已有的磁盘镜像启动(无图形模式): `make qemu-nographic`
 - 清理编译产生的文件: `make clean`
 - 编译文档: `make docs` (需要手动安装sphinx以及docs下的`requirements.txt`中的依赖)
 - 清理文档: `make clean-docs`

+ 1 - 1
kernel/src/arch/x86_64/driver/apic/ioapic.rs

@@ -403,7 +403,7 @@ pub fn ioapic_init(ignore: &'static [IrqNumber]) {
     }
 
     // 绑定irqchip
-    for i in 32..256 {
+    for i in IoApic::VECTOR_BASE as u32..256 {
         let irq = IrqNumber::new(i);
 
         if ignore.contains(&irq) {

+ 0 - 1
kernel/src/arch/x86_64/interrupt/entry.rs

@@ -58,7 +58,6 @@ macro_rules! interrupt_handler {
                         push rax
                         mov rsi, {irqnum}
                         jmp x86_64_do_irq
-                        // jmp do_IRQ
                         "
                     ),
                     irqnum = const($name),

+ 34 - 4
kernel/src/driver/serial/mod.rs

@@ -3,22 +3,27 @@ use core::{fmt::Debug, sync::atomic::AtomicU32};
 use alloc::sync::Arc;
 use system_error::SystemError;
 
-use crate::{driver::base::device::device_number::DeviceNumber, mm::VirtAddr};
+use crate::mm::VirtAddr;
 
 use self::serial8250::serial8250_manager;
 
+use super::tty::{
+    termios::{ControlMode, InputMode, LocalMode, OutputMode, Termios, INIT_CONTORL_CHARACTERS},
+    tty_ldisc::LineDisciplineType,
+};
+
 pub mod serial8250;
 
 #[allow(dead_code)]
 pub trait UartDriver: Debug + Send + Sync {
-    fn device_number(&self) -> DeviceNumber;
-
     /// 获取最大的设备数量
     fn max_devs_num(&self) -> i32;
 
     // todo: 获取指向console的指针(在我们系统里面,将来可能是改进后的Textui Window)
 }
 
+pub const SERIAL_BAUDRATE: BaudRate = BaudRate::new(115200);
+
 /// 串口端口应当实现的trait
 ///
 /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/serial_core.h#428
@@ -43,16 +48,41 @@ pub trait UartPort {
 int_like!(BaudRate, AtomicBaudRate, u32, AtomicU32);
 int_like!(DivisorFraction, u32);
 
+lazy_static! {
+    pub static ref TTY_SERIAL_DEFAULT_TERMIOS: Termios = {
+        Termios {
+            input_mode: InputMode::ICRNL | InputMode::IXON | InputMode::IUTF8,
+            output_mode: OutputMode::OPOST | OutputMode::ONLCR,
+            control_mode: ControlMode::B115200
+                | 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,
+            line: LineDisciplineType::NTty,
+            input_speed: SERIAL_BAUDRATE.data(),
+            output_speed: SERIAL_BAUDRATE.data(),
+        }
+    };
+}
+
 #[inline(always)]
 #[allow(dead_code)]
 pub(super) fn uart_manager() -> &'static UartManager {
     &UartManager
 }
-
 #[derive(Debug)]
 pub(super) struct UartManager;
 
 impl UartManager {
+    pub const NR_TTY_SERIAL_MAX: u32 = 128;
     /// todo: 把uart设备注册到tty层
     ///
     /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/tty/serial/serial_core.c?fi=uart_register_driver#2720

+ 54 - 18
kernel/src/driver/serial/serial8250/mod.rs

@@ -12,27 +12,35 @@ use log::error;
 use system_error::SystemError;
 
 use crate::{
-    driver::base::{
-        class::Class,
-        device::{
-            bus::Bus, device_manager, device_number::DeviceNumber, driver::Driver, Device,
-            DeviceCommonData, DeviceKObjType, DeviceState, DeviceType, IdTable,
-        },
-        kobject::{KObjType, KObject, KObjectCommonData, 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::Major, driver::Driver, Device,
+                DeviceCommonData, DeviceKObjType, DeviceState, DeviceType, IdTable,
+            },
+            kobject::{KObjType, KObject, KObjectCommonData, KObjectState, LockedKObjectState},
+            kset::KSet,
+            platform::{
+                platform_device::{platform_device_manager, PlatformDevice},
+                platform_driver::{platform_driver_manager, PlatformDriver},
+            },
         },
+        tty::tty_driver::{TtyDriver, TtyDriverManager, TtyDriverType},
     },
     filesystem::kernfs::KernFSInode,
     libs::rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard},
 };
 
-use self::serial8250_pio::{send_to_serial8250_pio_com1, serial8250_pio_port_early_init};
+#[cfg(target_arch = "x86_64")]
+use self::serial8250_pio::{
+    send_to_default_serial8250_pio_port, serial8250_pio_port_early_init,
+    serial_8250_pio_register_tty_devices, Serial8250PIOTtyDriverInner,
+};
 
-use super::{uart_manager, UartDriver, UartPort};
+use super::{uart_manager, UartDriver, UartManager, UartPort, TTY_SERIAL_DEFAULT_TERMIOS};
 
+#[cfg(target_arch = "x86_64")]
 mod serial8250_pio;
 
 static mut SERIAL8250_ISA_DEVICES: Option<Arc<Serial8250ISADevices>> = None;
@@ -62,6 +70,8 @@ static mut INITIALIZED: bool = false;
 pub(super) struct Serial8250Manager;
 
 impl Serial8250Manager {
+    pub const TTY_SERIAL_MINOR_START: u32 = 64;
+
     /// 初始化串口设备(在内存管理初始化之前)
     pub fn early_init(&self) -> Result<(), SystemError> {
         // todo: riscv64: 串口设备初始化
@@ -109,6 +119,7 @@ impl Serial8250Manager {
                 return e;
             })?;
 
+        self.serial_tty_init()?;
         unsafe {
             INITIALIZED = true;
         }
@@ -116,6 +127,34 @@ impl Serial8250Manager {
         return Ok(());
     }
 
+    #[cfg(target_arch = "riscv64")]
+    fn serial_tty_init(&self) -> Result<(), SystemError> {
+        Ok(())
+    }
+
+    #[cfg(target_arch = "x86_64")]
+    fn serial_tty_init(&self) -> Result<(), SystemError> {
+        let serial8250_tty_driver = TtyDriver::new(
+            UartManager::NR_TTY_SERIAL_MAX,
+            "ttyS",
+            0,
+            Major::TTY_MAJOR,
+            Self::TTY_SERIAL_MINOR_START,
+            TtyDriverType::Serial,
+            *TTY_SERIAL_DEFAULT_TERMIOS,
+            Arc::new(Serial8250PIOTtyDriverInner::new()),
+            None,
+        );
+
+        TtyDriverManager::tty_register_driver(serial8250_tty_driver)?;
+        if let Err(e) = serial_8250_pio_register_tty_devices() {
+            if e != SystemError::ENODEV {
+                return Err(e);
+            }
+        }
+        Ok(())
+    }
+
     /// 把uart端口与uart driver、uart device绑定
     ///
     /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/tty/serial/8250/8250_core.c?r=&mo=30224&fi=1169#553
@@ -124,6 +163,7 @@ impl Serial8250Manager {
         uart_driver: &Arc<Serial8250ISADriver>,
         devs: &Arc<Serial8250ISADevices>,
     ) {
+        #[cfg(target_arch = "x86_64")]
         self.bind_pio_ports(uart_driver, devs);
     }
 
@@ -394,10 +434,6 @@ impl Serial8250ISADriver {
 }
 
 impl UartDriver for Serial8250ISADriver {
-    fn device_number(&self) -> DeviceNumber {
-        todo!()
-    }
-
     fn max_devs_num(&self) -> i32 {
         todo!()
     }
@@ -522,7 +558,7 @@ impl KObject for Serial8250ISADriver {
 /// 临时函数,用于向默认的串口发送数据
 pub fn send_to_default_serial8250_port(s: &[u8]) {
     #[cfg(target_arch = "x86_64")]
-    send_to_serial8250_pio_com1(s);
+    send_to_default_serial8250_pio_port(s);
 
     #[cfg(target_arch = "riscv64")]
     {

+ 185 - 16
kernel/src/driver/serial/serial8250/serial8250_pio.rs

@@ -5,11 +5,33 @@ use core::{
     sync::atomic::{AtomicBool, Ordering},
 };
 
-use alloc::sync::{Arc, Weak};
+use alloc::{
+    string::ToString,
+    sync::{Arc, Weak},
+};
 
 use crate::{
-    arch::{io::PortIOArch, CurrentPortIOArch},
-    driver::serial::{AtomicBaudRate, BaudRate, DivisorFraction, UartPort},
+    arch::{driver::apic::ioapic::IoApic, io::PortIOArch, CurrentPortIOArch},
+    driver::{
+        base::device::{
+            device_number::{DeviceNumber, Major},
+            DeviceId,
+        },
+        serial::{AtomicBaudRate, BaudRate, DivisorFraction, UartPort},
+        tty::{
+            kthread::send_to_tty_refresh_thread,
+            termios::WindowSize,
+            tty_core::{TtyCore, TtyCoreData},
+            tty_driver::{TtyDriver, TtyDriverManager, TtyOperation},
+            virtual_terminal::{vc_manager, VirtConsole},
+        },
+    },
+    exception::{
+        irqdata::IrqHandlerData,
+        irqdesc::{IrqHandleFlags, IrqHandler, IrqReturn},
+        manage::irq_manager,
+        IrqNumber,
+    },
     libs::rwlock::RwLock,
 };
 use system_error::SystemError;
@@ -19,6 +41,8 @@ use super::{Serial8250ISADevices, Serial8250ISADriver, Serial8250Manager, Serial
 static mut PIO_PORTS: [Option<Serial8250PIOPort>; 8] =
     [None, None, None, None, None, None, None, None];
 
+const SERIAL_8250_PIO_IRQ: IrqNumber = IrqNumber::new(IoApic::VECTOR_BASE as u32 + 4);
+
 impl Serial8250Manager {
     #[allow(static_mut_refs)]
     pub(super) fn bind_pio_ports(
@@ -34,7 +58,7 @@ impl Serial8250Manager {
 }
 
 macro_rules! init_port {
-    ($port_num:expr, $baudrate:expr) => {
+    ($port_num:expr) => {
         unsafe {
             let port = Serial8250PIOPort::new(
                 match $port_num {
@@ -48,12 +72,17 @@ macro_rules! init_port {
                     8 => Serial8250PortBase::COM8,
                     _ => panic!("invalid port number"),
                 },
-                BaudRate::new($baudrate),
+                crate::driver::serial::SERIAL_BAUDRATE,
             );
             if let Ok(port) = port {
                 if port.init().is_ok() {
                     PIO_PORTS[$port_num - 1] = Some(port);
+                    true
+                } else {
+                    false
                 }
+            } else {
+                false
             }
         }
     };
@@ -62,8 +91,9 @@ macro_rules! init_port {
 /// 在内存管理初始化之前,初始化串口设备
 pub(super) fn serial8250_pio_port_early_init() -> Result<(), SystemError> {
     for i in 1..=8 {
-        init_port!(i, 115200);
+        init_port!(i);
     }
+
     return Ok(());
 }
 
@@ -100,7 +130,6 @@ impl Serial8250PIOPort {
         }
 
         let port = self.iobase as u16;
-
         unsafe {
             CurrentPortIOArch::out8(port + 1, 0x00); // Disable all interrupts
             self.set_divisor(self.baudrate.load(Ordering::SeqCst))
@@ -119,7 +148,9 @@ impl Serial8250PIOPort {
 
             // If serial is not faulty set it in normal operation mode
             // (not-loopback with IRQs enabled and OUT#1 and OUT#2 bits enabled)
-            CurrentPortIOArch::out8(port + 4, 0x08);
+            CurrentPortIOArch::out8(port + 4, 0x0b);
+
+            CurrentPortIOArch::out8(port + 1, 0x01); // Enable interrupts
         }
 
         return Ok(());
@@ -168,13 +199,12 @@ impl Serial8250PIOPort {
         }
     }
 
-    /// 读取一个字节
-    #[allow(dead_code)]
-    fn read_one_byte(&self) -> u8 {
-        while !self.serial_received() {
-            spin_loop();
+    /// 读取一个字节,如果没有数据则返回None
+    fn read_one_byte(&self) -> Option<u8> {
+        if !self.serial_received() {
+            return None;
         }
-        return self.serial_in(0) as u8;
+        return Some(self.serial_in(0) as u8);
     }
 }
 
@@ -235,7 +265,14 @@ impl UartPort for Serial8250PIOPort {
     }
 
     fn handle_irq(&self) -> Result<(), SystemError> {
-        todo!("serial8250_pio::handle_irq")
+        if let Some(c) = self.read_one_byte() {
+            send_to_tty_refresh_thread(&[c]);
+        }
+        Ok(())
+    }
+
+    fn iobase(&self) -> Option<usize> {
+        Some(self.iobase as usize)
     }
 }
 
@@ -280,8 +317,140 @@ pub enum Serial8250PortBase {
 }
 
 /// 临时函数,用于向COM1发送数据
-pub fn send_to_serial8250_pio_com1(s: &[u8]) {
+pub fn send_to_default_serial8250_pio_port(s: &[u8]) {
     if let Some(port) = unsafe { PIO_PORTS[0].as_ref() } {
         port.send_bytes(s);
     }
 }
+
+#[derive(Debug)]
+pub(super) struct Serial8250PIOTtyDriverInner;
+
+impl Serial8250PIOTtyDriverInner {
+    pub fn new() -> Self {
+        Self
+    }
+
+    fn do_install(
+        &self,
+        driver: Arc<TtyDriver>,
+        tty: Arc<TtyCore>,
+        vc: Arc<VirtConsole>,
+    ) -> Result<(), SystemError> {
+        driver.standard_install(tty.clone())?;
+        vc.port().setup_internal_tty(Arc::downgrade(&tty));
+        tty.set_port(vc.port());
+        vc.devfs_setup()?;
+
+        Ok(())
+    }
+}
+
+impl TtyOperation for Serial8250PIOTtyDriverInner {
+    fn open(&self, _tty: &TtyCoreData) -> Result<(), SystemError> {
+        Ok(())
+    }
+
+    fn write(&self, tty: &TtyCoreData, buf: &[u8], nr: usize) -> Result<usize, SystemError> {
+        let index = tty.index();
+        if tty.index() >= unsafe { PIO_PORTS.len() } {
+            return Err(SystemError::ENODEV);
+        }
+        let pio_port = unsafe { PIO_PORTS[index].as_ref() }.ok_or(SystemError::ENODEV)?;
+        pio_port.send_bytes(&buf[..nr]);
+
+        Ok(nr)
+    }
+
+    fn flush_chars(&self, _tty: &TtyCoreData) {}
+
+    fn put_char(&self, tty: &TtyCoreData, ch: u8) -> Result<(), SystemError> {
+        self.write(tty, &[ch], 1).map(|_| ())
+    }
+
+    fn ioctl(&self, _tty: Arc<TtyCore>, _cmd: u32, _arg: usize) -> Result<(), SystemError> {
+        Err(SystemError::ENOIOCTLCMD)
+    }
+
+    fn close(&self, _tty: Arc<TtyCore>) -> Result<(), SystemError> {
+        Ok(())
+    }
+
+    fn resize(&self, tty: Arc<TtyCore>, winsize: WindowSize) -> Result<(), SystemError> {
+        *tty.core().window_size_write() = winsize;
+        Ok(())
+    }
+
+    fn install(&self, driver: Arc<TtyDriver>, tty: Arc<TtyCore>) -> Result<(), SystemError> {
+        if tty.core().index() >= unsafe { PIO_PORTS.len() } {
+            return Err(SystemError::ENODEV);
+        }
+        let vc = VirtConsole::new(None);
+        let vc_index = vc_manager().alloc(vc.clone()).ok_or(SystemError::EBUSY)?;
+        self.do_install(driver, tty, vc.clone()).inspect_err(|_| {
+            vc_manager().free(vc_index);
+        })?;
+
+        Ok(())
+    }
+}
+
+pub(super) fn serial_8250_pio_register_tty_devices() -> Result<(), SystemError> {
+    let (_, driver) = TtyDriverManager::lookup_tty_driver(DeviceNumber::new(
+        Major::TTY_MAJOR,
+        Serial8250Manager::TTY_SERIAL_MINOR_START,
+    ))
+    .ok_or(SystemError::ENODEV)?;
+
+    for (i, port) in unsafe { PIO_PORTS.iter() }.enumerate() {
+        if let Some(port) = port {
+            let core = driver.init_tty_device(Some(i)).inspect_err(|_| {
+                log::error!(
+                    "failed to init tty device for serial 8250 pio port {}, port iobase: {:?}",
+                    i,
+                    port.iobase
+                );
+            })?;
+            core.resize( core.clone(), WindowSize::DEFAULT)
+                .inspect_err(|_| {
+                    log::error!(
+                        "failed to resize tty device for serial 8250 pio port {}, port iobase: {:?}",
+                        i,
+                        port.iobase
+                    );
+                })?;
+        }
+    }
+
+    irq_manager()
+        .request_irq(
+            SERIAL_8250_PIO_IRQ,
+            "serial8250_pio".to_string(),
+            &Serial8250IrqHandler,
+            IrqHandleFlags::IRQF_SHARED | IrqHandleFlags::IRQF_TRIGGER_RISING,
+            Some(DeviceId::new(Some("serial8250_pio"), None).unwrap()),
+        )
+        .inspect_err(|e| {
+            log::error!("failed to request irq for serial 8250 pio: {:?}", e);
+        })?;
+
+    Ok(())
+}
+
+#[derive(Debug)]
+struct Serial8250IrqHandler;
+
+impl IrqHandler for Serial8250IrqHandler {
+    fn handle(
+        &self,
+        _irq: IrqNumber,
+        _static_data: Option<&dyn IrqHandlerData>,
+        _dynamic_data: Option<Arc<dyn IrqHandlerData>>,
+    ) -> Result<IrqReturn, SystemError> {
+        for port in unsafe { PIO_PORTS.iter() }.flatten() {
+            port.handle_irq()?;
+        }
+
+        Ok(IrqReturn::Handled)
+    }
+}

+ 10 - 3
kernel/src/driver/tty/console.rs

@@ -1,13 +1,20 @@
+use alloc::sync::Arc;
 use system_error::SystemError;
 
-use super::virtual_terminal::virtual_console::{
-    CursorOperation, ScrollDir, VirtualConsoleData, VirtualConsoleIntensity,
+use super::virtual_terminal::{
+    virtual_console::{CursorOperation, ScrollDir, VirtualConsoleData, VirtualConsoleIntensity},
+    VirtConsole,
 };
 
 /// 终端切换相关的回调
 pub trait ConsoleSwitch: Sync + Send {
     /// 初始化,会对vc_data进行一系列初始化操作
-    fn con_init(&self, vc_data: &mut VirtualConsoleData, init: bool) -> Result<(), SystemError>;
+    fn con_init(
+        &self,
+        vc: &Arc<VirtConsole>,
+        vc_data: &mut VirtualConsoleData,
+        init: bool,
+    ) -> Result<(), SystemError>;
 
     /// 进行释放等系列操作,目前未使用
     #[allow(dead_code)]

+ 5 - 5
kernel/src/driver/tty/kthread.rs

@@ -5,7 +5,7 @@ use kdepends::thingbuf::StaticThingBuf;
 
 use crate::{
     arch::CurrentIrqArch,
-    driver::tty::virtual_terminal::virtual_console::CURRENT_VCNUM,
+    driver::tty::virtual_terminal::vc_manager,
     exception::InterruptArch,
     process::{
         kthread::{KernelThreadClosure, KernelThreadMechanism},
@@ -14,8 +14,6 @@ use crate::{
     sched::{schedule, SchedMode},
 };
 
-use super::tty_port::current_tty_port;
-
 /// 用于缓存键盘输入的缓冲区
 static KEYBUF: StaticThingBuf<u8, 512> = StaticThingBuf::new();
 
@@ -51,8 +49,10 @@ fn tty_refresh_thread() -> i32 {
             *item = KEYBUF.pop().unwrap();
         }
 
-        if CURRENT_VCNUM.load(core::sync::atomic::Ordering::SeqCst) != -1 {
-            let _ = current_tty_port().receive_buf(&data[0..to_dequeue], &[], to_dequeue);
+        if let Some(cur_vc) = vc_manager().current_vc() {
+            let _ = cur_vc
+                .port()
+                .receive_buf(&data[0..to_dequeue], &[], to_dequeue);
         } else {
             // 这里由于stdio未初始化,所以无法找到port
             // TODO: 考虑改用双端队列,能够将丢失的输入插回

+ 2 - 0
kernel/src/driver/tty/pty/mod.rs

@@ -253,6 +253,7 @@ pub fn pty_init() -> Result<(), SystemError> {
         TtyDriverType::Pty,
         *TTY_STD_TERMIOS,
         Arc::new(Unix98PtyDriverInner::new()),
+        None,
     );
     ptm_driver.set_subtype(TtyDriverSubType::PtyMaster);
     let term = ptm_driver.init_termios_mut();
@@ -273,6 +274,7 @@ pub fn pty_init() -> Result<(), SystemError> {
         TtyDriverType::Pty,
         *TTY_STD_TERMIOS,
         Arc::new(Unix98PtyDriverInner::new()),
+        None,
     );
     pts_driver.set_subtype(TtyDriverSubType::PtySlave);
     let term = pts_driver.init_termios_mut();

+ 1 - 1
kernel/src/driver/tty/pty/unix98pty.rs

@@ -263,7 +263,7 @@ pub fn ptmx_open(
 
     let index = fsinfo.alloc_index()?;
 
-    let tty = TtyDriver::init_tty_device(ptm_driver(), index)?;
+    let tty = ptm_driver().init_tty_device(Some(index))?;
 
     // 设置privdata
     *data = FilePrivateData::Tty(TtyFilePrivateData {

+ 9 - 3
kernel/src/driver/tty/termios.rs

@@ -2,7 +2,7 @@ use super::tty_ldisc::LineDisciplineType;
 
 /// ## 窗口大小
 #[repr(C)]
-#[derive(Debug, Default, Clone, Copy, PartialEq)]
+#[derive(Debug, Clone, Copy, PartialEq)]
 pub struct WindowSize {
     /// 行
     pub row: u16,
@@ -15,7 +15,8 @@ pub struct WindowSize {
 }
 
 impl WindowSize {
-    pub fn new(row: u16, col: u16, xpixel: u16, ypixel: u16) -> Self {
+    pub const DEFAULT: WindowSize = WindowSize::new(24, 80, 1, 1);
+    pub const fn new(row: u16, col: u16, xpixel: u16, ypixel: u16) -> Self {
         Self {
             row,
             col,
@@ -25,6 +26,12 @@ impl WindowSize {
     }
 }
 
+impl Default for WindowSize {
+    fn default() -> Self {
+        Self::DEFAULT
+    }
+}
+
 #[derive(Debug, Clone, Copy)]
 pub struct Termios {
     pub input_mode: InputMode,
@@ -63,7 +70,6 @@ impl PosixTermios {
         }
     }
 
-    #[allow(dead_code)]
     pub fn to_kernel_termios(self) -> Termios {
         // TODO:这里没有考虑非规范模式
         Termios {

+ 46 - 12
kernel/src/driver/tty/tty_core.rs

@@ -11,7 +11,7 @@ use alloc::{
 use system_error::SystemError;
 
 use crate::{
-    driver::{serial::serial8250::send_to_default_serial8250_port, tty::pty::ptm_driver},
+    driver::{base::device::device_number::DeviceNumber, tty::pty::ptm_driver},
     libs::{
         rwlock::{RwLock, RwLockReadGuard, RwLockUpgradableGuard, RwLockWriteGuard},
         spinlock::{SpinLock, SpinLockGuard},
@@ -25,13 +25,13 @@ use crate::{
 
 use super::{
     termios::{ControlMode, PosixTermios, Termios, TtySetTermiosOpt, WindowSize},
-    tty_driver::{TtyDriver, TtyDriverSubType, TtyDriverType, TtyOperation},
+    tty_driver::{TtyCorePrivateField, TtyDriver, TtyDriverSubType, TtyDriverType, TtyOperation},
     tty_ldisc::{
         ntty::{NTtyData, NTtyLinediscipline},
         TtyLineDiscipline,
     },
     tty_port::TtyPort,
-    virtual_terminal::{virtual_console::VirtualConsoleData, VIRT_CONSOLES},
+    virtual_terminal::{vc_manager, virtual_console::VirtualConsoleData},
 };
 
 #[derive(Debug)]
@@ -52,6 +52,9 @@ impl Drop for TtyCore {
 impl TtyCore {
     pub fn new(driver: Arc<TtyDriver>, index: usize) -> Arc<Self> {
         let name = driver.tty_line_name(index);
+        let device_number = driver
+            .device_number(index)
+            .expect("Get tty device number failed.");
         let termios = driver.init_termios();
         let core = TtyCoreData {
             tty_driver: driver,
@@ -64,11 +67,14 @@ impl TtyCore {
             write_wq: EventWaitQueue::new(),
             port: RwLock::new(None),
             index,
+            vc_index: AtomicUsize::new(usize::MAX),
             ctrl: SpinLock::new(TtyContorlInfo::default()),
             closing: AtomicBool::new(false),
             flow: SpinLock::new(TtyFlowState::default()),
             link: RwLock::default(),
             epitems: SpinLock::new(LinkedList::new()),
+            device_number,
+            privete_fields: SpinLock::new(None),
         };
 
         return Arc::new(Self {
@@ -84,6 +90,14 @@ impl TtyCore {
         return &self.core;
     }
 
+    pub fn private_fields(&self) -> Option<Arc<dyn TtyCorePrivateField>> {
+        self.core.privete_fields.lock().clone()
+    }
+
+    pub fn set_private_fields(&self, fields: Arc<dyn TtyCorePrivateField>) {
+        *self.core.privete_fields.lock() = Some(fields);
+    }
+
     #[inline]
     pub fn ldisc(&self) -> Arc<dyn TtyLineDiscipline> {
         self.line_discipline.clone()
@@ -231,7 +245,7 @@ impl TtyCore {
         Ok(0)
     }
 
-    pub fn set_termios_next(tty: Arc<TtyCore>, new_termios: Termios) -> Result<(), SystemError> {
+    fn set_termios_next(tty: Arc<TtyCore>, new_termios: Termios) -> Result<(), SystemError> {
         let mut termios = tty.core().termios_write();
 
         let old_termios = *termios;
@@ -252,7 +266,7 @@ impl TtyCore {
 
         drop(termios);
         let ld = tty.ldisc();
-        ld.set_termios(tty, Some(old_termios))?;
+        ld.set_termios(tty, Some(old_termios)).ok();
 
         Ok(())
     }
@@ -292,6 +306,7 @@ pub struct TtyCoreData {
     flags: RwLock<TtyFlag>,
     /// 在初始化时即确定不会更改,所以这里不用加锁
     index: usize,
+    vc_index: AtomicUsize,
     count: AtomicUsize,
     /// 窗口大小
     window_size: RwLock<WindowSize>,
@@ -311,12 +326,16 @@ pub struct TtyCoreData {
     link: RwLock<Weak<TtyCore>>,
     /// epitems
     epitems: SpinLock<LinkedList<Arc<EPollItem>>>,
+    /// 设备号
+    device_number: DeviceNumber,
+
+    privete_fields: SpinLock<Option<Arc<dyn TtyCorePrivateField>>>,
 }
 
 impl TtyCoreData {
     #[inline]
-    pub fn driver(&self) -> Arc<TtyDriver> {
-        self.tty_driver.clone()
+    pub fn driver(&self) -> &Arc<TtyDriver> {
+        &self.tty_driver
     }
 
     #[inline]
@@ -335,8 +354,12 @@ impl TtyCoreData {
     }
 
     #[inline]
-    pub fn name(&self) -> String {
-        self.name.clone()
+    pub fn name(&self) -> &String {
+        &self.name
+    }
+
+    pub fn device_number(&self) -> &DeviceNumber {
+        &self.device_number
     }
 
     #[inline]
@@ -412,8 +435,20 @@ impl TtyCoreData {
     }
 
     #[inline]
-    pub fn vc_data_irqsave(&self) -> SpinLockGuard<VirtualConsoleData> {
-        VIRT_CONSOLES[self.index].lock_irqsave()
+    pub fn vc_data(&self) -> Option<Arc<SpinLock<VirtualConsoleData>>> {
+        vc_manager().get(self.vc_index()?).unwrap().vc_data()
+    }
+
+    pub fn set_vc_index(&self, index: usize) {
+        self.vc_index.store(index, Ordering::SeqCst);
+    }
+
+    pub fn vc_index(&self) -> Option<usize> {
+        let x = self.vc_index.load(Ordering::SeqCst);
+        if x == usize::MAX {
+            return None;
+        }
+        return Some(x);
     }
 
     #[inline]
@@ -469,7 +504,6 @@ impl TtyOperation for TtyCore {
 
     #[inline]
     fn write(&self, tty: &TtyCoreData, buf: &[u8], nr: usize) -> Result<usize, SystemError> {
-        send_to_default_serial8250_port(buf);
         return self.core().tty_driver.driver_funcs().write(tty, buf, nr);
     }
 

+ 7 - 38
kernel/src/driver/tty/tty_device.rs

@@ -45,7 +45,7 @@ use super::{
     sysfs::sys_class_tty_instance,
     termios::WindowSize,
     tty_core::{TtyCore, TtyFlag, TtyIoctlCmd},
-    tty_driver::{TtyDriver, TtyDriverManager, TtyDriverSubType, TtyDriverType, TtyOperation},
+    tty_driver::{TtyDriverManager, TtyDriverSubType, TtyDriverType, TtyOperation},
     tty_job_control::TtyJobCtrlManager,
     virtual_terminal::vty_init,
 };
@@ -126,6 +126,10 @@ impl TtyDevice {
     pub fn inner_write(&self) -> RwLockWriteGuard<InnerTtyDevice> {
         self.inner.write()
     }
+
+    pub fn name_ref(&self) -> &str {
+        &self.name
+    }
 }
 
 impl IndexNode for TtyDevice {
@@ -145,7 +149,7 @@ impl IndexNode for TtyDevice {
         let (index, driver) =
             TtyDriverManager::lookup_tty_driver(dev_num).ok_or(SystemError::ENODEV)?;
 
-        let tty = TtyDriver::open_tty(index, driver)?;
+        let tty = driver.open_tty(Some(index))?;
 
         // 设置privdata
         *data = FilePrivateData::Tty(TtyFilePrivateData {
@@ -592,15 +596,6 @@ impl TtyFilePrivateData {
 #[unified_init(INITCALL_DEVICE)]
 #[inline(never)]
 pub fn tty_init() -> Result<(), SystemError> {
-    let tty = TtyDevice::new(
-        "tty0".to_string(),
-        IdTable::new(
-            String::from("tty0"),
-            Some(DeviceNumber::new(Major::TTY_MAJOR, 0)),
-        ),
-        TtyType::Tty,
-    );
-
     let console = TtyDevice::new(
         "console".to_string(),
         IdTable::new(
@@ -610,34 +605,8 @@ pub fn tty_init() -> Result<(), SystemError> {
         TtyType::Tty,
     );
 
-    // 注册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())?;
+    // 将设备注册到devfs,TODO:这里console设备应该与tty在一个设备group里面
     device_register(console.clone())?;
-    devfs_register(&tty.name.clone(), tty)?;
     devfs_register(&console.name.clone(), console)?;
 
     serial_init()?;

+ 84 - 25
kernel/src/driver/tty/tty_driver.rs

@@ -6,6 +6,7 @@ use alloc::{
     vec::Vec,
 };
 use hashbrown::HashMap;
+use ida::IdAllocator;
 use log::warn;
 use system_error::SystemError;
 
@@ -15,13 +16,17 @@ use crate::{
             char::CharDevOps,
             device::{
                 device_number::{DeviceNumber, Major},
+                device_register,
                 driver::Driver,
+                IdTable,
             },
             kobject::KObject,
         },
         tty::tty_port::TtyPortState,
     },
+    filesystem::devfs::devfs_register,
     libs::{
+        lazy_init::Lazy,
         rwlock::RwLock,
         spinlock::{SpinLock, SpinLockGuard},
     },
@@ -30,6 +35,7 @@ use crate::{
 use super::{
     termios::{Termios, WindowSize},
     tty_core::{TtyCore, TtyCoreData},
+    tty_device::TtyDevice,
     tty_ldisc::TtyLdiscManager,
     tty_port::{DefaultTtyPort, TtyPort},
 };
@@ -79,6 +85,7 @@ impl TtyDriverManager {
 
         // 加入全局TtyDriver表
         let driver = Arc::new(driver);
+        driver.self_ref.init(Arc::downgrade(&driver));
         TTY_DRIVERS.lock().push(driver.clone());
 
         // TODO: 加入procfs?
@@ -87,6 +94,10 @@ impl TtyDriverManager {
     }
 }
 
+/// tty 驱动程序的与设备相关的数据
+pub trait TtyDriverPrivateField: Debug + Send + Sync {}
+pub trait TtyCorePrivateField: Debug + Send + Sync {}
+
 #[allow(dead_code)]
 #[derive(Debug)]
 #[cast_to([sync] Driver)]
@@ -121,7 +132,11 @@ pub struct TtyDriver {
     ttys: SpinLock<HashMap<usize, Arc<TtyCore>>>,
     /// 管理的端口列表
     ports: RwLock<Vec<Arc<dyn TtyPort>>>,
-    // procfs入口?
+    /// 与设备相关的私有数据
+    private_field: Option<Arc<dyn TtyDriverPrivateField>>,
+    /// id分配器
+    ida: SpinLock<IdAllocator>,
+    self_ref: Lazy<Weak<Self>>,
 }
 
 impl TtyDriver {
@@ -135,6 +150,7 @@ impl TtyDriver {
         tty_driver_type: TtyDriverType,
         default_termios: Termios,
         driver_funcs: Arc<dyn TtyOperation>,
+        private_field: Option<Arc<dyn TtyDriverPrivateField>>,
     ) -> Self {
         let mut ports: Vec<Arc<dyn TtyPort>> = Vec::with_capacity(count as usize);
         for _ in 0..count {
@@ -156,6 +172,9 @@ impl TtyDriver {
             ttys: SpinLock::new(HashMap::new()),
             saved_termios: Vec::with_capacity(count as usize),
             ports: RwLock::new(ports),
+            private_field,
+            ida: SpinLock::new(IdAllocator::new(0, count as usize).unwrap()),
+            self_ref: Lazy::new(),
         }
     }
 
@@ -179,6 +198,22 @@ impl TtyDriver {
         self.driver_funcs.clone()
     }
 
+    /// ## 获取该驱动对应的设备的设备号
+    #[inline]
+    pub fn device_number(&self, index: usize) -> Option<DeviceNumber> {
+        if index >= self.device_count as usize {
+            return None;
+        }
+        Some(DeviceNumber::new(
+            self.major,
+            self.minor_start + index as u32,
+        ))
+    }
+
+    fn self_ref(&self) -> Arc<Self> {
+        self.self_ref.get().upgrade().unwrap()
+    }
+
     #[inline]
     pub fn init_termios(&self) -> Termios {
         self.init_termios
@@ -230,7 +265,7 @@ impl TtyDriver {
         ret.ok()
     }
 
-    fn standard_install(&self, tty_core: Arc<TtyCore>) -> Result<(), SystemError> {
+    pub fn standard_install(&self, tty_core: Arc<TtyCore>) -> Result<(), SystemError> {
         let tty = tty_core.core();
         tty.init_termios();
         // TODO:设置termios波特率?
@@ -242,59 +277,81 @@ impl TtyDriver {
         Ok(())
     }
 
-    fn driver_install_tty(driver: Arc<TtyDriver>, tty: Arc<TtyCore>) -> Result<(), SystemError> {
-        let res = tty.install(driver.clone(), tty.clone());
+    fn driver_install_tty(&self, tty: Arc<TtyCore>) -> Result<(), SystemError> {
+        let res = tty.install(self.self_ref(), tty.clone());
 
         if let Err(err) = res {
             if err == SystemError::ENOSYS {
-                return driver.standard_install(tty);
+                return self.standard_install(tty);
             } else {
                 return Err(err);
             }
         }
 
-        driver.add_tty(tty);
+        self.add_tty(tty);
 
         Ok(())
     }
 
-    pub fn init_tty_device(
-        driver: Arc<TtyDriver>,
-        index: usize,
-    ) -> Result<Arc<TtyCore>, SystemError> {
-        let tty = TtyCore::new(driver.clone(), index);
+    pub fn init_tty_device(&self, index: Option<usize>) -> Result<Arc<TtyCore>, SystemError> {
+        // 如果传入的index为None,那么就自动分配index
+        let idx: usize;
+        if let Some(i) = index {
+            if self.ida.lock().exists(i) {
+                return Err(SystemError::EINVAL);
+            }
+            idx = i;
+        } else {
+            idx = self.ida.lock().alloc().ok_or(SystemError::EBUSY)?;
+        }
+
+        let tty = TtyCore::new(self.self_ref(), idx);
 
-        Self::driver_install_tty(driver.clone(), tty.clone())?;
+        self.driver_install_tty(tty.clone())?;
 
         let core = tty.core();
 
         if core.port().is_none() {
-            let ports = driver.ports.read();
+            let ports = self.ports.read();
             ports[core.index()].setup_internal_tty(Arc::downgrade(&tty));
             tty.set_port(ports[core.index()].clone());
         }
 
         TtyLdiscManager::ldisc_setup(tty.clone(), tty.core().link())?;
 
+        // 在devfs创建对应的文件
+
+        let device = TtyDevice::new(
+            core.name().clone(),
+            IdTable::new(self.tty_line_name(idx), Some(*core.device_number())),
+            super::tty_device::TtyType::Tty,
+        );
+
+        devfs_register(device.name_ref(), device.clone())?;
+        device_register(device)?;
         Ok(tty)
     }
 
     /// ## 通过设备号找到对应驱动并且初始化Tty
-    pub fn open_tty(index: usize, driver: Arc<TtyDriver>) -> Result<Arc<TtyCore>, SystemError> {
-        let tty = match driver.lookup_tty(index) {
-            Some(tty) => {
-                // TODO: 暂时这么写,因为还没写TtyPort
-                if tty.core().port().is_none() {
-                    warn!("{} port is None", tty.core().name());
-                } else if tty.core().port().unwrap().state() == TtyPortState::KOPENED {
+    pub fn open_tty(&self, index: Option<usize>) -> Result<Arc<TtyCore>, SystemError> {
+        let mut tty: Option<Arc<TtyCore>> = None;
+
+        if index.is_some() {
+            if let Some(t) = self.lookup_tty(index.unwrap()) {
+                if t.core().port().is_none() {
+                    warn!("{} port is None", t.core().name());
+                } else if t.core().port().unwrap().state() == TtyPortState::KOPENED {
                     return Err(SystemError::EBUSY);
                 }
 
-                tty.reopen()?;
-                tty
+                t.reopen()?;
+                tty = Some(t);
             }
-            None => Self::init_tty_device(driver, index)?,
-        };
+        }
+        if tty.is_none() {
+            tty = Some(self.init_tty_device(index)?);
+        }
+        let tty = tty.ok_or(SystemError::ENODEV)?;
 
         return Ok(tty);
     }
@@ -447,7 +504,9 @@ pub trait TtyOperation: Sync + Send + Debug {
 
     fn close(&self, tty: Arc<TtyCore>) -> Result<(), SystemError>;
 
-    fn resize(&self, _tty: Arc<TtyCore>, _winsize: WindowSize) -> Result<(), SystemError>;
+    fn resize(&self, _tty: Arc<TtyCore>, _winsize: WindowSize) -> Result<(), SystemError> {
+        Err(SystemError::ENOSYS)
+    }
 }
 
 #[allow(dead_code)]

+ 2 - 1
kernel/src/driver/tty/tty_ldisc/ntty.rs

@@ -1209,7 +1209,8 @@ impl NTtyData {
                     if termios.output_mode.contains(OutputMode::OCRNL) {
                         break;
                     }
-                    self.canon_cursor_column = self.cursor_column;
+                    self.cursor_column = 0;
+                    self.canon_cursor_column = 0;
                 }
                 '\t' => {
                     break;

+ 2 - 18
kernel/src/driver/tty/tty_port.rs

@@ -1,4 +1,4 @@
-use core::{fmt::Debug, sync::atomic::Ordering};
+use core::fmt::Debug;
 
 use alloc::sync::{Arc, Weak};
 use kdepends::thingbuf::mpsc;
@@ -6,26 +6,10 @@ use system_error::SystemError;
 
 use crate::libs::spinlock::{SpinLock, SpinLockGuard};
 
-use super::{
-    tty_core::TtyCore,
-    virtual_terminal::{virtual_console::CURRENT_VCNUM, VIRT_CONSOLES},
-};
+use super::tty_core::TtyCore;
 
 const TTY_PORT_BUFSIZE: usize = 4096;
 
-/// 获取当前tty port
-#[inline]
-pub fn current_tty_port() -> Arc<dyn TtyPort> {
-    VIRT_CONSOLES[CURRENT_VCNUM.load(Ordering::SeqCst) as usize]
-        .lock_irqsave()
-        .port()
-}
-
-#[inline]
-pub fn tty_port(index: usize) -> Arc<dyn TtyPort> {
-    VIRT_CONSOLES[index].lock_irqsave().port()
-}
-
 #[allow(dead_code)]
 #[derive(Debug)]
 pub struct TtyPortData {

+ 260 - 76
kernel/src/driver/tty/virtual_terminal/mod.rs

@@ -1,22 +1,28 @@
-use core::{fmt::Formatter, sync::atomic::Ordering};
+use core::fmt::Formatter;
 
 use alloc::{
     string::{String, ToString},
     sync::Arc,
-    vec::Vec,
 };
+use hashbrown::HashMap;
+use ida::IdAllocator;
 use system_error::SystemError;
+use unified_init::macros::unified_init;
 
 use crate::{
-    driver::base::device::{
-        device_number::{DeviceNumber, Major},
-        device_register, IdTable,
+    driver::{
+        base::device::{
+            device_number::{DeviceNumber, Major},
+            device_register, IdTable,
+        },
+        serial::serial8250::send_to_default_serial8250_port,
     },
-    filesystem::devfs::devfs_register,
-    libs::spinlock::SpinLock,
+    filesystem::devfs::{devfs_register, devfs_unregister},
+    init::initcall::INITCALL_LATE,
+    libs::{lazy_init::Lazy, rwlock::RwLock, spinlock::SpinLock},
 };
 
-use self::virtual_console::{VirtualConsoleData, CURRENT_VCNUM};
+use self::virtual_console::VirtualConsoleData;
 
 use super::{
     console::ConsoleSwitch,
@@ -24,12 +30,13 @@ use super::{
     tty_core::{TtyCore, TtyCoreData},
     tty_device::{TtyDevice, TtyType},
     tty_driver::{TtyDriver, TtyDriverManager, TtyDriverType, TtyOperation},
+    tty_port::{DefaultTtyPort, TtyPort},
 };
 
 pub mod console_map;
 pub mod virtual_console;
 
-pub const MAX_NR_CONSOLES: u32 = 63;
+pub const MAX_NR_CONSOLES: u32 = 64;
 pub const VC_MAXCOL: usize = 32767;
 pub const VC_MAXROW: usize = 32767;
 
@@ -48,14 +55,190 @@ pub const DEFAULT_BLUE: [u16; 16] = [
 pub const COLOR_TABLE: &[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))));
+    static ref VC_MANAGER: VirtConsoleManager = VirtConsoleManager::new();
+}
+
+/// 获取虚拟终端管理器
+#[inline]
+pub fn vc_manager() -> &'static VirtConsoleManager {
+    &VC_MANAGER
+}
+
+pub struct VirtConsole {
+    vc_data: Option<Arc<SpinLock<VirtualConsoleData>>>,
+    port: Arc<dyn TtyPort>,
+    index: Lazy<usize>,
+    inner: SpinLock<InnerVirtConsole>,
+}
+
+struct InnerVirtConsole {
+    vcdev: Option<Arc<TtyDevice>>,
+}
+
+impl VirtConsole {
+    pub fn new(vc_data: Option<Arc<SpinLock<VirtualConsoleData>>>) -> Arc<Self> {
+        Arc::new(Self {
+            vc_data,
+            port: Arc::new(DefaultTtyPort::new()),
+            index: Lazy::new(),
+            inner: SpinLock::new(InnerVirtConsole { vcdev: None }),
+        })
+    }
+
+    pub fn vc_data(&self) -> Option<Arc<SpinLock<VirtualConsoleData>>> {
+        self.vc_data.clone()
+    }
+
+    pub fn port(&self) -> Arc<dyn TtyPort> {
+        self.port.clone()
+    }
+
+    pub fn index(&self) -> Option<usize> {
+        self.index.try_get().cloned()
+    }
+
+    pub fn devfs_setup(&self) -> Result<(), SystemError> {
+        let tty_core = self
+            .port
+            .port_data()
+            .internal_tty()
+            .ok_or(SystemError::ENODEV)?;
+        let tty_core_data = tty_core.core();
+        let devnum = *tty_core_data.device_number();
+        let vcname = format!("vc{}", self.index.get());
+
+        // 注册虚拟终端设备并将虚拟终端设备加入到文件系统
+        let vcdev = TtyDevice::new(
+            vcname.clone(),
+            IdTable::new(vcname, Some(devnum)),
+            TtyType::Tty,
+        );
+
+        device_register(vcdev.clone())?;
+        devfs_register(vcdev.name_ref(), vcdev.clone())?;
+        tty_core_data.set_vc_index(*self.index.get());
+        self.inner.lock().vcdev = Some(vcdev);
+
+        Ok(())
+    }
+
+    fn devfs_remove(&self) {
+        let vcdev = self.inner.lock().vcdev.take();
+        if let Some(vcdev) = vcdev {
+            devfs_unregister(vcdev.name_ref(), vcdev.clone())
+                .inspect_err(|e| {
+                    log::error!("virt console: devfs_unregister failed: {:?}", e);
+                })
+                .ok();
         }
+    }
+}
+
+struct InnerVirtConsoleManager {
+    consoles: HashMap<usize, Arc<VirtConsole>>,
+    ida: IdAllocator,
+}
+pub struct VirtConsoleManager {
+    inner: SpinLock<InnerVirtConsoleManager>,
 
-        v
-    };
+    current_vc: RwLock<Option<(Arc<VirtConsole>, usize)>>,
+}
+
+impl VirtConsoleManager {
+    pub const DEFAULT_VC_NAMES: [&'static str; 4] = ["tty0", "ttyS0", "tty1", "ttyS1"];
+
+    pub fn new() -> Self {
+        let ida = IdAllocator::new(0, MAX_NR_CONSOLES as usize).unwrap();
+        let consoles = HashMap::new();
+
+        Self {
+            inner: SpinLock::new(InnerVirtConsoleManager { consoles, ida }),
+            current_vc: RwLock::new(None),
+        }
+    }
+
+    pub fn get(&self, index: usize) -> Option<Arc<VirtConsole>> {
+        let inner = self.inner.lock();
+        inner.consoles.get(&index).cloned()
+    }
+
+    pub fn alloc(&self, vc: Arc<VirtConsole>) -> Option<usize> {
+        let mut inner = self.inner.lock();
+        let index = inner.ida.alloc()?;
+        vc.index.init(index);
+        if let Some(vc_data) = vc.vc_data.as_ref() {
+            vc_data.lock().vc_index = index;
+        }
+
+        inner.consoles.insert(index, vc);
+        Some(index)
+    }
+
+    /// 释放虚拟终端
+    pub fn free(&self, index: usize) {
+        let mut inner = self.inner.lock();
+        if let Some(vc) = inner.consoles.remove(&index) {
+            vc.devfs_remove();
+        }
+        inner.ida.free(index);
+    }
+
+    /// 获取当前虚拟终端
+    pub fn current_vc(&self) -> Option<Arc<VirtConsole>> {
+        self.current_vc.read().as_ref().map(|(vc, _)| vc.clone())
+    }
+
+    pub fn current_vc_index(&self) -> Option<usize> {
+        self.current_vc.read().as_ref().map(|(_, index)| *index)
+    }
+
+    pub fn current_vc_tty_name(&self) -> Option<String> {
+        self.current_vc()
+            .and_then(|vc| vc.port().port_data().internal_tty())
+            .map(|tty| tty.core().name().to_string())
+    }
+
+    /// 设置当前虚拟终端
+    pub fn set_current_vc(&self, vc: Arc<VirtConsole>) {
+        let index = *vc.index.get();
+        *self.current_vc.write() = Some((vc, index));
+    }
+
+    /// 通过tty名称查找虚拟终端
+    ///
+    /// # Arguments
+    ///
+    /// * `name` - tty名称 (如ttyS0)
+    pub fn lookup_vc_by_tty_name(&self, name: &str) -> Option<Arc<VirtConsole>> {
+        let inner = self.inner.lock();
+        for (_index, vc) in inner.consoles.iter() {
+            let found = vc
+                .port
+                .port_data()
+                .internal_tty()
+                .map(|tty| tty.core().name().as_str() == name)
+                .unwrap_or(false);
+
+            if found {
+                return Some(vc.clone());
+            }
+        }
+
+        None
+    }
+
+    pub fn setup_default_vc(&self) {
+        // todo: 从内核启动参数中获取
+        for name in Self::DEFAULT_VC_NAMES.iter() {
+            if let Some(vc) = self.lookup_vc_by_tty_name(name) {
+                log::info!("Set default vc with tty device: {}", name);
+                self.set_current_vc(vc);
+                return;
+            }
+        }
+
+        panic!("virt console: setup default vc failed");
+    }
 }
 
 #[derive(Debug, Clone, Copy, Default)]
@@ -119,7 +302,8 @@ impl TtyConsoleDriverInner {
 
     fn do_write(&self, tty: &TtyCoreData, buf: &[u8], mut nr: usize) -> Result<usize, SystemError> {
         // 关闭中断
-        let mut vc_data = tty.vc_data_irqsave();
+        let vc_data = tty.vc_data().unwrap();
+        let mut vc_data_guard = vc_data.lock_irqsave();
 
         let mut offset = 0;
 
@@ -130,7 +314,7 @@ impl TtyConsoleDriverInner {
         let mut draw = DrawRegion::default();
 
         // 首先隐藏光标再写
-        vc_data.hide_cursor();
+        vc_data_guard.hide_cursor();
 
         while nr != 0 {
             if !rescan {
@@ -139,7 +323,7 @@ impl TtyConsoleDriverInner {
                 nr -= 1;
             }
 
-            let (tc, rescan_last) = vc_data.translate(&mut ch);
+            let (tc, rescan_last) = vc_data_guard.translate(&mut ch);
             if tc.is_none() {
                 // 表示未转换完成
                 continue;
@@ -148,30 +332,30 @@ impl TtyConsoleDriverInner {
             let tc = tc.unwrap();
             rescan = rescan_last;
 
-            if vc_data.is_control(tc, ch) {
-                vc_data.flush(&mut draw);
-                vc_data.do_control(ch);
+            if vc_data_guard.is_control(tc, ch) {
+                vc_data_guard.flush(&mut draw);
+                vc_data_guard.do_control(ch);
                 continue;
             }
 
-            if !vc_data.console_write_normal(tc, ch, &mut draw) {
+            if !vc_data_guard.console_write_normal(tc, ch, &mut draw) {
                 continue;
             }
         }
 
-        vc_data.flush(&mut draw);
+        vc_data_guard.flush(&mut draw);
 
         // TODO: notify update
         return Ok(offset);
     }
-}
 
-impl TtyOperation for TtyConsoleDriverInner {
-    fn install(&self, _driver: Arc<TtyDriver>, tty: Arc<TtyCore>) -> Result<(), SystemError> {
+    fn do_install(&self, tty: Arc<TtyCore>, vc: &Arc<VirtConsole>) -> 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)?;
+        let binding = vc.vc_data().unwrap();
+        let mut vc_data = binding.lock();
+
+        self.console.con_init(vc, &mut vc_data, true)?;
         if vc_data.complement_mask == 0 {
             vc_data.complement_mask = if vc_data.color_mode { 0x7700 } else { 0x0800 };
         }
@@ -206,11 +390,24 @@ impl TtyOperation for TtyConsoleDriverInner {
         }
 
         // 设置tty的端口为vc端口
-        vc_data.port().setup_internal_tty(Arc::downgrade(&tty));
-        tty.set_port(vc_data.port());
+        vc.port().setup_internal_tty(Arc::downgrade(&tty));
+        tty.set_port(vc.port());
+        vc.devfs_setup()?;
         // 加入sysfs?
 
-        CURRENT_VCNUM.store(tty_core.index() as isize, Ordering::SeqCst);
+        Ok(())
+    }
+}
+
+impl TtyOperation for TtyConsoleDriverInner {
+    fn install(&self, _driver: Arc<TtyDriver>, tty: Arc<TtyCore>) -> Result<(), SystemError> {
+        let vc = VirtConsole::new(Some(Arc::new(SpinLock::new(VirtualConsoleData::new(
+            usize::MAX,
+        )))));
+        vc_manager().alloc(vc.clone()).ok_or(SystemError::EBUSY)?;
+        self.do_install(tty, &vc)
+            .inspect_err(|_| vc_manager().free(vc.index().unwrap()))?;
+
         Ok(())
     }
 
@@ -228,6 +425,7 @@ impl TtyOperation for TtyConsoleDriverInner {
         // if String::from_utf8_lossy(buf) == "Hello world!\n" {
         //     loop {}
         // }
+        send_to_default_serial8250_port(buf);
         let ret = self.do_write(tty, buf, nr);
         self.flush_chars(tty);
         ret
@@ -235,8 +433,9 @@ impl TtyOperation for TtyConsoleDriverInner {
 
     #[inline(never)]
     fn flush_chars(&self, tty: &TtyCoreData) {
-        let mut vc_data = tty.vc_data_irqsave();
-        vc_data.set_cursor();
+        let vc_data = tty.vc_data().unwrap();
+        let mut vc_data_guard = vc_data.lock_irqsave();
+        vc_data_guard.set_cursor();
     }
 
     fn put_char(&self, tty: &TtyCoreData, ch: u8) -> Result<(), SystemError> {
@@ -295,49 +494,34 @@ pub struct DrawRegion {
 // 初始化虚拟终端
 #[inline(never)]
 pub fn vty_init() -> Result<(), SystemError> {
-    // 注册虚拟终端设备并将虚拟终端设备加入到文件系统
-    let vc0 = TtyDevice::new(
-        "vc0".to_string(),
-        IdTable::new(
-            String::from("vc0"),
-            Some(DeviceNumber::new(Major::TTY_MAJOR, 0)),
-        ),
-        TtyType::Tty,
-    );
-    // 注册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,
-        Arc::new(TtyConsoleDriverInner::new()?),
-    );
-
-    TtyDriverManager::tty_register_driver(console_driver)?;
-
-    CURRENT_VCNUM.store(0, Ordering::SeqCst);
-
-    // 初始化键盘?
-
-    // TODO: 为vc
+    if let Ok(tty_console_driver_inner) = TtyConsoleDriverInner::new() {
+        let console_driver = TtyDriver::new(
+            MAX_NR_CONSOLES,
+            "tty",
+            0,
+            Major::TTY_MAJOR,
+            0,
+            TtyDriverType::Console,
+            *TTY_STD_TERMIOS,
+            Arc::new(tty_console_driver_inner),
+            None,
+        );
+
+        TtyDriverManager::tty_register_driver(console_driver).inspect(|_| {
+            log::error!("tty console: register driver failed");
+        })?;
+    }
+
+    Ok(())
+}
+
+#[unified_init(INITCALL_LATE)]
+fn vty_late_init() -> Result<(), SystemError> {
+    let (_, console_driver) =
+        TtyDriverManager::lookup_tty_driver(DeviceNumber::new(Major::TTY_MAJOR, 0))
+            .ok_or(SystemError::ENODEV)?;
+    console_driver.init_tty_device(None)?;
 
+    vc_manager().setup_default_vc();
     Ok(())
 }

+ 10 - 25
kernel/src/driver/tty/virtual_terminal/virtual_console.rs

@@ -1,4 +1,4 @@
-use core::sync::atomic::{AtomicBool, AtomicIsize, Ordering};
+use core::sync::atomic::{AtomicBool, Ordering};
 
 use alloc::{
     sync::{Arc, Weak},
@@ -10,11 +10,7 @@ use log::warn;
 use crate::{
     driver::{
         serial::serial8250::send_to_default_serial8250_port,
-        tty::{
-            console::ConsoleSwitch,
-            tty_port::{DefaultTtyPort, TtyPort},
-            ConsoleFont, KDMode,
-        },
+        tty::{console::ConsoleSwitch, ConsoleFont, KDMode},
     },
     libs::{font::FontDesc, rwlock::RwLock},
     process::Pid,
@@ -22,7 +18,8 @@ use crate::{
 
 use super::{
     console_map::{TranslationMap, TranslationMapType},
-    Color, DrawRegion, VtMode, VtModeData, COLOR_TABLE, DEFAULT_BLUE, DEFAULT_GREEN, DEFAULT_RED,
+    vc_manager, Color, DrawRegion, VtMode, VtModeData, COLOR_TABLE, DEFAULT_BLUE, DEFAULT_GREEN,
+    DEFAULT_RED,
 };
 
 pub(super) const NPAR: usize = 16;
@@ -34,14 +31,12 @@ lazy_static! {
 
 }
 
-pub static CURRENT_VCNUM: AtomicIsize = AtomicIsize::new(-1);
-
 pub static CONSOLE_BLANKED: AtomicBool = AtomicBool::new(false);
 
 /// ## 虚拟控制台的信息
 #[derive(Debug, Clone)]
 pub struct VirtualConsoleData {
-    pub num: usize,
+    pub vc_index: usize,
     pub state: VirtualConsoleInfo,
     pub saved_state: VirtualConsoleInfo,
     /// 最大列数
@@ -146,9 +141,6 @@ pub struct VirtualConsoleData {
 
     /// 对应的Console Driver funcs
     driver_funcs: Option<Weak<dyn ConsoleSwitch>>,
-
-    /// 对应端口
-    port: Arc<dyn TtyPort>,
 }
 
 impl VirtualConsoleData {
@@ -210,16 +202,10 @@ impl VirtualConsoleData {
             screen_buf: Default::default(),
             driver_funcs: None,
             cursor_type: VcCursor::empty(),
-            num,
-            port: Arc::new(DefaultTtyPort::new()),
+            vc_index: num,
         }
     }
 
-    #[inline]
-    pub fn port(&self) -> Arc<dyn TtyPort> {
-        self.port.clone()
-    }
-
     pub(super) fn init(&mut self, rows: Option<usize>, cols: Option<usize>, clear: bool) {
         if let Some(rows) = rows {
             self.rows = rows;
@@ -245,12 +231,11 @@ impl VirtualConsoleData {
     }
 
     pub fn is_visible(&self) -> bool {
-        let cur_vc = CURRENT_VCNUM.load(Ordering::SeqCst);
-        if cur_vc == -1 {
-            return false;
+        if let Some(cur_vc) = vc_manager().current_vc_index() {
+            cur_vc == self.vc_index
+        } else {
+            false
         }
-
-        cur_vc as usize == self.num
     }
 
     fn driver_funcs(&self) -> Arc<dyn ConsoleSwitch> {

+ 11 - 3
kernel/src/driver/video/console/dummycon.rs

@@ -5,7 +5,10 @@ use crate::driver::tty::{
     console::ConsoleSwitch,
     termios::WindowSize,
     tty_driver::TtyOperation,
-    virtual_terminal::virtual_console::{CursorOperation, ScrollDir, VirtualConsoleData},
+    virtual_terminal::{
+        virtual_console::{CursorOperation, ScrollDir, VirtualConsoleData},
+        VirtConsole,
+    },
 };
 
 lazy_static! {
@@ -49,14 +52,19 @@ impl ConsoleSwitch for DummyConsole {
     ) -> Result<u8, SystemError> {
         Ok(0)
     }
-    fn con_init(&self, vc_data: &mut VirtualConsoleData, init: bool) -> Result<(), SystemError> {
+    fn con_init(
+        &self,
+        vc: &Arc<VirtConsole>,
+        vc_data: &mut VirtualConsoleData,
+        init: bool,
+    ) -> Result<(), SystemError> {
         vc_data.color_mode = true;
 
         if init {
             vc_data.cols = Self::COLUNMS;
             vc_data.rows = Self::ROWS;
         } else {
-            let tty = vc_data.port().port_data().tty().unwrap();
+            let tty = vc.port().port_data().tty().unwrap();
             tty.resize(
                 tty.clone(),
                 WindowSize::new(Self::ROWS as u16, Self::COLUNMS as u16, 0, 0),

+ 2 - 1
kernel/src/driver/video/fbdev/base/fbcon/framebuffer_console.rs

@@ -8,7 +8,7 @@ use crate::{
             console::ConsoleSwitch,
             virtual_terminal::{
                 virtual_console::{CursorOperation, ScrollDir, VcCursor, VirtualConsoleData},
-                Color,
+                Color, VirtConsole,
             },
         },
         video::fbdev::base::{
@@ -174,6 +174,7 @@ impl BlittingFbConsole {
 impl ConsoleSwitch for BlittingFbConsole {
     fn con_init(
         &self,
+        _vc: &Arc<VirtConsole>,
         vc_data: &mut VirtualConsoleData,
         init: bool,
     ) -> Result<(), system_error::SystemError> {

+ 1 - 1
kernel/src/exception/manage.rs

@@ -156,7 +156,7 @@ impl IrqManager {
         *action_guard.flags_mut() = flags;
         *action_guard.dev_id_mut() = dev_id;
         drop(action_guard);
-        debug!("to inner_setup_irq");
+        debug!("to inner_setup_irq: {irq:?}");
         return self.inner_setup_irq(irq, irqaction, desc);
     }
 

+ 1 - 1
kernel/src/filesystem/devpts/mod.rs

@@ -50,7 +50,7 @@ impl DevPtsFs {
         let root_inode = Arc::new(LockedDevPtsFSInode::new());
         let ret = Arc::new(Self {
             root_inode,
-            pts_ida: SpinLock::new(IdAllocator::new(1, NR_UNIX98_PTY_MAX as usize).unwrap()),
+            pts_ida: SpinLock::new(IdAllocator::new(0, NR_UNIX98_PTY_MAX as usize).unwrap()),
             pts_count: AtomicU32::new(0),
         });
 

+ 3 - 5
kernel/src/libs/lib_ui/textui.rs

@@ -1,7 +1,6 @@
 use crate::{
     driver::{
-        serial::serial8250::send_to_default_serial8250_port,
-        tty::{tty_port::tty_port, virtual_terminal::virtual_console::CURRENT_VCNUM},
+        serial::serial8250::send_to_default_serial8250_port, tty::virtual_terminal::vc_manager,
         video::video_refresh_manager,
     },
     libs::{
@@ -1031,8 +1030,7 @@ 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 {
+    if let Some(current_vc) = vc_manager().current_vc() {
         // tty已经初始化了之后才输出到屏幕
         let fr = (fr_color & 0x00ff0000) >> 16;
         let fg = (fr_color & 0x0000ff00) >> 8;
@@ -1044,7 +1042,7 @@ pub extern "C" fn rs_textui_putchar(character: u8, fr_color: u32, bk_color: u32)
             "\x1B[38;2;{fr};{fg};{fb};48;2;{br};{bg};{bb}m{}\x1B[0m",
             character as char
         );
-        let port = tty_port(current_vcnum as usize);
+        let port = current_vc.port();
         let tty = port.port_data().internal_tty();
         if let Some(tty) = tty {
             send_to_default_serial8250_port(&[character]);

+ 4 - 11
kernel/src/libs/printk.rs

@@ -1,7 +1,4 @@
-use core::{
-    fmt::{self, Write},
-    sync::atomic::Ordering,
-};
+use core::fmt::{self, Write};
 
 use alloc::string::ToString;
 use log::{info, Level, Log};
@@ -9,10 +6,7 @@ use log::{info, Level, Log};
 use super::lib_ui::textui::{textui_putstr, FontColor};
 
 use crate::{
-    driver::tty::{
-        tty_driver::TtyOperation, tty_port::tty_port,
-        virtual_terminal::virtual_console::CURRENT_VCNUM,
-    },
+    driver::tty::{tty_driver::TtyOperation, virtual_terminal::vc_manager},
     filesystem::procfs::{
         kmsg::KMSG,
         log::{LogLevel, LogMessage},
@@ -44,10 +38,9 @@ impl PrintkWriter {
     /// 并输出白底黑字
     /// @param str: 要写入的字符
     pub fn __write_string(&mut self, s: &str) {
-        let current_vcnum = CURRENT_VCNUM.load(Ordering::SeqCst);
-        if current_vcnum != -1 {
+        if let Some(current_vc) = vc_manager().current_vc() {
             // tty已经初始化了之后才输出到屏幕
-            let port = tty_port(current_vcnum as usize);
+            let port = current_vc.port();
             let tty = port.port_data().internal_tty();
             if let Some(tty) = tty {
                 let _ = tty.write(tty.core(), s.as_bytes(), s.len());

+ 10 - 2
kernel/src/process/stdio.rs

@@ -1,6 +1,7 @@
 use system_error::SystemError;
 
 use crate::{
+    driver::tty::virtual_terminal::vc_manager,
     filesystem::vfs::{
         file::{File, FileMode},
         ROOT_INODE,
@@ -13,9 +14,16 @@ pub fn stdio_init() -> Result<(), SystemError> {
     if ProcessManager::current_pcb().pid() != Pid(1) {
         return Err(SystemError::EPERM);
     }
+    let tty_path = format!(
+        "/dev/{}",
+        vc_manager()
+            .current_vc_tty_name()
+            .expect("Init stdio: can't get tty name")
+    );
     let tty_inode = ROOT_INODE()
-        .lookup("/dev/tty0")
-        .expect("Init stdio: can't find tty0");
+        .lookup(&tty_path)
+        .unwrap_or_else(|_| panic!("Init stdio: can't find {}", tty_path));
+
     let stdin =
         File::new(tty_inode.clone(), FileMode::O_RDONLY).expect("Init stdio: can't create stdin");
     let stdout =

+ 31 - 22
tools/run-qemu.sh

@@ -77,6 +77,7 @@ QEMU_DRIVE="id=disk,file=${QEMU_DISK_IMAGE},if=none"
 QEMU_ACCELARATE=""
 QEMU_ARGUMENT=""
 QEMU_DEVICES=""
+BIOS_TYPE=""
 #这个变量为true则使用virtio磁盘
 VIRTIO_BLK_DEVICE=false
 # 如果qemu_accel不为空
@@ -109,6 +110,35 @@ if [ ${ARCH} == "riscv64" ]; then
     QEMU_SERIAL=""
 fi
 
+while true;do
+    case "$1" in
+        --bios) 
+        case "$2" in
+              uefi) #uefi启动新增ovmf.fd固件
+              BIOS_TYPE=uefi
+            ;;
+              legacy)
+              BIOS_TYPE=legacy
+              ;;
+        esac;shift 2;;
+        --display)
+        case "$2" in
+              vnc)
+              QEMU_ARGUMENT+=" -display vnc=:00"
+              ;;
+              window)
+              ;;
+              nographic)
+              QEMU_SERIAL=" -serial mon:stdio "
+              QEMU_MONITOR=""
+              QEMU_ARGUMENT+=" --nographic "
+
+              ;;
+        esac;shift 2;;
+        *) break
+      esac 
+  done
+
 
 # ps: 下面这条使用tap的方式,无法dhcp获取到ip,暂时不知道为什么
 # QEMU_DEVICES="-device ahci,id=ahci -device ide-hd,drive=disk,bus=ahci.0 -net nic,netdev=nic0 -netdev tap,id=nic0,model=virtio-net-pci,script=qemu/ifup-nat,downscript=qemu/ifdown-nat -usb -device qemu-xhci,id=xhci,p2=8,p3=4 "
@@ -149,28 +179,7 @@ install_riscv_uboot()
 
 
 if [ $flag_can_run -eq 1 ]; then
-  while true;do
-    case "$1" in
-        --bios) 
-        case "$2" in
-              uefi) #uefi启动新增ovmf.fd固件
-              BIOS_TYPE=uefi
-            ;;
-              legacy)
-              BIOS_TYPE=legacy
-              ;;
-        esac;shift 2;;
-        --display)
-        case "$2" in
-              vnc)
-              QEMU_ARGUMENT+=" -display vnc=:00"
-              ;;
-              window)
-              ;;
-        esac;shift 2;;
-        *) break
-      esac 
-  done 
+   
 
 # 删除共享内存
 sudo rm -rf ${QEMU_MEMORY_BACKEND_PATH_PREFIX}/${QEMU_MEMORY_BACKEND}