WIP: Userspace console
This commit is contained in:
parent
5757f3436e
commit
61eb0d1ca8
|
@ -3,4 +3,5 @@ name = "vesad"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
ransid = { git = "https://github.com/redox-os/ransid.git", branch = "new_api" }
|
||||||
syscall = { path = "../../syscall/" }
|
syscall = { path = "../../syscall/" }
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use std::cmp;
|
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");
|
static FONT: &'static [u8] = include_bytes!("../../../res/unifont.font");
|
||||||
|
|
||||||
|
@ -42,8 +42,8 @@ impl Display {
|
||||||
let mut rows = end_y - start_y;
|
let mut rows = end_y - start_y;
|
||||||
while rows > 0 {
|
while rows > 0 {
|
||||||
unsafe {
|
unsafe {
|
||||||
fast_set(offscreen_ptr as *mut u32, color, len);
|
fast_set32(offscreen_ptr as *mut u32, color, len);
|
||||||
fast_set(onscreen_ptr as *mut u32, color, len);
|
fast_set32(onscreen_ptr as *mut u32, color, len);
|
||||||
}
|
}
|
||||||
offscreen_ptr += stride;
|
offscreen_ptr += stride;
|
||||||
onscreen_ptr += stride;
|
onscreen_ptr += stride;
|
||||||
|
@ -52,7 +52,7 @@ impl Display {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Draw a character
|
/// 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 {
|
if x + 8 <= self.width && y + 16 <= self.height {
|
||||||
let mut font_i = 16 * (character as usize);
|
let mut font_i = 16 * (character as usize);
|
||||||
let font_end = font_i + 16;
|
let font_end = font_i + 16;
|
||||||
|
|
|
@ -1,22 +1,108 @@
|
||||||
#![feature(alloc)]
|
#![feature(alloc)]
|
||||||
#![feature(asm)]
|
#![feature(asm)]
|
||||||
#![feature(heap_api)]
|
#![feature(heap_api)]
|
||||||
|
#![feature(question_mark)]
|
||||||
|
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
|
extern crate ransid;
|
||||||
extern crate syscall;
|
extern crate syscall;
|
||||||
|
|
||||||
|
use std::cell::RefCell;
|
||||||
|
use std::collections::BTreeMap;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::{slice, thread};
|
use std::io::{Read, Write};
|
||||||
use syscall::{physmap, physunmap, MAP_WRITE, MAP_WRITE_COMBINE};
|
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 display::Display;
|
||||||
use mode_info::VBEModeInfo;
|
use mode_info::VBEModeInfo;
|
||||||
use primitive::fast_set64;
|
use primitive::{fast_copy, fast_set64};
|
||||||
|
|
||||||
pub mod display;
|
pub mod display;
|
||||||
pub mod mode_info;
|
pub mod mode_info;
|
||||||
pub mod primitive;
|
pub mod primitive;
|
||||||
|
|
||||||
|
struct DisplayScheme {
|
||||||
|
console: RefCell<Console>,
|
||||||
|
display: RefCell<Display>,
|
||||||
|
next_id: AtomicUsize,
|
||||||
|
handles: RefCell<BTreeMap<usize, usize>>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Scheme for DisplayScheme {
|
||||||
|
fn open(&self, _path: &[u8], _flags: usize) -> Result<usize> {
|
||||||
|
Ok(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn dup(&self, _id: usize) -> Result<usize> {
|
||||||
|
Ok(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write(&self, _id: usize, buf: &[u8]) -> Result<usize> {
|
||||||
|
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<usize> {
|
||||||
|
Ok(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
struct DisplayScheme {
|
||||||
|
display: RefCell<Display>,
|
||||||
|
next_id: AtomicUsize,
|
||||||
|
handles: RefCell<BTreeMap<usize, usize>>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Scheme for DisplayScheme {
|
||||||
|
fn open(&self, _path: &[u8], _flags: usize) -> Result<usize> {
|
||||||
|
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<usize> {
|
||||||
|
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<usize> {
|
||||||
|
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<usize> {
|
||||||
|
self.handles.borrow_mut().remove(&id).ok_or(Error::new(EBADF)).and(Ok(0))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let width;
|
let width;
|
||||||
let height;
|
let height;
|
||||||
|
@ -35,7 +121,7 @@ fn main() {
|
||||||
if physbaseptr > 0 {
|
if physbaseptr > 0 {
|
||||||
thread::spawn(move || {
|
thread::spawn(move || {
|
||||||
let mut socket = File::create(":display").expect("vesad: failed to create display scheme");
|
let mut socket = File::create(":display").expect("vesad: failed to create display scheme");
|
||||||
|
|
||||||
let size = width * height;
|
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") };
|
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) };
|
let offscreen = unsafe { alloc::heap::allocate(size * 4, 4096) };
|
||||||
unsafe { fast_set64(offscreen as *mut u64, 0, size/2) };
|
unsafe { fast_set64(offscreen as *mut u64, 0, size/2) };
|
||||||
|
|
||||||
let mut display = Display::new(width, height,
|
let scheme = DisplayScheme {
|
||||||
unsafe { slice::from_raw_parts_mut(onscreen as *mut u32, size) },
|
console: RefCell::new(Console::new(width/8, height/16)),
|
||||||
unsafe { slice::from_raw_parts_mut(offscreen as *mut u32, size) }
|
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);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
#[allow(unused_assignments)]
|
#[allow(unused_assignments)]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
|
@ -15,7 +28,7 @@ pub unsafe fn fast_copy64(dst: *mut u64, src: *const u64, len: usize) {
|
||||||
#[allow(unused_assignments)]
|
#[allow(unused_assignments)]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
#[cold]
|
#[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
|
asm!("cld
|
||||||
rep stosd"
|
rep stosd"
|
||||||
:
|
:
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
initfs:bin/vesad
|
initfs:bin/vesad
|
||||||
initfs:bin/ps2d
|
#initfs:bin/ps2d
|
||||||
initfs:bin/pcid
|
#initfs:bin/pcid
|
||||||
initfs:bin/example
|
initfs:bin/example
|
||||||
initfs:bin/ion
|
#initfs:bin/ion
|
||||||
|
|
|
@ -162,7 +162,7 @@ pub extern fn kmain() {
|
||||||
unsafe {
|
unsafe {
|
||||||
interrupt::disable();
|
interrupt::disable();
|
||||||
context::switch();
|
context::switch();
|
||||||
interrupt::enable_and_halt();
|
interrupt::enable_and_nop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,7 +81,7 @@ impl UserInner {
|
||||||
let full_size = ((offset + size + 4095)/4096) * 4096;
|
let full_size = ((offset + size + 4095)/4096) * 4096;
|
||||||
let mut to_address = arch::USER_GRANT_OFFSET;
|
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 {
|
if writable {
|
||||||
flags |= entry::WRITABLE;
|
flags |= entry::WRITABLE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,24 @@ impl Scheme for ExampleScheme {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main(){
|
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 || {
|
thread::spawn(move || {
|
||||||
let mut socket = File::create(":example").expect("example: failed to create example scheme");
|
let mut socket = File::create(":example").expect("example: failed to create example scheme");
|
||||||
let scheme = ExampleScheme;
|
let scheme = ExampleScheme;
|
||||||
|
|
Loading…
Reference in a new issue