From 526f40caea8797b023e99bde9dbe4040a231bfe1 Mon Sep 17 00:00:00 2001 From: Maciej Szeptuch Date: Sat, 18 May 2024 00:30:27 +0200 Subject: [PATCH] efiboot: prevent overwriting variables with exactly the same value --- include/efiboot.h | 20 ++++++++++++++++++++ include/efivar-lite/efivar-lite.h | 1 + src/efivar-lite.darwin.c | 5 +++++ src/efivar-lite.win32.c | 5 +++++ 4 files changed, 31 insertions(+) diff --git a/include/efiboot.h b/include/efiboot.h index 37ea50cb..f3f88b56 100644 --- a/include/efiboot.h +++ b/include/efiboot.h @@ -3593,6 +3593,16 @@ inline bool set_variable(const efi_guid_t &guid, const tstring &name, const Vari auto [value, attributes] = variable; Raw_data bytes; size_t size = serialize(bytes, value); + // Skip overwriting with exactly the same value + if(const auto current = EFIBoot::get_variable(guid, name); current) + { + const auto &[current_bytes, current_attributes] = *current; + if(current_attributes == attributes && current_bytes == bytes) + return true; + } + + // Don't care about the error from get_variable + efi_error_clear(); return efi_set_variable(guid, name.c_str(), bytes.data(), size, attributes, mode) == 0; } @@ -3602,6 +3612,16 @@ inline bool set_list_variable(const efi_guid_t &guid, const tstring &name, const auto [value, attributes] = variable; Raw_data bytes; size_t size = serialize_list(bytes, value); + // Skip overwriting with exactly the same value + if(const auto current = EFIBoot::get_variable(guid, name); current) + { + const auto &[current_bytes, current_attributes] = *current; + if(current_attributes == attributes && current_bytes == bytes) + return true; + } + + // Don't care about the error from get_variable + efi_error_clear(); return efi_set_variable(guid, name.c_str(), bytes.data(), size, attributes, mode) == 0; } diff --git a/include/efivar-lite/efivar-lite.h b/include/efivar-lite/efivar-lite.h index c6d7f9ed..6ed8ae78 100644 --- a/include/efivar-lite/efivar-lite.h +++ b/include/efivar-lite/efivar-lite.h @@ -80,3 +80,4 @@ void efi_set_get_next_variable_name_progress_cb(void (*progress_cb)(size_t, size int efi_guid_cmp(const efi_guid_t *a, const efi_guid_t *b); int efi_error_get(unsigned int n, TCHAR **const filename, TCHAR **const function, int *line, TCHAR **const message, int *error) ATTR_NONNULL(2, 3, 4, 5, 6); +void efi_error_clear(void); diff --git a/src/efivar-lite.darwin.c b/src/efivar-lite.darwin.c index 75669ce5..7252f271 100644 --- a/src/efivar-lite.darwin.c +++ b/src/efivar-lite.darwin.c @@ -176,3 +176,8 @@ int efi_error_get(unsigned int n, char **const filename, char **const function, *message = mach_error_string(err); return 1; } + +void efi_error_clear(void) +{ + // Nothing to do +} diff --git a/src/efivar-lite.win32.c b/src/efivar-lite.win32.c index 83a7517b..a801e5ad 100644 --- a/src/efivar-lite.win32.c +++ b/src/efivar-lite.win32.c @@ -215,3 +215,8 @@ int efi_error_get(unsigned int n, TCHAR **const filename, TCHAR **const function *message = error_buffer; return 1; } + +void efi_error_clear(void) +{ + // Nothing to do +}