@@ -142,6 +142,10 @@ pub fn get_sysroot_parent_dev() -> Result<String> {
142
142
return Ok ( parent) ;
143
143
}
144
144
145
+ pub fn type1_entry_conf_file_name ( sort_key : impl std:: fmt:: Display ) -> String {
146
+ format ! ( "bootc-composefs-{sort_key}.conf" )
147
+ }
148
+
145
149
/// Compute SHA256Sum of VMlinuz + Initrd
146
150
///
147
151
/// # Arguments
@@ -264,6 +268,51 @@ fn write_bls_boot_entries_to_disk(
264
268
Ok ( ( ) )
265
269
}
266
270
271
+ /// Parses /usr/lib/os-release and returns title and version fields
272
+ /// # Returns
273
+ /// - (title, version)
274
+ fn osrel_title_and_version (
275
+ fs : & FileSystem < Sha256HashValue > ,
276
+ repo : & ComposefsRepository < Sha256HashValue > ,
277
+ ) -> Result < Option < ( Option < String > , Option < String > ) > > {
278
+ // Every update should have its own /usr/lib/os-release
279
+ let ( dir, fname) = fs
280
+ . root
281
+ . split ( OsStr :: new ( "/usr/lib/os-release" ) )
282
+ . context ( "Getting /usr/lib/os-release" ) ?;
283
+
284
+ let os_release = dir
285
+ . get_file_opt ( fname)
286
+ . context ( "Getting /usr/lib/os-release" ) ?;
287
+
288
+ let Some ( os_rel_file) = os_release else {
289
+ return Ok ( None ) ;
290
+ } ;
291
+
292
+ let file_contents = match read_file ( os_rel_file, repo) {
293
+ Ok ( c) => c,
294
+ Err ( e) => {
295
+ tracing:: warn!( "Could not read /usr/lib/os-release: {e:?}" ) ;
296
+ return Ok ( None ) ;
297
+ }
298
+ } ;
299
+
300
+ let file_contents = match std:: str:: from_utf8 ( & file_contents) {
301
+ Ok ( c) => c,
302
+ Err ( e) => {
303
+ tracing:: warn!( "/usr/lib/os-release did not have valid UTF-8: {e}" ) ;
304
+ return Ok ( None ) ;
305
+ }
306
+ } ;
307
+
308
+ let parsed_contents = OsReleaseInfo :: parse ( file_contents) ;
309
+
310
+ let title = parsed_contents. get_pretty_name ( ) ;
311
+ let version = parsed_contents. get_version ( ) ;
312
+
313
+ Ok ( Some ( ( title, version) ) )
314
+ }
315
+
267
316
struct BLSEntryPath < ' a > {
268
317
/// Where to write vmlinuz/initrd
269
318
entries_path : Utf8PathBuf ,
@@ -372,51 +421,33 @@ pub(crate) fn setup_composefs_bls_boot(
372
421
} ;
373
422
374
423
let ( bls_config, boot_digest) = match & entry {
375
- ComposefsBootEntry :: Type1 ( ..) => unimplemented ! ( ) ,
376
- ComposefsBootEntry :: Type2 ( ..) => unimplemented ! ( ) ,
424
+ ComposefsBootEntry :: Type1 ( ..) => anyhow :: bail! ( "Found Type1 entries in /boot" ) ,
425
+ ComposefsBootEntry :: Type2 ( ..) => anyhow :: bail! ( "Found UKI" ) ,
377
426
378
427
ComposefsBootEntry :: UsrLibModulesVmLinuz ( usr_lib_modules_vmlinuz) => {
379
428
let boot_digest = compute_boot_digest ( usr_lib_modules_vmlinuz, & repo)
380
429
. context ( "Computing boot digest" ) ?;
381
430
382
- // Every update should have its own /usr/lib/os-release
383
- let ( dir, fname) = fs
384
- . root
385
- . split ( OsStr :: new ( "/usr/lib/os-release" ) )
386
- . context ( "Getting /usr/lib/os-release" ) ?;
387
-
388
- let os_release = dir
389
- . get_file_opt ( fname)
390
- . context ( "Getting /usr/lib/os-release" ) ?;
391
-
392
- let version = os_release. and_then ( |os_rel_file| {
393
- let file_contents = match read_file ( os_rel_file, & repo) {
394
- Ok ( c) => c,
395
- Err ( e) => {
396
- tracing:: warn!( "Could not read /usr/lib/os-release: {e:?}" ) ;
397
- return None ;
398
- }
399
- } ;
400
-
401
- let file_contents = match std:: str:: from_utf8 ( & file_contents) {
402
- Ok ( c) => c,
403
- Err ( ..) => {
404
- tracing:: warn!( "/usr/lib/os-release did not have valid UTF-8" ) ;
405
- return None ;
406
- }
407
- } ;
408
-
409
- OsReleaseInfo :: parse ( file_contents) . get_version ( )
410
- } ) ;
411
-
412
431
let default_sort_key = "1" ;
432
+ let default_title_version = ( id. to_hex ( ) , default_sort_key. to_string ( ) ) ;
433
+
434
+ let osrel_res = osrel_title_and_version ( fs, & repo) ?;
435
+
436
+ let ( title, version) = match osrel_res {
437
+ Some ( ( t, v) ) => (
438
+ t. unwrap_or ( default_title_version. 0 ) ,
439
+ v. unwrap_or ( default_title_version. 1 ) ,
440
+ ) ,
441
+
442
+ None => default_title_version,
443
+ } ;
413
444
414
445
let mut bls_config = BLSConfig :: default ( ) ;
415
446
416
447
bls_config
417
- . with_title ( id_hex . clone ( ) )
448
+ . with_title ( title )
418
449
. with_sort_key ( default_sort_key. into ( ) )
419
- . with_version ( version. unwrap_or ( default_sort_key . into ( ) ) )
450
+ . with_version ( version)
420
451
. with_linux ( format ! (
421
452
"/{}/{id_hex}/vmlinuz" ,
422
453
entry_paths. abs_entries_path
@@ -427,82 +458,70 @@ pub(crate) fn setup_composefs_bls_boot(
427
458
) ] )
428
459
. with_options ( cmdline_refs) ;
429
460
430
- if let Some ( symlink_to) = find_vmlinuz_initrd_duplicates ( & boot_digest) ? {
431
- bls_config. linux =
432
- format ! ( "/{}/{symlink_to}/vmlinuz" , entry_paths. abs_entries_path) ;
461
+ match find_vmlinuz_initrd_duplicates ( & boot_digest) ? {
462
+ Some ( symlink_to) => {
463
+ bls_config. linux =
464
+ format ! ( "/{}/{symlink_to}/vmlinuz" , entry_paths. abs_entries_path) ;
433
465
434
- bls_config. initrd = vec ! [ format!(
435
- "/{}/{symlink_to}/initrd" ,
436
- entry_paths. abs_entries_path
437
- ) ] ;
438
- } else {
439
- write_bls_boot_entries_to_disk (
440
- & entry_paths. entries_path ,
441
- id,
442
- usr_lib_modules_vmlinuz,
443
- & repo,
444
- ) ?;
445
- }
466
+ bls_config. initrd = vec ! [ format!(
467
+ "/{}/{symlink_to}/initrd" ,
468
+ entry_paths. abs_entries_path
469
+ ) ] ;
470
+ }
471
+
472
+ None => {
473
+ write_bls_boot_entries_to_disk (
474
+ & entry_paths. entries_path ,
475
+ id,
476
+ usr_lib_modules_vmlinuz,
477
+ & repo,
478
+ ) ?;
479
+ }
480
+ } ;
446
481
447
482
( bls_config, boot_digest)
448
483
}
449
484
} ;
450
485
486
+ let loader_path = entry_paths. config_path . join ( "loader" ) ;
487
+
451
488
let ( config_path, booted_bls) = if is_upgrade {
452
489
let mut booted_bls = get_booted_bls ( ) ?;
453
490
booted_bls. sort_key = Some ( "0" . into ( ) ) ; // entries are sorted by their filename in reverse order
454
491
455
492
// This will be atomically renamed to 'loader/entries' on shutdown/reboot
456
493
(
457
- entry_paths
458
- . config_path
459
- . join ( "loader" )
460
- . join ( STAGED_BOOT_LOADER_ENTRIES ) ,
494
+ loader_path. join ( STAGED_BOOT_LOADER_ENTRIES ) ,
461
495
Some ( booted_bls) ,
462
496
)
463
497
} else {
464
- (
465
- entry_paths
466
- . config_path
467
- . join ( "loader" )
468
- . join ( BOOT_LOADER_ENTRIES ) ,
469
- None ,
470
- )
498
+ ( loader_path. join ( BOOT_LOADER_ENTRIES ) , None )
471
499
} ;
472
500
473
501
create_dir_all ( & config_path) . with_context ( || format ! ( "Creating {:?}" , config_path) ) ?;
474
502
475
- // Scope to allow for proper unmounting
476
- {
477
- let loader_entries_dir = Dir :: open_ambient_dir ( & config_path, ambient_authority ( ) )
478
- . with_context ( || format ! ( "Opening {config_path:?}" ) ) ?;
503
+ let loader_entries_dir = Dir :: open_ambient_dir ( & config_path, ambient_authority ( ) )
504
+ . with_context ( || format ! ( "Opening {config_path:?}" ) ) ?;
505
+
506
+ loader_entries_dir. atomic_write (
507
+ // SAFETY: We set sort_key above
508
+ type1_entry_conf_file_name ( bls_config. sort_key . as_ref ( ) . unwrap ( ) ) ,
509
+ bls_config. to_string ( ) . as_bytes ( ) ,
510
+ ) ?;
479
511
512
+ if let Some ( booted_bls) = booted_bls {
480
513
loader_entries_dir. atomic_write (
481
514
// SAFETY: We set sort_key above
482
- format ! (
483
- "bootc-composefs-{}.conf" ,
484
- bls_config. sort_key. as_ref( ) . unwrap( )
485
- ) ,
486
- bls_config. to_string ( ) . as_bytes ( ) ,
515
+ type1_entry_conf_file_name ( booted_bls. sort_key . as_ref ( ) . unwrap ( ) ) ,
516
+ booted_bls. to_string ( ) . as_bytes ( ) ,
487
517
) ?;
518
+ }
488
519
489
- if let Some ( booted_bls) = booted_bls {
490
- loader_entries_dir. atomic_write (
491
- // SAFETY: We set sort_key above
492
- format ! (
493
- "bootc-composefs-{}.conf" ,
494
- booted_bls. sort_key. as_ref( ) . unwrap( )
495
- ) ,
496
- booted_bls. to_string ( ) . as_bytes ( ) ,
497
- ) ?;
498
- }
499
-
500
- let owned_loader_entries_fd = loader_entries_dir
501
- . reopen_as_ownedfd ( )
502
- . context ( "Reopening as owned fd" ) ?;
520
+ let owned_loader_entries_fd = loader_entries_dir
521
+ . reopen_as_ownedfd ( )
522
+ . context ( "Reopening as owned fd" ) ?;
503
523
504
- rustix:: fs:: fsync ( owned_loader_entries_fd) . context ( "fsync" ) ?;
505
- }
524
+ rustix:: fs:: fsync ( owned_loader_entries_fd) . context ( "fsync" ) ?;
506
525
507
526
Ok ( boot_digest)
508
527
}
0 commit comments