1 #pragma once
2 
3 #include <cstdint>
4 #include <memory>
5 #include <optional>
6 #include <span>
7 #include <unordered_map>
8 #include <vector>
9 
10 namespace bios_bmc_smm_error_logger
11 {
12 namespace rde
13 {
14 
15 /**
16  * @brief Resource ID for the annotation dictionary. The other entity
17  * communicating with the BMC (Eg: BIOS) should use the same resource ID for the
18  * annotation dictionary.
19  */
20 constexpr uint32_t annotationResourceId = 0;
21 
22 /**
23  * @brief Holds an RDE BEJ dictionary entry.
24  */
25 struct DictionaryEntry
26 {
27     DictionaryEntry(bool valid, const std::span<const uint8_t> data) :
28         valid(valid), data(data.begin(), data.end())
29     {}
30     // True indicates that the dictionary data is ready to be used.
31     bool valid;
32     std::vector<uint8_t> data;
33 };
34 
35 /**
36  * @brief Manages RDE BEJ dictionaries.
37  */
38 class DictionaryManager
39 {
40   public:
41     DictionaryManager();
42 
43     /**
44      * @brief Starts a dictionary entry with the provided data.
45      *
46      * @param[in] resourceId - PDR resource id corresponding to the dictionary.
47      * @param[in] data - dictionary data.
48      */
49     void startDictionaryEntry(uint32_t resourceId,
50                               const std::span<const uint8_t> data);
51 
52     /**
53      * @brief Set the dictionary valid status. Until this is called, dictionary
54      * data is considered to be incomplete for use.
55      *
56      * @param[in] resourceId - PDR resource id corresponding to the dictionary.
57      * @return true if successful.
58      */
59     bool markDataComplete(uint32_t resourceId);
60 
61     /**
62      * @brief Add more dictionary data for an existing entry. Adding data to a
63      * completed dictionary will mark the dictionary as incomplete.
64      *
65      * @param[in] resourceId - PDR resource id corresponding to the dictionary.
66      * @param[in] data - dictionary data.
67      * @return true if successful.
68      */
69     bool addDictionaryData(uint32_t resourceId,
70                            const std::span<const uint8_t> data);
71 
72     /**
73      * @brief Get a dictionary.
74      *
75      * @param[in] resourceId - PDR resource id corresponding to the dictionary.
76      * @return a pointer to the dictionary, if the dictionary is complete else
77      * std::nullopt.
78      */
79     std::optional<std::span<const uint8_t>> getDictionary(uint32_t resourceId);
80 
81     /**
82      * @brief Get the annotation dictionary.
83      *
84      * @return a pointer to the annotation dictionary, if the dictionary is
85      * complete else std::nullopt.
86      */
87     std::optional<std::span<const uint8_t>> getAnnotationDictionary();
88 
89     /**
90      * @brief Get the completed dictionary count.
91      *
92      * @return number of completed dictionaries available.
93      */
94     uint32_t getDictionaryCount();
95 
96     /**
97      * @brief Invalidate all dictionaries.
98      */
99     void invalidateDictionaries();
100 
101   private:
102     uint32_t validDictionaryCount;
103     std::unordered_map<uint32_t, std::unique_ptr<DictionaryEntry>> dictionaries;
104 
105     /**
106      * @brief Set a dictionary entry to be invalid and reduce the valid
107      * dictionary count.
108      *
109      * @param[in] entry - A dictionary entry.
110      */
111     void invalidateDictionaryEntry(DictionaryEntry& entry);
112 
113     /**
114      * @brief Set the dictionary entry valid flag and increase the valid
115      * dictionary count.
116      *
117      * @param[in] entry - A dictionary entry.
118      */
119     void validateDictionaryEntry(DictionaryEntry& entry);
120 };
121 
122 } // namespace rde
123 } // namespace bios_bmc_smm_error_logger
124