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