@@ -14,67 +14,206 @@ use std::process::{Child, Command, Stdio};
14
14
use std:: { env, thread} ;
15
15
use tempfile:: TempDir ;
16
16
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
+
17
32
struct OvmfPaths {
18
33
code : PathBuf ,
19
34
vars : PathBuf ,
20
35
}
21
36
22
37
impl 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 {
24
47
match arch {
48
+ // Package "edk2-armvirt".
25
49
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 ( ) ,
28
52
} ,
53
+ // Package "edk2-ovmf".
29
54
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 ( ) ,
32
57
} ,
58
+ // Package "edk2-ovmf".
33
59
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 ( ) ,
36
62
} ,
37
63
}
38
64
}
39
65
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
+ }
42
84
}
43
85
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
+ } ,
53
126
}
127
+ }
54
128
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
+ } ,
60
145
}
146
+ }
61
147
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 ( ) ;
62
152
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 ( ) ) ;
73
195
}
74
196
}
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
+ ) ;
75
206
}
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) ?;
76
215
77
- bail ! ( "OVMF files not found anywhere" ) ;
216
+ Ok ( Self { code , vars } )
78
217
}
79
218
}
80
219
0 commit comments