Skip to content

Commit

Permalink
Move kernel code to api (#204)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
vinc authored Jul 16, 2021
1 parent 04afe53 commit 6b8de26
Show file tree
Hide file tree
Showing 75 changed files with 834 additions and 774 deletions.
83 changes: 83 additions & 0 deletions src/api/console.rs
Original file line number Diff line number Diff line change
@@ -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
}
}

16 changes: 16 additions & 0 deletions src/kernel/fonts.rs → src/api/font.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(());
}
Expand All @@ -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);
}
3 changes: 3 additions & 0 deletions src/api/mod.rs
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
pub mod console;
pub mod font;
pub mod syscall;
pub mod vga;
2 changes: 1 addition & 1 deletion src/api/syscall.rs
Original file line number Diff line number Diff line change
@@ -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()) };
Expand Down
94 changes: 94 additions & 0 deletions src/api/vga/color.rs
Original file line number Diff line number Diff line change
@@ -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 changes: 5 additions & 0 deletions src/api/vga/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
pub mod color;
pub mod palette;

pub use color::Color;
pub use palette::Palette;
38 changes: 38 additions & 0 deletions src/api/vga/palette.rs
Original file line number Diff line number Diff line change
@@ -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);
}
38 changes: 19 additions & 19 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand All @@ -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);
}
}
Expand Down Expand Up @@ -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);
Expand Down
12 changes: 6 additions & 6 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,25 @@ 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);

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"]);
}
}
}
Expand All @@ -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)
}
}
Loading

0 comments on commit 6b8de26

Please sign in to comment.