1
0
Fork 0
forked from AbleOS/ableos

redux of relib, scheduler work and documentation

This commit is contained in:
Able 2022-01-26 19:43:03 -06:00
parent 95998acb99
commit 5cba768e85
33 changed files with 657 additions and 324 deletions

View file

@ -7,8 +7,7 @@ build-std-features = ["compiler-builtins-mem"]
[target.'cfg(target_arch = "x86_64")'] [target.'cfg(target_arch = "x86_64")']
# --quiet suppresses warning messages from the bootimage crate runner = "bootimage runner"
runner = "bootimage runner --quiet"
[target.riscv64gc-unknown-none-elf] [target.riscv64gc-unknown-none-elf]
rustflags = "-C link-arg=-T../ableos/src/arch/riscv/virt.lds" rustflags = "-C link-arg=-T../ableos/src/arch/riscv/virt.lds"

26
ableos/Cargo.lock generated
View file

@ -30,6 +30,8 @@ dependencies = [
"bootloader", "bootloader",
"cpuio", "cpuio",
"externc-libm", "externc-libm",
"facepalm",
"hashbrown",
"lazy_static", "lazy_static",
"linked_list_allocator", "linked_list_allocator",
"lliw", "lliw",
@ -48,7 +50,6 @@ dependencies = [
"vga", "vga",
"volatile 0.2.7", "volatile 0.2.7",
"wasmi", "wasmi",
"watson",
"x86_64", "x86_64",
"y-compositor-protocol", "y-compositor-protocol",
] ]
@ -172,6 +173,13 @@ dependencies = [
"libm", "libm",
] ]
[[package]]
name = "facepalm"
version = "0.1.0"
dependencies = [
"log",
]
[[package]] [[package]]
name = "font8x8" name = "font8x8"
version = "0.3.1" version = "0.3.1"
@ -670,22 +678,6 @@ dependencies = [
"parity-wasm", "parity-wasm",
] ]
[[package]]
name = "watson"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1cea7ead78c402dbf14e7f11911b0b48955ea13d46e012e2d98775e23c65d4ef"
dependencies = [
"serde",
"webassembly",
]
[[package]]
name = "webassembly"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d1a10e1dedffff9cfcbdd33c289c65b87da634259a460a3f23d513649fa7a8c"
[[package]] [[package]]
name = "x86_64" name = "x86_64"
version = "0.14.7" version = "0.14.7"

View file

@ -15,11 +15,16 @@ run-args = [
"stdio", "stdio",
"-smp", "-smp",
"cores=2", "cores=2",
# "-device",
# "virtio-gpu",
# An example gpu used with ableOS
"-device",
"virtio-gpu",
# An example disk used with ableOS
"-device", "-device",
"virtio-blk-pci,drive=drive0,id=virtblk0,num-queues=4", "virtio-blk-pci,drive=drive0,id=virtblk0,num-queues=4",
# A simple example of a boot image
"-drive", "-drive",
"file=disk.qcow2,if=none,id=drive0", "file=disk.qcow2,if=none,id=drive0",
] ]
@ -40,7 +45,7 @@ log= "*"
pretty-hex = "0.2.1" pretty-hex = "0.2.1"
unicode-width = "0.1.7" unicode-width = "0.1.7"
picorand = "*" picorand = "*"
watson = "0.4" # watson = "0.4"
[dependencies.serde] [dependencies.serde]
version = "*" version = "*"
@ -52,6 +57,11 @@ version = "*"
default-features = false default-features = false
features = ["alloc"] features = ["alloc"]
[dependencies.hashbrown]
version = "*"
default-features = false
features = ["inline-more"]
[dependencies.rkyv] [dependencies.rkyv]
version = "0.7.29" version = "0.7.29"
default-features = false default-features = false
@ -68,6 +78,9 @@ git = "https://git.ablecorp.us:443/able/y-compositor-protocol.git"
[dependencies.shadeable] [dependencies.shadeable]
path = "../shadeable" path = "../shadeable"
[dependencies.facepalm]
path = "../facepalm"
[dependencies.ab_glyph] [dependencies.ab_glyph]
version = "*" version = "*"
default-features = false default-features = false

View file

@ -1,5 +1,5 @@
// #![allow(clippy::print_literal)] // #![allow(clippy::print_literal)]
use crate::logger; use crate::{logger, SCHEDULER};
use super::{gdt, interrupts}; use super::{gdt, interrupts};
@ -11,7 +11,15 @@ pub fn init() {
Err(err) => error!("{}", err), Err(err) => error!("{}", err),
} }
gdt::init(); gdt::init();
use crate::scheduler::Priority;
let mut scheduler = SCHEDULER.lock();
use Priority::*;
scheduler.new_process(High);
drop(scheduler);
interrupts::init_idt(); interrupts::init_idt();
unsafe { interrupts::PICS.lock().initialize() }; unsafe { interrupts::PICS.lock().initialize() };
x86_64::instructions::interrupts::enable(); x86_64::instructions::interrupts::enable();
} }

View file

