diff --git a/bootloader/src/splash.rs b/bootloader/src/splash.rs index 9729426..ef29061 100644 --- a/bootloader/src/splash.rs +++ b/bootloader/src/splash.rs @@ -1,5 +1,5 @@ -pub const SPLASH: &'static str = -"▄ ▄ ▄ +pub const SPLASH: &'static str = + "▄ ▄ ▄ ██▄ ▄██ █ ▀█▄ ▄█▀▐█ █ ▀▄ ▄▀ ▐█ @@ -23,7 +23,7 @@ pub const SPLASH: &'static str = ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▀▀▀▀▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ Press any key to start..."; - + #[allow(dead_code)] pub fn splash() { for c in SPLASH.chars() { @@ -33,8 +33,8 @@ pub fn splash() { '▌' => print!("{}", 0xdd as char), '▄' => print!("{}", 0xdc as char), '█' => print!("{}", 0xdb as char), - '\n' => {}, + '\n' => {} _ => print!("{}", c), } } -} \ No newline at end of file +} diff --git a/kernel/src/filesystem/fat.rs b/kernel/src/filesystem/fat.rs old mode 100644 new mode 100755 index ec98da2..98e15e1 --- a/kernel/src/filesystem/fat.rs +++ b/kernel/src/filesystem/fat.rs @@ -2,15 +2,14 @@ use crate::drivers::disk::DISK; use core::mem; +use libfelix::mutex::Mutex; -//Warning! Mutable static here -//TODO: Implement a mutex to get safe access to this -pub static mut FAT: FatDriver = FatDriver { +pub static mut FAT: Mutex = Mutex::new(FatDriver { header: NULL_HEADER, entries: [NULL_ENTRY; ENTRY_COUNT], table: [0; FAT_SIZE], buffer: [0; 2048], -}; +}); const ENTRY_COUNT: usize = 512; const FAT_START: u16 = 36864; @@ -107,9 +106,11 @@ static NULL_ENTRY: Entry = Entry { size: 0, }; +#[derive(Copy, Clone)] pub struct FatDriver { pub header: Header, - pub entries: [Entry; ENTRY_COUNT], //the root directory is an array of file entries + pub entries: [Entry; ENTRY_COUNT], + //the root directory is an array of file entries pub table: [u16; FAT_SIZE], pub buffer: [u8; 2048], } @@ -130,6 +131,7 @@ impl FatDriver { //get entries array address and overwrite that mem location with data from root directory //calculate size and position of root direcotry based on data from header pub fn load_entries(&mut self) { + libfelix::print!(" loading entries"); let target = &mut self.entries as *mut Entry; let entry_size = mem::size_of::() as u16; @@ -186,8 +188,8 @@ impl FatDriver { } //read first cluster of file to buffer - pub fn read_file_to_buffer(&mut self, entry: &Entry) { - let target = &mut self.buffer as *mut u8; + pub fn read_file_to_buffer(&self, entry: &Entry) { + let target = self.buffer.as_ptr() as *mut u8; let data_lba: u64 = FAT_START as u64 + (self.header.reserved_sectors @@ -204,7 +206,7 @@ impl FatDriver { } //read file reading one cluster at time - pub fn read_file_to_target(&mut self, entry: &Entry, target: *mut u32) { + pub fn read_file_to_target(&self, entry: &Entry, target: *mut u32) { let mut next_cluster = entry.first_cluster_low; let mut current_target = target; diff --git a/kernel/src/filesystem/mod.rs b/kernel/src/filesystem/mod.rs old mode 100644 new mode 100755 diff --git a/kernel/src/main.rs b/kernel/src/main.rs old mode 100644 new mode 100755 index 5fd7090..5959cc7 --- a/kernel/src/main.rs +++ b/kernel/src/main.rs @@ -17,12 +17,12 @@ use core::arch::asm; use core::panic::PanicInfo; use drivers::disk::DISK; use drivers::pic::PICS; -use filesystem::fat::FAT; use interrupts::idt::IDT; use memory::allocator::Allocator; use memory::paging::PAGING; use shell::shell::SHELL; use syscalls::print::PRINTER; +use filesystem::fat::FAT; use multitasking::task::TASK_MANAGER; @@ -80,9 +80,11 @@ pub extern "C" fn _start() -> ! { //init filesystem if DISK.enabled { - FAT.load_header(); - FAT.load_entries(); - FAT.load_table(); + let fat = FAT.acquire_mut(); + fat.load_header(); + fat.load_table(); + fat.load_entries(); + FAT.free(); } //print name, version and copyright diff --git a/kernel/src/shell/mod.rs b/kernel/src/shell/mod.rs old mode 100644 new mode 100755 diff --git a/kernel/src/shell/shell.rs b/kernel/src/shell/shell.rs old mode 100644 new mode 100755 index 5235f5e..effda02 --- a/kernel/src/shell/shell.rs +++ b/kernel/src/shell/shell.rs @@ -97,7 +97,8 @@ impl Shell { //list root directory _b if self.is_command("ls") => unsafe { - FAT.list_entries(); + FAT.acquire().list_entries(); + FAT.free(); }, //list running tasks @@ -169,13 +170,14 @@ impl Shell { for i in 4..15 { self.arg[i - 4] = b[i]; } + let fat = FAT.acquire(); - let entry = FAT.search_file(&self.arg); + let entry = fat.search_file(&self.arg); if entry.name[0] != 0 { - FAT.read_file_to_buffer(entry); + fat.read_file_to_buffer(entry); - for c in FAT.buffer { + for c in fat.buffer { if c != 0 { libfelix::print!("{}", c as char); } @@ -184,6 +186,7 @@ impl Shell { } else { libfelix::println!("File not found!"); } + FAT.free(); } //loads an executable as a task @@ -191,8 +194,9 @@ impl Shell { for i in 4..15 { self.arg[i - 4] = b[i]; } + let fat = FAT.acquire(); - let entry = FAT.search_file(&self.arg); + let entry = fat.search_file(&self.arg); if entry.name[0] != 0 { let slot = TASK_MANAGER.get_free_slot(); let target = APP_TARGET + (slot as u32 * APP_SIZE); @@ -201,7 +205,7 @@ impl Shell { TABLES[8].set(target); PAGING.set_table(8, &TABLES[8]); - FAT.read_file_to_target(&entry, target as *mut u32); + fat.read_file_to_target(&entry, target as *mut u32); unsafe { let signature = *(target as *mut u32); @@ -215,6 +219,7 @@ impl Shell { } else { libfelix::println!("Program not found!"); } + FAT.free(); } pub fn is_command(&self, command: &str) -> bool { diff --git a/lib/Cargo.toml b/lib/Cargo.toml old mode 100644 new mode 100755 diff --git a/lib/src/lib.rs b/lib/src/lib.rs old mode 100644 new mode 100755 index 9e8d96a..8cc6829 --- a/lib/src/lib.rs +++ b/lib/src/lib.rs @@ -1,3 +1,4 @@ #![no_std] +pub mod mutex; pub mod print; diff --git a/lib/src/mutex.rs b/lib/src/mutex.rs new file mode 100755 index 0000000..fe5f372 --- /dev/null +++ b/lib/src/mutex.rs @@ -0,0 +1,45 @@ +use core::sync::atomic::{AtomicBool, Ordering}; +/* + This is a oversimplified mutex created from scratch. Meant to be used for global, static definitions of objects, visible for all active threads. Once a thread acquires the target object, all other threads trying to do so will wait until it is freed. + + There is plenty of room for improvements, since there are no mechanisms for e.g. creating a queue of threads that requested access to an object and giving it to the first that needs it. + + TODO: Improve it +*/ +pub struct Mutex { + target: T, + free: AtomicBool, +} + +impl Mutex { + pub const fn new(value: T) -> Self { + Self { + target: value, + free: AtomicBool::new(true), + } + } + + //WARNING: You MUST call free() after using acquire() or acquire_mut() when the target is no longer needed. Not doing so can, and will, lead to problems. + pub fn acquire_mut(&mut self) -> &mut T { + while !self.free.load(Ordering::SeqCst) {} // Wait until free is true + self.free.store(false, Ordering::SeqCst); // Set free to false + return &mut self.target; + } + + //WARNING: You MUST call free() after using acquire() or acquire_mut() when the target is no longer needed. Not doing so can, and will, lead to problems. + pub fn acquire(&mut self) -> &T { + while !self.free.load(Ordering::SeqCst) {} // Wait until free is true + self.free.store(false, Ordering::SeqCst); // Set free to false + return &self.target; + } + + pub fn free(&self) { + self.free.store(true, Ordering::SeqCst); // Set free to true + } +} + +impl Drop for Mutex { + fn drop(&mut self) { + self.free = AtomicBool::from(true); + } +} diff --git a/lib/src/print.rs b/lib/src/print.rs old mode 100644 new mode 100755