3636#include "rm-rf.h"
3737#include "stat-util.h"
3838#include "stdio-util.h"
39+ #include "string-table.h"
3940#include "string-util.h"
4041#include "strv.h"
4142#include "sync-util.h"
@@ -74,7 +75,8 @@ static int acquire_esp(
7475 uint32_t * ret_part ,
7576 uint64_t * ret_pstart ,
7677 uint64_t * ret_psize ,
77- sd_id128_t * ret_uuid ) {
78+ sd_id128_t * ret_uuid ,
79+ dev_t * ret_devid ) {
7880
7981 char * np ;
8082 int r ;
@@ -85,7 +87,7 @@ static int acquire_esp(
8587 * we simply eat up the error here, so that --list and --status work too, without noise about
8688 * this). */
8789
88- r = find_esp_and_warn (arg_esp_path , unprivileged_mode , & np , ret_part , ret_pstart , ret_psize , ret_uuid );
90+ r = find_esp_and_warn (arg_esp_path , unprivileged_mode , & np , ret_part , ret_pstart , ret_psize , ret_uuid , ret_devid );
8991 if (r == - ENOKEY ) {
9092 if (graceful )
9193 return log_info_errno (r , "Couldn't find EFI system partition, skipping." );
@@ -103,16 +105,23 @@ static int acquire_esp(
103105 return 1 ;
104106}
105107
106- static int acquire_xbootldr (bool unprivileged_mode , sd_id128_t * ret_uuid ) {
108+ static int acquire_xbootldr (
109+ bool unprivileged_mode ,
110+ sd_id128_t * ret_uuid ,
111+ dev_t * ret_devid ) {
112+
107113 char * np ;
108114 int r ;
109115
110- r = find_xbootldr_and_warn (arg_xbootldr_path , unprivileged_mode , & np , ret_uuid );
116+ r = find_xbootldr_and_warn (arg_xbootldr_path , unprivileged_mode , & np , ret_uuid , ret_devid );
111117 if (r == - ENOKEY ) {
112118 log_debug_errno (r , "Didn't find an XBOOTLDR partition, using the ESP as $BOOT." );
119+ arg_xbootldr_path = mfree (arg_xbootldr_path );
120+
113121 if (ret_uuid )
114122 * ret_uuid = SD_ID128_NULL ;
115- arg_xbootldr_path = mfree (arg_xbootldr_path );
123+ if (ret_devid )
124+ * ret_devid = 0 ;
116125 return 0 ;
117126 }
118127 if (r < 0 )
@@ -411,17 +420,52 @@ static void boot_entry_file_list(const char *field, const char *root, const char
411420 * ret_status = status ;
412421}
413422
414- static int boot_entry_show (const BootEntry * e , bool show_as_default ) {
423+ static const char * const boot_entry_type_table [_BOOT_ENTRY_TYPE_MAX ] = {
424+ [BOOT_ENTRY_CONF ] = "Boot Loader Specification Type #1 (.conf)" ,
425+ [BOOT_ENTRY_UNIFIED ] = "Boot Loader Specification Type #2 (.efi)" ,
426+ [BOOT_ENTRY_LOADER ] = "Reported by Boot Loader" ,
427+ [BOOT_ENTRY_LOADER_AUTO ] = "Automatic" ,
428+ };
429+
430+ DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING (boot_entry_type , BootEntryType );
431+
432+ static int boot_entry_show (
433+ const BootEntry * e ,
434+ bool show_as_default ,
435+ bool show_as_selected ,
436+ bool show_reported ) {
437+
415438 int status = 0 ;
416439
417440 /* Returns 0 on success, negative on processing error, and positive if something is wrong with the
418441 boot entry itself. */
419442
420443 assert (e );
421444
422- printf (" title: %s%s%s" "%s%s%s\n" ,
423- ansi_highlight (), boot_entry_title (e ), ansi_normal (),
424- ansi_highlight_green (), show_as_default ? " (default)" : "" , ansi_normal ());
445+ printf (" type: %s\n" ,
446+ boot_entry_type_to_string (e -> type ));
447+
448+ printf (" title: %s%s%s" ,
449+ ansi_highlight (), boot_entry_title (e ), ansi_normal ());
450+
451+ if (show_as_default )
452+ printf (" %s(default)%s" ,
453+ ansi_highlight_green (), ansi_normal ());
454+
455+ if (show_as_selected )
456+ printf (" %s(selected)%s" ,
457+ ansi_highlight_magenta (), ansi_normal ());
458+
459+ if (show_reported ) {
460+ if (e -> type == BOOT_ENTRY_LOADER )
461+ printf (" %s(reported/absent)%s" ,
462+ ansi_highlight_red (), ansi_normal ());
463+ else if (!e -> reported_by_loader && e -> type != BOOT_ENTRY_LOADER_AUTO )
464+ printf (" %s(not reported/new)%s" ,
465+ ansi_highlight_green (), ansi_normal ());
466+ }
467+
468+ putchar ('\n' );
425469
426470 if (e -> id )
427471 printf (" id: %s\n" , e -> id );
@@ -450,6 +494,7 @@ static int boot_entry_show(const BootEntry *e, bool show_as_default) {
450494 e -> root ,
451495 * s ,
452496 & status );
497+
453498 if (!strv_isempty (e -> options )) {
454499 _cleanup_free_ char * t = NULL , * t2 = NULL ;
455500 _cleanup_strv_free_ char * * ts = NULL ;
@@ -468,9 +513,16 @@ static int boot_entry_show(const BootEntry *e, bool show_as_default) {
468513
469514 printf (" options: %s\n" , t2 );
470515 }
516+
471517 if (e -> device_tree )
472518 boot_entry_file_list ("devicetree" , e -> root , e -> device_tree , & status );
473519
520+ STRV_FOREACH (s , e -> device_tree_overlay )
521+ boot_entry_file_list (s == e -> device_tree_overlay ? "devicetree-overlay" : NULL ,
522+ e -> root ,
523+ * s ,
524+ & status );
525+
474526 return - status ;
475527}
476528
@@ -511,7 +563,11 @@ static int status_entries(
511563 else {
512564 printf ("Default Boot Loader Entry:\n" );
513565
514- r = boot_entry_show (config .entries + config .default_entry , false);
566+ r = boot_entry_show (
567+ config .entries + config .default_entry ,
568+ /* show_as_default= */ false,
569+ /* show_as_selected= */ false,
570+ /* show_discovered= */ false);
515571 if (r > 0 )
516572 /* < 0 is already logged by the function itself, let's just emit an extra warning if
517573 the default entry is broken */
@@ -1388,7 +1444,7 @@ static void print_yes_no_line(bool first, bool good, const char *name) {
13881444static int are_we_installed (void ) {
13891445 int r ;
13901446
1391- r = acquire_esp (/* privileged_mode= */ false, /* graceful= */ false, NULL , NULL , NULL , NULL );
1447+ r = acquire_esp (/* privileged_mode= */ false, /* graceful= */ false, NULL , NULL , NULL , NULL , NULL );
13921448 if (r < 0 )
13931449 return r ;
13941450
@@ -1420,9 +1476,10 @@ static int are_we_installed(void) {
14201476
14211477static int verb_status (int argc , char * argv [], void * userdata ) {
14221478 sd_id128_t esp_uuid = SD_ID128_NULL , xbootldr_uuid = SD_ID128_NULL ;
1479+ dev_t esp_devid = 0 , xbootldr_devid = 0 ;
14231480 int r , k ;
14241481
1425- r = acquire_esp (/* unprivileged_mode= */ geteuid () != 0 , /* graceful= */ false, NULL , NULL , NULL , & esp_uuid );
1482+ r = acquire_esp (/* unprivileged_mode= */ geteuid () != 0 , /* graceful= */ false, NULL , NULL , NULL , & esp_uuid , & esp_devid );
14261483 if (arg_print_esp_path ) {
14271484 if (r == - EACCES ) /* If we couldn't acquire the ESP path, log about access errors (which is the only
14281485 * error the find_esp_and_warn() won't log on its own) */
@@ -1433,7 +1490,7 @@ static int verb_status(int argc, char *argv[], void *userdata) {
14331490 puts (arg_esp_path );
14341491 }
14351492
1436- r = acquire_xbootldr (/* unprivileged_mode= */ geteuid () != 0 , & xbootldr_uuid );
1493+ r = acquire_xbootldr (/* unprivileged_mode= */ geteuid () != 0 , & xbootldr_uuid , & xbootldr_devid );
14371494 if (arg_print_dollar_boot_path ) {
14381495 if (r == - EACCES )
14391496 return log_error_errno (r , "Failed to determine XBOOTLDR location: %m" );
@@ -1567,7 +1624,14 @@ static int verb_status(int argc, char *argv[], void *userdata) {
15671624 }
15681625
15691626 if (arg_esp_path || arg_xbootldr_path ) {
1570- k = status_entries (arg_esp_path , esp_uuid , arg_xbootldr_path , xbootldr_uuid );
1627+ /* If XBOOTLDR and ESP actually refer to the same block device, suppress XBOOTLDR, since it would find the same entries twice */
1628+ bool same = arg_esp_path && arg_xbootldr_path && devid_set_and_equal (esp_devid , xbootldr_devid );
1629+
1630+ k = status_entries (
1631+ arg_esp_path ,
1632+ esp_uuid ,
1633+ same ? NULL : arg_xbootldr_path ,
1634+ same ? SD_ID128_NULL : xbootldr_uuid );
15711635 if (k < 0 )
15721636 r = k ;
15731637 }
@@ -1578,25 +1642,29 @@ static int verb_status(int argc, char *argv[], void *userdata) {
15781642static int verb_list (int argc , char * argv [], void * userdata ) {
15791643 _cleanup_ (boot_config_free ) BootConfig config = {};
15801644 _cleanup_strv_free_ char * * efi_entries = NULL ;
1645+ dev_t esp_devid = 0 , xbootldr_devid = 0 ;
15811646 int r ;
15821647
15831648 /* If we lack privileges we invoke find_esp_and_warn() in "unprivileged mode" here, which does two things: turn
15841649 * off logging about access errors and turn off potentially privileged device probing. Here we're interested in
15851650 * the latter but not the former, hence request the mode, and log about EACCES. */
15861651
1587- r = acquire_esp (/* unprivileged_mode= */ geteuid () != 0 , /* graceful= */ false, NULL , NULL , NULL , NULL );
1652+ r = acquire_esp (/* unprivileged_mode= */ geteuid () != 0 , /* graceful= */ false, NULL , NULL , NULL , NULL , & esp_devid );
15881653 if (r == - EACCES ) /* We really need the ESP path for this call, hence also log about access errors */
15891654 return log_error_errno (r , "Failed to determine ESP: %m" );
15901655 if (r < 0 )
15911656 return r ;
15921657
1593- r = acquire_xbootldr (/* unprivileged_mode= */ geteuid () != 0 , NULL );
1658+ r = acquire_xbootldr (/* unprivileged_mode= */ geteuid () != 0 , NULL , & xbootldr_devid );
15941659 if (r == - EACCES )
15951660 return log_error_errno (r , "Failed to determine XBOOTLDR partition: %m" );
15961661 if (r < 0 )
15971662 return r ;
15981663
1599- r = boot_entries_load_config (arg_esp_path , arg_xbootldr_path , & config );
1664+ /* If XBOOTLDR and ESP actually refer to the same block device, suppress XBOOTLDR, since it would find the same entries twice */
1665+ bool same = arg_esp_path && arg_xbootldr_path && devid_set_and_equal (esp_devid , xbootldr_devid );
1666+
1667+ r = boot_entries_load_config (arg_esp_path , same ? NULL : arg_xbootldr_path , & config );
16001668 if (r < 0 )
16011669 return r ;
16021670
@@ -1606,7 +1674,7 @@ static int verb_list(int argc, char *argv[], void *userdata) {
16061674 else if (r < 0 )
16071675 log_warning_errno (r , "Failed to determine entries reported by boot loader, ignoring: %m" );
16081676 else
1609- (void ) boot_entries_augment_from_loader (& config , efi_entries );
1677+ (void ) boot_entries_augment_from_loader (& config , efi_entries , /* only_auto= */ false );
16101678
16111679 if (config .n_entries == 0 )
16121680 log_info ("No boot loader entries found." );
@@ -1616,7 +1684,11 @@ static int verb_list(int argc, char *argv[], void *userdata) {
16161684 printf ("Boot Loader Entries:\n" );
16171685
16181686 for (size_t n = 0 ; n < config .n_entries ; n ++ ) {
1619- r = boot_entry_show (config .entries + n , n == (size_t ) config .default_entry );
1687+ r = boot_entry_show (
1688+ config .entries + n ,
1689+ /* show_as_default= */ n == (size_t ) config .default_entry ,
1690+ /* show_as_selected= */ n == (size_t ) config .selected_entry ,
1691+ /* show_discovered= */ true);
16201692 if (r < 0 )
16211693 return r ;
16221694
@@ -1788,7 +1860,7 @@ static int verb_install(int argc, char *argv[], void *userdata) {
17881860 install = streq (argv [0 ], "install" );
17891861 graceful = !install && arg_graceful ; /* support graceful mode for updates */
17901862
1791- r = acquire_esp (/* unprivileged_mode= */ false, graceful , & part , & pstart , & psize , & uuid );
1863+ r = acquire_esp (/* unprivileged_mode= */ false, graceful , & part , & pstart , & psize , & uuid , NULL );
17921864 if (graceful && r == - ENOKEY )
17931865 return 0 ; /* If --graceful is specified and we can't find an ESP, handle this cleanly */
17941866 if (r < 0 )
@@ -1805,7 +1877,7 @@ static int verb_install(int argc, char *argv[], void *userdata) {
18051877 }
18061878 }
18071879
1808- r = acquire_xbootldr (/* unprivileged_mode= */ false, NULL );
1880+ r = acquire_xbootldr (/* unprivileged_mode= */ false, NULL , NULL );
18091881 if (r < 0 )
18101882 return r ;
18111883
@@ -1865,11 +1937,11 @@ static int verb_remove(int argc, char *argv[], void *userdata) {
18651937 sd_id128_t uuid = SD_ID128_NULL ;
18661938 int r , q ;
18671939
1868- r = acquire_esp (/* unprivileged_mode= */ false, /* graceful= */ false, NULL , NULL , NULL , & uuid );
1940+ r = acquire_esp (/* unprivileged_mode= */ false, /* graceful= */ false, NULL , NULL , NULL , & uuid , NULL );
18691941 if (r < 0 )
18701942 return r ;
18711943
1872- r = acquire_xbootldr (/* unprivileged_mode= */ false, NULL );
1944+ r = acquire_xbootldr (/* unprivileged_mode= */ false, NULL , NULL );
18731945 if (r < 0 )
18741946 return r ;
18751947
@@ -2078,7 +2150,7 @@ static int verb_set_efivar(int argc, char *argv[], void *userdata) {
20782150static int verb_random_seed (int argc , char * argv [], void * userdata ) {
20792151 int r ;
20802152
2081- r = find_esp_and_warn (arg_esp_path , false, & arg_esp_path , NULL , NULL , NULL , NULL );
2153+ r = find_esp_and_warn (arg_esp_path , false, & arg_esp_path , NULL , NULL , NULL , NULL , NULL );
20822154 if (r == - ENOKEY ) {
20832155 /* find_esp_and_warn() doesn't warn about ENOKEY, so let's do that on our own */
20842156 if (!arg_graceful )
0 commit comments