@ -4,7 +4,9 @@ use alloc::{format, vec::Vec};
use crate::{ use crate::{
boot_conf::BootConfig, boot_conf::BootConfig,
scheduler::{self, SCHEDULER}, capabilities::FileAccess,
file::{File, PathRep},
scheduler::SCHEDULER,
}; };
// use crate::scheduler; // use crate::scheduler;
@ -18,7 +20,6 @@ use {
systeminfo::{KERNEL_VERSION, RELEASE_TYPE}, systeminfo::{KERNEL_VERSION, RELEASE_TYPE},
}, },
graphics::{VgaBuffer, SCREEN_BUFFER}, graphics::{VgaBuffer, SCREEN_BUFFER},
relib::math::rand::RAND_HANDLE,
relib::network::socket::Socket, relib::network::socket::Socket,
relib::network::socket::{SimpleSock, SocketReturns}, relib::network::socket::{SimpleSock, SocketReturns},
vga_e::{self, num_to_vga16}, vga_e::{self, num_to_vga16},
@ -50,12 +51,15 @@ lazy_static! {
pub static ref BOOT_CONF: BootConfig = boot_conf::BootConfig::new(); pub static ref BOOT_CONF: BootConfig = boot_conf::BootConfig::new();
} }
/// The main entry point of the kernel
#[no_mangle] #[no_mangle]
pub fn kernel_main() -> ! { pub fn kernel_main() -> ! {
init::init(); init::init();
log::set_max_level(BOOT_CONF.log_level()); log::set_max_level(BOOT_CONF.log_level());
// info!("Initialized"); // info!("Initialized");
// facepalm::start_facepalm();
graphics_pipe_startup(); graphics_pipe_startup();
if false { if false {
@ -81,21 +85,41 @@ pub fn kernel_main() -> ! {
let mut scheduler = SCHEDULER.lock(); let mut scheduler = SCHEDULER.lock();
use Priority::*; use Priority::*;
scheduler.new_process(High);
scheduler.new_process(High);
scheduler.new_process(Low);
scheduler.new_process(Low);
scheduler.new_process(Low);
scheduler.new_process(Low);
scheduler.new_process(Medium);
scheduler.new_process(Medium);
scheduler.new_process(High);
let mut xyz = scheduler.new_process(High);
xyz.capabilities.files = FileAccess::Some(vec![PathRep {
location: FileLocations::Home,
file_name: "test".to_string(),
}]);
scheduler.add_process(xyz);
for x in &scheduler.list { for x in &scheduler.list {
trace!("{:?}", x); trace!("{:?}", x);
} }
drop(scheduler); drop(scheduler);
use crate::proto_filetable::contain::FILE_TABLE;
use crate::proto_filetable::file::FileLocations;
let mut file_table = FILE_TABLE.lock();
let mut new_file = File::new(FileLocations::Bin, "test".to_string(), "txt".to_string());
new_file.write_bytes(b"Hello, world!");
file_table.add_file("test", new_file);
let file = file_table.get_file("test");
match file {
Some(file) => {
let file_bytes = &file.data_pointer;
let file_string = String::from_utf8(file_bytes.to_vec()).unwrap();
info!("{}", file_string);
}
None => {
info!("File not found");
}
}
use crate::wasm::WasmProgram; use crate::wasm::WasmProgram;
let ret = WasmProgram::new_from_bytes(&[0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00]); let ret = WasmProgram::new_from_bytes(&[0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00]);
trace!("Binary Valid: {:?}", ret.validate_header()); trace!("Binary Valid: {:?}", ret.validate_header());
@ -117,10 +141,6 @@ pub fn kernel_main() -> ! {
shader_tests(); shader_tests();
} }
// graphics.copy_to_buffer();
// info!("buffer copied");
sloop() sloop()
} }
@ -129,8 +149,6 @@ pub fn tick() {
let mut data = TICK.load(Relaxed); let mut data = TICK.load(Relaxed);
data += 1; data += 1;
RAND_HANDLE.lock().seed_entropy_timer(data);
crate::kernel_state::KERNEL_STATE.lock().update_state(); crate::kernel_state::KERNEL_STATE.lock().update_state();
let mut scheduler = SCHEDULER.lock(); let mut scheduler = SCHEDULER.lock();
@ -138,10 +156,8 @@ pub fn tick() {
TICK.store(data, Relaxed) TICK.store(data, Relaxed)
} }
/// called every time a key is pressed to add it to the randomness pool
pub fn key_entropy(key: u8) { pub fn key_entropy(key: u8) {}
RAND_HANDLE.lock().seed_entropy_keyboard(key);
}
pub fn cpu_socket_startup() { pub fn cpu_socket_startup() {
let mut cpu_info_socket = SimpleSock::new(); let mut cpu_info_socket = SimpleSock::new();
@ -210,7 +226,6 @@ pub fn screen_writer_test() {
let mut sock_print_id = SimpleSock::new(); let mut sock_print_id = SimpleSock::new();
sock_print_id.register_protocol("Screen Printer".to_string()); sock_print_id.register_protocol("Screen Printer".to_string());
//
// sock_print_id.write(format!("a原 b画 cフ dァ eイ fル 集").into()); // sock_print_id.write(format!("a原 b画 cフ dァ eイ fル 集").into());
// sock_print_id.write(format!("⋮").into()); // sock_print_id.write(format!("⋮").into());
@ -219,16 +234,8 @@ pub fn screen_writer_test() {
// sock_print_id.write(format!("I look forward to ur ai stuff :^>").into()); // sock_print_id.write(format!("I look forward to ur ai stuff :^>").into());
// sock_print_id.write(format!("1....2....3....4....5....6....7....8....9").into()); // sock_print_id.write(format!("1....2....3....4....5....6....7....8....9").into());
let mut prev = None;
// let mut graphics = SCREEN_BUFFER.lock();
// graphics.clear();
// graphics.copy_to_buffer();
for current in (*String::from_utf8_lossy(&sock_print_id.peek().unwrap())).chars() { for current in (*String::from_utf8_lossy(&sock_print_id.peek().unwrap())).chars() {
vga_e::draw_char(prev, current, 0); vga_e::draw_char(0, 0, current, 0);
prev = Some(current);
} }
} }

View file

@ -1,4 +1,7 @@
//! hi //! main library for the AbleOS kernel.
//! exposing all the kernel functionality to the rest of the kernel.
//!
//!
#![no_std] #![no_std]
#![feature( #![feature(
@ -13,6 +16,7 @@
naked_functions naked_functions
)] )]
#![feature(exclusive_range_pattern)] #![feature(exclusive_range_pattern)]
#![feature(slice_pattern)]
#[cfg(target_arch = "aarch64")] #[cfg(target_arch = "aarch64")]
#[path = "arch/aarch64/mod.rs"] #[path = "arch/aarch64/mod.rs"]
@ -32,24 +36,49 @@ pub mod print;
#[macro_use] #[macro_use]
pub extern crate log; pub extern crate log;
/////////////
// Modules //
/////////////
pub mod allocator; pub mod allocator;
pub mod boot_conf; pub mod boot_conf;
pub mod driver_traits; pub mod driver_traits;
pub mod experiments; pub mod experiments;
pub mod graphics; pub mod graphics;
pub mod kernel_state;
pub mod keyboard; pub mod keyboard;
pub mod kmain; pub mod kmain;
pub mod logger; pub mod logger;
pub mod panic; pub mod panic;
pub mod proto_filetable;
pub mod relib; pub mod relib;
pub mod scheduler; pub mod scheduler;
mod unicode_utils; mod unicode_utils;
pub mod utils; pub mod utils;
pub mod vga_e;
pub mod wasm; pub mod wasm;
pub extern crate alloc; pub extern crate alloc;
pub extern crate externc_libm as libm; pub extern crate externc_libm as libm;
/////////////////////////////// //////////////////
pub mod kernel_state; // Re-exports ///
pub mod vga_e; ////////////////
pub use allocator::*;
pub use boot_conf::*;
pub use driver_traits::*;
pub use experiments::*;
pub use graphics::*;
pub use kernel_state::*;
pub use keyboard::*;
pub use logger::*;
pub use panic::*;
pub use proto_filetable::*;
pub use relib::*;
pub use scheduler::*;
pub use utils::*;
pub use vga_e::*;
pub use wasm::*;
//////////////////
pub mod virtio;
pub use virtio::*;

