/* * Copyright (c) 2022, Umut İnan Erdoğan * Copyright (c) 2022, able * * SPDX-License-Identifier: MPL-2.0 */ use std::{fs, process::Command}; use colored::*; struct Options { pub subcommand: Subcommand, pub arguments: Vec, } enum Subcommand { Doc, Help, Run, Empty, /// Run all tests for all architectures Test, Unknown(String), } impl Subcommand { fn from_str>(str: S) -> Subcommand { match str.as_ref() { "doc" => Subcommand::Doc, "help" => Subcommand::Help, "run" | "r" => Subcommand::Run, "test" | "t" => Subcommand::Test, "" => Subcommand::Empty, unknown => Subcommand::Unknown(unknown.to_string()), } } } enum MachineType { X86_64, RiscV64, AArch64, Unknown(String), } fn main() { let options = options(); match options.subcommand { Subcommand::Test => { Command::new("cargo") .args(["test", "--target=json_targets/x86_64-ableos.json"]) .current_dir(fs::canonicalize("./ableos").unwrap()) .status() .unwrap(); // panic!("Test Infrastructure missing"); } Subcommand::Doc => { let machine_text = options.arguments.get(0).cloned().unwrap_or_default(); match machine(machine_text) { MachineType::X86_64 => { Command::new("cargo") .args(["doc", "--open"]) .current_dir(fs::canonicalize("./ableos").unwrap()) .status() .unwrap(); } MachineType::RiscV64 => { Command::new("cargo") .args(["doc", "--open", "--target=riscv64gc-unknown-none-elf"]) .current_dir(fs::canonicalize("./ableos").unwrap()) .status() .unwrap(); } MachineType::AArch64 => { Command::new("cargo") .args(["doc", "--open", "--target=json_targets/aarch64-ableos.json"]) .current_dir(fs::canonicalize("./ableos").unwrap()) .status() .unwrap(); } MachineType::Unknown(unknown) => { eprintln!( "{}: unknown machine type `{}`", "error".red().bold(), unknown.bold(), ); eprintln!("expected one of x86_64, riscv64 or aarch64"); } } } Subcommand::Help => help(), Subcommand::Run => { let machine_text = options.arguments.get(0).cloned().unwrap_or_default(); let debug = options.arguments.get(1).cloned().unwrap_or_default(); let debug = matches!(debug.as_str(), "--debug" | "--dbg" | "-d"); match machine(machine_text) { MachineType::X86_64 if debug => { Command::new("cargo") .args(["run", "--", "-S", "-gdb", "tcp:9000"]) .current_dir(fs::canonicalize("./ableos").unwrap()) .status() .unwrap(); } MachineType::X86_64 => { Command::new("cargo") .args(["run", "--release"]) .current_dir(fs::canonicalize("./ableos").unwrap()) .status() .unwrap(); } MachineType::RiscV64 if debug => { eprintln!( "{}: debug is not implemented for riscv64", "error".red().bold() ); } MachineType::RiscV64 => { Command::new("cargo") .args(["build", "--release", "--target=riscv64gc-unknown-none-elf"]) .current_dir(fs::canonicalize("./ableos").unwrap()) .status() .unwrap(); Command::new("qemu-system-riscv64") .args(["-machine", "virt"]) .args(["-cpu", "rv64"]) .args(["-smp", "8"]) .args(["-m", "128M"]) .arg("-bios") .arg("src/arch/riscv/firmwear/opensbi-riscv64-generic-fw_jump.bin") .arg("-kernel") .arg("target/riscv64gc-unknown-none-elf/release/ableos") .current_dir(fs::canonicalize("./ableos").unwrap()) .status() .unwrap(); } MachineType::AArch64 if debug => { eprintln!( "{}: debug is not implemented for aarch64", "error".red().bold() ); } MachineType::AArch64 => { Command::new("cargo") .args([ "build", "--release", "--target=json_targets/aarch64-ableos.json", ]) .current_dir(fs::canonicalize("./ableos").unwrap()) .status() .unwrap(); Command::new("qemu-system-aarch64") .args(["-machine", "virt"]) .args(["-m", "1024M"]) .args(["-cpu", "cortex-a53"]) .args(["-kernel", "target/aarch64-ableos/release/ableos"]) .args(["-device", "virtio-keyboard"]) .current_dir(fs::canonicalize("./ableos").unwrap()) .status() .unwrap(); } MachineType::Unknown(unknown) => { eprintln!( "{}: unknown machine type `{}`", "error".red().bold(), unknown.bold(), ); eprintln!("expected one of x86_64, riscv64 or aarch64"); } } } Subcommand::Empty => { eprintln!("{}: no subcommand passed", "error".red().bold()); help(); } Subcommand::Unknown(unknown) => { eprintln!( "{}: unknown subcommand `{}`", "error".red().bold(), unknown.bold() ); help(); } } } fn options() -> Options { let subcommand = std::env::args().nth(1).unwrap_or_default(); let arguments = std::env::args().skip(2).collect(); Options { subcommand: Subcommand::from_str(subcommand), arguments, } } fn machine>(text: S) -> MachineType { match text.as_ref() { "x86" | "x86_64" => MachineType::X86_64, "riscv" | "riscv64" => MachineType::RiscV64, "arm" | "arm64" | "aarch64" => MachineType::AArch64, "" => { eprintln!( "{}: no machine type passed, defaulting to x86_64", "warning".yellow().bold() ); MachineType::X86_64 } unknown => MachineType::Unknown(unknown.to_string()), } } fn help() { todo!("`help`") }