Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions builder/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,12 @@ fn qemu() -> Result<()> {
} else if system_code.exists() && system_vars.exists() {
println!("Using system OVFM");

// We need to ensure that ovmf folder exists
DirBuilder::new()
.recursive(true)
.create("ovmf")
.context("Failed to create ovmf folder")?;

// QEMU will make changes to this file, so we need a local copy. We do
// not want to overwrite it every build
if !local_vars.exists() {
Expand Down
2 changes: 2 additions & 0 deletions kernel_userspace/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,7 @@ edition = "2021"
postcard = { version = "1.0.4", features = ["alloc"] }
serde = { version = "1.0.*", default-features = false, features = ["derive"] }
input = { path = "../input" }
lazy_static = { version = "1.4", features = ["spin_no_std"] }

conquer-once = {version = "0.4", default-features = false}
thiserror = { version = "1.0", package = "thiserror-core", default-features = false }
6 changes: 5 additions & 1 deletion kernel_userspace/src/fs.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use serde::{Deserialize, Serialize};
use thiserror::Error;

use alloc::{
boxed::Box,
Expand All @@ -22,10 +23,13 @@ pub enum FSServiceMessage<'a> {
GetDisksRequest,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[derive(Debug, Clone, Serialize, Deserialize, Error)]
pub enum FSServiceError {
#[error("No such partition: {0}")]
NoSuchPartition(u64),
#[error("Could not follow path")]
CouldNotFollowPath,
#[error("File not found")]
FileNotFound,
}

Expand Down
9 changes: 8 additions & 1 deletion kernel_userspace/src/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use core::sync::atomic::AtomicU64;

use alloc::vec::Vec;
use serde::{Deserialize, Serialize};
use thiserror::Error;

use crate::{
ids::{ProcessID, ServiceID},
Expand Down Expand Up @@ -37,13 +38,19 @@ pub enum SendServiceMessageDest {
ToSubscribers,
}

#[derive(Debug, Clone, Copy)]
#[derive(Debug, Clone, Copy, Error)]
pub enum SendError {
#[error("TODO")]
Ok,
#[error("TODO")]
ParseError,
#[error("TODO")]
NoSuchService,
#[error("TODO")]
NotYourPID,
#[error("TODO")]
TargetNotExists,
#[error("TODO")]
FailedToDecodeResponse,
}

Expand Down
3 changes: 3 additions & 0 deletions terminal/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ userspace = { path = "../userspace" }
kernel_userspace = { path = "../kernel_userspace" }
input = { path = "../input" }

thiserror = { version = "1.0", package = "thiserror-core", default-features = false }
hashbrown = "0.14"

[profile.dev]
strip = true
opt-level = 1
93 changes: 93 additions & 0 deletions terminal/src/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
//! This is my own little version of anyhow, but with a lot more control and
//! less std dependencies

use core::{
error::Error,
fmt::{Debug, Display},
};

extern crate alloc;
use alloc::{
boxed::Box,
string::{String, ToString},
vec::Vec,
};

pub type Result<T, E = InternalError> = core::result::Result<T, E>;

pub trait Context<T> {
fn context<C>(self, context: C) -> Result<T, InternalError>
where
C: Display;

fn with_context<C, F>(self, f: F) -> Result<T, InternalError>
where
C: Display,
F: FnOnce() -> C;
}

impl<T> Context<T> for Result<T, InternalError> {
fn context<C>(self, context: C) -> Result<T, InternalError>
where
C: Display,
{
self.map_err(|e| e.push_context(context.to_string()))
}

fn with_context<C, F>(self, f: F) -> Result<T, InternalError>
where
C: Display,
F: FnOnce() -> C,
{
self.map_err(|e| e.push_context(f().to_string()))
}
}

/// This is an error that can store a bunch of extra context information
pub struct InternalError {
primary: Box<dyn Error>,
context: Vec<String>,
}

impl InternalError {
pub fn new(primary: Box<dyn Error>, context: Vec<String>) -> Self {
Self { primary, context }
}

pub fn push_context(mut self, context: String) -> Self {
self.context.push(context);
self
}
}

impl Debug for InternalError {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
(self as &dyn Display).fmt(f)
}
}

impl Display for InternalError {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.write_str("Error: ")?;
f.write_str(&self.primary.to_string())?;

if self.context.len() != 0 {
f.write_str("\n\nCaused by:")?;
for ctx in self.context.iter() {
f.write_str("\n\t")?;
f.write_str(&ctx)?;
}
}

Ok(())
}
}

impl<E> From<E> for InternalError
where
E: Error + Sized + 'static,
{
fn from(value: E) -> Self {
InternalError::new(Box::new(value), Vec::new())
}
}
124 changes: 124 additions & 0 deletions terminal/src/fns.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
use alloc::string::{String, ToString};
use alloc::vec::Vec;
use kernel_userspace::fs::{self, add_path, get_disks, read_file_sector, StatResponse};
use terminal::error::Result;
use terminal::script::execute::{args_to_string, execute_expr};
use terminal::script::{execute::Value, parser::Expr, Environment};
use thiserror::Error;
use userspace::{print, println};

pub fn pwd<'a>(env: &mut Environment<'a>, _args: Vec<Expr>) -> Result<Value> {
println!("{}", env.cwd);
Ok(Value::Null)
}

pub fn echo<'a>(env: &mut Environment<'a>, args: Vec<Expr>) -> Result<Value> {
if args.len() == 0 {
println!("ECHO!");
} else {
println!("{}", execute_expr(&args[0], env)?);
}

Ok(Value::Null)
}

