Support `/dev/ttyS0` and `console=ttyS0`
This commit is contained in:
parent
000ad53c9f
commit
3c959bf0a0
|
|
@ -16,7 +16,7 @@ use crate::{
|
|||
registry::char,
|
||||
tty::{
|
||||
Tty,
|
||||
n_tty::{VtDriver, hvc0_device},
|
||||
n_tty::{VtDriver, hvc0_device, serial0_device},
|
||||
},
|
||||
},
|
||||
fs::{
|
||||
|
|
@ -114,6 +114,7 @@ impl SystemConsole {
|
|||
|
||||
let device = match console_name {
|
||||
"tty0" => Some(Arc::new(Tty0Device) as _),
|
||||
"ttyS0" => serial0_device().cloned().map(|device| device as _),
|
||||
"hvc0" => hvc0_device().cloned().map(|device| device as _),
|
||||
_ => None,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -63,6 +63,50 @@ impl TtyDriver for VtDriver {
|
|||
fn on_termios_change(&self, _old_termios: &CTermios, _new_termios: &CTermios) {}
|
||||
}
|
||||
|
||||
/// The driver for serial devices.
|
||||
#[derive(Clone)]
|
||||
pub struct SerialDriver {
|
||||
console: Arc<dyn AnyConsoleDevice>,
|
||||
}
|
||||
|
||||
impl SerialDriver {
|
||||
const MINOR_ID_BASE: u32 = 64;
|
||||
}
|
||||
|
||||
impl TtyDriver for SerialDriver {
|
||||
// Reference: <https://elixir.bootlin.com/linux/v6.17/source/include/uapi/linux/major.h#L18>.
|
||||
const DEVICE_MAJOR_ID: u32 = 4;
|
||||
|
||||
fn devtmpfs_path(&self, index: u32) -> Option<String> {
|
||||
Some(format!("ttyS{}", index - Self::MINOR_ID_BASE))
|
||||
}
|
||||
|
||||
fn open(tty: Arc<Tty<Self>>) -> Result<Box<dyn FileIo>> {
|
||||
Ok(Box::new(TtyFile(tty)))
|
||||
}
|
||||
|
||||
fn push_output(&self, chs: &[u8]) -> Result<usize> {
|
||||
self.console.send(chs);
|
||||
Ok(chs.len())
|
||||
}
|
||||
|
||||
fn echo_callback(&self) -> impl FnMut(&[u8]) + '_ {
|
||||
|chs| self.console.send(chs)
|
||||
}
|
||||
|
||||
fn can_push(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn notify_input(&self) {}
|
||||
|
||||
fn console(&self) -> Option<&dyn AnyConsoleDevice> {
|
||||
Some(&*self.console)
|
||||
}
|
||||
|
||||
fn on_termios_change(&self, _old_termios: &CTermios, _new_termios: &CTermios) {}
|
||||
}
|
||||
|
||||
/// The driver for hypervisor console devices.
|
||||
#[derive(Clone)]
|
||||
pub struct HvcDriver {
|
||||
|
|
@ -145,6 +189,8 @@ impl<D: TtyDriver> FileIo for TtyFile<D> {
|
|||
|
||||
static TTY1: Once<Arc<Tty<VtDriver>>> = Once::new();
|
||||
|
||||
static SERIAL0: Once<Arc<Tty<SerialDriver>>> = Once::new();
|
||||
|
||||
static HVC0: Once<Arc<Tty<HvcDriver>>> = Once::new();
|
||||
|
||||
/// Returns the `tty1` device.
|
||||
|
|
@ -156,6 +202,13 @@ pub fn tty1_device() -> &'static Arc<Tty<VtDriver>> {
|
|||
TTY1.get().unwrap()
|
||||
}
|
||||
|
||||
/// Returns the `ttyS0` device.
|
||||
///
|
||||
/// Returns `None` if the device is not found nor initialized.
|
||||
pub fn serial0_device() -> Option<&'static Arc<Tty<SerialDriver>>> {
|
||||
SERIAL0.get()
|
||||
}
|
||||
|
||||
/// Returns the `hvc0` device.
|
||||
///
|
||||
/// Returns `None` if the device is not found nor initialized.
|
||||
|
|
@ -190,6 +243,31 @@ pub(super) fn init_in_first_process() -> Result<()> {
|
|||
},
|
||||
)));
|
||||
|
||||
// Initialize the `ttyS0` device if the serial console is available.
|
||||
|
||||
let serial_console = devices
|
||||
.iter()
|
||||
.find(|(name, _)| name.as_str() == aster_uart::CONSOLE_NAME)
|
||||
.map(|(_, device)| device.clone());
|
||||
|
||||
if let Some(serial_console) = serial_console {
|
||||
let driver = SerialDriver {
|
||||
console: serial_console.clone(),
|
||||
};
|
||||
let serial0 = Tty::new(SerialDriver::MINOR_ID_BASE, driver);
|
||||
|
||||
SERIAL0.call_once(|| serial0.clone());
|
||||
char::register(serial0.clone())?;
|
||||
|
||||
serial_console.register_callback(Box::leak(Box::new(
|
||||
move |mut reader: VmReader<Infallible>| {
|
||||
let mut chs = vec![0u8; reader.remain()];
|
||||
reader.read(&mut VmWriter::from(chs.as_mut_slice()));
|
||||
let _ = serial0.push_input(chs.as_slice());
|
||||
},
|
||||
)));
|
||||
}
|
||||
|
||||
// Initialize the `hvc0` device if the virtio console is available.
|
||||
|
||||
let virtio_console = devices
|
||||
|
|
|
|||
Loading…
Reference in New Issue