bootctl: also print .uname if present

A UKI might have a version from .osrelease which is not tied to the
kernel version. Pretty print the .uname section too, if present.

         type: Boot Loader Specification Type #2 (UKI, .efi)
        title: Debian GNU/Linux 13 (trixie) (34.186) (selected)
           id: debian-trixie_34.186_x86-64.efi
       source: /boot/efi//EFI/Linux/debian-trixie_34.186_x86-64.efi (on the EFI System Partition)
     sort-key: debian-trixie
      version: 34.186
        uname: 6.12.100+deb13-amd64
        linux: /boot/efi//EFI/Linux/debian-trixie_34.186_x86-64.efi
      profile: 0
This commit is contained in:
Luca Boccassi
2026-08-06 20:16:59 +01:00
committed by Yu Watanabe
parent 5f2ec114b3
commit bf031984ff
4 changed files with 34 additions and 7 deletions

View File

@@ -859,7 +859,14 @@ static int run_link_now(LinkContext *c) {
for (unsigned p = 0; p < UNIFIED_PROFILES_MAX; p++) {
_cleanup_free_ char *osrelease = NULL, *profile = NULL;
r = pe_find_uki_sections(c->kernel_fd, j, p, &osrelease, &profile, /* ret_cmdline= */ NULL);
r = pe_find_uki_sections(
c->kernel_fd,
j,
p,
&osrelease,
&profile,
/* ret_cmdline= */ NULL,
/* ret_uname= */ NULL);
if (r < 0)
return r;
if (r == 0) /* this profile does not exist, we are done */

View File

@@ -139,6 +139,7 @@ static void boot_entry_free(BootEntry *entry) {
free(entry->show_title);
free(entry->sort_key);
free(entry->version);
free(entry->uname);
free(entry->machine_id);
free(entry->architecture);
strv_free(entry->options);
@@ -924,6 +925,7 @@ static int boot_entry_load_unified(
const char *osrelease_text,
const char *profile_text,
const char *cmdline_text,
const char *uname_text,
BootEntry *ret) {
int r;
@@ -1010,6 +1012,12 @@ static int boot_entry_load_unified(
if (!tmp.options)
return log_oom();
if (uname_text) {
tmp.uname = strdup(uname_text);
if (!tmp.uname)
return log_oom();
}
if (profile_title)
tmp.title = strjoin(good_name, " (", profile_title, ")");
else if (profile_id)
@@ -1158,9 +1166,10 @@ int pe_find_uki_sections(
unsigned profile,
char **ret_osrelease,
char **ret_profile,
char **ret_cmdline) {
char **ret_cmdline,
char **ret_uname) {
_cleanup_free_ char *osrelease_text = NULL, *profile_text = NULL, *cmdline_text = NULL;
_cleanup_free_ char *osrelease_text = NULL, *profile_text = NULL, *cmdline_text = NULL, *uname_text = NULL;
_cleanup_free_ IMAGE_SECTION_HEADER *sections = NULL;
_cleanup_free_ PeHeader *pe_header = NULL;
int r;
@@ -1196,6 +1205,7 @@ int pe_find_uki_sections(
{ ".osrel", &osrelease_text },
{ ".profile", &profile_text },
{ ".cmdline", &cmdline_text },
{ ".uname", &uname_text },
};
FOREACH_ELEMENT(t, table) {
@@ -1230,6 +1240,8 @@ int pe_find_uki_sections(
*ret_profile = TAKE_PTR(profile_text);
if (ret_cmdline)
*ret_cmdline = TAKE_PTR(cmdline_text);
if (ret_uname)
*ret_uname = TAKE_PTR(uname_text);
return 1;
nothing:
@@ -1239,6 +1251,8 @@ nothing:
*ret_profile = NULL;
if (ret_cmdline)
*ret_cmdline = NULL;
if (ret_uname)
*ret_uname = NULL;
return 0;
}
@@ -1467,9 +1481,9 @@ static int boot_entries_find_unified(
return log_oom();
for (unsigned p = 0; p < UNIFIED_PROFILES_MAX; p++) {
_cleanup_free_ char *osrelease = NULL, *profile = NULL, *cmdline = NULL;
_cleanup_free_ char *osrelease = NULL, *profile = NULL, *cmdline = NULL, *uname = NULL;
r = pe_find_uki_sections(fd, j, p, &osrelease, &profile, &cmdline);
r = pe_find_uki_sections(fd, j, p, &osrelease, &profile, &cmdline, &uname);
if (r == 0) /* this profile does not exist, we are done */
break;
if (r < 0)
@@ -1480,7 +1494,7 @@ static int boot_entries_find_unified(
BootEntry *entry = config->entries + config->n_entries;
if (boot_entry_load_unified(root, source, j, p, osrelease, profile, cmdline, entry) < 0)
if (boot_entry_load_unified(root, source, j, p, osrelease, profile, cmdline, uname, entry) < 0)
continue;
/* Look for .efi.extra.d/ */
@@ -2204,6 +2218,8 @@ int show_boot_entry(
printf(" sort-key: %s\n", e->sort_key);
if (e->version)
printf(" version: %s\n", e->version);
if (e->uname)
printf(" uname: %s\n", e->uname);
if (e->machine_id)
printf(" machine-id: %s\n", e->machine_id);
if (e->architecture)
@@ -2274,6 +2290,7 @@ int boot_entry_to_json(const BootConfig *c, size_t i, sd_json_variant **ret) {
SD_JSON_BUILD_PAIR_CONDITION(!!boot_entry_title(e), "showTitle", SD_JSON_BUILD_STRING(boot_entry_title(e))),
SD_JSON_BUILD_PAIR_CONDITION(!!e->sort_key, "sortKey", SD_JSON_BUILD_STRING(e->sort_key)),
SD_JSON_BUILD_PAIR_CONDITION(!!e->version, "version", SD_JSON_BUILD_STRING(e->version)),
SD_JSON_BUILD_PAIR_CONDITION(!!e->uname, "uname", SD_JSON_BUILD_STRING(e->uname)),
SD_JSON_BUILD_PAIR_CONDITION(!!e->machine_id, "machineId", SD_JSON_BUILD_STRING(e->machine_id)),
SD_JSON_BUILD_PAIR_CONDITION(!!e->architecture, "architecture", SD_JSON_BUILD_STRING(e->architecture)),
SD_JSON_BUILD_PAIR_CONDITION(!!opts, "options", SD_JSON_BUILD_STRING(opts)),

View File

@@ -55,6 +55,7 @@ typedef struct BootEntry {
char *show_title;
char *sort_key;
char *version;
char *uname;
char *machine_id;
char *architecture;
char **options;
@@ -175,6 +176,6 @@ int boot_filename_extract_tries(const char *fname, char **ret_stripped, unsigned
int boot_entry_to_json(const BootConfig *c, size_t i, sd_json_variant **ret);
int pe_find_uki_sections(int fd, const char *path, unsigned profile, char **ret_osrelease, char **ret_profile, char **ret_cmdline);
int pe_find_uki_sections(int fd, const char *path, unsigned profile, char **ret_osrelease, char **ret_profile, char **ret_cmdline, char **ret_uname);
int bootspec_extract_osrelease(const char *text, char **ret_good_name, char **ret_good_version, char **ret_good_sort_key, char **ret_os_id, char **ret_os_version_id, char **ret_image_id, char **ret_image_version);

View File

@@ -48,6 +48,8 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE(
SD_VARLINK_DEFINE_FIELD(sortKey, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("The version of the entry"),
SD_VARLINK_DEFINE_FIELD(version, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("The kernel version from the UKI's .uname section"),
SD_VARLINK_DEFINE_FIELD(uname, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("Machine ID of the OS installation belonging to the entry, if known"),
SD_VARLINK_DEFINE_FIELD(machineId, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("EFI architecture name for this entry"),