Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 41 additions & 9 deletions tool/microkit/src/argparse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
// SPDX-License-Identifier: BSD-2-Clause
//

use crate::sdk::Sdk;
use std::fmt;
use std::iter::Peekable;
use std::path::PathBuf;
Expand All @@ -12,7 +13,7 @@ pub fn print_usage() {
println!("usage: microkit [-h] [OPTIONS] --board BOARD --config CONFIG [--search-path SEARCH_PATH ...] system")
}

pub fn print_help(available_boards: &[String]) {
pub fn print_help(sdk: &Sdk) {
print_usage();
println!("\npositional arguments:");
println!(" system");
Expand All @@ -22,7 +23,10 @@ pub fn print_help(available_boards: &[String]) {
println!(" -r, --report REPORT");
println!(" --image-type {{binary,elf,uimage}}");
println!(" --override-kernel KERNEL (for debugging purposes)");
println!(" --board {}", available_boards.join("\n "));
println!(
" --board {}",
sdk.available_board_names().join("\n ")
);
println!(" --config CONFIG");
println!(" --capdl-json CAPDL_SPEC (JSON format)");
println!(" --search-path [SEARCH_PATH ...]");
Expand Down Expand Up @@ -73,11 +77,25 @@ pub struct Args {

#[derive(Debug)]
pub enum ArgsError {
InvalidImageTypeParameter { parameter: String },
InvalidBoardParameter { parameter: String },
MissingParameter { parent_argument: &'static str },
MissingRequiredArguments { args: Vec<&'static str> },
UnrecognizedArgument { arg: String },
InvalidImageTypeParameter {
parameter: String,
},
InvalidBoardParameter {
parameter: String,
},
InvalidConfigParameter {
parameter: String,
choices: Vec<String>,
},
MissingParameter {
parent_argument: &'static str,
},
MissingRequiredArguments {
args: Vec<&'static str>,
},
UnrecognizedArgument {
arg: String,
},
HelpWanted,
}

Expand All @@ -90,6 +108,13 @@ impl fmt::Display for ArgsError {
Self::InvalidBoardParameter { parameter } => {
write!(f, "argument --board: unknown parameter '{parameter}'")
}
Self::InvalidConfigParameter { parameter, choices } => {
write!(
f,
"argument --config: invalid choice '{parameter}' (choose from: {})",
choices.join(", ")
)
}
Self::MissingParameter { parent_argument } => {
write!(f, "argument {parent_argument}: expected one parameter")
}
Expand Down Expand Up @@ -136,7 +161,7 @@ where
}

impl Args {
pub fn parse(args: &[String], available_boards: &[String]) -> Result<Self, ArgsError> {
pub fn parse(args: &[String], sdk: &Sdk) -> Result<Self, ArgsError> {
let mut args = args.iter().skip(1).cloned().peekable();

let mut output_path = PathBuf::from("loader.img");
Expand All @@ -163,7 +188,7 @@ impl Args {
}
"--board" => {
let board_param = consume_parameter(&mut args, "--board")?;
if !available_boards.contains(&board_param) {
if !sdk.available_boards_contains(&board_param) {
return Err(ArgsError::InvalidBoardParameter {
parameter: board_param,
});
Expand Down Expand Up @@ -224,6 +249,13 @@ impl Args {
let config = config.unwrap();
let sdf_path = sdf_path.unwrap();

if sdk.select(&board, &config).is_none() {
return Err(ArgsError::InvalidConfigParameter {
parameter: config,
choices: sdk.available_config_names_for(&board),
});
}

Ok(Self {
sdf_path,
board,
Expand Down
1 change: 1 addition & 0 deletions tool/microkit/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ pub mod elf;
pub mod loader;
pub mod report;
pub mod sdf;
pub mod sdk;
pub mod sel4;
pub mod symbols;
pub mod uimage;
Expand Down
201 changes: 37 additions & 164 deletions tool/microkit/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ use microkit_tool::elf::ElfFile;
use microkit_tool::loader::Loader;
use microkit_tool::report::write_report;
use microkit_tool::sdf::{parse, SysMemoryRegion, SysMemoryRegionPaddr};
use microkit_tool::sdk::Sdk;
use microkit_tool::sel4::{
emulate_kernel_boot, emulate_kernel_boot_partial, Arch, Config, PlatformConfig,
RiscvVirtualMemory,
Expand Down Expand Up @@ -82,54 +83,31 @@ impl ImageOutputType {
}
}

fn main() -> Result<(), String> {
let exe_path = std::env::current_exe().unwrap();
let sdk_env = std::env::var("MICROKIT_SDK");
let sdk_dir = match sdk_env {
Ok(ref value) => Path::new(value),
Err(err) => match err {
// If there is no MICROKIT_SDK explicitly set, use the one that the binary is in.
std::env::VarError::NotPresent => exe_path.parent().unwrap().parent().unwrap(),
_ => {
return Err(format!(
"Could not read MICROKIT_SDK environment variable: {err}"
))
}
},
};

if !sdk_dir.exists() {
eprintln!(
"Error: SDK directory '{}' does not exist.",
sdk_dir.display()
);
std::process::exit(1);
}

let boards_path = sdk_dir.join("board");
if !boards_path.exists() || !boards_path.is_dir() {
fn bail_if_not_exists(description: &'static str, path: &Path) -> Result<(), String> {
if !path.exists() {
eprintln!(
"Error: SDK directory '{}' does not have a 'board' sub-directory.",
sdk_dir.display()
"microkit: error: {description} '{}' does not exist",
path.display()
);
std::process::exit(1);
}
Ok(())
}

let mut available_boards = Vec::new();
for p in fs::read_dir(&boards_path).unwrap() {
let path_buf = p.unwrap().path();
let path = path_buf.as_path();
if path.is_dir() {
available_boards.push(path.file_name().unwrap().to_str().unwrap().to_string());
fn main() -> Result<(), String> {
let sdk = match Sdk::discover() {
Ok(discovered_info) => discovered_info,
Err(err) => {
eprintln!("microkit: error: {err}");
std::process::exit(1);
}
}
available_boards.sort();
};

let env_args: Vec<_> = std::env::args().collect();
let args = match Args::parse(&env_args, &available_boards) {
Ok(result) => result,
let args = match Args::parse(&env_args, &sdk) {
Ok(parsed_arguments) => parsed_arguments,
Err(ArgsError::HelpWanted) => {
argparse::print_help(&available_boards);
argparse::print_help(&sdk);
std::process::exit(0);
}
Err(err) => {
Expand All @@ -145,113 +123,32 @@ fn main() -> Result<(), String> {
}
};

let board_path = boards_path.join(&args.board);
if !board_path.exists() {
eprintln!(
"Error: board path '{}' does not exist.",
board_path.display()
);
std::process::exit(1);
}

let mut available_configs = Vec::new();
for p in fs::read_dir(board_path).unwrap() {
let path_buf = p.unwrap().path();
let path = path_buf.as_path();

if path.file_name().unwrap() == "example" {
continue;
}

if path.is_dir() {
available_configs.push(path.file_name().unwrap().to_str().unwrap().to_string());
}
}
// NB safe unwrap: argparse would already have bailed if the config did not
// exist.
let current_config = sdk.select(&args.board, &args.config).unwrap();

if !available_configs.contains(&args.config.to_string()) {
eprintln!(
"microkit: error: argument --config: invalid choice: '{}' (choose from: {})",
args.config,
available_configs.join(", ")
)
}

let elf_path = sdk_dir
.join("board")
.join(&args.board)
.join(&args.config)
.join("elf");
// the real work begins here
let elf_path = current_config.config_dir.join("elf");
let loader_elf_path = elf_path.join("loader.elf");
let kernel_elf_path = match args.override_kernel {
Some(ref path) => path,
None => &elf_path.join("sel4.elf"),
};
let monitor_elf_path = elf_path.join("monitor.elf");
let capdl_init_elf_path = elf_path.join("initialiser.elf");

let kernel_config_path = sdk_dir
.join("board")
.join(&args.board)
.join(&args.config)
let kernel_config_path = current_config
.config_dir
.join("include/kernel/gen_config.json");

let invocations_all_path = sdk_dir
.join("board")
.join(&args.board)
.join(&args.config)
.join("invocations_all.json");

if !elf_path.exists() {
eprintln!(
"Error: board ELF directory '{}' does not exist",
elf_path.display()
);
std::process::exit(1);
}
if !kernel_elf_path.exists() {
eprintln!(
"Error: kernel ELF '{}' does not exist",
kernel_elf_path.display()
);
std::process::exit(1);
}
if !monitor_elf_path.exists() {
eprintln!(
"Error: monitor ELF '{}' does not exist",
monitor_elf_path.display()
);
std::process::exit(1);
}
if !capdl_init_elf_path.exists() {
eprintln!(
"Error: CapDL initialiser ELF '{}' does not exist",
capdl_init_elf_path.display()
);
std::process::exit(1);
}
if !kernel_config_path.exists() {
eprintln!(
"Error: kernel configuration file '{}' does not exist",
kernel_config_path.display()
);
std::process::exit(1);
}
if !invocations_all_path.exists() {
eprintln!(
"Error: invocations JSON file '{}' does not exist",
invocations_all_path.display()
);
std::process::exit(1);
}
let invocations_all_path = current_config.config_dir.join("invocations_all.json");
bail_if_not_exists("board ELF directory", &elf_path)?;
bail_if_not_exists("kernel ELF", kernel_elf_path)?;
bail_if_not_exists("monitor ELF", &monitor_elf_path)?;
bail_if_not_exists("CapDL initialiser ELF", &capdl_init_elf_path)?;
bail_if_not_exists("kernel configuration file", &kernel_config_path)?;
bail_if_not_exists("invocations JSON file", &invocations_all_path)?;

let system_path = &args.sdf_path;
if !system_path.exists() {
eprintln!(
"Error: system description file '{}' does not exist",
system_path.display()
);
std::process::exit(1);
}
bail_if_not_exists("system description file", system_path)?;

let xml: String = fs::read_to_string(system_path).unwrap();

Expand Down Expand Up @@ -286,23 +183,10 @@ fn main() -> Result<(), String> {
let (device_regions, normal_regions) = match arch {
Arch::X86_64 => (None, None),
_ => {
let kernel_platform_config_path = sdk_dir
.join("board")
.join(&args.board)
.join(&args.config)
.join("platform_gen.json");

if !kernel_platform_config_path.exists() {
eprintln!(
"Error: kernel platform configuration file '{}' does not exist",
kernel_platform_config_path.display()
);
std::process::exit(1);
}

let platform_gen_path = current_config.config_dir.join("platform_gen.json");
bail_if_not_exists("kernel platform configuration file", &platform_gen_path)?;
let kernel_platform_config: PlatformConfig =
serde_json::from_str(&fs::read_to_string(kernel_platform_config_path).unwrap())
.unwrap();
serde_json::from_str(&fs::read_to_string(platform_gen_path).unwrap()).unwrap();

(
Some(kernel_platform_config.devices),
Expand All @@ -312,19 +196,8 @@ fn main() -> Result<(), String> {
};

let object_sizes = {
let object_sizes_path = sdk_dir
.join("board")
.join(args.board)
.join(&args.config)
.join("object_sizes.json");

if !object_sizes_path.exists() {
eprintln!(
"Error: object sizes file '{}' does not exist",
object_sizes_path.display()
);
std::process::exit(1);
}
let object_sizes_path = current_config.config_dir.join("object_sizes.json");
bail_if_not_exists("kernel object sizes file", &object_sizes_path)?;

serde_json::from_str(&fs::read_to_string(object_sizes_path).unwrap()).unwrap()
};
Expand Down
Loading
Loading