summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2020-06-25 15:24:25 +0200
committerLennart Poettering <lennart@poettering.net>2020-06-26 10:43:42 +0200
commite8df4eee65643f9b0806763857a9f265e3d764ee (patch)
tree4cbec1255c91ee4a6f52e7a1def89224ad54429d /src
parent6eea6e30ab99f8a3eebaa338c02803f33ab5b855 (diff)
downloadsystemd-e8df4eee65643f9b0806763857a9f265e3d764ee.tar.gz
efi-loader: cache LoaderConfigTimeoutOneShot too
The data from this EFI variable is exposed as dbus property, and gdbus clients are happy to issue GetAllProperties() as if it was free. Hence make sure it's actually free and cache LoaderConfigTimeoutOneShot, since it's easy.
Diffstat (limited to 'src')
-rw-r--r--src/login/logind-dbus.c16
-rw-r--r--src/shared/efi-loader.c38
-rw-r--r--src/shared/efi-loader.h6
3 files changed, 46 insertions, 14 deletions
diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c
index 7fed32c3b4..d8ae0287ec 100644
--- a/src/login/logind-dbus.c
+++ b/src/login/logind-dbus.c
@@ -2751,8 +2751,6 @@ static int property_get_reboot_to_boot_loader_menu(
r = getenv_bool("SYSTEMD_REBOOT_TO_BOOT_LOADER_MENU");
if (r == -ENXIO) {
- _cleanup_free_ char *v = NULL;
-
/* EFI case: returns the current value of LoaderConfigTimeoutOneShot. Three cases are distuingished:
*
* 1. Variable not set, boot into boot loader menu is not enabled (we return UINT64_MAX to the user)
@@ -2760,20 +2758,10 @@ static int property_get_reboot_to_boot_loader_menu(
* 3. Variable set to numeric value formatted in ASCII, boot into boot loader menu with the specified timeout in seconds
*/
- r = efi_get_variable_string(EFI_VENDOR_LOADER, "LoaderConfigTimeoutOneShot", &v);
+ r = efi_loader_get_config_timeout_one_shot(&x);
if (r < 0) {
if (r != -ENOENT)
- log_warning_errno(r, "Failed to read LoaderConfigTimeoutOneShot variable: %m");
- } else {
- uint64_t sec;
-
- r = safe_atou64(v, &sec);
- if (r < 0)
- log_warning_errno(r, "Failed to parse LoaderConfigTimeoutOneShot value '%s': %m", v);
- else if (sec > (USEC_INFINITY / USEC_PER_SEC))
- log_warning("LoaderConfigTimeoutOneShot too large, ignoring: %m");
- else
- x = sec * USEC_PER_SEC; /* return in µs */
+ log_warning_errno(r, "Failed to read LoaderConfigTimeoutOneShot variable, ignoring: %m");
}
} else if (r < 0)
diff --git a/src/shared/efi-loader.c b/src/shared/efi-loader.c
index b6ad43b856..ce9e78b274 100644
--- a/src/shared/efi-loader.c
+++ b/src/shared/efi-loader.c
@@ -734,3 +734,41 @@ char *efi_tilt_backslashes(char *s) {
return s;
}
+
+int efi_loader_get_config_timeout_one_shot(usec_t *ret) {
+ _cleanup_free_ char *v = NULL, *fn = NULL;
+ static struct stat cache_stat = {};
+ struct stat new_stat;
+ static usec_t cache;
+ uint64_t sec;
+ int r;
+
+ 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)
+ return -errno;
+
+ if (stat_inode_unmodified(&new_stat, &cache_stat)) {
+ *ret = cache;
+ return 0;
+ }
+
+ r = efi_get_variable_string(EFI_VENDOR_LOADER, "LoaderConfigTimeoutOneShot", &v);
+ if (r < 0)
+ return r;
+
+ r = safe_atou64(v, &sec);
+ if (r < 0)
+ return r;
+ if (sec > USEC_INFINITY / USEC_PER_SEC)
+ return -ERANGE;
+
+ cache_stat = new_stat;
+ *ret = cache = sec * USEC_PER_SEC; /* return in µs */
+ return 0;
+}
diff --git a/src/shared/efi-loader.h b/src/shared/efi-loader.h
index 96208d25bf..98bb57ecbd 100644
--- a/src/shared/efi-loader.h
+++ b/src/shared/efi-loader.h
@@ -23,6 +23,8 @@ int efi_loader_get_entries(char ***ret);
int efi_loader_get_features(uint64_t *ret);
+int efi_loader_get_config_timeout_one_shot(usec_t *ret);
+
#else
static inline int efi_reboot_to_firmware_supported(void) {
@@ -77,6 +79,10 @@ static inline int efi_loader_get_features(uint64_t *ret) {
return -EOPNOTSUPP;
}
+static inline int efi_loader_get_config_timeout_one_shot(usec_t *ret) {
+ return -EOPNOTSUPP;
+}
+
#endif
bool efi_loader_entry_name_valid(const char *s);