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