pub fn disk<'a>(env: &mut Environment<'a>, args: Vec<Expr>) -> Result<Value> {
if args.len() == 1 {
if let Some(new_id) = execute_expr(&args[0], env)?
.to_string()
.chars()
.next()
.and_then(|c| c.to_digit(10))
{
env.partition_id = new_id as u64;
return Ok(Value::Null);
}
}

let fs_sid = env.services.ok_or(FuncExecError::UninitedService)?.fs;

println!("Drives:");
for part in get_disks(fs_sid, env.services_buffer()?)?.iter() {
println!("{}:", part)
}

Ok(Value::Null)
}

pub fn ls<'a>(env: &mut Environment<'a>, args: Vec<Expr>) -> Result<Value> {
let fs_sid = env.services.ok_or(FuncExecError::UninitedService)?.fs;

let path = add_path(&env.cwd.clone(), &args_to_string(args, env)?);

let stat = fs::stat(
fs_sid,
env.partition_id as usize,
path.as_str(),
env.services_buffer()?,
)?;

match stat {
StatResponse::File(_) => println!("This is a file"),
StatResponse::Folder(c) => {
for child in c.children {
println!("{child}")
}
}
};

Ok(Value::Null)
}

pub fn cd<'a>(env: &mut Environment<'a>, args: Vec<Expr>) -> Result<Value> {
env.cwd = add_path(&env.cwd.clone(), &args_to_string(args, env)?);
Ok(Value::Null)
}

pub fn cat<'a>(env: &mut Environment<'a>, args: Vec<Expr>) -> Result<Value> {
let fs_sid = env.services.ok_or(FuncExecError::UninitedService)?.fs;

for file in args {
let file = execute_expr(&file, env)?.to_string();

let path = add_path(&env.cwd, &file);

let stat = fs::stat(
fs_sid,
env.partition_id as usize,
path.as_str(),
env.services_buffer()?,
)?;

let file = match stat {
StatResponse::File(f) => f,
StatResponse::Folder(_) => {
println!("Not a file");
continue;
}
};

for i in 0..file.file_size / 512 {
let sect = read_file_sector(
fs_sid,
env.partition_id as usize,
file.node_id,
i as u32,
env.services_buffer()?,
)?;
if let Some(data) = sect {
print!("{}", String::from_utf8_lossy(data))
} else {
print!("Error reading");
break;
}
}
}

Ok(Value::Null)
}

#[derive(Debug, Clone, Error)]
pub enum FuncExecError {
#[error("Service was not initialized")]
UninitedService,
}
6 changes: 6 additions & 0 deletions terminal/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#![no_std]
#![feature(error_in_core)]
#![feature(let_chains)]

pub mod error;
pub mod script;
Loading