Move kernel code to api (#204)

* Move code to api

* Add palette::from_csv

* Refactor palette::from_str with tests

* Add tests to api::font::from_bytes

* Add TODO comments to fs code

* Rename kernel and user dirs to sys and usr

* Add missing files from migration

* Move console::Style to api

* Add more missing changes
This commit is contained in:
Vincent Ollivier 2021-07-16 10:19:18 +02:00 committed by GitHub
parent 04afe534e3
commit 6b8de261ca
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
75 changed files with 834 additions and 774 deletions

83
src/api/console.rs Normal file
View File

@ -0,0 +1,83 @@
use core::fmt;
pub struct Style {
foreground: Option<usize>,
background: Option<usize>,
}
impl Style {
pub fn reset() -> Self {
Self { foreground: None, background: None }
}
pub fn foreground(name: &str) -> Self {
Self { foreground: color_to_fg(name), background: None }
}
pub fn with_foreground(self, name: &str) -> Self {
Self { foreground: color_to_fg(name), background: self.background }
}
pub fn background(name: &str) -> Self {
Self { foreground: None, background: color_to_bg(name) }
}
pub fn with_background(self, name: &str) -> Self {
Self { foreground: self.foreground, background: color_to_bg(name) }
}
pub fn color(name: &str) -> Self {
Self::foreground(name)
}
pub fn with_color(self, name: &str) -> Self {
self.with_foreground(name)
}
}
impl fmt::Display for Style {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if let Some(fg) = self.foreground {
if let Some(bg) = self.background {
write!(f, "\x1b[{};{}m", fg, bg)
} else {
write!(f, "\x1b[{}m", fg)
}
} else if let Some(bg) = self.background {
write!(f, "\x1b[{}m", bg)
} else {
write!(f, "\x1b[0m")
}
}
}
fn color_to_fg(name: &str) -> Option<usize> {
match name {
"Black" => Some(30),
"Red" => Some(31),
"Green" => Some(32),
"Brown" => Some(33),
"Blue" => Some(34),
"Magenta" => Some(35),
"Cyan" => Some(36),
"LightGray" => Some(37),
"DarkGray" => Some(90),
"LightRed" => Some(91),
"LightGreen" => Some(92),
"Yellow" => Some(93),
"LightBlue" => Some(94),
"Pink" => Some(95),
"LightCyan" => Some(96),
"White" => Some(97),
_ => None,
}
}
fn color_to_bg(name: &str) -> Option<usize> {
if let Some(fg) = color_to_fg(name) {
Some(fg + 10)
} else {
None
}
}

View File

