summaryrefslogtreecommitdiff
path: root/src/basic/efivars.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/basic/efivars.c')
-rw-r--r--src/basic/efivars.c26
1 files changed, 25 insertions, 1 deletions
diff --git a/src/basic/efivars.c b/src/basic/efivars.c
index bb115a7b99..7a9d1bf641 100644
--- a/src/basic/efivars.c
+++ b/src/basic/efivars.c
@@ -17,6 +17,7 @@
#include "fileio.h"
#include "io-util.h"
#include "macro.h"
+#include "memory-util.h"
#include "stdio-util.h"
#include "strv.h"
#include "time-util.h"
@@ -159,12 +160,29 @@ int efi_get_variable_string(const char *variable, char **p) {
return 0;
}
+static int efi_verify_variable(const char *variable, uint32_t attr, const void *value, size_t size) {
+ _cleanup_free_ void *buf = NULL;
+ size_t n;
+ uint32_t a;
+ int r;
+
+ assert(variable);
+ assert(value || size == 0);
+
+ r = efi_get_variable(variable, &a, &buf, &n);
+ if (r < 0)
+ return r;
+
+ return a == attr && memcmp_nn(buf, n, value, size) == 0;
+}
+
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_close_ int fd = -1;
+ uint32_t attr = EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS;
bool saved_flags_valid = false;
unsigned saved_flags;
int r;
@@ -174,6 +192,12 @@ int efi_set_variable(const char *variable, const void *value, size_t size) {
const char *p = strjoina("/sys/firmware/efi/efivars/", variable);
+ /* size 0 means removal, empty variable would not be enough for that */
+ if (size > 0 && efi_verify_variable(variable, attr, value, size) > 0) {
+ log_debug("Variable '%s' is already in wanted state, skipping write.", variable);
+ return 0;
+ }
+
/* 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
* accidentally however, hence let's unset the bit first. */
@@ -205,7 +229,7 @@ int efi_set_variable(const char *variable, const void *value, size_t size) {
goto finish;
}
- buf->attr = EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS;
+ buf->attr = attr;
memcpy(buf->buf, value, size);
r = loop_write(fd, buf, sizeof(uint32_t) + size, false);