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