Support `/dev/ttyS0` and `console=ttyS0`
This commit is contained in:
parent
000ad53c9f
commit
3c959bf0a0
|
|
@ -16,7 +16,7 @@ use crate::{
|
||||||
registry::char,
|
registry::char,
|
||||||
tty::{
|
tty::{
|
||||||
Tty,
|
Tty,
|
||||||
n_tty::{VtDriver, hvc0_device},
|
n_tty::{VtDriver, hvc0_device, serial0_device},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
fs::{
|
fs::{
|
||||||
|
|
@ -114,6 +114,7 @@ impl SystemConsole {
|
||||||
|
|
||||||
let device = match console_name {
|
let device = match console_name {
|
||||||
"tty0" => Some(Arc::new(Tty0Device) as _),
|
"tty0" => Some(Arc::new(Tty0Device) as _),
|
||||||
|
"ttyS0" => serial0_device().cloned().map(|device| device as _),
|
||||||
"hvc0" => hvc0_device().cloned().map(|device| device as _),
|
"hvc0" => hvc0_device().cloned().map(|device| device as _),
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -63,6 +63,50 @@ impl TtyDriver for VtDriver {
|
||||||
fn on_termios_change(&self, _old_termios: &CTermios, _new_termios: &CTermios) {}
|
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.
|
/// The driver for hypervisor console devices.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct HvcDriver {
|
pub struct HvcDriver {
|
||||||
|
|
@ -145,6 +189,8 @@ impl<D: TtyDriver> FileIo for TtyFile<D> {
|
||||||
|
|
||||||
static TTY1: Once<Arc<Tty<VtDriver>>> = Once::new();
|
static TTY1: Once<Arc<Tty<VtDriver>>> = Once::new();
|
||||||
|
|
||||||
|
static SERIAL0: Once<Arc<Tty<SerialDriver>>> = Once::new();
|
||||||
|
|
||||||
static HVC0: Once<Arc<Tty<HvcDriver>>> = Once::new();
|
static HVC0: Once<Arc<Tty<HvcDriver>>> = Once::new();
|
||||||
|
|
||||||
/// Returns the `tty1` device.
|
/// Returns the `tty1` device.
|
||||||
|
|
@ -156,6 +202,13 @@ pub fn tty1_device() -> &'static Arc<Tty<VtDriver>> {
|
||||||
TTY1.get().unwrap()
|
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 the `hvc0` device.
|
||||||
///
|
///
|
||||||
/// Returns `None` if the device is not found nor initialized.
|
/// 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.
|
// Initialize the `hvc0` device if the virtio console is available.
|
||||||
|
|
||||||
let virtio_console = devices
|
let virtio_console = devices
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue