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         pdr->hdr.record_handle = 0;
60         pdr->hdr.version = 1;
61         pdr->hdr.type = PLDM_STATE_SENSOR_PDR;
62         pdr->hdr.record_change_num = 0;
63         pdr->hdr.length = pdrSize - sizeof(pldm_pdr_hdr);
64 
65         HTOLE32(pdr->hdr.record_handle);
66         HTOLE16(pdr->hdr.record_change_num);
67         HTOLE16(pdr->hdr.length);
68 
69         pdr->terminus_handle = 0;
70         pdr->sensor_id = handler.getNextSensorId();
71 
72         try
73         {
74             std::string entity_path = e.value("entity_path", "");
75             auto& associatedEntityMap = handler.getAssociateEntityMap();
76             if (entity_path != "" && associatedEntityMap.find(entity_path) !=
77                                          associatedEntityMap.end())
78             {
79                 pdr->entity_type =
80                     associatedEntityMap.at(entity_path).entity_type;
81                 pdr->entity_instance =
82                     associatedEntityMap.at(entity_path).entity_instance_num;
83                 pdr->container_id =
84                     associatedEntityMap.at(entity_path).entity_container_id;
85             }
86             else
87             {
88                 pdr->entity_type = e.value("type", 0);
89                 pdr->entity_instance = e.value("instance", 0);
90                 pdr->container_id = e.value("container", 0);
91             }
92         }
93         catch (const std::exception& ex)
94         {
95             pdr->entity_type = e.value("type", 0);
96             pdr->entity_instance = e.value("instance", 0);
97             pdr->container_id = e.value("container", 0);
98         }
99 
100         pdr->sensor_init = PLDM_NO_INIT;
101         pdr->sensor_auxiliary_names_pdr = false;
102         if (sensors.size() > 8)
103         {
104             throw std::runtime_error("sensor size must be less than 8");
105         }
106         pdr->composite_sensor_count = sensors.size();
107 
108         HTOLE16(pdr->terminus_handle);
109         HTOLE16(pdr->sensor_id);
110         HTOLE16(pdr->entity_type);
111         HTOLE16(pdr->entity_instance);
112         HTOLE16(pdr->container_id);
113 
114         DbusMappings dbusMappings{};
115         DbusValMaps dbusValMaps{};
116         uint8_t* start =
117             entry.data() + sizeof(pldm_state_sensor_pdr) - sizeof(uint8_t);
118         for (const auto& sensor : sensors)
119         {
120             auto set = sensor.value("set", empty);
121             state_sensor_possible_states* possibleStates =
122                 reinterpret_cast<state_sensor_possible_states*>(start);
123             possibleStates->state_set_id = set.value("id", 0);
124             HTOLE16(possibleStates->state_set_id);
125             possibleStates->possible_states_size = set.value("size", 0);
126 
127             start += sizeof(possibleStates->state_set_id) +
128                      sizeof(possibleStates->possible_states_size);
129             static const std::vector<uint8_t> emptyStates{};
130             PossibleValues stateValues;
131             auto states = set.value("states", emptyStates);
132             for (const auto& state : states)
133             {
134                 auto index = state / 8;
135                 auto bit = state - (index * 8);
136                 bitfield8_t* bf = reinterpret_cast<bitfield8_t*>(start + index);
137                 bf->byte |= 1 << bit;
138                 stateValues.emplace_back(state);
139             }
140             start += possibleStates->possible_states_size;
141             auto dbusEntry = sensor.value("dbus", empty);
142             auto objectPath = dbusEntry.value("path", "");
143             auto interface = dbusEntry.value("interface", "");
144             auto propertyName = dbusEntry.value("property_name", "");
145             auto propertyType = dbusEntry.value("property_type", "");
146 
147             StatestoDbusVal dbusIdToValMap{};
148             pldm::utils::DBusMapping dbusMapping{};
149             try
150             {
151                 auto service =
152                     dBusIntf.getService(objectPath.c_str(), interface.c_str());
153 
154                 dbusMapping = pldm::utils::DBusMapping{
155                     objectPath, interface, propertyName, propertyType};
156                 dbusIdToValMap = populateMapping(
157                     propertyType, dbusEntry["property_values"], stateValues);
158             }
159             catch (const std::exception& e)
160             {
161                 std::cerr << "D-Bus object path does not exist, sensor ID: "
162                           << pdr->sensor_id << "\n";
163             }
164 
165             dbusMappings.emplace_back(std::move(dbusMapping));
166             dbusValMaps.emplace_back(std::move(dbusIdToValMap));
167         }
168 
169         handler.addDbusObjMaps(
170             pdr->sensor_id,
171             std::make_tuple(std::move(dbusMappings), std::move(dbusValMaps)),
172             TypeId::PLDM_SENSOR_ID);
173         PdrEntry pdrEntry{};
174         pdrEntry.data = entry.data();
175         pdrEntry.size = pdrSize;
176         repo.addRecord(pdrEntry);
177     }
178 }
179 
180 } // namespace pdr_state_sensor
181 } // namespace responder
182 } // namespace pldm
183