@ -9,6 +9,7 @@ pub struct Font {
// http://www.fifi.org/doc/console-tools-dev/file-formats/psf
pub fn from_bytes(buf: &[u8]) -> Result<Font, ()> {
// Header
if buf.len() < 4 || buf[0] != 0x36 || buf[1] != 0x04 {
return Err(());
}
@ -19,10 +20,25 @@ pub fn from_bytes(buf: &[u8]) -> Result<Font, ()> {
1 | 3 => 512,
_ => return Err(()),
};
// Data
let n = (4 + size * height as u16) as usize;
if buf.len() < n {
return Err(());
}
let data = buf[4..n].to_vec();
// TODO: Unicode Table
Ok(Font { height, size, data })
}
#[test_case]
fn parse_psf_font() {
assert!(from_bytes(include_bytes!("../../dsk/ini/boot.sh")).is_err());
let font = from_bytes(include_bytes!("../../dsk/ini/fonts/zap-light-8x16.psf")).unwrap();
assert_eq!(font.height, 16);
assert_eq!(font.size, 256);
assert_eq!(font.data.len(), 256 * 16);
}

View File

@ -1 +1,4 @@
pub mod console;
pub mod font;
pub mod syscall;
pub mod vga;

View File

@ -1,5 +1,5 @@
use crate::syscall;
use crate::kernel::syscall::number::*;
use crate::sys::syscall::number::*;
pub fn sleep(seconds: f64) {
unsafe { syscall!(SLEEP, seconds.to_bits()) };

94
src/api/vga/color.rs Normal file
View File

@ -0,0 +1,94 @@
/// The standard color palette in VGA text mode
#[allow(dead_code)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u8)]
pub enum Color {
Black = 0,
Blue = 1,
Green = 2,
Cyan = 3,
Red = 4,
Magenta = 5,
Brown = 6,
LightGray = 7,
DarkGray = 8,
LightBlue = 9,
LightGreen = 10,
LightCyan = 11,
LightRed = 12,
Pink = 13,
Yellow = 14,
White = 15,
}
const COLORS: [Color; 16] = [
Color::Black,
Color::Blue,
Color::Green,
Color::Cyan,
Color::Red,
Color::Magenta,
Color::Brown,
Color::LightGray,
Color::DarkGray,
Color::LightBlue,
Color::LightGreen,
Color::LightCyan,
Color::LightRed,
Color::Pink,
Color::Yellow,
Color::White,
];
pub fn colors() -> [Color; 16] {
COLORS
}
pub fn from_index(index: usize) -> Color {
COLORS[index]
}
pub fn from_ansi(code: u8) -> Color {
match code {
30 => Color::Black,
31 => Color::Red,
32 => Color::Green,
33 => Color::Brown,
34 => Color::Blue,
35 => Color::Magenta,
36 => Color::Cyan,
37 => Color::LightGray,
90 => Color::DarkGray,
91 => Color::LightRed,
92 => Color::LightGreen,
93 => Color::Yellow,
94 => Color::LightBlue,
95 => Color::Pink,
96 => Color::LightCyan,
97 => Color::White,
_ => Color::Black, // Error
}
}
impl Color {
pub fn to_palette_code(&self) -> u8 {
match self {
Color::Black => 0x00,
Color::Blue => 0x01,
Color::Green => 0x02,
Color::Cyan => 0x03,
Color::Red => 0x04,
Color::Magenta => 0x05,
Color::LightGray => 0x07,
Color::Brown => 0x14,
Color::DarkGray => 0x38,
Color::LightBlue => 0x39,
Color::LightGreen => 0x3A,
Color::LightCyan => 0x3B,
Color::LightRed => 0x3C,
Color::Pink => 0x3D,
Color::Yellow => 0x3E,
Color::White => 0x3F,
}
}
}

5
src/api/vga/mod.rs Normal file
View File

@ -0,0 +1,5 @@
pub mod color;
pub mod palette;
pub use color::Color;
pub use palette::Palette;

38
src/api/vga/palette.rs Normal file
View File

@ -0,0 +1,38 @@
use alloc::vec::Vec;
use core::convert::TryInto;
pub struct Palette {
pub colors: [(u8, u8, u8, u8); 16]
}
pub fn from_csv(s: &str) -> Result<Palette, ()> {
let colors: Vec<_> = s.split("\n").filter_map(|line| {
let line = line.split("#").next().unwrap(); // Remove comments
let color: Vec<u8> = line.split(",").filter_map(|value| {
let radix = if value.contains("0x") { 16 } else { 10 };
let value = value.trim().trim_start_matches("0x");
u8::from_str_radix(value, radix).ok()
}).collect();
if color.len() == 4 { // Color index + rgb values
Some((color[0], color[1], color[2], color[3]))
} else {
None
}
}).collect();
if let Ok(colors) = colors.try_into() { // Array of 16 colors
Ok(Palette { colors })
} else {
Err(())
}
}
#[test_case]
fn parse_palette_csv() {
assert!(from_csv("").is_err());
assert!(from_csv("0,0,0,0").is_err());
let s = include_str!("../../../dsk/ini/palette.csv");
let palette = from_csv(s).unwrap();
assert_eq!(palette.colors[0x03].0, 0x03);
assert_eq!(palette.colors[0x0D].2, 0x86);
}

View File

@ -10,30 +10,30 @@
extern crate alloc;
pub mod kernel;
pub mod api;
pub mod user;
pub mod sys;
pub mod usr;
use bootloader::BootInfo;
pub fn init(boot_info: &'static BootInfo) {
kernel::vga::init();
kernel::gdt::init();
kernel::idt::init();
unsafe { kernel::pic::PICS.lock().initialize() };
sys::vga::init();
sys::gdt::init();
sys::idt::init();
unsafe { sys::pic::PICS.lock().initialize() };
x86_64::instructions::interrupts::enable();
log!("MOROS v{}\n", env!("CARGO_PKG_VERSION"));
kernel::time::init();
kernel::keyboard::init();
kernel::serial::init();
kernel::mem::init(boot_info);
kernel::cpu::init();
kernel::pci::init(); // Require MEM
kernel::net::init(); // Require PCI
kernel::ata::init();
kernel::fs::init(); // Require ATA
sys::time::init();
sys::keyboard::init();
sys::serial::init();
sys::mem::init(boot_info);
sys::cpu::init();
sys::pci::init(); // Require MEM
sys::net::init(); // Require PCI
sys::ata::init();
sys::fs::init(); // Require ATA
}
#[alloc_error_handler]
@ -49,8 +49,8 @@ impl<T> Testable for T where T: Fn() {
fn run(&self) {
print!("test {} ... ", core::any::type_name::<T>());
self();
let csi_color = kernel::console::Style::color("LightGreen");
let csi_reset = kernel::console::Style::reset();
let csi_color = api::console::Style::color("LightGreen");
let csi_reset = api::console::Style::reset();
print!("{}ok{}\n", csi_color, csi_reset);
}
}
@ -106,8 +106,8 @@ fn test_kernel_main(boot_info: &'static BootInfo) -> ! {
#[cfg(test)]
#[panic_handler]
fn panic(info: &PanicInfo) -> ! {
let csi_color = kernel::console::Style::color("LightRed");
let csi_reset = kernel::console::Style::reset();
let csi_color = api::console::Style::color("LightRed");
let csi_reset = api::console::Style::reset();
print!("{}failed{}\n\n", csi_color, csi_reset);
print!("{}\n\n", info);
exit_qemu(QemuExitCode::Failed);

View File

@ -5,7 +5,7 @@ extern crate alloc;
use bootloader::{entry_point, BootInfo};
use core::panic::PanicInfo;
use moros::{kernel, print, user};
use moros::{sys, usr, print};
entry_point!(main);
@ -13,17 +13,17 @@ fn main(boot_info: &'static BootInfo) -> ! {
moros::init(boot_info);
loop {
let bootrc = "/ini/boot.sh";
if kernel::fs::File::open(bootrc).is_some() {
user::shell::main(&["shell", bootrc]);
if sys::fs::File::open(bootrc).is_some() {
usr::shell::main(&["shell", bootrc]);
} else {
if kernel::fs::is_mounted() {
if sys::fs::is_mounted() {
print!("Could not find '{}'\n", bootrc);
} else {
print!("MFS is not mounted to '/'\n");
}
print!("Running console in diskless mode\n");
user::shell::main(&["shell"]);
usr::shell::main(&["shell"]);
}
}
}
@ -32,6 +32,6 @@ fn main(boot_info: &'static BootInfo) -> ! {
fn panic(info: &PanicInfo) -> ! {
print!("{}\n", info);
loop {
kernel::time::sleep(10.0)
sys::time::sleep(10.0)
}
}

View File

@ -1,4 +1,4 @@
use crate::{kernel, log};
use crate::{sys, log};
use acpi::{AcpiHandler, PhysicalMapping, AcpiTables};
use alloc::boxed::Box;
use aml::{AmlContext, AmlName, DebugVerbosity, Handler};
@ -22,7 +22,7 @@ enum FADT {
}
fn read_addr<T>(physical_address: usize) -> T where T: Copy {
let virtual_address = kernel::mem::phys_to_virt(PhysAddr::new(physical_address as u64));
let virtual_address = sys::mem::phys_to_virt(PhysAddr::new(physical_address as u64));
unsafe { *virtual_address.as_ptr::<T>() }
}
@ -51,7 +51,7 @@ pub fn shutdown() {
let acpi_enable = read_fadt::<u8>(sdt.physical_address, FADT::AcpiEnable);
let mut port: Port<u8> = Port::new(smi_cmd_port);
unsafe { port.write(acpi_enable); }
kernel::time::sleep(3.0);
sys::time::sleep(3.0);
*/
pm1a_control_block = read_fadt::<u32>(sdt.physical_address, FADT::Pm1aControlBlock);
@ -61,7 +61,7 @@ pub fn shutdown() {
match &acpi.dsdt {
Some(dsdt) => {
//log!("ACPI Found DSDT at {}\n", dsdt.address);
let address = kernel::mem::phys_to_virt(PhysAddr::new(dsdt.address as u64));
let address = sys::mem::phys_to_virt(PhysAddr::new(dsdt.address as u64));
let stream = unsafe { core::slice::from_raw_parts(address.as_ptr(), dsdt.length as usize) };
if aml.parse_table(stream).is_ok() {
let name = AmlName::from_str("\\_S5").unwrap();
@ -99,7 +99,7 @@ pub struct MorosAcpiHandler;
impl AcpiHandler for MorosAcpiHandler {
unsafe fn map_physical_region<T>(&self, physical_address: usize, size: usize) -> PhysicalMapping<Self, T> {
let virtual_address = kernel::mem::phys_to_virt(PhysAddr::new(physical_address as u64));
let virtual_address = sys::mem::phys_to_virt(PhysAddr::new(physical_address as u64));
PhysicalMapping {
physical_start: physical_address,
virtual_start: core::ptr::NonNull::new(virtual_address.as_mut_ptr()).unwrap(),

View File

@ -1,4 +1,4 @@
use crate::kernel;
use crate::sys;
use alloc::slice::SliceIndex;
use alloc::sync::Arc;
use alloc::vec::Vec;
@ -70,7 +70,7 @@ impl PhysBuf {
fn phys_addr(ptr: &u8) -> u64 {
let rx_ptr = ptr as *const u8;
let virt_addr = VirtAddr::new(rx_ptr as u64);
let phys_addr = kernel::mem::virt_to_phys(virt_addr).unwrap();
let phys_addr = sys::mem::virt_to_phys(virt_addr).unwrap();
phys_addr.as_u64()
}

View File

@ -1,4 +1,4 @@
use crate::{kernel, log, print};
use crate::{sys, log, print};
use alloc::string::String;
use alloc::vec::Vec;
use bit_field::BitField;
@ -74,9 +74,9 @@ impl Bus {
fn reset(&mut self) {
unsafe {
self.control_register.write(4); // Set SRST bit
kernel::time::nanowait(5); // Wait at least 5 us
sys::time::nanowait(5); // Wait at least 5 us
self.control_register.write(0); // Then clear it
kernel::time::nanowait(2000); // Wait at least 2 ms
sys::time::nanowait(2000); // Wait at least 2 ms
}
}
@ -114,9 +114,9 @@ impl Bus {
fn busy_loop(&mut self) {
self.wait();
let start = kernel::clock::uptime();
let start = sys::clock::uptime();
while self.is_busy() {
if kernel::clock::uptime() - start > 1.0 { // Hanged
if sys::clock::uptime() - start > 1.0 { // Hanged
return self.reset();
}

View File

@ -1,11 +1,11 @@
use crate::kernel;
use crate::kernel::cmos::CMOS;
use crate::sys;
use crate::sys::cmos::CMOS;
const DAYS_BEFORE_MONTH: [u64; 13] = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365];
// NOTE: This clock is monotonic
pub fn uptime() -> f64 {
kernel::time::time_between_ticks() * kernel::time::ticks() as f64
sys::time::time_between_ticks() * sys::time::ticks() as f64
}
// NOTE: This clock is not monotonic
@ -19,8 +19,8 @@ pub fn realtime() -> f64 {
+ 60 * rtc.minute as u64
+ rtc.second as u64;
let fract = kernel::time::time_between_ticks()
* (kernel::time::ticks() - kernel::time::last_rtc_update()) as f64;
let fract = sys::time::time_between_ticks()
* (sys::time::ticks() - sys::time::last_rtc_update()) as f64;
(timestamp as f64) + fract
}

View File

@ -1,91 +1,9 @@
use crate::{kernel, print};
use crate::{sys, print};
use alloc::string::String;
use core::fmt;
use lazy_static::lazy_static;
use spin::Mutex;
use x86_64::instructions::interrupts;
pub struct Style {
foreground: Option<usize>,
background: Option<usize>,
}
impl Style {
pub fn reset() -> Self {
Self { foreground: None, background: None }
}
pub fn foreground(name: &str) -> Self {
Self { foreground: color_to_fg(name), background: None }
}
pub fn with_foreground(self, name: &str) -> Self {
Self { foreground: color_to_fg(name), background: self.background }
}
pub fn background(name: &str) -> Self {
Self { foreground: None, background: color_to_bg(name) }
}
pub fn with_background(self, name: &str) -> Self {
Self { foreground: self.foreground, background: color_to_bg(name) }
}
pub fn color(name: &str) -> Self {
Self::foreground(name)
}
pub fn with_color(self, name: &str) -> Self {
self.with_foreground(name)
}
}
impl fmt::Display for Style {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if let Some(fg) = self.foreground {
if let Some(bg) = self.background {
write!(f, "\x1b[{};{}m", fg, bg)
} else {
write!(f, "\x1b[{}m", fg)
}
} else if let Some(bg) = self.background {
write!(f, "\x1b[{}m", bg)
} else {
write!(f, "\x1b[0m")
}
}
}
fn color_to_fg(name: &str) -> Option<usize> {
match name {
"Black" => Some(30),
"Red" => Some(31),
"Green" => Some(32),
"Brown" => Some(33),
"Blue" => Some(34),
"Magenta" => Some(35),
"Cyan" => Some(36),
"LightGray" => Some(37),
"DarkGray" => Some(90),
"LightRed" => Some(91),
"LightGreen" => Some(92),
"Yellow" => Some(93),
"LightBlue" => Some(94),
"Pink" => Some(95),
"LightCyan" => Some(96),
"White" => Some(97),
_ => None,
}
}
fn color_to_bg(name: &str) -> Option<usize> {
if let Some(fg) = color_to_fg(name) {
Some(fg + 10)
} else {
None
}
}
lazy_static! {
pub static ref STDIN: Mutex<String> = Mutex::new(String::new());
pub static ref ECHO: Mutex<bool> = Mutex::new(true);
@ -98,7 +16,7 @@ pub fn has_cursor() -> bool {
pub fn clear_row_after(x: usize) {
if cfg!(feature = "video") {
kernel::vga::clear_row_after(x);
sys::vga::clear_row_after(x);
} else {
print!("\r"); // Move cursor to begining of line
print!("\x1b[{}C", x); // Move cursor forward to position
@ -108,7 +26,7 @@ pub fn clear_row_after(x: usize) {
pub fn cursor_position() -> (usize, usize) {
if cfg!(feature = "video") {
kernel::vga::cursor_position()
sys::vga::cursor_position()
} else {
print!("\x1b[6n"); // Ask cursor position
get_char(); // ESC
@ -137,7 +55,7 @@ pub fn cursor_position() -> (usize, usize) {
pub fn set_writer_position(x: usize, y: usize) {
if cfg!(feature = "video") {
kernel::vga::set_writer_position(x, y);
sys::vga::set_writer_position(x, y);
} else {
print!("\x1b[{};{}H", y + 1, x + 1);
}
@ -147,9 +65,9 @@ pub fn set_writer_position(x: usize, y: usize) {
macro_rules! print {
($($arg:tt)*) => ({
if cfg!(feature="video") {
$crate::kernel::vga::print_fmt(format_args!($($arg)*));
$crate::sys::vga::print_fmt(format_args!($($arg)*));
} else {
$crate::kernel::serial::print_fmt(format_args!($($arg)*));
$crate::sys::serial::print_fmt(format_args!($($arg)*));
}
});
}
@ -158,15 +76,15 @@ macro_rules! print {
macro_rules! log {
($($arg:tt)*) => ({
if !cfg!(test) {
let uptime = $crate::kernel::clock::uptime();
let csi_color = $crate::kernel::console::Style::color("LightGreen");
let csi_reset = $crate::kernel::console::Style::reset();
let uptime = $crate::sys::clock::uptime();
let csi_color = $crate::api::console::Style::color("LightGreen");
let csi_reset = $crate::api::console::Style::reset();
if cfg!(feature="video") {
$crate::kernel::vga::print_fmt(format_args!("{}[{:.6}]{} ", csi_color, uptime, csi_reset));
$crate::kernel::vga::print_fmt(format_args!($($arg)*));
$crate::sys::vga::print_fmt(format_args!("{}[{:.6}]{} ", csi_color, uptime, csi_reset));
$crate::sys::vga::print_fmt(format_args!($($arg)*));
} else {
$crate::kernel::serial::print_fmt(format_args!("{}[{:.6}]{} ", csi_color, uptime, csi_reset));
$crate::kernel::serial::print_fmt(format_args!($($arg)*));
$crate::sys::serial::print_fmt(format_args!("{}[{:.6}]{} ", csi_color, uptime, csi_reset));
$crate::sys::serial::print_fmt(format_args!($($arg)*));
}
}
});
@ -243,10 +161,10 @@ pub fn drain() {
}
pub fn get_char() -> char {
kernel::console::disable_echo();
kernel::console::enable_raw();
sys::console::disable_echo();
sys::console::enable_raw();
loop {
kernel::time::halt();
sys::time::halt();
let res = interrupts::without_interrupts(|| {
let mut stdin = STDIN.lock();
match stdin.chars().next_back() {
@ -260,8 +178,8 @@ pub fn get_char() -> char {
}
});
if let Some(c) = res {
kernel::console::enable_echo();
kernel::console::disable_raw();
sys::console::enable_echo();
sys::console::disable_raw();
return c;
}
}
@ -269,7 +187,7 @@ pub fn get_char() -> char {
pub fn get_line() -> String {
loop {
kernel::time::halt();
sys::time::halt();
let res = interrupts::without_interrupts(|| {
let mut stdin = STDIN.lock();
match stdin.chars().next_back() {

View File

@ -1,4 +1,4 @@
use crate::{kernel, log};
use crate::{sys, log};
use alloc::format;
use alloc::string::String;
use alloc::vec::Vec;
@ -42,7 +42,7 @@ pub fn realpath(pathname: &str) -> String {
if pathname.starts_with("/") {
pathname.into()
} else {
let dirname = kernel::process::dir();
let dirname = sys::process::dir();
let sep = if dirname.ends_with("/") { "" } else { "/" };
format!("{}{}{}", dirname, sep, pathname)
}
@ -54,6 +54,7 @@ pub struct File {
addr: u32,
size: u32,
dir: Dir, // TODO: Replace with `parent: Some(Dir)` and also add it to `Dir`
// TODO: add `offset: usize`
}
impl File {
@ -87,6 +88,9 @@ impl File {
self.size as usize
}
// TODO: return `Result<usize>`
// TODO: start `i` at `self.offset` instead of `0`
// TODO: set `self.offset` to `i` at the end
pub fn read(&self, buf: &mut [u8]) -> usize {
let buf_len = buf.len();
let mut addr = self.addr;
@ -109,6 +113,11 @@ impl File {
}
}
// TODO: add `seek(&mut self, pos: SeekFrom) -> Result<u32>`
// TODO: add `read_to_end(&self, buf: &mut Vec<u8>) -> Result<u32>`
// TODO: `return Result<String>`
pub fn read_to_string(&self) -> String {
let mut buf: Vec<u8> = Vec::with_capacity(self.size());
buf.resize(self.size(), 0);
@ -117,6 +126,9 @@ impl File {
String::from_utf8(buf).unwrap()
}
// TODO: `return Result<usize>`
// TODO: start `i` at `self.offset` instead of `0`
// TODO: set `self.offset` to `i` at the end
pub fn write(&mut self, buf: &[u8]) -> Result<(), ()> {
let buf_len = buf.len();
let mut addr = self.addr;
@ -650,11 +662,11 @@ impl BlockDevice {
}
pub fn read(&self, block: u32, mut buf: &mut [u8]) {
kernel::ata::read(self.bus, self.dsk, block, &mut buf);
sys::ata::read(self.bus, self.dsk, block, &mut buf);
}
pub fn write(&self, block: u32, buf: &[u8]) {
kernel::ata::write(self.bus, self.dsk, block, &buf);
sys::ata::write(self.bus, self.dsk, block, &buf);
}
}
@ -685,7 +697,7 @@ pub fn init() {
for bus in 0..2 {
for dsk in 0..2 {
let mut buf = [0u8; 512];
kernel::ata::read(bus, dsk, SUPERBLOCK_ADDR, &mut buf);
sys::ata::read(bus, dsk, SUPERBLOCK_ADDR, &mut buf);
if let Ok(header) = String::from_utf8(buf[0..8].to_vec()) {
if header == MAGIC {
log!("MFS Superblock found in ATA {}:{}\n", bus, dsk);

View File

@ -1,4 +1,4 @@
use crate::{kernel, print};
use crate::{sys, print};
use lazy_static::lazy_static;
use spin::Mutex;
use x86_64::instructions::interrupts;
@ -14,7 +14,7 @@ pub fn init() {
// Translate IRQ into system interrupt
fn interrupt_index(irq: u8) -> u8 {
kernel::pic::PIC_1_OFFSET + irq
sys::pic::PIC_1_OFFSET + irq
}
fn default_irq_handler() {
@ -27,7 +27,7 @@ lazy_static! {
let mut idt = InterruptDescriptorTable::new();
idt.breakpoint.set_handler_fn(breakpoint_handler);
unsafe {
idt.double_fault.set_handler_fn(double_fault_handler).set_stack_index(kernel::gdt::DOUBLE_FAULT_IST_INDEX);
idt.double_fault.set_handler_fn(double_fault_handler).set_stack_index(sys::gdt::DOUBLE_FAULT_IST_INDEX);
}
idt[interrupt_index(0) as usize].set_handler_fn(irq0_handler);
idt[interrupt_index(1) as usize].set_handler_fn(irq1_handler);
@ -55,7 +55,7 @@ macro_rules! irq_handler {
pub extern "x86-interrupt" fn $handler(_stack_frame: InterruptStackFrame) {
let handlers = IRQ_HANDLERS.lock();
handlers[$irq]();
unsafe { kernel::pic::PICS.lock().notify_end_of_interrupt(interrupt_index($irq)); }
unsafe { sys::pic::PICS.lock().notify_end_of_interrupt(interrupt_index($irq)); }
}
};
}
@ -167,8 +167,8 @@ extern "sysv64" fn syscall_handler(_stack_frame: &mut InterruptStackFrame, regs:
let arg1 = regs.rdi;
let arg2 = regs.rsi;
let arg3 = regs.rdx;
regs.rax = kernel::syscall::dispatcher(n, arg1, arg2, arg3);
unsafe { kernel::pic::PICS.lock().notify_end_of_interrupt(0x80) };
regs.rax = sys::syscall::dispatcher(n, arg1, arg2, arg3);
unsafe { sys::pic::PICS.lock().notify_end_of_interrupt(0x80) };
}
pub fn set_irq_handler(irq: u8, handler: fn()) {

View File

@ -1,4 +1,4 @@
use crate::kernel;
use crate::sys;
use lazy_static::lazy_static;
use pc_keyboard::{layouts, DecodedKey, HandleControl, KeyCode, Keyboard, ScancodeSet1};
use spin::Mutex;
@ -39,11 +39,11 @@ pub fn init() {
let res = unsafe {
port.read()
};
print!("[{:.6}] keyboard: identify {:#X}\n", kernel::clock::uptime(), res);
print!("[{:.6}] keyboard: identify {:#X}\n", sys::clock::uptime(), res);
let res = unsafe {
port.read()
};
print!("[{:.6}] keyboard: identify {:#X}\n", kernel::clock::uptime(), res);
print!("[{:.6}] keyboard: identify {:#X}\n", sys::clock::uptime(), res);
// Self-test
let res = unsafe {
@ -57,9 +57,9 @@ pub fn init() {
port.read()
};
if res == 0xAA { // 0xAA == Passed, 0xFC or 0xFD == Failed, 0xFE == Resend
print!("[{:.6}] keyboard: self test passed\n", kernel::clock::uptime());
print!("[{:.6}] keyboard: self test passed\n", sys::clock::uptime());
} else {
print!("[{:.6}] keyboard: self test failed ({:#X})\n", kernel::clock::uptime(), res);
print!("[{:.6}] keyboard: self test failed ({:#X})\n", sys::clock::uptime(), res);
}
// Switch to scancode set 2
@ -72,9 +72,9 @@ pub fn init() {
if res != 0xFA { // 0xFA == ACK, 0xFE == Resend
return init();
}
print!("[{:.6}] keyboard: switch to scancode set 2\n", kernel::clock::uptime());
print!("[{:.6}] keyboard: switch to scancode set 2\n", sys::clock::uptime());
*/
kernel::idt::set_irq_handler(1, interrupt_handler);
sys::idt::set_irq_handler(1, interrupt_handler);
}
fn read_scancode() -> u8 {
@ -95,7 +95,7 @@ fn interrupt_handler() {
DecodedKey::RawKey(KeyCode::ArrowDown) => '↓', // U+2193
DecodedKey::RawKey(_) => { return; }
};
kernel::console::key_handle(c);
sys::console::key_handle(c);
}
}
}

View File

@ -1,4 +1,4 @@
use crate::{kernel, log};
use crate::{sys, log};
use bootloader::bootinfo::{BootInfo, MemoryMap, MemoryRegionType};
use x86_64::structures::paging::{FrameAllocator, OffsetPageTable, PageTable, PhysFrame, Size4KiB, Translate};
use x86_64::{PhysAddr, VirtAddr};
@ -20,7 +20,7 @@ pub fn init(boot_info: &'static BootInfo) {
let mut mapper = unsafe { mapper(VirtAddr::new(PHYS_MEM_OFFSET)) };
let mut frame_allocator = unsafe { BootInfoFrameAllocator::init(&boot_info.memory_map) };
kernel::allocator::init_heap(&mut mapper, &mut frame_allocator).expect("heap initialization failed");
sys::allocator::init_heap(&mut mapper, &mut frame_allocator).expect("heap initialization failed");
}
pub fn phys_to_virt(addr: PhysAddr) -> VirtAddr {

View File

@ -5,7 +5,6 @@ pub mod clock;
pub mod cmos;
pub mod console;
pub mod cpu;
pub mod fonts;
pub mod fs;
pub mod gdt;
pub mod idt;

View File

@ -1,6 +1,6 @@
use crate::{kernel, log, print, user};
use crate::kernel::allocator::PhysBuf;
use crate::kernel::net::Stats;
use crate::{sys, usr, log, print};
use crate::sys::allocator::PhysBuf;
use crate::sys::net::Stats;
use alloc::collections::BTreeMap;
use alloc::sync::Arc;
@ -258,7 +258,7 @@ impl PCNET {
// Wait until init is done
while !self.ports.read_csr_32(0).get_bit(CSR0_IDON) {
kernel::time::halt();
sys::time::halt();
}
assert!(self.ports.read_csr_32(0) == 0b110000001); // IDON + INTR + INIT
@ -347,7 +347,7 @@ impl<'a> Device<'a> for PCNET {
self.stats.rx_add(packet.len() as u64);
if self.debug_mode {
//print!("Size: {} bytes\n", packet.len());
user::hex::print_hex(&packet);
usr::hex::print_hex(&packet);
//print!("CSR0: {:016b}\n", self.ports.read_csr_32(0));
//print!("RDTE: {:016b}\n", self.rx_des[rx_id * DE_LEN + 7]);
}
@ -427,7 +427,7 @@ impl phy::TxToken for TxToken {
self.device.stats.tx_add(len as u64);
if self.device.debug_mode {
//print!("Size: {} bytes\n", len);
user::hex::print_hex(&buf);
usr::hex::print_hex(&buf);
//print!("CSR0: {:016b}\n", self.device.ports.read_csr_32(0));
}
@ -436,7 +436,7 @@ impl phy::TxToken for TxToken {
}
pub fn init() {
if let Some(mut pci_device) = kernel::pci::find_device(0x1022, 0x2000) {
if let Some(mut pci_device) = sys::pci::find_device(0x1022, 0x2000) {
pci_device.enable_bus_mastering();
let io_base = (pci_device.base_addresses[0] as u16) & 0xFFF0;
let mut net_device = PCNET::new(io_base);
@ -456,7 +456,7 @@ pub fn init() {
routes(routes).
finalize();
*kernel::net::IFACE.lock() = Some(iface);
*sys::net::IFACE.lock() = Some(iface);
}
}
}

View File

@ -1,6 +1,6 @@
use crate::{kernel, log, print, user};
use crate::kernel::allocator::PhysBuf;
use crate::kernel::net::Stats;
use crate::{sys, usr, log, print};
use crate::sys::allocator::PhysBuf;
use crate::sys::net::Stats;
use alloc::collections::BTreeMap;
use alloc::vec::Vec;
use array_macro::array;
@ -256,7 +256,7 @@ impl<'a> Device<'a> for RTL8139 {
//print!("Size: {} bytes\n", len);
//print!("CRC: {:#08X}\n", crc);
//print!("RX Offset: {}\n", offset);
user::hex::print_hex(&self.rx_buffer[(offset + 4)..(offset + n)]);
usr::hex::print_hex(&self.rx_buffer[(offset + 4)..(offset + n)]);
}
self.stats.rx_add(len as u64);
@ -353,7 +353,7 @@ impl phy::TxToken for TxToken {
self.device.stats.tx_add(len as u64);
if self.device.debug_mode {
//print!("Size: {} bytes\n", len);
user::hex::print_hex(&buf[0..len]);
usr::hex::print_hex(&buf[0..len]);
}
res
@ -361,7 +361,7 @@ impl phy::TxToken for TxToken {
}
pub fn init() {
if let Some(mut pci_device) = kernel::pci::find_device(0x10EC, 0x8139) {
if let Some(mut pci_device) = sys::pci::find_device(0x10EC, 0x8139) {
pci_device.enable_bus_mastering();
let io_base = (pci_device.base_addresses[0] as u16) & 0xFFF0;
@ -382,17 +382,17 @@ pub fn init() {
routes(routes).
finalize();
*kernel::net::IFACE.lock() = Some(iface);
*sys::net::IFACE.lock() = Some(iface);
}
//let irq = pci_device.interrupt_line;
//kernel::idt::set_irq_handler(irq, interrupt_handler);
//sys::idt::set_irq_handler(irq, interrupt_handler);
}
}
pub fn interrupt_handler() {
print!("RTL8139 interrupt!\n");
if let Some(mut guard) = kernel::net::IFACE.try_lock() {
if let Some(mut guard) = sys::net::IFACE.try_lock() {
if let Some(ref mut iface) = *guard {
unsafe { iface.device_mut().ports.isr.write(0xffff) } // Clear the interrupt
}

View File

@ -1,4 +1,4 @@
use crate::kernel;
use crate::sys;
use core::fmt;
use core::fmt::Write;
use lazy_static::lazy_static;
@ -40,7 +40,7 @@ pub fn print_fmt(args: fmt::Arguments) {
}
pub fn init() {
kernel::idt::set_irq_handler(4, interrupt_handler);
sys::idt::set_irq_handler(4, interrupt_handler);
}
fn interrupt_handler() {
@ -50,5 +50,5 @@ fn interrupt_handler() {
'\x7F' => '\x08', // Delete => Backspace
c => c,
};
kernel::console::key_handle(c);
sys::console::key_handle(c);
}

View File

@ -76,15 +76,15 @@ pub unsafe fn syscall3(n: usize, arg1: usize, arg2: usize, arg3: usize) -> usize
#[macro_export]
macro_rules! syscall {
($n:expr) => (
$crate::kernel::syscall::syscall0(
$crate::sys::syscall::syscall0(
$n as usize));
($n:expr, $a1:expr) => (
$crate::kernel::syscall::syscall1(
$crate::sys::syscall::syscall1(
$n as usize, $a1 as usize));
($n:expr, $a1:expr, $a2:expr) => (
$crate::kernel::syscall::syscall2(
$crate::sys::syscall::syscall2(
$n as usize, $a1 as usize, $a2 as usize));
($n:expr, $a1:expr, $a2:expr, $a3:expr) => (
$crate::kernel::syscall::syscall3(
$crate::sys::syscall::syscall3(
$n as usize, $a1 as usize, $a2 as usize, $a3 as usize));
}

View File

@ -1,15 +1,15 @@
use crate::kernel;
use crate::sys;
pub fn sleep(seconds: f64) {
unsafe { asm!("sti") }; // Restore interrupts
kernel::time::sleep(seconds);
sys::time::sleep(seconds);
unsafe { asm!("cli") }; // Disable interrupts
}
pub fn uptime() -> f64 {
kernel::clock::uptime()
sys::clock::uptime()
}
pub fn realtime() -> f64 {
kernel::clock::realtime()
sys::clock::realtime()
}

View File

@ -1,5 +1,5 @@
use crate::kernel;
use crate::kernel::cmos::CMOS;
use crate::sys;
use crate::sys::cmos::CMOS;
use core::hint::spin_loop;
use core::sync::atomic::{AtomicUsize, AtomicU64, Ordering};
use x86_64::instructions::interrupts;
@ -41,8 +41,8 @@ fn rdtsc() -> u64 {
}
pub fn sleep(seconds: f64) {
let start = kernel::clock::uptime();
while kernel::clock::uptime() - start < seconds {
let start = sys::clock::uptime();
while sys::clock::uptime() - start < seconds {
halt();
}
}
@ -82,10 +82,10 @@ pub fn init() {
// PIT timmer
let divider = if PIT_DIVIDER < 65536 { PIT_DIVIDER } else { 0 };
set_pit_frequency_divider(divider as u16);
kernel::idt::set_irq_handler(0, pit_interrupt_handler);
sys::idt::set_irq_handler(0, pit_interrupt_handler);
// RTC timmer
kernel::idt::set_irq_handler(8, rtc_interrupt_handler);
sys::idt::set_irq_handler(8, rtc_interrupt_handler);
CMOS::new().enable_update_interrupt();
// TSC timmer

View File

@ -1,4 +1,6 @@
use crate::kernel::fonts::Font;
use crate::api::font::Font;
use crate::api::vga::{Color, Palette};
use crate::api::vga::color;
use bit_field::BitField;
use core::fmt;
use core::fmt::Write;
@ -25,93 +27,6 @@ lazy_static! {
});
}
/// The standard color palette in VGA text mode
#[allow(dead_code)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u8)]
pub enum Color {
Black = 0,
Blue = 1,
Green = 2,
Cyan = 3,
Red = 4,
Magenta = 5,
Brown = 6,
LightGray = 7,
DarkGray = 8,
LightBlue = 9,
LightGreen = 10,
LightCyan = 11,
LightRed = 12,
Pink = 13,
Yellow = 14,
White = 15,
}
const COLORS: [Color; 16] = [
Color::Black,
Color::Blue,
Color::Green,
Color::Cyan,
Color::Red,
Color::Magenta,
Color::Brown,
Color::LightGray,
Color::DarkGray,
Color::LightBlue,
Color::LightGreen,
Color::LightCyan,
Color::LightRed,
Color::Pink,
Color::Yellow,
Color::White,
];
fn color_from_ansi(code: u8) -> Color {
match code {
30 => Color::Black,
31 => Color::Red,
32 => Color::Green,
33 => Color::Brown,
34 => Color::Blue,
35 => Color::Magenta,
36 => Color::Cyan,
37 => Color::LightGray,
90 => Color::DarkGray,
91 => Color::LightRed,
92 => Color::LightGreen,
93 => Color::Yellow,
94 => Color::LightBlue,
95 => Color::Pink,
96 => Color::LightCyan,
97 => Color::White,
_ => FG, // Error
}
}
impl Color {
fn to_palette_code(&self) -> u8 {
match self {
Color::Black => 0x00,
Color::Blue => 0x01,
Color::Green => 0x02,
Color::Cyan => 0x03,
Color::Red => 0x04,
Color::Magenta => 0x05,
Color::LightGray => 0x07,
Color::Brown => 0x14,
Color::DarkGray => 0x38,
Color::LightBlue => 0x39,
Color::LightGreen => 0x3A,
Color::LightCyan => 0x3B,
Color::LightRed => 0x3C,
Color::Pink => 0x3D,
Color::Yellow => 0x3E,
Color::White => 0x3F,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(transparent)]
struct ColorCode(u8);
@ -263,8 +178,8 @@ impl Writer {
pub fn color(&self) -> (Color, Color) {
let cc = self.color_code.0;
let fg = COLORS[cc.get_bits(0..4) as usize];
let bg = COLORS[cc.get_bits(4..8) as usize];
let fg = color::from_index(cc.get_bits(0..4) as usize);
let bg = color::from_index(cc.get_bits(4..8) as usize);
(fg, bg)
}
@ -306,7 +221,7 @@ impl Writer {
let mut data: Port<u8> = Port::new(0x03C9); // Data Register
for (i, r, g, b) in palette.colors {
if i < 16 {
let code = COLORS[i as usize].to_palette_code();
let code = color::from_index(i as usize).to_palette_code();
unsafe {
addr.write(code);
data.write(r >> 2); // Convert 8-bit color to 6-bit color
@ -340,10 +255,10 @@ impl Perform for Writer {
bg = BG;
},
30..=37 | 90..=97 => {
fg = color_from_ansi(param[0] as u8);
fg = color::from_ansi(param[0] as u8);
},
40..=47 | 100..=107 => {
bg = color_from_ansi((param[0] as u8) - 10);
bg = color::from_ansi((param[0] as u8) - 10);
},
_ => {}
}
@ -434,10 +349,6 @@ pub fn set_color(foreground: Color, background: Color) {
})
}
pub fn colors() -> [Color; 16] {
COLORS
}
// Printable ascii chars + backspace + newline + ext chars
pub fn is_printable(c: u8) -> bool {
match c {
@ -458,10 +369,6 @@ pub fn set_palette(palette: Palette) {
})
}
pub struct Palette {
pub colors: [(u8, u8, u8, u8); 16]
}
pub fn init() {
let mut isr: Port<u8> = Port::new(0x03DA); // Input Status Register
let mut aadr: Port<u8> = Port::new(0x03C0); // Attribute Address/Data Register

View File

@ -1,6 +0,0 @@
use crate::{kernel, user};
pub fn main(_args: &[&str]) -> user::shell::ExitCode {
kernel::vga::clear_screen();
user::shell::ExitCode::CommandSuccessful
}

View File

@ -1,13 +0,0 @@
use crate::{kernel, print, user};
use crate::kernel::console::Style;
use alloc::string::ToString;
pub fn main(_args: &[&str]) -> user::shell::ExitCode {
let width = kernel::allocator::size().to_string().len();
let color = Style::color("LightCyan");
let reset = Style::reset();
print!("{}Size:{} {:width$}\n", color, reset, kernel::allocator::size(), width = width);
print!("{}Used:{} {:width$}\n", color, reset, kernel::allocator::used(), width = width);
print!("{}Free:{} {:width$}\n", color, reset, kernel::allocator::free(), width = width);
user::shell::ExitCode::CommandSuccessful
}

View File

@ -1,13 +0,0 @@
use crate::user;
pub fn main(args: &[&str]) -> user::shell::ExitCode {
if args.len() != 3 {
return user::shell::ExitCode::CommandError;
}
// TODO: Avoid doing copy+delete
match user::copy::main(args) {
user::shell::ExitCode::CommandSuccessful => user::delete::main(&args[0..2]),
_ => user::shell::ExitCode::CommandError,
}
}

View File

@ -1,12 +0,0 @@
use crate::user;
use crate::api::syscall;
pub fn main(args: &[&str]) -> user::shell::ExitCode {
if args.len() == 2 {
if let Ok(duration) = args[1].parse::<f64>() {
syscall::sleep(duration);
return user::shell::ExitCode::CommandSuccessful;
}
}
user::shell::ExitCode::CommandError
}

View File

@ -1,7 +0,0 @@
use crate::{print, user};
use crate::api::syscall;
pub fn main(_args: &[&str]) -> user::shell::ExitCode {
print!("{:.6}\n", syscall::uptime());
user::shell::ExitCode::CommandSuccessful
}

View File

@ -1,60 +0,0 @@
use crate::{kernel, print, user};
use crate::kernel::vga::Palette;
use alloc::vec::Vec;
use core::convert::TryInto;
pub fn main(args: &[&str]) -> user::shell::ExitCode {
if args.len() == 1 {
print!("Usage: vga <command>\n");
return user::shell::ExitCode::CommandError;
}
match args[1] {
"set" => {
if args.len() == 4 && args[2] == "font" {
if let Some(file) = kernel::fs::File::open(args[3]) {
let size = file.size();
let mut buf = Vec::with_capacity(size);
buf.resize(size, 0);
file.read(&mut buf);
if let Ok(font) = kernel::fonts::from_bytes(&buf) {
kernel::vga::set_font(&font);
} else {
print!("Could not parse font file\n");
return user::shell::ExitCode::CommandError;
}
}
} else if args.len() == 4 && args[2] == "palette" {
if let Some(file) = kernel::fs::File::open(args[3]) {
let mut colors = Vec::with_capacity(16);
for line in file.read_to_string().split("\n") {
let line = line.split("#").next().unwrap();
let color: Vec<u8> = line.split(",").filter_map(|value| {
let radix = if value.contains("0x") { 16 } else { 10 };
let value = value.trim().trim_start_matches("0x");
u8::from_str_radix(value, radix).ok()
}).collect();
if color.len() == 4 {
colors.push((color[0], color[1], color[2], color[3]));
}
}
if let Ok(colors) = colors.try_into() {
let palette = Palette { colors };
kernel::vga::set_palette(palette);
} else {
print!("Could not parse palette file\n");
return user::shell::ExitCode::CommandError;
}
}
} else {
print!("Invalid command\n");
return user::shell::ExitCode::CommandError;
}
},
_ => {
print!("Invalid command\n");
return user::shell::ExitCode::CommandError;
}
}
user::shell::ExitCode::CommandSuccessful
}

View File

@ -1,15 +1,15 @@
use crate::{print, user};
use crate::{usr, print};
use alloc::string::String;
use alloc::vec::Vec;
pub fn main(args: &[&str]) -> user::shell::ExitCode {
pub fn main(args: &[&str]) -> usr::shell::ExitCode {
if args.len() != 2 {
user::shell::ExitCode::CommandError
usr::shell::ExitCode::CommandError
} else {
let buf = encode(args[1].as_bytes());
let encoded = String::from_utf8(buf).unwrap();
print!("{}\n", encoded);
user::shell::ExitCode::CommandSuccessful
usr::shell::ExitCode::CommandSuccessful
}
}

6
src/usr/clear.rs Normal file
View File

@ -0,0 +1,6 @@
use crate::{sys, usr};
pub fn main(_args: &[&str]) -> usr::shell::ExitCode {
sys::vga::clear_screen();
usr::shell::ExitCode::CommandSuccessful
}

View File

@ -1,7 +1,7 @@
use crate::{print, user};
use crate::{usr, print};
use alloc::format;
pub fn main(_args: &[&str]) -> user::shell::ExitCode {
pub fn main(_args: &[&str]) -> usr::shell::ExitCode {
let csi_reset = "\x1b[0m";
for i in 30..38 {
@ -25,5 +25,5 @@ pub fn main(_args: &[&str]) -> user::shell::ExitCode {
}
print!("\n");
user::shell::ExitCode::CommandSuccessful
usr::shell::ExitCode::CommandSuccessful
}

View File

@ -1,10 +1,10 @@
use crate::{kernel, print, user};
use crate::{sys, usr, print};
use alloc::vec::Vec;
pub fn main(args: &[&str]) -> user::shell::ExitCode {
pub fn main(args: &[&str]) -> usr::shell::ExitCode {
if args.len() != 3 {
print!("Usage: copy <source> <dest>\n");
return user::shell::ExitCode::CommandError;
return usr::shell::ExitCode::CommandError;
}
let source = args[1];
@ -12,30 +12,30 @@ pub fn main(args: &[&str]) -> user::shell::ExitCode {
if dest.starts_with("/dev") || dest.starts_with("/sys") {
print!("Permission denied to write to '{}'\n", dest);
return user::shell::ExitCode::CommandError;
return usr::shell::ExitCode::CommandError;
}
if let Some(source_file) = kernel::fs::File::open(source) {
if let Some(mut dest_file) = kernel::fs::File::create(dest) {
if let Some(source_file) = sys::fs::File::open(source) {
if let Some(mut dest_file) = sys::fs::File::create(dest) {
let filesize = source_file.size();
let mut buf = Vec::with_capacity(filesize);
buf.resize(filesize, 0);
source_file.read(&mut buf);
match dest_file.write(&buf) {
Ok(()) => {
user::shell::ExitCode::CommandSuccessful
usr::shell::ExitCode::CommandSuccessful
},
Err(()) => {
print!("Could not write to '{}'\n", dest);
user::shell::ExitCode::CommandError
usr::shell::ExitCode::CommandError
}
}
} else {
print!("Permission denied to write to '{}'\n", dest);
user::shell::ExitCode::CommandError
usr::shell::ExitCode::CommandError
}
} else {
print!("File not found '{}'\n", source);
user::shell::ExitCode::CommandError
usr::shell::ExitCode::CommandError
}
}

View File

@ -1,8 +1,8 @@
use crate::{kernel, print, user};
use crate::{sys, usr, print};
use crate::api::syscall;
use time::{OffsetDateTime, Duration, UtcOffset};
pub fn main(args: &[&str]) -> user::shell::ExitCode {
pub fn main(args: &[&str]) -> usr::shell::ExitCode {
let seconds = syscall::realtime(); // Since Unix Epoch
let nanoseconds = libm::floor(1e9 * (seconds - libm::floor(seconds))) as i64;
let date = OffsetDateTime::from_unix_timestamp(seconds as i64).to_offset(offset())
@ -12,17 +12,17 @@ pub fn main(args: &[&str]) -> user::shell::ExitCode {
match time::util::validate_format_string(format) {
Ok(()) => {
print!("{}\n", date.format(format));
user::shell::ExitCode::CommandSuccessful
usr::shell::ExitCode::CommandSuccessful
}
Err(e) => {
print!("Error: {}\n", e);
user::shell::ExitCode::CommandError
usr::shell::ExitCode::CommandError
}
}
}
fn offset() -> UtcOffset {
if let Some(tz) = kernel::process::env("TZ") {
if let Some(tz) = sys::process::env("TZ") {
if let Ok(offset) = tz.parse::<i32>() {
return UtcOffset::seconds(offset);
}

View File

@ -1,15 +1,15 @@
use crate::{kernel, print, user};
use crate::{sys, usr, print};
pub fn main(args: &[&str]) -> user::shell::ExitCode {
pub fn main(args: &[&str]) -> usr::shell::ExitCode {
if args.len() != 2 {
return user::shell::ExitCode::CommandError;
return usr::shell::ExitCode::CommandError;
}
let mut pathname = args[1];
if pathname.starts_with("/dev") || pathname.starts_with("/sys") {
print!("Permission denied to delete '{}'\n", pathname);
return user::shell::ExitCode::CommandError;
return usr::shell::ExitCode::CommandError;
}
// The commands `delete /usr/alice/` and `delete /usr/alice` are equivalent,
@ -18,27 +18,27 @@ pub fn main(args: &[&str]) -> user::shell::ExitCode {
pathname = pathname.trim_end_matches('/');
}
if let Some(dir) = kernel::fs::Dir::open(pathname) {
if let Some(dir) = sys::fs::Dir::open(pathname) {
if dir.read().count() == 0 {
if kernel::fs::Dir::delete(pathname).is_ok() {
user::shell::ExitCode::CommandSuccessful
if sys::fs::Dir::delete(pathname).is_ok() {
usr::shell::ExitCode::CommandSuccessful
} else {
print!("Could not delete directory '{}'\n", pathname);
user::shell::ExitCode::CommandError
usr::shell::ExitCode::CommandError
}
} else {
print!("Directory '{}' not empty\n", pathname);
user::shell::ExitCode::CommandError
usr::shell::ExitCode::CommandError
}
} else if kernel::fs::File::open(pathname).is_some() {
if kernel::fs::File::delete(pathname).is_ok() {
user::shell::ExitCode::CommandSuccessful
} else if sys::fs::File::open(pathname).is_some() {
if sys::fs::File::delete(pathname).is_ok() {
usr::shell::ExitCode::CommandSuccessful
} else {
print!("Could not delete file '{}'\n", pathname);
user::shell::ExitCode::CommandError
usr::shell::ExitCode::CommandError
}
} else {
print!("File not found '{}'\n", pathname);
user::shell::ExitCode::CommandError
usr::shell::ExitCode::CommandError
}
}

View File

@ -1,4 +1,4 @@
use crate::{kernel, print, user};
use crate::{sys, usr, print};
use crate::api::syscall;
use alloc::string::ToString;
use alloc::vec;
@ -9,8 +9,8 @@ use smoltcp::socket::{RawPacketMetadata, RawSocketBuffer, SocketSet};
use smoltcp::time::Instant;
use smoltcp::wire::{IpCidr, Ipv4Address, Ipv4Cidr};
pub fn main(_args: &[&str]) -> user::shell::ExitCode {
if let Some(ref mut iface) = *kernel::net::IFACE.lock() {
pub fn main(_args: &[&str]) -> usr::shell::ExitCode {
if let Some(ref mut iface) = *sys::net::IFACE.lock() {
let mut iface = iface;
let mut sockets = SocketSet::new(vec![]);
let dhcp_rx_buffer = RawSocketBuffer::new([RawPacketMetadata::EMPTY; 1], vec![0; 900]);
@ -30,11 +30,11 @@ pub fn main(_args: &[&str]) -> user::shell::ExitCode {
loop {
if syscall::realtime() - started > timeout {
print!("Timeout reached\n");
return user::shell::ExitCode::CommandError;
return usr::shell::ExitCode::CommandError;
}
if kernel::console::abort() {
if sys::console::abort() {
print!("\n");
return user::shell::ExitCode::CommandError;
return usr::shell::ExitCode::CommandError;
}
let timestamp = Instant::from_millis((syscall::realtime() * 1000.0) as i64);
match iface.poll(&mut sockets, timestamp) {
@ -77,7 +77,7 @@ pub fn main(_args: &[&str]) -> user::shell::ExitCode {
print!("DNS: {}\n", dns_servers.join(", "));
}
return user::shell::ExitCode::CommandSuccessful;
return usr::shell::ExitCode::CommandSuccessful;
}
if let Some(wait_duration) = iface.poll_delay(&sockets, timestamp) {
@ -87,5 +87,5 @@ pub fn main(_args: &[&str]) -> user::shell::ExitCode {
}
}
user::shell::ExitCode::CommandError
usr::shell::ExitCode::CommandError
}

View File

@ -1,9 +1,9 @@
use crate::{kernel, print, user};
use crate::{sys, usr, print};
use alloc::vec::Vec;
const COMMANDS: [&'static str; 2] = ["list", "format"];
pub fn main(args: &[&str]) -> user::shell::ExitCode {
pub fn main(args: &[&str]) -> usr::shell::ExitCode {
if args.len() == 1 || !COMMANDS.contains(&args[1]) {
return usage();
}
@ -24,36 +24,36 @@ pub fn main(args: &[&str]) -> user::shell::ExitCode {
}
}
fn usage() -> user::shell::ExitCode {
fn usage() -> usr::shell::ExitCode {
print!("Usage: <command>\n");
print!("\n");
print!("Commands:\n");
print!(" list\n");
print!(" format <path>\n");
user::shell::ExitCode::CommandError
usr::shell::ExitCode::CommandError
}
fn list() -> user::shell::ExitCode {
fn list() -> usr::shell::ExitCode {
print!("Path Name (Size)\n");
for (bus, drive, model, serial, size, unit) in kernel::ata::list() {
for (bus, drive, model, serial, size, unit) in sys::ata::list() {
print!("/dev/ata/{}/{} {} {} ({} {})\n", bus, drive, model, serial, size, unit);
}
user::shell::ExitCode::CommandSuccessful
usr::shell::ExitCode::CommandSuccessful
}
fn format(pathname: &str) -> user::shell::ExitCode {
fn format(pathname: &str) -> usr::shell::ExitCode {
let path: Vec<_> = pathname.split('/').collect();
if !pathname.starts_with("/dev/ata/") || path.len() != 5 {
print!("Could not find disk at '{}'\n", pathname);
return user::shell::ExitCode::CommandError;
return usr::shell::ExitCode::CommandError;
}
let bus = path[3].parse().expect("Could not parse <bus>");
let dsk = path[4].parse().expect("Could not parse <dsk>");
kernel::fs::format(bus, dsk);
sys::fs::format(bus, dsk);
print!("Disk successfully formatted\n");
print!("MFS is now mounted to '/'\n");
user::shell::ExitCode::CommandSuccessful
usr::shell::ExitCode::CommandSuccessful
}

View File

@ -1,13 +1,13 @@
use crate::{kernel, print, user};
use crate::kernel::console::Style;
use crate::{sys, usr, print};
use crate::api::console::Style;
use alloc::format;
use alloc::string::{String, ToString};
use alloc::vec::Vec;
use core::cmp;
pub fn main(args: &[&str]) -> user::shell::ExitCode {
pub fn main(args: &[&str]) -> usr::shell::ExitCode {
if args.len() != 2 {
return user::shell::ExitCode::CommandError;
return usr::shell::ExitCode::CommandError;
}
let pathname = args[1];
@ -20,7 +20,7 @@ struct EditorConfig {
}
pub struct Editor {
file: Option<kernel::fs::File>,
file: Option<sys::fs::File>,
pathname: String,
lines: Vec<String>,
dx: usize, // Horizontal offset
@ -35,7 +35,7 @@ impl Editor {
let mut lines = Vec::new();
let config = EditorConfig { tab_size: 4 };
let file = match kernel::fs::File::open(pathname) {
let file = match sys::fs::File::open(pathname) {
Some(file) => {
let contents = file.read_to_string();
for line in contents.split('\n') {
@ -45,7 +45,7 @@ impl Editor {
},
None => {
lines.push(String::new());
kernel::fs::File::create(pathname)
sys::fs::File::create(pathname)
}
};
@ -54,7 +54,7 @@ impl Editor {
Self { file, pathname, lines, dx, dy, config }
}
pub fn save(&mut self) -> user::shell::ExitCode {
pub fn save(&mut self) -> usr::shell::ExitCode {
let mut contents = String::new();
let n = self.lines.len();
for i in 0..n {
@ -68,22 +68,22 @@ impl Editor {
file.write(&contents.as_bytes()).unwrap();
let status = format!("Wrote {}L to '{}'", n, self.pathname);
self.print_status(&status, "Yellow");
user::shell::ExitCode::CommandSuccessful
usr::shell::ExitCode::CommandSuccessful
} else {
let status = format!("Could not write to '{}'", self.pathname);
self.print_status(&status, "LightRed");
user::shell::ExitCode::CommandError
usr::shell::ExitCode::CommandError
}
}
fn print_status(&mut self, status: &str, background: &str) {
let color = Style::color("Black").with_background(background);
let reset = Style::reset();
let (x, y) = kernel::vga::cursor_position();
kernel::vga::set_writer_position(0, self.height());
let (x, y) = sys::vga::cursor_position();
sys::vga::set_writer_position(0, self.height());
print!("{}{:width$}{}", color, status, reset, width = self.width());
kernel::vga::set_writer_position(x, y);
kernel::vga::set_cursor_position(x, y);
sys::vga::set_writer_position(x, y);
sys::vga::set_cursor_position(x, y);
}
fn print_screen(&mut self) {
@ -93,7 +93,7 @@ impl Editor {
for y in a..b {
rows.push(self.render_line(y));
}
kernel::vga::set_writer_position(0, 0);
sys::vga::set_writer_position(0, 0);
print!("{}", rows.join("\n"));
let status = format!("Editing '{}'", self.pathname);
@ -124,22 +124,22 @@ impl Editor {
}
}
pub fn run(&mut self) -> user::shell::ExitCode {
kernel::vga::clear_screen();
pub fn run(&mut self) -> usr::shell::ExitCode {
sys::vga::clear_screen();
self.print_screen();
kernel::vga::set_cursor_position(0, 0);
kernel::vga::set_writer_position(0, 0);
sys::vga::set_cursor_position(0, 0);
sys::vga::set_writer_position(0, 0);
loop {
let (mut x, mut y) = kernel::vga::cursor_position();
let c = kernel::console::get_char();
let (mut x, mut y) = sys::vga::cursor_position();
let c = sys::console::get_char();
match c {
'\0' => {
continue;
}
'\x11' => { // Ctrl Q
// TODO: Warn if modifications have not been saved
kernel::vga::clear_screen();
sys::vga::clear_screen();
break;
},
'\x17' => { // Ctrl W
@ -147,7 +147,7 @@ impl Editor {
},
'\x18' => { // Ctrl X
let res = self.save();
kernel::vga::clear_screen();
sys::vga::clear_screen();
return res;
},
'\n' => { // Newline
@ -257,7 +257,7 @@ impl Editor {
} else {
x -= 1;
let line = self.render_line(self.dy + y);
kernel::vga::clear_row();
sys::vga::clear_row();
print!("{}", line);
}
} else { // Remove newline from previous line
@ -294,7 +294,7 @@ impl Editor {
} else { // Remove char from line
self.lines[self.dy + y].remove(self.dx + x);
let line = self.render_line(self.dy + y);
kernel::vga::clear_row();
sys::vga::clear_row();
print!("{}", line);
}
},
@ -314,16 +314,16 @@ impl Editor {
self.print_screen();
} else {
let line = self.render_line(self.dy + y);
kernel::vga::clear_row();
sys::vga::clear_row();
print!("{}", line);
}
}
},
}
kernel::vga::set_cursor_position(x, y);
kernel::vga::set_writer_position(x, y);
sys::vga::set_cursor_position(x, y);
sys::vga::set_writer_position(x, y);
}
user::shell::ExitCode::CommandSuccessful
usr::shell::ExitCode::CommandSuccessful
}
// Move cursor past end of line to end of line or left of the screen
@ -341,11 +341,11 @@ impl Editor {
}
fn height(&self) -> usize {
kernel::vga::screen_height() - 1 // Leave out one line for status line
sys::vga::screen_height() - 1 // Leave out one line for status line
}
fn width(&self) -> usize {
kernel::vga::screen_width()
sys::vga::screen_width()
}
}

View File

@ -1,8 +1,8 @@
use crate::{kernel, print, user};
use crate::{sys, usr, print};
pub fn main(args: &[&str]) -> user::shell::ExitCode {
pub fn main(args: &[&str]) -> usr::shell::ExitCode {
if args.len() == 1 {
for (key, val) in kernel::process::envs() {
for (key, val) in sys::process::envs() {
print!("{}={}\n", key, val);
}
} else {
@ -10,13 +10,13 @@ pub fn main(args: &[&str]) -> user::shell::ExitCode {
if let Some(i) = arg.find('=') {
let (key, mut val) = arg.split_at(i);
val = &val[1..];
kernel::process::set_env(key, val);
sys::process::set_env(key, val);
print!("{}={}\n", key, val);
} else {
print!("Error: could not parse '{}'\n", arg);
return user::shell::ExitCode::CommandError;
return usr::shell::ExitCode::CommandError;
}
}
}
user::shell::ExitCode::CommandSuccessful
usr::shell::ExitCode::CommandSuccessful
}

View File

@ -1,12 +1,12 @@
use crate::{print, user};
use crate::{usr, print};
use crate::api::syscall;
use alloc::format;
use core::f64::consts::PI;
pub fn main(args: &[&str]) -> user::shell::ExitCode {
pub fn main(args: &[&str]) -> usr::shell::ExitCode {
if args.len() < 2 {
print!("Usage: <longitude> [<timestamp>]\n");
return user::shell::ExitCode::CommandError;
return usr::shell::ExitCode::CommandError;
}
let longitude = args[1].parse().expect("Could not parse longitude");
@ -21,7 +21,7 @@ pub fn main(args: &[&str]) -> user::shell::ExitCode {
let t = libm::floor(100.0 * t) / 100.0; // Avoid rounding up 99.996 to 100.00
print!("{}\n", format!("{:05.2}", t).replace(".", ":"));
user::shell::ExitCode::CommandSuccessful
usr::shell::ExitCode::CommandSuccessful
}
pub fn geotime(longitude: f64, timestamp: f64) -> f64 {

View File

@ -1,11 +1,11 @@
use crate::{kernel, print, user};
use crate::{sys, usr, print};
use crate::api::syscall;
use crate::kernel::console::Style;
use crate::api::console::Style;
pub fn main(_args: &[&str]) -> user::shell::ExitCode {
pub fn main(_args: &[&str]) -> usr::shell::ExitCode {
let csi_color = Style::color("Yellow");
let csi_reset = Style::reset();
print!("{}MOROS has reached its fate, the system is now halting.{}\n", csi_color, csi_reset);
kernel::acpi::shutdown();
sys::acpi::shutdown();
loop { syscall::sleep(1.0) }
}

View File

@ -1,7 +1,7 @@
use crate::{print, user};
use crate::kernel::console::Style;
use crate::{usr, print};
use crate::api::console::Style;
pub fn main(args: &[&str]) -> user::shell::ExitCode {
pub fn main(args: &[&str]) -> usr::shell::ExitCode {
if args.len() > 1 {
help_command(args[1])
} else {
@ -9,7 +9,7 @@ pub fn main(args: &[&str]) -> user::shell::ExitCode {
}
}
fn help_command(cmd: &str) -> user::shell::ExitCode {
fn help_command(cmd: &str) -> usr::shell::ExitCode {
match cmd {
"date" => help_date(),
"edit" => help_edit(),
@ -17,12 +17,12 @@ fn help_command(cmd: &str) -> user::shell::ExitCode {
}
}
fn help_unknown(cmd: &str) -> user::shell::ExitCode {
fn help_unknown(cmd: &str) -> usr::shell::ExitCode {
print!("Help not found for command '{}'\n", cmd);
user::shell::ExitCode::CommandError
usr::shell::ExitCode::CommandError
}
fn help_summary() -> user::shell::ExitCode {
fn help_summary() -> usr::shell::ExitCode {
let csi_color = Style::color("Yellow");
let csi_reset = Style::reset();
print!("{}Commands:{}\n", csi_color, csi_reset);
@ -52,10 +52,10 @@ fn help_summary() -> user::shell::ExitCode {
print!("\n");
print!("Made with <3 in 2019-2021 by Vincent Ollivier <v@vinc.cc>\n");
user::shell::ExitCode::CommandSuccessful
usr::shell::ExitCode::CommandSuccessful
}
fn help_edit() -> user::shell::ExitCode {
fn help_edit() -> usr::shell::ExitCode {
let csi_color = Style::color("Yellow");
let csi_reset = Style::reset();
print!("MOROS text editor is somewhat inspired by Pico, but with an even smaller range\n");
@ -78,10 +78,10 @@ fn help_edit() -> user::shell::ExitCode {
let csi_reset = Style::reset();
print!(" {}{}{} {}\n", csi_color, shortcut, csi_reset, usage);
}
user::shell::ExitCode::CommandSuccessful
usr::shell::ExitCode::CommandSuccessful
}
fn help_date() -> user::shell::ExitCode {
fn help_date() -> usr::shell::ExitCode {
let csi_color = Style::color("Yellow");
let csi_reset = Style::reset();
print!("The date command's formatting behavior is based on strftime in C\n");
@ -128,5 +128,5 @@ fn help_date() -> user::shell::ExitCode {
let csi_reset = Style::reset();
print!(" {}{}{} {}\n", csi_color, specifier, csi_reset, usage);
}
user::shell::ExitCode::CommandSuccessful
usr::shell::ExitCode::CommandSuccessful
}

View File

@ -1,20 +1,20 @@
use crate::{kernel, print, user};
use crate::kernel::console::Style;
use crate::{sys, usr, print};
use crate::api::console::Style;
pub fn main(args: &[&str]) -> user::shell::ExitCode {
pub fn main(args: &[&str]) -> usr::shell::ExitCode {
if args.len() != 2 {
return user::shell::ExitCode::CommandError;
return usr::shell::ExitCode::CommandError;
}
let pathname = args[1];
if let Some(file) = kernel::fs::File::open(pathname) {
if let Some(file) = sys::fs::File::open(pathname) {
let contents = file.read_to_string();
print_hex(contents.as_bytes());
user::shell::ExitCode::CommandSuccessful
usr::shell::ExitCode::CommandSuccessful
} else {
print!("File not found '{}'\n", pathname);
user::shell::ExitCode::CommandError
usr::shell::ExitCode::CommandError
}
}

View File

@ -1,4 +1,4 @@
use crate::{kernel, print, user};
use crate::{sys, usr, print};
use crate::api::syscall;
use alloc::vec;
use alloc::vec::Vec;
@ -59,7 +59,7 @@ impl Message {
pub fn query(qname: &str, qtype: QueryType, qclass: QueryClass) -> Self {
let mut datagram = Vec::new();
let id = kernel::random::get_u16();
let id = sys::random::get_u16();
for b in id.to_be_bytes().iter() {
datagram.push(*b); // Transaction ID
}
@ -125,7 +125,7 @@ pub fn resolve(name: &str) -> Result<IpAddress, ResponseCode> {
let dns_port = 53;
let server = IpEndpoint::new(dns_address, dns_port);
let local_port = 49152 + kernel::random::get_u16() % 16384;
let local_port = 49152 + sys::random::get_u16() % 16384;
let client = IpEndpoint::new(IpAddress::Unspecified, local_port);
let qname = name;
@ -142,7 +142,7 @@ pub fn resolve(name: &str) -> Result<IpAddress, ResponseCode> {
enum State { Bind, Query, Response }
let mut state = State::Bind;
if let Some(ref mut iface) = *kernel::net::IFACE.lock() {
if let Some(ref mut iface) = *sys::net::IFACE.lock() {
match iface.ipv4_addr() {
None => {
return Err(ResponseCode::NetworkError);
@ -215,20 +215,20 @@ pub fn resolve(name: &str) -> Result<IpAddress, ResponseCode> {
}
}
pub fn main(args: &[&str]) -> user::shell::ExitCode {
pub fn main(args: &[&str]) -> usr::shell::ExitCode {
if args.len() != 2 {
print!("Usage: host <name>\n");
return user::shell::ExitCode::CommandError;
return usr::shell::ExitCode::CommandError;
}
let name = args[1];
match resolve(name) {
Ok(ip_addr) => {
print!("{} has address {}\n", name, ip_addr);
user::shell::ExitCode::CommandSuccessful
usr::shell::ExitCode::CommandSuccessful
}
Err(e) => {
print!("Could not resolve host: {:?}\n", e);
user::shell::ExitCode::CommandError
usr::shell::ExitCode::CommandError
}
}
}

View File

@ -1,4 +1,4 @@
use crate::{kernel, print, user};
use crate::{sys, usr, print};
use crate::api::syscall;
use alloc::borrow::ToOwned;
use alloc::string::{String, ToString};
@ -40,7 +40,7 @@ impl URL {
}
}
pub fn main(args: &[&str]) -> user::shell::ExitCode {
pub fn main(args: &[&str]) -> usr::shell::ExitCode {
// Parse command line options
let mut is_verbose = false;
let mut args: Vec<String> = args.iter().map(ToOwned::to_owned).map(ToOwned::to_owned).filter(|arg| {
@ -64,7 +64,7 @@ pub fn main(args: &[&str]) -> user::shell::ExitCode {
if args.len() != 3 {
print!("Usage: http <host> <path>\n");
return user::shell::ExitCode::CommandError;
return usr::shell::ExitCode::CommandError;
}
let url = "http://".to_owned() + &args[1] + &args[2];
@ -73,13 +73,13 @@ pub fn main(args: &[&str]) -> user::shell::ExitCode {
let address = if url.host.ends_with(char::is_numeric) {
IpAddress::from_str(&url.host).expect("invalid address format")
} else {
match user::host::resolve(&url.host) {
match usr::host::resolve(&url.host) {
Ok(ip_addr) => {
ip_addr
}
Err(e) => {
print!("Could not resolve host: {:?}\n", e);
return user::shell::ExitCode::CommandError;
return usr::shell::ExitCode::CommandError;
}
}
};
@ -94,15 +94,15 @@ pub fn main(args: &[&str]) -> user::shell::ExitCode {
enum State { Connect, Request, Response }
let mut state = State::Connect;
if let Some(ref mut iface) = *kernel::net::IFACE.lock() {
if let Some(ref mut iface) = *sys::net::IFACE.lock() {
match iface.ipv4_addr() {
None => {
print!("Error: Interface not ready\n");
return user::shell::ExitCode::CommandError;
return usr::shell::ExitCode::CommandError;
}
Some(ip_addr) if ip_addr.is_unspecified() => {
print!("Error: Interface not ready\n");
return user::shell::ExitCode::CommandError;
return usr::shell::ExitCode::CommandError;
}
_ => {}
}
@ -113,11 +113,11 @@ pub fn main(args: &[&str]) -> user::shell::ExitCode {
loop {
if syscall::realtime() - started > timeout {
print!("Timeout reached\n");
return user::shell::ExitCode::CommandError;
return usr::shell::ExitCode::CommandError;
}
if kernel::console::abort() {
if sys::console::abort() {
print!("\n");
return user::shell::ExitCode::CommandError;
return usr::shell::ExitCode::CommandError;
}
let timestamp = Instant::from_millis((syscall::realtime() * 1000.0) as i64);
match iface.poll(&mut sockets, timestamp) {
@ -133,13 +133,13 @@ pub fn main(args: &[&str]) -> user::shell::ExitCode {
state = match state {
State::Connect if !socket.is_active() => {
let local_port = 49152 + kernel::random::get_u16() % 16384;
let local_port = 49152 + sys::random::get_u16() % 16384;
if is_verbose {
print!("* Connecting to {}:{}\n", address, url.port);
}
if socket.connect((address, url.port), local_port).is_err() {
print!("Could not connect to {}:{}\n", address, url.port);
return user::shell::ExitCode::CommandError;
return usr::shell::ExitCode::CommandError;
}
State::Request
}
@ -193,8 +193,8 @@ pub fn main(args: &[&str]) -> user::shell::ExitCode {
syscall::sleep(wait_duration.as_secs_f64());
}
}
user::shell::ExitCode::CommandSuccessful
usr::shell::ExitCode::CommandSuccessful
} else {
user::shell::ExitCode::CommandError
usr::shell::ExitCode::CommandError
}
}

View File

@ -1,6 +1,6 @@
use crate::{kernel, print, user};
use crate::{sys, usr, print};
use crate::api::syscall;
use crate::kernel::console::Style;
use crate::api::console::Style;
use alloc::collections::vec_deque::VecDeque;
use alloc::format;
use alloc::string::String;
@ -14,18 +14,18 @@ use smoltcp::socket::SocketSet;
use smoltcp::phy::Device;
use time::OffsetDateTime;
pub fn main(_args: &[&str]) -> user::shell::ExitCode {
pub fn main(_args: &[&str]) -> usr::shell::ExitCode {
let port = 80;
if let Some(ref mut iface) = *kernel::net::IFACE.lock() {
if let Some(ref mut iface) = *sys::net::IFACE.lock() {
match iface.ipv4_addr() {
None => {
print!("Error: Interface not ready\n");
return user::shell::ExitCode::CommandError;
return usr::shell::ExitCode::CommandError;
}
Some(ip_addr) if ip_addr.is_unspecified() => {
print!("Error: Interface not ready\n");
return user::shell::ExitCode::CommandError;
return usr::shell::ExitCode::CommandError;
}
_ => {}
}
@ -44,9 +44,9 @@ pub fn main(_args: &[&str]) -> user::shell::ExitCode {
let mut send_queue: VecDeque<Vec<u8>> = VecDeque::new();
let mut tcp_active = false;
loop {
if kernel::console::abort() {
if sys::console::abort() {
print!("\n");
return user::shell::ExitCode::CommandSuccessful;
return usr::shell::ExitCode::CommandSuccessful;
}
let timestamp = Instant::from_millis((syscall::realtime() * 1000.0) as i64);
@ -111,12 +111,12 @@ pub fn main(_args: &[&str]) -> user::shell::ExitCode {
res.push_str(&format!("Location: {}\r\n", path.trim_end_matches('/')));
body = format!("<h1>Moved Permanently</h1>\r\n");
mime = "text/html";
} else if let Some(file) = kernel::fs::File::open(path) {
} else if let Some(file) = sys::fs::File::open(path) {
code = 200;
res.push_str("HTTP/1.0 200 OK\r\n");
body = file.read_to_string().replace("\n", "\r\n");
mime = "text/plain";
} else if let Some(dir) = kernel::fs::Dir::open(path) {
} else if let Some(dir) = sys::fs::Dir::open(path) {
code = 200;
res.push_str("HTTP/1.0 200 OK\r\n");
body = format!("<h1>Index of {}</h1>\r\n", path);
@ -138,10 +138,10 @@ pub fn main(_args: &[&str]) -> user::shell::ExitCode {
"PUT" => {
if path.ends_with("/") { // Write directory
let path = path.trim_end_matches('/');
if kernel::fs::Dir::open(path).is_some() {
if sys::fs::Dir::open(path).is_some() {
code = 403;
res.push_str("HTTP/1.0 403 Forbidden\r\n");
} else if kernel::fs::Dir::create(path).is_none() {
} else if sys::fs::Dir::create(path).is_none() {
code = 500;
res.push_str("HTTP/1.0 500 Internal Server Error\r\n");
} else {
@ -149,9 +149,9 @@ pub fn main(_args: &[&str]) -> user::shell::ExitCode {
res.push_str("HTTP/1.0 200 OK\r\n");
}
} else { // Write file
let maybe_file = match kernel::fs::File::open(path) {
let maybe_file = match sys::fs::File::open(path) {
Some(file) => Some(file),
None => kernel::fs::File::create(path),
None => sys::fs::File::create(path),
};
match maybe_file {
Some(mut file) => {
@ -173,8 +173,8 @@ pub fn main(_args: &[&str]) -> user::shell::ExitCode {
mime = "text/plain";
},
"DELETE" => {
if kernel::fs::File::open(path).is_some() {
if kernel::fs::File::delete(path).is_ok() {
if sys::fs::File::open(path).is_some() {
if sys::fs::File::delete(path).is_ok() {
code = 200;
res.push_str("HTTP/1.0 200 OK\r\n");
} else {
@ -235,7 +235,7 @@ pub fn main(_args: &[&str]) -> user::shell::ExitCode {
}
} else {
print!("Error: Could not find network interface\n");
user::shell::ExitCode::CommandError
usr::shell::ExitCode::CommandError
}
}

View File

@ -1,27 +1,27 @@
use crate::{kernel, print, user};
use crate::kernel::console::Style;
use crate::{sys, usr, print};
use crate::api::console::Style;
use alloc::string::String;
pub fn main(_args: &[&str]) -> user::shell::ExitCode {
pub fn main(_args: &[&str]) -> usr::shell::ExitCode {
let csi_color = Style::color("Yellow");
let csi_reset = Style::reset();
print!("{}Welcome to MOROS v{} installation program!{}\n", csi_color, env!("CARGO_PKG_VERSION"), csi_reset);
print!("\n");
print!("Proceed? [y/N] ");
if kernel::console::get_line().trim() == "y" {
if sys::console::get_line().trim() == "y" {
print!("\n");
if !kernel::fs::is_mounted() {
if !sys::fs::is_mounted() {
print!("{}Listing disks ...{}\n", csi_color, csi_reset);
user::disk::main(&["disk", "list"]);
usr::disk::main(&["disk", "list"]);
print!("\n");
print!("{}Formatting disk ...{}\n", csi_color, csi_reset);
print!("Enter path of disk to format: ");
let pathname = kernel::console::get_line();
let res = user::disk::main(&["disk", "format", pathname.trim_end()]);
if res == user::shell::ExitCode::CommandError {
let pathname = sys::console::get_line();
let res = usr::disk::main(&["disk", "format", pathname.trim_end()]);
if res == usr::shell::ExitCode::CommandError {
return res;
}
print!("\n");
@ -49,11 +49,11 @@ pub fn main(_args: &[&str]) -> user::shell::ExitCode {
copy_file("/ini/fonts/zap-light-8x16.psf", include_bytes!("../../dsk/ini/fonts/zap-light-8x16.psf"));
copy_file("/ini/fonts/zap-vga-8x16.psf", include_bytes!("../../dsk/ini/fonts/zap-vga-8x16.psf"));
if kernel::process::user().is_none() {
if sys::process::user().is_none() {
print!("\n");
print!("{}Creating user...{}\n", csi_color, csi_reset);
let res = user::user::main(&["user", "create"]);
if res == user::shell::ExitCode::CommandError {
let res = usr::user::main(&["user", "create"]);
if res == usr::shell::ExitCode::CommandError {
return res;
}
}
@ -64,20 +64,20 @@ pub fn main(_args: &[&str]) -> user::shell::ExitCode {
print!("Exit console or reboot to apply changes\n");
}
user::shell::ExitCode::CommandSuccessful
usr::shell::ExitCode::CommandSuccessful
}
fn create_dir(pathname: &str) {
if kernel::fs::Dir::create(pathname).is_some() {
if sys::fs::Dir::create(pathname).is_some() {
print!("Created '{}'\n", pathname);
}
}
fn copy_file(pathname: &str, buf: &[u8]) {
if kernel::fs::File::open(pathname).is_some() {
if sys::fs::File::open(pathname).is_some() {
return;
}
if let Some(mut file) = kernel::fs::File::create(pathname) {
if let Some(mut file) = sys::fs::File::create(pathname) {
if pathname.ends_with(".txt") {
if let Ok(text) = String::from_utf8(buf.to_vec()) {
let text = text.replace("{x.x.x}", env!("CARGO_PKG_VERSION"));

View File

@ -1,9 +1,9 @@
use crate::{kernel, print, user};
use crate::{sys, usr, print};
use core::str::FromStr;
use smoltcp::wire::IpCidr;
pub fn main(args: &[&str]) -> user::shell::ExitCode {
if let Some(ref mut iface) = *kernel::net::IFACE.lock() {
pub fn main(args: &[&str]) -> usr::shell::ExitCode {
if let Some(ref mut iface) = *sys::net::IFACE.lock() {
if args.len() == 1 {
print!("Link: {}\n", iface.ethernet_addr());
for ip_cidr in iface.ip_addrs() {
@ -37,13 +37,13 @@ pub fn main(args: &[&str]) -> user::shell::ExitCode {
}
}
}
user::shell::ExitCode::CommandSuccessful
usr::shell::ExitCode::CommandSuccessful
} else {
error("could not find network interface")
}
}
fn error(message: &str) -> user::shell::ExitCode {
fn error(message: &str) -> usr::shell::ExitCode {
print!("Error: {}\n", message);
user::shell::ExitCode::CommandError
usr::shell::ExitCode::CommandError
}

View File

@ -1,8 +1,8 @@
use crate::{kernel, print, user};
use crate::{sys, usr, print};
use alloc::vec::Vec;
pub fn main(args: &[&str]) -> user::shell::ExitCode {
let current_dir = kernel::process::dir();
pub fn main(args: &[&str]) -> usr::shell::ExitCode {
let current_dir = sys::process::dir();
let mut pathname = if args.len() == 2 && args[1].len() > 0 {
args[1]
} else {
@ -15,7 +15,7 @@ pub fn main(args: &[&str]) -> user::shell::ExitCode {
pathname = pathname.trim_end_matches('/');
}
if let Some(dir) = kernel::fs::Dir::open(pathname) {
if let Some(dir) = sys::fs::Dir::open(pathname) {
let mut files: Vec<_> = dir.read().collect();
files.sort_by_key(|f| f.name());
@ -23,9 +23,9 @@ pub fn main(args: &[&str]) -> user::shell::ExitCode {
for file in files {
print!("{}\n", file.name());
}
user::shell::ExitCode::CommandSuccessful
usr::shell::ExitCode::CommandSuccessful
} else {
print!("Dir not found '{}'\n", pathname);
user::shell::ExitCode::CommandError
usr::shell::ExitCode::CommandError
}
}

13
src/usr/mem.rs Normal file
View File

@ -0,0 +1,13 @@
use crate::{sys, usr, print};
use crate::api::console::Style;
use alloc::string::ToString;
pub fn main(_args: &[&str]) -> usr::shell::ExitCode {
let width = sys::allocator::size().to_string().len();
let color = Style::color("LightCyan");
let reset = Style::reset();
print!("{}Size:{} {:width$}\n", color, reset, sys::allocator::size(), width = width);
print!("{}Used:{} {:width$}\n", color, reset, sys::allocator::used(), width = width);
print!("{}Free:{} {:width$}\n", color, reset, sys::allocator::free(), width = width);
usr::shell::ExitCode::CommandSuccessful
}

13
src/usr/move.rs Normal file
View File

@ -0,0 +1,13 @@
use crate::usr;
pub fn main(args: &[&str]) -> usr::shell::ExitCode {
if args.len() != 3 {
return usr::shell::ExitCode::CommandError;
}
// TODO: Avoid doing copy+delete
match usr::copy::main(args) {
usr::shell::ExitCode::CommandSuccessful => usr::delete::main(&args[0..2]),
_ => usr::shell::ExitCode::CommandError,
}
}

View File

@ -1,21 +1,21 @@
use crate::{kernel, print, user};
use crate::{sys, usr, print};
use crate::api::syscall;
//use smoltcp::wire::Ipv4Address;
use smoltcp::socket::{SocketSet, TcpSocket, TcpSocketBuffer};
use smoltcp::time::Instant;
pub fn main(args: &[&str]) -> user::shell::ExitCode {
pub fn main(args: &[&str]) -> usr::shell::ExitCode {
if args.len() == 1 {
print!("Usage: net <command>\n");
return user::shell::ExitCode::CommandError;
return usr::shell::ExitCode::CommandError;
}
if let Some(ref mut iface) = *kernel::net::IFACE.lock() {
if let Some(ref mut iface) = *sys::net::IFACE.lock() {
match args[1] {
"config" => {
if args.len() < 4 {
print!("Usage: net config <key> <value>\n");
return user::shell::ExitCode::CommandError;
return usr::shell::ExitCode::CommandError;
}
match args[2] {
"debug" => {
@ -24,13 +24,13 @@ pub fn main(args: &[&str]) -> user::shell::ExitCode {
"0" | "off" | "disable" => false,
_ => {
print!("Invalid config value\n");
return user::shell::ExitCode::CommandError;
return usr::shell::ExitCode::CommandError;
}
}
}
_ => {
print!("Invalid config key\n");
return user::shell::ExitCode::CommandError;
return usr::shell::ExitCode::CommandError;
}
}
}
@ -49,9 +49,9 @@ pub fn main(args: &[&str]) -> user::shell::ExitCode {
let _server_handle = sockets.add(server_socket);
loop {
if kernel::console::abort() {
if sys::console::abort() {
print!("\n");
return user::shell::ExitCode::CommandSuccessful;
return usr::shell::ExitCode::CommandSuccessful;
}
let now = syscall::uptime();
@ -74,9 +74,9 @@ pub fn main(args: &[&str]) -> user::shell::ExitCode {
}
_ => {
print!("Invalid command\n");
return user::shell::ExitCode::CommandError;
return usr::shell::ExitCode::CommandError;
}
}
}
user::shell::ExitCode::CommandSuccessful
usr::shell::ExitCode::CommandSuccessful
}

View File

@ -1,6 +1,6 @@
use crate::{print, user};
use crate::{usr, print};
pub fn main(args: &[&str]) -> user::shell::ExitCode {
pub fn main(args: &[&str]) -> usr::shell::ExitCode {
let n = args.len();
for i in 1..n {
print!("{}", args[i]);
@ -9,5 +9,5 @@ pub fn main(args: &[&str]) -> user::shell::ExitCode {
}
}
print!("\n");
user::shell::ExitCode::CommandSuccessful
usr::shell::ExitCode::CommandSuccessful
}

View File

@ -1,12 +1,12 @@
use crate::{kernel, print, user};
use crate::{sys, usr, print};
use crate::api::syscall;
use crate::kernel::cmos::CMOS;
use crate::sys::cmos::CMOS;
use alloc::borrow::ToOwned;
use alloc::vec::Vec;
pub fn main(args: &[&str]) -> user::shell::ExitCode {
pub fn main(args: &[&str]) -> usr::shell::ExitCode {
if args.len() != 2 {
return user::shell::ExitCode::CommandError;
return usr::shell::ExitCode::CommandError;
}
let pathname = args[1];
@ -19,26 +19,26 @@ pub fn main(args: &[&str]) -> user::shell::ExitCode {
rtc.year, rtc.month, rtc.day,
rtc.hour, rtc.minute, rtc.second
);
user::shell::ExitCode::CommandSuccessful
usr::shell::ExitCode::CommandSuccessful
},
"/dev/clk/realtime" => {
print!("{:.6}\n", syscall::realtime());
user::shell::ExitCode::CommandSuccessful
usr::shell::ExitCode::CommandSuccessful
},
"/dev/clk/uptime" => {
print!("{:.6}\n", syscall::uptime());
user::shell::ExitCode::CommandSuccessful
usr::shell::ExitCode::CommandSuccessful
},
"/dev/random" => {
loop {
// Generate ASCII graphic chars
let i = (kernel::random::get_u32() % (0x72 - 0x20)) + 0x20;
let i = (sys::random::get_u32() % (0x72 - 0x20)) + 0x20;
if let Some(c) = core::char::from_u32(i) {
print!("{}", c);
}
if kernel::console::abort() {
if sys::console::abort() {
print!("\n");
return user::shell::ExitCode::CommandSuccessful;
return usr::shell::ExitCode::CommandSuccessful;
}
}
},
@ -52,37 +52,37 @@ pub fn main(args: &[&str]) -> user::shell::ExitCode {
let parts: Vec<_> = pathname.split('/').collect();
if parts.len() < 4 {
print!("Usage: read /net/http/<host>/<path>\n");
user::shell::ExitCode::CommandError
usr::shell::ExitCode::CommandError
} else {
match parts[2] {
"tcp" => {
let host = parts[3];
user::tcp::main(&["tcp", host])
usr::tcp::main(&["tcp", host])
}
"daytime" => {
let host = parts[3];
let port = "13";
user::tcp::main(&["tcp", host, port])
usr::tcp::main(&["tcp", host, port])
}
"http" => {
let host = parts[3];
let path = "/".to_owned() + &parts[4..].join("/");
user::http::main(&["http", host, &path])
usr::http::main(&["http", host, &path])
}
_ => {
print!("Error: unknown protocol '{}'\n", parts[2]);
user::shell::ExitCode::CommandError
usr::shell::ExitCode::CommandError
}
}
}
} else if pathname.ends_with('/') {
user::list::main(args)
} else if let Some(file) = kernel::fs::File::open(pathname) {
usr::list::main(args)
} else if let Some(file) = sys::fs::File::open(pathname) {
print!("{}", file.read_to_string());
user::shell::ExitCode::CommandSuccessful
usr::shell::ExitCode::CommandSuccessful
} else {
print!("File not found '{}'\n", pathname);
user::shell::ExitCode::CommandError
usr::shell::ExitCode::CommandError
}
}
}

View File

@ -1,17 +1,17 @@
use crate::{kernel, print, user};
use crate::{sys, usr, print};
use alloc::string::ToString;
pub fn main(_args: &[&str]) -> user::shell::ExitCode {
if let Some(ref mut iface) = *kernel::net::IFACE.lock() {
pub fn main(_args: &[&str]) -> usr::shell::ExitCode {
if let Some(ref mut iface) = *sys::net::IFACE.lock() {
print!("{:<19} {}\n", "Destination", "Gateway");
iface.routes_mut().update(|storage| {
for (cidr, route) in storage.iter() {
print!("{:<19} {}\n", cidr.to_string(), route.via_router);
}
});
user::shell::ExitCode::CommandSuccessful
usr::shell::ExitCode::CommandSuccessful
} else {
print!("Could not find network interface\n");
user::shell::ExitCode::CommandError
usr::shell::ExitCode::CommandError
}
}

View File

@ -1,5 +1,5 @@
use crate::{print, user, kernel};
use crate::kernel::console::Style;
use crate::{sys, usr, print};
use crate::api::console::Style;
use alloc::format;
use alloc::vec;
use alloc::vec::Vec;
@ -55,20 +55,20 @@ impl Shell {
}
}
pub fn run(&mut self) -> user::shell::ExitCode {
pub fn run(&mut self) -> usr::shell::ExitCode {
self.load_history();
print!("\n");
self.print_prompt();
loop {
let (x, y) = kernel::vga::cursor_position();
let c = kernel::console::get_char();
let (x, y) = sys::vga::cursor_position();
let c = sys::console::get_char();
match c {
'\0' => {
continue;
}
'\x04' => { // Ctrl D
if self.cmd.is_empty() {
kernel::vga::clear_screen();
sys::vga::clear_screen();
return ExitCode::CommandSuccessful;
}
},
@ -98,14 +98,14 @@ impl Shell {
self.save_history();
},
ExitCode::ShellExit => {
kernel::vga::clear_screen();
sys::vga::clear_screen();
return ExitCode::CommandSuccessful
},
_ => {
self.errored = true;
},
}
kernel::console::drain();
sys::console::drain();
self.cmd.clear();
} else {
self.errored = false;
@ -125,8 +125,8 @@ impl Shell {
}
let cmd = &self.history[self.history_index];
let n = self.prompt.len();
kernel::console::clear_row_after(n + cmd.len());
kernel::vga::set_writer_position(n, y);
sys::console::clear_row_after(n + cmd.len());
sys::vga::set_writer_position(n, y);
print!("{}", cmd);
}
},
@ -140,8 +140,8 @@ impl Shell {
&self.cmd
};
let n = self.prompt.len();
kernel::console::clear_row_after(n + cmd.len());
kernel::vga::set_writer_position(n, y);
sys::console::clear_row_after(n + cmd.len());
sys::vga::set_writer_position(n, y);
print!("{}", cmd);
}
},
@ -149,23 +149,23 @@ impl Shell {
self.update_history();
self.update_autocomplete();
if x > self.prompt.len() {
kernel::vga::set_cursor_position(x - 1, y);
kernel::vga::set_writer_position(x - 1, y);
sys::vga::set_cursor_position(x - 1, y);
sys::vga::set_writer_position(x - 1, y);
}
},
'→' => { // Arrow right
self.update_history();
self.update_autocomplete();
if x < self.prompt.len() + self.cmd.len() {
kernel::vga::set_cursor_position(x + 1, y);
kernel::vga::set_writer_position(x + 1, y);
sys::vga::set_cursor_position(x + 1, y);
sys::vga::set_writer_position(x + 1, y);
}
},
'\x08' => { // Backspace
self.update_history();
self.update_autocomplete();
if self.cmd.len() > 0 {
if kernel::console::has_cursor() {
if sys::console::has_cursor() {
if x > self.prompt.len() {
let cmd = self.cmd.clone();
let (before_cursor, mut after_cursor) = cmd.split_at(x - 1 - self.prompt.len());
@ -176,8 +176,8 @@ impl Shell {
self.cmd.push_str(before_cursor);
self.cmd.push_str(after_cursor);
print!("{}{} ", c, after_cursor);
kernel::vga::set_cursor_position(x - 1, y);
kernel::vga::set_writer_position(x - 1, y);
sys::vga::set_cursor_position(x - 1, y);
sys::vga::set_writer_position(x - 1, y);
}
} else {
self.cmd.pop();
@ -189,7 +189,7 @@ impl Shell {
self.update_history();
self.update_autocomplete();
if self.cmd.len() > 0 {
if kernel::console::has_cursor() {
if sys::console::has_cursor() {
let cmd = self.cmd.clone();
let (before_cursor, mut after_cursor) = cmd.split_at(x - self.prompt.len());
if after_cursor.len() > 0 {
@ -199,16 +199,16 @@ impl Shell {
self.cmd.push_str(before_cursor);
self.cmd.push_str(after_cursor);
print!("{} ", after_cursor);
kernel::vga::set_cursor_position(x, y);
kernel::vga::set_writer_position(x, y);
sys::vga::set_cursor_position(x, y);
sys::vga::set_writer_position(x, y);
}
}
},
c => {
self.update_history();
self.update_autocomplete();
if c.is_ascii() && kernel::vga::is_printable(c as u8) {
if kernel::console::has_cursor() {
if c.is_ascii() && sys::vga::is_printable(c as u8) {
if sys::console::has_cursor() {
let cmd = self.cmd.clone();
let (before_cursor, after_cursor) = cmd.split_at(x - self.prompt.len());
self.cmd.clear();
@ -216,8 +216,8 @@ impl Shell {
self.cmd.push(c);
self.cmd.push_str(after_cursor);
print!("{}{}", c, after_cursor);
kernel::vga::set_cursor_position(x + 1, y);
kernel::vga::set_writer_position(x + 1, y);
sys::vga::set_cursor_position(x + 1, y);
sys::vga::set_writer_position(x + 1, y);
} else {
self.cmd.push(c);
print!("{}", c);
@ -240,10 +240,10 @@ impl Shell {
}
pub fn load_history(&mut self) {
if let Some(home) = kernel::process::env("HOME") {
if let Some(home) = sys::process::env("HOME") {
let pathname = format!("{}/.shell_history", home);
if let Some(file) = kernel::fs::File::open(&pathname) {
if let Some(file) = sys::fs::File::open(&pathname) {
let contents = file.read_to_string();
for line in contents.split('\n') {
let cmd = line.trim();
@ -257,7 +257,7 @@ impl Shell {
}
pub fn save_history(&mut self) {
if let Some(home) = kernel::process::env("HOME") {
if let Some(home) = sys::process::env("HOME") {
let pathname = format!("{}/.shell_history", home);
let mut contents = String::new();
@ -265,9 +265,9 @@ impl Shell {
contents.push_str(&format!("{}\n", cmd));
}
let mut file = match kernel::fs::File::open(&pathname) {
let mut file = match sys::fs::File::open(&pathname) {
Some(file) => file,
None => kernel::fs::File::create(&pathname).unwrap(),
None => sys::fs::File::create(&pathname).unwrap(),
};
file.write(&contents.as_bytes()).unwrap();
@ -286,20 +286,20 @@ impl Shell {
}
}
} else { // Autocomplete path
let pathname = kernel::fs::realpath(args[i]);
let dirname = kernel::fs::dirname(&pathname);
let filename = kernel::fs::filename(&pathname);
let pathname = sys::fs::realpath(args[i]);
let dirname = sys::fs::dirname(&pathname);
let filename = sys::fs::filename(&pathname);
self.autocomplete = vec![args[i].into()];
let sep = if dirname.ends_with("/") { "" } else { "/" };
if pathname.starts_with("/dev") {
for dev in &AUTOCOMPLETE_DEVICES {
let d = kernel::fs::dirname(dev);
let f = kernel::fs::filename(dev);
let d = sys::fs::dirname(dev);
let f = sys::fs::filename(dev);
if d == dirname && f.starts_with(filename) {
self.autocomplete.push(format!("{}{}{}", d, sep, f));
}
}
} else if let Some(dir) = kernel::fs::Dir::open(dirname) {
} else if let Some(dir) = sys::fs::Dir::open(dirname) {
for entry in dir.read() {
let name = entry.name();
if name.starts_with(filename) {
@ -316,9 +316,9 @@ impl Shell {
let cmd = args.join(" ");
let n = self.prompt.len();
let (_, y) = kernel::console::cursor_position();
kernel::console::clear_row_after(n + cmd.len());
kernel::console::set_writer_position(n, y);
let (_, y) = sys::console::cursor_position();
sys::console::clear_row_after(n + cmd.len());
sys::console::set_writer_position(n, y);
print!("{}", cmd);
}
@ -383,53 +383,53 @@ impl Shell {
"" => ExitCode::CommandSuccessful,
"a" | "alias" => ExitCode::CommandUnknown,
"b" => ExitCode::CommandUnknown,
"c" | "copy" => user::copy::main(&args),
"d" | "del" | "delete" => user::delete::main(&args),
"e" | "edit" => user::editor::main(&args),
"c" | "copy" => usr::copy::main(&args),
"d" | "del" | "delete" => usr::delete::main(&args),
"e" | "edit" => usr::editor::main(&args),
"f" | "find" => ExitCode::CommandUnknown,
"g" | "go" | "goto" => self.change_dir(&args),
"h" | "help" => user::help::main(&args),
"h" | "help" => usr::help::main(&args),
"i" => ExitCode::CommandUnknown,
"j" | "jump" => ExitCode::CommandUnknown,
"k" | "kill" => ExitCode::CommandUnknown,
"l" | "list" => user::list::main(&args),
"m" | "move" => user::r#move::main(&args),
"l" | "list" => usr::list::main(&args),
"m" | "move" => usr::r#move::main(&args),
"n" => ExitCode::CommandUnknown,
"o" => ExitCode::CommandUnknown,
"p" | "print" => user::print::main(&args),
"p" | "print" => usr::print::main(&args),
"q" | "quit" | "exit" => ExitCode::ShellExit,
"r" | "read" => user::read::main(&args),
"r" | "read" => usr::read::main(&args),
"s" => ExitCode::CommandUnknown,
"t" => ExitCode::CommandUnknown,
"u" => ExitCode::CommandUnknown,
"v" => ExitCode::CommandUnknown,
"w" | "write" => user::write::main(&args),
"w" | "write" => usr::write::main(&args),
"x" => ExitCode::CommandUnknown,
"y" => ExitCode::CommandUnknown,
"z" => ExitCode::CommandUnknown,
"vga" => user::vga::main(&args),
"shell" => user::shell::main(&args),
"sleep" => user::sleep::main(&args),
"clear" => user::clear::main(&args),
"base64" => user::base64::main(&args),
"date" => user::date::main(&args),
"env" => user::env::main(&args),
"halt" => user::halt::main(&args),
"hex" => user::hex::main(&args),
"net" => user::net::main(&args),
"route" => user::route::main(&args),
"dhcp" => user::dhcp::main(&args),
"http" => user::http::main(&args),
"httpd" => user::httpd::main(&args),
"tcp" => user::tcp::main(&args),
"host" => user::host::main(&args),
"install" => user::install::main(&args),
"ip" => user::ip::main(&args),
"geotime" => user::geotime::main(&args),
"colors" => user::colors::main(&args),
"disk" => user::disk::main(&args),
"user" => user::user::main(&args),
"mem" | "memory" => user::mem::main(&args),
"vga" => usr::vga::main(&args),
"shell" => usr::shell::main(&args),
"sleep" => usr::sleep::main(&args),
"clear" => usr::clear::main(&args),
"base64" => usr::base64::main(&args),
"date" => usr::date::main(&args),
"env" => usr::env::main(&args),
"halt" => usr::halt::main(&args),
"hex" => usr::hex::main(&args),
"net" => usr::net::main(&args),
"route" => usr::route::main(&args),
"dhcp" => usr::dhcp::main(&args),
"http" => usr::http::main(&args),
"httpd" => usr::httpd::main(&args),
"tcp" => usr::tcp::main(&args),
"host" => usr::host::main(&args),
"install" => usr::install::main(&args),
"ip" => usr::ip::main(&args),
"geotime" => usr::geotime::main(&args),
"colors" => usr::colors::main(&args),
"disk" => usr::disk::main(&args),
"user" => usr::user::main(&args),
"mem" | "memory" => usr::mem::main(&args),
_ => ExitCode::CommandUnknown,
}
}
@ -444,13 +444,13 @@ impl Shell {
fn change_dir(&self, args: &[&str]) -> ExitCode {
match args.len() {
1 => {
print!("{}\n", kernel::process::dir());
print!("{}\n", sys::process::dir());
ExitCode::CommandSuccessful
},
2 => {
let pathname = kernel::fs::realpath(args[1]);
if kernel::fs::Dir::open(&pathname).is_some() {
kernel::process::set_dir(&pathname);
let pathname = sys::fs::realpath(args[1]);
if sys::fs::Dir::open(&pathname).is_some() {
sys::process::set_dir(&pathname);
ExitCode::CommandSuccessful
} else {
print!("File not found '{}'\n", pathname);
@ -472,7 +472,7 @@ pub fn main(args: &[&str]) -> ExitCode {
},
2 => {
let pathname = args[1];
if let Some(file) = kernel::fs::File::open(pathname) {
if let Some(file) = sys::fs::File::open(pathname) {
for line in file.read_to_string().split("\n") {
if line.len() > 0 {
shell.exec(line);

12
src/usr/sleep.rs Normal file
View File

@ -0,0 +1,12 @@
use crate::usr;
use crate::api::syscall;
pub fn main(args: &[&str]) -> usr::shell::ExitCode {
if args.len() == 2 {
if let Ok(duration) = args[1].parse::<f64>() {
syscall::sleep(duration);
return usr::shell::ExitCode::CommandSuccessful;
}
}
usr::shell::ExitCode::CommandError
}

View File

@ -1,4 +1,4 @@
use crate::{kernel, print, user};
use crate::{sys, usr, print};
use crate::api::syscall;
use alloc::borrow::ToOwned;
use alloc::string::{String, ToString};
@ -10,7 +10,7 @@ use smoltcp::socket::{SocketSet, TcpSocket, TcpSocketBuffer};
use smoltcp::time::Instant;
use smoltcp::wire::IpAddress;
pub fn main(args: &[&str]) -> user::shell::ExitCode {
pub fn main(args: &[&str]) -> usr::shell::ExitCode {
let mut args: Vec<String> = args.iter().map(ToOwned::to_owned).map(ToOwned::to_owned).collect();
// Split <host> and <port>
@ -25,7 +25,7 @@ pub fn main(args: &[&str]) -> user::shell::ExitCode {
if args.len() != 3 {
print!("Usage: tcp <host> <port>\n");
return user::shell::ExitCode::CommandError;
return usr::shell::ExitCode::CommandError;
}
let host = &args[1];
@ -35,13 +35,13 @@ pub fn main(args: &[&str]) -> user::shell::ExitCode {
let address = if host.ends_with(char::is_numeric) {
IpAddress::from_str(&host).expect("invalid address format")
} else {
match user::host::resolve(&host) {
match usr::host::resolve(&host) {
Ok(ip_addr) => {
ip_addr
}
Err(e) => {
print!("Could not resolve host: {:?}\n", e);
return user::shell::ExitCode::CommandError;
return usr::shell::ExitCode::CommandError;
}
}
};
@ -56,15 +56,15 @@ pub fn main(args: &[&str]) -> user::shell::ExitCode {
enum State { Connect, Request, Response }
let mut state = State::Connect;
if let Some(ref mut iface) = *kernel::net::IFACE.lock() {
if let Some(ref mut iface) = *sys::net::IFACE.lock() {
match iface.ipv4_addr() {
None => {
print!("Interface not ready\n");
return user::shell::ExitCode::CommandError;
return usr::shell::ExitCode::CommandError;
}
Some(ip_addr) if ip_addr.is_unspecified() => {
print!("Interface not ready\n");
return user::shell::ExitCode::CommandError;
return usr::shell::ExitCode::CommandError;
}
_ => {}
}
@ -74,11 +74,11 @@ pub fn main(args: &[&str]) -> user::shell::ExitCode {
loop {
if syscall::realtime() - started > timeout {
print!("Timeout reached\n");
return user::shell::ExitCode::CommandError;
return usr::shell::ExitCode::CommandError;
}
if kernel::console::abort() {
if sys::console::abort() {
print!("\n");
return user::shell::ExitCode::CommandError;
return usr::shell::ExitCode::CommandError;
}
let timestamp = Instant::from_millis((syscall::realtime() * 1000.0) as i64);
match iface.poll(&mut sockets, timestamp) {
@ -94,11 +94,11 @@ pub fn main(args: &[&str]) -> user::shell::ExitCode {
state = match state {
State::Connect if !socket.is_active() => {
let local_port = 49152 + kernel::random::get_u16() % 16384;
let local_port = 49152 + sys::random::get_u16() % 16384;
print!("Connecting to {}:{}\n", address, port);
if socket.connect((address, port), local_port).is_err() {
print!("Could not connect to {}:{}\n", address, port);
return user::shell::ExitCode::CommandError;
return usr::shell::ExitCode::CommandError;
}
State::Request
}
@ -130,8 +130,8 @@ pub fn main(args: &[&str]) -> user::shell::ExitCode {
syscall::sleep(wait_duration.as_secs_f64());
}
}
user::shell::ExitCode::CommandSuccessful
usr::shell::ExitCode::CommandSuccessful
} else {
user::shell::ExitCode::CommandError
usr::shell::ExitCode::CommandError
}
}

7
src/usr/uptime.rs Normal file
View File

@ -0,0 +1,7 @@
use crate::{usr, print};
use crate::api::syscall;
pub fn main(_args: &[&str]) -> usr::shell::ExitCode {
print!("{:.6}\n", syscall::uptime());
usr::shell::ExitCode::CommandSuccessful
}

View File

@ -1,4 +1,4 @@
use crate::{kernel, print, user};
use crate::{sys, usr, print};
use crate::api::syscall;
use alloc::collections::btree_map::BTreeMap;
use alloc::format;
@ -12,14 +12,14 @@ use sha2::Sha256;
const PASSWORDS: &'static str = "/ini/passwords.csv";
const COMMANDS: [&'static str; 2] = ["create", "login"];
pub fn main(args: &[&str]) -> user::shell::ExitCode {
pub fn main(args: &[&str]) -> usr::shell::ExitCode {
if args.len() == 1 || !COMMANDS.contains(&args[1]) {
return usage();
}
let username: String = if args.len() == 2 {
print!("Username: ");
kernel::console::get_line().trim_end().into()
sys::console::get_line().trim_end().into()
} else {
args[2].into()
};
@ -31,13 +31,13 @@ pub fn main(args: &[&str]) -> user::shell::ExitCode {
}
}
fn usage() -> user::shell::ExitCode {
fn usage() -> usr::shell::ExitCode {
print!("Usage: user [{}] <username>\n", COMMANDS.join("|"));
return user::shell::ExitCode::CommandError;
return usr::shell::ExitCode::CommandError;
}
// TODO: Add max number of attempts
pub fn login(username: &str) -> user::shell::ExitCode {
pub fn login(username: &str) -> usr::shell::ExitCode {
if username.is_empty() {
print!("\n");
syscall::sleep(1.0);
@ -47,9 +47,9 @@ pub fn login(username: &str) -> user::shell::ExitCode {
match hashed_password(&username) {
Some(hash) => {
print!("Password: ");
kernel::console::disable_echo();
let mut password = kernel::console::get_line();
kernel::console::enable_echo();
sys::console::disable_echo();
let mut password = sys::console::get_line();
sys::console::enable_echo();
print!("\n");
password.pop();
if !check(&password, &hash) {
@ -66,56 +66,56 @@ pub fn login(username: &str) -> user::shell::ExitCode {
}
let home = format!("/usr/{}", username);
kernel::process::set_user(&username);
kernel::process::set_env("HOME", &home);
kernel::process::set_dir(&home);
sys::process::set_user(&username);
sys::process::set_env("HOME", &home);
sys::process::set_dir(&home);
// TODO: load shell
user::shell::ExitCode::CommandSuccessful
usr::shell::ExitCode::CommandSuccessful
}
pub fn create(username: &str) -> user::shell::ExitCode {
pub fn create(username: &str) -> usr::shell::ExitCode {
if username.is_empty() {
return user::shell::ExitCode::CommandError;
return usr::shell::ExitCode::CommandError;
}
if hashed_password(&username).is_some() {
print!("Username exists\n");
return user::shell::ExitCode::CommandError;
return usr::shell::ExitCode::CommandError;
}
print!("Password: ");
kernel::console::disable_echo();
let mut password = kernel::console::get_line();
kernel::console::enable_echo();
sys::console::disable_echo();
let mut password = sys::console::get_line();
sys::console::enable_echo();
print!("\n");
password.pop();
if password.is_empty() {
return user::shell::ExitCode::CommandError;
return usr::shell::ExitCode::CommandError;
}
print!("Confirm: ");
kernel::console::disable_echo();
let mut confirm = kernel::console::get_line();
kernel::console::enable_echo();
sys::console::disable_echo();
let mut confirm = sys::console::get_line();
sys::console::enable_echo();
print!("\n");
confirm.pop();
if password != confirm {
print!("Password confirmation failed\n");
return user::shell::ExitCode::CommandError;
return usr::shell::ExitCode::CommandError;
}
if save_hashed_password(&username, &hash(&password)).is_err() {
print!("Could not save user\n");
return user::shell::ExitCode::CommandError;
return usr::shell::ExitCode::CommandError;
}
// Create home dir
kernel::fs::Dir::create(&format!("/usr/{}", username)).unwrap();
sys::fs::Dir::create(&format!("/usr/{}", username)).unwrap();
user::shell::ExitCode::CommandSuccessful
usr::shell::ExitCode::CommandSuccessful
}
pub fn check(password: &str, hashed_password: &str) -> bool {
@ -124,15 +124,15 @@ pub fn check(password: &str, hashed_password: &str) -> bool {
return false;
}
let decoded_field = user::base64::decode(&fields[1].as_bytes());
let decoded_field = usr::base64::decode(&fields[1].as_bytes());
let c = u32::from_be_bytes(decoded_field[0..4].try_into().unwrap());
let decoded_field = user::base64::decode(&fields[2].as_bytes());
let decoded_field = usr::base64::decode(&fields[2].as_bytes());
let salt: [u8; 16] = decoded_field[0..16].try_into().unwrap();
let mut hash = [0u8; 32];
pbkdf2::pbkdf2::<Hmac<Sha256>>(password.as_bytes(), &salt, c as usize, &mut hash);
let encoded_hash = String::from_utf8(user::base64::encode(&hash)).unwrap();
let encoded_hash = String::from_utf8(usr::base64::encode(&hash)).unwrap();
encoded_hash == fields[3]
}
@ -148,7 +148,7 @@ pub fn hash(password: &str) -> String {
// Generating salt
for i in 0..2 {
let num = kernel::random::get_u64();
let num = sys::random::get_u64();
let buf = num.to_be_bytes();
let n = buf.len();
for j in 0..n {
@ -163,17 +163,17 @@ pub fn hash(password: &str) -> String {
let c = c.to_be_bytes();
let mut res: String = String::from(v);
res.push('$');
res.push_str(&String::from_utf8(user::base64::encode(&c)).unwrap());
res.push_str(&String::from_utf8(usr::base64::encode(&c)).unwrap());
res.push('$');
res.push_str(&String::from_utf8(user::base64::encode(&salt)).unwrap());
res.push_str(&String::from_utf8(usr::base64::encode(&salt)).unwrap());
res.push('$');
res.push_str(&String::from_utf8(user::base64::encode(&hash)).unwrap());
res.push_str(&String::from_utf8(usr::base64::encode(&hash)).unwrap());
res
}
fn read_hashed_passwords() -> BTreeMap<String, String> {
let mut hashed_passwords = BTreeMap::new();
if let Some(file) = kernel::fs::File::open(PASSWORDS) {
if let Some(file) = sys::fs::File::open(PASSWORDS) {
for line in file.read_to_string().split("\n") {
let mut rows = line.split(",");
if let Some(username) = rows.next() {
@ -200,8 +200,8 @@ fn save_hashed_password(username: &str, hash: &str) -> Result<(), ()> {
hashed_passwords.remove(username.into());
hashed_passwords.insert(username.into(), hash.into());
let mut file = match kernel::fs::File::open(PASSWORDS) {
None => match kernel::fs::File::create(PASSWORDS) {
let mut file = match sys::fs::File::open(PASSWORDS) {
None => match sys::fs::File::create(PASSWORDS) {
None => return Err(()),
Some(file) => file,
},

45
src/usr/vga.rs Normal file
View File

@ -0,0 +1,45 @@
use crate::{api, sys, usr, print};
use crate::api::vga::palette;
use alloc::vec::Vec;
pub fn main(args: &[&str]) -> usr::shell::ExitCode {
if args.len() == 1 {
print!("Usage: vga <command>\n");
return usr::shell::ExitCode::CommandError;
}
match args[1] {
"set" => {
if args.len() == 4 && args[2] == "font" {
if let Some(file) = sys::fs::File::open(args[3]) {
let size = file.size();
let mut buf = Vec::with_capacity(size);
buf.resize(size, 0);
file.read(&mut buf);
if let Ok(font) = api::font::from_bytes(&buf) {
sys::vga::set_font(&font);
} else {
print!("Could not parse font file\n");
return usr::shell::ExitCode::CommandError;
}
}
} else if args.len() == 4 && args[2] == "palette" {
if let Some(file) = sys::fs::File::open(args[3]) {
if let Ok(palette) = palette::from_csv(&file.read_to_string()) {
sys::vga::set_palette(palette);
} else {
print!("Could not parse palette file\n");
return usr::shell::ExitCode::CommandError;
}
}
} else {
print!("Invalid command\n");
return usr::shell::ExitCode::CommandError;
}
},
_ => {
print!("Invalid command\n");
return usr::shell::ExitCode::CommandError;
}
}
usr::shell::ExitCode::CommandSuccessful
}

View File

@ -1,15 +1,15 @@
use crate::{kernel, print, user};
use crate::{sys, usr, print};
pub fn main(args: &[&str]) -> user::shell::ExitCode {
pub fn main(args: &[&str]) -> usr::shell::ExitCode {
if args.len() != 2 {
return user::shell::ExitCode::CommandError;
return usr::shell::ExitCode::CommandError;
}
let pathname = args[1];
if pathname.starts_with("/dev") || pathname.starts_with("/sys") {
print!("Permission denied to write to '{}'\n", pathname);
return user::shell::ExitCode::CommandError;
return usr::shell::ExitCode::CommandError;
}
// The command `write /usr/alice/` with a trailing slash will create
@ -17,15 +17,15 @@ pub fn main(args: &[&str]) -> user::shell::ExitCode {
// create a file.
let success = if pathname.ends_with('/') {
let pathname = pathname.trim_end_matches('/');
kernel::fs::Dir::create(pathname).is_some()
sys::fs::Dir::create(pathname).is_some()
} else {
kernel::fs::File::create(pathname).is_some()
sys::fs::File::create(pathname).is_some()
};
if success {
user::shell::ExitCode::CommandSuccessful
usr::shell::ExitCode::CommandSuccessful
} else {
print!("Could not write to '{}'\n", pathname);
user::shell::ExitCode::CommandError
usr::shell::ExitCode::CommandError
}
}