1 2 #include "platform.hpp" 3 4 #include "pdr_numeric_effecter.hpp" 5 #include "pdr_state_effecter.hpp" 6 #include "platform_state_effecter.hpp" 7 #include "utils.hpp" 8 9 namespace pldm 10 { 11 namespace responder 12 { 13 namespace platform 14 { 15 16 using InternalFailure = 17 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure; 18 19 static const Json empty{}; 20 21 using EventEntryMap = std::map<EventEntry, DBusInfo>; 22 23 const EventEntryMap eventEntryMap = { 24 { 25 0x01010007, // SensorID for VMI Port 0 ipv4 = 7, SensorOffset for the 26 // State Set ID 15 = 1 & PLDM State Set Enumeration List = 1 27 // (Valid Configuration) 28 {"/xyz/openbmc_project/network/vmi/intf0/ipv4/addr0", 29 "xyz.openbmc_project.Object.Enable", "Enabled", "bool", true}, 30 }, 31 { 32 0x02010007, // SensorID for VMI Port 0 ipv4 = 7, SensorOffset for the 33 // State Set ID 15 = 1 & PLDM State Set Enumeration List = 2 34 // (Invalid Configuration) 35 {"/xyz/openbmc_project/network/vmi/intf0/ipv4/addr0", 36 "xyz.openbmc_project.Object.Enable", "Enabled", "bool", false}, 37 }, 38 { 39 0x01010008, // SensorID for VMI Port 1 ipv4 = 8, SensorOffset for the 40 // State Set ID 15 = 1 & PLDM State Set Enumeration List = 1 41 // (Valid Configuration) 42 {"/xyz/openbmc_project/network/vmi/intf1/ipv4/addr0", 43 "xyz.openbmc_project.Object.Enable", "Enabled", "bool", true}, 44 }, 45 { 46 0x02010008, // SensorID for VMI Port 1 ipv4 = 8, SensorOffset for the 47 // State Set ID 15 = 1 & PLDM State Set Enumeration List = 2 48 // (Invalid Configuration) 49 {"/xyz/openbmc_project/network/vmi/intf1/ipv4/addr0", 50 "xyz.openbmc_project.Object.Enable", "Enabled", "bool", false}, 51 }}; 52 53 void Handler::addDbusObjMaps( 54 uint16_t effecterId, 55 std::tuple<pdr_utils::DbusMappings, pdr_utils::DbusValMaps> dbusObj) 56 { 57 dbusObjMaps.emplace(effecterId, dbusObj); 58 } 59 60 const std::tuple<pdr_utils::DbusMappings, pdr_utils::DbusValMaps>& 61 Handler::getDbusObjMaps(uint16_t effecterId) const 62 { 63 return dbusObjMaps.at(effecterId); 64 } 65 66 void Handler::generate(const std::string& dir, Repo& repo) 67 { 68 // A map of PDR type to a lambda that handles creation of that PDR type. 69 // The lambda essentially would parse the platform specific PDR JSONs to 70 // generate the PDR structures. This function iterates through the map to 71 // invoke all lambdas, so that all PDR types can be created. 72 73 const std::map<Type, generatePDR> generateHandlers = { 74 {PLDM_STATE_EFFECTER_PDR, 75 [this](const auto& json, RepoInterface& repo) { 76 pdr_state_effecter::generateStateEffecterPDR<Handler>(json, *this, 77 repo); 78 }}, 79 {PLDM_NUMERIC_EFFECTER_PDR, 80 [this](const auto& json, RepoInterface& repo) { 81 pdr_numeric_effecter::generateNumericEffecterPDR<Handler>( 82 json, *this, repo); 83 }}}; 84 85 Type pdrType{}; 86 for (const auto& dirEntry : fs::directory_iterator(dir)) 87 { 88 try 89 { 90 auto json = readJson(dirEntry.path().string()); 91 if (!json.empty()) 92 { 93 auto effecterPDRs = json.value("effecterPDRs", empty); 94 for (const auto& effecter : effecterPDRs) 95 { 96 pdrType = effecter.value("pdrType", 0); 97 generateHandlers.at(pdrType)(effecter, repo); 98 } 99 } 100 } 101 catch (const InternalFailure& e) 102 { 103 std::cerr << "PDR config directory does not exist or empty, TYPE= " 104 << pdrType << "PATH= " << dirEntry 105 << " ERROR=" << e.what() << "\n"; 106 } 107 catch (const Json::exception& e) 108 { 109 std::cerr << "Failed parsing PDR JSON file, TYPE= " << pdrType 110 << " ERROR=" << e.what() << "\n"; 111 pldm::utils::reportError( 112 "xyz.openbmc_project.bmc.pldm.InternalFailure"); 113 } 114 catch (const std::exception& e) 115 { 116 std::cerr << "Failed parsing PDR JSON file, TYPE= " << pdrType 117 << " ERROR=" << e.what() << "\n"; 118 pldm::utils::reportError( 119 "xyz.openbmc_project.bmc.pldm.InternalFailure"); 120 } 121 } 122 } 123 124 Response Handler::getPDR(const pldm_msg* request, size_t payloadLength) 125 { 126 Response response(sizeof(pldm_msg_hdr) + PLDM_GET_PDR_MIN_RESP_BYTES, 0); 127 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data()); 128 129 if (payloadLength != PLDM_GET_PDR_REQ_BYTES) 130 { 131 return CmdHandler::ccOnlyResponse(request, PLDM_ERROR_INVALID_LENGTH); 132 } 133 134 uint32_t recordHandle{}; 135 uint32_t dataTransferHandle{}; 136 uint8_t transferOpFlag{}; 137 uint16_t reqSizeBytes{}; 138 uint16_t recordChangeNum{}; 139 140 auto rc = decode_get_pdr_req(request, payloadLength, &recordHandle, 141 &dataTransferHandle, &transferOpFlag, 142 &reqSizeBytes, &recordChangeNum); 143 if (rc != PLDM_SUCCESS) 144 { 145 return CmdHandler::ccOnlyResponse(request, rc); 146 } 147 148 uint16_t respSizeBytes{}; 149 uint8_t* recordData = nullptr; 150 try 151 { 152 pdr_utils::PdrEntry e; 153 auto record = pdr::getRecordByHandle(pdrRepo, recordHandle, e); 154 if (record == NULL) 155 { 156 return CmdHandler::ccOnlyResponse( 157 request, PLDM_PLATFORM_INVALID_RECORD_HANDLE); 158 } 159 160 if (reqSizeBytes) 161 { 162 respSizeBytes = e.size; 163 if (respSizeBytes > reqSizeBytes) 164 { 165 respSizeBytes = reqSizeBytes; 166 } 167 recordData = e.data; 168 } 169 response.resize(sizeof(pldm_msg_hdr) + PLDM_GET_PDR_MIN_RESP_BYTES + 170 respSizeBytes, 171 0); 172 responsePtr = reinterpret_cast<pldm_msg*>(response.data()); 173 rc = encode_get_pdr_resp( 174 request->hdr.instance_id, PLDM_SUCCESS, e.handle.nextRecordHandle, 175 0, PLDM_START_AND_END, respSizeBytes, recordData, 0, responsePtr); 176 if (rc != PLDM_SUCCESS) 177 { 178 return ccOnlyResponse(request, rc); 179 } 180 } 181 catch (const std::exception& e) 182 { 183 std::cerr << "Error accessing PDR, HANDLE=" << recordHandle 184 << " ERROR=" << e.what() << "\n"; 185 return CmdHandler::ccOnlyResponse(request, PLDM_ERROR); 186 } 187 return response; 188 } 189 190 Response Handler::setStateEffecterStates(const pldm_msg* request, 191 size_t payloadLength) 192 { 193 Response response( 194 sizeof(pldm_msg_hdr) + PLDM_SET_STATE_EFFECTER_STATES_RESP_BYTES, 0); 195 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data()); 196 uint16_t effecterId; 197 uint8_t compEffecterCnt; 198 constexpr auto maxCompositeEffecterCnt = 8; 199 std::vector<set_effecter_state_field> stateField(maxCompositeEffecterCnt, 200 {0, 0}); 201 202 if ((payloadLength > PLDM_SET_STATE_EFFECTER_STATES_REQ_BYTES) || 203 (payloadLength < sizeof(effecterId) + sizeof(compEffecterCnt) + 204 sizeof(set_effecter_state_field))) 205 { 206 return CmdHandler::ccOnlyResponse(request, PLDM_ERROR_INVALID_LENGTH); 207 } 208 209 int rc = decode_set_state_effecter_states_req(request, payloadLength, 210 &effecterId, &compEffecterCnt, 211 stateField.data()); 212 213 if (rc != PLDM_SUCCESS) 214 { 215 return CmdHandler::ccOnlyResponse(request, rc); 216 } 217 218 stateField.resize(compEffecterCnt); 219 const pldm::utils::DBusHandler dBusIntf; 220 rc = platform_state_effecter::setStateEffecterStatesHandler< 221 pldm::utils::DBusHandler, Handler>(dBusIntf, *this, effecterId, 222 stateField); 223 if (rc != PLDM_SUCCESS) 224 { 225 return CmdHandler::ccOnlyResponse(request, rc); 226 } 227 228 rc = encode_set_state_effecter_states_resp(request->hdr.instance_id, rc, 229 responsePtr); 230 if (rc != PLDM_SUCCESS) 231 { 232 return ccOnlyResponse(request, rc); 233 } 234 235 return response; 236 } 237 238 Response Handler::platformEventMessage(const pldm_msg* request, 239 size_t payloadLength) 240 { 241 uint8_t formatVersion{}; 242 uint8_t tid{}; 243 uint8_t eventClass{}; 244 size_t offset{}; 245 246 auto rc = decode_platform_event_message_req( 247 request, payloadLength, &formatVersion, &tid, &eventClass, &offset); 248 if (rc != PLDM_SUCCESS) 249 { 250 return CmdHandler::ccOnlyResponse(request, rc); 251 } 252 253 try 254 { 255 const auto& handlers = eventHandlers.at(eventClass); 256 for (const auto& handler : handlers) 257 { 258 auto rc = 259 handler(request, payloadLength, formatVersion, tid, offset); 260 if (rc != PLDM_SUCCESS) 261 { 262 return CmdHandler::ccOnlyResponse(request, rc); 263 } 264 } 265 } 266 catch (const std::out_of_range& e) 267 { 268 return CmdHandler::ccOnlyResponse(request, PLDM_ERROR_INVALID_DATA); 269 } 270 271 Response response( 272 sizeof(pldm_msg_hdr) + PLDM_PLATFORM_EVENT_MESSAGE_RESP_BYTES, 0); 273 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data()); 274 275 rc = encode_platform_event_message_resp(request->hdr.instance_id, rc, 276 PLDM_EVENT_NO_LOGGING, responsePtr); 277 if (rc != PLDM_SUCCESS) 278 { 279 return ccOnlyResponse(request, rc); 280 } 281 282 return response; 283 } 284 285 int Handler::sensorEvent(const pldm_msg* request, size_t payloadLength, 286 uint8_t /*formatVersion*/, uint8_t /*tid*/, 287 size_t eventDataOffset) 288 { 289 uint16_t sensorId{}; 290 uint8_t eventClass{}; 291 size_t eventClassDataOffset{}; 292 auto eventData = 293 reinterpret_cast<const uint8_t*>(request->payload) + eventDataOffset; 294 auto eventDataSize = payloadLength - eventDataOffset; 295 296 auto rc = decode_sensor_event_data(eventData, eventDataSize, &sensorId, 297 &eventClass, &eventClassDataOffset); 298 if (rc != PLDM_SUCCESS) 299 { 300 return rc; 301 } 302 303 auto eventClassData = reinterpret_cast<const uint8_t*>(request->payload) + 304 eventDataOffset + eventClassDataOffset; 305 auto eventClassDataSize = 306 payloadLength - eventDataOffset - eventClassDataOffset; 307 308 if (eventClass == PLDM_STATE_SENSOR_STATE) 309 { 310 uint8_t sensorOffset{}; 311 uint8_t eventState{}; 312 uint8_t previousEventState{}; 313 314 rc = decode_state_sensor_data(eventClassData, eventClassDataSize, 315 &sensorOffset, &eventState, 316 &previousEventState); 317 if (rc != PLDM_SUCCESS) 318 { 319 return PLDM_ERROR; 320 } 321 322 rc = setSensorEventData(sensorId, sensorOffset, eventState); 323 324 if (rc != PLDM_SUCCESS) 325 { 326 return PLDM_ERROR; 327 } 328 } 329 else 330 { 331 return PLDM_ERROR_INVALID_DATA; 332 } 333 334 return PLDM_SUCCESS; 335 } 336 337 int Handler::setSensorEventData(uint16_t sensorId, uint8_t sensorOffset, 338 uint8_t eventState) 339 { 340 EventEntry eventEntry = ((static_cast<uint32_t>(eventState)) << 24) + 341 ((static_cast<uint32_t>(sensorOffset)) << 16) + 342 sensorId; 343 auto iter = eventEntryMap.find(eventEntry); 344 if (iter == eventEntryMap.end()) 345 { 346 return PLDM_SUCCESS; 347 } 348 349 const auto& dBusInfo = iter->second; 350 try 351 { 352 pldm::utils::DBusMapping dbusMapping{ 353 dBusInfo.dBusValues.objectPath, dBusInfo.dBusValues.interface, 354 dBusInfo.dBusValues.propertyName, dBusInfo.dBusValues.propertyType}; 355 pldm::utils::DBusHandler().setDbusProperty(dbusMapping, 356 dBusInfo.dBusPropertyValue); 357 } 358 catch (std::exception& e) 359 { 360 361 std::cerr 362 << "Error Setting dbus property,SensorID=" << eventEntry 363 << "DBusInfo=" << dBusInfo.dBusValues.objectPath 364 << dBusInfo.dBusValues.interface << dBusInfo.dBusValues.propertyName 365 << "ERROR=" << e.what() << "\n"; 366 return PLDM_ERROR; 367 } 368 return PLDM_SUCCESS; 369 } 370 371 int Handler::pldmPDRRepositoryChgEvent(const pldm_msg* request, 372 size_t payloadLength, 373 uint8_t /*formatVersion*/, 374 uint8_t /*tid*/, size_t eventDataOffset) 375 { 376 uint8_t eventDataFormat{}; 377 uint8_t numberOfChangeRecords{}; 378 size_t dataOffset{}; 379 380 auto eventData = 381 reinterpret_cast<const uint8_t*>(request->payload) + eventDataOffset; 382 auto eventDataSize = payloadLength - eventDataOffset; 383 384 auto rc = decode_pldm_pdr_repository_chg_event_data( 385 eventData, eventDataSize, &eventDataFormat, &numberOfChangeRecords, 386 &dataOffset); 387 if (rc != PLDM_SUCCESS) 388 { 389 return rc; 390 } 391 392 PDRRecordHandles pdrRecordHandles; 393 if (eventDataFormat == FORMAT_IS_PDR_HANDLES) 394 { 395 uint8_t eventDataOperation{}; 396 uint8_t numberOfChangeEntries{}; 397 398 auto changeRecordData = eventData + dataOffset; 399 auto changeRecordDataSize = eventDataSize - dataOffset; 400 401 while (changeRecordDataSize) 402 { 403 rc = decode_pldm_pdr_repository_change_record_data( 404 changeRecordData, changeRecordDataSize, &eventDataOperation, 405 &numberOfChangeEntries, &dataOffset); 406 407 if (rc != PLDM_SUCCESS) 408 { 409 return rc; 410 } 411 412 if (eventDataOperation == PLDM_RECORDS_ADDED) 413 { 414 rc = getPDRRecordHandles( 415 reinterpret_cast<const ChangeEntry*>(changeRecordData + 416 dataOffset), 417 changeRecordDataSize - dataOffset, 418 static_cast<size_t>(numberOfChangeEntries), 419 pdrRecordHandles); 420 421 if (rc != PLDM_SUCCESS) 422 { 423 return rc; 424 } 425 } 426 427 changeRecordData += 428 dataOffset + (numberOfChangeEntries * sizeof(ChangeEntry)); 429 changeRecordDataSize -= 430 dataOffset + (numberOfChangeEntries * sizeof(ChangeEntry)); 431 } 432 433 if (hostPDRHandler && !pdrRecordHandles.empty()) 434 { 435 hostPDRHandler->fetchPDR(std::move(pdrRecordHandles)); 436 } 437 } 438 else 439 { 440 return PLDM_ERROR_INVALID_DATA; 441 } 442 443 return PLDM_SUCCESS; 444 } 445 446 int Handler::getPDRRecordHandles(const ChangeEntry* changeEntryData, 447 size_t changeEntryDataSize, 448 size_t numberOfChangeEntries, 449 PDRRecordHandles& pdrRecordHandles) 450 { 451 if (numberOfChangeEntries > (changeEntryDataSize / sizeof(ChangeEntry))) 452 { 453 return PLDM_ERROR_INVALID_DATA; 454 } 455 for (size_t i = 0; i < numberOfChangeEntries; i++) 456 { 457 pdrRecordHandles.push_back(changeEntryData[i]); 458 } 459 return PLDM_SUCCESS; 460 } 461 462 } // namespace platform 463 } // namespace responder 464 } // namespace pldm 465