ableos/ableos/src/scratchpad.rs

379 lines
11 KiB
Rust

/*
* Copyright (c) 2022, Able <able@ablecorp.us>
*
* 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::ide::{Channel, Drive};
use crate::devices::pci::{PciDevice, PCI_DEVICES};
use crate::filesystem;
use crate::filesystem::vfs::VFS;
use crate::systeminfo::{KERNEL_VERSION, RELEASE_TYPE};
use crate::time::fetch_time;
use crate::{
arch::shutdown, rhai_shell::KEYBUFF, vterm::VTerm, wasm_jumploader::run_program, KERNEL_STATE,
};
use acpi::{AcpiTables, PlatformInfo};
use cpuio::{inb, outb};
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<T>(
&self,
physical_address: usize,
size: usize,
) -> acpi::PhysicalMapping<Self, T> {
info!("PHYS ADDR: {:?}", physical_address);
info!("Size: {:?}", size);
todo!("map_physical_region");
}
fn unmap_physical_region<T>(_region: &acpi::PhysicalMapping<Self, T>) {
todo!("unmap_physical_region");
}
}
pub static TERM: Lazy<spin::Mutex<VTerm>> = Lazy::new(|| spin::Mutex::new(VTerm::new()));
#[derive(Debug)]
pub struct Path {
pub path: Vec<String>,
}
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();
disable();
let tick_time = fetch_time();
let hostname = KERNEL_STATE.lock().hostname.clone();
let allocator = ALLOCATOR.lock();
let size = allocator.size();
let used = allocator.used();
drop(allocator);
enable();
println!(
"{}
,-------. OS: \u{001A}BLUE\u{001A}AbleOS\u{001A}RESET\u{001A}
,'\\ _ _`. Host: \u{001A}PINK\u{001A}{}\u{001A}RESET\u{001A}
/ \\)_)-)_)-\\ Kernel: \u{001A}RED\u{001A}AKern-{}-v{}\u{001A}RESET\u{001A}
: : Uptime: \u{001A}GREEN\u{001A}{}\u{001A}RESET\u{001A}
\\ / 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
);
let pci_ide_device = {
let pci_devices = PCI_DEVICES.lock();
pci_devices
.iter()
.find_map(|device_ref| {
let device = device_ref.lock();
if let PciDevice::Ide(dev) = &*device {
println!("IDE Device found: {}", dev.device_info());
Some(device_ref.clone())
} else {
None
}
})
.unwrap()
};
{
let mut pci_ide_device = pci_ide_device.lock();
if let PciDevice::Ide(device) = &mut *pci_ide_device {
let mut first_sector = Vec::with_capacity(512);
device
.read(Channel::Primary, Drive::Master, 0, 1, &mut first_sector)
.unwrap();
// trace!("IDE Primary/Master sector 0: {first_sector:?}");
}
}
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::<rhai::Dynamic>(&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 mut iter = command.split_whitespace();
let current_path = Path::new("/home/able".to_string());
trace!("Current path: {:?}", current_path);
let current_path = "/home/able/";
let bin_name = iter.next().unwrap();
let mut strin = String::new();
for stri in iter.clone() {
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" => {
// shell();
// }
"list" | "ls" => {
let mut vfs = VFS.lock();
let handle = vfs.resolve(current_path).unwrap();
let dir = vfs.fs_node(handle).unwrap();
drop(vfs);
for dir_entry in dir.directory().unwrap() {
println!("{}", dir_entry.name());
}
}
"echo" => match conf_args.1.arguments.get("p") {
Some(path) => echo_file(path.to_string()),
None => println!("No path provided"),
},
"test" => {}
"quit" => shutdown(),
"tree" => filesystem::tree("/").unwrap(),
_ => {
let file = {
let mut vfs = VFS.lock();
let path = format!("/home/{user}/bins/{bin_name}.wasm");
let handle = if let Ok(file) = vfs.resolve(path) {
file
} else {
let path = format!("/shared/bins/{bin_name}.wasm");
if let Ok(file) = vfs.resolve(path) {
file
} else {
let path = format!("/system/bins/{bin_name}.wasm");
match vfs.resolve(path) {
Ok(file) => file,
Err(error) => {
trace!("{:?}", error);
println!("No such binary: {}", bin_name);
error!("No such binary: {}", bin_name);
return;
}
}
}
};
vfs.fs_node(handle).unwrap()
};
let mut binary = vec![];
file.read(0, file.size(), &mut binary).unwrap();
let args = iter.collect::<Vec<&str>>();
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 echo_file(path: String) {
println!("{}", path);
let mut current_path = String::from("");
current_path.push_str(&path);
debug!("Aquiring lock");
let mut vfs = VFS.lock();
debug!("Resolving path");
let maybe_handle = vfs.resolve(&current_path);
match maybe_handle {
Ok(handle) => {
debug!("Loading file");
let maybe_file = vfs.fs_node(handle);
match maybe_file {
Some(file) => {
trace!("checking is directory");
if file.is_dir() {
println!(
"\u{001A}RED\u{001A}ERROR\u{001A}RESET\u{001A} {} is a directory",
path
);
error!("{} is a directory", path);
} else {
trace!("allocating buffer for file contents");
let mut file_contents = Vec::new();
trace!("Reading file {} into buffer", path);
file.read(0, file.size(), &mut file_contents).unwrap();
trace!("Converting file bytes into string");
let file_contents_str = String::from_utf8_lossy(&file_contents);
println!("{}", file_contents_str);
}
}
None => {
error!("File {} doesn't exist", path);
println!(
"\u{001A}RED\u{001A}ERROR\u{001A}RESET\u{001A}: File {} doesn't exist",
path
);
}
}
}
Err(err) => {
println!(
"\u{001A}RED\u{001A}ERROR\u{001A}RESET\u{001A}: path {} Error {}",
path, err
);
error!("path {} Error {}", path, err);
}
}
}