Skip to content

Commit 00f86ca

Browse files
zaklogicianmidnightveil
authored andcommitted
tool: migrate to new environment info gathering
This pulls out the SDK discovery into a separate file and parsing steps. Signed-off-by: Zoltan A. Kocsis <11808286+zaklogician@users.noreply.github.com>
1 parent 31ee14b commit 00f86ca

4 files changed

Lines changed: 333 additions & 173 deletions

File tree

tool/microkit/src/argparse.rs

Lines changed: 41 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
// SPDX-License-Identifier: BSD-2-Clause
55
//
66

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

15-
pub fn print_help(available_boards: &[String]) {
16+
pub fn print_help(sdk: &Sdk) {
1617
print_usage();
1718
println!("\npositional arguments:");
1819
println!(" system");
@@ -22,7 +23,10 @@ pub fn print_help(available_boards: &[String]) {
2223
println!(" -r, --report REPORT");
2324
println!(" --image-type {{binary,elf,uimage}}");
2425
println!(" --override-kernel KERNEL (for debugging purposes)");
25-
println!(" --board {}", available_boards.join("\n "));
26+
println!(
27+
" --board {}",
28+
sdk.available_board_names().join("\n ")
29+
);
2630
println!(" --config CONFIG");
2731
println!(" --capdl-json CAPDL_SPEC (JSON format)");
2832
println!(" --search-path [SEARCH_PATH ...]");
@@ -73,11 +77,25 @@ pub struct Args {
7377

7478
#[derive(Debug)]
7579
pub enum ArgsError {
76-
InvalidImageTypeParameter { parameter: String },
77-
InvalidBoardParameter { parameter: String },
78-
MissingParameter { parent_argument: &'static str },
79-
MissingRequiredArguments { args: Vec<&'static str> },
80-
UnrecognizedArgument { arg: String },
80+
InvalidImageTypeParameter {
81+
parameter: String,
82+
},
83+
InvalidBoardParameter {
84+
parameter: String,
85+
},
86+
InvalidConfigParameter {
87+
parameter: String,
88+
choices: Vec<String>,
89+
},
90+
MissingParameter {
91+
parent_argument: &'static str,
92+
},
93+
MissingRequiredArguments {
94+
args: Vec<&'static str>,
95+
},
96+
UnrecognizedArgument {
97+
arg: String,
98+
},
8199
HelpWanted,
82100
}
83101

@@ -90,6 +108,13 @@ impl fmt::Display for ArgsError {
90108
Self::InvalidBoardParameter { parameter } => {
91109
write!(f, "argument --board: unknown parameter '{parameter}'")
92110
}
111+
Self::InvalidConfigParameter { parameter, choices } => {
112+
write!(
113+
f,
114+
"argument --config: invalid choice '{parameter}' (choose from: {})",
115+
choices.join(", ")
116+
)
117+
}
93118
Self::MissingParameter { parent_argument } => {
94119
write!(f, "argument {parent_argument}: expected one parameter")
95120
}
@@ -136,7 +161,7 @@ where
136161
}
137162

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

142167
let mut output_path = PathBuf::from("loader.img");
@@ -163,7 +188,7 @@ impl Args {
163188
}
164189
"--board" => {
165190
let board_param = consume_parameter(&mut args, "--board")?;
166-
if !available_boards.contains(&board_param) {
191+
if !sdk.available_boards_contains(&board_param) {
167192
return Err(ArgsError::InvalidBoardParameter {
168193
parameter: board_param,
169194
});
@@ -224,6 +249,13 @@ impl Args {
224249
let config = config.unwrap();
225250
let sdf_path = sdf_path.unwrap();
226251

252+
if sdk.select(&board, &config).is_none() {
253+
return Err(ArgsError::InvalidConfigParameter {
254+
parameter: config,
255+
choices: sdk.available_config_names_for(&board),
256+
});
257+
}
258+
227259
Ok(Self {
228260
sdf_path,
229261
board,

tool/microkit/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ pub mod elf;
1818
pub mod loader;
1919
pub mod report;
2020
pub mod sdf;
21+
pub mod sdk;
2122
pub mod sel4;
2223
pub mod symbols;
2324
pub mod uimage;

tool/microkit/src/main.rs

Lines changed: 37 additions & 164 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ use microkit_tool::elf::ElfFile;
1919
use microkit_tool::loader::Loader;
2020
use microkit_tool::report::write_report;
2121
use microkit_tool::sdf::{parse, SysMemoryRegion, SysMemoryRegionPaddr};
22+
use microkit_tool::sdk::Sdk;
2223
use microkit_tool::sel4::{
2324
emulate_kernel_boot, emulate_kernel_boot_partial, Arch, Config, PlatformConfig,
2425
RiscvVirtualMemory,
@@ -82,54 +83,31 @@ impl ImageOutputType {
8283
}
8384
}
8485

85-
fn main() -> Result<(), String> {
86-
let exe_path = std::env::current_exe().unwrap();
87-
let sdk_env = std::env::var("MICROKIT_SDK");
88-
let sdk_dir = match sdk_env {
89-
Ok(ref value) => Path::new(value),
90-
Err(err) => match err {
91-
// If there is no MICROKIT_SDK explicitly set, use the one that the binary is in.
92-
std::env::VarError::NotPresent => exe_path.parent().unwrap().parent().unwrap(),
93-
_ => {
94-
return Err(format!(
95-
"Could not read MICROKIT_SDK environment variable: {err}"
96-
))
97-
}
98-
},
99-
};
100-
101-
if !sdk_dir.exists() {
102-
eprintln!(
103-
"Error: SDK directory '{}' does not exist.",
104-
sdk_dir.display()
105-
);
106-
std::process::exit(1);
107-
}
108-
109-
let boards_path = sdk_dir.join("board");
110-
if !boards_path.exists() || !boards_path.is_dir() {
86+
fn bail_if_not_exists(description: &'static str, path: &Path) -> Result<(), String> {
87+
if !path.exists() {
11188
eprintln!(
112-
"Error: SDK directory '{}' does not have a 'board' sub-directory.",
113-
sdk_dir.display()
89+
"microkit: error: {description} '{}' does not exist",
90+
path.display()
11491
);
11592
std::process::exit(1);
11693
}
94+
Ok(())
95+
}
11796

118-
let mut available_boards = Vec::new();
119-
for p in fs::read_dir(&boards_path).unwrap() {
120-
let path_buf = p.unwrap().path();
121-
let path = path_buf.as_path();
122-
if path.is_dir() {
123-
available_boards.push(path.file_name().unwrap().to_str().unwrap().to_string());
97+
fn main() -> Result<(), String> {
98+
let sdk = match Sdk::discover() {
99+
Ok(discovered_info) => discovered_info,
100+
Err(err) => {
101+
eprintln!("microkit: error: {err}");
102+
std::process::exit(1);
124103
}
125-
}
126-
available_boards.sort();
104+
};
127105

128106
let env_args: Vec<_> = std::env::args().collect();
129-
let mut args = match Args::parse(&env_args, &available_boards) {
130-
Ok(result) => result,
107+
let mut args = match Args::parse(&env_args, &sdk) {
108+
Ok(parsed_arguments) => parsed_arguments,
131109
Err(ArgsError::HelpWanted) => {
132-
argparse::print_help(&available_boards);
110+
argparse::print_help(&sdk);
133111
std::process::exit(0);
134112
}
135113
Err(err) => {
@@ -146,113 +124,32 @@ fn main() -> Result<(), String> {
146124
};
147125
args.search_paths.push(std::env::current_dir().unwrap());
148126

149-
let board_path = boards_path.join(&args.board);
150-
if !board_path.exists() {
151-
eprintln!(
152-
"Error: board path '{}' does not exist.",
153-
board_path.display()
154-
);
155-
std::process::exit(1);
156-
}
157-
158-
let mut available_configs = Vec::new();
159-
for p in fs::read_dir(board_path).unwrap() {
160-
let path_buf = p.unwrap().path();
161-
let path = path_buf.as_path();
162-
163-
if path.file_name().unwrap() == "example" {
164-
continue;
165-
}
166-
167-
if path.is_dir() {
168-
available_configs.push(path.file_name().unwrap().to_str().unwrap().to_string());
169-
}
170-
}
127+
// NB safe unwrap: argparse would already have bailed if the config did not
128+
// exist.
129+
let current_config = sdk.select(&args.board, &args.config).unwrap();
171130

172-
if !available_configs.contains(&args.config.to_string()) {
173-
eprintln!(
174-
"microkit: error: argument --config: invalid choice: '{}' (choose from: {})",
175-
args.config,
176-
available_configs.join(", ")
177-
)
178-
}
179-
180-
let elf_path = sdk_dir
181-
.join("board")
182-
.join(&args.board)
183-
.join(&args.config)
184-
.join("elf");
131+
// the real work begins here
132+
let elf_path = current_config.config_dir.join("elf");
185133
let loader_elf_path = elf_path.join("loader.elf");
186134
let kernel_elf_path = match args.override_kernel {
187135
Some(ref path) => path,
188136
None => &elf_path.join("sel4.elf"),
189137
};
190138
let monitor_elf_path = elf_path.join("monitor.elf");
191139
let capdl_init_elf_path = elf_path.join("initialiser.elf");
192-
193-
let kernel_config_path = sdk_dir
194-
.join("board")
195-
.join(&args.board)
196-
.join(&args.config)
140+
let kernel_config_path = current_config
141+
.config_dir
197142
.join("include/kernel/gen_config.json");
198-
199-
let invocations_all_path = sdk_dir
200-
.join("board")
201-
.join(&args.board)
202-
.join(&args.config)
203-
.join("invocations_all.json");
204-
205-
if !elf_path.exists() {
206-
eprintln!(
207-
"Error: board ELF directory '{}' does not exist",
208-
elf_path.display()
209-
);
210-
std::process::exit(1);
211-
}
212-
if !kernel_elf_path.exists() {
213-
eprintln!(
214-
"Error: kernel ELF '{}' does not exist",
215-
kernel_elf_path.display()
216-
);
217-
std::process::exit(1);
218-
}
219-
if !monitor_elf_path.exists() {
220-
eprintln!(
221-
"Error: monitor ELF '{}' does not exist",
222-
monitor_elf_path.display()
223-
);
224-
std::process::exit(1);
225-
}
226-
if !capdl_init_elf_path.exists() {
227-
eprintln!(
228-
"Error: CapDL initialiser ELF '{}' does not exist",
229-
capdl_init_elf_path.display()
230-
);
231-
std::process::exit(1);
232-
}
233-
if !kernel_config_path.exists() {
234-
eprintln!(
235-
"Error: kernel configuration file '{}' does not exist",
236-
kernel_config_path.display()
237-
);
238-
std::process::exit(1);
239-
}
240-
if !invocations_all_path.exists() {
241-
eprintln!(
242-
"Error: invocations JSON file '{}' does not exist",
243-
invocations_all_path.display()
244-
);
245-
std::process::exit(1);
246-
}
143+
let invocations_all_path = current_config.config_dir.join("invocations_all.json");
144+
bail_if_not_exists("board ELF directory", &elf_path)?;
145+
bail_if_not_exists("kernel ELF", kernel_elf_path)?;
146+
bail_if_not_exists("monitor ELF", &monitor_elf_path)?;
147+
bail_if_not_exists("CapDL initialiser ELF", &capdl_init_elf_path)?;
148+
bail_if_not_exists("kernel configuration file", &kernel_config_path)?;
149+
bail_if_not_exists("invocations JSON file", &invocations_all_path)?;
247150

248151
let system_path = &args.sdf_path;
249-
if !system_path.exists() {
250-
eprintln!(
251-
"Error: system description file '{}' does not exist",
252-
system_path.display()
253-
);
254-
std::process::exit(1);
255-
}
152+
bail_if_not_exists("system description file", system_path)?;
256153

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

@@ -287,23 +184,10 @@ fn main() -> Result<(), String> {
287184
let (device_regions, normal_regions) = match arch {
288185
Arch::X86_64 => (None, None),
289186
_ => {
290-
let kernel_platform_config_path = sdk_dir
291-
.join("board")
292-
.join(&args.board)
293-
.join(&args.config)
294-
.join("platform_gen.json");
295-
296-
if !kernel_platform_config_path.exists() {
297-
eprintln!(
298-
"Error: kernel platform configuration file '{}' does not exist",
299-
kernel_platform_config_path.display()
300-
);
301-
std::process::exit(1);
302-
}
303-
187+
let platform_gen_path = current_config.config_dir.join("platform_gen.json");
188+
bail_if_not_exists("kernel platform configuration file", &platform_gen_path)?;
304189
let kernel_platform_config: PlatformConfig =
305-
serde_json::from_str(&fs::read_to_string(kernel_platform_config_path).unwrap())
306-
.unwrap();
190+
serde_json::from_str(&fs::read_to_string(platform_gen_path).unwrap()).unwrap();
307191

308192
(
309193
Some(kernel_platform_config.devices),
@@ -313,19 +197,8 @@ fn main() -> Result<(), String> {
313197
};
314198

315199
let object_sizes = {
316-
let object_sizes_path = sdk_dir
317-
.join("board")
318-
.join(args.board)
319-
.join(&args.config)
320-
.join("object_sizes.json");
321-
322-
if !object_sizes_path.exists() {
323-
eprintln!(
324-
"Error: object sizes file '{}' does not exist",
325-
object_sizes_path.display()
326-
);
327-
std::process::exit(1);
328-
}
200+
let object_sizes_path = current_config.config_dir.join("object_sizes.json");
201+
bail_if_not_exists("kernel object sizes file", &object_sizes_path)?;
329202

330203
serde_json::from_str(&fs::read_to_string(object_sizes_path).unwrap()).unwrap()
331204
};

0 commit comments

Comments
 (0)