1 #pragma once
2 
3 #include "libpldmresponder/pdr_utils.hpp"
4 
5 #include "libpldm/platform.h"
6 
7 namespace pldm
8 {
9 
10 namespace responder
11 {
12 
13 namespace pdr_state_effecter
14 {
15 
16 using Json = nlohmann::json;
17 
18 static const Json empty{};
19 
20 /** @brief Parse PDR JSON file and generate state effecter PDR structure
21  *
22  *  @param[in] json - the JSON Object with the state effecter PDR
23  *  @param[out] handler - the Parser of PLDM command handler
24  *  @param[out] repo - pdr::RepoInterface
25  *
26  */
27 template <class Handler>
28 void generateStateEffecterPDR(const Json& json, Handler& handler,
29                               pdr_utils::RepoInterface& repo)
30 {
31     static const std::vector<Json> emptyList{};
32     auto entries = json.value("entries", emptyList);
33     for (const auto& e : entries)
34     {
35         size_t pdrSize = 0;
36         auto effecters = e.value("effecters", emptyList);
37         for (const auto& effecter : effecters)
38         {
39             auto set = effecter.value("set", empty);
40             auto statesSize = set.value("size", 0);
41             if (!statesSize)
42             {
43                 std::cerr << "Malformed PDR JSON return "
44                              "pdrEntry;- no state set "
45                              "info, TYPE="
46                           << PLDM_STATE_EFFECTER_PDR << "\n";
47                 throw InternalFailure();
48             }
49             pdrSize += sizeof(state_effecter_possible_states) -
50                        sizeof(bitfield8_t) + (sizeof(bitfield8_t) * statesSize);
51         }
52         pdrSize += sizeof(pldm_state_effecter_pdr) - sizeof(uint8_t);
53 
54         std::vector<uint8_t> entry{};
55         entry.resize(pdrSize);
56 
57         pldm_state_effecter_pdr* pdr =
58             reinterpret_cast<pldm_state_effecter_pdr*>(entry.data());
59         pdr->hdr.record_handle = 0;
60         pdr->hdr.version = 1;
61         pdr->hdr.type = PLDM_STATE_EFFECTER_PDR;
62         pdr->hdr.record_change_num = 0;
63         pdr->hdr.length = pdrSize - sizeof(pldm_pdr_hdr);
64 
65         pdr->terminus_handle = 0;
66         pdr->effecter_id = handler.getNextEffecterId();
67         pdr->entity_type = e.value("type", 0);
68         pdr->entity_instance = e.value("instance", 0);
69         pdr->container_id = e.value("container", 0);
70         pdr->effecter_semantic_id = 0;
71         pdr->effecter_init = PLDM_NO_INIT;
72         pdr->has_description_pdr = false;
73         pdr->composite_effecter_count = effecters.size();
74 
75         DbusMappings dbusMappings{};
76         DbusValMaps dbusValMaps{};
77         uint8_t* start =
78             entry.data() + sizeof(pldm_state_effecter_pdr) - sizeof(uint8_t);
79         for (const auto& effecter : effecters)
80         {
81             auto set = effecter.value("set", empty);
82             state_effecter_possible_states* possibleStates =
83                 reinterpret_cast<state_effecter_possible_states*>(start);
84             possibleStates->state_set_id = set.value("id", 0);
85             possibleStates->possible_states_size = set.value("size", 0);
86 
87             start += sizeof(possibleStates->state_set_id) +
88                      sizeof(possibleStates->possible_states_size);
89             static const std::vector<uint8_t> emptyStates{};
90             PossibleValues stateValues;
91             auto states = set.value("states", emptyStates);
92             for (const auto& state : states)
93             {
94                 auto index = state / 8;
95                 auto bit = state - (index * 8);
96                 bitfield8_t* bf = reinterpret_cast<bitfield8_t*>(start + index);
97                 bf->byte |= 1 << bit;
98                 stateValues.emplace_back(std::move(state));
99             }
100             start += possibleStates->possible_states_size;
101 
102             auto dbusEntry = effecter.value("dbus", empty);
103             auto objectPath = dbusEntry.value("path", "");
104             auto interface = dbusEntry.value("interface", "");
105             auto propertyName = dbusEntry.value("property_name", "");
106             auto propertyType = dbusEntry.value("property_type", "");
107             pldm::utils::DBusMapping dbusMapping{objectPath, interface,
108                                                  propertyName, propertyType};
109             dbusMappings.emplace_back(std::move(dbusMapping));
110 
111             Json propValues = dbusEntry["property_values"];
112             StatestoDbusVal dbusIdToValMap =
113                 populateMapping(propertyType, propValues, stateValues);
114             if (!dbusIdToValMap.empty())
115             {
116                 dbusValMaps.emplace_back(std::move(dbusIdToValMap));
117             }
118         }
119         handler.addDbusObjMaps(
120             pdr->effecter_id,
121             std::make_tuple(std::move(dbusMappings), std::move(dbusValMaps)));
122         PdrEntry pdrEntry{};
123         pdrEntry.data = entry.data();
124         pdrEntry.size = pdrSize;
125         repo.addRecord(pdrEntry);
126     }
127 }
128 
129 } // namespace pdr_state_effecter
130 } // namespace responder
131 } // namespace pldm
132