View file

@ -1,6 +1,6 @@
use core::sync::atomic::Ordering; use core::sync::atomic::Ordering;
use crate::kmain::{BOOT_CONF, TICK}; use crate::kmain::TICK;
use crate::serial_println; use crate::serial_println;
use lliw::{Fg, Reset}; use lliw::{Fg, Reset};
pub use log::{debug, info, trace, warn}; pub use log::{debug, info, trace, warn};
@ -42,7 +42,7 @@ impl log::Log for SimpleLogger {
); );
} }
} }
/// Clear the log buffer
fn flush(&self) {} fn flush(&self) {}
} }

View file

@ -1,8 +1,22 @@
use {crate::arch::sloop, core::panic::PanicInfo}; use {crate::arch::sloop, core::panic::PanicInfo};
/// A function to handle a panic in the kernel.
/// # Example
/// ```
/// use ableos::panic::panic;
/// panic!("This is a panic!");
/// ```
///
/// # Safety
/// This function is unsafe because it does not guarantee that the panic is handled.
#[panic_handler] #[panic_handler]
fn panic(info: &PanicInfo) -> ! { fn panic(info: &PanicInfo) -> ! {
// println!("{}", info);
error!("{}", info); error!("{}", info);
// help me use facepalm::start_facepalm;
sloop() sloop()
} }
pub fn test_panic() {
panic!("test panic!");
}

View file

@ -1,22 +0,0 @@
pub fn pciConfigReadWord(bus: u8, slot: u8, func: u8, offset: u8) {}
/*
uint16_t pciConfigReadWord(uint8_t bus, uint8_t slot, uint8_t func, uint8_t offset) {
uint32_t address;
uint32_t lbus = (uint32_t)bus;
uint32_t lslot = (uint32_t)slot;
uint32_t lfunc = (uint32_t)func;
uint16_t tmp = 0;
// Create configuration address as per Figure 1
address = (uint32_t)((lbus << 16) | (lslot << 11) |
(lfunc << 8) | (offset & 0xFC) | ((uint32_t)0x80000000));
// Write out the address
outl(0xCF8, address);
// Read in the data
// (offset & 2) * 8) = 0 will choose the first word of the 32-bit register
tmp = (uint16_t)((inl(0xCFC) >> ((offset & 2) * 8)) & 0xFFFF);
return tmp;
}
*/

View file

@ -0,0 +1,5 @@
use crate::ProtoFileTable;
lazy_static::lazy_static!(
pub static ref FILE_TABLE: spin::Mutex<ProtoFileTable> = spin::Mutex::new(ProtoFileTable::new());
);

View file

@ -0,0 +1,76 @@
use core::fmt;
use alloc::{string::String, vec, vec::Vec};
#[derive(Debug, PartialEq, Clone)]
pub struct PathRep {
pub location: FileLocations,
pub file_name: String,
}
#[derive(Debug)]
pub struct FileMetadata {
pub file_type: String,
pub size: usize,
}
#[derive(Debug, Clone, PartialEq)]
pub enum FileLocations {
Bin,
Config,
Home,
}
impl fmt::Display for FileLocations {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:?}", self)
}
}
#[derive(Debug)]
pub struct File {
pub location: FileLocations,
pub file_name: String,
pub meta_data: FileMetadata,
pub data_pointer: Vec<u8>,
}
impl File {
/// Write the provided bytes to a file
pub fn write_bytes(&mut self, bytes: &[u8]) {
for byte in bytes {
self.data_pointer.push(*byte);
}
self.meta_data.size = self.data_pointer.len();
}
pub fn new(location: FileLocations, file_name: String, file_type: String) -> Self {
let bytes: Vec<u8> = vec![];
let abc123 = bytes;
Self {
location,
file_name,
meta_data: FileMetadata { file_type, size: 0 },
data_pointer: abc123,
}
}
pub fn size(&self) -> usize {
self.meta_data.size.clone()
}
pub fn read_to_string(&mut self, _string: &mut String) {
todo!();
}
pub fn read_and_return(&mut self) -> String {
String::from_utf8(self.data_pointer.clone()).expect("Found invalid UTF-8")
}
}
impl fmt::Display for File {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}://{}", self.location, self.file_name)
}
}

