11use std:: fmt:: Write ;
2+ use std:: os:: unix:: io:: AsRawFd ;
23use std:: path:: { Path , PathBuf } ;
34
45use anyhow:: { anyhow, Context , Result } ;
6+ use bootc_utils:: CommandRunExt ;
57use fn_error_context:: context;
68use openat_ext:: OpenatDirExt ;
79
810/// The subdirectory of /boot we use
911const GRUB2DIR : & str = "grub2" ;
1012const CONFIGDIR : & str = "/usr/lib/bootupd/grub2-static" ;
1113const DROPINDIR : & str = "configs.d" ;
14+ const GRUBENV : & str = "grubenv" ;
1215
1316/// Install the static GRUB config files.
1417#[ context( "Installing static GRUB configs" ) ]
@@ -62,6 +65,8 @@ pub(crate) fn install(
6265 . context ( "Copying grub-static.cfg" ) ?;
6366 println ! ( "Installed: grub.cfg" ) ;
6467
68+ write_grubenv ( & bootdir) . context ( "Create grubenv" ) ?;
69+
6570 let uuid_path = if write_uuid {
6671 let target_fs = if boot_is_mount { bootdir } else { target_root } ;
6772 let bootfs_meta = crate :: filesystem:: inspect_filesystem ( target_fs, "." ) ?;
@@ -104,6 +109,24 @@ pub(crate) fn install(
104109 Ok ( ( ) )
105110}
106111
112+ #[ context( "Create file boot/grub2/grubenv" ) ]
113+ fn write_grubenv ( bootdir : & openat:: Dir ) -> Result < ( ) > {
114+ let grubdir = & bootdir. sub_dir ( GRUB2DIR ) . context ( "Opening boot/grub2" ) ?;
115+
116+ if grubdir. exists ( GRUBENV ) ? {
117+ return Ok ( ( ) ) ;
118+ }
119+ let editenv = Path :: new ( "/usr/bin/grub2-editenv" ) ;
120+ if !editenv. exists ( ) {
121+ anyhow:: bail!( "Failed to find {:?}" , editenv) ;
122+ }
123+
124+ std:: process:: Command :: new ( editenv)
125+ . args ( [ GRUBENV , "create" ] )
126+ . current_dir ( format ! ( "/proc/self/fd/{}" , grubdir. as_raw_fd( ) ) )
127+ . run_with_cmd_context ( )
128+ }
129+
107130#[ cfg( test) ]
108131mod tests {
109132 use super :: * ;
@@ -124,4 +147,15 @@ mod tests {
124147 assert ! ( td. exists( "boot/efi/EFI/fedora/grub.cfg" ) ?) ;
125148 Ok ( ( ) )
126149 }
150+ #[ test]
151+ fn test_write_grubenv ( ) -> Result < ( ) > {
152+ let td = tempfile:: tempdir ( ) ?;
153+ let tdp = td. path ( ) ;
154+ std:: fs:: create_dir_all ( tdp. join ( "boot/grub2" ) ) ?;
155+ let td = openat:: Dir :: open ( & tdp. join ( "boot" ) ) ?;
156+ write_grubenv ( & td) ?;
157+
158+ assert ! ( td. exists( "grub2/grubenv" ) ?) ;
159+ Ok ( ( ) )
160+ }
127161}
0 commit comments