|
@@ -0,0 +1,716 @@
|
|
|
+From f0c1c15fc8886349f7aeb04e1328472894b674d7 Mon Sep 17 00:00:00 2001
|
|
|
+From: Bence Balogh <bence.balogh@arm.com>
|
|
|
+Date: Mon, 25 Nov 2024 22:11:33 +0100
|
|
|
+Subject: [PATCH 1/3] Revert "Make variable index usage robust with redundancy"
|
|
|
+
|
|
|
+This reverts commit 8e394bbfae1dccf86a6a5428471e1b10fdaa74ec.
|
|
|
+This revert is needed because the FMP support added for Corstone-1000 only
|
|
|
+works if the SMM_VARIABLE_INDEX_STORAGE_UID is 0x787. See the implementation
|
|
|
+in the 0003-FMP-Support-in-Corstone1000.patch file.
|
|
|
+
|
|
|
+The 0003-FMP-Support-in-Corstone1000.patch is also inappropriate and will be
|
|
|
+redesigned. Instead of fixing that patch, revert this redundancy feature until
|
|
|
+the FMP support is redesigned.
|
|
|
+
|
|
|
+Upstream-Status: Inappropriate [To be removed after new FWU design]
|
|
|
+Signed-off-by: Bence Balogh <bence.balogh@arm.com>
|
|
|
+---
|
|
|
+ .../backend/test/variable_index_tests.cpp | 50 ++---
|
|
|
+ .../backend/test/variable_store_tests.cpp | 166 ----------------
|
|
|
+ .../backend/uefi_variable_store.c | 181 +++---------------
|
|
|
+ .../backend/uefi_variable_store.h | 1 -
|
|
|
+ .../smm_variable/backend/variable_index.c | 29 +--
|
|
|
+ .../smm_variable/backend/variable_index.h | 3 +-
|
|
|
+ 6 files changed, 46 insertions(+), 384 deletions(-)
|
|
|
+
|
|
|
+diff --git a/components/service/uefi/smm_variable/backend/test/variable_index_tests.cpp b/components/service/uefi/smm_variable/backend/test/variable_index_tests.cpp
|
|
|
+index cf0f6a12e..a52cfbf76 100644
|
|
|
+--- a/components/service/uefi/smm_variable/backend/test/variable_index_tests.cpp
|
|
|
++++ b/components/service/uefi/smm_variable/backend/test/variable_index_tests.cpp
|
|
|
+@@ -208,8 +208,7 @@ TEST(UefiVariableIndexTests, enumerateStore)
|
|
|
+
|
|
|
+ TEST(UefiVariableIndexTests, dumpLoadRoadtrip)
|
|
|
+ {
|
|
|
+- uint8_t buffer[sizeof(uint32_t) +
|
|
|
+- MAX_VARIABLES * (sizeof(struct variable_metadata) + sizeof(bool))];
|
|
|
++ uint8_t buffer[MAX_VARIABLES * sizeof(struct variable_metadata)];
|
|
|
+
|
|
|
+ create_variables();
|
|
|
+
|
|
|
+@@ -223,13 +222,7 @@ TEST(UefiVariableIndexTests, dumpLoadRoadtrip)
|
|
|
+
|
|
|
+ CHECK_TRUE(is_dirty);
|
|
|
+ UNSIGNED_LONGS_EQUAL(EFI_SUCCESS, status);
|
|
|
+- /*
|
|
|
+- * Variable index counter is at the beginning, which is followed by metadata and
|
|
|
+- * constraint status byte of both NV variables
|
|
|
+- */
|
|
|
+- UNSIGNED_LONGS_EQUAL(sizeof(uint32_t) +
|
|
|
+- ((sizeof(struct variable_metadata) + sizeof(bool)) * 2),
|
|
|
+- dump_len);
|
|
|
++ UNSIGNED_LONGS_EQUAL(((sizeof(struct variable_metadata) + sizeof(bool)) * 2), dump_len);
|
|
|
+
|
|
|
+ /* Expect no records to be dirty when the dump is repeated */
|
|
|
+ dump_len = 0;
|
|
|
+@@ -238,9 +231,7 @@ TEST(UefiVariableIndexTests, dumpLoadRoadtrip)
|
|
|
+
|
|
|
+ UNSIGNED_LONGS_EQUAL(EFI_SUCCESS, status);
|
|
|
+ CHECK_FALSE(is_dirty);
|
|
|
+- UNSIGNED_LONGS_EQUAL(sizeof(uint32_t) +
|
|
|
+- ((sizeof(struct variable_metadata) + sizeof(bool)) * 2),
|
|
|
+- dump_len);
|
|
|
++ UNSIGNED_LONGS_EQUAL(((sizeof(struct variable_metadata) + sizeof(bool)) * 2), dump_len);
|
|
|
+
|
|
|
+ /* Tear down and reinitialize to simulate a reboot */
|
|
|
+ variable_index_deinit(&m_variable_index);
|
|
|
+@@ -279,8 +270,7 @@ TEST(UefiVariableIndexTests, dumpLoadRoadtrip)
|
|
|
+
|
|
|
+ TEST(UefiVariableIndexTests, dumpLoadConstrainedVariable)
|
|
|
+ {
|
|
|
+- uint8_t buffer[sizeof(uint32_t) +
|
|
|
+- MAX_VARIABLES * (sizeof(struct variable_metadata) + sizeof(bool))];
|
|
|
++ uint8_t buffer[MAX_VARIABLES * sizeof(struct variable_metadata)];
|
|
|
+
|
|
|
+ create_variables();
|
|
|
+
|
|
|
+@@ -314,13 +304,8 @@ TEST(UefiVariableIndexTests, dumpLoadConstrainedVariable)
|
|
|
+ UNSIGNED_LONGS_EQUAL(EFI_SUCCESS, status);
|
|
|
+ CHECK_TRUE(is_dirty);
|
|
|
+
|
|
|
+- /*
|
|
|
+- * Variable index counter is at the beginning, which is followed by metadata and
|
|
|
+- * constraint status byte of both NV variables, but only one of them has
|
|
|
+- * constraints
|
|
|
+- */
|
|
|
+- UNSIGNED_LONGS_EQUAL(sizeof(uint32_t) +
|
|
|
+- (sizeof(struct variable_metadata) + sizeof(bool)) * 2 +
|
|
|
++ /* metadata and constraint status byte are stored for both NV variables, but only one of them has constraints */
|
|
|
++ UNSIGNED_LONGS_EQUAL((sizeof(struct variable_metadata) + sizeof(bool)) * 2 +
|
|
|
+ sizeof(struct variable_constraints),
|
|
|
+ dump_len);
|
|
|
+
|
|
|
+@@ -331,11 +316,7 @@ TEST(UefiVariableIndexTests, dumpLoadConstrainedVariable)
|
|
|
+
|
|
|
+ TEST(UefiVariableIndexTests, dumpBufferTooSmall)
|
|
|
+ {
|
|
|
+- /*
|
|
|
+- * Enough to fit the variable index counter and the metadata and constraint
|
|
|
+- * status of a single variable
|
|
|
+- */
|
|
|
+- uint8_t buffer[sizeof(uint32_t) + sizeof(struct variable_metadata) + sizeof(bool)];
|
|
|
++ uint8_t buffer[1 * sizeof(struct variable_metadata) + 1];
|
|
|
+
|
|
|
+ create_variables();
|
|
|
+
|
|
|
+@@ -357,8 +338,7 @@ TEST(UefiVariableIndexTests, dumpBufferTooSmall)
|
|
|
+
|
|
|
+ TEST(UefiVariableIndexTests, removeVariable)
|
|
|
+ {
|
|
|
+- uint8_t buffer[sizeof(uint32_t) +
|
|
|
+- MAX_VARIABLES * (sizeof(struct variable_metadata) + sizeof(bool))];
|
|
|
++ uint8_t buffer[MAX_VARIABLES * sizeof(struct variable_metadata)];
|
|
|
+ struct variable_info *info = NULL;
|
|
|
+
|
|
|
+ create_variables();
|
|
|
+@@ -378,12 +358,7 @@ TEST(UefiVariableIndexTests, removeVariable)
|
|
|
+
|
|
|
+ CHECK_TRUE(is_dirty);
|
|
|
+ UNSIGNED_LONGS_EQUAL(EFI_SUCCESS, status);
|
|
|
+- /*
|
|
|
+- * Dump to now contains the variable index counter and metadata,
|
|
|
+- * constraint status data of a variable
|
|
|
+- */
|
|
|
+- UNSIGNED_LONGS_EQUAL(sizeof(uint32_t) + sizeof(struct variable_metadata) + sizeof(bool),
|
|
|
+- dump_len);
|
|
|
++ UNSIGNED_LONGS_EQUAL(sizeof(struct variable_metadata) + sizeof(bool), dump_len);
|
|
|
+
|
|
|
+ /* Remove the volatile variable */
|
|
|
+ info = variable_index_find(&m_variable_index, &guid_1, string_get_size_in_bytes(name_1),
|
|
|
+@@ -398,8 +373,7 @@ TEST(UefiVariableIndexTests, removeVariable)
|
|
|
+
|
|
|
+ CHECK_FALSE(is_dirty);
|
|
|
+ UNSIGNED_LONGS_EQUAL(EFI_SUCCESS, status);
|
|
|
+- UNSIGNED_LONGS_EQUAL(sizeof(uint32_t) + sizeof(struct variable_metadata) + sizeof(bool),
|
|
|
+- dump_len);
|
|
|
++ UNSIGNED_LONGS_EQUAL(sizeof(struct variable_metadata) + sizeof(bool), dump_len);
|
|
|
+
|
|
|
+ /* Remove the remaining NV variable */
|
|
|
+ info = variable_index_find(&m_variable_index, &guid_1, string_get_size_in_bytes(name_3),
|
|
|
+@@ -407,14 +381,14 @@ TEST(UefiVariableIndexTests, removeVariable)
|
|
|
+
|
|
|
+ variable_index_clear_variable(&m_variable_index, info);
|
|
|
+
|
|
|
+- /* Expect index to be dirty and dump to now contains only the variable index counter */
|
|
|
++ /* Expect index to be dirty and dump to now be empty */
|
|
|
+ dump_len = 0;
|
|
|
+ status = variable_index_dump(&m_variable_index, sizeof(buffer), buffer, &dump_len,
|
|
|
+ &is_dirty);
|
|
|
+
|
|
|
+ CHECK_TRUE(is_dirty);
|
|
|
+ UNSIGNED_LONGS_EQUAL(EFI_SUCCESS, status);
|
|
|
+- UNSIGNED_LONGS_EQUAL(sizeof(uint32_t), dump_len);
|
|
|
++ UNSIGNED_LONGS_EQUAL(0, dump_len);
|
|
|
+
|
|
|
+ /* Enumerate and now expect an empty index */
|
|
|
+ info = NULL;
|
|
|
+diff --git a/components/service/uefi/smm_variable/backend/test/variable_store_tests.cpp b/components/service/uefi/smm_variable/backend/test/variable_store_tests.cpp
|
|
|
+index 0f962f206..e0f21f77a 100644
|
|
|
+--- a/components/service/uefi/smm_variable/backend/test/variable_store_tests.cpp
|
|
|
++++ b/components/service/uefi/smm_variable/backend/test/variable_store_tests.cpp
|
|
|
+@@ -5,7 +5,6 @@
|
|
|
+ */
|
|
|
+
|
|
|
+ #include <CppUTest/TestHarness.h>
|
|
|
+-#include <limits>
|
|
|
+ #include <service/secure_storage/backend/mock_store/mock_store.h>
|
|
|
+ #include <service/uefi/smm_variable/backend/uefi_variable_store.h>
|
|
|
+ #include <string.h>
|
|
|
+@@ -270,17 +269,8 @@ TEST_GROUP(UefiVariableStoreTests)
|
|
|
+ static const size_t MAX_VARIABLES = 5;
|
|
|
+ static const size_t MAX_VARIABLE_SIZE = 3000;
|
|
|
+ static const size_t STORE_CAPACITY = MAX_VARIABLES * MAX_VARIABLE_SIZE;
|
|
|
+- static const size_t VARIABLE_INDEX_MAX_SIZE =
|
|
|
+- sizeof(uint32_t) +
|
|
|
+- MAX_VARIABLES * (sizeof(struct variable_metadata) +
|
|
|
+- sizeof(struct variable_constraints) + sizeof(bool));
|
|
|
+
|
|
|
+ static const uint32_t OWNER_ID = 100;
|
|
|
+-
|
|
|
+- /* Synchronize these with the variables with the store */
|
|
|
+- uint64_t DEFAULT_VARIABLE_INDEX_STORAGE_A_UID = 0x8000000000000001;
|
|
|
+- uint64_t DEFAULT_VARIABLE_INDEX_STORAGE_B_UID = 0x8000000000000002;
|
|
|
+-
|
|
|
+ /*
|
|
|
+ * Make sure the variable buffer in the test is way above the limit
|
|
|
+ * so the buffer problems will be handled by the component
|
|
|
+@@ -873,159 +863,3 @@ TEST(UefiVariableStoreTests, fillIndex)
|
|
|
+ LONGS_EQUAL(0, input_data.compare(output_data));
|
|
|
+ }
|
|
|
+ }
|
|
|
+-
|
|
|
+-TEST(UefiVariableStoreTests, variableIndexCounterOverflow)
|
|
|
+-{
|
|
|
+- efi_status_t efi_status = EFI_SUCCESS;
|
|
|
+- psa_status_t psa_status = PSA_SUCCESS;
|
|
|
+- std::u16string var_name = u"var";
|
|
|
+- std::string input_data = "a";
|
|
|
+- uint32_t attributes = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS |
|
|
|
+- EFI_VARIABLE_RUNTIME_ACCESS;
|
|
|
+- /* There are no variables set in the index, only the counter is there */
|
|
|
+- uint8_t buffer[sizeof(uint32_t)] = { 0 };
|
|
|
+-
|
|
|
+- mock_store_reset(&m_persistent_store);
|
|
|
+-
|
|
|
+- /* Counter of index A is 0 */
|
|
|
+- psa_status = m_persistent_store.backend.interface->set(
|
|
|
+- m_persistent_store.backend.context, OWNER_ID, DEFAULT_VARIABLE_INDEX_STORAGE_A_UID,
|
|
|
+- sizeof(buffer), &buffer, PSA_STORAGE_FLAG_NONE);
|
|
|
+- UNSIGNED_LONGLONGS_EQUAL(PSA_SUCCESS, psa_status);
|
|
|
+-
|
|
|
+- /* Set max counter value */
|
|
|
+- buffer[0] = 0xFF;
|
|
|
+- buffer[1] = 0xFF;
|
|
|
+- buffer[2] = 0xFF;
|
|
|
+- buffer[3] = 0xFF;
|
|
|
+-
|
|
|
+- /* Counter of index B is max value */
|
|
|
+- psa_status = m_persistent_store.backend.interface->set(
|
|
|
+- m_persistent_store.backend.context, OWNER_ID, DEFAULT_VARIABLE_INDEX_STORAGE_B_UID,
|
|
|
+- sizeof(buffer), &buffer, PSA_STORAGE_FLAG_NONE);
|
|
|
+- UNSIGNED_LONGLONGS_EQUAL(PSA_SUCCESS, psa_status);
|
|
|
+-
|
|
|
+- /* At next initialization of the store index A should be the latest index with counter value 0 */
|
|
|
+- uefi_variable_store_deinit(&m_uefi_variable_store);
|
|
|
+-
|
|
|
+- efi_status = uefi_variable_store_init(&m_uefi_variable_store, OWNER_ID, MAX_VARIABLES,
|
|
|
+- m_persistent_backend, m_volatile_backend);
|
|
|
+- UNSIGNED_LONGLONGS_EQUAL(EFI_SUCCESS, efi_status);
|
|
|
+-
|
|
|
+- UNSIGNED_LONGLONGS_EQUAL(m_uefi_variable_store.active_variable_index_uid,
|
|
|
+- DEFAULT_VARIABLE_INDEX_STORAGE_A_UID);
|
|
|
+- UNSIGNED_LONGLONGS_EQUAL(m_uefi_variable_store.variable_index.counter, 0);
|
|
|
+-
|
|
|
+- /* After setting a variable to trigger sync and rebooting index B should be the latest index with counter value 1*/
|
|
|
+- efi_status = set_variable(var_name, input_data, attributes);
|
|
|
+- UNSIGNED_LONGLONGS_EQUAL(EFI_SUCCESS, efi_status);
|
|
|
+-
|
|
|
+- power_cycle();
|
|
|
+-
|
|
|
+- UNSIGNED_LONGLONGS_EQUAL(m_uefi_variable_store.active_variable_index_uid,
|
|
|
+- DEFAULT_VARIABLE_INDEX_STORAGE_B_UID);
|
|
|
+- UNSIGNED_LONGLONGS_EQUAL(m_uefi_variable_store.variable_index.counter, 1);
|
|
|
+-}
|
|
|
+-
|
|
|
+-TEST(UefiVariableStoreTests, oneEmptyVariableIndexExists)
|
|
|
+-{
|
|
|
+- psa_status_t status = PSA_SUCCESS;
|
|
|
+-
|
|
|
+- /* Only, variable index A exists, but it is empty */
|
|
|
+- mock_store_reset(&m_persistent_store);
|
|
|
+-
|
|
|
+- status = m_persistent_store.backend.interface->create(m_persistent_store.backend.context,
|
|
|
+- OWNER_ID,
|
|
|
+- DEFAULT_VARIABLE_INDEX_STORAGE_A_UID,
|
|
|
+- 100, PSA_STORAGE_FLAG_NONE);
|
|
|
+- UNSIGNED_LONGLONGS_EQUAL(PSA_SUCCESS, status);
|
|
|
+-
|
|
|
+- power_cycle();
|
|
|
+-
|
|
|
+- /* Empty index is considered non-existing so default index (A) is selected */
|
|
|
+- UNSIGNED_LONGLONGS_EQUAL(m_uefi_variable_store.active_variable_index_uid,
|
|
|
+- DEFAULT_VARIABLE_INDEX_STORAGE_A_UID);
|
|
|
+- UNSIGNED_LONGLONGS_EQUAL(m_uefi_variable_store.variable_index.counter, 0);
|
|
|
+-
|
|
|
+- /* Only, variable index B exists, but it is empty*/
|
|
|
+- mock_store_reset(&m_persistent_store);
|
|
|
+-
|
|
|
+- status = m_persistent_store.backend.interface->create(m_persistent_store.backend.context,
|
|
|
+- OWNER_ID,
|
|
|
+- DEFAULT_VARIABLE_INDEX_STORAGE_B_UID,
|
|
|
+- 100, PSA_STORAGE_FLAG_NONE);
|
|
|
+- UNSIGNED_LONGLONGS_EQUAL(PSA_SUCCESS, status);
|
|
|
+-
|
|
|
+- power_cycle();
|
|
|
+-
|
|
|
+- /* Empty index is considered non-existing so default index (A) is selected */
|
|
|
+- UNSIGNED_LONGLONGS_EQUAL(m_uefi_variable_store.active_variable_index_uid,
|
|
|
+- DEFAULT_VARIABLE_INDEX_STORAGE_A_UID);
|
|
|
+- UNSIGNED_LONGLONGS_EQUAL(m_uefi_variable_store.variable_index.counter, 0);
|
|
|
+-}
|
|
|
+-
|
|
|
+-TEST(UefiVariableStoreTests, oneVariableIndexAlreadySet)
|
|
|
+-{
|
|
|
+- efi_status_t status = EFI_SUCCESS;
|
|
|
+- /* Empty variable index with zero counter value */
|
|
|
+- uint8_t buffer[VARIABLE_INDEX_MAX_SIZE] = { 0 };
|
|
|
+-
|
|
|
+- /* Set index A in the store with some data, so it will be found as the currently active index */
|
|
|
+- mock_store_reset(&m_persistent_store);
|
|
|
+-
|
|
|
+- status = m_persistent_store.backend.interface->set(
|
|
|
+- m_persistent_store.backend.context, OWNER_ID, DEFAULT_VARIABLE_INDEX_STORAGE_A_UID,
|
|
|
+- sizeof(buffer), &buffer, PSA_STORAGE_FLAG_NONE);
|
|
|
+- UNSIGNED_LONGLONGS_EQUAL(PSA_SUCCESS, status);
|
|
|
+-
|
|
|
+- power_cycle();
|
|
|
+-
|
|
|
+- UNSIGNED_LONGLONGS_EQUAL(m_uefi_variable_store.active_variable_index_uid,
|
|
|
+- DEFAULT_VARIABLE_INDEX_STORAGE_A_UID);
|
|
|
+- UNSIGNED_LONGLONGS_EQUAL(m_uefi_variable_store.variable_index.counter, 0);
|
|
|
+-
|
|
|
+- /* Set index B in the store with some data, so it will be found as the currently active index */
|
|
|
+- mock_store_reset(&m_persistent_store);
|
|
|
+-
|
|
|
+- status = m_persistent_store.backend.interface->set(
|
|
|
+- m_persistent_store.backend.context, OWNER_ID, DEFAULT_VARIABLE_INDEX_STORAGE_B_UID,
|
|
|
+- sizeof(buffer), &buffer, PSA_STORAGE_FLAG_NONE);
|
|
|
+- UNSIGNED_LONGLONGS_EQUAL(PSA_SUCCESS, status);
|
|
|
+-
|
|
|
+- power_cycle();
|
|
|
+-
|
|
|
+- UNSIGNED_LONGLONGS_EQUAL(m_uefi_variable_store.active_variable_index_uid,
|
|
|
+- DEFAULT_VARIABLE_INDEX_STORAGE_B_UID);
|
|
|
+- UNSIGNED_LONGLONGS_EQUAL(m_uefi_variable_store.variable_index.counter, 0);
|
|
|
+-}
|
|
|
+-
|
|
|
+-TEST(UefiVariableStoreTests, variableIndexesWithSameData)
|
|
|
+-{
|
|
|
+- psa_status_t psa_status = PSA_SUCCESS;
|
|
|
+- efi_status_t efi_status = EFI_SUCCESS;
|
|
|
+- /* Empty variable index with zero counter value */
|
|
|
+- uint8_t buffer[VARIABLE_INDEX_MAX_SIZE] = { 0 };
|
|
|
+-
|
|
|
+- /* Set both indexes to the same data and counter value */
|
|
|
+- mock_store_reset(&m_persistent_store);
|
|
|
+-
|
|
|
+- psa_status = m_persistent_store.backend.interface->set(
|
|
|
+- m_persistent_store.backend.context, OWNER_ID, DEFAULT_VARIABLE_INDEX_STORAGE_A_UID,
|
|
|
+- sizeof(buffer), &buffer, PSA_STORAGE_FLAG_NONE);
|
|
|
+- UNSIGNED_LONGLONGS_EQUAL(PSA_SUCCESS, psa_status);
|
|
|
+-
|
|
|
+- psa_status = m_persistent_store.backend.interface->set(
|
|
|
+- m_persistent_store.backend.context, OWNER_ID, DEFAULT_VARIABLE_INDEX_STORAGE_B_UID,
|
|
|
+- sizeof(buffer), &buffer, PSA_STORAGE_FLAG_NONE);
|
|
|
+- UNSIGNED_LONGLONGS_EQUAL(PSA_SUCCESS, psa_status);
|
|
|
+-
|
|
|
+- /*
|
|
|
+- * Initializing the store should fail, because if there are two indexes with the same counter it cannot be decided
|
|
|
+- * which has the valid data.
|
|
|
+- */
|
|
|
+- uefi_variable_store_deinit(&m_uefi_variable_store);
|
|
|
+-
|
|
|
+- efi_status = uefi_variable_store_init(&m_uefi_variable_store, OWNER_ID, MAX_VARIABLES,
|
|
|
+- m_persistent_backend, m_volatile_backend);
|
|
|
+- UNSIGNED_LONGLONGS_EQUAL(EFI_LOAD_ERROR, efi_status);
|
|
|
+-}
|
|
|
+diff --git a/components/service/uefi/smm_variable/backend/uefi_variable_store.c b/components/service/uefi/smm_variable/backend/uefi_variable_store.c
|
|
|
+index 48b81ff37..459ca4566 100644
|
|
|
+--- a/components/service/uefi/smm_variable/backend/uefi_variable_store.c
|
|
|
++++ b/components/service/uefi/smm_variable/backend/uefi_variable_store.c
|
|
|
+@@ -28,12 +28,9 @@
|
|
|
+ #include "service/crypto/client/psa/crypto_client.h"
|
|
|
+ #endif
|
|
|
+
|
|
|
+-static psa_status_t get_active_variable_uid(struct uefi_variable_store *context,
|
|
|
+- uint64_t *active_index_uid, uint32_t *counter);
|
|
|
+-
|
|
|
+ static efi_status_t load_variable_index(struct uefi_variable_store *context);
|
|
|
+
|
|
|
+-static efi_status_t sync_variable_index(struct uefi_variable_store *context);
|
|
|
++static efi_status_t sync_variable_index(const struct uefi_variable_store *context);
|
|
|
+
|
|
|
+ static efi_status_t check_capabilities(const SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *var);
|
|
|
+
|
|
|
+@@ -138,14 +135,6 @@ static bool compare_name_to_key_store_name(const int16_t *name1, size_t size1,
|
|
|
+ const uint16_t *name2, size_t size2);
|
|
|
+ #endif
|
|
|
+
|
|
|
+-/* Private UID for storing the variable index */
|
|
|
+-#define SMM_VARIABLE_INDEX_STORAGE_A_UID UINT64_C(0x8000000000000001)
|
|
|
+-#define SMM_VARIABLE_INDEX_STORAGE_B_UID UINT64_C(0x8000000000000002)
|
|
|
+-
|
|
|
+-_Static_assert(SMM_VARIABLE_INDEX_STORAGE_A_UID != SMM_VARIABLE_INDEX_STORAGE_B_UID,
|
|
|
+- "SMM_VARIABLE_INDEX_STORAGE_A_UID must not be the same value as "
|
|
|
+- "SMM_VARIABLE_INDEX_STORAGE_B_UID");
|
|
|
+-
|
|
|
+ /* Default maximum variable size -
|
|
|
+ * may be overridden using uefi_variable_store_set_storage_limits()
|
|
|
+ */
|
|
|
+@@ -398,7 +387,7 @@ efi_status_t uefi_variable_store_set_variable(const struct uefi_variable_store *
|
|
|
+ * index entry.
|
|
|
+ */
|
|
|
+ if (should_sync_index)
|
|
|
+- status = sync_variable_index((struct uefi_variable_store *)context);
|
|
|
++ status = sync_variable_index(context);
|
|
|
+
|
|
|
+ /* Store any variable data to the storage backend with the updated metadata */
|
|
|
+ if (info->is_variable_set && (status == EFI_SUCCESS)) {
|
|
|
+@@ -620,148 +609,40 @@ efi_status_t uefi_variable_store_get_var_check_property(
|
|
|
+ return status;
|
|
|
+ }
|
|
|
+
|
|
|
+-/* Checks which index contains the latest data, which shall be loaded */
|
|
|
+-static psa_status_t get_active_variable_uid(struct uefi_variable_store *context,
|
|
|
+- uint64_t *active_index_uid, uint32_t *counter)
|
|
|
+-{
|
|
|
+- uint32_t counter_A = 0;
|
|
|
+- uint32_t counter_B = 0;
|
|
|
+- size_t data_len = 0;
|
|
|
+- psa_status_t psa_status_A = PSA_SUCCESS;
|
|
|
+- psa_status_t psa_status_B = PSA_SUCCESS;
|
|
|
+- struct storage_backend *persistent_store = context->persistent_store.storage_backend;
|
|
|
+-
|
|
|
+- /* Set default value for the case when the index does not exist yet */
|
|
|
+- *active_index_uid = SMM_VARIABLE_INDEX_STORAGE_A_UID;
|
|
|
+- *counter = 0;
|
|
|
+-
|
|
|
+- if (persistent_store) {
|
|
|
+- psa_status_A = persistent_store->interface->get(persistent_store->context,
|
|
|
+- context->owner_id,
|
|
|
+- SMM_VARIABLE_INDEX_STORAGE_A_UID, 0,
|
|
|
+- sizeof(counter_A), &counter_A,
|
|
|
+- &data_len);
|
|
|
+-
|
|
|
+- if (psa_status_A == PSA_SUCCESS && data_len == 0) {
|
|
|
+- psa_status_A = persistent_store->interface->remove(
|
|
|
+- persistent_store->context, context->owner_id,
|
|
|
+- SMM_VARIABLE_INDEX_STORAGE_A_UID);
|
|
|
+-
|
|
|
+- if (psa_status_A == PSA_SUCCESS)
|
|
|
+- psa_status_A = PSA_ERROR_DOES_NOT_EXIST;
|
|
|
+- else {
|
|
|
+- EMSG("Erronous state of variable index");
|
|
|
+- return PSA_ERROR_STORAGE_FAILURE;
|
|
|
+- }
|
|
|
+- }
|
|
|
+-
|
|
|
+- psa_status_B = persistent_store->interface->get(persistent_store->context,
|
|
|
+- context->owner_id,
|
|
|
+- SMM_VARIABLE_INDEX_STORAGE_B_UID, 0,
|
|
|
+- sizeof(counter_B), &counter_B,
|
|
|
+- &data_len);
|
|
|
+-
|
|
|
+- if (psa_status_B == PSA_SUCCESS && data_len == 0) {
|
|
|
+- psa_status_B = persistent_store->interface->remove(
|
|
|
+- persistent_store->context, context->owner_id,
|
|
|
+- SMM_VARIABLE_INDEX_STORAGE_B_UID);
|
|
|
+-
|
|
|
+- if (psa_status_B == PSA_SUCCESS)
|
|
|
+- psa_status_B = PSA_ERROR_DOES_NOT_EXIST;
|
|
|
+- else {
|
|
|
+- EMSG("Erronous state of variable index");
|
|
|
+- return PSA_ERROR_STORAGE_FAILURE;
|
|
|
+- }
|
|
|
+- }
|
|
|
+-
|
|
|
+- if ((psa_status_A != PSA_SUCCESS && psa_status_A != PSA_ERROR_DOES_NOT_EXIST) ||
|
|
|
+- (psa_status_B != PSA_SUCCESS && psa_status_B != PSA_ERROR_DOES_NOT_EXIST))
|
|
|
+- return PSA_ERROR_STORAGE_FAILURE;
|
|
|
+-
|
|
|
+- if (psa_status_A == PSA_ERROR_DOES_NOT_EXIST) {
|
|
|
+- if (psa_status_B == PSA_ERROR_DOES_NOT_EXIST)
|
|
|
+- return PSA_ERROR_DOES_NOT_EXIST;
|
|
|
+-
|
|
|
+- *active_index_uid = SMM_VARIABLE_INDEX_STORAGE_B_UID;
|
|
|
+- *counter = counter_B;
|
|
|
+-
|
|
|
+- return PSA_SUCCESS;
|
|
|
+- } else if (psa_status_B == PSA_ERROR_DOES_NOT_EXIST) {
|
|
|
+- *active_index_uid = SMM_VARIABLE_INDEX_STORAGE_A_UID;
|
|
|
+- *counter = counter_A;
|
|
|
+-
|
|
|
+- return PSA_SUCCESS;
|
|
|
+- }
|
|
|
+-
|
|
|
+- if (counter_A + 1 == counter_B) {
|
|
|
+- *active_index_uid = SMM_VARIABLE_INDEX_STORAGE_B_UID;
|
|
|
+- *counter = counter_B;
|
|
|
+- return PSA_SUCCESS;
|
|
|
+- } else if (counter_B + 1 == counter_A) {
|
|
|
+- *active_index_uid = SMM_VARIABLE_INDEX_STORAGE_A_UID;
|
|
|
+- *counter = counter_A;
|
|
|
+- return PSA_SUCCESS;
|
|
|
+- } else {
|
|
|
+- EMSG("UEFI metadata variable index is invalid.");
|
|
|
+- return PSA_ERROR_STORAGE_FAILURE;
|
|
|
+- }
|
|
|
+- } else {
|
|
|
+- EMSG("Store backend is not accessible");
|
|
|
+- return PSA_ERROR_STORAGE_FAILURE;
|
|
|
+- }
|
|
|
+-
|
|
|
+- return PSA_ERROR_STORAGE_FAILURE;
|
|
|
+-}
|
|
|
+-
|
|
|
+ static efi_status_t load_variable_index(struct uefi_variable_store *context)
|
|
|
+ {
|
|
|
+ struct storage_backend *persistent_store = context->persistent_store.storage_backend;
|
|
|
+- psa_status_t psa_status = PSA_SUCCESS;
|
|
|
+
|
|
|
+ if (persistent_store) {
|
|
|
+ size_t data_len = 0;
|
|
|
+ size_t data_offset = 0;
|
|
|
+- struct psa_storage_info_t variable_index_info = { 0 };
|
|
|
+-
|
|
|
+- psa_status = get_active_variable_uid(context, &context->active_variable_index_uid,
|
|
|
+- &context->variable_index.counter);
|
|
|
+- switch (psa_status) {
|
|
|
+- case PSA_SUCCESS:
|
|
|
+- break;
|
|
|
+-
|
|
|
+- case PSA_ERROR_DOES_NOT_EXIST:
|
|
|
+- IMSG("Variable index does not exist in NV store, continuing with empty index");
|
|
|
+- return EFI_SUCCESS;
|
|
|
+-
|
|
|
+- default:
|
|
|
+- EMSG("Loading variable index failed: %d", psa_status);
|
|
|
+- return EFI_LOAD_ERROR;
|
|
|
+- }
|
|
|
+-
|
|
|
+- /* Make sure the variable index fits the buffer */
|
|
|
+- persistent_store->interface->get_info(persistent_store->context, context->owner_id,
|
|
|
+- context->active_variable_index_uid,
|
|
|
+- &variable_index_info);
|
|
|
+-
|
|
|
+- if (variable_index_info.size > context->index_sync_buffer_size) {
|
|
|
+- EMSG("Variable index cannot fit the sync buffer");
|
|
|
+- return EFI_LOAD_ERROR;
|
|
|
+- }
|
|
|
+
|
|
|
+ do {
|
|
|
+- psa_status = persistent_store->interface->get(
|
|
|
++ psa_status_t psa_status = persistent_store->interface->get(
|
|
|
+ persistent_store->context, context->owner_id,
|
|
|
+- context->active_variable_index_uid, data_offset,
|
|
|
++ SMM_VARIABLE_INDEX_STORAGE_UID, data_offset,
|
|
|
+ RPC_CALLER_SESSION_SHARED_MEMORY_SIZE,
|
|
|
+ context->index_sync_buffer + data_offset, &data_len);
|
|
|
+
|
|
|
+- if (psa_status != PSA_SUCCESS) {
|
|
|
++ switch (psa_status) {
|
|
|
++ case PSA_SUCCESS:
|
|
|
++ data_offset += data_len;
|
|
|
++
|
|
|
++ if (data_offset > context->index_sync_buffer_size) {
|
|
|
++ EMSG("Variable index cannot fit the sync buffer");
|
|
|
++ return EFI_LOAD_ERROR;
|
|
|
++ }
|
|
|
++
|
|
|
++ break;
|
|
|
++
|
|
|
++ case PSA_ERROR_DOES_NOT_EXIST:
|
|
|
++ IMSG("Index variable does not exist in NV store, continuing with empty index");
|
|
|
++ return EFI_SUCCESS;
|
|
|
++
|
|
|
++ default:
|
|
|
+ EMSG("Loading variable index failed: %d", psa_status);
|
|
|
+ return EFI_LOAD_ERROR;
|
|
|
+ }
|
|
|
+-
|
|
|
+- data_offset += data_len;
|
|
|
+-
|
|
|
+ } while (data_len == RPC_CALLER_SESSION_SHARED_MEMORY_SIZE);
|
|
|
+
|
|
|
+ variable_index_restore(&context->variable_index, data_offset,
|
|
|
+@@ -774,7 +655,7 @@ static efi_status_t load_variable_index(struct uefi_variable_store *context)
|
|
|
+ return EFI_SUCCESS;
|
|
|
+ }
|
|
|
+
|
|
|
+-static efi_status_t sync_variable_index(struct uefi_variable_store *context)
|
|
|
++static efi_status_t sync_variable_index(const struct uefi_variable_store *context)
|
|
|
+ {
|
|
|
+ efi_status_t status = EFI_SUCCESS;
|
|
|
+ psa_status_t psa_status = PSA_SUCCESS;
|
|
|
+@@ -794,24 +675,19 @@ static efi_status_t sync_variable_index(struct uefi_variable_store *context)
|
|
|
+
|
|
|
+ if (persistent_store) {
|
|
|
+ size_t data_offset = 0;
|
|
|
+- uint64_t next_index_uid = 0;
|
|
|
+-
|
|
|
+- /* Write the older one */
|
|
|
+- next_index_uid = (context->active_variable_index_uid ==
|
|
|
+- SMM_VARIABLE_INDEX_STORAGE_A_UID ?
|
|
|
+- SMM_VARIABLE_INDEX_STORAGE_B_UID :
|
|
|
+- SMM_VARIABLE_INDEX_STORAGE_A_UID);
|
|
|
+
|
|
|
+ psa_status = persistent_store->interface->remove(
|
|
|
+- persistent_store->context, context->owner_id, next_index_uid);
|
|
|
++ persistent_store->context, context->owner_id,
|
|
|
++ SMM_VARIABLE_INDEX_STORAGE_UID);
|
|
|
+
|
|
|
+ if (psa_status != PSA_SUCCESS && psa_status != PSA_ERROR_DOES_NOT_EXIST)
|
|
|
+ goto end;
|
|
|
+
|
|
|
+ /* Check if the index exists and create if not yet */
|
|
|
+ psa_status = persistent_store->interface->create(
|
|
|
+- persistent_store->context, context->owner_id, next_index_uid,
|
|
|
+- remaining_data_len, PSA_STORAGE_FLAG_NONE);
|
|
|
++ persistent_store->context, context->owner_id,
|
|
|
++ SMM_VARIABLE_INDEX_STORAGE_UID, remaining_data_len,
|
|
|
++ PSA_STORAGE_FLAG_NONE);
|
|
|
+
|
|
|
+ if (psa_status != PSA_SUCCESS)
|
|
|
+ goto end;
|
|
|
+@@ -822,7 +698,8 @@ static efi_status_t sync_variable_index(struct uefi_variable_store *context)
|
|
|
+
|
|
|
+ psa_status = persistent_store->interface->set_extended(
|
|
|
+ persistent_store->context, context->owner_id,
|
|
|
+- next_index_uid, data_offset, data_of_this_iteration,
|
|
|
++ SMM_VARIABLE_INDEX_STORAGE_UID, data_offset,
|
|
|
++ data_of_this_iteration,
|
|
|
+ context->index_sync_buffer + data_offset);
|
|
|
+
|
|
|
+ if (psa_status != PSA_SUCCESS)
|
|
|
+@@ -1827,7 +1704,7 @@ static void purge_orphan_index_entries(const struct uefi_variable_store *context
|
|
|
+ }
|
|
|
+
|
|
|
+ if (any_orphans)
|
|
|
+- sync_variable_index((struct uefi_variable_store *)context);
|
|
|
++ sync_variable_index(context);
|
|
|
+ }
|
|
|
+
|
|
|
+ static struct delegate_variable_store *
|
|
|
+diff --git a/components/service/uefi/smm_variable/backend/uefi_variable_store.h b/components/service/uefi/smm_variable/backend/uefi_variable_store.h
|
|
|
+index 9f2c4a00c..2493ff6b4 100644
|
|
|
+--- a/components/service/uefi/smm_variable/backend/uefi_variable_store.h
|
|
|
++++ b/components/service/uefi/smm_variable/backend/uefi_variable_store.h
|
|
|
+@@ -52,7 +52,6 @@ struct uefi_variable_store {
|
|
|
+ uint32_t owner_id;
|
|
|
+ uint8_t *index_sync_buffer;
|
|
|
+ size_t index_sync_buffer_size;
|
|
|
+- uint64_t active_variable_index_uid;
|
|
|
+ struct variable_index variable_index;
|
|
|
+ struct delegate_variable_store persistent_store;
|
|
|
+ struct delegate_variable_store volatile_store;
|
|
|
+diff --git a/components/service/uefi/smm_variable/backend/variable_index.c b/components/service/uefi/smm_variable/backend/variable_index.c
|
|
|
+index 90230426f..5fb6d08c5 100644
|
|
|
+--- a/components/service/uefi/smm_variable/backend/variable_index.c
|
|
|
++++ b/components/service/uefi/smm_variable/backend/variable_index.c
|
|
|
+@@ -91,7 +91,6 @@ static struct variable_entry *containing_entry(const struct variable_info *info)
|
|
|
+ efi_status_t variable_index_init(struct variable_index *context, size_t max_variables)
|
|
|
+ {
|
|
|
+ context->max_variables = max_variables;
|
|
|
+- context->counter = 0;
|
|
|
+ context->entries =
|
|
|
+ (struct variable_entry *)malloc(sizeof(struct variable_entry) * max_variables);
|
|
|
+
|
|
|
+@@ -109,9 +108,9 @@ void variable_index_deinit(struct variable_index *context)
|
|
|
+
|
|
|
+ size_t variable_index_max_dump_size(struct variable_index *context)
|
|
|
+ {
|
|
|
+- return sizeof(context->counter) + (sizeof(struct variable_metadata) + sizeof(bool) +
|
|
|
+- sizeof(struct variable_constraints)) *
|
|
|
+- context->max_variables;
|
|
|
++ return (sizeof(struct variable_metadata) + sizeof(bool) +
|
|
|
++ sizeof(struct variable_constraints)) *
|
|
|
++ context->max_variables;
|
|
|
+ }
|
|
|
+
|
|
|
+ struct variable_info *variable_index_find(const struct variable_index *context,
|
|
|
+@@ -288,16 +287,6 @@ efi_status_t variable_index_dump(const struct variable_index *context, size_t bu
|
|
|
+ *data_len = 0;
|
|
|
+ *any_dirty = false;
|
|
|
+
|
|
|
+- /*
|
|
|
+- * Intentionally letting the counter overflow.
|
|
|
+- * The buffer (index_sync_buffer) is provided by malloc, which allocates memory to a boundary
|
|
|
+- * suitable for any default data type of the system (e.g uint32_t)
|
|
|
+- */
|
|
|
+- *((uint32_t *)dump_pos) = context->counter + 1;
|
|
|
+- bytes_dumped += sizeof(context->counter);
|
|
|
+- dump_pos += sizeof(context->counter);
|
|
|
+-
|
|
|
+- /* Store variables */
|
|
|
+ for (size_t pos = 0; pos < context->max_variables; pos++) {
|
|
|
+ struct variable_entry *entry = &context->entries[pos];
|
|
|
+ struct variable_metadata *metadata = &entry->info.metadata;
|
|
|
+@@ -344,24 +333,14 @@ efi_status_t variable_index_dump(const struct variable_index *context, size_t bu
|
|
|
+ return EFI_SUCCESS;
|
|
|
+ }
|
|
|
+
|
|
|
+-void variable_index_confirm_write(struct variable_index *context)
|
|
|
+-{
|
|
|
+- context->counter++;
|
|
|
+-}
|
|
|
+
|
|
|
+-size_t variable_index_restore(struct variable_index *context, size_t data_len,
|
|
|
++size_t variable_index_restore(const struct variable_index *context, size_t data_len,
|
|
|
+ const uint8_t *buffer)
|
|
|
+ {
|
|
|
+ size_t bytes_loaded = 0;
|
|
|
+ const uint8_t *load_pos = buffer;
|
|
|
+ int pos = 0;
|
|
|
+
|
|
|
+- if (data_len >= sizeof(context->counter)) {
|
|
|
+- context->counter = *((uint32_t *)load_pos);
|
|
|
+- bytes_loaded += sizeof(context->counter);
|
|
|
+- load_pos += sizeof(context->counter);
|
|
|
+- }
|
|
|
+-
|
|
|
+ while (bytes_loaded < data_len) {
|
|
|
+ struct variable_entry *entry = &context->entries[pos];
|
|
|
+
|
|
|
+diff --git a/components/service/uefi/smm_variable/backend/variable_index.h b/components/service/uefi/smm_variable/backend/variable_index.h
|
|
|
+index 592dddc83..0151d636a 100644
|
|
|
+--- a/components/service/uefi/smm_variable/backend/variable_index.h
|
|
|
++++ b/components/service/uefi/smm_variable/backend/variable_index.h
|
|
|
+@@ -75,7 +75,6 @@ struct variable_entry {
|
|
|
+ */
|
|
|
+ struct variable_index {
|
|
|
+ size_t max_variables;
|
|
|
+- uint32_t counter;
|
|
|
+ struct variable_entry *entries;
|
|
|
+ };
|
|
|
+
|
|
|
+@@ -229,7 +228,7 @@ void variable_index_confirm_write(struct variable_index *context);
|
|
|
+ *
|
|
|
+ * @return Number of bytes loaded
|
|
|
+ */
|
|
|
+-size_t variable_index_restore(struct variable_index *context, size_t data_len,
|
|
|
++size_t variable_index_restore(const struct variable_index *context, size_t data_len,
|
|
|
+ const uint8_t *buffer);
|
|
|
+
|
|
|
+ #ifdef __cplusplus
|
|
|
+--
|
|
|
+2.25.1
|
|
|
+
|