mirror of https://github.com/vinc/moros.git
121 lines
4.2 KiB
Rust
121 lines
4.2 KiB
Rust
use crate::{sys, usr};
|
|
use crate::api::console::Style;
|
|
use crate::api::io;
|
|
use crate::sys::ata::Drive;
|
|
|
|
use alloc::format;
|
|
use alloc::string::String;
|
|
use alloc::string::ToString;
|
|
use alloc::vec::Vec;
|
|
use alloc::vec;
|
|
|
|
pub fn main(args: &[&str]) -> usr::shell::ExitCode {
|
|
if args.len() == 1 {
|
|
return usage();
|
|
}
|
|
match args[1] {
|
|
"format" if args.len() == 3 => format(args[2]),
|
|
"erase" if args.len() == 3 => erase(args[2]),
|
|
"usage" => usage(),
|
|
"list" => list(),
|
|
_ => help(),
|
|
}
|
|
}
|
|
|
|
fn parse_disk_path(pathname: &str) -> Result<(u8, u8), String> {
|
|
let path: Vec<_> = pathname.split('/').collect();
|
|
if !pathname.starts_with("/dev/ata/") || path.len() != 5 {
|
|
return Err(format!("Could not find disk at '{}'", pathname));
|
|
}
|
|
let bus = path[3].parse().or(Err("Could not parse <bus>".to_string()))?;
|
|
let dsk = path[4].parse().or(Err("Could not parse <dsk>".to_string()))?;
|
|
Ok((bus, dsk))
|
|
}
|
|
|
|
fn format(pathname: &str) -> usr::shell::ExitCode {
|
|
match parse_disk_path(pathname) {
|
|
Ok((bus, dsk)) => {
|
|
sys::fs::mount_ata(bus, dsk);
|
|
sys::fs::format_ata();
|
|
println!("Disk successfully formatted");
|
|
println!("MFS is now mounted to '/'");
|
|
usr::shell::ExitCode::CommandSuccessful
|
|
}
|
|
Err(msg) => {
|
|
error!("{}", msg);
|
|
usr::shell::ExitCode::CommandError
|
|
}
|
|
}
|
|
}
|
|
|
|
fn erase(pathname: &str) -> usr::shell::ExitCode {
|
|
match parse_disk_path(pathname) {
|
|
Ok((bus, dsk)) => {
|
|
if let Some(drive) = Drive::open(bus, dsk) {
|
|
print!("Proceed? [y/N] ");
|
|
if io::stdin().read_line().trim() == "y" {
|
|
println!();
|
|
|
|
let n = drive.block_count();
|
|
let buf = vec![0; drive.block_size() as usize];
|
|
print!("\x1b[?25l"); // Disable cursor
|
|
for i in 0..n {
|
|
if sys::console::end_of_text() || sys::console::end_of_transmission() {
|
|
println!();
|
|
print!("\x1b[?25h"); // Enable cursor
|
|
return usr::shell::ExitCode::CommandError;
|
|
}
|
|
print!("\x1b[2K\x1b[1G");
|
|
print!("Erasing block {}/{}", i, n);
|
|
// TODO: Implement drive.write(block, buf)
|
|
sys::ata::write(bus, dsk, i, &buf).ok();
|
|
}
|
|
println!();
|
|
print!("\x1b[?25h"); // Enable cursor
|
|
}
|
|
}
|
|
usr::shell::ExitCode::CommandSuccessful
|
|
}
|
|
Err(msg) => {
|
|
error!("{}", msg);
|
|
usr::shell::ExitCode::CommandError
|
|
}
|
|
}
|
|
}
|
|
|
|
fn list() -> usr::shell::ExitCode {
|
|
println!("Path Name (Size)");
|
|
for drive in sys::ata::list() {
|
|
println!("/dev/ata/{}/{} {}", drive.bus, drive.dsk, drive);
|
|
}
|
|
usr::shell::ExitCode::CommandSuccessful
|
|
}
|
|
|
|
fn usage() -> usr::shell::ExitCode {
|
|
let size = sys::fs::disk_size();
|
|
let used = sys::fs::disk_used();
|
|
let free = size - used;
|
|
|
|
let width = size.to_string().len();
|
|
let color = Style::color("LightCyan");
|
|
let reset = Style::reset();
|
|
println!("{}size:{} {:width$} bytes", color, reset, size, width = width);
|
|
println!("{}used:{} {:width$} bytes", color, reset, used, width = width);
|
|
println!("{}free:{} {:width$} bytes", color, reset, free, width = width);
|
|
usr::shell::ExitCode::CommandSuccessful
|
|
}
|
|
|
|
fn help() -> usr::shell::ExitCode {
|
|
let csi_option = Style::color("LightCyan");
|
|
let csi_title = Style::color("Yellow");
|
|
let csi_reset = Style::reset();
|
|
println!("{}Usage:{} disk {}<command>{}", csi_title, csi_reset, csi_option, csi_reset);
|
|
println!();
|
|
println!("{}Commands:{}", csi_title, csi_reset);
|
|
println!(" {}list{} List detected disks", csi_option, csi_reset);
|
|
println!(" {}usage{} List disk usage", csi_option, csi_reset);
|
|
println!(" {}format <path>{} Format disk", csi_option, csi_reset);
|
|
println!(" {}erase <path>{} Erase disk", csi_option, csi_reset);
|
|
usr::shell::ExitCode::CommandSuccessful
|
|
}
|