@@ -14,67 +14,206 @@ use std::process::{Child, Command, Stdio};
1414use std:: { env, thread} ;
1515use tempfile:: TempDir ;
1616
17+ #[ derive( Clone , Copy , Debug ) ]
18+ enum OvmfFileType {
19+ Code ,
20+ Vars ,
21+ }
22+
23+ impl OvmfFileType {
24+ fn as_str ( & self ) -> & ' static str {
25+ match self {
26+ Self :: Code => "code" ,
27+ Self :: Vars => "vars" ,
28+ }
29+ }
30+ }
31+
1732struct OvmfPaths {
1833 code : PathBuf ,
1934 vars : PathBuf ,
2035}
2136
2237impl OvmfPaths {
23- fn from_dir ( dir : & Path , arch : UefiArch ) -> Self {
38+ fn get_path ( & self , file_type : OvmfFileType ) -> & Path {
39+ match file_type {
40+ OvmfFileType :: Code => & self . code ,
41+ OvmfFileType :: Vars => & self . vars ,
42+ }
43+ }
44+
45+ /// Get the Arch Linux OVMF paths for the given guest arch.
46+ fn arch_linux ( arch : UefiArch ) -> Self {
2447 match arch {
48+ // Package "edk2-armvirt".
2549 UefiArch :: AArch64 => Self {
26- code : dir . join ( "QEMU_EFI-pflash.raw" ) ,
27- vars : dir . join ( "vars-template-pflash.raw" ) ,
50+ code : "/usr/share/edk2-armvirt/aarch64/QEMU_CODE.fd" . into ( ) ,
51+ vars : "/usr/share/edk2-armvirt/aarch64/QEMU_VARS.fd" . into ( ) ,
2852 } ,
53+ // Package "edk2-ovmf".
2954 UefiArch :: IA32 => Self {
30- code : dir . join ( "OVMF32_CODE .fd") ,
31- vars : dir . join ( "OVMF32_VARS .fd") ,
55+ code : "/usr/share/edk2-ovmf/ia32/OVMF_CODE .fd". into ( ) ,
56+ vars : "/usr/share/edk2-ovmf/ia32/OVMF_VARS .fd". into ( ) ,
3257 } ,
58+ // Package "edk2-ovmf".
3359 UefiArch :: X86_64 => Self {
34- code : dir . join ( " OVMF_CODE.fd") ,
35- vars : dir . join ( " OVMF_VARS.fd") ,
60+ code : "/usr/share/edk2-ovmf/x64/ OVMF_CODE.fd". into ( ) ,
61+ vars : "/usr/share/edk2-ovmf/x64/ OVMF_VARS.fd". into ( ) ,
3662 } ,
3763 }
3864 }
3965
40- fn exists ( & self ) -> bool {
41- self . code . exists ( ) && self . vars . exists ( )
66+ /// Get the CentOS OVMF paths for the given guest arch.
67+ fn centos_linux ( arch : UefiArch ) -> Option < Self > {
68+ match arch {
69+ // Package "edk2-aarch64".
70+ UefiArch :: AArch64 => Some ( Self {
71+ code : "/usr/share/edk2/aarch64/QEMU_EFI-pflash.raw" . into ( ) ,
72+ vars : "/usr/share/edk2/aarch64/vars-template-pflash.raw" . into ( ) ,
73+ } ) ,
74+ // There's no official ia32 package.
75+ UefiArch :: IA32 => None ,
76+ // Package "edk2-ovmf".
77+ UefiArch :: X86_64 => Some ( Self {
78+ // Use the `.secboot` variant because the CentOS package
79+ // doesn't have a plain "OVMF_CODE.fd".
80+ code : "/usr/share/edk2/ovmf/OVMF_CODE.secboot.fd" . into ( ) ,
81+ vars : "/usr/share/edk2/ovmf/OVMF_VARS.fd" . into ( ) ,
82+ } ) ,
83+ }
4284 }
4385
44- /// Find path to OVMF files.
45- fn find ( opt : & QemuOpt , arch : UefiArch ) -> Result < Self > {
46- // If the path is specified in the settings, use it.
47- if let Some ( ovmf_dir) = & opt. ovmf_dir {
48- let ovmf_paths = Self :: from_dir ( ovmf_dir, arch) ;
49- if ovmf_paths. exists ( ) {
50- return Ok ( ovmf_paths) ;
51- }
52- bail ! ( "OVMF files not found in {}" , ovmf_dir. display( ) ) ;
86+ /// Get the Debian OVMF paths for the given guest arch. These paths
87+ /// also work on Ubuntu.
88+ fn debian_linux ( arch : UefiArch ) -> Self {
89+ match arch {
90+ // Package "qemu-efi-aarch64".
91+ UefiArch :: AArch64 => Self {
92+ code : "/usr/share/AAVMF/AAVMF_CODE.fd" . into ( ) ,
93+ vars : "/usr/share/AAVMF/AAVMF_VARS.fd" . into ( ) ,
94+ } ,
95+ // Package "ovmf-ia32".
96+ UefiArch :: IA32 => Self {
97+ code : "/usr/share/OVMF/OVMF32_CODE_4M.secboot.fd" . into ( ) ,
98+ vars : "/usr/share/OVMF/OVMF32_VARS_4M.fd" . into ( ) ,
99+ } ,
100+ // Package "ovmf".
101+ UefiArch :: X86_64 => Self {
102+ code : "/usr/share/OVMF/OVMF_CODE.fd" . into ( ) ,
103+ vars : "/usr/share/OVMF/OVMF_VARS.fd" . into ( ) ,
104+ } ,
105+ }
106+ }
107+
108+ /// Get the Fedora OVMF paths for the given guest arch.
109+ fn fedora_linux ( arch : UefiArch ) -> Self {
110+ match arch {
111+ // Package "edk2-aarch64".
112+ UefiArch :: AArch64 => Self {
113+ code : "/usr/share/edk2/aarch64/QEMU_EFI-pflash.raw" . into ( ) ,
114+ vars : "/usr/share/edk2/aarch64/vars-template-pflash.raw" . into ( ) ,
115+ } ,
116+ // Package "edk2-ovmf-ia32".
117+ UefiArch :: IA32 => Self {
118+ code : "/usr/share/edk2/ovmf-ia32/OVMF_CODE.fd" . into ( ) ,
119+ vars : "/usr/share/edk2/ovmf-ia32/OVMF_VARS.fd" . into ( ) ,
120+ } ,
121+ // Package "edk2-ovmf".
122+ UefiArch :: X86_64 => Self {
123+ code : "/usr/share/edk2/ovmf/OVMF_CODE.fd" . into ( ) ,
124+ vars : "/usr/share/edk2/ovmf/OVMF_VARS.fd" . into ( ) ,
125+ } ,
53126 }
127+ }
54128
55- // Check whether the test runner directory contains the files.
56- let ovmf_dir = Path :: new ( "uefi-test-runner" ) ;
57- let ovmf_paths = Self :: from_dir ( ovmf_dir, arch) ;
58- if ovmf_paths. exists ( ) {
59- return Ok ( ovmf_paths) ;
129+ /// Get the Windows OVMF paths for the given guest arch.
130+ fn windows ( arch : UefiArch ) -> Self {
131+ match arch {
132+ UefiArch :: AArch64 => Self {
133+ code : r"C:\Program Files\qemu\share\edk2-aarch64-code.fd" . into ( ) ,
134+ vars : r"C:\Program Files\qemu\share\edk2-arm-vars.fd" . into ( ) ,
135+ } ,
136+ UefiArch :: IA32 => Self {
137+ code : r"C:\Program Files\qemu\share\edk2-i386-code.fd" . into ( ) ,
138+ vars : r"C:\Program Files\qemu\share\edk2-i386-vars.fd" . into ( ) ,
139+ } ,
140+ UefiArch :: X86_64 => Self {
141+ code : r"C:\Program Files\qemu\share\edk2-x86_64-code.fd" . into ( ) ,
142+ // There's no x86_64 vars file, but the i386 one works.
143+ vars : r"C:\Program Files\qemu\share\edk2-i386-vars.fd" . into ( ) ,
144+ } ,
60145 }
146+ }
61147
148+ /// Get candidate paths where OVMF code/vars might exist for the
149+ /// given guest arch and host platform.
150+ fn get_candidate_paths ( arch : UefiArch ) -> Vec < Self > {
151+ let mut candidates = Vec :: new ( ) ;
62152 if platform:: is_linux ( ) {
63- let possible_paths = [
64- // Most distros, including CentOS, Fedora, Debian, and Ubuntu.
65- Path :: new ( "/usr/share/OVMF" ) ,
66- // Arch Linux.
67- Path :: new ( "/usr/share/ovmf/x64" ) ,
68- ] ;
69- for path in possible_paths {
70- let ovmf_paths = Self :: from_dir ( path, arch) ;
71- if ovmf_paths. exists ( ) {
72- return Ok ( ovmf_paths) ;
153+ candidates. push ( Self :: arch_linux ( arch) ) ;
154+ if let Some ( candidate) = Self :: centos_linux ( arch) {
155+ candidates. push ( candidate) ;
156+ }
157+ candidates. push ( Self :: debian_linux ( arch) ) ;
158+ candidates. push ( Self :: fedora_linux ( arch) ) ;
159+ }
160+ if platform:: is_windows ( ) {
161+ candidates. push ( Self :: windows ( arch) ) ;
162+ }
163+ candidates
164+ }
165+
166+ /// Search for an OVMF file (either code or vars).
167+ ///
168+ /// If `user_provided_path` is not None, it is always used. An error
169+ /// is returned if the path does not exist.
170+ ///
171+ /// Otherwise, the paths in `candidates` are searched to find one
172+ /// that exists. If none of them exist, an error is returned.
173+ fn find_ovmf_file (
174+ file_type : OvmfFileType ,
175+ user_provided_path : & Option < PathBuf > ,
176+ candidates : & [ Self ] ,
177+ ) -> Result < PathBuf > {
178+ if let Some ( path) = user_provided_path {
179+ // The user provided an exact path to use; verify that it
180+ // exists.
181+ if path. exists ( ) {
182+ Ok ( path. to_owned ( ) )
183+ } else {
184+ bail ! (
185+ "ovmf {} file does not exist: {}" ,
186+ file_type. as_str( ) ,
187+ path. display( )
188+ ) ;
189+ }
190+ } else {
191+ for candidate in candidates {
192+ let path = candidate. get_path ( file_type) ;
193+ if path. exists ( ) {
194+ return Ok ( path. to_owned ( ) ) ;
73195 }
74196 }
197+
198+ bail ! (
199+ "no ovmf {} file found in candidates: {:?}" ,
200+ file_type. as_str( ) ,
201+ candidates
202+ . iter( )
203+ . map( |c| c. get_path( file_type) )
204+ . collect:: <Vec <_>>( ) ,
205+ ) ;
75206 }
207+ }
208+
209+ /// Find path to OVMF files.
210+ fn find ( opt : & QemuOpt , arch : UefiArch ) -> Result < Self > {
211+ let candidates = Self :: get_candidate_paths ( arch) ;
212+
213+ let code = Self :: find_ovmf_file ( OvmfFileType :: Code , & opt. ovmf_code , & candidates) ?;
214+ let vars = Self :: find_ovmf_file ( OvmfFileType :: Vars , & opt. ovmf_vars , & candidates) ?;
76215
77- bail ! ( "OVMF files not found anywhere" ) ;
216+ Ok ( Self { code , vars } )
78217 }
79218}
80219
0 commit comments