@@ -26,20 +26,28 @@ pub(crate) struct Kernel {
2626 pub ( crate ) unified : bool ,
2727}
2828
29- /// Internal-only kernel wrapper with extra information (paths to
30- /// vmlinuz, initramfs) that are useful but we don't want to leak out
31- /// via serialization to inspection.
29+ /// Path to kernel component(s)
30+ ///
31+ /// UKI kernels only have the single PE binary, whereas
32+ /// traditional "vmlinuz" kernels have distinct kernel and
33+ /// initramfs.
34+ pub ( crate ) enum KernelPath {
35+ Uki ( Utf8PathBuf ) ,
36+ Vmlinuz {
37+ path : Utf8PathBuf ,
38+ initramfs : Utf8PathBuf ,
39+ } ,
40+ }
41+
42+ /// Internal-only kernel wrapper with extra path information that are
43+ /// useful but we don't want to leak out via serialization to
44+ /// inspection.
3245///
3346/// `Kernel` implements `From<KernelInternal>` so we can just `.into()`
3447/// to get the "public" form where needed.
3548pub ( crate ) struct KernelInternal {
3649 pub ( crate ) kernel : Kernel ,
37- /// Path to vmlinuz for traditional kernels.
38- /// This is `None` for UKI images.
39- pub ( crate ) vmlinuz : Option < Utf8PathBuf > ,
40- /// Path to initramfs.img for traditional kernels.
41- /// This is `None` for UKI images.
42- pub ( crate ) initramfs : Option < Utf8PathBuf > ,
50+ pub ( crate ) path : KernelPath ,
4351}
4452
4553impl From < KernelInternal > for Kernel {
@@ -57,18 +65,14 @@ impl From<KernelInternal> for Kernel {
5765/// Returns `None` if no kernel is found.
5866pub ( crate ) fn find_kernel ( root : & Dir ) -> Result < Option < KernelInternal > > {
5967 // First, try to find a UKI
60- if let Some ( uki_filename) = find_uki_filename ( root) ? {
61- let version = uki_filename
62- . strip_suffix ( ".efi" )
63- . unwrap_or ( & uki_filename)
64- . to_owned ( ) ;
68+ if let Some ( uki_path) = find_uki_path ( root) ? {
69+ let version = uki_path. file_stem ( ) . unwrap_or ( uki_path. as_str ( ) ) . to_owned ( ) ;
6570 return Ok ( Some ( KernelInternal {
6671 kernel : Kernel {
6772 version,
6873 unified : true ,
6974 } ,
70- vmlinuz : None ,
71- initramfs : None ,
75+ path : KernelPath :: Uki ( uki_path) ,
7276 } ) ) ;
7377 }
7478
@@ -85,19 +89,21 @@ pub(crate) fn find_kernel(root: &Dir) -> Result<Option<KernelInternal>> {
8589 version,
8690 unified : false ,
8791 } ,
88- vmlinuz : Some ( vmlinuz) ,
89- initramfs : Some ( initramfs) ,
92+ path : KernelPath :: Vmlinuz {
93+ path : vmlinuz,
94+ initramfs,
95+ } ,
9096 } ) ) ;
9197 }
9298
9399 Ok ( None )
94100}
95101
96- /// Returns the filename of the first UKI found in the container root, if any.
102+ /// Returns the path to the first UKI found in the container root, if any.
97103///
98104/// Looks in `/boot/EFI/Linux/*.efi`. If multiple UKIs are present, returns
99105/// the first one in sorted order for determinism.
100- fn find_uki_filename ( root : & Dir ) -> Result < Option < String > > {
106+ fn find_uki_path ( root : & Dir ) -> Result < Option < Utf8PathBuf > > {
101107 let Some ( boot) = root. open_dir_optional ( crate :: install:: BOOT ) ? else {
102108 return Ok ( None ) ;
103109 } ;
@@ -120,13 +126,15 @@ fn find_uki_filename(root: &Dir) -> Result<Option<String>> {
120126
121127 // Sort for deterministic behavior when multiple UKIs are present
122128 uki_files. sort ( ) ;
123- Ok ( uki_files. into_iter ( ) . next ( ) )
129+ Ok ( uki_files
130+ . into_iter ( )
131+ . next ( )
132+ . map ( |filename| Utf8PathBuf :: from ( format ! ( "boot/{EFI_LINUX}/{filename}" ) ) ) )
124133}
125134
126135#[ cfg( test) ]
127136mod tests {
128137 use super :: * ;
129- use camino:: Utf8Path ;
130138 use cap_std_ext:: { cap_std, cap_tempfile, dirext:: CapStdExtDirExt } ;
131139
132140 #[ test]
@@ -148,18 +156,19 @@ mod tests {
148156 let kernel_internal = find_kernel ( & tempdir) ?. expect ( "should find kernel" ) ;
149157 assert_eq ! ( kernel_internal. kernel. version, "6.12.0-100.fc41.x86_64" ) ;
150158 assert ! ( !kernel_internal. kernel. unified) ;
151- assert_eq ! (
152- kernel_internal. vmlinuz. as_deref( ) ,
153- Some ( Utf8Path :: new(
154- "usr/lib/modules/6.12.0-100.fc41.x86_64/vmlinuz"
155- ) )
156- ) ;
157- assert_eq ! (
158- kernel_internal. initramfs. as_deref( ) ,
159- Some ( Utf8Path :: new(
160- "usr/lib/modules/6.12.0-100.fc41.x86_64/initramfs.img"
161- ) )
162- ) ;
159+ match & kernel_internal. path {
160+ KernelPath :: Vmlinuz { path, initramfs } => {
161+ assert_eq ! (
162+ path. as_str( ) ,
163+ "usr/lib/modules/6.12.0-100.fc41.x86_64/vmlinuz"
164+ ) ;
165+ assert_eq ! (
166+ initramfs. as_str( ) ,
167+ "usr/lib/modules/6.12.0-100.fc41.x86_64/initramfs.img"
168+ ) ;
169+ }
170+ KernelPath :: Uki ( _) => panic ! ( "Expected Vmlinuz, got Uki" ) ,
171+ }
163172 Ok ( ( ) )
164173 }
165174
@@ -172,8 +181,12 @@ mod tests {
172181 let kernel_internal = find_kernel ( & tempdir) ?. expect ( "should find kernel" ) ;
173182 assert_eq ! ( kernel_internal. kernel. version, "fedora-6.12.0" ) ;
174183 assert ! ( kernel_internal. kernel. unified) ;
175- assert ! ( kernel_internal. vmlinuz. is_none( ) ) ;
176- assert ! ( kernel_internal. initramfs. is_none( ) ) ;
184+ match & kernel_internal. path {
185+ KernelPath :: Uki ( path) => {
186+ assert_eq ! ( path. as_str( ) , "boot/EFI/Linux/fedora-6.12.0.efi" ) ;
187+ }
188+ KernelPath :: Vmlinuz { .. } => panic ! ( "Expected Uki, got Vmlinuz" ) ,
189+ }
177190 Ok ( ( ) )
178191 }
179192
@@ -197,16 +210,16 @@ mod tests {
197210 }
198211
199212 #[ test]
200- fn test_find_uki_filename_sorted ( ) -> Result < ( ) > {
213+ fn test_find_uki_path_sorted ( ) -> Result < ( ) > {
201214 let tempdir = cap_tempfile:: tempdir ( cap_std:: ambient_authority ( ) ) ?;
202215 tempdir. create_dir_all ( "boot/EFI/Linux" ) ?;
203216 tempdir. atomic_write ( "boot/EFI/Linux/zzz.efi" , b"fake uki" ) ?;
204217 tempdir. atomic_write ( "boot/EFI/Linux/aaa.efi" , b"fake uki" ) ?;
205218 tempdir. atomic_write ( "boot/EFI/Linux/mmm.efi" , b"fake uki" ) ?;
206219
207220 // Should return first in sorted order
208- let filename = find_uki_filename ( & tempdir) ?. expect ( "should find uki" ) ;
209- assert_eq ! ( filename , "aaa.efi" ) ;
221+ let path = find_uki_path ( & tempdir) ?. expect ( "should find uki" ) ;
222+ assert_eq ! ( path . as_str ( ) , "boot/EFI/Linux/ aaa.efi" ) ;
210223 Ok ( ( ) )
211224 }
212225}
0 commit comments