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