View file

@ -0,0 +1,61 @@
//! A file table module for AbleOS
//!
//! This module provides a file table interface for AbleOS.
//!
//! # Examples
//! ```
//! use relib::filesystem::ProtoFileTable;
//! let mut file_table = ProtoFileTable::new();
//! file_table.add_file("test.txt", "Hello, world!".as_bytes());
//! let file = file_table.get_file("test.txt");
//! assert_eq!(file.unwrap().as_slice(), "Hello, world!".as_bytes());
//! ```
//! # Notes
//! The file table is a simple in-memory hashmap.
//! The file table is not thread safe.
//! The file table is not persistent.
use alloc::{
string::{String, ToString},
vec::Vec,
};
use hashbrown::HashMap;
pub mod contain;
pub mod file;
use file::File;
/// A prototype file table for AbleOS
///
/// This module provides a file table interface for AbleOS.
///
/// # Examples
/// ```
/// use crate::filesystem::ProtoFileTable;
/// let mut file_table = ProtoFileTable::new();
/// file_table.add_file("test.txt", "Hello, world!".as_bytes());
/// let file = file_table.get_file("test.txt");
/// assert_eq!(file.unwrap().as_slice(), "Hello, world!".as_bytes());
/// ```
pub struct ProtoFileTable {
files: HashMap<String, File>,
}
impl ProtoFileTable {
pub fn new() -> ProtoFileTable {
ProtoFileTable {
files: HashMap::new(),
}
}
pub fn add_file(&mut self, path: &str, contents: File) {
self.files.insert(path.to_string(), contents);
}
pub fn get_file(&self, path: &str) -> Option<&File> {
self.files.get(path)
}
}
#[cfg(test)]
mod tests;

View file

@ -0,0 +1,16 @@
use super::file::FileLocations;
use super::*;
// #[test]
fn test_add_file() {
let mut file_table = ProtoFileTable::new();
let file_to_add = File::new(FileLocations::Bin, "test".to_string(), "txt".to_string());
file_to_add.write_bytes(b"Hello, world!");
file_table.add_file("test", file_to_add);
let file = file_table.get_file("test.txt");
assert_eq!(
file.unwrap().data_pointer.as_slice(),
"Hello, world!".as_bytes()
);
}

View file

@ -1,2 +1,3 @@
//! A standard implementation of common math functions
pub mod ciphers; pub mod ciphers;
pub mod rand;

View file

@ -1,32 +0,0 @@
use crate::relib::math::rand::RNG;
pub struct LinearShiftRegister {
reg: u64,
}
// 64 bit
// non-cryptographically secure
impl RNG for LinearShiftRegister {
fn new() -> Self {
Self { reg: (1 << 63) | 1 }
}
fn rand(&mut self) -> u64 {
let newbit = (self.reg >> 1) ^ (self.reg >> 2) ^ (self.reg >> 7);
self.reg = (self.reg >> 1) | (newbit << 3);
newbit
}
fn seed(&mut self, seed: u64) {
let entropy = 34; // replace with hardware entropy
let shifted = (self.reg >> 1) ^ ((self.reg >> 2) + entropy);
let x: u64 = 2983745;
let x123: u64 = 100000000;
let multitude: u64 = x123.wrapping_mul(x) / x;
let mult = shifted.wrapping_mul(multitude);
let seeded_bit = seed / mult;
for _ in 0..seeded_bit {
self.rand();
}
}
}

View file

@ -1,85 +0,0 @@
#![allow(dead_code)]
pub mod linearshift;
pub mod prand;
pub mod wichmanhillrand; // FIXEME: Reimplement
use lazy_static::lazy_static;
use linearshift::LinearShiftRegister;
use prand::PRand;
pub trait RNG {
fn new() -> Self;
fn rand(&mut self) -> u64;
fn seed(&mut self, seed: u64);
}
pub type KeyEntropyHandler = u8;
pub struct Entropy {
// Everytime entropy is used decrement bits count
bytes_count: u8, // 167 is our lower desired bit count
pool_index: u8,
pool: [u64; 255],
}
impl Entropy {
pub fn new() -> Self {
Self {
bytes_count: 0,
pool: [0; 255],
pool_index: 0,
}
}
pub fn poll_hardware() {
todo!();
}
pub fn read_entropy(&mut self) -> u8 {
self.bytes_count -= 1;
1
}
}
impl Default for Entropy {
fn default() -> Self {
Self::new()
}
}
pub struct RandomHandeler {
prand: prand::PRand,
linearshift: linearshift::LinearShiftRegister,
entropy: Entropy,
}
impl RandomHandeler {
pub fn seed_entropy(&mut self) {
// n is even
self.prand
.seed(self.entropy.pool[self.entropy.pool_index as usize]);
//otherwise odd
self.linearshift
.seed(self.entropy.pool[self.entropy.pool_index as usize]);
}
pub fn seed_entropy_keyboard(&mut self, key: u8) {
self.entropy.pool_index += key;
if self.entropy.pool_index > 254 {
self.entropy.pool_index = 0
}
self.entropy.pool[self.entropy.pool_index as usize] += key as u64;
self.entropy.pool_index += 1;
}
pub fn seed_entropy_timer(&mut self, seed: u64) {
let bytes = seed.to_be_bytes();
for byte in bytes {
if self.entropy.pool_index > 254 {
self.entropy.pool_index = 0
}
self.entropy.pool[self.entropy.pool_index as usize] += byte as u64;
self.entropy.pool_index += 1;
}
}
}
lazy_static! {
pub static ref RAND_HANDLE: spin::Mutex<RandomHandeler> = spin::Mutex::new(RandomHandeler {
prand: PRand::new(),
linearshift: LinearShiftRegister::new(),
entropy: Entropy::new(),
});
}

