@@ -35,6 +35,9 @@ const ENV_VAR_OVMF_CODE: &str = "OVMF_CODE";
3535/// Environment variable for overriding the path of the OVMF vars file.
3636const ENV_VAR_OVMF_VARS : & str = "OVMF_VARS" ;
3737
38+ /// Environment variable for overriding the path of the OVMF shell file.
39+ const ENV_VAR_OVMF_SHELL : & str = "OVMF_SHELL" ;
40+
3841/// Download `url` and return the raw data.
3942fn download_url ( url : & str ) -> Result < Vec < u8 > > {
4043 let agent: Agent = ureq:: AgentBuilder :: new ( )
@@ -145,13 +148,22 @@ fn update_prebuilt() -> Result<PathBuf> {
145148enum OvmfFileType {
146149 Code ,
147150 Vars ,
151+ Shell ,
148152}
149153
150154impl OvmfFileType {
151155 fn as_str ( & self ) -> & ' static str {
152156 match self {
153157 Self :: Code => "code" ,
154158 Self :: Vars => "vars" ,
159+ Self :: Shell => "shell" ,
160+ }
161+ }
162+
163+ fn extension ( & self ) -> & ' static str {
164+ match self {
165+ Self :: Code | Self :: Vars => "fd" ,
166+ Self :: Shell => "efi" ,
155167 }
156168 }
157169
@@ -171,6 +183,10 @@ impl OvmfFileType {
171183 opt_path = & opt. ovmf_vars ;
172184 var_name = ENV_VAR_OVMF_VARS ;
173185 }
186+ Self :: Shell => {
187+ opt_path = & None ;
188+ var_name = ENV_VAR_OVMF_SHELL ;
189+ }
174190 }
175191 if let Some ( path) = opt_path {
176192 Some ( path. clone ( ) )
@@ -183,6 +199,7 @@ impl OvmfFileType {
183199struct OvmfPaths {
184200 code : PathBuf ,
185201 vars : PathBuf ,
202+ shell : PathBuf ,
186203}
187204
188205impl OvmfPaths {
@@ -209,7 +226,11 @@ impl OvmfPaths {
209226 } else {
210227 let prebuilt_dir = update_prebuilt ( ) ?;
211228
212- Ok ( prebuilt_dir. join ( format ! ( "{arch}/{}.fd" , file_type. as_str( ) ) ) )
229+ Ok ( prebuilt_dir. join ( format ! (
230+ "{arch}/{}.{}" ,
231+ file_type. as_str( ) ,
232+ file_type. extension( )
233+ ) ) )
213234 }
214235 }
215236
@@ -218,8 +239,9 @@ impl OvmfPaths {
218239 fn find ( opt : & QemuOpt , arch : UefiArch ) -> Result < Self > {
219240 let code = Self :: find_ovmf_file ( OvmfFileType :: Code , opt, arch) ?;
220241 let vars = Self :: find_ovmf_file ( OvmfFileType :: Vars , opt, arch) ?;
242+ let shell = Self :: find_ovmf_file ( OvmfFileType :: Shell , opt, arch) ?;
221243
222- Ok ( Self { code, vars } )
244+ Ok ( Self { code, vars, shell } )
223245 }
224246}
225247
@@ -362,7 +384,7 @@ fn process_qemu_io(mut monitor_io: Io, mut serial_io: Io, tmp_dir: &Path) -> Res
362384}
363385
364386/// Create an EFI boot directory to pass into QEMU.
365- fn build_esp_dir ( opt : & QemuOpt ) -> Result < PathBuf > {
387+ fn build_esp_dir ( opt : & QemuOpt , ovmf_paths : & OvmfPaths ) -> Result < PathBuf > {
366388 let build_mode = if opt. build_mode . release {
367389 "release"
368390 } else {
@@ -372,21 +394,36 @@ fn build_esp_dir(opt: &QemuOpt) -> Result<PathBuf> {
372394 . join ( opt. target . as_triple ( ) )
373395 . join ( build_mode) ;
374396 let esp_dir = build_dir. join ( "esp" ) ;
397+
398+ // Create boot dir.
375399 let boot_dir = esp_dir. join ( "EFI" ) . join ( "Boot" ) ;
376- let built_file = if let Some ( example) = & opt. example {
377- build_dir. join ( "examples" ) . join ( format ! ( "{example}.efi" ) )
378- } else {
379- build_dir. join ( "uefi-test-runner.efi" )
380- } ;
381- let output_file = match * opt. target {
400+ if !boot_dir. exists ( ) {
401+ fs_err:: create_dir_all ( & boot_dir) ?;
402+ }
403+
404+ let boot_file_name = match * opt. target {
382405 UefiArch :: AArch64 => "BootAA64.efi" ,
383406 UefiArch :: IA32 => "BootIA32.efi" ,
384407 UefiArch :: X86_64 => "BootX64.efi" ,
385408 } ;
386- if !boot_dir. exists ( ) {
387- fs_err:: create_dir_all ( & boot_dir) ?;
388- }
389- fs_err:: copy ( built_file, boot_dir. join ( output_file) ) ?;
409+
410+ if let Some ( example) = & opt. example {
411+ // Launch examples directly.
412+ let src_path = build_dir. join ( "examples" ) . join ( format ! ( "{example}.efi" ) ) ;
413+ fs_err:: copy ( src_path, boot_dir. join ( boot_file_name) ) ?;
414+ } else {
415+ // For the test-runner, launch the `shell_launcher` binary first. That
416+ // will then launch the UEFI shell, and run the `uefi-test-runner`
417+ // inside the shell. This allows the test-runner to test protocols that
418+ // use the shell.
419+ let shell_launcher = build_dir. join ( "shell_launcher.efi" ) ;
420+ fs_err:: copy ( shell_launcher, boot_dir. join ( boot_file_name) ) ?;
421+
422+ fs_err:: copy ( & ovmf_paths. shell , boot_dir. join ( "shell.efi" ) ) ?;
423+
424+ let test_runner = build_dir. join ( "uefi-test-runner.efi" ) ;
425+ fs_err:: copy ( test_runner, boot_dir. join ( "test_runner.efi" ) ) ?;
426+ } ;
390427
391428 Ok ( esp_dir)
392429}
@@ -413,8 +450,6 @@ impl Drop for ChildWrapper {
413450}
414451
415452pub fn run_qemu ( arch : UefiArch , opt : & QemuOpt ) -> Result < ( ) > {
416- let esp_dir = build_esp_dir ( opt) ?;
417-
418453 let qemu_exe = match arch {
419454 UefiArch :: AArch64 => "qemu-system-aarch64" ,
420455 UefiArch :: IA32 | UefiArch :: X86_64 => "qemu-system-x86_64" ,
@@ -516,6 +551,7 @@ pub fn run_qemu(arch: UefiArch, opt: &QemuOpt) -> Result<()> {
516551 // Mount a local directory as a FAT partition.
517552 cmd. arg ( "-drive" ) ;
518553 let mut drive_arg = OsString :: from ( "format=raw,file=fat:rw:" ) ;
554+ let esp_dir = build_esp_dir ( opt, & ovmf_paths) ?;
519555 drive_arg. push ( esp_dir) ;
520556 cmd. arg ( drive_arg) ;
521557
0 commit comments