drivers: support graphic console output

This commit is contained in:
Yuekai Jia 2021-10-05 04:50:30 +08:00
parent dd835e5af7
commit d8e6aca2f9
27 changed files with 362 additions and 158 deletions

View File

@ -8,7 +8,7 @@ description = "Device drivers of zCore"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[features] [features]
graphic = [] graphic = ["rcore-console"]
mock = ["async-std", "sdl2"] mock = ["async-std", "sdl2"]
virtio = ["virtio-drivers"] virtio = ["virtio-drivers"]
@ -21,6 +21,7 @@ lazy_static = "1.4"
device_tree = { git = "https://github.com/rcore-os/device_tree-rs", rev = "4e8144b" } device_tree = { git = "https://github.com/rcore-os/device_tree-rs", rev = "4e8144b" }
bitmap-allocator = { git = "https://github.com/rcore-os/bitmap-allocator", rev = "b3f9f51" } bitmap-allocator = { git = "https://github.com/rcore-os/bitmap-allocator", rev = "b3f9f51" }
virtio-drivers = { git = "https://github.com/rcore-os/virtio-drivers", rev = "2b3c6cf", optional = true } virtio-drivers = { git = "https://github.com/rcore-os/virtio-drivers", rev = "2b3c6cf", optional = true }
rcore-console = { git = "https://github.com/rcore-os/rcore-console", default-features = false, rev = "ee95abd", optional = true }
[target.'cfg(not(target_os = "none"))'.dependencies] [target.'cfg(not(target_os = "none"))'.dependencies]
async-std = { version = "1.10", optional = true } async-std = { version = "1.10", optional = true }

View File

@ -1 +1 @@
pub use crate::scheme::display::{ColorDepth, ColorFormat, DisplayInfo}; pub use crate::scheme::display::{ColorFormat, DisplayInfo, RgbColor};

View File

