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 namespace pldm 10 { 11 12 namespace responder 13 { 14 15 namespace pdr_state_effecter 16 { 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 std::cerr << "Malformed PDR JSON return " 46 "pdrEntry;- no state set " 47 "info, TYPE=" 48 << PLDM_STATE_EFFECTER_PDR << "\n"; 49 throw InternalFailure(); 50 } 51 pdrSize += sizeof(state_effecter_possible_states) - 52 sizeof(bitfield8_t) + (sizeof(bitfield8_t) * statesSize); 53 } 54 pdrSize += sizeof(pldm_state_effecter_pdr) - sizeof(uint8_t); 55 56 std::vector<uint8_t> entry{}; 57 entry.resize(pdrSize); 58 59 pldm_state_effecter_pdr* pdr = 60 reinterpret_cast<pldm_state_effecter_pdr*>(entry.data()); 61 if (!pdr) 62 { 63 std::cerr << "Failed to get state effecter PDR.\n"; 64 continue; 65 } 66 pdr->hdr.record_handle = 0; 67 pdr->hdr.version = 1; 68 pdr->hdr.type = PLDM_STATE_EFFECTER_PDR; 69 pdr->hdr.record_change_num = 0; 70 pdr->hdr.length = pdrSize - sizeof(pldm_pdr_hdr); 71 72 pdr->terminus_handle = TERMINUS_HANDLE; 73 pdr->effecter_id = handler.getNextEffecterId(); 74 75 try 76 { 77 std::string entity_path = e.value("entity_path", ""); 78 auto& associatedEntityMap = handler.getAssociateEntityMap(); 79 if (entity_path != "" && associatedEntityMap.find(entity_path) != 80 associatedEntityMap.end()) 81 { 82 pdr->entity_type = 83 associatedEntityMap.at(entity_path).entity_type; 84 pdr->entity_instance = 85 associatedEntityMap.at(entity_path).entity_instance_num; 86 pdr->container_id = 87 associatedEntityMap.at(entity_path).entity_container_id; 88 } 89 else 90 { 91 pdr->entity_type = e.value("type", 0); 92 pdr->entity_instance = e.value("instance", 0); 93 pdr->container_id = e.value("container", 0); 94 } 95 } 96 catch (const std::exception& ex) 97 { 98 pdr->entity_type = e.value("type", 0); 99 pdr->entity_instance = e.value("instance", 0); 100 pdr->container_id = e.value("container", 0); 101 } 102 103 pdr->effecter_semantic_id = 0; 104 pdr->effecter_init = PLDM_NO_INIT; 105 pdr->has_description_pdr = false; 106 pdr->composite_effecter_count = effecters.size(); 107 108 pldm::responder::pdr_utils::DbusMappings dbusMappings{}; 109 pldm::responder::pdr_utils::DbusValMaps dbusValMaps{}; 110 uint8_t* start = 111 entry.data() + sizeof(pldm_state_effecter_pdr) - sizeof(uint8_t); 112 for (const auto& effecter : effecters) 113 { 114 auto set = effecter.value("set", empty); 115 state_effecter_possible_states* possibleStates = 116 reinterpret_cast<state_effecter_possible_states*>(start); 117 possibleStates->state_set_id = set.value("id", 0); 118 possibleStates->possible_states_size = set.value("size", 0); 119 120 start += sizeof(possibleStates->state_set_id) + 121 sizeof(possibleStates->possible_states_size); 122 static const std::vector<uint8_t> emptyStates{}; 123 pldm::responder::pdr_utils::PossibleValues stateValues; 124 auto states = set.value("states", emptyStates); 125 for (const auto& state : states) 126 { 127 auto index = state / 8; 128 auto bit = state - (index * 8); 129 bitfield8_t* bf = reinterpret_cast<bitfield8_t*>(start + index); 130 bf->byte |= 1 << bit; 131 stateValues.emplace_back(state); 132 } 133 start += possibleStates->possible_states_size; 134 135 auto dbusEntry = effecter.value("dbus", empty); 136 auto objectPath = dbusEntry.value("path", ""); 137 auto interface = dbusEntry.value("interface", ""); 138 auto propertyName = dbusEntry.value("property_name", ""); 139 auto propertyType = dbusEntry.value("property_type", ""); 140 141 pldm::responder::pdr_utils::StatestoDbusVal dbusIdToValMap{}; 142 pldm::utils::DBusMapping dbusMapping{}; 143 try 144 { 145 auto service = 146 dBusIntf.getService(objectPath.c_str(), interface.c_str()); 147 148 dbusMapping = pldm::utils::DBusMapping{ 149 objectPath, interface, propertyName, propertyType}; 150 dbusIdToValMap = pldm::responder::pdr_utils::populateMapping( 151 propertyType, dbusEntry["property_values"], stateValues); 152 } 153 catch (const std::exception& e) 154 { 155 std::cerr << "D-Bus object path does not exist, effecter ID: " 156 << pdr->effecter_id << "\n"; 157 } 158 159 dbusMappings.emplace_back(std::move(dbusMapping)); 160 dbusValMaps.emplace_back(std::move(dbusIdToValMap)); 161 } 162 handler.addDbusObjMaps( 163 pdr->effecter_id, 164 std::make_tuple(std::move(dbusMappings), std::move(dbusValMaps))); 165 pldm::responder::pdr_utils::PdrEntry pdrEntry{}; 166 pdrEntry.data = entry.data(); 167 pdrEntry.size = pdrSize; 168 repo.addRecord(pdrEntry); 169 } 170 } 171 172 } // namespace pdr_state_effecter 173 } // namespace responder 174 } // namespace pldm 175