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