diff --git a/src/basic/strv.h b/src/basic/strv.h index 7249d8a311..d7c4b2bcf0 100644 --- a/src/basic/strv.h +++ b/src/basic/strv.h @@ -104,10 +104,6 @@ static inline const char* STRV_IFNOTNULL(const char *x) { return x ?: STRV_IGNORE; } -static inline bool strv_isempty(char * const *l) { - return !l || !*l; -} - int strv_split_full(char ***t, const char *s, const char *separators, ExtractFlags flags); char** strv_split(const char *s, const char *separators); diff --git a/src/boot/boot.c b/src/boot/boot.c index bffedf78e2..904f9bf589 100644 --- a/src/boot/boot.c +++ b/src/boot/boot.c @@ -61,6 +61,9 @@ typedef enum LoaderType { LOADER_SECURE_BOOT_KEYS, LOADER_BAD, /* Marker: this boot loader spec type #1 entry is invalid */ LOADER_IGNORE, /* Marker: this boot loader spec type #1 entry does not match local host */ + LOADER_REBOOT, + LOADER_POWEROFF, + LOADER_FWSETUP, _LOADER_TYPE_MAX, } LoaderType; @@ -82,6 +85,9 @@ typedef enum LoaderType { /* Whether to persistently save the selected entry in an EFI variable, if that's requested. */ #define LOADER_TYPE_SAVE_ENTRY(t) IN_SET(t, LOADER_AUTO, LOADER_EFI, LOADER_LINUX, LOADER_UKI, LOADER_UKI_URL, LOADER_TYPE2_UKI) +/* Whether this item is implemented fully inside of systemd-boot */ +#define LOADER_TYPE_IS_INTERNAL(t) IN_SET(t, LOADER_SECURE_BOOT_KEYS, LOADER_REBOOT, LOADER_POWEROFF, LOADER_FWSETUP) + typedef enum { REBOOT_NO, REBOOT_YES, @@ -319,9 +325,13 @@ static void print_status(Config *config, char16_t *loaded_image_path) { secure_boot_mode_to_string(secure)); printf(" shim: %ls\n", yes_no(shim_loaded())); printf(" TPM: %ls\n", yes_no(tpm_present())); - printf(" console mode: %i/%" PRIi64 " (%zux%zu @%ux%u)\n", - ST->ConOut->Mode->Mode, ST->ConOut->Mode->MaxMode - INT64_C(1), - x_max, y_max, screen_width, screen_height); + printf(" console mode: %i/%" PRIi64 " (%zux%zu", + ST->ConOut->Mode->Mode, ST->ConOut->Mode->MaxMode - INT64_C(1), + x_max, y_max); + if (screen_width > 0 && screen_height > 0) + printf(" @ %ux%u", + screen_width, screen_height); + printf(")\n"); if (!ps_continue()) return; @@ -419,7 +429,7 @@ static void print_status(Config *config, char16_t *loaded_image_path) { printf(" options: %ls\n", entry->options); if (entry->profile > 0) printf(" profile: %u\n", entry->profile); - printf(" internal call: %ls\n", yes_no(!!entry->call)); + printf(" internal call: %ls\n", yes_no(LOADER_TYPE_IS_INTERNAL(entry->type))); printf("counting boots: %ls\n", yes_no(entry->tries_left >= 0)); if (entry->tries_left >= 0) { @@ -1735,6 +1745,12 @@ static void config_load_smbios_entries( } } +static unsigned boot_entry_profile(const BootEntry *a) { + assert(a); + + return a->profile == UINT_MAX ? 0 : a->profile; +} + static int boot_entry_compare(const BootEntry *a, const BootEntry *b) { int r; @@ -1768,6 +1784,10 @@ static int boot_entry_compare(const BootEntry *a, const BootEntry *b) { r = -strverscmp_improved(a->version, b->version); if (r != 0) return r; + + r = CMP(boot_entry_profile(a), boot_entry_profile(b)); + if (r != 0) + return r; } /* Now order by ID. The version is likely part of the ID, thus note that this will generatelly put @@ -1782,7 +1802,7 @@ static int boot_entry_compare(const BootEntry *a, const BootEntry *b) { /* Note: the strverscmp_improved() call above checked for us that we are looking at the very * same id, hence at this point we only need to compare profile numbers, since we know they * belong to the same UKI. */ - r = CMP(a->profile, b->profile); + r = CMP(boot_entry_profile(a), boot_entry_profile(b)); if (r != 0) return r; } @@ -2547,7 +2567,7 @@ static EFI_STATUS initrd_prepare( assert(ret_initrd_pages); assert(ret_initrd_size); - if (entry->type != LOADER_LINUX || !entry->initrd) { + if (entry->type != LOADER_LINUX || strv_isempty(entry->initrd)) { *ret_options = NULL; *ret_initrd_pages = (Pages) {}; *ret_initrd_size = 0; @@ -3047,6 +3067,7 @@ static void config_add_system_entries(Config *config) { if (config->auto_firmware && FLAGS_SET(get_os_indications_supported(), EFI_OS_INDICATIONS_BOOT_TO_FW_UI)) { BootEntry *entry = xnew(BootEntry, 1); *entry = (BootEntry) { + .type = LOADER_FWSETUP, .id = xstrdup16(u"auto-reboot-to-firmware-setup"), .title = xstrdup16(u"Reboot Into Firmware Interface"), .call = call_reboot_into_firmware, @@ -3059,6 +3080,7 @@ static void config_add_system_entries(Config *config) { if (config->auto_poweroff) { BootEntry *entry = xnew(BootEntry, 1); *entry = (BootEntry) { + .type = LOADER_POWEROFF, .id = xstrdup16(u"auto-poweroff"), .title = xstrdup16(u"Power Off The System"), .call = call_poweroff_system, @@ -3071,6 +3093,7 @@ static void config_add_system_entries(Config *config) { if (config->auto_reboot) { BootEntry *entry = xnew(BootEntry, 1); *entry = (BootEntry) { + .type = LOADER_REBOOT, .id = xstrdup16(u"auto-reboot"), .title = xstrdup16(u"Reboot The System"), .call = call_reboot_system, diff --git a/src/fundamental/strv-fundamental.h b/src/fundamental/strv-fundamental.h index 3abcdc4b02..7e7e34822f 100644 --- a/src/fundamental/strv-fundamental.h +++ b/src/fundamental/strv-fundamental.h @@ -2,9 +2,14 @@ #pragma once #include "macro-fundamental.h" +#include "string-util-fundamental.h" #define _STRV_FOREACH(s, l, i) \ for (typeof(*(l)) *s, *i = (l); (s = i) && *i; i++) #define STRV_FOREACH(s, l) \ _STRV_FOREACH(s, l, UNIQ_T(i, UNIQ)) + +static inline bool strv_isempty(sd_char * const *l) { + return !l || !*l; +} diff --git a/src/shared/bootspec.c b/src/shared/bootspec.c index 2a898067f8..36eb2e7086 100644 --- a/src/shared/bootspec.c +++ b/src/shared/bootspec.c @@ -555,6 +555,12 @@ static int boot_loader_read_conf_path(BootConfig *config, const char *root, cons return boot_loader_read_conf(config, f, full); } +static unsigned boot_entry_profile(const BootEntry *a) { + assert(a); + + return a->profile == UINT_MAX ? 0 : a->profile; +} + static int boot_entry_compare(const BootEntry *a, const BootEntry *b) { int r; @@ -583,6 +589,10 @@ static int boot_entry_compare(const BootEntry *a, const BootEntry *b) { r = -strverscmp_improved(a->version, b->version); if (r != 0) return r; + + r = CMP(boot_entry_profile(a), boot_entry_profile(b)); + if (r != 0) + return r; } r = -strverscmp_improved(a->id_without_profile ?: a->id, b->id_without_profile ?: b->id); @@ -592,7 +602,7 @@ static int boot_entry_compare(const BootEntry *a, const BootEntry *b) { if (a->id_without_profile && b->id_without_profile) { /* The strverscmp_improved() call above already established that we are talking about the * same image here, hence order by profile, if there is one */ - r = CMP(a->profile, b->profile); + r = CMP(boot_entry_profile(a), boot_entry_profile(b)); if (r != 0) return r; }