diff --git a/Cargo.lock b/Cargo.lock index eb38e45..f5158d0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5,9 +5,10 @@ version = 3 [[package]] name = "able_graphics_library" version = "0.1.2" -source = "git+https://git.ablecorp.us/ableos/ableos_userland#70a65fc10d2caafe370be90eb0e31aa7d9347218" +source = "git+https://git.ablecorp.us/ableos/ableos_userland#f433484f2f56a4e8f77b1f39680b88c3d1e27830" dependencies = [ "embedded-graphics", + "log", "versioning", ] @@ -140,9 +141,9 @@ dependencies = [ [[package]] name = "clparse" version = "0.1.0" -source = "git+https://git.ablecorp.us/ableos/ableos_userland#70a65fc10d2caafe370be90eb0e31aa7d9347218" +source = "git+https://git.ablecorp.us/ableos/ableos_userland#f433484f2f56a4e8f77b1f39680b88c3d1e27830" dependencies = [ - "hashbrown 0.13.2", + "hashbrown 0.12.3", "log", "toml", ] @@ -364,6 +365,15 @@ dependencies = [ "ahash 0.8.3", ] +[[package]] +name = "hbvm" +version = "0.1.0" +source = "git+https://git.ablecorp.us/ableos/holey-bytes#76302b4ca8aeda6597ee51cb1cf5f59a5d385c4f" +dependencies = [ + "hashbrown 0.13.2", + "log", +] + [[package]] name = "hermit-abi" version = "0.1.19" @@ -457,7 +467,8 @@ dependencies = [ "derive_more", "embedded-graphics", "error-stack 0.3.1", - "hashbrown 0.13.2", + "hashbrown 0.12.3", + "hbvm", "limine", "log", "rdrand", @@ -822,7 +833,7 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "versioning" version = "0.1.3" -source = "git+https://git.ablecorp.us/ableos/ableos_userland#70a65fc10d2caafe370be90eb0e31aa7d9347218" +source = "git+https://git.ablecorp.us/ableos/ableos_userland#f433484f2f56a4e8f77b1f39680b88c3d1e27830" dependencies = [ "serde", ] @@ -1110,7 +1121,7 @@ dependencies = [ [[package]] name = "xml" version = "0.1.0" -source = "git+https://git.ablecorp.us/ableos/ableos_userland#70a65fc10d2caafe370be90eb0e31aa7d9347218" +source = "git+https://git.ablecorp.us/ableos/ableos_userland#f433484f2f56a4e8f77b1f39680b88c3d1e27830" dependencies = [ "serde", ] diff --git a/README.md b/README.md index fa3c1ba..50159fe 100644 --- a/README.md +++ b/README.md @@ -3,5 +3,4 @@ TODO: # Compiling 1. `git submodule --update init` -1. Add [this binary](https://git.ablecorp.us/AbleOS/ableos/src/commit/e6c8d184d42961cf3cfa2e4aa319fc86c8880585/test.wasm) to the root. 1. `cargo repbuild` diff --git a/kernel/Cargo.toml b/kernel/Cargo.toml index 76ca60f..f992bf1 100644 --- a/kernel/Cargo.toml +++ b/kernel/Cargo.toml @@ -6,7 +6,7 @@ resolver = "2" [dependencies] - +hbvm = { git = "https://git.ablecorp.us/ableos/holey-bytes" } embedded-graphics = "0.7.1" diff --git a/kernel/lds/x86_64.ld b/kernel/lds/x86_64.ld index e430d28..427e4a9 100644 --- a/kernel/lds/x86_64.ld +++ b/kernel/lds/x86_64.ld @@ -47,7 +47,8 @@ SECTIONS /* Align initial kernel heap to page boundary */ . = ALIGN(4K); PROVIDE(_initial_kernel_heap_start = .); - PROVIDE(_initial_kernel_heap_size = 1024 * 1024); + /* PROVIDE(_initial_kernel_heap_size = 1024 * 1024); */ + PROVIDE(_initial_kernel_heap_size = 1024 * 4096); . += _initial_kernel_heap_size; } :data } diff --git a/kernel/src/allocator.rs b/kernel/src/allocator.rs index e3985c5..2375d22 100644 --- a/kernel/src/allocator.rs +++ b/kernel/src/allocator.rs @@ -39,6 +39,8 @@ struct Allocator(Mutex>); unsafe impl GlobalAlloc for Allocator { unsafe fn alloc(&self, layout: Layout) -> *mut u8 { + // log::info!("Global allocation"); + let mut lock = self.0.lock(); let allocator = lock.as_mut().expect("heap allocator should be initialized"); diff --git a/kernel/src/arch/x86_64/graphics.rs b/kernel/src/arch/x86_64/graphics.rs index 998f354..642faa3 100644 --- a/kernel/src/arch/x86_64/graphics.rs +++ b/kernel/src/arch/x86_64/graphics.rs @@ -12,6 +12,7 @@ use { pub static DISPLAY: Lazy> = Lazy::new(|| { static FB_REQ: FramebufferRequest = FramebufferRequest::new(0); let fb1: &NonNullPtr = &FB_REQ.get_response().get().unwrap().framebuffers()[0]; + { use crate::alloc::string::ToString; let mut dt = DEVICE_TREE.lock(); @@ -22,8 +23,13 @@ pub static DISPLAY: Lazy> = Lazy::new(|| { disp.set_attribute("bits per pixel", fb1.bpp); dt.devices.insert("Displays".to_string(), alloc::vec![disp]); } + let size: usize = (fb1.width * fb1.height).try_into().unwrap(); + let back_buffer: alloc::vec::Vec = alloc::vec![0; 800*600]; + let m = Mutex::new(Display { fb: fb1.address.as_ptr().unwrap().cast(), + // bb: fb1.address.as_ptr().unwrap().cast(), + bb: back_buffer.as_slice().as_ptr() as *mut u32, size: Size::new(fb1.width as u32, fb1.height as u32), color: Rgb888::WHITE, }); diff --git a/kernel/src/arch/x86_64/logging.rs b/kernel/src/arch/x86_64/logging.rs index 457fb07..2e1ba55 100644 --- a/kernel/src/arch/x86_64/logging.rs +++ b/kernel/src/arch/x86_64/logging.rs @@ -7,7 +7,7 @@ use { uart_16550::SerialPort, }; -static SERIAL_CONSOLE: Mutex = Mutex::new(unsafe { SerialPort::new(0x3F8) }); +pub static SERIAL_CONSOLE: Mutex = Mutex::new(unsafe { SerialPort::new(0x3F8) }); static TERMINAL_LOGGER: Lazy> = Lazy::new(|| Mutex::new(TermLogger::new())); pub fn init() { @@ -17,8 +17,10 @@ pub fn init() { pub fn log(args: core::fmt::Arguments<'_>) -> core::fmt::Result { x86_64::instructions::interrupts::without_interrupts(|| { - TERMINAL_LOGGER.lock().write_fmt(args)?; - SERIAL_CONSOLE.lock().write_fmt(args) + // TERMINAL_LOGGER.lock().write_fmt(args)?; + let mut sc = SERIAL_CONSOLE.lock(); + sc.write_fmt(args)?; + Ok(()) }) } diff --git a/kernel/src/arch/x86_64/mod.rs b/kernel/src/arch/x86_64/mod.rs index f944793..6293db9 100644 --- a/kernel/src/arch/x86_64/mod.rs +++ b/kernel/src/arch/x86_64/mod.rs @@ -8,9 +8,9 @@ pub mod memory; mod cpuid; mod gdt; -mod graphics; +pub mod graphics; pub(crate) mod interrupts; -mod logging; +pub mod logging; pub mod pci; pub mod virtio; @@ -114,12 +114,57 @@ unsafe extern "C" fn _kernel_start() -> ! { graphics::init(); let mut dis = DISPLAY.lock(); use {able_graphics_library::raw_pixel, embedded_graphics::prelude::RgbColor}; - dis.set_color(Rgb888::GREEN); - dis.line(1, 1, 700, 1000, 1); - // dis.line(10, 10, 100, 10, 10); - // dis.line(100, 10, 1, 1, 10); + // dis.set_color(Rgb888::GREEN); + // dis.line(400, 400, 700, 100, 50); + + // dis.set_color(Rgb888::new(100, 23, 100)); + + // dis.line(100, 100, 400, 400, 3); + + // dis.line(100, 100, 700, 100, 1); + dis.set_color(Rgb888::YELLOW); + let thick = 3; + let p1 = (400, 30); + let p2 = (200, 150); + let p3 = (600, 150); + let p4 = (200, 350); + let p5 = (600, 350); + let p6 = (400, 470); + + { + //HEXAGON + + dis.line(p1.0, p1.1, p2.0, p2.1, thick); + dis.line(p1.0, p1.1, p3.0, p3.1, thick); + dis.line(p2.0, p2.1, p4.0, p4.1, thick); + dis.line(p3.0, p3.1, p5.0, p5.1, thick); + dis.line(p6.0, p6.1, p4.0, p4.1, thick); + dis.line(p6.0, p6.1, p5.0, p5.1, thick); + } + { + dis.line(600, 150, 200, 350, thick); + dis.line(600, 350, 400, 250, thick); + } + + { + dis.set_color(Rgb888::WHITE); + let hp1 = (350, 150); + let hp2 = (350, 350); + let hp3 = (450, 250); + let hp4 = (350, 250); + let hp5 = (450, 150); + let hp6 = (450, 350); + + dis.line(hp1.0, hp1.1, hp2.0, hp2.1, thick); + dis.line(hp3.0, hp3.1, hp4.0, hp4.1, thick); + dis.line(hp5.0, hp5.1, hp6.0, hp6.1, thick); + } + + dis.swap_buffers(); } + let rand = xml::XMLElement::new("Random"); + crate::kmain::kmain( KFILE_REQ .get_response() @@ -144,7 +189,7 @@ unsafe extern "C" fn _kernel_start() -> ! { }), ) } - +use embedded_graphics::prelude::WebColors; /// Spin loop pub fn sloop() -> ! { loop { diff --git a/kernel/src/arch/x86_64/pci/mod.rs b/kernel/src/arch/x86_64/pci/mod.rs index eb1696f..2556eba 100644 --- a/kernel/src/arch/x86_64/pci/mod.rs +++ b/kernel/src/arch/x86_64/pci/mod.rs @@ -23,10 +23,22 @@ pub fn init() { let id = device_info.device_id.id; use Vendor::*; let (dev_type, dev_name) = match (vendor, id) { + (Qemu, 4369) => ("GPUs", "QEMU VGA"), (VirtIO, 4176) => ("GPUs", "VirtIO PCI GPU"), (CirrusLogic, 184) => ("GPUs", "Cirrus SVGA"), //GD 5446? (_, _) => ("Unidentified PCI", "UNKNOWN DEVICE"), }; + // let (dev_type, dev_name) = match device_info.full_class { + // PciFullClass::Unclassified_NonVgaCompatible => todo!(), + // PciFullClass::Unclassified_VgaCompatible => todo!(), + + // PciFullClass::Display_VGA => ("GPUs", "VGA Device"), + // PciFullClass::Display_XGA => ("GPUs", "XGA Device"), + // PciFullClass::Display_3D => ("GPUs", "3D Device"), + // PciFullClass::Display_Other => ("GPUs", "Other"), + + // _ => ("Unidentified PCI", "UNKNOWN DEVICE"), + // }; let mut dev = xml::XMLElement::new(dev_name); let mut pci_info = xml::XMLElement::new("PCI Info"); diff --git a/kernel/src/device_tree.rs b/kernel/src/device_tree.rs index 208318f..97bc9b1 100644 --- a/kernel/src/device_tree.rs +++ b/kernel/src/device_tree.rs @@ -3,6 +3,7 @@ use alloc::{string::String, vec::Vec}; use {crate::alloc::string::ToString, core::fmt, hashbrown::HashMap}; pub type Device = xml::XMLElement; +// TODO: alphabatize this list #[derive(Debug)] pub struct DeviceTree { pub devices: HashMap>, diff --git a/kernel/src/host_functions.rs b/kernel/src/host_functions.rs new file mode 100644 index 0000000..bd2fd29 --- /dev/null +++ b/kernel/src/host_functions.rs @@ -0,0 +1,57 @@ +use {alloc::collections::VecDeque, hbvm::engine::Engine}; + +use { + crossbeam_queue::{ArrayQueue, SegQueue}, + log::trace, +}; + +use crate::{ipc::message::Message, kmain::DEVICE_TREE}; +pub enum HostError { + MemoryError, +} + +pub fn ipc_send(engine: &mut Engine) -> Result<(), HostError> { + let handle = engine.registers.f0; + let message_start = engine.registers.f1; + let message_length = engine.registers.f2; + + let mut ipc_msg: alloc::vec::Vec = alloc::vec![]; + + for x in message_start..message_start + message_length { + let byte = engine.read_mem_addr_8(x); + match byte { + Ok(byte) => ipc_msg.push(byte), + Err(_) => return Err(HostError::MemoryError), + } + } + log::trace!("Message bytes {:?}", ipc_msg); + Ok(()) +} + +pub fn ipc_recv(engine: &mut Engine) {} + +/// Check f0 for the buffer type +/// 0 means an unbound buffer +/// 1 means a bound buffer +/// Check f1 if the buffer is bound +/// +/// f2 Return a handle to the sender +/// f3 returns a handle the the reciever +pub fn ipc_mkbuf(engine: &mut Engine) { + match engine.registers.f0 as usize { + 0 => { + trace!("Making a new ipc unbound buffer"); + let buf: SegQueue = SegQueue::new(); + } + 1 => { + let buf_len = engine.registers.f1 as usize; + trace!("Making a new ipc buffer with capacity {}", buf_len); + let buf: ArrayQueue = ArrayQueue::new(buf_len); + } + _ => {} + } +} + +pub fn rpc_discover(engine: &mut Engine) {} +pub fn rpc_register(engine: &mut Engine) {} +pub fn rpc_call(engine: &mut Engine) {} diff --git a/kernel/src/ipc/buffer.rs b/kernel/src/ipc/buffer.rs new file mode 100644 index 0000000..a2b39db --- /dev/null +++ b/kernel/src/ipc/buffer.rs @@ -0,0 +1,15 @@ +use crossbeam_queue::{ArrayQueue, SegQueue}; + +use super::message::Message; + +enum BufferTypes { + Unbound(SegQueue), + Bound(ArrayQueue), +} + +pub struct IpcBuffer { + protocol: Protocol, + buffer: BufferTypes, +} + +pub struct Protocol {} diff --git a/kernel/src/ipc/message.rs b/kernel/src/ipc/message.rs new file mode 100644 index 0000000..bc91825 --- /dev/null +++ b/kernel/src/ipc/message.rs @@ -0,0 +1,3 @@ +use alloc::vec::Vec; + +pub type Message = Vec; diff --git a/kernel/src/ipc/mod.rs b/kernel/src/ipc/mod.rs new file mode 100644 index 0000000..b392926 --- /dev/null +++ b/kernel/src/ipc/mod.rs @@ -0,0 +1,24 @@ +pub mod buffer; +pub mod message; + +use alloc::string::ToString; + +pub struct IpcV1 { + abc: alloc::string::String, +} + +pub struct IpcV2 { + abc: alloc::string::String, +} + +pub fn IPCV1_to_IPCV2(ipc_v1: IpcV1) -> IpcV2 { + return IpcV2 { + abc: "abc".to_string(), + }; +} + +pub fn IPCV2_to_IPCV1(ipc_v2: IpcV2) -> IpcV1 { + return IpcV1 { + abc: "abc".to_string(), + }; +} diff --git a/kernel/src/kmain.rs b/kernel/src/kmain.rs index 77aa4ff..3a5b555 100644 --- a/kernel/src/kmain.rs +++ b/kernel/src/kmain.rs @@ -7,7 +7,13 @@ use { spin::{Lazy, Mutex}, }; -use crate::device_tree::DeviceTree; +use {embedded_graphics::pixelcolor::Rgb888, hbvm::engine::Engine}; + +use crate::{ + arch::{graphics::DISPLAY, logging::SERIAL_CONSOLE}, + device_tree::DeviceTree, + // host_functions::read_device_tree, +}; use crate::alloc::string::ToString; @@ -39,10 +45,40 @@ pub fn kmain(cmdline: &str, bootstrap: Option<&'static [u8]>) -> ! { let mut dt = DEVICE_TREE.lock(); info!("Device Tree {}", &dt); + + let bytes = alloc::vec![0]; + let mut prog = Engine::new(bytes); + // prog.enviroment_call_table[0] = read_device_tree; + prog.run(); + prog.dump(); + + // TODO: change this to a driver + { + let mut buf = [8; 128 * 4]; + + let mut sc = SERIAL_CONSOLE.lock(); + loop { + let byte = sc.receive(); + if byte == b'\r' { + sc.send(b'\n'); + } + sc.send(byte); + } + } + crate::arch::sloop() } +use embedded_graphics::prelude::RgbColor; +use hbvm::bytecode::ops::Operations::*; pub static DEVICE_TREE: Lazy> = Lazy::new(|| { let mut dt = DeviceTree::new(); Mutex::new(dt) }); + +#[test_case] +fn trivial_assertion() { + trace!("trivial assertion... "); + assert_eq!(1, 1); + info!("[ok]"); +} diff --git a/kernel/src/lib.rs b/kernel/src/lib.rs index 10f2db0..0227992 100644 --- a/kernel/src/lib.rs +++ b/kernel/src/lib.rs @@ -10,6 +10,9 @@ ptr_sub_ptr )] #![no_std] +#![feature(custom_test_frameworks)] +#![test_runner(crate::test_runner)] + // #![deny(missing_docs)] extern crate alloc; @@ -18,10 +21,11 @@ mod allocator; mod arch; pub mod device_tree; pub mod handle; +pub mod host_functions; +pub mod ipc; mod kmain; mod logger; mod memory; -mod task; pub mod utils; use versioning::Version; @@ -50,3 +54,11 @@ fn panic(info: &core::panic::PanicInfo) -> ! { loop {} } + +#[cfg(test)] +fn test_runner(tests: &[&dyn Fn()]) { + println!("Running {} tests", tests.len()); + for test in tests { + test(); + } +} diff --git a/kernel/src/main.rs b/kernel/src/main.rs index 973e301..308e166 100644 --- a/kernel/src/main.rs +++ b/kernel/src/main.rs @@ -1,4 +1,3 @@ #![no_std] #![no_main] - extern crate kernel; diff --git a/kernel/src/task.rs b/kernel/src/task.rs deleted file mode 100644 index e6800e7..0000000 --- a/kernel/src/task.rs +++ /dev/null @@ -1,149 +0,0 @@ -//! Async task and executor - -use alloc::{boxed::Box, collections::BTreeMap, sync::Arc, task::Wake}; -use core::{ - future::Future, - pin::Pin, - task::{Context, Poll, Waker}, -}; -use crossbeam_queue::SegQueue; -use slab::Slab; -use spin::RwLock; - -type TaskQueue = Arc>; -type SpawnQueue = Arc>; - -static SPAWN_QUEUE: RwLock> = RwLock::new(None); - -/// Spawn a new task -pub fn spawn(future: impl Future + Send + 'static) { - match &*SPAWN_QUEUE.read() { - Some(s) => s.push(Task::new(future)), - None => panic!("no task executor is running"), - } -} - -/// Forcibly yield a task -pub fn yield_now() -> impl Future { - struct YieldNow(bool); - impl Future for YieldNow { - type Output = (); - - fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { - if self.0 { - Poll::Ready(()) - } else { - self.0 = true; - cx.waker().wake_by_ref(); - Poll::Pending - } - } - } - - YieldNow(false) -} - -/// Tasks executor -#[derive(Default)] -pub struct Executor { - /// All spawned tasks' stash - tasks: Slab, - - /// Awake tasks' queue - queue: TaskQueue, - - /// Incoming tasks to enqueue - incoming: SpawnQueue, - - /// Wakers - wakers: BTreeMap, -} - -impl Executor { - /// Spawn a task - pub fn spawn(&mut self, future: impl Future + Send + 'static) { - self.queue - .push(TaskId(self.tasks.insert(Task::new(future)))); - } - - /// Spin poll loop until it runs out of tasks - pub fn run(&mut self) { - // Assign `self.incoming` to global spawn queue to spawn tasks - // from within - { - let mut spawner = SPAWN_QUEUE.write(); - if spawner.is_some() { - panic!("task executor is already running"); - } - - *spawner = Some(Arc::clone(&self.incoming)); - } - - // Try to get incoming task, if none available, poll - // enqueued one - while let Some(id) = self - .incoming - .pop() - .map(|t| TaskId(self.tasks.insert(t))) - .or_else(|| self.queue.pop()) - { - let Some(task) = self.tasks.get_mut(id.0) else { - panic!("attempted to get non-extant task with id {}", id.0) - }; - - let mut cx = Context::from_waker(self.wakers.entry(id).or_insert_with(|| { - Waker::from(Arc::new(TaskWaker { - id, - queue: Arc::clone(&self.queue), - })) - })); - - match task.poll(&mut cx) { - Poll::Ready(()) => { - // Task done, unregister - self.tasks.remove(id.0); - self.wakers.remove(&id); - } - Poll::Pending => (), - } - } - - *SPAWN_QUEUE.write() = None; - } -} - -#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] -struct TaskId(usize); - -/// Async task -struct Task { - future: Pin + Send>>, -} - -impl Task { - /// Create a new task from a future - fn new(future: impl Future + Send + 'static) -> Self { - Self { - future: Box::pin(future), - } - } - - fn poll(&mut self, cx: &mut Context) -> Poll<()> { - self.future.as_mut().poll(cx) - } -} - -struct TaskWaker { - id: TaskId, - queue: TaskQueue, -} - -impl Wake for TaskWaker { - fn wake(self: Arc) { - self.wake_by_ref(); - } - - fn wake_by_ref(self: &Arc) { - self.queue.push(self.id); - } -}