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