88#![ allow( clippy:: assertions_on_constants) ]
99
1010use microkit_tool:: argparse;
11- use microkit_tool:: argparse:: { Args , ArgsError , RequestedImageType } ;
11+ use microkit_tool:: argparse:: { Args , ArgsError } ;
1212use microkit_tool:: capdl:: allocation:: {
1313 simulate_capdl_object_alloc_algorithm, CapDLAllocEmulationErrorLevel ,
1414} ;
@@ -19,15 +19,13 @@ use microkit_tool::elf::ElfFile;
1919use microkit_tool:: loader:: Loader ;
2020use microkit_tool:: report:: write_report;
2121use microkit_tool:: sdf:: { parse, SysMemoryRegion , SysMemoryRegionPaddr } ;
22- use microkit_tool:: sdk:: { AvailableConfig , Sdk } ;
22+ use microkit_tool:: sdk:: Sdk ;
2323use microkit_tool:: sel4:: {
24- emulate_kernel_boot, emulate_kernel_boot_partial, AddressSpaceConstants , Arch , Config ,
25- ObjectSizes , PlatformConfig , RiscvVirtualMemory ,
24+ emulate_kernel_boot, emulate_kernel_boot_partial, Arch , Config , ImageOutputType ,
2625} ;
2726use microkit_tool:: symbols:: patch_symbols;
2827use microkit_tool:: util:: {
29- get_full_path, human_size_strict, json_str, json_str_as_bool, json_str_as_u64, round_down,
30- round_up,
28+ bail_if_not_exists, get_full_path, human_size_strict, round_down, round_up,
3129} ;
3230use microkit_tool:: viper;
3331use microkit_tool:: { DisjointMemoryRegion , MemoryRegion } ;
@@ -45,67 +43,6 @@ const KERNEL_COPY_FILENAME: &str = "sel4.elf";
4543// also copy the 32-bit version that was prepared by build_sdk.py for convenience.
4644const KERNEL32_COPY_FILENAME : & str = "sel4_32.elf" ;
4745
48- enum ImageOutputType {
49- Binary ,
50- Elf ,
51- Uimage ,
52- }
53-
54- impl ImageOutputType {
55- fn default_from_arch_and_board ( arch : & Arch , board_name : & str ) -> Self {
56- match board_name {
57- "ariane" | "cheshire" | "serengeti" => ImageOutputType :: Elf ,
58- _ => match arch {
59- Arch :: Aarch64 => ImageOutputType :: Binary ,
60- Arch :: Riscv64 => ImageOutputType :: Uimage ,
61- Arch :: X86_64 => ImageOutputType :: Elf ,
62- } ,
63- }
64- }
65-
66- /// Resolve the optional user-specified image type with what is the default for the
67- /// platform.
68- /// Not all image types are supported for all platforms, so we check here.
69- fn resolve ( requested : & RequestedImageType , arch : & Arch , board_name : & str ) -> Option < Self > {
70- match requested {
71- RequestedImageType :: Binary => match arch {
72- Arch :: Aarch64 | Arch :: Riscv64 => Some ( Self :: Binary ) ,
73- Arch :: X86_64 => None ,
74- } ,
75- RequestedImageType :: Elf => Some ( Self :: Elf ) ,
76- RequestedImageType :: Uimage => match arch {
77- Arch :: Riscv64 => Some ( Self :: Uimage ) ,
78- Arch :: X86_64 | Arch :: Aarch64 => None ,
79- } ,
80- RequestedImageType :: Unspecified => {
81- Some ( Self :: default_from_arch_and_board ( arch, board_name) )
82- }
83- }
84- }
85- }
86-
87- fn bail_if_not_exists ( description : & ' static str , path : & Path ) -> Result < ( ) , String > {
88- if !path. exists ( ) {
89- eprintln ! (
90- "microkit: error: {description} '{}' does not exist" ,
91- path. display( )
92- ) ;
93- std:: process:: exit ( 1 ) ;
94- }
95- Ok ( ( ) )
96- }
97-
98- fn parse_json_file < T : serde:: de:: DeserializeOwned > (
99- file_name : & str ,
100- file_description : & ' static str ,
101- current_config : & AvailableConfig ,
102- ) -> Result < T , String > {
103- let path = current_config. config_dir . join ( file_name) ;
104- bail_if_not_exists ( file_description, & path) ?;
105- serde_json:: from_str ( & fs:: read_to_string ( & path) . expect ( "Error: Unable to read {path}" ) )
106- . map_err ( |err| format ! ( "Error: Unable to parse {file_name}: {err}" ) )
107- }
108-
10946fn main ( ) -> Result < ( ) , String > {
11047 let sdk = match Sdk :: discover ( ) {
11148 Ok ( discovered_info) => discovered_info,
@@ -134,13 +71,13 @@ fn main() -> Result<(), String> {
13471 std:: process:: exit ( 1 ) ;
13572 }
13673 } ;
74+
13775 args. search_paths . push ( sdk. cwd . clone ( ) ) ;
13876
139- // NB safe unwrap: argparse would already have bailed if the config did not
140- // exist.
141- let current_config = sdk. select ( & args. board , & args. config ) . unwrap ( ) ;
77+ let system_path = & args. sdf_path ;
78+ bail_if_not_exists ( "system description file" , system_path) ?;
14279
143- // the real work begins here
80+ let current_config = sdk . select ( & args . board , & args . config ) . unwrap ( ) ;
14481 let elf_path = current_config. config_dir . join ( "elf" ) ;
14582 let loader_elf_path = elf_path. join ( "loader.elf" ) ;
14683 let kernel_elf_path = match args. override_kernel {
@@ -149,164 +86,39 @@ fn main() -> Result<(), String> {
14986 } ;
15087 let monitor_elf_path = elf_path. join ( "monitor.elf" ) ;
15188 let capdl_init_elf_path = elf_path. join ( "initialiser.elf" ) ;
152- let kernel_config_path = current_config
153- . config_dir
154- . join ( "include/kernel/gen_config.json" ) ;
155- let invocations_all_path = current_config. config_dir . join ( "invocations_all.json" ) ;
89+
15690 bail_if_not_exists ( "board ELF directory" , & elf_path) ?;
15791 bail_if_not_exists ( "kernel ELF" , kernel_elf_path) ?;
15892 bail_if_not_exists ( "monitor ELF" , & monitor_elf_path) ?;
15993 bail_if_not_exists ( "CapDL initialiser ELF" , & capdl_init_elf_path) ?;
160- bail_if_not_exists ( "kernel configuration file" , & kernel_config_path) ?;
161- bail_if_not_exists ( "invocations JSON file" , & invocations_all_path) ?;
162-
163- let system_path = & args. sdf_path ;
164- bail_if_not_exists ( "system description file" , system_path) ?;
16594
16695 let xml: String = fs:: read_to_string ( system_path) . unwrap ( ) ;
16796
168- let kernel_config_json: serde_json:: Value =
169- serde_json:: from_str ( & fs:: read_to_string ( kernel_config_path) . unwrap ( ) ) . unwrap ( ) ;
97+ let kernel_config = Config :: build_kernel_config ( & args, & sdk) . unwrap ( ) ;
17098
171- let invocations_labels: serde_json:: Value =
172- serde_json:: from_str ( & fs:: read_to_string ( invocations_all_path) . unwrap ( ) ) . unwrap ( ) ;
173-
174- let arch = match json_str ( & kernel_config_json, "SEL4_ARCH" ) ? {
175- "aarch64" => Arch :: Aarch64 ,
176- "riscv64" => Arch :: Riscv64 ,
177- "x86_64" => Arch :: X86_64 ,
178- _ => panic ! ( "Unsupported kernel config architecture" ) ,
179- } ;
99+ if kernel_config. arch != Arch :: X86_64 && !loader_elf_path. exists ( ) {
100+ eprintln ! (
101+ "Error: loader ELF '{}' does not exist" ,
102+ loader_elf_path. display( )
103+ ) ;
104+ std:: process:: exit ( 1 ) ;
105+ }
180106
181107 let image_output_type = match ImageOutputType :: resolve (
182108 & args. requested_image_type ,
183- & arch,
109+ & kernel_config . arch ,
184110 args. board . as_str ( ) ,
185111 ) {
186112 Some ( image) => image,
187113 None => {
188114 eprintln ! (
189- "microkit: error: building the output image as '{0}' is unsupported for target architecture '{arch }'" ,
190- args. requested_image_type
115+ "microkit: error: building the output image as '{0}' is unsupported for target architecture '{1 }'" ,
116+ args. requested_image_type, kernel_config . arch
191117 ) ;
192118 std:: process:: exit ( 1 ) ;
193119 }
194120 } ;
195121
196- let ( device_regions, normal_regions) = match arch {
197- Arch :: X86_64 => ( None , None ) ,
198- _ => {
199- let platform_gen_path = current_config. config_dir . join ( "platform_gen.json" ) ;
200- bail_if_not_exists ( "kernel platform configuration file" , & platform_gen_path) ?;
201- let kernel_platform_config: PlatformConfig =
202- serde_json:: from_str ( & fs:: read_to_string ( platform_gen_path) . unwrap ( ) ) . unwrap ( ) ;
203-
204- (
205- Some ( kernel_platform_config. devices ) ,
206- Some ( kernel_platform_config. memory ) ,
207- )
208- }
209- } ;
210-
211- let object_sizes: ObjectSizes = parse_json_file (
212- "object_sizes.json" ,
213- "kernel object sizes file" ,
214- current_config,
215- ) ?;
216-
217- let address_space_constants: AddressSpaceConstants = parse_json_file (
218- "address_space_constants.json" ,
219- "kernel address space constants file" ,
220- current_config,
221- ) ?;
222-
223- let hypervisor = match arch {
224- Arch :: Aarch64 => json_str_as_bool ( & kernel_config_json, "ARM_HYPERVISOR_SUPPORT" ) ?,
225- Arch :: X86_64 => json_str_as_bool ( & kernel_config_json, "VTX" ) ?,
226- // Hypervisor mode is not available on RISC-V
227- _ => false ,
228- } ;
229-
230- let iommu = match arch {
231- Arch :: X86_64 => json_str_as_bool ( & kernel_config_json, "IOMMU" ) ?,
232- _ => false ,
233- } ;
234-
235- let arm_pa_size_bits = match arch {
236- Arch :: Aarch64 => {
237- if json_str_as_bool ( & kernel_config_json, "ARM_PA_SIZE_BITS_40" ) ? {
238- Some ( 40 )
239- } else if json_str_as_bool ( & kernel_config_json, "ARM_PA_SIZE_BITS_44" ) ? {
240- Some ( 44 )
241- } else {
242- panic ! ( "Expected ARM platform to have 40 or 44 physical address bits" )
243- }
244- }
245- Arch :: X86_64 | Arch :: Riscv64 => None ,
246- } ;
247-
248- let arm_smc = match arch {
249- Arch :: Aarch64 => Some ( json_str_as_bool ( & kernel_config_json, "ALLOW_SMC_CALLS" ) ?) ,
250- _ => None ,
251- } ;
252-
253- let kernel_frame_size = match arch {
254- Arch :: Aarch64 => 1 << 12 ,
255- Arch :: Riscv64 => 1 << 21 ,
256- Arch :: X86_64 => 1 << 12 ,
257- } ;
258-
259- let kernel_config = Config {
260- arch,
261- word_size : json_str_as_u64 ( & kernel_config_json, "WORD_SIZE" ) ?,
262- minimum_page_size : 1 << object_sizes. small_page ,
263- paddr_user_device_top : json_str_as_u64 ( & kernel_config_json, "PADDR_USER_DEVICE_TOP" ) ?,
264- kernel_frame_size,
265- init_cnode_bits : json_str_as_u64 ( & kernel_config_json, "ROOT_CNODE_SIZE_BITS" ) ?,
266- cap_address_bits : 64 ,
267- fan_out_limit : json_str_as_u64 ( & kernel_config_json, "RETYPE_FAN_OUT_LIMIT" ) ?,
268- max_num_bootinfo_untypeds : json_str_as_u64 (
269- & kernel_config_json,
270- "MAX_NUM_BOOTINFO_UNTYPED_CAPS" ,
271- ) ?,
272- hypervisor,
273- iommu,
274- benchmark : args. config == "benchmark" ,
275- num_cores : if json_str_as_bool ( & kernel_config_json, "ENABLE_SMP_SUPPORT" ) ? {
276- json_str_as_u64 ( & kernel_config_json, "MAX_NUM_NODES" ) ?
277- . try_into ( )
278- . expect ( "number of cores fits in u8" )
279- } else {
280- 1
281- } ,
282- num_domains : json_str_as_u64 ( & kernel_config_json, "NUM_DOMAINS" ) ?
283- . try_into ( )
284- . unwrap ( ) ,
285- num_domain_schedules : json_str_as_u64 ( & kernel_config_json, "NUM_DOMAIN_SCHEDULES" ) ?,
286- fpu : json_str_as_bool ( & kernel_config_json, "HAVE_FPU" ) ?,
287- arm_pa_size_bits,
288- arm_smc,
289- riscv_pt_levels : Some ( RiscvVirtualMemory :: Sv39 ) ,
290- invocations_labels,
291- device_regions,
292- normal_regions,
293- object_sizes,
294- address_space_constants,
295- } ;
296-
297- if kernel_config. arch != Arch :: X86_64 && !loader_elf_path. exists ( ) {
298- eprintln ! (
299- "Error: loader ELF '{}' does not exist" ,
300- loader_elf_path. display( )
301- ) ;
302- std:: process:: exit ( 1 ) ;
303- }
304-
305- assert ! (
306- kernel_config. word_size == 64 ,
307- "Microkit tool has various assumptions about the word size being 64-bits."
308- ) ;
309-
310122 let mut system = match parse (
311123 system_path. as_path ( ) ,
312124 & xml,
0 commit comments