1a1a69f19Skasunath #include "rde/rde_dictionary_manager.hpp"
2a1a69f19Skasunath
3*5de90619SPatrick Williams #include <stdplus/print.hpp>
4*5de90619SPatrick Williams
5*5de90619SPatrick Williams #include <format>
6a1a69f19Skasunath
7a1a69f19Skasunath namespace bios_bmc_smm_error_logger
8a1a69f19Skasunath {
9a1a69f19Skasunath namespace rde
10a1a69f19Skasunath {
11a1a69f19Skasunath
DictionaryManager()12b8125763SPatrick Williams DictionaryManager::DictionaryManager() : validDictionaryCount(0) {}
13a1a69f19Skasunath
startDictionaryEntry(uint32_t resourceId,const std::span<const uint8_t> data)14a1a69f19Skasunath void DictionaryManager::startDictionaryEntry(
15a1a69f19Skasunath uint32_t resourceId, const std::span<const uint8_t> data)
16a1a69f19Skasunath {
17a1a69f19Skasunath // Check whether the resourceId is already available.
18a1a69f19Skasunath auto itemIt = dictionaries.find(resourceId);
19a1a69f19Skasunath if (itemIt == dictionaries.end())
20a1a69f19Skasunath {
21b8125763SPatrick Williams dictionaries[resourceId] = std::make_unique<DictionaryEntry>(false,
22b8125763SPatrick Williams data);
23a1a69f19Skasunath return;
24a1a69f19Skasunath }
25a1a69f19Skasunath
26a1a69f19Skasunath // Since we are creating a new dictionary on an existing entry, invalidate
27a1a69f19Skasunath // the existing entry.
28a1a69f19Skasunath invalidateDictionaryEntry(*itemIt->second);
29a1a69f19Skasunath
30a1a69f19Skasunath // Flush the existing data.
31a1a69f19Skasunath itemIt->second->data.clear();
32a1a69f19Skasunath itemIt->second->data.insert(itemIt->second->data.begin(), data.begin(),
33a1a69f19Skasunath data.end());
34a1a69f19Skasunath }
35a1a69f19Skasunath
markDataComplete(uint32_t resourceId)36a1a69f19Skasunath bool DictionaryManager::markDataComplete(uint32_t resourceId)
37a1a69f19Skasunath {
38a1a69f19Skasunath auto itemIt = dictionaries.find(resourceId);
39a1a69f19Skasunath if (itemIt == dictionaries.end())
40a1a69f19Skasunath {
41*5de90619SPatrick Williams stdplus::print(stderr, "Resource ID {} not found.\n", resourceId);
42a1a69f19Skasunath return false;
43a1a69f19Skasunath }
44a1a69f19Skasunath validateDictionaryEntry(*itemIt->second);
45a1a69f19Skasunath return true;
46a1a69f19Skasunath }
47a1a69f19Skasunath
addDictionaryData(uint32_t resourceId,const std::span<const uint8_t> data)48a1a69f19Skasunath bool DictionaryManager::addDictionaryData(uint32_t resourceId,
49a1a69f19Skasunath const std::span<const uint8_t> data)
50a1a69f19Skasunath {
51a1a69f19Skasunath auto itemIt = dictionaries.find(resourceId);
52a1a69f19Skasunath if (itemIt == dictionaries.end())
53a1a69f19Skasunath {
54*5de90619SPatrick Williams stdplus::print(stderr, "Resource ID {} not found.\n", resourceId);
55a1a69f19Skasunath return false;
56a1a69f19Skasunath }
57a1a69f19Skasunath // Since we are modifying an existing entry, invalidate the existing entry.
58a1a69f19Skasunath invalidateDictionaryEntry(*itemIt->second);
59a1a69f19Skasunath itemIt->second->data.insert(itemIt->second->data.end(), data.begin(),
60a1a69f19Skasunath data.end());
61a1a69f19Skasunath return true;
62a1a69f19Skasunath }
63a1a69f19Skasunath
64a1a69f19Skasunath std::optional<std::span<const uint8_t>>
getDictionary(uint32_t resourceId)65a1a69f19Skasunath DictionaryManager::getDictionary(uint32_t resourceId)
66a1a69f19Skasunath {
67a1a69f19Skasunath auto itemIt = dictionaries.find(resourceId);
68a1a69f19Skasunath if (itemIt == dictionaries.end())
69a1a69f19Skasunath {
70*5de90619SPatrick Williams stdplus::print(stderr, "Resource ID {} not found.\n", resourceId);
71a1a69f19Skasunath return std::nullopt;
72a1a69f19Skasunath }
73a1a69f19Skasunath
74a1a69f19Skasunath if (!itemIt->second->valid)
75a1a69f19Skasunath {
76*5de90619SPatrick Williams stdplus::print(stderr,
77a1a69f19Skasunath "Requested an incomplete dictionary. Resource ID {}\n",
78a1a69f19Skasunath resourceId);
79a1a69f19Skasunath return std::nullopt;
80a1a69f19Skasunath }
81a1a69f19Skasunath return itemIt->second->data;
82a1a69f19Skasunath }
83a1a69f19Skasunath
84a1a69f19Skasunath std::optional<std::span<const uint8_t>>
getAnnotationDictionary()85a1a69f19Skasunath DictionaryManager::getAnnotationDictionary()
86a1a69f19Skasunath {
87a1a69f19Skasunath return getDictionary(annotationResourceId);
88a1a69f19Skasunath }
89a1a69f19Skasunath
getDictionaryCount()90a1a69f19Skasunath uint32_t DictionaryManager::getDictionaryCount()
91a1a69f19Skasunath {
92a1a69f19Skasunath return validDictionaryCount;
93a1a69f19Skasunath }
94a1a69f19Skasunath
invalidateDictionaries()95a1a69f19Skasunath void DictionaryManager::invalidateDictionaries()
96a1a69f19Skasunath {
97a1a69f19Skasunath // We won't flush the existing data. The data will be flushed if a new entry
98a1a69f19Skasunath // is added for an existing resource ID.
99a1a69f19Skasunath for (const auto& element : dictionaries)
100a1a69f19Skasunath {
101a1a69f19Skasunath element.second->valid = false;
102a1a69f19Skasunath }
103a1a69f19Skasunath validDictionaryCount = 0;
104a1a69f19Skasunath }
105a1a69f19Skasunath
invalidateDictionaryEntry(DictionaryEntry & entry)106a1a69f19Skasunath void DictionaryManager::invalidateDictionaryEntry(DictionaryEntry& entry)
107a1a69f19Skasunath {
108a1a69f19Skasunath // If this is a valid entry, reduce the valid dictionary count.
109a1a69f19Skasunath if (entry.valid)
110a1a69f19Skasunath {
111a1a69f19Skasunath --validDictionaryCount;
112a1a69f19Skasunath }
113a1a69f19Skasunath entry.valid = false;
114a1a69f19Skasunath }
115a1a69f19Skasunath
validateDictionaryEntry(DictionaryEntry & entry)116a1a69f19Skasunath void DictionaryManager::validateDictionaryEntry(DictionaryEntry& entry)
117a1a69f19Skasunath {
118a1a69f19Skasunath if (!entry.valid)
119a1a69f19Skasunath {
120a1a69f19Skasunath ++validDictionaryCount;
121a1a69f19Skasunath }
122a1a69f19Skasunath entry.valid = true;
123a1a69f19Skasunath }
124a1a69f19Skasunath
125a1a69f19Skasunath } // namespace rde
126a1a69f19Skasunath } // namespace bios_bmc_smm_error_logger
127