1 #pragma once 2 3 #include "libpldm/platform.h" 4 5 #include "pdr.hpp" 6 #include "pdr_utils.hpp" 7 8 namespace pldm 9 { 10 11 namespace responder 12 { 13 14 namespace pdr_state_effecter 15 { 16 17 using Json = nlohmann::json; 18 19 static const Json empty{}; 20 21 /** @brief Parse PDR JSON file and generate state effecter PDR structure 22 * 23 * @param[in] json - the JSON Object with the state effecter 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 generateStateEffecterPDR(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 effecters = e.value("effecters", emptyList); 38 for (const auto& effecter : effecters) 39 { 40 auto set = effecter.value("set", empty); 41 auto statesSize = set.value("size", 0); 42 if (!statesSize) 43 { 44 std::cerr << "Malformed PDR JSON return " 45 "pdrEntry;- no state set " 46 "info, TYPE=" 47 << PLDM_STATE_EFFECTER_PDR << "\n"; 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 std::cerr << "Failed to get state effecter PDR.\n"; 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 = pdr::BmcPldmTerminusHandle; 72 pdr->effecter_id = handler.getNextEffecterId(); 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 } 95 catch (const std::exception& ex) 96 { 97 pdr->entity_type = e.value("type", 0); 98 pdr->entity_instance = e.value("instance", 0); 99 pdr->container_id = e.value("container", 0); 100 } 101 102 pdr->effecter_semantic_id = 0; 103 pdr->effecter_init = PLDM_NO_INIT; 104 pdr->has_description_pdr = false; 105 pdr->composite_effecter_count = effecters.size(); 106 107 pldm::responder::pdr_utils::DbusMappings dbusMappings{}; 108 pldm::responder::pdr_utils::DbusValMaps dbusValMaps{}; 109 uint8_t* start = 110 entry.data() + sizeof(pldm_state_effecter_pdr) - sizeof(uint8_t); 111 for (const auto& effecter : effecters) 112 { 113 auto set = effecter.value("set", empty); 114 state_effecter_possible_states* possibleStates = 115 reinterpret_cast<state_effecter_possible_states*>(start); 116 possibleStates->state_set_id = set.value("id", 0); 117 possibleStates->possible_states_size = set.value("size", 0); 118 119 start += sizeof(possibleStates->state_set_id) + 120 sizeof(possibleStates->possible_states_size); 121 static const std::vector<uint8_t> emptyStates{}; 122 pldm::responder::pdr_utils::PossibleValues stateValues; 123 auto states = set.value("states", emptyStates); 124 for (const auto& state : states) 125 { 126 auto index = state / 8; 127 auto bit = state - (index * 8); 128 bitfield8_t* bf = reinterpret_cast<bitfield8_t*>(start + index); 129 bf->byte |= 1 << bit; 130 stateValues.emplace_back(state); 131 } 132 start += possibleStates->possible_states_size; 133 134 auto dbusEntry = effecter.value("dbus", empty); 135 auto objectPath = dbusEntry.value("path", ""); 136 auto interface = dbusEntry.value("interface", ""); 137 auto propertyName = dbusEntry.value("property_name", ""); 138 auto propertyType = dbusEntry.value("property_type", ""); 139 140 pldm::responder::pdr_utils::StatestoDbusVal dbusIdToValMap{}; 141 pldm::utils::DBusMapping dbusMapping{}; 142 try 143 { 144 auto service = 145 dBusIntf.getService(objectPath.c_str(), interface.c_str()); 146 147 dbusMapping = pldm::utils::DBusMapping{ 148 objectPath, interface, propertyName, propertyType}; 149 dbusIdToValMap = pldm::responder::pdr_utils::populateMapping( 150 propertyType, dbusEntry["property_values"], stateValues); 151 } 152 catch (const std::exception& e) 153 { 154 std::cerr << "D-Bus object path does not exist, effecter ID: " 155 << pdr->effecter_id << "\n"; 156 } 157 158 dbusMappings.emplace_back(std::move(dbusMapping)); 159 dbusValMaps.emplace_back(std::move(dbusIdToValMap)); 160 } 161 handler.addDbusObjMaps( 162 pdr->effecter_id, 163 std::make_tuple(std::move(dbusMappings), std::move(dbusValMaps))); 164 pldm::responder::pdr_utils::PdrEntry pdrEntry{}; 165 pdrEntry.data = entry.data(); 166 pdrEntry.size = pdrSize; 167 repo.addRecord(pdrEntry); 168 } 169 } 170 171 } // namespace pdr_state_effecter 172 } // namespace responder 173 } // namespace pldm 174