View file

@ -1,17 +0,0 @@
use crate::relib::math::rand::RNG;
pub struct PRand {
next: u64,
}
impl RNG for PRand {
fn new() -> Self {
Self { next: 7 }
}
fn rand(&mut self) -> u64 {
let internal_seed_1 = 21354;
self.next = self.next.wrapping_mul(1103515245) + internal_seed_1;
(self.next / 65536) % 32768
}
fn seed(&mut self, seed: u64) {
self.next = seed;
}
}

View file

@ -1,27 +0,0 @@
use crate::relib::math::rand::RNG;
pub struct WichmannHillRand {
seed0: u16,
seed1: u16,
seed2: u16,
}
impl RNG for WichmannHillRand {
fn new() -> Self {
Self {
seed0: 123,
seed1: 456,
seed2: 789,
}
}
fn rand(&mut self) -> u64 {
self.seed0 = (self.seed0.wrapping_mul(170)) % 30269;
self.seed1 = (self.seed1.wrapping_mul(172)) % 30307;
self.seed2 = (self.seed2.wrapping_mul(173)) % 30323;
(self.seed0 / 30269 + self.seed1 / 30307 + self.seed2 / 30323).into()
}
fn seed(&mut self, seed: u64) {
self.seed0 = (seed >> 48) as u16;
self.seed1 = ((seed << 16) >> 48) as u16;
self.seed2 = ((seed << 32) >> 48) as u16;
}
}

View file

@ -1,3 +1,5 @@
//! A simple reimplimentation of the the rust standard library
pub mod clparse; pub mod clparse;
pub mod encoding; pub mod encoding;
pub mod image; pub mod image;

View file

@ -1 +1,23 @@
// Copilot module
// Language: rust
//! Security module.
//!
//! This module provides a security interface for AbleOS.
//!
//! # Examples
//! ```
//! use crate::security::Security;
//!
//! let mut security = Security::new();
//! security.add_user("admin", "password");
//! security.add_user("user", "password");
//! security.add_user("guest", "password");
//!
//! assert_eq!(security.authenticate("admin", "password"), true);
//! assert_eq!(security.authenticate("user", "password"), true);
//! assert_eq!(security.authenticate("guest", "password"), true);
//! assert_eq!(security.authenticate("admin", "password2"), false);
//! assert_eq!(security.authenticate("user", "password2"), false);
//! assert_eq!(security.authenticate("guest", "password2"), false);
//! ```

View file

@ -1,51 +1,60 @@
use alloc::vec::Vec; use alloc::vec::Vec;
/// Placeholder to be replaced with a proper FileReference when such a thing exists use crate::file::PathRep;
pub type FileID = u8;
pub type SoundCardID = u8; pub type SoundCardID = u8;
pub type DeviceID = u8; pub type DeviceID = u8;
pub type ControllerID = u8; pub type ControllerID = u8;
#[derive(Clone, Debug)] #[derive(Clone, Debug, PartialEq)]
pub enum FileAccess { pub enum FileAccess {
All, All,
Some(Vec<FileID>), Some(Vec<PathRep>),
None, None,
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug, PartialEq)]
pub enum ControllerAccess { pub enum ControllerAccess {
All, All,
Some(Vec<ControllerID>), Some(Vec<ControllerID>),
None, None,
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug, PartialEq)]
pub enum SoundCardAccess { pub enum SoundCardAccess {
All, All,
Some(Vec<SoundCardID>), Some(Vec<SoundCardID>),
None, None,
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug, PartialEq)]
pub enum MouseAccess { pub enum MouseAccess {
Yes, Yes,
No, No,
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug, PartialEq)]
pub enum KeyboardAccess { pub enum KeyboardAccess {
Yes, Yes,
No, No,
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug, PartialEq)]
pub enum NetworkAccess {
Yes,
No,
}
/// A set of capabilities that a process has
#[derive(Clone, Debug, PartialEq)]
pub struct Capabilities { pub struct Capabilities {
files: FileAccess, pub files: FileAccess,
mouse: MouseAccess, pub mouse: MouseAccess,
keyboard: KeyboardAccess, pub keyboard: KeyboardAccess,
controllers: ControllerAccess, pub controllers: ControllerAccess,
sound_cards: SoundCardAccess, pub sound_cards: SoundCardAccess,
pub network_access: NetworkAccess,
} }
impl Capabilities { impl Capabilities {
@ -57,8 +66,7 @@ impl Capabilities {
keyboard: KeyboardAccess::No, keyboard: KeyboardAccess::No,
controllers: ControllerAccess::None, controllers: ControllerAccess::None,
sound_cards: SoundCardAccess::None, sound_cards: SoundCardAccess::None,
network_access: NetworkAccess::No,
} }
} }
} }

