/* * Copyright (c) 2022, Able * * SPDX-License-Identifier: MPL-2.0 */ use crate::arch::drivers::sysinfo::master; use crate::arch::interrupts::{reset_pit_for_cpu, set_pit_2}; use crate::devices::pci::brute_force_scan; use crate::systeminfo::{KERNEL_VERSION, RELEASE_TYPE}; use crate::time::fetch_time; use crate::KERNEL_STATE; use crate::{ arch::shutdown, rhai_shell::KEYBUFF, vterm::Term, // wasm_jumploader::run_program, }; use acpi::{AcpiTables, PlatformInfo}; use cpuio::{inb, outb}; use ext2::fs::sync::{DirectoryEntry, Synced}; use ext2::{fs::Ext2, sector::Size1024}; use genfs::{Fs, OpenOptions}; use kernel::allocator::ALLOCATOR; use spin::Lazy; use x86_64::instructions::interrupts::{disable, enable}; pub const BANNER_WIDTH: &str = "================================================================================"; // TODO: move to a better place #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub struct AcpiStruct {} impl acpi::AcpiHandler for AcpiStruct { unsafe fn map_physical_region( &self, physical_address: usize, size: usize, ) -> acpi::PhysicalMapping { info!("PHYS ADDR: {:?}", physical_address); info!("Size: {:?}", size); todo!("map_physical_region"); } fn unmap_physical_region(_region: &acpi::PhysicalMapping) { todo!("unmap_physical_region"); } } pub static TERM: Lazy> = Lazy::new(|| spin::Mutex::new(VTerm::new())); #[derive(Debug)] pub struct Path { pub path: Vec, } impl Path { pub fn new(path: String) -> Self { let mut path_vec_string = vec![]; for part in path.split(&['\\', '/'][..]) { path_vec_string.push(part.to_string()); } Path { path: path_vec_string, } } } /// Experimental scratchpad for testing. pub fn scratchpad() { // bruh(); // panic!(":>"); // for c in 0..144_697 { // trace!("{:?}", char::from_u32(c)); // } // bruh(); for x in brute_force_scan() { println!("{}", x); } disable(); let tick_time = fetch_time(); let hostname = &KERNEL_STATE.lock().hostname; let allocator = ALLOCATOR.lock(); let size = allocator.size(); let used = allocator.used(); drop(allocator); enable(); println!( "{} ,-------. OS: \0BLUE\0AbleOS\0RESET\0 ,'\\ _ _`. Host: \0PINK\0{}\0RESET\0 / \\)_)-)_)-\\ Kernel: \0RED\0AKern-{}-v{}\0RESET\0 : : Uptime: \0GREEN\0{}\0RESET\0 \\ / Packages: None \\ / Shell: BuiltinShell `. ,' Resolution: 640x480 `. ,' Terminal: VGABuffer `.,' CPU: {} /\\`. ,-._ GPU: VGA Compatible `-' Memory: {}/{} {}", // include_str!("../assets/balloon.txt"), // kstate.hostname, BANNER_WIDTH, hostname, RELEASE_TYPE, KERNEL_VERSION, tick_time, master().unwrap().brand_string().unwrap(), // "", // mem used, size, BANNER_WIDTH ); real_shell(); } pub fn acpi() { let acpi_handler = AcpiStruct {}; let _table; unsafe { _table = AcpiTables::search_for_rsdp_bios(acpi_handler); } match _table.unwrap().platform_info().unwrap() { PlatformInfo { power_profile, interrupt_model, .. } => { info!("{:?}", power_profile); info!("{:?}", interrupt_model); // info!("{:?}", processor_info.unwrap()); // info!("{:?}", pm_timer.unwrap()); } } } pub fn real_shell() { let prompt = "-> "; let _current_dir = "/".to_string(); let current_user = "able".to_string(); let mut buf = String::new(); print!("{}", prompt); // panic!(":<"); loop { match x86_64::instructions::interrupts::without_interrupts(|| KEYBUFF.lock().pop()) { Some('\n') => { // panic!(); println!(); // match engine.eval_with_scope::(&mut scope, &buf) { // Ok(o) => println!("{o}"), // Err(e) => println!("Eval error: {e}"), // }; if !buf.is_empty() { command_parser(current_user.clone(), buf.clone()); } buf.clear(); print!("{}", prompt); } Some('\u{8}') => { print!("\u{8}"); buf.pop(); } Some('\u{0009}') => { buf.push(' '); buf.push(' '); buf.push(' '); buf.push(' '); } Some(chr) => { buf.push(chr); print!("{}", chr); } None => { // trace!("{}", buf); } } } } pub fn command_parser(user: String, command: String) { // let fs = &*FILE_SYSTEM.lock(); let mut iter = command.split_whitespace(); // TODO: update the open() function to take either a ableOS path or a b"/" type path let current_path = Path::new("/home/able".to_string()); trace!("Current path: {:?}", current_path); let current_path = b"/home/able/"; let bin_name = iter.next().unwrap(); let mut strin = String::new(); for stri in iter { trace!("{}", stri); strin.push_str(stri); } let conf_args; match clparse::Arguments::parse_from_string(strin) { Ok(ok) => conf_args = ok, Err(err) => { println!("ERROR: {}", err); error!("{}", err); return; } }; match bin_name { // note: able asked for rhaish to stay in the repo but will be removed // in the future so just comment it out for now // "rhai" => { // drop(fs); // shell(); // } // "list" | "ls" => { // for dir_entry in list_files_in_dir(fs, current_path) { // println!("{}", dir_entry.file_name_string()); // } // } // "echo" => match conf_args.1.arguments.get("p") { // Some(path) => echo_file(path.to_string(), fs), // None => println!("No path provided"), // } "test" => {} "quit" => shutdown(), _ => { // let mut options = OpenOptions::new(); // options.read(true); // let file = { // let path = format!("/home/{user}/bins/{bin_name}.wasm"); // if let Ok(file) = fs.open(&path.as_bytes(), &options) { // file // } else { // let path = format!("/shared/bins/{bin_name}.wasm"); // if let Ok(file) = fs.open(&path.as_bytes(), &options) { // file // } else { // let path = format!("/system/bins/{bin_name}.wasm"); // match fs.open(&path.as_bytes(), &options) { // Ok(file) => file, // Err(error) => { // trace!("{:?}", error); println!("No such binary: {}", bin_name); error!("No such binary: {}", bin_name); // } // } // } // } // }; // let mut binary = vec![]; // file.read_to_end(&mut binary).unwrap(); // let args = iter.collect::>(); // println!("{:?}", args); // run_program(&binary); } } } pub fn sound(n_frequency: u32) { let div: u32; let tmp: u8; div = 1193180 / n_frequency; unsafe { outb(0xb6, 0x43); set_pit_2(div); // And play the sound using the PC speaker tmp = inb(0x61); if tmp != (tmp | 3) { outb(tmp | 3, 0x61); } } } pub fn sound_off() { unsafe { let tmp = inb(0x61) & 0xFC; outb(tmp, 0x61) }; reset_pit_for_cpu(); } pub fn list_files_in_dir( fs: &Synced>>, _path: &[u8], ) -> Vec { let mut entry_list = vec![]; let dirr = fs.read_dir(b"/").unwrap(); for dir_entry in dirr { entry_list.push(dir_entry.unwrap()); } entry_list } pub static CURRENT_DIR: Lazy> = Lazy::new(|| spin::Mutex::new("/".to_string())); pub fn echo_file(path: String, fs: &Synced>>) { let mut current_dir = CURRENT_DIR.lock(); current_dir.push_str(&path); let file = fs .open(current_dir.as_bytes(), OpenOptions::new().read(true)) .unwrap(); if file.is_dir() { // println!("{} is a directory", path); } else { let mut file_contents = Vec::new(); let _ret = file.read_to_end(&mut file_contents).unwrap(); let file_contents_str = String::from_utf8_lossy(&file_contents); println!("{}", file_contents_str); } }