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)
* 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)
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;
+}
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) {
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);