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