From 61eb0d1ca8484145392f413924e7133ecf194f3e Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Wed, 21 Sep 2016 12:18:48 -0600 Subject: [PATCH] WIP: Userspace console --- drivers/vesad/Cargo.toml | 1 + drivers/vesad/src/display.rs | 8 +-- drivers/vesad/src/main.rs | 115 ++++++++++++++++++++++++++++++--- drivers/vesad/src/primitive.rs | 15 ++++- initfs/etc/init.rc | 6 +- kernel/lib.rs | 2 +- kernel/scheme/user.rs | 2 +- schemes/example/src/main.rs | 18 ++++++ 8 files changed, 148 insertions(+), 19 deletions(-) diff --git a/drivers/vesad/Cargo.toml b/drivers/vesad/Cargo.toml index eb9335b..f8482a4 100644 --- a/drivers/vesad/Cargo.toml +++ b/drivers/vesad/Cargo.toml @@ -3,4 +3,5 @@ name = "vesad" version = "0.1.0" [dependencies] +ransid = { git = "https://github.com/redox-os/ransid.git", branch = "new_api" } syscall = { path = "../../syscall/" } diff --git a/drivers/vesad/src/display.rs b/drivers/vesad/src/display.rs index f1befd3..9975c8d 100644 --- a/drivers/vesad/src/display.rs +++ b/drivers/vesad/src/display.rs @@ -1,6 +1,6 @@ use std::cmp; -use primitive::{fast_set, fast_set64, fast_copy64}; +use primitive::{fast_set32, fast_set64, fast_copy64}; static FONT: &'static [u8] = include_bytes!("../../../res/unifont.font"); @@ -42,8 +42,8 @@ impl Display { let mut rows = end_y - start_y; while rows > 0 { unsafe { - fast_set(offscreen_ptr as *mut u32, color, len); - fast_set(onscreen_ptr as *mut u32, color, len); + fast_set32(offscreen_ptr as *mut u32, color, len); + fast_set32(onscreen_ptr as *mut u32, color, len); } offscreen_ptr += stride; onscreen_ptr += stride; @@ -52,7 +52,7 @@ impl Display { } /// Draw a character - fn char(&mut self, x: usize, y: usize, character: char, color: u32) { + pub fn char(&mut self, x: usize, y: usize, character: char, color: u32) { if x + 8 <= self.width && y + 16 <= self.height { let mut font_i = 16 * (character as usize); let font_end = font_i + 16; diff --git a/drivers/vesad/src/main.rs b/drivers/vesad/src/main.rs index 1cd185a..a0022d5 100644 --- a/drivers/vesad/src/main.rs +++ b/drivers/vesad/src/main.rs @@ -1,22 +1,108 @@ #![feature(alloc)] #![feature(asm)] #![feature(heap_api)] +#![feature(question_mark)] extern crate alloc; +extern crate ransid; extern crate syscall; +use std::cell::RefCell; +use std::collections::BTreeMap; use std::fs::File; -use std::{slice, thread}; -use syscall::{physmap, physunmap, MAP_WRITE, MAP_WRITE_COMBINE}; +use std::io::{Read, Write}; +use std::sync::atomic::{AtomicUsize, Ordering}; +use std::{cmp, slice, thread}; +use ransid::{Console, Event}; +use syscall::{physmap, physunmap, Error, EINVAL, EBADF, Packet, Result, Scheme, SEEK_SET, SEEK_CUR, SEEK_END, MAP_WRITE, MAP_WRITE_COMBINE}; use display::Display; use mode_info::VBEModeInfo; -use primitive::fast_set64; +use primitive::{fast_copy, fast_set64}; pub mod display; pub mod mode_info; pub mod primitive; +struct DisplayScheme { + console: RefCell, + display: RefCell, + next_id: AtomicUsize, + handles: RefCell> +} + +impl Scheme for DisplayScheme { + fn open(&self, _path: &[u8], _flags: usize) -> Result { + Ok(0) + } + + fn dup(&self, _id: usize) -> Result { + Ok(0) + } + + fn write(&self, _id: usize, buf: &[u8]) -> Result { + let mut display = self.display.borrow_mut(); + self.console.borrow_mut().write(buf, |event| { + match event { + Event::Char { x, y, c, color, .. } => display.char(x * 8, y * 16, c, color.data), + Event::Rect { x, y, w, h, color } => display.rect(x * 8, y * 16, w * 8, h * 16, color.data), + Event::Scroll { rows, color } => display.scroll(rows * 16, color.data) + } + }); + Ok(buf.len()) + } + + fn close(&self, id: usize) -> Result { + Ok(0) + } +} + +/* +struct DisplayScheme { + display: RefCell, + next_id: AtomicUsize, + handles: RefCell> +} + +impl Scheme for DisplayScheme { + fn open(&self, _path: &[u8], _flags: usize) -> Result { + let id = self.next_id.fetch_add(1, Ordering::SeqCst); + self.handles.borrow_mut().insert(id, 0); + Ok(id) + } + + fn write(&self, id: usize, buf: &[u8]) -> Result { + let mut handles = self.handles.borrow_mut(); + let mut seek = handles.get_mut(&id).ok_or(Error::new(EBADF))?; + let mut display = self.display.borrow_mut(); + let len = cmp::min(buf.len(), display.offscreen.len() * 4 - *seek); + unsafe { + fast_copy((display.offscreen.as_mut_ptr() as usize + *seek) as *mut u8, buf.as_ptr(), len); + fast_copy((display.onscreen.as_mut_ptr() as usize + *seek) as *mut u8, buf.as_ptr(), len); + } + *seek += len; + Ok(len) + } + + fn seek(&self, id: usize, pos: usize, whence: usize) -> Result { + let mut handles = self.handles.borrow_mut(); + let mut seek = handles.get_mut(&id).ok_or(Error::new(EBADF))?; + let len = self.display.borrow().offscreen.len() * 4; + *seek = match whence { + SEEK_SET => cmp::min(len, pos), + SEEK_CUR => cmp::max(0, cmp::min(len as isize, *seek as isize + pos as isize)) as usize, + SEEK_END => cmp::max(0, cmp::min(len as isize, len as isize + pos as isize)) as usize, + _ => return Err(Error::new(EINVAL)) + }; + Ok(*seek) + } + + fn close(&self, id: usize) -> Result { + self.handles.borrow_mut().remove(&id).ok_or(Error::new(EBADF)).and(Ok(0)) + } +} +*/ + fn main() { let width; let height; @@ -35,7 +121,7 @@ fn main() { if physbaseptr > 0 { thread::spawn(move || { let mut socket = File::create(":display").expect("vesad: failed to create display scheme"); - + let size = width * height; let onscreen = unsafe { physmap(physbaseptr as usize, size * 4, MAP_WRITE | MAP_WRITE_COMBINE).expect("vesad: failed to map VBE LFB") }; @@ -44,12 +130,23 @@ fn main() { let offscreen = unsafe { alloc::heap::allocate(size * 4, 4096) }; unsafe { fast_set64(offscreen as *mut u64, 0, size/2) }; - let mut display = Display::new(width, height, - unsafe { slice::from_raw_parts_mut(onscreen as *mut u32, size) }, - unsafe { slice::from_raw_parts_mut(offscreen as *mut u32, size) } - ); + let scheme = DisplayScheme { + console: RefCell::new(Console::new(width/8, height/16)), + display: RefCell::new(Display::new(width, height, + unsafe { slice::from_raw_parts_mut(onscreen as *mut u32, size) }, + unsafe { slice::from_raw_parts_mut(offscreen as *mut u32, size) } + )), + next_id: AtomicUsize::new(0), + handles: RefCell::new(BTreeMap::new()) + }; - display.rect(100, 100, 100, 100, 0xFF0000); + loop { + let mut packet = Packet::default(); + socket.read(&mut packet); + //println!("vesad: {:?}", packet); + scheme.handle(&mut packet); + socket.write(&packet); + } }); } } diff --git a/drivers/vesad/src/primitive.rs b/drivers/vesad/src/primitive.rs index e3bdc25..8427745 100644 --- a/drivers/vesad/src/primitive.rs +++ b/drivers/vesad/src/primitive.rs @@ -1,3 +1,16 @@ +#[cfg(target_arch = "x86_64")] +#[allow(unused_assignments)] +#[inline(always)] +#[cold] +pub unsafe fn fast_copy(dst: *mut u8, src: *const u8, len: usize) { + asm!("cld + rep movsb" + : + : "{rdi}"(dst as usize), "{rsi}"(src as usize), "{rcx}"(len) + : "cc", "memory" + : "intel", "volatile"); +} + #[cfg(target_arch = "x86_64")] #[allow(unused_assignments)] #[inline(always)] @@ -15,7 +28,7 @@ pub unsafe fn fast_copy64(dst: *mut u64, src: *const u64, len: usize) { #[allow(unused_assignments)] #[inline(always)] #[cold] -pub unsafe fn fast_set(dst: *mut u32, src: u32, len: usize) { +pub unsafe fn fast_set32(dst: *mut u32, src: u32, len: usize) { asm!("cld rep stosd" : diff --git a/initfs/etc/init.rc b/initfs/etc/init.rc index b24016f..c66bf29 100644 --- a/initfs/etc/init.rc +++ b/initfs/etc/init.rc @@ -1,5 +1,5 @@ initfs:bin/vesad -initfs:bin/ps2d -initfs:bin/pcid +#initfs:bin/ps2d +#initfs:bin/pcid initfs:bin/example -initfs:bin/ion +#initfs:bin/ion diff --git a/kernel/lib.rs b/kernel/lib.rs index e9eec63..0bc1c0e 100644 --- a/kernel/lib.rs +++ b/kernel/lib.rs @@ -162,7 +162,7 @@ pub extern fn kmain() { unsafe { interrupt::disable(); context::switch(); - interrupt::enable_and_halt(); + interrupt::enable_and_nop(); } } } diff --git a/kernel/scheme/user.rs b/kernel/scheme/user.rs index 7604b0f..ba8fd95 100644 --- a/kernel/scheme/user.rs +++ b/kernel/scheme/user.rs @@ -81,7 +81,7 @@ impl UserInner { let full_size = ((offset + size + 4095)/4096) * 4096; let mut to_address = arch::USER_GRANT_OFFSET; - let mut flags = entry::PRESENT | entry::NO_EXECUTE; + let mut flags = entry::PRESENT | entry::NO_EXECUTE | entry::USER_ACCESSIBLE; if writable { flags |= entry::WRITABLE; } diff --git a/schemes/example/src/main.rs b/schemes/example/src/main.rs index 84fb345..ffe5ae9 100644 --- a/schemes/example/src/main.rs +++ b/schemes/example/src/main.rs @@ -25,6 +25,24 @@ impl Scheme for ExampleScheme { } fn main(){ + { + let fd = syscall::open("display:", 0).expect("example: failed to open display"); + let mut buf = *b" \n"; + let mut i: usize = 0; + while i < 10000000000 { + i += 1; + let mut n = i; + let mut e = 10; + while e > 0 && n > 0 { + e -= 1; + buf[e] = (n % 10) as u8 + b'0'; + n = n / 10; + } + syscall::write(fd, &buf[e..]); + } + syscall::close(fd); + } + thread::spawn(move || { let mut socket = File::create(":example").expect("example: failed to create example scheme"); let scheme = ExampleScheme;