forked from rcore-os/zCore
drivers: support graphic console output
This commit is contained in:
parent
dd835e5af7
commit
d8e6aca2f9
|
@ -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
|
||||
|
||||
[features]
|
||||
graphic = []
|
||||
graphic = ["rcore-console"]
|
||||
mock = ["async-std", "sdl2"]
|
||||
virtio = ["virtio-drivers"]
|
||||
|
||||
|
@ -21,6 +21,7 @@ lazy_static = "1.4"
|
|||
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" }
|
||||
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]
|
||||
async-std = { version = "1.10", optional = true }
|
||||
|
|
|
@ -1 +1 @@
|
|||
pub use crate::scheme::display::{ColorDepth, ColorFormat, DisplayInfo};
|
||||
pub use crate::scheme::display::{ColorFormat, DisplayInfo, RgbColor};
|
||||
|
|
|
@ -9,8 +9,6 @@ extern crate log;
|
|||
use alloc::sync::Arc;
|
||||
use core::fmt;
|
||||
|
||||
mod utils;
|
||||
|
||||
#[cfg(feature = "mock")]
|
||||
pub mod mock;
|
||||
|
||||
|
@ -23,6 +21,7 @@ pub mod io;
|
|||
pub mod irq;
|
||||
pub mod scheme;
|
||||
pub mod uart;
|
||||
pub mod utils;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum DeviceError {
|
||||
|
|
|
@ -2,7 +2,7 @@ pub mod sdl;
|
|||
|
||||
use alloc::vec::Vec;
|
||||
|
||||
use crate::display::{ColorDepth, ColorFormat, DisplayInfo};
|
||||
use crate::display::{ColorFormat, DisplayInfo};
|
||||
use crate::scheme::{DisplayScheme, Scheme};
|
||||
|
||||
pub struct MockDisplay {
|
||||
|
@ -12,15 +12,13 @@ pub struct MockDisplay {
|
|||
|
||||
impl MockDisplay {
|
||||
pub fn new(width: u32, height: u32) -> Self {
|
||||
let depth = ColorDepth::ColorDepth32;
|
||||
let format = ColorFormat::RGBA8888;
|
||||
let fb_size = (width * height * depth.bytes() as u32) as usize;
|
||||
let format = ColorFormat::RGB888;
|
||||
let fb_size = (width * height * format.bytes() as u32) as usize;
|
||||
let info = DisplayInfo {
|
||||
width,
|
||||
height,
|
||||
fb_size,
|
||||
depth,
|
||||
format,
|
||||
fb_size,
|
||||
};
|
||||
let fb = vec![0; fb_size];
|
||||
Self { info, fb }
|
||||
|
@ -34,10 +32,12 @@ impl Scheme for MockDisplay {
|
|||
}
|
||||
|
||||
impl DisplayScheme for MockDisplay {
|
||||
#[inline]
|
||||
fn info(&self) -> DisplayInfo {
|
||||
self.info
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn raw_fb(&self) -> &mut [u8] {
|
||||
core::slice::from_raw_parts_mut(self.fb.as_ptr() as _, self.info.fb_size)
|
||||
}
|
||||
|
|
|
@ -1,47 +1,48 @@
|
|||
use alloc::sync::Arc;
|
||||
|
||||
use sdl2::{event::Event, keyboard::Keycode, EventPump};
|
||||
use sdl2::{pixels::PixelFormatEnum, render::Canvas, video::Window};
|
||||
|
||||
use crate::display::{ColorFormat, DisplayInfo};
|
||||
use crate::display::ColorFormat;
|
||||
use crate::scheme::DisplayScheme;
|
||||
|
||||
pub struct SdlWindow {
|
||||
canvas: Canvas<Window>,
|
||||
event_pump: EventPump,
|
||||
info: DisplayInfo,
|
||||
display: Arc<dyn DisplayScheme>,
|
||||
}
|
||||
|
||||
impl SdlWindow {
|
||||
pub fn new(title: &str, info: DisplayInfo) -> Self {
|
||||
assert_eq!(info.format, ColorFormat::RGBA8888);
|
||||
pub fn new(title: &str, display: Arc<dyn DisplayScheme>) -> Self {
|
||||
let sdl_context = sdl2::init().unwrap();
|
||||
let video_subsystem = sdl_context.video().unwrap();
|
||||
let window = video_subsystem
|
||||
.window(title, info.width, info.height)
|
||||
.window(title, display.info().width, display.info().height)
|
||||
.position_centered()
|
||||
.build()
|
||||
.unwrap();
|
||||
|
||||
let event_pump = sdl_context.event_pump().unwrap();
|
||||
let mut canvas = window.into_canvas().build().unwrap();
|
||||
canvas.clear();
|
||||
canvas.present();
|
||||
Self {
|
||||
info,
|
||||
let canvas = window.into_canvas().build().unwrap();
|
||||
let mut ret = Self {
|
||||
display,
|
||||
canvas,
|
||||
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 format: PixelFormatEnum = info.format.into();
|
||||
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();
|
||||
|
||||
let buf = unsafe { display.raw_fb() };
|
||||
texture
|
||||
.update(None, buf, display.info().width as usize * 4)
|
||||
.unwrap();
|
||||
let buf = unsafe { self.display.raw_fb() };
|
||||
texture.update(None, buf, info.pitch() as usize).unwrap();
|
||||
self.canvas.copy(&texture, None, None).unwrap();
|
||||
self.canvas.present();
|
||||
}
|
||||
|
@ -60,3 +61,15 @@ impl SdlWindow {
|
|||
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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,21 +1,65 @@
|
|||
use super::Scheme;
|
||||
use crate::{DeviceError, DeviceResult};
|
||||
|
||||
#[repr(u8)]
|
||||
#[repr(transparent)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum ColorDepth {
|
||||
ColorDepth8 = 8,
|
||||
ColorDepth16 = 16,
|
||||
ColorDepth24 = 24,
|
||||
ColorDepth32 = 32,
|
||||
pub struct RgbColor(u32);
|
||||
|
||||
impl RgbColor {
|
||||
#[inline]
|
||||
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)]
|
||||
pub enum ColorFormat {
|
||||
RGB332,
|
||||
RGB565,
|
||||
RGB888,
|
||||
RGBA8888, // QEMU and low version RPi use RGBA
|
||||
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)]
|
||||
|
@ -24,28 +68,17 @@ pub struct DisplayInfo {
|
|||
pub width: u32,
|
||||
/// visible height
|
||||
pub height: u32,
|
||||
/// frame buffer size
|
||||
pub fb_size: usize,
|
||||
|
||||
/// bits per pixel
|
||||
pub depth: ColorDepth,
|
||||
/// color encoding format of RGBA
|
||||
pub format: ColorFormat,
|
||||
/// frame buffer size
|
||||
pub fb_size: usize,
|
||||
}
|
||||
|
||||
impl ColorDepth {
|
||||
pub fn try_from(depth: u8) -> Result<Self, &'static str> {
|
||||
match depth {
|
||||
8 => Ok(Self::ColorDepth8),
|
||||
16 => Ok(Self::ColorDepth16),
|
||||
24 => Ok(Self::ColorDepth24),
|
||||
32 => Ok(Self::ColorDepth32),
|
||||
_ => Err("unsupported color depth"),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn bytes(self) -> u8 {
|
||||
self as u8 / 8
|
||||
impl DisplayInfo {
|
||||
/// Number of bytes between each row of the frame buffer.
|
||||
#[inline]
|
||||
pub const fn pitch(self) -> u32 {
|
||||
self.width * self.format.bytes() as u32
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -53,5 +86,51 @@ pub trait DisplayScheme: Scheme {
|
|||
fn info(&self) -> DisplayInfo;
|
||||
|
||||
#[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];
|
||||
|
||||
#[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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -2,6 +2,13 @@ mod event_listener;
|
|||
mod id_allocator;
|
||||
mod irq_manager;
|
||||
|
||||
pub(super) use event_listener::EventListener;
|
||||
#[cfg(feature = "graphic")]
|
||||
mod graphic_console;
|
||||
|
||||
pub(super) use id_allocator::IdAllocator;
|
||||
pub(super) use irq_manager::IrqManager;
|
||||
|
||||
pub use event_listener::EventListener;
|
||||
|
||||
#[cfg(feature = "graphic")]
|
||||
pub use graphic_console::GraphicConsole;
|
||||
|
|
|
@ -33,7 +33,6 @@ async-std = { version = "1.10", optional = true }
|
|||
executor = { git = "https://github.com/rcore-os/executor.git", rev = "a2d02ee9" }
|
||||
naive-timer = "0.2.0"
|
||||
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
|
||||
[target.'cfg(all(target_os = "none", target_arch = "x86_64"))'.dependencies]
|
||||
|
|
|
@ -48,8 +48,8 @@ pub fn send_ipi(sipi_value: usize) {
|
|||
}
|
||||
|
||||
hal_fn_impl! {
|
||||
impl mod crate::hal_fn::serial {
|
||||
fn serial_write_early(s: &str) {
|
||||
impl mod crate::hal_fn::console {
|
||||
fn console_write_early(s: &str) {
|
||||
for c in s.bytes() {
|
||||
console_putchar(c as usize);
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ pub mod special;
|
|||
pub mod timer;
|
||||
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};
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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> {
|
||||
buf: &'a mut [u8],
|
||||
}
|
||||
|
|
|
@ -10,5 +10,5 @@ pub(super) mod vdso;
|
|||
pub(super) mod vm;
|
||||
|
||||
pub mod addr;
|
||||
pub mod serial;
|
||||
pub mod console;
|
||||
pub mod user;
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -87,8 +87,8 @@ hal_fn_def! {
|
|||
pub fn msi_register_handler(block: Range<usize>, msi_id: usize, handler: IrqHandler) -> HalResult;
|
||||
}
|
||||
|
||||
pub(crate) mod serial {
|
||||
pub(crate) fn serial_write_early(_s: &str) {}
|
||||
pub(crate) mod console {
|
||||
pub(crate) fn console_write_early(_s: &str) {}
|
||||
}
|
||||
|
||||
pub mod context: common::context {
|
||||
|
|
|
@ -36,7 +36,7 @@ cfg_if! {
|
|||
pub(crate) use config::KCONFIG;
|
||||
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 imp::*;
|
||||
pub use kernel_handler::KernelHandler;
|
||||
|
|
|
@ -3,17 +3,16 @@ use alloc::sync::Arc;
|
|||
use zcore_drivers::mock::uart::MockUart;
|
||||
use zcore_drivers::{scheme::Scheme, Device};
|
||||
|
||||
use crate::drivers;
|
||||
|
||||
pub(super) fn init() {
|
||||
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));
|
||||
|
||||
#[cfg(feature = "graphic")]
|
||||
{
|
||||
use zcore_drivers::mock::display::MockDisplay;
|
||||
let display = Arc::new(MockDisplay::new(800, 600));
|
||||
drivers::add_device(Device::Display(display));
|
||||
let display = Arc::new(MockDisplay::new(1280, 720));
|
||||
crate::drivers::add_device(Device::Display(display.clone()));
|
||||
crate::console::init_graphic_console(display);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ pub mod libos;
|
|||
|
||||
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! {
|
||||
if #[cfg(target_os = "linux")] {
|
||||
|
|
|
@ -3,9 +3,9 @@ pub fn run_display_serve() {
|
|||
use zcore_drivers::mock::display::sdl::SdlWindow;
|
||||
|
||||
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() {
|
||||
window.flush(display.as_ref());
|
||||
window.flush();
|
||||
std::thread::sleep(std::time::Duration::from_millis(10));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,24 +28,26 @@ async fn main() {
|
|||
);
|
||||
}
|
||||
|
||||
// run first process
|
||||
let args: Vec<_> = std::env::args().skip(1).collect();
|
||||
let proc_name = args.join(" ");
|
||||
let envs = vec!["PATH=/usr/sbin:/usr/bin:/sbin:/bin:/usr/x86_64-alpine-linux-musl/bin".into()];
|
||||
|
||||
// Run the first process.
|
||||
let run_proc = async move {
|
||||
let hostfs = HostFS::new("rootfs");
|
||||
let proc = run(args, envs, hostfs);
|
||||
proc.wait_for_exit().await
|
||||
};
|
||||
|
||||
let wait_for_exit = async move { proc.wait_for_exit().await };
|
||||
|
||||
// If the graphic mode is on, run the process in another thread.
|
||||
#[cfg(feature = "graphic")]
|
||||
let wait_for_exit = {
|
||||
let handle = async_std::task::spawn(wait_for_exit);
|
||||
let run_proc = {
|
||||
let handle = async_std::task::spawn(run_proc);
|
||||
kernel_hal::libos::run_display_serve();
|
||||
handle
|
||||
};
|
||||
|
||||
let code = wait_for_exit.await;
|
||||
let code = run_proc.await;
|
||||
log::info!("process {:?} exited with {}", proc_name, code);
|
||||
std::process::exit(code as i32);
|
||||
}
|
||||
|
|
|
@ -132,7 +132,7 @@ impl INode for Stdout {
|
|||
fn write_at(&self, _offset: usize, buf: &[u8]) -> Result<usize> {
|
||||
// we do not care the utf-8 things, we just want to print it!
|
||||
let s = unsafe { core::str::from_utf8_unchecked(buf) };
|
||||
kernel_hal::serial::serial_write(s);
|
||||
kernel_hal::console::console_write(s);
|
||||
Ok(buf.len())
|
||||
}
|
||||
fn poll(&self) -> Result<PollStatus> {
|
||||
|
|
|
@ -22,7 +22,7 @@ impl Syscall<'_> {
|
|||
&mut self,
|
||||
mut ufds: UserInOutPtr<PollFd>,
|
||||
nfds: usize,
|
||||
timeout_msecs: usize,
|
||||
timeout_msecs: isize,
|
||||
) -> SysResult {
|
||||
let mut polls = ufds.read_array(nfds)?;
|
||||
info!(
|
||||
|
@ -32,7 +32,7 @@ impl Syscall<'_> {
|
|||
#[must_use = "future does nothing unless polled/`await`-ed"]
|
||||
struct PollFuture<'a> {
|
||||
polls: &'a mut Vec<PollFd>,
|
||||
timeout_msecs: usize,
|
||||
timeout_msecs: isize,
|
||||
begin_time_ms: usize,
|
||||
syscall: &'a Syscall<'a>,
|
||||
}
|
||||
|
@ -79,23 +79,23 @@ impl Syscall<'_> {
|
|||
return Poll::Ready(Ok(events));
|
||||
}
|
||||
|
||||
if self.timeout_msecs == 0 {
|
||||
match self.timeout_msecs {
|
||||
// no timeout, return now;
|
||||
0 => return Poll::Ready(Ok(0)),
|
||||
1.. => {
|
||||
let current_time_ms = TimeVal::now().to_msec();
|
||||
let deadline = self.begin_time_ms + self.timeout_msecs as usize;
|
||||
if current_time_ms >= deadline {
|
||||
return Poll::Ready(Ok(0));
|
||||
} else {
|
||||
let waker = cx.waker().clone();
|
||||
timer::timer_set(
|
||||
timer::deadline_after(Duration::from_millis(self.timeout_msecs as u64)),
|
||||
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
|
||||
|
@ -122,13 +122,13 @@ impl Syscall<'_> {
|
|||
timeout: UserInPtr<TimeSpec>,
|
||||
) -> SysResult {
|
||||
let timeout_msecs = if timeout.is_null() {
|
||||
1 << 31 // infinity
|
||||
-1
|
||||
} else {
|
||||
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
|
||||
|
@ -169,10 +169,10 @@ impl Syscall<'_> {
|
|||
|
||||
let timeout_msecs = if !timeout.is_null() {
|
||||
let timeout = timeout.read()?;
|
||||
timeout.to_msec()
|
||||
timeout.to_msec() as isize
|
||||
} else {
|
||||
// infinity
|
||||
1 << 31
|
||||
-1
|
||||
};
|
||||
let begin_time_ms = TimeVal::now().to_msec();
|
||||
|
||||
|
@ -181,7 +181,7 @@ impl Syscall<'_> {
|
|||
read_fds: &'a mut FdSet,
|
||||
write_fds: &'a mut FdSet,
|
||||
err_fds: &'a mut FdSet,
|
||||
timeout_msecs: usize,
|
||||
timeout_msecs: isize,
|
||||
begin_time_ms: usize,
|
||||
syscall: &'a Syscall<'a>,
|
||||
}
|
||||
|
@ -225,25 +225,24 @@ impl Syscall<'_> {
|
|||
return Poll::Ready(Ok(events));
|
||||
}
|
||||
|
||||
if self.timeout_msecs == 0 {
|
||||
match self.timeout_msecs {
|
||||
// no timeout, return now;
|
||||
0 => return Poll::Ready(Ok(0)),
|
||||
1.. => {
|
||||
let current_time_ms = TimeVal::now().to_msec();
|
||||
let deadline = self.begin_time_ms + self.timeout_msecs as usize;
|
||||
if current_time_ms >= deadline {
|
||||
return Poll::Ready(Ok(0));
|
||||
} else {
|
||||
let waker = cx.waker().clone();
|
||||
timer::timer_set(
|
||||
timer::deadline_after(Duration::from_millis(self.timeout_msecs as u64)),
|
||||
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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -269,7 +269,7 @@ impl Syscall<'_> {
|
|||
Sys::OPEN => self.sys_open(a0.into(), a1, a2),
|
||||
Sys::STAT => self.sys_stat(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::PIPE => self.sys_pipe(a0.into()),
|
||||
Sys::SELECT => {
|
||||
|
|
|
@ -37,12 +37,12 @@ macro_rules! with_color {
|
|||
}
|
||||
|
||||
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)]
|
||||
pub fn print(args: fmt::Arguments) {
|
||||
kernel_hal::serial::serial_write_fmt(args);
|
||||
kernel_hal::console::console_write_fmt(args);
|
||||
}
|
||||
|
||||
struct SimpleLogger;
|
||||
|
|
|
@ -6,7 +6,7 @@ impl Syscall<'_> {
|
|||
pub fn sys_debug_write(&self, buf: UserInPtr<u8>, len: usize) -> ZxResult {
|
||||
info!("debug.write: buf=({:?}; {:#x})", buf, 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(())
|
||||
}
|
||||
|
||||
|
@ -26,7 +26,7 @@ impl Syscall<'_> {
|
|||
proc.get_object::<Resource>(handle)?
|
||||
.validate(ResourceKind::ROOT)?;
|
||||
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])?;
|
||||
actual.write(len as u32)?;
|
||||
Ok(())
|
||||
|
|
|
@ -54,9 +54,9 @@ impl Syscall<'_> {
|
|||
let dlog = proc.get_object_with_rights::<DebugLog>(handle_value, Rights::WRITE)?;
|
||||
dlog.write(Severity::Info, options, self.thread.id(), proc.id(), &data);
|
||||
// print to kernel console
|
||||
kernel_hal::serial::serial_write(&data);
|
||||
kernel_hal::console::console_write(&data);
|
||||
if data.as_bytes().last() != Some(&b'\n') {
|
||||
kernel_hal::serial::serial_write("\n");
|
||||
kernel_hal::console::console_write("\n");
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue