mirror of
https://github.com/systemd/systemd.git
synced 2025-03-31 14:50:15 +03:00
Merge pull request #19896 from keszybz/systemd-efi-options-hint
Print hint in bootctl when systemd-efi-options output is out-of-date
This commit is contained in:
commit
8f12ee7178
@ -125,6 +125,7 @@ manpages = [
|
||||
'SD_ID128_FORMAT_VAL',
|
||||
'SD_ID128_MAKE',
|
||||
'SD_ID128_MAKE_STR',
|
||||
'SD_ID128_MAKE_UUID_STR',
|
||||
'SD_ID128_NULL',
|
||||
'SD_ID128_UUID_FORMAT_STR',
|
||||
'sd_id128_equal',
|
||||
|
@ -24,6 +24,7 @@
|
||||
<refname>SD_ID128_FORMAT_VAL</refname>
|
||||
<refname>SD_ID128_MAKE</refname>
|
||||
<refname>SD_ID128_MAKE_STR</refname>
|
||||
<refname>SD_ID128_MAKE_UUID_STR</refname>
|
||||
<refname>SD_ID128_NULL</refname>
|
||||
<refname>SD_ID128_UUID_FORMAT_STR</refname>
|
||||
<refname>sd_id128_equal</refname>
|
||||
@ -121,10 +122,12 @@ int main(int argc, char **argv) {
|
||||
return 0;
|
||||
}</programlisting>
|
||||
|
||||
<para><constant>SD_ID128_UUID_FORMAT_STR</constant> is similar to
|
||||
<constant>SD_ID128_FORMAT_STR</constant> but includes separating hyphens to conform to the "<ulink
|
||||
url="https://en.wikipedia.org/wiki/Universally_unique_identifier#Format">canonical
|
||||
representation</ulink>". This formats the string based on <ulink
|
||||
<para><constant>SD_ID128_UUID_FORMAT_STR</constant> and <function>SD_ID128_MAKE_UUID_STR()</function>
|
||||
are similar to
|
||||
<constant>SD_ID128_FORMAT_STR</constant> and <function>SD_ID128_MAKE_STR()</function>,
|
||||
but include separating hyphens to conform to the
|
||||
"<ulink url="https://en.wikipedia.org/wiki/Universally_unique_identifier#Format">canonical representation</ulink>".
|
||||
They format the string based on <ulink
|
||||
url="https://tools.ietf.org/html/rfc4122">RFC4122</ulink> Variant 1 rules, i.e. converting from Big
|
||||
Endian byte order. This matches behaviour of most other Linux userspace infrastructure. It's probably
|
||||
best to avoid UUIDs of other variants, in order to avoid unnecessary ambiguities. All 128-bit IDs
|
||||
|
@ -30,48 +30,22 @@
|
||||
#define EFI_N_RETRIES_TOTAL 25
|
||||
#define EFI_RETRY_DELAY (50 * USEC_PER_MSEC)
|
||||
|
||||
char* efi_variable_path(sd_id128_t vendor, const char *name) {
|
||||
char *p;
|
||||
|
||||
if (asprintf(&p,
|
||||
"/sys/firmware/efi/efivars/%s-" SD_ID128_UUID_FORMAT_STR,
|
||||
name, SD_ID128_FORMAT_VAL(vendor)) < 0)
|
||||
return NULL;
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
static char* efi_variable_cache_path(sd_id128_t vendor, const char *name) {
|
||||
char *p;
|
||||
|
||||
if (asprintf(&p,
|
||||
"/run/systemd/efivars/%s-" SD_ID128_UUID_FORMAT_STR,
|
||||
name, SD_ID128_FORMAT_VAL(vendor)) < 0)
|
||||
return NULL;
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
int efi_get_variable(
|
||||
sd_id128_t vendor,
|
||||
const char *name,
|
||||
const char *variable,
|
||||
uint32_t *ret_attribute,
|
||||
void **ret_value,
|
||||
size_t *ret_size) {
|
||||
|
||||
_cleanup_close_ int fd = -1;
|
||||
_cleanup_free_ char *p = NULL;
|
||||
_cleanup_free_ void *buf = NULL;
|
||||
struct stat st;
|
||||
usec_t begin = 0; /* Unnecessary initialization to appease gcc */
|
||||
uint32_t a;
|
||||
ssize_t n;
|
||||
|
||||
assert(name);
|
||||
assert(variable);
|
||||
|
||||
p = efi_variable_path(vendor, name);
|
||||
if (!p)
|
||||
return -ENOMEM;
|
||||
const char *p = strjoina("/sys/firmware/efi/efivars/", variable);
|
||||
|
||||
if (!ret_value && !ret_size && !ret_attribute) {
|
||||
/* If caller is not interested in anything, just check if the variable exists and is
|
||||
@ -136,7 +110,8 @@ int efi_get_variable(
|
||||
return log_debug_errno(errno, "Failed to read value of EFI variable %s: %m", p);
|
||||
assert(n <= st.st_size - 4);
|
||||
|
||||
/* Always NUL terminate (3 bytes, to properly protect UTF-16, even if truncated in the middle of a character) */
|
||||
/* Always NUL-terminate (3 bytes, to properly protect UTF-16, even if truncated in the middle
|
||||
* of a character) */
|
||||
((char*) buf)[n] = 0;
|
||||
((char*) buf)[n + 1] = 0;
|
||||
((char*) buf)[n + 2] = 0;
|
||||
@ -150,8 +125,8 @@ int efi_get_variable(
|
||||
|
||||
end = now(CLOCK_MONOTONIC);
|
||||
if (end > begin + EFI_RETRY_DELAY)
|
||||
log_debug("Detected slow EFI variable read access on " SD_ID128_FORMAT_STR "-%s: %s",
|
||||
SD_ID128_FORMAT_VAL(vendor), name, format_timespan(ts, sizeof(ts), end - begin, 1));
|
||||
log_debug("Detected slow EFI variable read access on %s: %s",
|
||||
variable, format_timespan(ts, sizeof(ts), end - begin, 1));
|
||||
}
|
||||
|
||||
/* Note that efivarfs interestingly doesn't require ftruncate() to update an existing EFI variable
|
||||
@ -169,13 +144,13 @@ int efi_get_variable(
|
||||
return 0;
|
||||
}
|
||||
|
||||
int efi_get_variable_string(sd_id128_t vendor, const char *name, char **p) {
|
||||
int efi_get_variable_string(const char *variable, char **p) {
|
||||
_cleanup_free_ void *s = NULL;
|
||||
size_t ss = 0;
|
||||
int r;
|
||||
char *x;
|
||||
|
||||
r = efi_get_variable(vendor, name, NULL, &s, &ss);
|
||||
r = efi_get_variable(variable, NULL, &s, &ss);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -187,28 +162,20 @@ int efi_get_variable_string(sd_id128_t vendor, const char *name, char **p) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int efi_set_variable(
|
||||
sd_id128_t vendor,
|
||||
const char *name,
|
||||
const void *value,
|
||||
size_t size) {
|
||||
|
||||
int efi_set_variable(const char *variable, const void *value, size_t size) {
|
||||
struct var {
|
||||
uint32_t attr;
|
||||
char buf[];
|
||||
} _packed_ * _cleanup_free_ buf = NULL;
|
||||
_cleanup_free_ char *p = NULL;
|
||||
_cleanup_close_ int fd = -1;
|
||||
bool saved_flags_valid = false;
|
||||
unsigned saved_flags;
|
||||
int r;
|
||||
|
||||
assert(name);
|
||||
assert(variable);
|
||||
assert(value || size == 0);
|
||||
|
||||
p = efi_variable_path(vendor, name);
|
||||
if (!p)
|
||||
return -ENOMEM;
|
||||
const char *p = strjoina("/sys/firmware/efi/efivars/", variable);
|
||||
|
||||
/* Newer efivarfs protects variables that are not in an allow list with FS_IMMUTABLE_FL by default,
|
||||
* to protect them for accidental removal and modification. We are not changing these variables
|
||||
@ -274,14 +241,14 @@ finish:
|
||||
return r;
|
||||
}
|
||||
|
||||
int efi_set_variable_string(sd_id128_t vendor, const char *name, const char *v) {
|
||||
int efi_set_variable_string(const char *variable, const char *value) {
|
||||
_cleanup_free_ char16_t *u16 = NULL;
|
||||
|
||||
u16 = utf8_to_utf16(v, strlen(v));
|
||||
u16 = utf8_to_utf16(value, strlen(value));
|
||||
if (!u16)
|
||||
return -ENOMEM;
|
||||
|
||||
return efi_set_variable(vendor, name, u16, (char16_strlen(u16) + 1) * sizeof(char16_t));
|
||||
return efi_set_variable(variable, u16, (char16_strlen(u16) + 1) * sizeof(char16_t));
|
||||
}
|
||||
|
||||
bool is_efi_boot(void) {
|
||||
@ -300,7 +267,7 @@ bool is_efi_boot(void) {
|
||||
return cache;
|
||||
}
|
||||
|
||||
static int read_flag(const char *varname) {
|
||||
static int read_flag(const char *variable) {
|
||||
_cleanup_free_ void *v = NULL;
|
||||
uint8_t b;
|
||||
size_t s;
|
||||
@ -309,7 +276,7 @@ static int read_flag(const char *varname) {
|
||||
if (!is_efi_boot()) /* If this is not an EFI boot, assume the queried flags are zero */
|
||||
return 0;
|
||||
|
||||
r = efi_get_variable(EFI_VENDOR_GLOBAL, varname, NULL, &v, &s);
|
||||
r = efi_get_variable(variable, NULL, &v, &s);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -324,7 +291,7 @@ bool is_efi_secure_boot(void) {
|
||||
static int cache = -1;
|
||||
|
||||
if (cache < 0)
|
||||
cache = read_flag("SecureBoot");
|
||||
cache = read_flag(EFI_GLOBAL_VARIABLE(SecureBoot));
|
||||
|
||||
return cache > 0;
|
||||
}
|
||||
@ -333,13 +300,12 @@ bool is_efi_secure_boot_setup_mode(void) {
|
||||
static int cache = -1;
|
||||
|
||||
if (cache < 0)
|
||||
cache = read_flag("SetupMode");
|
||||
cache = read_flag(EFI_GLOBAL_VARIABLE(SetupMode));
|
||||
|
||||
return cache > 0;
|
||||
}
|
||||
|
||||
int cache_efi_options_variable(void) {
|
||||
_cleanup_free_ char *line = NULL, *cachepath = NULL;
|
||||
static int read_efi_options_variable(char **line) {
|
||||
int r;
|
||||
|
||||
/* In SecureBoot mode this is probably not what you want. As your cmdline is cryptographically signed
|
||||
@ -350,39 +316,39 @@ int cache_efi_options_variable(void) {
|
||||
* (NB: For testing purposes, we still check the $SYSTEMD_EFI_OPTIONS env var before accessing this
|
||||
* cache, even when in SecureBoot mode.) */
|
||||
if (is_efi_secure_boot()) {
|
||||
_cleanup_free_ char *k = NULL;
|
||||
|
||||
k = efi_variable_path(EFI_VENDOR_SYSTEMD, "SystemdOptions");
|
||||
if (!k)
|
||||
return -ENOMEM;
|
||||
|
||||
/* Let's be helpful with the returned error and check if the variable exists at all. If it
|
||||
* does, let's return a recognizable error (EPERM), and if not ENODATA. */
|
||||
|
||||
if (access(k, F_OK) < 0)
|
||||
if (access(EFIVAR_PATH(EFI_SYSTEMD_VARIABLE(SystemdOptions)), F_OK) < 0)
|
||||
return errno == ENOENT ? -ENODATA : -errno;
|
||||
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
r = efi_get_variable_string(EFI_VENDOR_SYSTEMD, "SystemdOptions", &line);
|
||||
r = efi_get_variable_string(EFI_SYSTEMD_VARIABLE(SystemdOptions), line);
|
||||
if (r == -ENOENT)
|
||||
return -ENODATA;
|
||||
return r;
|
||||
}
|
||||
|
||||
int cache_efi_options_variable(void) {
|
||||
_cleanup_free_ char *line = NULL;
|
||||
int r;
|
||||
|
||||
r = read_efi_options_variable(&line);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
cachepath = efi_variable_cache_path(EFI_VENDOR_SYSTEMD, "SystemdOptions");
|
||||
if (!cachepath)
|
||||
return -ENOMEM;
|
||||
|
||||
return write_string_file(cachepath, line, WRITE_STRING_FILE_ATOMIC|WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_MKDIR_0755);
|
||||
return write_string_file(EFIVAR_CACHE_PATH(EFI_SYSTEMD_VARIABLE(SystemdOptions)), line,
|
||||
WRITE_STRING_FILE_ATOMIC|WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_MKDIR_0755);
|
||||
}
|
||||
|
||||
int systemd_efi_options_variable(char **line) {
|
||||
const char *e;
|
||||
_cleanup_free_ char *cachepath = NULL;
|
||||
int r;
|
||||
|
||||
/* Returns the contents of the variable for current boot from the cache. */
|
||||
|
||||
assert(line);
|
||||
|
||||
/* For testing purposes it is sometimes useful to be able to override this */
|
||||
@ -398,11 +364,37 @@ int systemd_efi_options_variable(char **line) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
cachepath = efi_variable_cache_path(EFI_VENDOR_SYSTEMD, "SystemdOptions");
|
||||
if (!cachepath)
|
||||
return -ENOMEM;
|
||||
r = read_one_line_file(EFIVAR_CACHE_PATH(EFI_SYSTEMD_VARIABLE(SystemdOptions)), line);
|
||||
if (r == -ENOENT)
|
||||
return -ENODATA;
|
||||
return r;
|
||||
}
|
||||
|
||||
r = read_one_line_file(cachepath, line);
|
||||
static inline int compare_stat_mtime(const struct stat *a, const struct stat *b) {
|
||||
return CMP(timespec_load(&a->st_mtim), timespec_load(&b->st_mtim));
|
||||
}
|
||||
|
||||
int systemd_efi_options_efivarfs_if_newer(char **line) {
|
||||
struct stat a = {}, b;
|
||||
int r;
|
||||
|
||||
if (stat(EFIVAR_PATH(EFI_SYSTEMD_VARIABLE(SystemdOptions)), &a) < 0 && errno != ENOENT)
|
||||
return log_debug_errno(errno, "Failed to stat EFI variable SystemdOptions: %m");
|
||||
|
||||
if (stat(EFIVAR_CACHE_PATH(EFI_SYSTEMD_VARIABLE(SystemdOptions)), &b) < 0) {
|
||||
if (errno != -ENOENT)
|
||||
log_debug_errno(errno, "Failed to stat "EFIVAR_CACHE_PATH(EFI_SYSTEMD_VARIABLE(SystemdOptions))": %m");
|
||||
} else if (compare_stat_mtime(&a, &b) > 0)
|
||||
log_debug("Variable SystemdOptions in evifarfs is newer than in cache.");
|
||||
else {
|
||||
log_debug("Variable SystemdOptions in cache is up to date.");
|
||||
*line = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = read_efi_options_variable(line);
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "Failed to read SystemdOptions EFI variable: %m");
|
||||
if (r == -ENOENT)
|
||||
return -ENODATA;
|
||||
return r;
|
||||
|
@ -12,20 +12,39 @@
|
||||
|
||||
#include "time-util.h"
|
||||
|
||||
#define EFI_VENDOR_LOADER SD_ID128_MAKE(4a,67,b0,82,0a,4c,41,cf,b6,c7,44,0b,29,bb,8c,4f)
|
||||
#define EFI_VENDOR_GLOBAL SD_ID128_MAKE(8b,e4,df,61,93,ca,11,d2,aa,0d,00,e0,98,03,2b,8c)
|
||||
#define EFI_VENDOR_SYSTEMD SD_ID128_MAKE(8c,f2,64,4b,4b,0b,42,8f,93,87,6d,87,60,50,dc,67)
|
||||
#define EFI_VENDOR_LOADER SD_ID128_MAKE(4a,67,b0,82,0a,4c,41,cf,b6,c7,44,0b,29,bb,8c,4f)
|
||||
#define EFI_VENDOR_LOADER_STR SD_ID128_MAKE_UUID_STR(4a,67,b0,82,0a,4c,41,cf,b6,c7,44,0b,29,bb,8c,4f)
|
||||
#define EFI_VENDOR_GLOBAL SD_ID128_MAKE(8b,e4,df,61,93,ca,11,d2,aa,0d,00,e0,98,03,2b,8c)
|
||||
#define EFI_VENDOR_GLOBAL_STR SD_ID128_MAKE_UUID_STR(8b,e4,df,61,93,ca,11,d2,aa,0d,00,e0,98,03,2b,8c)
|
||||
#define EFI_VENDOR_SYSTEMD SD_ID128_MAKE(8c,f2,64,4b,4b,0b,42,8f,93,87,6d,87,60,50,dc,67)
|
||||
#define EFI_VENDOR_SYSTEMD_STR SD_ID128_MAKE_UUID_STR(8c,f2,64,4b,4b,0b,42,8f,93,87,6d,87,60,50,dc,67)
|
||||
#define EFI_VARIABLE_NON_VOLATILE 0x0000000000000001
|
||||
#define EFI_VARIABLE_BOOTSERVICE_ACCESS 0x0000000000000002
|
||||
#define EFI_VARIABLE_RUNTIME_ACCESS 0x0000000000000004
|
||||
|
||||
/* Note that the <lowercaseuuid>-<varname> naming scheme is an efivarfs convention, i.e. part of the Linux
|
||||
* API file system implementation for EFI. EFI itself processes UIDS in binary form.
|
||||
*/
|
||||
|
||||
#define EFI_VENDOR_VARIABLE_STR(vendor, name) name "-" vendor
|
||||
|
||||
#define EFI_GLOBAL_VARIABLE_STR(name) EFI_VENDOR_VARIABLE_STR(EFI_VENDOR_GLOBAL_STR, name)
|
||||
#define EFI_LOADER_VARIABLE_STR(name) EFI_VENDOR_VARIABLE_STR(EFI_VENDOR_LOADER_STR, name)
|
||||
#define EFI_SYSTEMD_VARIABLE_STR(name) EFI_VENDOR_VARIABLE_STR(EFI_VENDOR_SYSTEMD_STR, name)
|
||||
|
||||
#define EFI_GLOBAL_VARIABLE(name) EFI_GLOBAL_VARIABLE_STR(STRINGIFY(name))
|
||||
#define EFI_LOADER_VARIABLE(name) EFI_LOADER_VARIABLE_STR(STRINGIFY(name))
|
||||
#define EFI_SYSTEMD_VARIABLE(name) EFI_SYSTEMD_VARIABLE_STR(STRINGIFY(name))
|
||||
|
||||
#define EFIVAR_PATH(variable) "/sys/firmware/efi/efivars/" variable
|
||||
#define EFIVAR_CACHE_PATH(variable) "/run/systemd/efivars/" variable
|
||||
|
||||
#if ENABLE_EFI
|
||||
|
||||
char* efi_variable_path(sd_id128_t vendor, const char *name);
|
||||
int efi_get_variable(sd_id128_t vendor, const char *name, uint32_t *attribute, void **value, size_t *size);
|
||||
int efi_get_variable_string(sd_id128_t vendor, const char *name, char **p);
|
||||
int efi_set_variable(sd_id128_t vendor, const char *name, const void *value, size_t size);
|
||||
int efi_set_variable_string(sd_id128_t vendor, const char *name, const char *p);
|
||||
int efi_get_variable(const char *variable, uint32_t *attribute, void **value, size_t *size);
|
||||
int efi_get_variable_string(const char *variable, char **p);
|
||||
int efi_set_variable(const char *variable, const void *value, size_t size);
|
||||
int efi_set_variable_string(const char *variable, const char *p);
|
||||
|
||||
bool is_efi_boot(void);
|
||||
bool is_efi_secure_boot(void);
|
||||
@ -33,26 +52,23 @@ bool is_efi_secure_boot_setup_mode(void);
|
||||
|
||||
int cache_efi_options_variable(void);
|
||||
int systemd_efi_options_variable(char **line);
|
||||
int systemd_efi_options_efivarfs_if_newer(char **line);
|
||||
|
||||
#else
|
||||
|
||||
static inline char* efi_variable_path(sd_id128_t vendor, const char *name) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline int efi_get_variable(sd_id128_t vendor, const char *name, uint32_t *attribute, void **value, size_t *size) {
|
||||
static inline int efi_get_variable(const char *variable, uint32_t *attribute, void **value, size_t *size) {
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline int efi_get_variable_string(sd_id128_t vendor, const char *name, char **p) {
|
||||
static inline int efi_get_variable_string(const char *variable, char **p) {
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline int efi_set_variable(sd_id128_t vendor, const char *name, const void *value, size_t size) {
|
||||
static inline int efi_set_variable(const char *variable, const void *value, size_t size) {
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline int efi_set_variable_string(sd_id128_t vendor, const char *name, const char *p) {
|
||||
static inline int efi_set_variable_string(const char *variable, const char *p) {
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
@ -76,4 +92,7 @@ static inline int systemd_efi_options_variable(char **line) {
|
||||
return -ENODATA;
|
||||
}
|
||||
|
||||
static inline int systemd_efi_options_efivarfs_if_newer(char **line) {
|
||||
return -ENODATA;
|
||||
}
|
||||
#endif
|
||||
|
@ -47,7 +47,7 @@ int main(int argc, char *argv[]) {
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
if (access("/sys/firmware/efi/efivars/LoaderBootCountPath-4a67b082-0a4c-41cf-b6c7-440b29bb8c4f", F_OK) < 0) {
|
||||
if (access(EFIVAR_PATH(EFI_LOADER_VARIABLE(LoaderBootCountPath)), F_OK) < 0) {
|
||||
|
||||
if (errno == ENOENT) {
|
||||
log_debug_errno(errno, "Skipping generator, not booted with boot counting in effect.");
|
||||
|
@ -212,7 +212,7 @@ static int acquire_boot_count_path(
|
||||
uint64_t left, done;
|
||||
int r;
|
||||
|
||||
r = efi_get_variable_string(EFI_VENDOR_LOADER, "LoaderBootCountPath", &path);
|
||||
r = efi_get_variable_string(EFI_LOADER_VARIABLE(LoaderBootCountPath), &path);
|
||||
if (r == -ENOENT)
|
||||
return -EUNATCH; /* in this case, let the caller print a message */
|
||||
if (r < 0)
|
||||
|
@ -288,7 +288,7 @@ static int print_efi_option(uint16_t id, bool in_order) {
|
||||
|
||||
static int status_variables(void) {
|
||||
_cleanup_free_ uint16_t *options = NULL, *order = NULL;
|
||||
int n_options, n_order, i;
|
||||
int n_options, n_order;
|
||||
|
||||
n_options = efi_get_boot_options(&options);
|
||||
if (n_options == -ENOENT)
|
||||
@ -306,14 +306,12 @@ static int status_variables(void) {
|
||||
|
||||
/* print entries in BootOrder first */
|
||||
printf("Boot Loaders Listed in EFI Variables:\n");
|
||||
for (i = 0; i < n_order; i++)
|
||||
for (int i = 0; i < n_order; i++)
|
||||
print_efi_option(order[i], true);
|
||||
|
||||
/* print remaining entries */
|
||||
for (i = 0; i < n_options; i++) {
|
||||
int j;
|
||||
|
||||
for (j = 0; j < n_order; j++)
|
||||
for (int i = 0; i < n_options; i++) {
|
||||
for (int j = 0; j < n_order; j++)
|
||||
if (options[i] == order[j])
|
||||
goto next_option;
|
||||
|
||||
@ -726,7 +724,7 @@ static int find_slot(sd_id128_t uuid, const char *path, uint16_t *id) {
|
||||
static int insert_into_order(uint16_t slot, bool first) {
|
||||
_cleanup_free_ uint16_t *order = NULL;
|
||||
uint16_t *t;
|
||||
int n, i;
|
||||
int n;
|
||||
|
||||
n = efi_get_boot_order(&order);
|
||||
if (n <= 0)
|
||||
@ -738,7 +736,7 @@ static int insert_into_order(uint16_t slot, bool first) {
|
||||
return 0;
|
||||
|
||||
/* are we already in the boot order? */
|
||||
for (i = 0; i < n; i++) {
|
||||
for (int i = 0; i < n; i++) {
|
||||
if (order[i] != slot)
|
||||
continue;
|
||||
|
||||
@ -770,13 +768,13 @@ static int insert_into_order(uint16_t slot, bool first) {
|
||||
|
||||
static int remove_from_order(uint16_t slot) {
|
||||
_cleanup_free_ uint16_t *order = NULL;
|
||||
int n, i;
|
||||
int n;
|
||||
|
||||
n = efi_get_boot_order(&order);
|
||||
if (n <= 0)
|
||||
return n;
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
for (int i = 0; i < n; i++) {
|
||||
if (order[i] != slot)
|
||||
continue;
|
||||
|
||||
@ -979,29 +977,29 @@ static int remove_variables(sd_id128_t uuid, const char *path, bool in_order) {
|
||||
}
|
||||
|
||||
static int remove_loader_variables(void) {
|
||||
const char *p;
|
||||
const char *variable;
|
||||
int r = 0;
|
||||
|
||||
/* Remove all persistent loader variables we define */
|
||||
|
||||
FOREACH_STRING(p,
|
||||
"LoaderConfigTimeout",
|
||||
"LoaderConfigTimeoutOneShot",
|
||||
"LoaderEntryDefault",
|
||||
"LoaderEntryOneShot",
|
||||
"LoaderSystemToken") {
|
||||
FOREACH_STRING(variable,
|
||||
EFI_LOADER_VARIABLE(LoaderConfigTimeout),
|
||||
EFI_LOADER_VARIABLE(LoaderConfigTimeoutOneShot),
|
||||
EFI_LOADER_VARIABLE(LoaderEntryDefault),
|
||||
EFI_LOADER_VARIABLE(LoaderEntryOneShot),
|
||||
EFI_LOADER_VARIABLE(LoaderSystemToken)){
|
||||
|
||||
int q;
|
||||
|
||||
q = efi_set_variable(EFI_VENDOR_LOADER, p, NULL, 0);
|
||||
q = efi_set_variable(variable, NULL, 0);
|
||||
if (q == -ENOENT)
|
||||
continue;
|
||||
if (q < 0) {
|
||||
log_warning_errno(q, "Failed to remove %s variable: %m", p);
|
||||
log_warning_errno(q, "Failed to remove EFI variable %s: %m", variable);
|
||||
if (r >= 0)
|
||||
r = q;
|
||||
} else
|
||||
log_info("Removed EFI variable %s.", p);
|
||||
log_info("Removed EFI variable %s.", variable);
|
||||
}
|
||||
|
||||
return r;
|
||||
@ -1224,12 +1222,12 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void read_loader_efi_var(const char *name, char **var) {
|
||||
static void read_efi_var(const char *variable, char **ret) {
|
||||
int r;
|
||||
|
||||
r = efi_get_variable_string(EFI_VENDOR_LOADER, name, var);
|
||||
r = efi_get_variable_string(variable, ret);
|
||||
if (r < 0 && r != -ENOENT)
|
||||
log_warning_errno(r, "Failed to read EFI variable %s: %m", name);
|
||||
log_warning_errno(r, "Failed to read EFI variable %s: %m", variable);
|
||||
}
|
||||
|
||||
static void print_yes_no_line(bool first, bool good, const char *name) {
|
||||
@ -1295,13 +1293,13 @@ static int verb_status(int argc, char *argv[], void *userdata) {
|
||||
_cleanup_free_ char *fw_type = NULL, *fw_info = NULL, *loader = NULL, *loader_path = NULL, *stub = NULL;
|
||||
sd_id128_t loader_part_uuid = SD_ID128_NULL;
|
||||
uint64_t loader_features = 0;
|
||||
size_t i;
|
||||
int have;
|
||||
|
||||
read_loader_efi_var("LoaderFirmwareType", &fw_type);
|
||||
read_loader_efi_var("LoaderFirmwareInfo", &fw_info);
|
||||
read_loader_efi_var("LoaderInfo", &loader);
|
||||
read_loader_efi_var("StubInfo", &stub);
|
||||
read_loader_efi_var("LoaderImageIdentifier", &loader_path);
|
||||
read_efi_var(EFI_LOADER_VARIABLE(LoaderFirmwareType), &fw_type);
|
||||
read_efi_var(EFI_LOADER_VARIABLE(LoaderFirmwareInfo), &fw_info);
|
||||
read_efi_var(EFI_LOADER_VARIABLE(LoaderInfo), &loader);
|
||||
read_efi_var(EFI_LOADER_VARIABLE(StubInfo), &stub);
|
||||
read_efi_var(EFI_LOADER_VARIABLE(LoaderImageIdentifier), &loader_path);
|
||||
(void) efi_loader_get_features(&loader_features);
|
||||
|
||||
if (loader_path)
|
||||
@ -1333,7 +1331,7 @@ static int verb_status(int argc, char *argv[], void *userdata) {
|
||||
printf("Current Boot Loader:\n");
|
||||
printf(" Product: %s%s%s\n", ansi_highlight(), strna(loader), ansi_normal());
|
||||
|
||||
for (i = 0; i < ELEMENTSOF(flags); i++)
|
||||
for (size_t i = 0; i < ELEMENTSOF(flags); i++)
|
||||
print_yes_no_line(i == 0, FLAGS_SET(loader_features, flags[i].flag), flags[i].name);
|
||||
|
||||
sd_id128_t bootloader_esp_uuid;
|
||||
@ -1354,8 +1352,10 @@ static int verb_status(int argc, char *argv[], void *userdata) {
|
||||
printf("\n");
|
||||
|
||||
printf("Random Seed:\n");
|
||||
printf(" Passed to OS: %s\n", yes_no(access("/sys/firmware/efi/efivars/LoaderRandomSeed-4a67b082-0a4c-41cf-b6c7-440b29bb8c4f", F_OK) >= 0));
|
||||
printf(" System Token: %s\n", access("/sys/firmware/efi/efivars/LoaderSystemToken-4a67b082-0a4c-41cf-b6c7-440b29bb8c4f", F_OK) >= 0 ? "set" : "not set");
|
||||
have = access(EFIVAR_PATH(EFI_LOADER_VARIABLE(LoaderRandomSeed)), F_OK) >= 0;
|
||||
printf(" Passed to OS: %s\n", yes_no(have));
|
||||
have = access(EFIVAR_PATH(EFI_LOADER_VARIABLE(LoaderSystemToken)), F_OK) >= 0;
|
||||
printf(" System Token: %s\n", have ? "set" : "not set");
|
||||
|
||||
if (arg_esp_path) {
|
||||
_cleanup_free_ char *p = NULL;
|
||||
@ -1364,7 +1364,8 @@ static int verb_status(int argc, char *argv[], void *userdata) {
|
||||
if (!p)
|
||||
return log_oom();
|
||||
|
||||
printf(" Exists: %s\n", yes_no(access(p, F_OK) >= 0));
|
||||
have = access(p, F_OK) >= 0;
|
||||
printf(" Exists: %s\n", yes_no(have));
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
@ -1428,13 +1429,11 @@ static int verb_list(int argc, char *argv[], void *userdata) {
|
||||
if (config.n_entries == 0)
|
||||
log_info("No boot loader entries found.");
|
||||
else {
|
||||
size_t n;
|
||||
|
||||
(void) pager_open(arg_pager_flags);
|
||||
|
||||
printf("Boot Loader Entries:\n");
|
||||
|
||||
for (n = 0; n < config.n_entries; n++) {
|
||||
for (size_t n = 0; n < config.n_entries; n++) {
|
||||
r = boot_entry_show(config.entries + n, n == (size_t) config.default_entry);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@ -1539,7 +1538,7 @@ static int install_random_seed(const char *esp) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = efi_get_variable(EFI_VENDOR_LOADER, "LoaderSystemToken", NULL, NULL, &token_size);
|
||||
r = efi_get_variable(EFI_LOADER_VARIABLE(LoaderSystemToken), NULL, NULL, &token_size);
|
||||
if (r == -ENODATA)
|
||||
log_debug_errno(r, "LoaderSystemToken EFI variable is invalid (too short?), replacing.");
|
||||
else if (r < 0) {
|
||||
@ -1563,7 +1562,7 @@ static int install_random_seed(const char *esp) {
|
||||
* and possibly get identification information or too much insight into the kernel's entropy pool
|
||||
* state. */
|
||||
RUN_WITH_UMASK(0077) {
|
||||
r = efi_set_variable(EFI_VENDOR_LOADER, "LoaderSystemToken", buffer, sz);
|
||||
r = efi_set_variable(EFI_LOADER_VARIABLE(LoaderSystemToken), buffer, sz);
|
||||
if (r < 0) {
|
||||
if (!arg_graceful)
|
||||
return log_error_errno(r, "Failed to write 'LoaderSystemToken' EFI variable: %m");
|
||||
@ -1764,15 +1763,15 @@ static int verb_is_installed(int argc, char *argv[], void *userdata) {
|
||||
static int parse_loader_entry_target_arg(const char *arg1, char16_t **ret_target, size_t *ret_target_size) {
|
||||
int r;
|
||||
if (streq(arg1, "@current")) {
|
||||
r = efi_get_variable(EFI_VENDOR_LOADER, "LoaderEntrySelected", NULL, (void *) ret_target, ret_target_size);
|
||||
r = efi_get_variable(EFI_LOADER_VARIABLE(LoaderEntrySelected), NULL, (void *) ret_target, ret_target_size);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to get EFI variable 'LoaderEntrySelected': %m");
|
||||
} else if (streq(arg1, "@oneshot")) {
|
||||
r = efi_get_variable(EFI_VENDOR_LOADER, "LoaderEntryOneShot", NULL, (void *) ret_target, ret_target_size);
|
||||
r = efi_get_variable(EFI_LOADER_VARIABLE(LoaderEntryOneShot), NULL, (void *) ret_target, ret_target_size);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to get EFI variable 'LoaderEntryOneShot': %m");
|
||||
} else if (streq(arg1, "@default")) {
|
||||
r = efi_get_variable(EFI_VENDOR_LOADER, "LoaderEntryDefault", NULL, (void *) ret_target, ret_target_size);
|
||||
r = efi_get_variable(EFI_LOADER_VARIABLE(LoaderEntryDefault), NULL, (void *) ret_target, ret_target_size);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to get EFI variable 'LoaderEntryDefault': %m");
|
||||
} else {
|
||||
@ -1787,14 +1786,13 @@ static int parse_loader_entry_target_arg(const char *arg1, char16_t **ret_target
|
||||
}
|
||||
|
||||
static int verb_set_default(int argc, char *argv[], void *userdata) {
|
||||
const char *name;
|
||||
int r;
|
||||
|
||||
if (!is_efi_boot())
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
|
||||
"Not booted with UEFI.");
|
||||
|
||||
if (access("/sys/firmware/efi/efivars/LoaderInfo-4a67b082-0a4c-41cf-b6c7-440b29bb8c4f", F_OK) < 0) {
|
||||
if (access(EFIVAR_PATH(EFI_LOADER_VARIABLE(LoaderInfo)), F_OK) < 0) {
|
||||
if (errno == ENOENT) {
|
||||
log_error_errno(errno, "Not booted with a supported boot loader.");
|
||||
return -EOPNOTSUPP;
|
||||
@ -1813,12 +1811,13 @@ static int verb_set_default(int argc, char *argv[], void *userdata) {
|
||||
"'%s' operation cannot be combined with --touch-variables=no.",
|
||||
argv[0]);
|
||||
|
||||
name = streq(argv[0], "set-default") ? "LoaderEntryDefault" : "LoaderEntryOneShot";
|
||||
const char *variable = streq(argv[0], "set-default") ?
|
||||
EFI_LOADER_VARIABLE(LoaderEntryDefault) : EFI_LOADER_VARIABLE(LoaderEntryOneShot);
|
||||
|
||||
if (isempty(argv[1])) {
|
||||
r = efi_set_variable(EFI_VENDOR_LOADER, name, NULL, 0);
|
||||
r = efi_set_variable(variable, NULL, 0);
|
||||
if (r < 0 && r != -ENOENT)
|
||||
return log_error_errno(r, "Failed to remove EFI variable '%s': %m", name);
|
||||
return log_error_errno(r, "Failed to remove EFI variable '%s': %m", variable);
|
||||
} else {
|
||||
_cleanup_free_ char16_t *target = NULL;
|
||||
size_t target_size = 0;
|
||||
@ -1826,9 +1825,9 @@ static int verb_set_default(int argc, char *argv[], void *userdata) {
|
||||
r = parse_loader_entry_target_arg(argv[1], &target, &target_size);
|
||||
if (r < 0)
|
||||
return r;
|
||||
r = efi_set_variable(EFI_VENDOR_LOADER, name, target, target_size);
|
||||
r = efi_set_variable(variable, target, target_size);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to update EFI variable '%s': %m", name);
|
||||
return log_error_errno(r, "Failed to update EFI variable '%s': %m", variable);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -1861,16 +1860,27 @@ static int verb_systemd_efi_options(int argc, char *argv[], void *userdata) {
|
||||
int r;
|
||||
|
||||
if (argc == 1) {
|
||||
_cleanup_free_ char *line = NULL;
|
||||
_cleanup_free_ char *line = NULL, *new = NULL;
|
||||
|
||||
r = systemd_efi_options_variable(&line);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to query SystemdOptions EFI variable: %m");
|
||||
|
||||
puts(line);
|
||||
if (r == -ENODATA)
|
||||
log_debug("No SystemdOptions EFI variable present in cache.");
|
||||
else if (r < 0)
|
||||
return log_error_errno(r, "Failed to read SystemdOptions EFI variable from cache: %m");
|
||||
else
|
||||
puts(line);
|
||||
|
||||
r = systemd_efi_options_efivarfs_if_newer(&new);
|
||||
if (r == -ENODATA) {
|
||||
if (line)
|
||||
log_notice("Note: SystemdOptions EFI variable has been removed since boot.");
|
||||
} else if (r < 0)
|
||||
log_warning_errno(r, "Failed to check SystemdOptions EFI variable in efivarfs, ignoring: %m");
|
||||
else if (new && !streq_ptr(line, new))
|
||||
log_notice("Note: SystemdOptions EFI variable has been modified since boot. New value: %s",
|
||||
new);
|
||||
} else {
|
||||
r = efi_set_variable_string(EFI_VENDOR_SYSTEMD, "SystemdOptions", argv[1]);
|
||||
r = efi_set_variable_string(EFI_SYSTEMD_VARIABLE(SystemdOptions), argv[1]);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to set SystemdOptions EFI variable: %m");
|
||||
}
|
||||
|
@ -27,8 +27,8 @@ static void lock_down_efi_variables(void) {
|
||||
* identify the system or gain too much insight into what we might have credited to the entropy
|
||||
* pool. */
|
||||
FOREACH_STRING(p,
|
||||
"/sys/firmware/efi/efivars/LoaderRandomSeed-4a67b082-0a4c-41cf-b6c7-440b29bb8c4f",
|
||||
"/sys/firmware/efi/efivars/LoaderSystemToken-4a67b082-0a4c-41cf-b6c7-440b29bb8c4f") {
|
||||
EFIVAR_PATH(EFI_LOADER_VARIABLE(LoaderRandomSeed)),
|
||||
EFIVAR_PATH(EFI_LOADER_VARIABLE(LoaderSystemToken))) {
|
||||
|
||||
r = chattr_path(p, 0, FS_IMMUTABLE_FL, NULL);
|
||||
if (r == -ENOENT)
|
||||
@ -61,7 +61,7 @@ int efi_take_random_seed(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = efi_get_variable(EFI_VENDOR_LOADER, "LoaderRandomSeed", NULL, &value, &size);
|
||||
r = efi_get_variable(EFI_LOADER_VARIABLE(LoaderRandomSeed), NULL, &value, &size);
|
||||
if (r == -EOPNOTSUPP) {
|
||||
log_debug_errno(r, "System lacks EFI support, not initializing random seed from EFI variable.");
|
||||
return 0;
|
||||
|
@ -2868,12 +2868,12 @@ static int method_set_reboot_to_boot_loader_menu(
|
||||
|
||||
if (use_efi) {
|
||||
if (x == UINT64_MAX)
|
||||
r = efi_set_variable(EFI_VENDOR_LOADER, "LoaderConfigTimeoutOneShot", NULL, 0);
|
||||
r = efi_set_variable(EFI_LOADER_VARIABLE(LoaderConfigTimeoutOneShot), NULL, 0);
|
||||
else {
|
||||
char buf[DECIMAL_STR_MAX(uint64_t) + 1];
|
||||
xsprintf(buf, "%" PRIu64, DIV_ROUND_UP(x, USEC_PER_SEC)); /* second granularity */
|
||||
|
||||
r = efi_set_variable_string(EFI_VENDOR_LOADER, "LoaderConfigTimeoutOneShot", buf);
|
||||
r = efi_set_variable_string(EFI_LOADER_VARIABLE(LoaderConfigTimeoutOneShot), buf);
|
||||
}
|
||||
if (r < 0)
|
||||
return r;
|
||||
@ -3071,9 +3071,9 @@ static int method_set_reboot_to_boot_loader_entry(
|
||||
if (use_efi) {
|
||||
if (isempty(v))
|
||||
/* Delete item */
|
||||
r = efi_set_variable(EFI_VENDOR_LOADER, "LoaderEntryOneShot", NULL, 0);
|
||||
r = efi_set_variable(EFI_LOADER_VARIABLE(LoaderEntryOneShot), NULL, 0);
|
||||
else
|
||||
r = efi_set_variable_string(EFI_VENDOR_LOADER, "LoaderEntryOneShot", v);
|
||||
r = efi_set_variable_string(EFI_LOADER_VARIABLE(LoaderEntryOneShot), v);
|
||||
if (r < 0)
|
||||
return r;
|
||||
} else {
|
||||
|
@ -4419,7 +4419,7 @@ static int parse_efi_variable_factory_reset(void) {
|
||||
if (!in_initrd()) /* Never honour EFI variable factory reset request outside of the initrd */
|
||||
return 0;
|
||||
|
||||
r = efi_get_variable_string(EFI_VENDOR_SYSTEMD, "FactoryReset", &value);
|
||||
r = efi_get_variable_string(EFI_SYSTEMD_VARIABLE(FactoryReset), &value);
|
||||
if (r == -ENOENT || ERRNO_IS_NOT_SUPPORTED(r))
|
||||
return 0;
|
||||
if (r < 0)
|
||||
@ -4439,7 +4439,7 @@ static int parse_efi_variable_factory_reset(void) {
|
||||
static int remove_efi_variable_factory_reset(void) {
|
||||
int r;
|
||||
|
||||
r = efi_set_variable(EFI_VENDOR_SYSTEMD, "FactoryReset", NULL, 0);
|
||||
r = efi_set_variable(EFI_SYSTEMD_VARIABLE(FactoryReset), NULL, 0);
|
||||
if (r == -ENOENT || ERRNO_IS_NOT_SUPPORTED(r))
|
||||
return 0;
|
||||
if (r < 0)
|
||||
|
@ -677,14 +677,14 @@ int boot_entries_load_config(
|
||||
return log_error_errno(r, "Failed to uniquify boot entries: %m");
|
||||
|
||||
if (is_efi_boot()) {
|
||||
r = efi_get_variable_string(EFI_VENDOR_LOADER, "LoaderEntryOneShot", &config->entry_oneshot);
|
||||
r = efi_get_variable_string(EFI_LOADER_VARIABLE(LoaderEntryOneShot), &config->entry_oneshot);
|
||||
if (r < 0 && !IN_SET(r, -ENOENT, -ENODATA)) {
|
||||
log_warning_errno(r, "Failed to read EFI variable \"LoaderEntryOneShot\": %m");
|
||||
if (r == -ENOMEM)
|
||||
return r;
|
||||
}
|
||||
|
||||
r = efi_get_variable_string(EFI_VENDOR_LOADER, "LoaderEntryDefault", &config->entry_default);
|
||||
r = efi_get_variable_string(EFI_LOADER_VARIABLE(LoaderEntryDefault), &config->entry_default);
|
||||
if (r < 0 && !IN_SET(r, -ENOENT, -ENODATA)) {
|
||||
log_warning_errno(r, "Failed to read EFI variable \"LoaderEntryDefault\": %m");
|
||||
if (r == -ENOMEM)
|
||||
@ -776,7 +776,7 @@ int boot_entries_augment_from_loader(
|
||||
break;
|
||||
}
|
||||
|
||||
p = efi_variable_path(EFI_VENDOR_LOADER, "LoaderEntries");
|
||||
p = strdup(EFIVAR_PATH(EFI_LOADER_VARIABLE(LoaderEntries)));
|
||||
if (!p)
|
||||
return log_oom();
|
||||
|
||||
|
@ -82,7 +82,7 @@ int efi_reboot_to_firmware_supported(void) {
|
||||
if (!is_efi_boot())
|
||||
goto not_supported;
|
||||
|
||||
r = efi_get_variable(EFI_VENDOR_GLOBAL, "OsIndicationsSupported", NULL, &v, &s);
|
||||
r = efi_get_variable(EFI_GLOBAL_VARIABLE(OsIndicationsSupported), NULL, &v, &s);
|
||||
if (r == -ENOENT)
|
||||
goto not_supported; /* variable doesn't exist? it's not supported then */
|
||||
if (r < 0)
|
||||
@ -105,7 +105,6 @@ not_supported:
|
||||
static int get_os_indications(uint64_t *ret) {
|
||||
static struct stat cache_stat = {};
|
||||
_cleanup_free_ void *v = NULL;
|
||||
_cleanup_free_ char *fn = NULL;
|
||||
static uint64_t cache;
|
||||
struct stat new_stat;
|
||||
size_t s;
|
||||
@ -118,12 +117,8 @@ static int get_os_indications(uint64_t *ret) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
fn = efi_variable_path(EFI_VENDOR_GLOBAL, "OsIndications");
|
||||
if (!fn)
|
||||
return -ENOMEM;
|
||||
|
||||
/* stat() the EFI variable, to see if the mtime changed. If it did we need to cache again. */
|
||||
if (stat(fn, &new_stat) < 0) {
|
||||
if (stat(EFIVAR_PATH(EFI_GLOBAL_VARIABLE(OsIndications)), &new_stat) < 0) {
|
||||
if (errno != ENOENT)
|
||||
return -errno;
|
||||
|
||||
@ -137,7 +132,7 @@ static int get_os_indications(uint64_t *ret) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = efi_get_variable(EFI_VENDOR_GLOBAL, "OsIndications", NULL, &v, &s);
|
||||
r = efi_get_variable(EFI_GLOBAL_VARIABLE(OsIndications), NULL, &v, &s);
|
||||
if (r == -ENOENT) {
|
||||
/* Some firmware implementations that do support OsIndications and report that with
|
||||
* OsIndicationsSupported will remove the OsIndications variable when it is unset. Let's
|
||||
@ -180,7 +175,7 @@ int efi_set_reboot_to_firmware(bool value) {
|
||||
|
||||
/* Avoid writing to efi vars store if we can due to firmware bugs. */
|
||||
if (b != b_new)
|
||||
return efi_set_variable(EFI_VENDOR_GLOBAL, "OsIndications", &b_new, sizeof(uint64_t));
|
||||
return efi_set_variable(EFI_GLOBAL_VARIABLE(OsIndications), &b_new, sizeof(uint64_t));
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -235,7 +230,7 @@ int efi_get_boot_option(
|
||||
char **path,
|
||||
bool *active) {
|
||||
|
||||
char boot_id[9];
|
||||
char variable[STRLEN(EFI_GLOBAL_VARIABLE_STR("Boot")) + 4 + 1];
|
||||
_cleanup_free_ uint8_t *buf = NULL;
|
||||
size_t l;
|
||||
struct boot_option *header;
|
||||
@ -247,8 +242,8 @@ int efi_get_boot_option(
|
||||
if (!is_efi_boot())
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
xsprintf(boot_id, "Boot%04X", id);
|
||||
r = efi_get_variable(EFI_VENDOR_GLOBAL, boot_id, NULL, (void **)&buf, &l);
|
||||
xsprintf(variable, EFI_GLOBAL_VARIABLE_STR("Boot%04X"), id);
|
||||
r = efi_get_variable(variable, NULL, (void **)&buf, &l);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (l < offsetof(struct boot_option, title))
|
||||
@ -350,9 +345,7 @@ static void id128_to_efi_guid(sd_id128_t id, void *guid) {
|
||||
}
|
||||
|
||||
static uint16_t *tilt_slashes(uint16_t *s) {
|
||||
uint16_t *p;
|
||||
|
||||
for (p = s; *p; p++)
|
||||
for (uint16_t *p = s; *p; p++)
|
||||
if (*p == '/')
|
||||
*p = '\\';
|
||||
|
||||
@ -372,7 +365,7 @@ int efi_add_boot_option(
|
||||
_cleanup_free_ char *buf = NULL;
|
||||
struct boot_option *option;
|
||||
struct device_path *devicep;
|
||||
char boot_id[9];
|
||||
char variable[STRLEN(EFI_GLOBAL_VARIABLE_STR("Boot")) + 4 + 1];
|
||||
|
||||
if (!is_efi_boot())
|
||||
return -EOPNOTSUPP;
|
||||
@ -424,18 +417,18 @@ int efi_add_boot_option(
|
||||
devicep->length = offsetof(struct device_path, path);
|
||||
size += devicep->length;
|
||||
|
||||
xsprintf(boot_id, "Boot%04X", id);
|
||||
return efi_set_variable(EFI_VENDOR_GLOBAL, boot_id, buf, size);
|
||||
xsprintf(variable, EFI_GLOBAL_VARIABLE_STR("Boot%04X"), id);
|
||||
return efi_set_variable(variable, buf, size);
|
||||
}
|
||||
|
||||
int efi_remove_boot_option(uint16_t id) {
|
||||
char boot_id[9];
|
||||
char variable[STRLEN(EFI_GLOBAL_VARIABLE_STR("Boot")) + 4 + 1];
|
||||
|
||||
if (!is_efi_boot())
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
xsprintf(boot_id, "Boot%04X", id);
|
||||
return efi_set_variable(EFI_VENDOR_GLOBAL, boot_id, NULL, 0);
|
||||
xsprintf(variable, EFI_GLOBAL_VARIABLE_STR("Boot%04X"), id);
|
||||
return efi_set_variable(variable, NULL, 0);
|
||||
}
|
||||
|
||||
int efi_get_boot_order(uint16_t **order) {
|
||||
@ -446,7 +439,7 @@ int efi_get_boot_order(uint16_t **order) {
|
||||
if (!is_efi_boot())
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
r = efi_get_variable(EFI_VENDOR_GLOBAL, "BootOrder", NULL, &buf, &l);
|
||||
r = efi_get_variable(EFI_GLOBAL_VARIABLE(BootOrder), NULL, &buf, &l);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -466,15 +459,15 @@ int efi_set_boot_order(uint16_t *order, size_t n) {
|
||||
if (!is_efi_boot())
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return efi_set_variable(EFI_VENDOR_GLOBAL, "BootOrder", order, n * sizeof(uint16_t));
|
||||
return efi_set_variable(EFI_GLOBAL_VARIABLE(BootOrder), order, n * sizeof(uint16_t));
|
||||
}
|
||||
|
||||
static int boot_id_hex(const char s[static 4]) {
|
||||
int id = 0, i;
|
||||
int id = 0;
|
||||
|
||||
assert(s);
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
for (int i = 0; i < 4; i++)
|
||||
if (s[i] >= '0' && s[i] <= '9')
|
||||
id |= (s[i] - '0') << (3 - i) * 4;
|
||||
else if (s[i] >= 'A' && s[i] <= 'F')
|
||||
@ -500,7 +493,7 @@ int efi_get_boot_options(uint16_t **options) {
|
||||
if (!is_efi_boot())
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
dir = opendir("/sys/firmware/efi/efivars/");
|
||||
dir = opendir(EFIVAR_PATH("."));
|
||||
if (!dir)
|
||||
return -errno;
|
||||
|
||||
@ -513,7 +506,7 @@ int efi_get_boot_options(uint16_t **options) {
|
||||
if (strlen(de->d_name) != 45)
|
||||
continue;
|
||||
|
||||
if (strcmp(de->d_name + 8, "-8be4df61-93ca-11d2-aa0d-00e098032b8c") != 0)
|
||||
if (strcmp(de->d_name + 8, EFI_GLOBAL_VARIABLE_STR("")) != 0) /* generate variable suffix using macro */
|
||||
continue;
|
||||
|
||||
id = boot_id_hex(de->d_name + 4);
|
||||
@ -533,15 +526,15 @@ int efi_get_boot_options(uint16_t **options) {
|
||||
return count;
|
||||
}
|
||||
|
||||
static int read_usec(sd_id128_t vendor, const char *name, usec_t *u) {
|
||||
static int read_usec(const char *variable, usec_t *u) {
|
||||
_cleanup_free_ char *j = NULL;
|
||||
int r;
|
||||
uint64_t x = 0;
|
||||
|
||||
assert(name);
|
||||
assert(variable);
|
||||
assert(u);
|
||||
|
||||
r = efi_get_variable_string(EFI_VENDOR_LOADER, name, &j);
|
||||
r = efi_get_variable_string(variable, &j);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -563,11 +556,11 @@ int efi_loader_get_boot_usec(usec_t *firmware, usec_t *loader) {
|
||||
if (!is_efi_boot())
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
r = read_usec(EFI_VENDOR_LOADER, "LoaderTimeInitUSec", &x);
|
||||
r = read_usec(EFI_LOADER_VARIABLE(LoaderTimeInitUSec), &x);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to read LoaderTimeInitUSec: %m");
|
||||
|
||||
r = read_usec(EFI_VENDOR_LOADER, "LoaderTimeExecUSec", &y);
|
||||
r = read_usec(EFI_LOADER_VARIABLE(LoaderTimeExecUSec), &y);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to read LoaderTimeExecUSec: %m");
|
||||
|
||||
@ -589,7 +582,7 @@ int efi_loader_get_device_part_uuid(sd_id128_t *u) {
|
||||
if (!is_efi_boot())
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
r = efi_get_variable_string(EFI_VENDOR_LOADER, "LoaderDevicePartUUID", &p);
|
||||
r = efi_get_variable_string(EFI_LOADER_VARIABLE(LoaderDevicePartUUID), &p);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -600,12 +593,9 @@ int efi_loader_get_device_part_uuid(sd_id128_t *u) {
|
||||
&parsed[12], &parsed[13], &parsed[14], &parsed[15]) != 16)
|
||||
return -EIO;
|
||||
|
||||
if (u) {
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < ELEMENTSOF(parsed); i++)
|
||||
if (u)
|
||||
for (unsigned i = 0; i < ELEMENTSOF(parsed); i++)
|
||||
u->bytes[i] = parsed[i];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -613,7 +603,7 @@ int efi_loader_get_device_part_uuid(sd_id128_t *u) {
|
||||
int efi_loader_get_entries(char ***ret) {
|
||||
_cleanup_free_ char16_t *entries = NULL;
|
||||
_cleanup_strv_free_ char **l = NULL;
|
||||
size_t size, i, start;
|
||||
size_t size;
|
||||
int r;
|
||||
|
||||
assert(ret);
|
||||
@ -621,13 +611,13 @@ int efi_loader_get_entries(char ***ret) {
|
||||
if (!is_efi_boot())
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
r = efi_get_variable(EFI_VENDOR_LOADER, "LoaderEntries", NULL, (void**) &entries, &size);
|
||||
r = efi_get_variable(EFI_LOADER_VARIABLE(LoaderEntries), NULL, (void**) &entries, &size);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
/* The variable contains a series of individually NUL terminated UTF-16 strings. */
|
||||
|
||||
for (i = 0, start = 0;; i++) {
|
||||
for (size_t i = 0, start = 0;; i++) {
|
||||
_cleanup_free_ char *decoded = NULL;
|
||||
bool end;
|
||||
|
||||
@ -673,12 +663,12 @@ int efi_loader_get_features(uint64_t *ret) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = efi_get_variable(EFI_VENDOR_LOADER, "LoaderFeatures", NULL, &v, &s);
|
||||
r = efi_get_variable(EFI_LOADER_VARIABLE(LoaderFeatures), NULL, &v, &s);
|
||||
if (r == -ENOENT) {
|
||||
_cleanup_free_ char *info = NULL;
|
||||
|
||||
/* The new (v240+) LoaderFeatures variable is not supported, let's see if it's systemd-boot at all */
|
||||
r = efi_get_variable_string(EFI_VENDOR_LOADER, "LoaderInfo", &info);
|
||||
r = efi_get_variable_string(EFI_LOADER_VARIABLE(LoaderInfo), &info);
|
||||
if (r < 0) {
|
||||
if (r != -ENOENT)
|
||||
return r;
|
||||
@ -713,7 +703,7 @@ int efi_loader_get_features(uint64_t *ret) {
|
||||
}
|
||||
|
||||
int efi_loader_get_config_timeout_one_shot(usec_t *ret) {
|
||||
_cleanup_free_ char *v = NULL, *fn = NULL;
|
||||
_cleanup_free_ char *v = NULL;
|
||||
static struct stat cache_stat = {};
|
||||
struct stat new_stat;
|
||||
static usec_t cache;
|
||||
@ -722,12 +712,8 @@ int efi_loader_get_config_timeout_one_shot(usec_t *ret) {
|
||||
|
||||
assert(ret);
|
||||
|
||||
fn = efi_variable_path(EFI_VENDOR_LOADER, "LoaderConfigTimeoutOneShot");
|
||||
if (!fn)
|
||||
return -ENOMEM;
|
||||
|
||||
/* stat() the EFI variable, to see if the mtime changed. If it did we need to cache again. */
|
||||
if (stat(fn, &new_stat) < 0)
|
||||
/* stat() the EFI variable, to see if the mtime changed. If it did, we need to cache again. */
|
||||
if (stat(EFIVAR_PATH(EFI_LOADER_VARIABLE(LoaderConfigTimeoutOneShot)), &new_stat) < 0)
|
||||
return -errno;
|
||||
|
||||
if (stat_inode_unmodified(&new_stat, &cache_stat)) {
|
||||
@ -735,7 +721,7 @@ int efi_loader_get_config_timeout_one_shot(usec_t *ret) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = efi_get_variable_string(EFI_VENDOR_LOADER, "LoaderConfigTimeoutOneShot", &v);
|
||||
r = efi_get_variable_string(EFI_LOADER_VARIABLE(LoaderConfigTimeoutOneShot), &v);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -751,25 +737,21 @@ int efi_loader_get_config_timeout_one_shot(usec_t *ret) {
|
||||
}
|
||||
|
||||
int efi_loader_update_entry_one_shot_cache(char **cache, struct stat *cache_stat) {
|
||||
_cleanup_free_ char *fn = NULL, *v = NULL;
|
||||
_cleanup_free_ char *v = NULL;
|
||||
struct stat new_stat;
|
||||
int r;
|
||||
|
||||
assert(cache);
|
||||
assert(cache_stat);
|
||||
|
||||
fn = efi_variable_path(EFI_VENDOR_LOADER, "LoaderEntryOneShot");
|
||||
if (!fn)
|
||||
return -ENOMEM;
|
||||
|
||||
/* stat() the EFI variable, to see if the mtime changed. If it did we need to cache again. */
|
||||
if (stat(fn, &new_stat) < 0)
|
||||
if (stat(EFIVAR_PATH(EFI_LOADER_VARIABLE(LoaderEntryOneShot)), &new_stat) < 0)
|
||||
return -errno;
|
||||
|
||||
if (stat_inode_unmodified(&new_stat, cache_stat))
|
||||
return 0;
|
||||
|
||||
r = efi_get_variable_string(EFI_VENDOR_LOADER, "LoaderEntryOneShot", &v);
|
||||
r = efi_get_variable_string(EFI_LOADER_VARIABLE(LoaderEntryOneShot), &v);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -808,7 +790,6 @@ bool efi_has_tpm2(void) {
|
||||
#endif
|
||||
|
||||
bool efi_loader_entry_name_valid(const char *s) {
|
||||
|
||||
if (!filename_is_valid(s)) /* Make sure entry names fit in filenames */
|
||||
return false;
|
||||
|
||||
@ -816,9 +797,7 @@ bool efi_loader_entry_name_valid(const char *s) {
|
||||
}
|
||||
|
||||
char *efi_tilt_backslashes(char *s) {
|
||||
char *p;
|
||||
|
||||
for (p = s; *p; p++)
|
||||
for (char *p = s; *p; p++)
|
||||
if (*p == '\\')
|
||||
*p = '/';
|
||||
|
||||
|
@ -107,6 +107,9 @@ int sd_id128_get_boot_app_specific(sd_id128_t app_id, sd_id128_t *ret);
|
||||
#define SD_ID128_MAKE_STR(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) \
|
||||
#a #b #c #d #e #f #g #h #i #j #k #l #m #n #o #p
|
||||
|
||||
#define SD_ID128_MAKE_UUID_STR(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) \
|
||||
#a #b #c #d "-" #e #f "-" #g #h "-" #i #j "-" #k #l #m #n #o #p
|
||||
|
||||
_sd_pure_ static __inline__ int sd_id128_equal(sd_id128_t a, sd_id128_t b) {
|
||||
return memcmp(&a, &b, 16) == 0;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user