1 2 #include "platform.hpp" 3 4 #include "pdr_state_effecter.hpp" 5 #include "utils.hpp" 6 7 namespace pldm 8 { 9 namespace responder 10 { 11 namespace platform 12 { 13 14 using InternalFailure = 15 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure; 16 17 static const Json empty{}; 18 19 void Handler::addDbusObjMaps( 20 uint16_t effecterId, 21 std::tuple<pdr_utils::DbusMappings, pdr_utils::DbusValMaps> dbusObj) 22 { 23 dbusObjMaps.emplace(effecterId, dbusObj); 24 } 25 26 const std::tuple<pdr_utils::DbusMappings, pdr_utils::DbusValMaps>& 27 Handler::getDbusObjMaps(uint16_t effecterId) const 28 { 29 return dbusObjMaps.at(effecterId); 30 } 31 32 void Handler::generate(const std::string& dir, Repo& repo) 33 { 34 // A map of PDR type to a lambda that handles creation of that PDR type. 35 // The lambda essentially would parse the platform specific PDR JSONs to 36 // generate the PDR structures. This function iterates through the map to 37 // invoke all lambdas, so that all PDR types can be created. 38 39 const std::map<Type, generatePDR> generateHandlers = { 40 {PLDM_STATE_EFFECTER_PDR, 41 [this](const auto& json, RepoInterface& repo) { 42 pdr_state_effecter::generateStateEffecterPDR<Handler>(json, *this, 43 repo); 44 }}}; 45 46 Type pdrType{}; 47 for (const auto& dirEntry : fs::directory_iterator(dir)) 48 { 49 try 50 { 51 auto json = readJson(dirEntry.path().string()); 52 if (!json.empty()) 53 { 54 auto effecterPDRs = json.value("effecterPDRs", empty); 55 for (const auto& effecter : effecterPDRs) 56 { 57 pdrType = effecter.value("pdrType", 0); 58 generateHandlers.at(pdrType)(effecter, repo); 59 } 60 } 61 } 62 catch (const InternalFailure& e) 63 { 64 std::cerr << "PDR config directory does not exist or empty, TYPE= " 65 << pdrType << "PATH= " << dirEntry 66 << " ERROR=" << e.what() << "\n"; 67 } 68 catch (const Json::exception& e) 69 { 70 std::cerr << "Failed parsing PDR JSON file, TYPE= " << pdrType 71 << " ERROR=" << e.what() << "\n"; 72 pldm::utils::reportError( 73 "xyz.openbmc_project.bmc.pldm.InternalFailure"); 74 } 75 catch (const std::exception& e) 76 { 77 std::cerr << "Failed parsing PDR JSON file, TYPE= " << pdrType 78 << " ERROR=" << e.what() << "\n"; 79 pldm::utils::reportError( 80 "xyz.openbmc_project.bmc.pldm.InternalFailure"); 81 } 82 } 83 } 84 85 Response Handler::getPDR(const pldm_msg* request, size_t payloadLength) 86 { 87 Response response(sizeof(pldm_msg_hdr) + PLDM_GET_PDR_MIN_RESP_BYTES, 0); 88 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data()); 89 90 if (payloadLength != PLDM_GET_PDR_REQ_BYTES) 91 { 92 return CmdHandler::ccOnlyResponse(request, PLDM_ERROR_INVALID_LENGTH); 93 } 94 95 uint32_t recordHandle{}; 96 uint32_t dataTransferHandle{}; 97 uint8_t transferOpFlag{}; 98 uint16_t reqSizeBytes{}; 99 uint16_t recordChangeNum{}; 100 101 auto rc = decode_get_pdr_req(request, payloadLength, &recordHandle, 102 &dataTransferHandle, &transferOpFlag, 103 &reqSizeBytes, &recordChangeNum); 104 if (rc != PLDM_SUCCESS) 105 { 106 return CmdHandler::ccOnlyResponse(request, rc); 107 } 108 109 uint16_t respSizeBytes{}; 110 uint8_t* recordData = nullptr; 111 try 112 { 113 pdr_utils::PdrEntry e; 114 auto record = pdr::getRecordByHandle(pdrRepo, recordHandle, e); 115 if (record == NULL) 116 { 117 return CmdHandler::ccOnlyResponse( 118 request, PLDM_PLATFORM_INVALID_RECORD_HANDLE); 119 } 120 121 if (reqSizeBytes) 122 { 123 respSizeBytes = e.size; 124 if (respSizeBytes > reqSizeBytes) 125 { 126 respSizeBytes = reqSizeBytes; 127 } 128 recordData = e.data; 129 } 130 response.resize(sizeof(pldm_msg_hdr) + PLDM_GET_PDR_MIN_RESP_BYTES + 131 respSizeBytes, 132 0); 133 responsePtr = reinterpret_cast<pldm_msg*>(response.data()); 134 rc = encode_get_pdr_resp( 135 request->hdr.instance_id, PLDM_SUCCESS, e.handle.nextRecordHandle, 136 0, PLDM_START_AND_END, respSizeBytes, recordData, 0, responsePtr); 137 if (rc != PLDM_SUCCESS) 138 { 139 return ccOnlyResponse(request, rc); 140 } 141 } 142 catch (const std::exception& e) 143 { 144 std::cerr << "Error accessing PDR, HANDLE=" << recordHandle 145 << " ERROR=" << e.what() << "\n"; 146 return CmdHandler::ccOnlyResponse(request, PLDM_ERROR); 147 } 148 return response; 149 } 150 151 Response Handler::setStateEffecterStates(const pldm_msg* request, 152 size_t payloadLength) 153 { 154 Response response( 155 sizeof(pldm_msg_hdr) + PLDM_SET_STATE_EFFECTER_STATES_RESP_BYTES, 0); 156 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data()); 157 uint16_t effecterId; 158 uint8_t compEffecterCnt; 159 constexpr auto maxCompositeEffecterCnt = 8; 160 std::vector<set_effecter_state_field> stateField(maxCompositeEffecterCnt, 161 {0, 0}); 162 163 if ((payloadLength > PLDM_SET_STATE_EFFECTER_STATES_REQ_BYTES) || 164 (payloadLength < sizeof(effecterId) + sizeof(compEffecterCnt) + 165 sizeof(set_effecter_state_field))) 166 { 167 return CmdHandler::ccOnlyResponse(request, PLDM_ERROR_INVALID_LENGTH); 168 } 169 170 int rc = decode_set_state_effecter_states_req(request, payloadLength, 171 &effecterId, &compEffecterCnt, 172 stateField.data()); 173 174 if (rc != PLDM_SUCCESS) 175 { 176 return CmdHandler::ccOnlyResponse(request, rc); 177 } 178 179 stateField.resize(compEffecterCnt); 180 const pldm::utils::DBusHandler dBusIntf; 181 rc = setStateEffecterStatesHandler<pldm::utils::DBusHandler>( 182 dBusIntf, effecterId, stateField); 183 if (rc != PLDM_SUCCESS) 184 { 185 return CmdHandler::ccOnlyResponse(request, rc); 186 } 187 188 rc = encode_set_state_effecter_states_resp(request->hdr.instance_id, rc, 189 responsePtr); 190 if (rc != PLDM_SUCCESS) 191 { 192 return ccOnlyResponse(request, rc); 193 } 194 195 return response; 196 } 197 198 Response Handler::platformEventMessage(const pldm_msg* request, 199 size_t payloadLength) 200 { 201 uint8_t formatVersion{}; 202 uint8_t tid{}; 203 uint8_t eventClass{}; 204 size_t offset{}; 205 206 auto rc = decode_platform_event_message_req( 207 request, payloadLength, &formatVersion, &tid, &eventClass, &offset); 208 if (rc != PLDM_SUCCESS) 209 { 210 return CmdHandler::ccOnlyResponse(request, rc); 211 } 212 213 try 214 { 215 const auto& handlers = eventHandlers.at(eventClass); 216 for (const auto& handler : handlers) 217 { 218 auto rc = 219 handler(request, payloadLength, formatVersion, tid, offset); 220 if (rc != PLDM_SUCCESS) 221 { 222 return CmdHandler::ccOnlyResponse(request, rc); 223 } 224 } 225 } 226 catch (const std::out_of_range& e) 227 { 228 return CmdHandler::ccOnlyResponse(request, PLDM_ERROR_INVALID_DATA); 229 } 230 231 Response response( 232 sizeof(pldm_msg_hdr) + PLDM_PLATFORM_EVENT_MESSAGE_RESP_BYTES, 0); 233 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data()); 234 235 rc = encode_platform_event_message_resp(request->hdr.instance_id, rc, 236 PLDM_EVENT_NO_LOGGING, responsePtr); 237 if (rc != PLDM_SUCCESS) 238 { 239 return ccOnlyResponse(request, rc); 240 } 241 242 return response; 243 } 244 245 int Handler::sensorEvent(const pldm_msg* request, size_t payloadLength, 246 uint8_t /*formatVersion*/, uint8_t /*tid*/, 247 size_t eventDataOffset) 248 { 249 uint16_t sensorId{}; 250 uint8_t eventClass{}; 251 size_t eventClassDataOffset{}; 252 auto eventData = 253 reinterpret_cast<const uint8_t*>(request->payload) + eventDataOffset; 254 auto eventDataSize = payloadLength - eventDataOffset; 255 256 auto rc = decode_sensor_event_data(eventData, eventDataSize, &sensorId, 257 &eventClass, &eventClassDataOffset); 258 if (rc != PLDM_SUCCESS) 259 { 260 return rc; 261 } 262 263 if (eventClass == PLDM_STATE_SENSOR_STATE) 264 { 265 uint8_t sensorOffset{}; 266 uint8_t eventState{}; 267 uint8_t previousEventState{}; 268 269 rc = decode_state_sensor_data(&eventClass, eventClassDataOffset, 270 &sensorOffset, &eventState, 271 &previousEventState); 272 } 273 else 274 { 275 return PLDM_ERROR_INVALID_DATA; 276 } 277 278 return PLDM_SUCCESS; 279 } 280 281 } // namespace platform 282 } // namespace responder 283 } // namespace pldm 284