Add a class to handle RDE BEJ dictionary data
This class is used to store RDE BEJ dictionary data transmitted
through bios-bmc circular buffer interface.
Signed-off-by: Kasun Athukorala <kasunath@google.com>
Change-Id: Idf7726a9f4647885ede615229d507f233ffb13c5
diff --git a/src/rde/meson.build b/src/rde/meson.build
new file mode 100644
index 0000000..4e6220f
--- /dev/null
+++ b/src/rde/meson.build
@@ -0,0 +1,8 @@
+rde_lib = static_library(
+ 'rde',
+ 'rde_dictionary_manager.cpp',
+ include_directories : rde_inc,
+ implicit_include_directories: false)
+
+rde_dep = declare_dependency(
+ link_with: rde_lib)
diff --git a/src/rde/rde_dictionary_manager.cpp b/src/rde/rde_dictionary_manager.cpp
new file mode 100644
index 0000000..a71114c
--- /dev/null
+++ b/src/rde/rde_dictionary_manager.cpp
@@ -0,0 +1,125 @@
+#include "rde/rde_dictionary_manager.hpp"
+
+#include <fmt/format.h>
+
+namespace bios_bmc_smm_error_logger
+{
+namespace rde
+{
+
+DictionaryManager::DictionaryManager() : validDictionaryCount(0)
+{}
+
+void DictionaryManager::startDictionaryEntry(
+ uint32_t resourceId, const std::span<const uint8_t> data)
+{
+ // Check whether the resourceId is already available.
+ auto itemIt = dictionaries.find(resourceId);
+ if (itemIt == dictionaries.end())
+ {
+ dictionaries[resourceId] =
+ std::make_unique<DictionaryEntry>(false, data);
+ return;
+ }
+
+ // Since we are creating a new dictionary on an existing entry, invalidate
+ // the existing entry.
+ invalidateDictionaryEntry(*itemIt->second);
+
+ // Flush the existing data.
+ itemIt->second->data.clear();
+ itemIt->second->data.insert(itemIt->second->data.begin(), data.begin(),
+ data.end());
+}
+
+bool DictionaryManager::markDataComplete(uint32_t resourceId)
+{
+ auto itemIt = dictionaries.find(resourceId);
+ if (itemIt == dictionaries.end())
+ {
+ fmt::print(stderr, "Resource ID {} not found.\n", resourceId);
+ return false;
+ }
+ validateDictionaryEntry(*itemIt->second);
+ return true;
+}
+
+bool DictionaryManager::addDictionaryData(uint32_t resourceId,
+ const std::span<const uint8_t> data)
+{
+ auto itemIt = dictionaries.find(resourceId);
+ if (itemIt == dictionaries.end())
+ {
+ fmt::print(stderr, "Resource ID {} not found.\n", resourceId);
+ return false;
+ }
+ // Since we are modifying an existing entry, invalidate the existing entry.
+ invalidateDictionaryEntry(*itemIt->second);
+ itemIt->second->data.insert(itemIt->second->data.end(), data.begin(),
+ data.end());
+ return true;
+}
+
+std::optional<std::span<const uint8_t>>
+ DictionaryManager::getDictionary(uint32_t resourceId)
+{
+ auto itemIt = dictionaries.find(resourceId);
+ if (itemIt == dictionaries.end())
+ {
+ fmt::print(stderr, "Resource ID {} not found.\n", resourceId);
+ return std::nullopt;
+ }
+
+ if (!itemIt->second->valid)
+ {
+ fmt::print(stderr,
+ "Requested an incomplete dictionary. Resource ID {}\n",
+ resourceId);
+ return std::nullopt;
+ }
+ return itemIt->second->data;
+}
+
+std::optional<std::span<const uint8_t>>
+ DictionaryManager::getAnnotationDictionary()
+{
+ return getDictionary(annotationResourceId);
+}
+
+uint32_t DictionaryManager::getDictionaryCount()
+{
+ return validDictionaryCount;
+}
+
+void DictionaryManager::invalidateDictionaries()
+{
+ // We won't flush the existing data. The data will be flushed if a new entry
+ // is added for an existing resource ID.
+ for (const auto& element : dictionaries)
+ {
+ element.second->valid = false;
+ }
+ validDictionaryCount = 0;
+}
+
+void DictionaryManager::invalidateDictionaryEntry(DictionaryEntry& entry)
+{
+ // If this is a valid entry, reduce the valid dictionary count.
+ if (entry.valid)
+ {
+ --validDictionaryCount;
+ }
+ entry.valid = false;
+}
+
+void DictionaryManager::validateDictionaryEntry(DictionaryEntry& entry)
+{
+ if (!entry.valid)
+ {
+ ++validDictionaryCount;
+ }
+ entry.valid = true;
+}
+
+} // namespace rde
+} // namespace bios_bmc_smm_error_logger