@@ -43,7 +43,7 @@ use tokio::fs;
4343use crate :: {
4444 Tool ,
4545 run:: {
46- output_matcher:: { ByteStreamMatcher , StreamMatch , StreamMatchKind } ,
46+ output_matcher:: { ByteStreamMatcher , StreamMatch , StreamMatchKind , compile_regexes , print_match_event } ,
4747 ovmf_prebuilt:: { Arch , FileType , Prebuilt , Source } ,
4848 shell_init:: { ShellAutoInitMatcher , normalize_shell_init_config, spawn_delayed_send} ,
4949 } ,
@@ -106,6 +106,7 @@ pub struct RunQemuArgs {
106106
107107#[ derive( Debug , Clone , Default ) ]
108108struct QemuDefaultOverrides {
109+ to_bin : Option < bool > ,
109110 args : Vec < String > ,
110111 success_regex : Vec < String > ,
111112 fail_regex : Vec < String > ,
@@ -126,13 +127,14 @@ struct QemuDefaultOverrides {
126127/// Returns an error if QEMU fails to start or exits with an error.
127128impl Tool {
128129 pub async fn run_qemu ( & mut self , args : RunQemuArgs ) -> anyhow:: Result < ( ) > {
129- self . run_qemu_with_more_default_args ( args, vec ! [ ] , vec ! [ ] , vec ! [ ] )
130+ self . run_qemu_with_more_default_args ( args, None , vec ! [ ] , vec ! [ ] , vec ! [ ] )
130131 . await
131132 }
132133
133134 pub async fn run_qemu_with_more_default_args (
134135 & mut self ,
135136 run_args : RunQemuArgs ,
137+ to_bin : Option < bool > ,
136138 args : Vec < String > ,
137139 success_regex : Vec < String > ,
138140 fail_regex : Vec < String > ,
@@ -141,6 +143,7 @@ impl Tool {
141143 self ,
142144 run_args,
143145 QemuDefaultOverrides {
146+ to_bin,
144147 args,
145148 success_regex,
146149 fail_regex,
@@ -168,30 +171,32 @@ async fn load_or_create_qemu_config(
168171
169172 info ! ( "Using QEMU config file: {}" , config_path. display( ) ) ;
170173
171- if config_path. exists ( ) {
172- let config_content = fs:: read_to_string ( & config_path)
173- . await
174- . with_path ( "failed to read file" , & config_path) ?;
175- let mut config: QemuConfig = toml:: from_str ( & config_content)
176- . with_context ( || format ! ( "failed to parse QEMU config: {}" , config_path. display( ) ) ) ?;
177- config. normalize ( & format ! ( "QEMU config {}" , config_path. display( ) ) ) ?;
178- return Ok ( config) ;
179- }
180-
181- let mut config = build_default_qemu_config ( tool. ctx . arch , overrides) ;
182- config. normalize ( & format ! ( "QEMU config {}" , config_path. display( ) ) ) ?;
183- fs:: write ( & config_path, toml:: to_string_pretty ( & config) ?)
184- . await
185- . with_path ( "failed to write file" , & config_path) ?;
186- Ok ( config)
174+ let config_content = match fs:: read_to_string ( & config_path) . await {
175+ Ok ( content) => {
176+ let mut config: QemuConfig = toml:: from_str ( & content)
177+ . with_context ( || format ! ( "failed to parse QEMU config: {}" , config_path. display( ) ) ) ?;
178+ config. normalize ( & format ! ( "QEMU config {}" , config_path. display( ) ) ) ?;
179+ return Ok ( config) ;
180+ }
181+ Err ( e) if e. kind ( ) == io:: ErrorKind :: NotFound => {
182+ let mut config = build_default_qemu_config ( tool. ctx . arch , overrides) ;
183+ config. normalize ( & format ! ( "QEMU config {}" , config_path. display( ) ) ) ?;
184+ fs:: write ( & config_path, toml:: to_string_pretty ( & config) ?)
185+ . await
186+ . with_path ( "failed to write file" , & config_path) ?;
187+ config
188+ }
189+ Err ( e) => return Err ( e. into ( ) ) ,
190+ } ;
191+ Ok ( config_content)
187192}
188193
189194fn build_default_qemu_config (
190195 arch : Option < Architecture > ,
191196 overrides : QemuDefaultOverrides ,
192197) -> QemuConfig {
193198 let mut config = QemuConfig {
194- to_bin : true ,
199+ to_bin : overrides . to_bin . unwrap_or ( true ) ,
195200 success_regex : overrides. success_regex ,
196201 fail_regex : overrides. fail_regex ,
197202 ..Default :: default ( )
@@ -222,7 +227,6 @@ async fn run_qemu_with_config(
222227 let mut runner = QemuRunner {
223228 tool,
224229 config,
225- args : vec ! [ ] ,
226230 dtbdump : run_args. dtb_dump ,
227231 success_regex : vec ! [ ] ,
228232 fail_regex : vec ! [ ] ,
@@ -233,7 +237,6 @@ async fn run_qemu_with_config(
233237struct QemuRunner < ' a > {
234238 tool : & ' a mut Tool ,
235239 config : QemuConfig ,
236- args : Vec < String > ,
237240 dtbdump : bool ,
238241 success_regex : Vec < regex:: Regex > ,
239242 fail_regex : Vec < regex:: Regex > ,
@@ -262,7 +265,7 @@ impl Drop for RawModeGuard {
262265
263266impl QemuRunner < ' _ > {
264267 async fn run ( & mut self ) -> anyhow:: Result < ( ) > {
265- self . preper_regex ( ) ?;
268+ self . prepare_regex ( ) ?;
266269
267270 if self . config . to_bin {
268271 self . tool . objcopy_output_bin ( ) ?;
@@ -281,14 +284,6 @@ impl QemuRunner<'_> {
281284
282285 let mut need_machine = true ;
283286
284- for arg in & self . config . args {
285- if arg == "-machine" || arg == "-M" {
286- need_machine = false ;
287- }
288-
289- self . args . push ( arg. clone ( ) ) ;
290- }
291-
292287 #[ allow( unused_mut) ]
293288 let mut qemu_executable = format ! ( "qemu-system-{}" , arch) ;
294289
@@ -308,6 +303,9 @@ impl QemuRunner<'_> {
308303 let mut cmd = self . tool . command ( & qemu_executable) ;
309304
310305 for arg in & self . config . args {
306+ if arg == "-machine" || arg == "-M" {
307+ need_machine = false ;
308+ }
311309 cmd. arg ( arg) ;
312310 }
313311
@@ -549,7 +547,7 @@ impl QemuRunner<'_> {
549547 let _ = std:: io:: stdout ( ) . flush ( ) ;
550548
551549 if let Some ( matched) = matcher. observe_byte ( byte) {
552- Self :: print_match_event ( & matched) ;
550+ print_match_event ( & matched) ;
553551 }
554552
555553 if let Some ( shell_auto_init) = shell_auto_init. as_mut ( )
@@ -606,23 +604,6 @@ impl QemuRunner<'_> {
606604 } ) ;
607605 }
608606
609- fn print_match_event ( matched : & StreamMatch ) {
610- match matched. kind {
611- StreamMatchKind :: Success => println ! (
612- "{}" ,
613- format!(
614- "\n === SUCCESS PATTERN MATCHED: {} ===" ,
615- matched. matched_regex
616- )
617- . green( )
618- ) ,
619- StreamMatchKind :: Fail => println ! (
620- "{}" ,
621- format!( "\n === FAIL PATTERN MATCHED: {} ===" , matched. matched_regex) . red( )
622- ) ,
623- }
624- }
625-
626607 fn kill_qemu ( child : & mut Child ) -> anyhow:: Result < ( ) > {
627608 if let Err ( err) = child. kill ( )
628609 && err. kind ( ) != ErrorKind :: InvalidInput
@@ -646,23 +627,10 @@ impl QemuRunner<'_> {
646627 Ok ( ( ) )
647628 }
648629
649- fn preper_regex ( & mut self ) -> anyhow:: Result < ( ) > {
650- // Prepare regex patterns if needed
651- // Compile success regex patterns
652- for pattern in self . config . success_regex . iter ( ) {
653- // Compile and store the regex
654- let regex =
655- regex:: Regex :: new ( pattern) . map_err ( |e| anyhow ! ( "success regex error: {e}" ) ) ?;
656- self . success_regex . push ( regex) ;
657- }
658-
659- // Compile fail regex patterns
660- for pattern in self . config . fail_regex . iter ( ) {
661- // Compile and store the regex
662- let regex = regex:: Regex :: new ( pattern) . map_err ( |e| anyhow ! ( "fail regex error: {e}" ) ) ?;
663- self . fail_regex . push ( regex) ;
664- }
665-
630+ fn prepare_regex ( & mut self ) -> anyhow:: Result < ( ) > {
631+ let ( success, fail) = compile_regexes ( & self . config . success_regex , & self . config . fail_regex ) ?;
632+ self . success_regex = success;
633+ self . fail_regex = fail;
666634 Ok ( ( ) )
667635 }
668636}
@@ -790,11 +758,13 @@ mod tests {
790758 let config = build_default_qemu_config (
791759 Some ( Architecture :: X86_64 ) ,
792760 QemuDefaultOverrides {
761+ to_bin : Some ( false ) ,
793762 args : vec ! [ "-smp" . into( ) , "2" . into( ) ] ,
794763 ..Default :: default ( )
795764 } ,
796765 ) ;
797766
767+ assert ! ( !config. to_bin) ;
798768 assert_eq ! ( config. args, vec![ "-nographic" , "-smp" , "2" ] ) ;
799769 }
800770
0 commit comments