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         pdr->entity_type = e.value("type", 0);
72         pdr->entity_instance = e.value("instance", 0);
73         pdr->container_id = e.value("container", 0);
74         pdr->sensor_init = PLDM_NO_INIT;
75         pdr->sensor_auxiliary_names_pdr = false;
76         if (sensors.size() > 8)
77         {
78             throw std::runtime_error("sensor size must be less than 8");
79         }
80         pdr->composite_sensor_count = sensors.size();
81 
82         HTOLE16(pdr->terminus_handle);
83         HTOLE16(pdr->sensor_id);
84         HTOLE16(pdr->entity_type);
85         HTOLE16(pdr->entity_instance);
86         HTOLE16(pdr->container_id);
87 
88         DbusMappings dbusMappings{};
89         DbusValMaps dbusValMaps{};
90         uint8_t* start =
91             entry.data() + sizeof(pldm_state_sensor_pdr) - sizeof(uint8_t);
92         for (const auto& sensor : sensors)
93         {
94             auto set = sensor.value("set", empty);
95             state_sensor_possible_states* possibleStates =
96                 reinterpret_cast<state_sensor_possible_states*>(start);
97             possibleStates->state_set_id = set.value("id", 0);
98             HTOLE16(possibleStates->state_set_id);
99             possibleStates->possible_states_size = set.value("size", 0);
100 
101             start += sizeof(possibleStates->state_set_id) +
102                      sizeof(possibleStates->possible_states_size);
103             static const std::vector<uint8_t> emptyStates{};
104             PossibleValues stateValues;
105             auto states = set.value("states", emptyStates);
106             for (const auto& state : states)
107             {
108                 auto index = state / 8;
109                 auto bit = state - (index * 8);
110                 bitfield8_t* bf = reinterpret_cast<bitfield8_t*>(start + index);
111                 bf->byte |= 1 << bit;
112                 stateValues.emplace_back(state);
113             }
114             start += possibleStates->possible_states_size;
115             auto dbusEntry = sensor.value("dbus", empty);
116             auto objectPath = dbusEntry.value("path", "");
117             auto interface = dbusEntry.value("interface", "");
118             auto propertyName = dbusEntry.value("property_name", "");
119             auto propertyType = dbusEntry.value("property_type", "");
120 
121             try
122             {
123                 auto service =
124                     dBusIntf.getService(objectPath.c_str(), interface.c_str());
125             }
126             catch (const std::exception& e)
127             {
128                 continue;
129             }
130 
131             pldm::utils::DBusMapping dbusMapping{objectPath, interface,
132                                                  propertyName, propertyType};
133             dbusMappings.emplace_back(std::move(dbusMapping));
134 
135             Json propValues = dbusEntry["property_values"];
136             StatestoDbusVal dbusIdToValMap =
137                 populateMapping(propertyType, propValues, stateValues);
138             if (!dbusIdToValMap.empty())
139             {
140                 dbusValMaps.emplace_back(std::move(dbusIdToValMap));
141             }
142         }
143 
144         handler.addDbusObjMaps(
145             pdr->sensor_id,
146             std::make_tuple(std::move(dbusMappings), std::move(dbusValMaps)),
147             TypeId::PLDM_SENSOR_ID);
148         PdrEntry pdrEntry{};
149         pdrEntry.data = entry.data();
150         pdrEntry.size = pdrSize;
151         repo.addRecord(pdrEntry);
152     }
153 }
154 
155 } // namespace pdr_state_sensor
156 } // namespace responder
157 } // namespace pldm
158