Skip to content

Commit f3376ee

Browse files
authored
Merge pull request systemd#22487 from poettering/bootspec-source-flags
bootctl: show all discovered entries, but show state + type in details
2 parents 88586e5 + d5ac1d4 commit f3376ee

File tree

7 files changed

+323
-115
lines changed

7 files changed

+323
-115
lines changed

TODO

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,8 @@ Janitorial Clean-ups:
7878

7979
Features:
8080

81+
* bootspec: remove tries counter from boot entry ids
82+
8183
* automatically ignore threaded cgroups in cg_xyz().
8284

8385
* add linker script that implicitly adds symbol for build ID and new coredump

src/basic/stat-util.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,3 +115,9 @@ int statx_fallback(int dfd, const char *path, int flags, unsigned mask, struct s
115115
struct new_statx nsx; \
116116
} var
117117
#endif
118+
119+
static inline bool devid_set_and_equal(dev_t a, dev_t b) {
120+
/* Returns true if a and b definitely refer to the same device. If either is zero, this means "don't
121+
* know" and we'll return false */
122+
return a == b && a != 0;
123+
}

src/boot/bless-boot.c

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "parse-util.h"
1515
#include "path-util.h"
1616
#include "pretty-print.h"
17+
#include "stat-util.h"
1718
#include "sync-util.h"
1819
#include "terminal-util.h"
1920
#include "util.h"
@@ -98,17 +99,18 @@ static int parse_argv(int argc, char *argv[]) {
9899

99100
static int acquire_path(void) {
100101
_cleanup_free_ char *esp_path = NULL, *xbootldr_path = NULL;
102+
dev_t esp_devid = 0, xbootldr_devid = 0;
101103
char **a;
102104
int r;
103105

104106
if (!strv_isempty(arg_path))
105107
return 0;
106108

107-
r = find_esp_and_warn(NULL, false, &esp_path, NULL, NULL, NULL, NULL);
109+
r = find_esp_and_warn(NULL, /* unprivileged_mode= */ false, &esp_path, NULL, NULL, NULL, NULL, &esp_devid);
108110
if (r < 0 && r != -ENOKEY) /* ENOKEY means not found, and is the only error the function won't log about on its own */
109111
return r;
110112

111-
r = find_xbootldr_and_warn(NULL, false, &xbootldr_path, NULL);
113+
r = find_xbootldr_and_warn(NULL, /* unprivileged_mode= */ false, &xbootldr_path, NULL, &xbootldr_devid);
112114
if (r < 0 && r != -ENOKEY)
113115
return r;
114116

@@ -117,8 +119,10 @@ static int acquire_path(void) {
117119
"Couldn't find $BOOT partition. It is recommended to mount it to /boot.\n"
118120
"Alternatively, use --path= to specify path to mount point.");
119121

120-
if (esp_path)
122+
if (esp_path && xbootldr_path && !devid_set_and_equal(esp_devid, xbootldr_devid)) /* in case the two paths refer to the same inode, suppress one */
121123
a = strv_new(esp_path, xbootldr_path);
124+
else if (esp_path)
125+
a = strv_new(esp_path);
122126
else
123127
a = strv_new(xbootldr_path);
124128
if (!a)
@@ -130,7 +134,7 @@ static int acquire_path(void) {
130134
_cleanup_free_ char *j = NULL;
131135

132136
j = strv_join(arg_path, ":");
133-
log_debug("Using %s as boot loader drop-in search path.", j);
137+
log_debug("Using %s as boot loader drop-in search path.", strna(j));
134138
}
135139

136140
return 0;

src/boot/bootctl.c

Lines changed: 96 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
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) {
13881444
static 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

14211477
static 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) {
15781642
static 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) {
20782150
static 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)

src/login/logind-dbus.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2933,9 +2933,9 @@ static int boot_loader_entry_exists(Manager *m, const char *id) {
29332933

29342934
r = manager_read_efi_boot_loader_entries(m);
29352935
if (r >= 0)
2936-
(void) boot_entries_augment_from_loader(&config, m->efi_boot_loader_entries);
2936+
(void) boot_entries_augment_from_loader(&config, m->efi_boot_loader_entries, /* auto_only= */ true);
29372937

2938-
return boot_config_has_entry(&config, id);
2938+
return !!boot_config_find_entry(&config, id);
29392939
}
29402940

29412941
static int method_set_reboot_to_boot_loader_entry(
@@ -3091,7 +3091,7 @@ static int property_get_boot_loader_entries(
30913091

30923092
r = manager_read_efi_boot_loader_entries(m);
30933093
if (r >= 0)
3094-
(void) boot_entries_augment_from_loader(&config, m->efi_boot_loader_entries);
3094+
(void) boot_entries_augment_from_loader(&config, m->efi_boot_loader_entries, /* auto_only= */ true);
30953095

30963096
r = sd_bus_message_open_container(reply, 'a', "s");
30973097
if (r < 0)

0 commit comments

Comments
 (0)