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 = TERMINUS_HANDLE; 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