1 #pragma once 2 3 #include "pdr.hpp" 4 #include "pdr_utils.hpp" 5 6 #include <libpldm/platform.h> 7 8 #include <phosphor-logging/lg2.hpp> 9 10 PHOSPHOR_LOG2_USING; 11 12 namespace pldm 13 { 14 namespace responder 15 { 16 namespace pdr_state_effecter 17 { 18 using Json = nlohmann::json; 19 20 static const Json empty{}; 21 22 /** @brief Parse PDR JSON file and generate state effecter PDR structure 23 * 24 * @param[in] json - the JSON Object with the state effecter PDR 25 * @param[out] handler - the Parser of PLDM command handler 26 * @param[out] repo - pdr::RepoInterface 27 * 28 */ 29 template <class DBusInterface, class Handler> 30 void generateStateEffecterPDR(const DBusInterface& dBusIntf, const Json& json, 31 Handler& handler, pdr_utils::RepoInterface& repo) 32 { 33 static const std::vector<Json> emptyList{}; 34 auto entries = json.value("entries", emptyList); 35 for (const auto& e : entries) 36 { 37 size_t pdrSize = 0; 38 auto effecters = e.value("effecters", emptyList); 39 for (const auto& effecter : effecters) 40 { 41 auto set = effecter.value("set", empty); 42 auto statesSize = set.value("size", 0); 43 if (!statesSize) 44 { 45 error( 46 "Malformed PDR JSON return pdrEntry; no state set info for state effecter pdr '{STATE_EFFECTER_PDR}'", 47 "STATE_EFFECTER_PDR", PLDM_STATE_EFFECTER_PDR); 48 throw InternalFailure(); 49 } 50 pdrSize += sizeof(state_effecter_possible_states) - 51 sizeof(bitfield8_t) + (sizeof(bitfield8_t) * statesSize); 52 } 53 pdrSize += sizeof(pldm_state_effecter_pdr) - sizeof(uint8_t); 54 55 std::vector<uint8_t> entry{}; 56 entry.resize(pdrSize); 57 58 pldm_state_effecter_pdr* pdr = 59 reinterpret_cast<pldm_state_effecter_pdr*>(entry.data()); 60 if (!pdr) 61 { 62 error("Failed to get state effecter PDR."); 63 continue; 64 } 65 pdr->hdr.record_handle = 0; 66 pdr->hdr.version = 1; 67 pdr->hdr.type = PLDM_STATE_EFFECTER_PDR; 68 pdr->hdr.record_change_num = 0; 69 pdr->hdr.length = pdrSize - sizeof(pldm_pdr_hdr); 70 71 pdr->terminus_handle = TERMINUS_HANDLE; 72 73 try 74 { 75 std::string entity_path = e.value("entity_path", ""); 76 auto& associatedEntityMap = handler.getAssociateEntityMap(); 77 if (entity_path != "" && associatedEntityMap.contains(entity_path)) 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 // do not create the PDR when the FRU or the entity path is not 93 // present 94 if (!pdr->entity_type) 95 { 96 continue; 97 } 98 } 99 } 100 catch (const std::exception&) 101 { 102 pdr->entity_type = e.value("type", 0); 103 pdr->entity_instance = e.value("instance", 0); 104 pdr->container_id = e.value("container", 0); 105 } 106 107 pdr->effecter_semantic_id = 0; 108 pdr->effecter_init = PLDM_NO_INIT; 109 pdr->has_description_pdr = false; 110 pdr->composite_effecter_count = effecters.size(); 111 112 pldm::responder::pdr_utils::DbusMappings dbusMappings{}; 113 pldm::responder::pdr_utils::DbusValMaps dbusValMaps{}; 114 uint8_t* start = 115 entry.data() + sizeof(pldm_state_effecter_pdr) - sizeof(uint8_t); 116 for (const auto& effecter : effecters) 117 { 118 auto set = effecter.value("set", empty); 119 state_effecter_possible_states* possibleStates = 120 reinterpret_cast<state_effecter_possible_states*>(start); 121 possibleStates->state_set_id = set.value("id", 0); 122 possibleStates->possible_states_size = set.value("size", 0); 123 124 start += sizeof(possibleStates->state_set_id) + 125 sizeof(possibleStates->possible_states_size); 126 static const std::vector<uint8_t> emptyStates{}; 127 pldm::responder::pdr_utils::PossibleValues stateValues; 128 auto states = set.value("states", emptyStates); 129 for (const auto& state : states) 130 { 131 auto index = state / 8; 132 auto bit = state - (index * 8); 133 bitfield8_t* bf = reinterpret_cast<bitfield8_t*>(start + index); 134 bf->byte |= 1 << bit; 135 stateValues.emplace_back(state); 136 } 137 start += possibleStates->possible_states_size; 138 139 auto dbusEntry = effecter.value("dbus", empty); 140 auto objectPath = dbusEntry.value("path", ""); 141 auto interface = dbusEntry.value("interface", ""); 142 auto propertyName = dbusEntry.value("property_name", ""); 143 auto propertyType = dbusEntry.value("property_type", ""); 144 145 pldm::responder::pdr_utils::StatestoDbusVal dbusIdToValMap{}; 146 pldm::utils::DBusMapping dbusMapping{}; 147 try 148 { 149 auto service = 150 dBusIntf.getService(objectPath.c_str(), interface.c_str()); 151 152 dbusMapping = pldm::utils::DBusMapping{ 153 objectPath, interface, propertyName, propertyType}; 154 dbusIdToValMap = pldm::responder::pdr_utils::populateMapping( 155 propertyType, dbusEntry["property_values"], stateValues); 156 } 157 catch (const std::exception& e) 158 { 159 error( 160 "Failed to create effecter PDR, D-Bus object '{PATH}' returned error - {ERROR}", 161 "PATH", objectPath, "ERROR", e); 162 break; 163 } 164 dbusMappings.emplace_back(std::move(dbusMapping)); 165 dbusValMaps.emplace_back(std::move(dbusIdToValMap)); 166 } 167 if (!(dbusMappings.empty() && dbusValMaps.empty())) 168 { 169 pdr->effecter_id = handler.getNextEffecterId(); 170 handler.addDbusObjMaps(pdr->effecter_id, 171 std::make_tuple(std::move(dbusMappings), 172 std::move(dbusValMaps))); 173 pldm::responder::pdr_utils::PdrEntry pdrEntry{}; 174 pdrEntry.data = entry.data(); 175 pdrEntry.size = pdrSize; 176 repo.addRecord(pdrEntry); 177 } 178 } 179 } 180 181 } // namespace pdr_state_effecter 182 } // namespace responder 183 } // namespace pldm 184