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