@ -9,8 +9,6 @@ extern crate log;
use alloc::sync::Arc; use alloc::sync::Arc;
use core::fmt; use core::fmt;
mod utils;
#[cfg(feature = "mock")] #[cfg(feature = "mock")]
pub mod mock; pub mod mock;
@ -23,6 +21,7 @@ pub mod io;
pub mod irq; pub mod irq;
pub mod scheme; pub mod scheme;
pub mod uart; pub mod uart;
pub mod utils;
#[derive(Debug)] #[derive(Debug)]
pub enum DeviceError { pub enum DeviceError {

View File

@ -2,7 +2,7 @@ pub mod sdl;
use alloc::vec::Vec; use alloc::vec::Vec;
use crate::display::{ColorDepth, ColorFormat, DisplayInfo}; use crate::display::{ColorFormat, DisplayInfo};
use crate::scheme::{DisplayScheme, Scheme}; use crate::scheme::{DisplayScheme, Scheme};
pub struct MockDisplay { pub struct MockDisplay {
@ -12,15 +12,13 @@ pub struct MockDisplay {
impl MockDisplay { impl MockDisplay {
pub fn new(width: u32, height: u32) -> Self { pub fn new(width: u32, height: u32) -> Self {
let depth = ColorDepth::ColorDepth32; let format = ColorFormat::RGB888;
let format = ColorFormat::RGBA8888; let fb_size = (width * height * format.bytes() as u32) as usize;
let fb_size = (width * height * depth.bytes() as u32) as usize;
let info = DisplayInfo { let info = DisplayInfo {
width, width,
height, height,
fb_size,
depth,
format, format,
fb_size,
}; };
let fb = vec![0; fb_size]; let fb = vec![0; fb_size];
Self { info, fb } Self { info, fb }
@ -34,10 +32,12 @@ impl Scheme for MockDisplay {
} }
impl DisplayScheme for MockDisplay { impl DisplayScheme for MockDisplay {
#[inline]
fn info(&self) -> DisplayInfo { fn info(&self) -> DisplayInfo {
self.info self.info
} }
#[inline]
unsafe fn raw_fb(&self) -> &mut [u8] { unsafe fn raw_fb(&self) -> &mut [u8] {
core::slice::from_raw_parts_mut(self.fb.as_ptr() as _, self.info.fb_size) core::slice::from_raw_parts_mut(self.fb.as_ptr() as _, self.info.fb_size)
} }

View File

@ -1,47 +1,48 @@
use alloc::sync::Arc;
use sdl2::{event::Event, keyboard::Keycode, EventPump}; use sdl2::{event::Event, keyboard::Keycode, EventPump};
use sdl2::{pixels::PixelFormatEnum, render::Canvas, video::Window}; use sdl2::{pixels::PixelFormatEnum, render::Canvas, video::Window};
use crate::display::{ColorFormat, DisplayInfo}; use crate::display::ColorFormat;
use crate::scheme::DisplayScheme; use crate::scheme::DisplayScheme;
pub struct SdlWindow { pub struct SdlWindow {
canvas: Canvas<Window>, canvas: Canvas<Window>,
event_pump: EventPump, event_pump: EventPump,
info: DisplayInfo, display: Arc<dyn DisplayScheme>,
} }
impl SdlWindow { impl SdlWindow {
pub fn new(title: &str, info: DisplayInfo) -> Self { pub fn new(title: &str, display: Arc<dyn DisplayScheme>) -> Self {
assert_eq!(info.format, ColorFormat::RGBA8888);
let sdl_context = sdl2::init().unwrap(); let sdl_context = sdl2::init().unwrap();
let video_subsystem = sdl_context.video().unwrap(); let video_subsystem = sdl_context.video().unwrap();
let window = video_subsystem let window = video_subsystem
.window(title, info.width, info.height) .window(title, display.info().width, display.info().height)
.position_centered() .position_centered()
.build() .build()
.unwrap(); .unwrap();
let event_pump = sdl_context.event_pump().unwrap(); let event_pump = sdl_context.event_pump().unwrap();
let mut canvas = window.into_canvas().build().unwrap(); let canvas = window.into_canvas().build().unwrap();
canvas.clear(); let mut ret = Self {
canvas.present(); display,
Self {
info,
canvas, canvas,
event_pump, event_pump,
} };
ret.flush();
ret
} }
pub fn flush(&mut self, display: &dyn DisplayScheme) { pub fn flush(&mut self) {
let info = self.display.info();
let texture_creator = self.canvas.texture_creator(); let texture_creator = self.canvas.texture_creator();
let format: PixelFormatEnum = info.format.into();
let mut texture = texture_creator let mut texture = texture_creator
.create_texture_streaming(PixelFormatEnum::RGBA8888, self.info.width, self.info.height) .create_texture_streaming(format, info.width, info.height)
.unwrap(); .unwrap();
let buf = unsafe { display.raw_fb() }; let buf = unsafe { self.display.raw_fb() };
texture texture.update(None, buf, info.pitch() as usize).unwrap();
.update(None, buf, display.info().width as usize * 4)
.unwrap();
self.canvas.copy(&texture, None, None).unwrap(); self.canvas.copy(&texture, None, None).unwrap();
self.canvas.present(); self.canvas.present();
} }
@ -60,3 +61,15 @@ impl SdlWindow {
false false
} }
} }
impl core::convert::From<ColorFormat> for PixelFormatEnum {
fn from(format: ColorFormat) -> Self {
match format {
ColorFormat::RGB332 => Self::RGB332,
ColorFormat::RGB565 => Self::RGB565,
ColorFormat::RGB888 => Self::BGR24, // notice: BGR24 means R at the highest address, B at the lowest address.
ColorFormat::RGBA8888 => Self::RGBA8888,
ColorFormat::BGRA8888 => Self::BGRA8888,
}
}
}

View File

@ -1,21 +1,65 @@
use super::Scheme; use super::Scheme;
use crate::{DeviceError, DeviceResult};
#[repr(u8)] #[repr(transparent)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ColorDepth { pub struct RgbColor(u32);
ColorDepth8 = 8,
ColorDepth16 = 16, impl RgbColor {
ColorDepth24 = 24, #[inline]
ColorDepth32 = 32, pub const fn new(r: u8, g: u8, b: u8) -> Self {
Self(((r as u32) << 16) | ((g as u32) << 8) | b as u32)
}
#[inline]
pub const fn r(self) -> u8 {
(self.0 >> 16) as u8
}
#[inline]
pub const fn g(self) -> u8 {
(self.0 >> 8) as u8
}
#[inline]
pub const fn b(self) -> u8 {
self.0 as u8
}
#[inline]
pub const fn raw_value(self) -> u32 {
self.0
}
} }
/// Color format for one pixel. `RGB888` means R in bits 16-23, G in bits 8-15 and B in bits 0-7.
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ColorFormat { pub enum ColorFormat {
RGB332, RGB332,
RGB565, RGB565,
RGB888,
RGBA8888, // QEMU and low version RPi use RGBA RGBA8888, // QEMU and low version RPi use RGBA
BGRA8888, // RPi3 B+ uses BGRA BGRA8888, // RPi3 B+ uses BGRA
VgaPalette, }
impl ColorFormat {
/// Number of bits per pixel.
#[inline]
pub const fn depth(self) -> u8 {
match self {
Self::RGB332 => 8,
Self::RGB565 => 16,
Self::RGB888 => 24,
Self::RGBA8888 => 32,
Self::BGRA8888 => 32,
}
}
/// Number of bytes per pixel.
#[inline]
pub const fn bytes(self) -> u8 {
self.depth() / 8
}
} }
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
@ -24,28 +68,17 @@ pub struct DisplayInfo {
pub width: u32, pub width: u32,
/// visible height /// visible height
pub height: u32, pub height: u32,
/// frame buffer size
pub fb_size: usize,
/// bits per pixel
pub depth: ColorDepth,
/// color encoding format of RGBA /// color encoding format of RGBA
pub format: ColorFormat, pub format: ColorFormat,
/// frame buffer size
pub fb_size: usize,
} }
impl ColorDepth { impl DisplayInfo {
pub fn try_from(depth: u8) -> Result<Self, &'static str> { /// Number of bytes between each row of the frame buffer.
match depth { #[inline]
8 => Ok(Self::ColorDepth8), pub const fn pitch(self) -> u32 {
16 => Ok(Self::ColorDepth16), self.width * self.format.bytes() as u32
24 => Ok(Self::ColorDepth24),
32 => Ok(Self::ColorDepth32),
_ => Err("unsupported color depth"),
}
}
pub fn bytes(self) -> u8 {
self as u8 / 8
} }
} }
@ -53,5 +86,51 @@ pub trait DisplayScheme: Scheme {
fn info(&self) -> DisplayInfo; fn info(&self) -> DisplayInfo;
#[allow(clippy::mut_from_ref)] #[allow(clippy::mut_from_ref)]
/// Returns the raw framebuffer.
///
/// # Safety
///
/// This function is unsafe because it returns the raw pointer of the framebuffer.
unsafe fn raw_fb(&self) -> &mut [u8]; unsafe fn raw_fb(&self) -> &mut [u8];
#[inline]
fn write_pixel(&self, x: u32, y: u32, color: RgbColor) -> DeviceResult {
let info = self.info();
let fb = unsafe { self.raw_fb() };
let offset = (x + y * info.width) as usize * info.format.bytes() as usize;
if offset >= info.fb_size {
return Err(DeviceError::InvalidParam);
}
unsafe { write_color(&mut fb[offset as usize] as _, color, info.format) };
Ok(())
}
}
const fn pack_channel(r_val: u8, _r_bits: u8, g_val: u8, g_bits: u8, b_val: u8, b_bits: u8) -> u32 {
((r_val as u32) << (g_bits + b_bits)) | ((g_val as u32) << b_bits) | b_val as u32
}
unsafe fn write_color(ptr: *mut u8, color: RgbColor, format: ColorFormat) {
let (r, g, b) = (color.r(), color.g(), color.b());
let dst = core::slice::from_raw_parts_mut(ptr, 4);
match format {
ColorFormat::RGB332 => {
*ptr = pack_channel(r >> (8 - 3), 3, g >> (8 - 3), 3, b >> (8 - 2), 2) as u8
}
ColorFormat::RGB565 => {
*(ptr as *mut u16) =
pack_channel(r >> (8 - 5), 5, g >> (8 - 6), 6, b >> (8 - 5), 5) as u16
}
ColorFormat::RGB888 => {
dst[2] = r;
dst[1] = g;
dst[0] = b;
}
ColorFormat::RGBA8888 => *(ptr as *mut u32) = color.raw_value() << 8,
ColorFormat::BGRA8888 => {
dst[3] = b;
dst[2] = g;
dst[1] = r;
}
}
} }

View File

@ -0,0 +1,60 @@
use alloc::sync::Arc;
use core::convert::Infallible;
use core::ops::{Deref, DerefMut};
use rcore_console::{Console, ConsoleOnGraphic, DrawTarget, OriginDimensions, Pixel, Rgb888, Size};
use crate::scheme::DisplayScheme;
pub struct DisplayWrapper(Arc<dyn DisplayScheme>);
pub struct GraphicConsole {
inner: ConsoleOnGraphic<DisplayWrapper>,
}
impl GraphicConsole {
pub fn new(display: Arc<dyn DisplayScheme>) -> Self {
Self {
inner: Console::on_frame_buffer(DisplayWrapper(display)),
}
}
}
impl DrawTarget for DisplayWrapper {
type Color = Rgb888;
type Error = Infallible;
fn draw_iter<I>(&mut self, pixels: I) -> Result<(), Self::Error>
where
I: IntoIterator<Item = Pixel<Self::Color>>,
{
for p in pixels {
let color = unsafe { core::mem::transmute(p.1) };
self.0
.write_pixel(p.0.x as u32, p.0.y as u32, color)
.unwrap();
}
Ok(())
}
}
impl OriginDimensions for DisplayWrapper {
fn size(&self) -> Size {
let info = self.0.info();
Size::new(info.width, info.height)
}
}
impl Deref for GraphicConsole {
type Target = ConsoleOnGraphic<DisplayWrapper>;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl DerefMut for GraphicConsole {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.inner
}
}

View File

@ -2,6 +2,13 @@ mod event_listener;
mod id_allocator; mod id_allocator;
mod irq_manager; mod irq_manager;
pub(super) use event_listener::EventListener; #[cfg(feature = "graphic")]
mod graphic_console;
pub(super) use id_allocator::IdAllocator; pub(super) use id_allocator::IdAllocator;
pub(super) use irq_manager::IrqManager; pub(super) use irq_manager::IrqManager;
pub use event_listener::EventListener;
#[cfg(feature = "graphic")]
pub use graphic_console::GraphicConsole;

View File

@ -33,7 +33,6 @@ async-std = { version = "1.10", optional = true }
executor = { git = "https://github.com/rcore-os/executor.git", rev = "a2d02ee9" } executor = { git = "https://github.com/rcore-os/executor.git", rev = "a2d02ee9" }
naive-timer = "0.2.0" naive-timer = "0.2.0"
lazy_static = { version = "1.4", features = ["spin_no_std"] } lazy_static = { version = "1.4", features = ["spin_no_std"] }
bitmap-allocator = { git = "https://github.com/rcore-os/bitmap-allocator", rev = "b3f9f51" }
# Bare-metal mode on x86_64 # Bare-metal mode on x86_64
[target.'cfg(all(target_os = "none", target_arch = "x86_64"))'.dependencies] [target.'cfg(all(target_os = "none", target_arch = "x86_64"))'.dependencies]

View File

@ -48,8 +48,8 @@ pub fn send_ipi(sipi_value: usize) {
} }
hal_fn_impl! { hal_fn_impl! {
impl mod crate::hal_fn::serial { impl mod crate::hal_fn::console {
fn serial_write_early(s: &str) { fn console_write_early(s: &str) {
for c in s.bytes() { for c in s.bytes() {
console_putchar(c as usize); console_putchar(c as usize);
} }

View File

@ -10,7 +10,7 @@ pub mod special;
pub mod timer; pub mod timer;
pub mod vm; pub mod vm;
hal_fn_impl_default!(crate::hal_fn::serial); hal_fn_impl_default!(crate::hal_fn::console);
use x86_64::registers::control::{Cr4, Cr4Flags}; use x86_64::registers::control::{Cr4, Cr4Flags};

View File

@ -0,0 +1,77 @@
use core::fmt::{Arguments, Result, Write};
use crate::drivers;
struct SerialWriter;
impl Write for SerialWriter {
fn write_str(&mut self, s: &str) -> Result {
if let Some(uart) = drivers::uart::first() {
uart.write_str(s).unwrap();
} else {
crate::hal_fn::console::console_write_early(s);
}
Ok(())
}
}
cfg_if! {
if #[cfg(feature = "graphic")] {
use crate::utils::init_once::InitOnce;
use alloc::sync::Arc;
use spin::Mutex;
use zcore_drivers::{scheme::DisplayScheme, utils::GraphicConsole};
static GRAPHIC_CONSOLE: InitOnce<Mutex<GraphicConsole>> = InitOnce::new();
#[allow(dead_code)]
pub(crate) fn init_graphic_console(display: Arc<dyn DisplayScheme>) {
GRAPHIC_CONSOLE.init_once_by(Mutex::new(GraphicConsole::new(display)));
}
}
}
/// Print format string and its arguments to serial.
pub fn serial_write_fmt(fmt: Arguments) {
SerialWriter.write_fmt(fmt).unwrap();
}
/// Print format string and its arguments to serial.
pub fn serial_write(s: &str) {
SerialWriter.write_str(s).unwrap();
}
/// Print format string and its arguments to graphic console.
#[allow(unused_variables)]
pub fn graphic_console_write_fmt(fmt: Arguments) {
#[cfg(feature = "graphic")]
if let Some(cons) = GRAPHIC_CONSOLE.try_get() {
cons.lock().write_fmt(fmt).unwrap();
}
}
/// Print format string and its arguments to graphic console.
#[allow(unused_variables)]
pub fn graphic_console_write(s: &str) {
#[cfg(feature = "graphic")]
if let Some(cons) = GRAPHIC_CONSOLE.try_get() {
cons.lock().write_str(s).unwrap();
}
}
/// Print format string and its arguments to serial and graphic console (if exists).
pub fn console_write_fmt(fmt: Arguments) {
serial_write_fmt(fmt);
graphic_console_write_fmt(fmt);
}
/// Print a string to serial and graphic console (if exists).
pub fn console_write(s: &str) {
serial_write(s);
graphic_console_write(s);
}
/// Read buffer data from console (serial).
pub async fn console_read(buf: &mut [u8]) -> usize {
super::future::SerialReadFuture::new(buf).await
}

View File

@ -49,7 +49,7 @@ impl Future for SleepFuture {
} }
} }
#[must_use = "`serial_read()` does nothing unless polled/`await`-ed"] #[must_use = "`console_read()` does nothing unless polled/`await`-ed"]
pub(super) struct SerialReadFuture<'a> { pub(super) struct SerialReadFuture<'a> {
buf: &'a mut [u8], buf: &'a mut [u8],
} }

View File

@ -10,5 +10,5 @@ pub(super) mod vdso;
pub(super) mod vm; pub(super) mod vm;
pub mod addr; pub mod addr;
pub mod serial; pub mod console;
pub mod user; pub mod user;

View File

@ -1,31 +0,0 @@
use core::fmt::{Arguments, Result, Write};
use crate::drivers;
struct SerialWriter;
impl Write for SerialWriter {
fn write_str(&mut self, s: &str) -> Result {
if let Some(uart) = drivers::uart::first() {
uart.write_str(s).unwrap();
} else {
crate::hal_fn::serial::serial_write_early(s);
}
Ok(())
}
}
/// Print format string and its arguments to serial.
pub fn serial_write_fmt(fmt: Arguments) {
SerialWriter.write_fmt(fmt).unwrap();
}
/// Print a string to serial.
pub fn serial_write(s: &str) {
serial_write_fmt(format_args!("{}", s));
}
/// Read buffer data from serial.
pub async fn serial_read(buf: &mut [u8]) -> usize {
super::future::SerialReadFuture::new(buf).await
}

View File

@ -87,8 +87,8 @@ hal_fn_def! {
pub fn msi_register_handler(block: Range<usize>, msi_id: usize, handler: IrqHandler) -> HalResult; pub fn msi_register_handler(block: Range<usize>, msi_id: usize, handler: IrqHandler) -> HalResult;
} }
pub(crate) mod serial { pub(crate) mod console {
pub(crate) fn serial_write_early(_s: &str) {} pub(crate) fn console_write_early(_s: &str) {}
} }
pub mod context: common::context { pub mod context: common::context {

View File

@ -36,7 +36,7 @@ cfg_if! {
pub(crate) use config::KCONFIG; pub(crate) use config::KCONFIG;
pub(crate) use kernel_handler::KHANDLER; pub(crate) use kernel_handler::KHANDLER;
pub use common::{addr, defs::*, serial, user}; pub use common::{addr, console, defs::*, user};
pub use config::KernelConfig; pub use config::KernelConfig;
pub use imp::*; pub use imp::*;
pub use kernel_handler::KernelHandler; pub use kernel_handler::KernelHandler;

View File

@ -3,17 +3,16 @@ use alloc::sync::Arc;
use zcore_drivers::mock::uart::MockUart; use zcore_drivers::mock::uart::MockUart;
use zcore_drivers::{scheme::Scheme, Device}; use zcore_drivers::{scheme::Scheme, Device};
use crate::drivers;
pub(super) fn init() { pub(super) fn init() {
let uart = Arc::new(MockUart::new()); let uart = Arc::new(MockUart::new());
drivers::add_device(Device::Uart(uart.clone())); crate::drivers::add_device(Device::Uart(uart.clone()));
MockUart::start_irq_serve(move || uart.handle_irq(0)); MockUart::start_irq_serve(move || uart.handle_irq(0));
#[cfg(feature = "graphic")] #[cfg(feature = "graphic")]
{ {
use zcore_drivers::mock::display::MockDisplay; use zcore_drivers::mock::display::MockDisplay;
let display = Arc::new(MockDisplay::new(800, 600)); let display = Arc::new(MockDisplay::new(1280, 720));
drivers::add_device(Device::Display(display)); crate::drivers::add_device(Device::Display(display.clone()));
crate::console::init_graphic_console(display);
} }
} }

View File

@ -14,7 +14,7 @@ pub mod libos;
pub use super::hal_fn::{context, cpu, interrupt, rand}; pub use super::hal_fn::{context, cpu, interrupt, rand};
hal_fn_impl_default!(context, cpu, interrupt, rand, super::hal_fn::serial); hal_fn_impl_default!(context, cpu, interrupt, rand, super::hal_fn::console);
cfg_if! { cfg_if! {
if #[cfg(target_os = "linux")] { if #[cfg(target_os = "linux")] {

View File

@ -3,9 +3,9 @@ pub fn run_display_serve() {
use zcore_drivers::mock::display::sdl::SdlWindow; use zcore_drivers::mock::display::sdl::SdlWindow;
let display = crate::drivers::display::first_unwrap(); let display = crate::drivers::display::first_unwrap();
let mut window = SdlWindow::new("zcore-libos", display.info()); let mut window = SdlWindow::new("zcore-libos", display.clone());
while !window.is_quit() { while !window.is_quit() {
window.flush(display.as_ref()); window.flush();
std::thread::sleep(std::time::Duration::from_millis(10)); std::thread::sleep(std::time::Duration::from_millis(10));
} }
} }

View File

@ -28,24 +28,26 @@ async fn main() {
); );
} }
// run first process
let args: Vec<_> = std::env::args().skip(1).collect(); let args: Vec<_> = std::env::args().skip(1).collect();
let proc_name = args.join(" "); let proc_name = args.join(" ");
let envs = vec!["PATH=/usr/sbin:/usr/bin:/sbin:/bin:/usr/x86_64-alpine-linux-musl/bin".into()]; let envs = vec!["PATH=/usr/sbin:/usr/bin:/sbin:/bin:/usr/x86_64-alpine-linux-musl/bin".into()];
let hostfs = HostFS::new("rootfs"); // Run the first process.
let proc = run(args, envs, hostfs); let run_proc = async move {
let hostfs = HostFS::new("rootfs");
let wait_for_exit = async move { proc.wait_for_exit().await }; let proc = run(args, envs, hostfs);
proc.wait_for_exit().await
};
// If the graphic mode is on, run the process in another thread.
#[cfg(feature = "graphic")] #[cfg(feature = "graphic")]
let wait_for_exit = { let run_proc = {
let handle = async_std::task::spawn(wait_for_exit); let handle = async_std::task::spawn(run_proc);
kernel_hal::libos::run_display_serve(); kernel_hal::libos::run_display_serve();
handle handle
}; };
let code = wait_for_exit.await; let code = run_proc.await;
log::info!("process {:?} exited with {}", proc_name, code); log::info!("process {:?} exited with {}", proc_name, code);
std::process::exit(code as i32); std::process::exit(code as i32);
} }

View File

@ -132,7 +132,7 @@ impl INode for Stdout {
fn write_at(&self, _offset: usize, buf: &[u8]) -> Result<usize> { fn write_at(&self, _offset: usize, buf: &[u8]) -> Result<usize> {
// we do not care the utf-8 things, we just want to print it! // we do not care the utf-8 things, we just want to print it!
let s = unsafe { core::str::from_utf8_unchecked(buf) }; let s = unsafe { core::str::from_utf8_unchecked(buf) };
kernel_hal::serial::serial_write(s); kernel_hal::console::console_write(s);
Ok(buf.len()) Ok(buf.len())
} }
fn poll(&self) -> Result<PollStatus> { fn poll(&self) -> Result<PollStatus> {

View File

@ -22,7 +22,7 @@ impl Syscall<'_> {
&mut self, &mut self,
mut ufds: UserInOutPtr<PollFd>, mut ufds: UserInOutPtr<PollFd>,
nfds: usize, nfds: usize,
timeout_msecs: usize, timeout_msecs: isize,
) -> SysResult { ) -> SysResult {
let mut polls = ufds.read_array(nfds)?; let mut polls = ufds.read_array(nfds)?;
info!( info!(
@ -32,7 +32,7 @@ impl Syscall<'_> {
#[must_use = "future does nothing unless polled/`await`-ed"] #[must_use = "future does nothing unless polled/`await`-ed"]
struct PollFuture<'a> { struct PollFuture<'a> {
polls: &'a mut Vec<PollFd>, polls: &'a mut Vec<PollFd>,
timeout_msecs: usize, timeout_msecs: isize,
begin_time_ms: usize, begin_time_ms: usize,
syscall: &'a Syscall<'a>, syscall: &'a Syscall<'a>,
} }
@ -79,23 +79,23 @@ impl Syscall<'_> {
return Poll::Ready(Ok(events)); return Poll::Ready(Ok(events));
} }
if self.timeout_msecs == 0 { match self.timeout_msecs {
// no timeout, return now; // no timeout, return now;
return Poll::Ready(Ok(0)); 0 => return Poll::Ready(Ok(0)),
} else { 1.. => {
let waker = cx.waker().clone(); let current_time_ms = TimeVal::now().to_msec();
timer::timer_set( let deadline = self.begin_time_ms + self.timeout_msecs as usize;
timer::deadline_after(Duration::from_millis(self.timeout_msecs as u64)), if current_time_ms >= deadline {
Box::new(move |_| waker.wake()), return Poll::Ready(Ok(0));
); } else {
} let waker = cx.waker().clone();
timer::timer_set(
let current_time_ms = TimeVal::now().to_msec(); Duration::from_millis(deadline as u64),
// infinity check Box::new(move |_| waker.wake()),
if self.timeout_msecs < (1 << 31) );
&& current_time_ms - self.begin_time_ms >= self.timeout_msecs as usize }
{ }
return Poll::Ready(Ok(0)); _ => {}
} }
Poll::Pending Poll::Pending
@ -122,13 +122,13 @@ impl Syscall<'_> {
timeout: UserInPtr<TimeSpec>, timeout: UserInPtr<TimeSpec>,
) -> SysResult { ) -> SysResult {
let timeout_msecs = if timeout.is_null() { let timeout_msecs = if timeout.is_null() {
1 << 31 // infinity -1
} else { } else {
let timeout = timeout.read().unwrap(); let timeout = timeout.read().unwrap();
timeout.to_msec() timeout.to_msec() as isize
}; };
self.sys_poll(ufds, nfds, timeout_msecs as usize).await self.sys_poll(ufds, nfds, timeout_msecs).await
} }
/// similar to select, but have sigmask argument /// similar to select, but have sigmask argument
@ -169,10 +169,10 @@ impl Syscall<'_> {
let timeout_msecs = if !timeout.is_null() { let timeout_msecs = if !timeout.is_null() {
let timeout = timeout.read()?; let timeout = timeout.read()?;
timeout.to_msec() timeout.to_msec() as isize
} else { } else {
// infinity // infinity
1 << 31 -1
}; };
let begin_time_ms = TimeVal::now().to_msec(); let begin_time_ms = TimeVal::now().to_msec();
@ -181,7 +181,7 @@ impl Syscall<'_> {
read_fds: &'a mut FdSet, read_fds: &'a mut FdSet,
write_fds: &'a mut FdSet, write_fds: &'a mut FdSet,
err_fds: &'a mut FdSet, err_fds: &'a mut FdSet,
timeout_msecs: usize, timeout_msecs: isize,
begin_time_ms: usize, begin_time_ms: usize,
syscall: &'a Syscall<'a>, syscall: &'a Syscall<'a>,
} }
@ -225,25 +225,24 @@ impl Syscall<'_> {
return Poll::Ready(Ok(events)); return Poll::Ready(Ok(events));
} }
if self.timeout_msecs == 0 { match self.timeout_msecs {
// no timeout, return now; // no timeout, return now;
return Poll::Ready(Ok(0)); 0 => return Poll::Ready(Ok(0)),
} else { 1.. => {
let waker = cx.waker().clone(); let current_time_ms = TimeVal::now().to_msec();
timer::timer_set( let deadline = self.begin_time_ms + self.timeout_msecs as usize;
timer::deadline_after(Duration::from_millis(self.timeout_msecs as u64)), if current_time_ms >= deadline {
Box::new(move |_| waker.wake()), return Poll::Ready(Ok(0));
); } else {
let waker = cx.waker().clone();
timer::timer_set(
Duration::from_millis(deadline as u64),
Box::new(move |_| waker.wake()),
);
}
}
_ => {}
} }
let current_time_ms = TimeVal::now().to_msec();
// infinity check
if self.timeout_msecs < (1 << 31)
&& current_time_ms - self.begin_time_ms >= self.timeout_msecs as usize
{
return Poll::Ready(Ok(0));
}
Poll::Pending Poll::Pending
} }
} }

View File

@ -269,7 +269,7 @@ impl Syscall<'_> {
Sys::OPEN => self.sys_open(a0.into(), a1, a2), Sys::OPEN => self.sys_open(a0.into(), a1, a2),
Sys::STAT => self.sys_stat(a0.into(), a1.into()), Sys::STAT => self.sys_stat(a0.into(), a1.into()),
Sys::LSTAT => self.sys_lstat(a0.into(), a1.into()), Sys::LSTAT => self.sys_lstat(a0.into(), a1.into()),
Sys::POLL => self.sys_poll(a0.into(), a1, a2).await, Sys::POLL => self.sys_poll(a0.into(), a1, a2 as _).await,
Sys::ACCESS => self.sys_access(a0.into(), a1), Sys::ACCESS => self.sys_access(a0.into(), a1),
Sys::PIPE => self.sys_pipe(a0.into()), Sys::PIPE => self.sys_pipe(a0.into()),
Sys::SELECT => { Sys::SELECT => {

View File

@ -37,12 +37,12 @@ macro_rules! with_color {
} }
fn print_in_color(args: fmt::Arguments, color_code: u8) { fn print_in_color(args: fmt::Arguments, color_code: u8) {
kernel_hal::serial::serial_write_fmt(with_color!(args, color_code)); kernel_hal::console::console_write_fmt(with_color!(args, color_code));
} }
#[allow(dead_code)] #[allow(dead_code)]
pub fn print(args: fmt::Arguments) { pub fn print(args: fmt::Arguments) {
kernel_hal::serial::serial_write_fmt(args); kernel_hal::console::console_write_fmt(args);
} }
struct SimpleLogger; struct SimpleLogger;

View File

@ -6,7 +6,7 @@ impl Syscall<'_> {
pub fn sys_debug_write(&self, buf: UserInPtr<u8>, len: usize) -> ZxResult { pub fn sys_debug_write(&self, buf: UserInPtr<u8>, len: usize) -> ZxResult {
info!("debug.write: buf=({:?}; {:#x})", buf, len); info!("debug.write: buf=({:?}; {:#x})", buf, len);
let data = buf.read_array(len)?; let data = buf.read_array(len)?;
kernel_hal::serial::serial_write(core::str::from_utf8(&data).unwrap()); kernel_hal::console::console_write(core::str::from_utf8(&data).unwrap());
Ok(()) Ok(())
} }
@ -26,7 +26,7 @@ impl Syscall<'_> {
proc.get_object::<Resource>(handle)? proc.get_object::<Resource>(handle)?
.validate(ResourceKind::ROOT)?; .validate(ResourceKind::ROOT)?;
let mut vec = vec![0u8; buf_size as usize]; let mut vec = vec![0u8; buf_size as usize];
let len = kernel_hal::serial::serial_read(&mut vec).await; let len = kernel_hal::console::console_read(&mut vec).await;
buf.write_array(&vec[..len])?; buf.write_array(&vec[..len])?;
actual.write(len as u32)?; actual.write(len as u32)?;
Ok(()) Ok(())

View File

@ -54,9 +54,9 @@ impl Syscall<'_> {
let dlog = proc.get_object_with_rights::<DebugLog>(handle_value, Rights::WRITE)?; let dlog = proc.get_object_with_rights::<DebugLog>(handle_value, Rights::WRITE)?;
dlog.write(Severity::Info, options, self.thread.id(), proc.id(), &data); dlog.write(Severity::Info, options, self.thread.id(), proc.id(), &data);
// print to kernel console // print to kernel console
kernel_hal::serial::serial_write(&data); kernel_hal::console::console_write(&data);
if data.as_bytes().last() != Some(&b'\n') { if data.as_bytes().last() != Some(&b'\n') {
kernel_hal::serial::serial_write("\n"); kernel_hal::console::console_write("\n");
} }
Ok(()) Ok(())
} }