1 #pragma once
2 
3 #include "libpldm/platform.h"
4 
5 #include "libpldmresponder/pdr_utils.hpp"
6 
7 namespace pldm
8 {
9 
10 namespace responder
11 {
12 
13 namespace pdr_state_sensor
14 {
15 
16 using Json = nlohmann::json;
17 
18 static const Json empty{};
19 
20 /** @brief Parse PDR JSON file and generate state sensor PDR structure
21  *
22  *  @param[in] json - the JSON Object with the state sensor PDR
23  *  @param[out] handler - the Parser of PLDM command handler
24  *  @param[out] repo - pdr::RepoInterface
25  *
26  */
27 template <class DBusInterface, class Handler>
28 void generateStateSensorPDR(const DBusInterface& dBusIntf, const Json& json,
29                             Handler& handler, 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 sensors = e.value("sensors", emptyList);
37         for (const auto& sensor : sensors)
38         {
39             auto set = sensor.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_SENSOR_PDR << "\n";
47                 throw InternalFailure();
48             }
49             pdrSize += sizeof(state_sensor_possible_states) -
50                        sizeof(bitfield8_t) + (sizeof(bitfield8_t) * statesSize);
51         }
52         pdrSize += sizeof(pldm_state_sensor_pdr) - sizeof(uint8_t);
53 
54         std::vector<uint8_t> entry{};
55         entry.resize(pdrSize);
56 
57         pldm_state_sensor_pdr* pdr =
58             reinterpret_cast<pldm_state_sensor_pdr*>(entry.data());
59         if (!pdr)
60         {
61             std::cerr << "Failed to get state sensor PDR.\n";
62             continue;
63         }
64         pdr->hdr.record_handle = 0;
65         pdr->hdr.version = 1;
66         pdr->hdr.type = PLDM_STATE_SENSOR_PDR;
67         pdr->hdr.record_change_num = 0;
68         pdr->hdr.length = pdrSize - sizeof(pldm_pdr_hdr);
69 
70         HTOLE32(pdr->hdr.record_handle);
71         HTOLE16(pdr->hdr.record_change_num);
72         HTOLE16(pdr->hdr.length);
73 
74         pdr->terminus_handle = 0;
75         pdr->sensor_id = handler.getNextSensorId();
76 
77         try
78         {
79             std::string entity_path = e.value("entity_path", "");
80             auto& associatedEntityMap = handler.getAssociateEntityMap();
81             if (entity_path != "" && associatedEntityMap.find(entity_path) !=
82                                          associatedEntityMap.end())
83             {
84                 pdr->entity_type =
85                     associatedEntityMap.at(entity_path).entity_type;
86                 pdr->entity_instance =
87                     associatedEntityMap.at(entity_path).entity_instance_num;
88                 pdr->container_id =
89                     associatedEntityMap.at(entity_path).entity_container_id;
90             }
91             else
92             {
93                 pdr->entity_type = e.value("type", 0);
94                 pdr->entity_instance = e.value("instance", 0);
95                 pdr->container_id = e.value("container", 0);
96             }
97         }
98         catch (const std::exception& ex)
99         {
100             pdr->entity_type = e.value("type", 0);
101             pdr->entity_instance = e.value("instance", 0);
102             pdr->container_id = e.value("container", 0);
103         }
104 
105         pdr->sensor_init = PLDM_NO_INIT;
106         pdr->sensor_auxiliary_names_pdr = false;
107         if (sensors.size() > 8)
108         {
109             throw std::runtime_error("sensor size must be less than 8");
110         }
111         pdr->composite_sensor_count = sensors.size();
112 
113         HTOLE16(pdr->terminus_handle);
114         HTOLE16(pdr->sensor_id);
115         HTOLE16(pdr->entity_type);
116         HTOLE16(pdr->entity_instance);
117         HTOLE16(pdr->container_id);
118 
119         pldm::responder::pdr_utils::DbusMappings dbusMappings{};
120         pldm::responder::pdr_utils::DbusValMaps dbusValMaps{};
121         uint8_t* start =
122             entry.data() + sizeof(pldm_state_sensor_pdr) - sizeof(uint8_t);
123         for (const auto& sensor : sensors)
124         {
125             auto set = sensor.value("set", empty);
126             state_sensor_possible_states* possibleStates =
127                 reinterpret_cast<state_sensor_possible_states*>(start);
128             possibleStates->state_set_id = set.value("id", 0);
129             HTOLE16(possibleStates->state_set_id);
130             possibleStates->possible_states_size = set.value("size", 0);
131 
132             start += sizeof(possibleStates->state_set_id) +
133                      sizeof(possibleStates->possible_states_size);
134             static const std::vector<uint8_t> emptyStates{};
135             pldm::responder::pdr_utils::PossibleValues stateValues;
136             auto states = set.value("states", emptyStates);
137             for (const auto& state : states)
138             {
139                 auto index = state / 8;
140                 auto bit = state - (index * 8);
141                 bitfield8_t* bf = reinterpret_cast<bitfield8_t*>(start + index);
142                 bf->byte |= 1 << bit;
143                 stateValues.emplace_back(state);
144             }
145             start += possibleStates->possible_states_size;
146             auto dbusEntry = sensor.value("dbus", empty);
147             auto objectPath = dbusEntry.value("path", "");
148             auto interface = dbusEntry.value("interface", "");
149             auto propertyName = dbusEntry.value("property_name", "");
150             auto propertyType = dbusEntry.value("property_type", "");
151 
152             pldm::responder::pdr_utils::StatestoDbusVal dbusIdToValMap{};
153             pldm::utils::DBusMapping dbusMapping{};
154             try
155             {
156                 auto service =
157                     dBusIntf.getService(objectPath.c_str(), interface.c_str());
158 
159                 dbusMapping = pldm::utils::DBusMapping{
160                     objectPath, interface, propertyName, propertyType};
161                 dbusIdToValMap = pldm::responder::pdr_utils::populateMapping(
162                     propertyType, dbusEntry["property_values"], stateValues);
163             }
164             catch (const std::exception& e)
165             {
166                 std::cerr << "D-Bus object path does not exist, sensor ID: "
167                           << pdr->sensor_id << "\n";
168             }
169 
170             dbusMappings.emplace_back(std::move(dbusMapping));
171             dbusValMaps.emplace_back(std::move(dbusIdToValMap));
172         }
173 
174         handler.addDbusObjMaps(
175             pdr->sensor_id,
176             std::make_tuple(std::move(dbusMappings), std::move(dbusValMaps)),
177             pldm::responder::pdr_utils::TypeId::PLDM_SENSOR_ID);
178         pldm::responder::pdr_utils::PdrEntry pdrEntry{};
179         pdrEntry.data = entry.data();
180         pdrEntry.size = pdrSize;
181         repo.addRecord(pdrEntry);
182     }
183 }
184 
185 } // namespace pdr_state_sensor
186 } // namespace responder
187 } // namespace pldm
188