View file

@ -3,7 +3,10 @@ use alloc::{vec, vec::Vec};
pub mod capabilities; pub mod capabilities;
pub mod proc; pub mod proc;
use proc::{Process, ProcessPermissions, PID}; use proc::{Process, PID};
#[cfg(test)]
mod tests;
use self::capabilities::Capabilities; use self::capabilities::Capabilities;
@ -14,8 +17,6 @@ lazy_static::lazy_static!(
); );
// pub struct VirtualMemoryTable {}
/// Scheduler priority model /// Scheduler priority model
#[derive(Clone, Copy, Debug)] #[derive(Clone, Copy, Debug)]
pub enum Priority { pub enum Priority {
@ -38,24 +39,56 @@ pub enum FileAccessTypes {
None, None,
} }
/// This structure handles the process scheduling and execution
/// ///
/// # Example
/// ```
/// use crate::scheduler::Priority;
/// use crate::scheduler::Scheduler;
///
/// let mut scheduler = Scheduler::new();
///
/// let pid = scheduler.new_process(Priority::High);
/// scheduler.run_process(pid);
/// ```
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct Scheduler { pub struct Scheduler {
/// The highest free process ID
pub free_pid: PID, pub free_pid: PID,
/// The execution time of the current process in ticks
pub process_exec_time: u64, pub process_exec_time: u64,
/// The list of processes
pub list: Vec<Process>, pub list: Vec<Process>,
} }
impl Scheduler { impl Scheduler {
/// Create a new scheduler
///
/// # Example
/// ```
/// use ableos::scheduler::Priority;
/// let mut scheduler = Scheduler::new();
/// ```
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {
list: vec![],
process_exec_time: 0,
free_pid: PID(0), free_pid: PID(0),
process_exec_time: 0,
list: Vec::new(),
} }
} }
/// Change the current process to the next process in the list
///
/// # Example
///
/// ```
/// let mut scheduler = scheduler();
/// let mut process = scheduler.next_process();
/// ```
///
/// # Panics
///
/// Panics if there are no processes in the list
pub fn next_process(&mut self) { pub fn next_process(&mut self) {
self.process_exec_time = 0; self.process_exec_time = 0;
let previous_task = self.list[0].clone(); let previous_task = self.list[0].clone();
@ -63,19 +96,47 @@ impl Scheduler {
self.list.push(previous_task); self.list.push(previous_task);
} }
/// Create a /// Creates a new process
pub fn new_process(&mut self, priority: Priority) { ///
// let new_pid = self.free_pid; /// # Arguments
///
/// * `priority` - The priority of the process
///
/// # Example
///
/// ```
/// let mut scheduler = scheduler();
/// let mut process = scheduler.new_process(Priority::Medium);
/// ```
pub fn new_process(&mut self, priority: Priority) -> Process {
let process = Process { let process = Process {
id: self.free_pid.clone(), id: self.free_pid.clone(),
capabilities: Capabilities::empty(), capabilities: Capabilities::empty(),
priority, priority,
}; };
self.free_pid.0 += 1; // self.free_pid.0 += 1;
// self.list.push(process);
process
}
pub fn add_process(&mut self, process: Process) {
self.list.push(process); self.list.push(process);
self.free_pid.0 += 1;
} }
/// Terminate the process with the matching PID /// Terminate the process with the matching PID
///
/// # Arguments
///
/// * `pid` - The PID of the process to terminate
///
/// # Example
///
/// ```
/// let mut scheduler = scheduler();
/// let mut process = scheduler.new_process(Priority::Medium);
/// scheduler.terminate_process(process.id);
/// ```
pub fn term_process(&mut self, pid: PID) { pub fn term_process(&mut self, pid: PID) {
let mut process_index = 0; let mut process_index = 0;
for x in &self.list { for x in &self.list {
@ -86,11 +147,19 @@ impl Scheduler {
process_index += 1 process_index += 1
} }
} }
/// Bump the current process' execution time
///
/// # Example
///
/// ```
/// let mut scheduler = scheduler();
/// let mut process = scheduler.new_process(Priority::Medium);
/// scheduler.bump_exec();
/// ```
pub fn bump_exec(&mut self) { pub fn bump_exec(&mut self) {
self.process_exec_time += 1; self.process_exec_time += 1;
use Priority::*;
use Priority::*;
if self.list.len() > 0 { if self.list.len() > 0 {
match (self.process_exec_time, self.list[0].priority) { match (self.process_exec_time, self.list[0].priority) {
(20, High) => { (20, High) => {

View file

@ -7,12 +7,6 @@ use super::{capabilities::Capabilities, FileAccessTypes, Priority};
pub struct PID(pub usize); pub struct PID(pub usize);
/// Temporary till integration of capabilities
#[derive(Clone, Debug)]
pub struct ProcessPermissions {
pub file_access: FileAccessTypes,
}
/// A process /// A process
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct Process { pub struct Process {

View file

@ -0,0 +1,49 @@
use super::*;
use crate::scheduler::{
capabilities::{ControllerAccess, FileAccess, KeyboardAccess, MouseAccess, SoundCardAccess},
proc::PID,
Priority::*,
Scheduler,
};
// #[test]
fn test_new_process() {
let mut scheduler = Scheduler::new();
scheduler.new_process(High);
assert_eq!(scheduler.list.len(), 1);
}
// #[test]
fn test_next_process() {
let mut scheduler = Scheduler::new();
scheduler.new_process(High);
scheduler.next_process();
assert_eq!(scheduler.list.len(), 0);
}
// #[test]
fn test_term_process() {
let mut scheduler = Scheduler::new();
scheduler.new_process(High);
scheduler.term_process(PID(1));
assert_eq!(scheduler.list.len(), 0);
}
// #[test]
fn test_bump_exec() {
let mut scheduler = Scheduler::new();
scheduler.new_process(High);
scheduler.bump_exec();
assert_eq!(scheduler.process_exec_time, 1);
}
// #[test]
fn test_capabilities() {
let caps = Capabilities::empty();
assert_eq!(caps.files, FileAccess::None);
assert_eq!(caps.mouse, MouseAccess::No);
assert_eq!(caps.keyboard, KeyboardAccess::No);
assert_eq!(caps.controllers, ControllerAccess::None);
assert_eq!(caps.sound_cards, SoundCardAccess::None);
}

View file

@ -6,3 +6,13 @@
pub fn type_of<T>(_: &T) -> &str { pub fn type_of<T>(_: &T) -> &str {
core::any::type_name::<T>() core::any::type_name::<T>()
} }
#[cfg(test)]
mod tests {
use super::*;
// #[test]
fn test_type_of() {
assert_eq!(type_of(&1), "i32");
}
}

View file

@ -1,3 +1,7 @@
use shadeable::pixel_format::Rgba64;
use crate::SCREEN_BUFFER;
use { use {
ab_glyph::{Font, FontRef, Glyph}, ab_glyph::{Font, FontRef, Glyph},
vga::{ vga::{
@ -16,15 +20,16 @@ lazy_static::lazy_static! {
pub static ref VGAE_BUFF_OFFSET_Y: spin::Mutex<u8> = spin::Mutex::new(0); pub static ref VGAE_BUFF_OFFSET_Y: spin::Mutex<u8> = spin::Mutex::new(0);
} }
pub fn draw_char(previous_character: Option<char>, character: char, _offset: usize) { /// Draw a glyph on the screen at the given position
let mode = *VGAE.lock(); ///
let mut offset_x = VGAE_BUFF_OFFSET_X.lock(); /// # Arguments
let mut offset_y = VGAE_BUFF_OFFSET_Y.lock(); /// * `x` - the x position of the glyph
/// * `y` - the y position of the glyph
if *offset_x == 39 { /// * `glyph` - the glyph to draw
*offset_x = 0; /// * `color` - the color of the glyph
*offset_y += 1; pub fn draw_char(x: u8, y: u8, character: char, color: Rgba64) {
} // let mode = *VGAE.lock();
let mut mode = SCREEN_BUFFER.lock();
let font = FontRef::try_from_slice(include_bytes!( let font = FontRef::try_from_slice(include_bytes!(
"../../ableos/assets/fonts/unifont-14.0.01.ttf" "../../ableos/assets/fonts/unifont-14.0.01.ttf"
@ -55,29 +60,10 @@ pub fn draw_char(previous_character: Option<char>, character: char, _offset: usi
match character { match character {
'\n' => {} '\n' => {}
_ => { _ => {
let previous_glyph: Glyph = used_font
.glyph_id(previous_character.unwrap_or(' '))
.with_scale_and_position(
20.0 * font_scale,
ab_glyph::point(
*offset_x as f32 * (10.0 * font_scale),
*offset_y as f32 + (18.0 * font_scale),
),
);
let mut q_glyph: Glyph = used_font.glyph_id(character).with_scale_and_position( let mut q_glyph: Glyph = used_font.glyph_id(character).with_scale_and_position(
20.0 * font_scale, 20.0 * font_scale,
ab_glyph::point( ab_glyph::point(10.0 * font_scale, 18.0 * font_scale),
*offset_x as f32 * (10.0 * font_scale),
*offset_y as f32 + (18.0 * font_scale),
),
); );
{
// figure it our latter bruh
let spacing = used_font.kern_unscaled(previous_glyph.id, q_glyph.id);
// info!("{spacing} {:?} {:?}", previous_glyph.id, q_glyph.id);
q_glyph.position.x += spacing * font_scale;
}
if let Some(q) = used_font.outline_glyph(q_glyph) { if let Some(q) = used_font.outline_glyph(q_glyph) {
q.draw(|x, y, c| { q.draw(|x, y, c| {
@ -86,13 +72,11 @@ pub fn draw_char(previous_character: Option<char>, character: char, _offset: usi
mode.set_pixel( mode.set_pixel(
x as usize + corner.x as usize, x as usize + corner.x as usize,
y as usize + corner.y as usize, y as usize + corner.y as usize,
Color16::Green, color,
); );
} }
}); });
} }
*offset_x += 1;
} }
} }
} }

61
ableos/src/virtio/mod.rs Normal file
View file

@ -0,0 +1,61 @@
//! virtio device
//!
//! This module contains the virtio device structural code.
//!
//! # Notes
//! https://docs.oasis-open.org/virtio/virtio/v1.1/csprd01/virtio-v1.1-csprd01.html#x1-20001
pub struct VirtioDevice {
status: VirtioDeviceStatus,
}
#[repr(C)]
pub enum VirtioDeviceStatus {
// Indicates that the guest OS has found the device and recognized it as a valid virtio device.
Acknowleged = 1,
// Indicates that the guest OS knows how to drive the device. Note: There could be a significant (or infinite) delay before setting this bit. For example, under Linux, drivers can be loadable modules.
Driver = 2,
// Indicates that the driver has acknowledged all the features it understands, and feature negotiation is complete.
FeaturesOk = 8,
// Indicates that the device is set up and ready to drive the device.
DriverOk = 4,
// Indicates that the device needs to be reset.
DeviceNeedsReset = 64,
// Indicates that the device has failed.
Failed = 128,
}
pub struct FeaturesBits(u64);
impl FeaturesBits {
// bit mask the first 23 bits and return a u64
// 0 to 23
// Feature bits for the specific device type
pub fn device_type_features(&self) -> u64 {
0
}
// bit mask the 24th bit to the 37th bit and return a u64
// 24 to 37
// Feature bits reserved for extensions to the queue and feature negotiation mechanisms
pub fn extension_features(&self) -> u64 {
0
}
// bit mask the 38th bit to the 63th bit and return a u64
// 38 and above
// Feature bits reserved for future extensions.
pub fn future_features(&self) -> u64 {
0
}
}
// configuration change notification
// available buffer notification
// used buffer notification.
#[repr(C)]
pub struct VirtioDeviceNotification {
pub type_: u32,
pub index: u32,
pub value: u32,
}

View file

@ -5,21 +5,78 @@ pub const WASM_BINARY_MAGIC: [u8; 4] = [0x00, 0x61, 0x73, 0x6d];
/// `1 0 0 0` as an array of 4 bytes /// `1 0 0 0` as an array of 4 bytes
pub const WASM_VERSION: [u8; 4] = [0x01, 0x00, 0x00, 0x00]; pub const WASM_VERSION: [u8; 4] = [0x01, 0x00, 0x00, 0x00];
/// Validate a wasm header (8 bytes) /// A wasm section
///
/// # Examples
/// ```
/// use wasm_loader::wasm::WasmSection;
/// let section = WasmSection::new(0, vec![0x00, 0x01, 0x02, 0x03]);
/// assert_eq!(section.id, 0);
/// assert_eq!(section.data, vec![0x00, 0x01, 0x02, 0x03]);
/// ```
/// # Notes
/// The wasm spec defines the following section types:
/// * `0`: custom
/// * `1`: type
/// * `2`: import
/// * `3`: function
/// * `4`: table
/// * `5`: memory
/// * `6`: global
/// * `7`: export
/// * `8`: start
/// * `9`: element
/// * `10`: code
/// * `11`: data
pub enum SectionType { pub enum SectionType {
None = 0, None = 0,
Type = 1, Type = 1,
Import = 2,
Function = 3,
Table = 4,
Memory = 5,
Global = 6,
Export = 7,
Start = 8,
Element = 9,
Code = 10,
Data = 11,
} }
pub struct Section { pub struct Section {
/// The section type
stype: SectionType, stype: SectionType,
section_size: u8, section_size: u8,
} }
/// A wasm type
/// # Examples
/// ```
/// use wasm_loader::wasm::WasmType;
/// let type_ = WasmType::new(vec![0x00, 0x01, 0x02, 0x03]);
/// assert_eq!(type_.subtypes, vec![0x00, 0x01, 0x02, 0x03]);
/// ```
/// # Notes
/// The wasm spec defines the following type subtypes:
/// * `0`: anyfunc
/// * `1`: func
/// * `2`: block
/// * `3`: i32
/// * `4`: i64
/// * `5`: f32
/// * `6`: f64
pub enum WasmType {
Anyfunc = 0,
Func = 1,
Block = 2,
I32 = 3,
I64 = 4,
F32 = 5,
F64 = 6,
}
pub struct WasmProgram { pub struct WasmProgram {
raw_bytes: Vec<u8>, raw_bytes: Vec<u8>,
// version:
} }
impl WasmProgram { impl WasmProgram {
@ -28,7 +85,16 @@ impl WasmProgram {
raw_bytes: bytes.to_vec(), raw_bytes: bytes.to_vec(),
} }
} }
/// Returns the a tuple of two bools
/// The first bool is true if the wasm binary is valid
/// The second bool is true if the wasm binary version is 1
///
/// # Examples
/// ```
/// use wasm_loader::wasm::WasmProgram;
/// let wasm_program = WasmProgram::new_from_bytes(b"\0\0\0\0\1\0\0\0");
/// assert_eq!(wasm_program.is_valid(), (true, false));
/// ```
pub fn validate_header(self) -> (bool, bool) { pub fn validate_header(self) -> (bool, bool) {
let mut byte_magic_valid = false; let mut byte_magic_valid = false;
let mut byte_version_valid = false; let mut byte_version_valid = false;
@ -42,9 +108,4 @@ impl WasmProgram {
} }
return (byte_magic_valid, byte_version_valid); return (byte_magic_valid, byte_version_valid);
} }
} }

18
facepalm/Cargo.lock generated
View file

@ -2,6 +2,24 @@
# It is not intended for manual editing. # It is not intended for manual editing.
version = 3 version = 3
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]] [[package]]
name = "facepalm" name = "facepalm"
version = "0.1.0" version = "0.1.0"
dependencies = [
"log",
]
[[package]]
name = "log"
version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
dependencies = [
"cfg-if",
]

View file

@ -6,3 +6,4 @@ edition = "2021"
# 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
[dependencies] [dependencies]
log = "0.4.0"

19
facepalm/src/lib.rs Normal file
View file

@ -0,0 +1,19 @@
#![no_std]
// extern crate alloc;
use log::*;
pub const VERSION: &str = env!("CARGO_PKG_VERSION");
#[cfg(debug_assertions)]
pub const RELEASE_TYPE: &str = "debug";
#[cfg(not(debug_assertions))]
pub const RELEASE_TYPE: &str = "release";
pub fn start_facepalm() {
info!("facepalm 🤦 launched!");
info!("facepalm 🤦 version: {}", VERSION);
info!("facepalm 🤦 {} mode", RELEASE_TYPE);
}

View file

@ -1,3 +0,0 @@
fn main() {
println!("Hello, world!");
}