@@ -2,67 +2,19 @@ use std::io::prelude::*;
22use std:: path:: Path ;
33use std:: process:: Command ;
44
5+ use crate :: blockdev;
56use crate :: component:: * ;
67use crate :: model:: * ;
78use crate :: packagesystem;
89use anyhow:: { bail, Result } ;
910
10- use crate :: util;
11- use serde:: { Deserialize , Serialize } ;
12-
1311// grub2-install file path
1412pub ( crate ) const GRUB_BIN : & str = "usr/sbin/grub2-install" ;
1513
16- #[ derive( Serialize , Deserialize , Debug ) ]
17- struct BlockDevice {
18- path : String ,
19- pttype : Option < String > ,
20- parttypename : Option < String > ,
21- }
22-
23- #[ derive( Serialize , Deserialize , Debug ) ]
24- struct Devices {
25- blockdevices : Vec < BlockDevice > ,
26- }
27-
2814#[ derive( Default ) ]
2915pub ( crate ) struct Bios { }
3016
3117impl Bios {
32- // get target device for running update
33- fn get_device ( & self ) -> Result < String > {
34- let mut cmd: Command ;
35- #[ cfg( target_arch = "x86_64" ) ]
36- {
37- // find /boot partition
38- cmd = Command :: new ( "findmnt" ) ;
39- cmd. arg ( "--noheadings" )
40- . arg ( "--nofsroot" )
41- . arg ( "--output" )
42- . arg ( "SOURCE" )
43- . arg ( "/boot" ) ;
44- let partition = util:: cmd_output ( & mut cmd) ?;
45-
46- // lsblk to find parent device
47- cmd = Command :: new ( "lsblk" ) ;
48- cmd. arg ( "--paths" )
49- . arg ( "--noheadings" )
50- . arg ( "--output" )
51- . arg ( "PKNAME" )
52- . arg ( partition. trim ( ) ) ;
53- }
54-
55- #[ cfg( target_arch = "powerpc64" ) ]
56- {
57- // get PowerPC-PReP-boot partition
58- cmd = Command :: new ( "realpath" ) ;
59- cmd. arg ( "/dev/disk/by-partlabel/PowerPC-PReP-boot" ) ;
60- }
61-
62- let device = util:: cmd_output ( & mut cmd) ?;
63- Ok ( device)
64- }
65-
6618 // Return `true` if grub2-modules installed
6719 fn check_grub_modules ( & self ) -> Result < bool > {
6820 let usr_path = Path :: new ( "/usr/lib/grub" ) ;
@@ -115,37 +67,18 @@ impl Bios {
11567 }
11668
11769 // check bios_boot partition on gpt type disk
118- fn get_bios_boot_partition ( & self ) -> Result < Option < String > > {
119- let target = self . get_device ( ) ?;
120- // lsblk to list children with bios_boot
121- let output = Command :: new ( "lsblk" )
122- . args ( [
123- "--json" ,
124- "--output" ,
125- "PATH,PTTYPE,PARTTYPENAME" ,
126- target. trim ( ) ,
127- ] )
128- . output ( ) ?;
129- if !output. status . success ( ) {
130- std:: io:: stderr ( ) . write_all ( & output. stderr ) ?;
131- bail ! ( "Failed to run lsblk" ) ;
70+ fn get_bios_boot_partition ( & self ) -> Option < Vec < String > > {
71+ let bios_boot_devices =
72+ blockdev:: find_colocated_bios_boot ( "/" ) . expect ( "get bios_boot devices" ) ;
73+ // skip bios update if has multiple devices
74+ if bios_boot_devices. len ( ) > 1 {
75+ log:: warn!( "Find multiple devices which are currently not supported" ) ;
76+ return None ;
13277 }
133-
134- let output = String :: from_utf8 ( output. stdout ) ?;
135- // Parse the JSON string into the `Devices` struct
136- let Ok ( devices) = serde_json:: from_str :: < Devices > ( & output) else {
137- bail ! ( "Could not deserialize JSON output from lsblk" ) ;
138- } ;
139-
140- // Find the device with the parttypename "BIOS boot"
141- for device in devices. blockdevices {
142- if let Some ( parttypename) = & device. parttypename {
143- if parttypename == "BIOS boot" && device. pttype . as_deref ( ) == Some ( "gpt" ) {
144- return Ok ( Some ( device. path ) ) ;
145- }
146- }
78+ if !bios_boot_devices. is_empty ( ) {
79+ return Some ( bios_boot_devices) ;
14780 }
148- Ok ( None )
81+ None
14982 }
15083}
15184
@@ -187,7 +120,7 @@ impl Component for Bios {
187120
188121 fn query_adopt ( & self ) -> Result < Option < Adoptable > > {
189122 #[ cfg( target_arch = "x86_64" ) ]
190- if crate :: efi:: is_efi_booted ( ) ? && self . get_bios_boot_partition ( ) ? . is_none ( ) {
123+ if crate :: efi:: is_efi_booted ( ) ? && self . get_bios_boot_partition ( ) . is_none ( ) {
191124 log:: debug!( "Skip BIOS adopt" ) ;
192125 return Ok ( None ) ;
193126 }
@@ -199,9 +132,13 @@ impl Component for Bios {
199132 anyhow:: bail!( "Failed to find adoptable system" )
200133 } ;
201134
202- let device = self . get_device ( ) ?;
203- let device = device. trim ( ) ;
204- self . run_grub_install ( "/" , device) ?;
135+ let target_root = "/" ;
136+ let devices = blockdev:: get_backing_devices ( & target_root) ?
137+ . into_iter ( )
138+ . next ( ) ;
139+ let dev = devices. unwrap ( ) ;
140+ self . run_grub_install ( target_root, & dev) ?;
141+ log:: debug!( "Install grub2 on {dev}" ) ;
205142 Ok ( InstalledContent {
206143 meta : update. clone ( ) ,
207144 filetree : None ,
@@ -215,9 +152,14 @@ impl Component for Bios {
215152
216153 fn run_update ( & self , sysroot : & openat:: Dir , _: & InstalledContent ) -> Result < InstalledContent > {
217154 let updatemeta = self . query_update ( sysroot) ?. expect ( "update available" ) ;
218- let device = self . get_device ( ) ?;
219- let device = device. trim ( ) ;
220- self . run_grub_install ( "/" , device) ?;
155+ let sysroot = sysroot. recover_path ( ) ?;
156+ let dest_root = sysroot. to_str ( ) . unwrap_or ( "/" ) ;
157+ let devices = blockdev:: get_backing_devices ( & dest_root) ?
158+ . into_iter ( )
159+ . next ( ) ;
160+ let dev = devices. unwrap ( ) ;
161+ self . run_grub_install ( dest_root, & dev) ?;
162+ log:: debug!( "Install grub2 on {dev}" ) ;
221163
222164 let adopted_from = None ;
223165 Ok ( InstalledContent {
@@ -235,18 +177,3 @@ impl Component for Bios {
235177 Ok ( None )
236178 }
237179}
238-
239- #[ cfg( test) ]
240- mod tests {
241- use super :: * ;
242-
243- #[ test]
244- fn test_deserialize_lsblk_output ( ) {
245- let data = include_str ! ( "../tests/fixtures/example-lsblk-output.json" ) ;
246- let devices: Devices = serde_json:: from_str ( & data) . expect ( "JSON was not well-formatted" ) ;
247- assert_eq ! ( devices. blockdevices. len( ) , 7 ) ;
248- assert_eq ! ( devices. blockdevices[ 0 ] . path, "/dev/sr0" ) ;
249- assert ! ( devices. blockdevices[ 0 ] . pttype. is_none( ) ) ;
250- assert ! ( devices. blockdevices[ 0 ] . parttypename. is_none( ) ) ;
251- }
252- }
0 commit comments