1 #include "platform.hpp" 2 3 #include "libpldm/entity.h" 4 #include "libpldm/state_set.h" 5 6 #include "common/types.hpp" 7 #include "common/utils.hpp" 8 #include "event_parser.hpp" 9 #include "pdr.hpp" 10 #include "pdr_numeric_effecter.hpp" 11 #include "pdr_state_effecter.hpp" 12 #include "pdr_state_sensor.hpp" 13 #include "pdr_utils.hpp" 14 #include "platform_numeric_effecter.hpp" 15 #include "platform_state_effecter.hpp" 16 #include "platform_state_sensor.hpp" 17 18 #include <config.h> 19 20 using namespace pldm::utils; 21 using namespace pldm::responder::pdr; 22 using namespace pldm::responder::pdr_utils; 23 24 namespace pldm 25 { 26 namespace responder 27 { 28 namespace platform 29 { 30 31 using InternalFailure = 32 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure; 33 34 static const Json empty{}; 35 36 void Handler::addDbusObjMaps( 37 uint16_t id, 38 std::tuple<pdr_utils::DbusMappings, pdr_utils::DbusValMaps> dbusObj, 39 TypeId typeId) 40 { 41 if (typeId == TypeId::PLDM_SENSOR_ID) 42 { 43 sensorDbusObjMaps.emplace(id, dbusObj); 44 } 45 else 46 { 47 effecterDbusObjMaps.emplace(id, dbusObj); 48 } 49 } 50 51 const std::tuple<pdr_utils::DbusMappings, pdr_utils::DbusValMaps>& 52 Handler::getDbusObjMaps(uint16_t id, TypeId typeId) const 53 { 54 if (typeId == TypeId::PLDM_SENSOR_ID) 55 { 56 return sensorDbusObjMaps.at(id); 57 } 58 else 59 { 60 return effecterDbusObjMaps.at(id); 61 } 62 } 63 64 void Handler::generate(const pldm::utils::DBusHandler& dBusIntf, 65 const std::string& dir, Repo& repo) 66 { 67 if (!fs::exists(dir)) 68 { 69 return; 70 } 71 72 // A map of PDR type to a lambda that handles creation of that PDR type. 73 // The lambda essentially would parse the platform specific PDR JSONs to 74 // generate the PDR structures. This function iterates through the map to 75 // invoke all lambdas, so that all PDR types can be created. 76 77 const std::map<Type, generatePDR> generateHandlers = { 78 {PLDM_STATE_EFFECTER_PDR, 79 [this](const DBusHandler& dBusIntf, const auto& json, 80 RepoInterface& repo) { 81 pdr_state_effecter::generateStateEffecterPDR< 82 pldm::utils::DBusHandler, Handler>(dBusIntf, json, *this, 83 repo); 84 }}, 85 {PLDM_NUMERIC_EFFECTER_PDR, 86 [this](const DBusHandler& dBusIntf, const auto& json, 87 RepoInterface& repo) { 88 pdr_numeric_effecter::generateNumericEffecterPDR< 89 pldm::utils::DBusHandler, Handler>(dBusIntf, json, *this, 90 repo); 91 }}, 92 {PLDM_STATE_SENSOR_PDR, [this](const DBusHandler& dBusIntf, 93 const auto& json, RepoInterface& repo) { 94 pdr_state_sensor::generateStateSensorPDR<pldm::utils::DBusHandler, 95 Handler>(dBusIntf, json, 96 *this, repo); 97 }}}; 98 99 Type pdrType{}; 100 for (const auto& dirEntry : fs::directory_iterator(dir)) 101 { 102 try 103 { 104 auto json = readJson(dirEntry.path().string()); 105 if (!json.empty()) 106 { 107 auto effecterPDRs = json.value("effecterPDRs", empty); 108 for (const auto& effecter : effecterPDRs) 109 { 110 pdrType = effecter.value("pdrType", 0); 111 generateHandlers.at(pdrType)(dBusIntf, effecter, repo); 112 } 113 114 auto sensorPDRs = json.value("sensorPDRs", empty); 115 for (const auto& sensor : sensorPDRs) 116 { 117 pdrType = sensor.value("pdrType", 0); 118 generateHandlers.at(pdrType)(dBusIntf, sensor, repo); 119 } 120 } 121 } 122 catch (const InternalFailure& e) 123 { 124 std::cerr << "PDR config directory does not exist or empty, TYPE= " 125 << pdrType << "PATH= " << dirEntry 126 << " ERROR=" << e.what() << "\n"; 127 } 128 catch (const Json::exception& e) 129 { 130 std::cerr << "Failed parsing PDR JSON file, TYPE= " << pdrType 131 << " ERROR=" << e.what() << "\n"; 132 pldm::utils::reportError( 133 "xyz.openbmc_project.bmc.pldm.InternalFailure"); 134 } 135 catch (const std::exception& e) 136 { 137 std::cerr << "Failed parsing PDR JSON file, TYPE= " << pdrType 138 << " ERROR=" << e.what() << "\n"; 139 pldm::utils::reportError( 140 "xyz.openbmc_project.bmc.pldm.InternalFailure"); 141 } 142 } 143 } 144 145 Response Handler::getPDR(const pldm_msg* request, size_t payloadLength) 146 { 147 if (hostPDRHandler) 148 { 149 if (hostPDRHandler->isHostUp() && oemPlatformHandler != nullptr) 150 { 151 auto rc = oemPlatformHandler->checkBMCState(); 152 if (rc != PLDM_SUCCESS) 153 { 154 return ccOnlyResponse(request, PLDM_ERROR_NOT_READY); 155 } 156 } 157 } 158 159 // Build FRU table if not built, since entity association PDR's 160 // are built when the FRU table is constructed. 161 if (fruHandler) 162 { 163 fruHandler->buildFRUTable(); 164 } 165 166 if (!pdrCreated) 167 { 168 generateTerminusLocatorPDR(pdrRepo); 169 generate(*dBusIntf, pdrJsonsDir, pdrRepo); 170 if (oemPlatformHandler != nullptr) 171 { 172 oemPlatformHandler->buildOEMPDR(pdrRepo); 173 } 174 175 pdrCreated = true; 176 177 if (dbusToPLDMEventHandler) 178 { 179 deferredGetPDREvent = std::make_unique<sdeventplus::source::Defer>( 180 event, 181 std::bind(std::mem_fn(&pldm::responder::platform::Handler:: 182 _processPostGetPDRActions), 183 this, std::placeholders::_1)); 184 } 185 } 186 187 Response response(sizeof(pldm_msg_hdr) + PLDM_GET_PDR_MIN_RESP_BYTES, 0); 188 189 if (payloadLength != PLDM_GET_PDR_REQ_BYTES) 190 { 191 return CmdHandler::ccOnlyResponse(request, PLDM_ERROR_INVALID_LENGTH); 192 } 193 194 uint32_t recordHandle{}; 195 uint32_t dataTransferHandle{}; 196 uint8_t transferOpFlag{}; 197 uint16_t reqSizeBytes{}; 198 uint16_t recordChangeNum{}; 199 200 auto rc = decode_get_pdr_req(request, payloadLength, &recordHandle, 201 &dataTransferHandle, &transferOpFlag, 202 &reqSizeBytes, &recordChangeNum); 203 if (rc != PLDM_SUCCESS) 204 { 205 return CmdHandler::ccOnlyResponse(request, rc); 206 } 207 208 uint16_t respSizeBytes{}; 209 uint8_t* recordData = nullptr; 210 try 211 { 212 pdr_utils::PdrEntry e; 213 auto record = pdr::getRecordByHandle(pdrRepo, recordHandle, e); 214 if (record == NULL) 215 { 216 return CmdHandler::ccOnlyResponse( 217 request, PLDM_PLATFORM_INVALID_RECORD_HANDLE); 218 } 219 220 if (reqSizeBytes) 221 { 222 respSizeBytes = e.size; 223 if (respSizeBytes > reqSizeBytes) 224 { 225 respSizeBytes = reqSizeBytes; 226 } 227 recordData = e.data; 228 } 229 response.resize(sizeof(pldm_msg_hdr) + PLDM_GET_PDR_MIN_RESP_BYTES + 230 respSizeBytes, 231 0); 232 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data()); 233 rc = encode_get_pdr_resp( 234 request->hdr.instance_id, PLDM_SUCCESS, e.handle.nextRecordHandle, 235 0, PLDM_START_AND_END, respSizeBytes, recordData, 0, responsePtr); 236 if (rc != PLDM_SUCCESS) 237 { 238 return ccOnlyResponse(request, rc); 239 } 240 } 241 catch (const std::exception& e) 242 { 243 std::cerr << "Error accessing PDR, HANDLE=" << recordHandle 244 << " ERROR=" << e.what() << "\n"; 245 return CmdHandler::ccOnlyResponse(request, PLDM_ERROR); 246 } 247 return response; 248 } 249 250 Response Handler::setStateEffecterStates(const pldm_msg* request, 251 size_t payloadLength) 252 { 253 Response response( 254 sizeof(pldm_msg_hdr) + PLDM_SET_STATE_EFFECTER_STATES_RESP_BYTES, 0); 255 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data()); 256 uint16_t effecterId; 257 uint8_t compEffecterCnt; 258 constexpr auto maxCompositeEffecterCnt = 8; 259 std::vector<set_effecter_state_field> stateField(maxCompositeEffecterCnt, 260 {0, 0}); 261 262 if ((payloadLength > PLDM_SET_STATE_EFFECTER_STATES_REQ_BYTES) || 263 (payloadLength < sizeof(effecterId) + sizeof(compEffecterCnt) + 264 sizeof(set_effecter_state_field))) 265 { 266 return CmdHandler::ccOnlyResponse(request, PLDM_ERROR_INVALID_LENGTH); 267 } 268 269 int rc = decode_set_state_effecter_states_req(request, payloadLength, 270 &effecterId, &compEffecterCnt, 271 stateField.data()); 272 273 if (rc != PLDM_SUCCESS) 274 { 275 return CmdHandler::ccOnlyResponse(request, rc); 276 } 277 278 stateField.resize(compEffecterCnt); 279 const pldm::utils::DBusHandler dBusIntf; 280 uint16_t entityType{}; 281 uint16_t entityInstance{}; 282 uint16_t stateSetId{}; 283 284 if (isOemStateEffecter(*this, effecterId, compEffecterCnt, entityType, 285 entityInstance, stateSetId) && 286 oemPlatformHandler != nullptr && 287 !effecterDbusObjMaps.contains(effecterId)) 288 { 289 rc = oemPlatformHandler->oemSetStateEffecterStatesHandler( 290 entityType, entityInstance, stateSetId, compEffecterCnt, stateField, 291 effecterId); 292 } 293 else 294 { 295 rc = platform_state_effecter::setStateEffecterStatesHandler< 296 pldm::utils::DBusHandler, Handler>(dBusIntf, *this, effecterId, 297 stateField); 298 } 299 if (rc != PLDM_SUCCESS) 300 { 301 return CmdHandler::ccOnlyResponse(request, rc); 302 } 303 304 rc = encode_set_state_effecter_states_resp(request->hdr.instance_id, rc, 305 responsePtr); 306 if (rc != PLDM_SUCCESS) 307 { 308 return ccOnlyResponse(request, rc); 309 } 310 311 return response; 312 } 313 314 Response Handler::platformEventMessage(const pldm_msg* request, 315 size_t payloadLength) 316 { 317 uint8_t formatVersion{}; 318 uint8_t tid{}; 319 uint8_t eventClass{}; 320 size_t offset{}; 321 322 auto rc = decode_platform_event_message_req( 323 request, payloadLength, &formatVersion, &tid, &eventClass, &offset); 324 if (rc != PLDM_SUCCESS) 325 { 326 return CmdHandler::ccOnlyResponse(request, rc); 327 } 328 329 if (eventClass == PLDM_HEARTBEAT_TIMER_ELAPSED_EVENT) 330 { 331 rc = PLDM_SUCCESS; 332 if (oemPlatformHandler) 333 { 334 oemPlatformHandler->resetWatchDogTimer(); 335 } 336 } 337 else 338 { 339 try 340 { 341 const auto& handlers = eventHandlers.at(eventClass); 342 for (const auto& handler : handlers) 343 { 344 auto rc = 345 handler(request, payloadLength, formatVersion, tid, offset); 346 if (rc != PLDM_SUCCESS) 347 { 348 return CmdHandler::ccOnlyResponse(request, rc); 349 } 350 } 351 } 352 catch (const std::out_of_range& e) 353 { 354 return CmdHandler::ccOnlyResponse(request, PLDM_ERROR_INVALID_DATA); 355 } 356 } 357 Response response( 358 sizeof(pldm_msg_hdr) + PLDM_PLATFORM_EVENT_MESSAGE_RESP_BYTES, 0); 359 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data()); 360 361 rc = encode_platform_event_message_resp(request->hdr.instance_id, rc, 362 PLDM_EVENT_NO_LOGGING, responsePtr); 363 if (rc != PLDM_SUCCESS) 364 { 365 return ccOnlyResponse(request, rc); 366 } 367 368 return response; 369 } 370 371 int Handler::sensorEvent(const pldm_msg* request, size_t payloadLength, 372 uint8_t /*formatVersion*/, uint8_t tid, 373 size_t eventDataOffset) 374 { 375 uint16_t sensorId{}; 376 uint8_t eventClass{}; 377 size_t eventClassDataOffset{}; 378 auto eventData = 379 reinterpret_cast<const uint8_t*>(request->payload) + eventDataOffset; 380 auto eventDataSize = payloadLength - eventDataOffset; 381 382 auto rc = decode_sensor_event_data(eventData, eventDataSize, &sensorId, 383 &eventClass, &eventClassDataOffset); 384 if (rc != PLDM_SUCCESS) 385 { 386 return rc; 387 } 388 389 auto eventClassData = reinterpret_cast<const uint8_t*>(request->payload) + 390 eventDataOffset + eventClassDataOffset; 391 auto eventClassDataSize = 392 payloadLength - eventDataOffset - eventClassDataOffset; 393 394 if (eventClass == PLDM_STATE_SENSOR_STATE) 395 { 396 uint8_t sensorOffset{}; 397 uint8_t eventState{}; 398 uint8_t previousEventState{}; 399 400 rc = decode_state_sensor_data(eventClassData, eventClassDataSize, 401 &sensorOffset, &eventState, 402 &previousEventState); 403 if (rc != PLDM_SUCCESS) 404 { 405 return PLDM_ERROR; 406 } 407 408 // Emitting state sensor event signal 409 emitStateSensorEventSignal(tid, sensorId, sensorOffset, eventState, 410 previousEventState); 411 412 // If there are no HOST PDR's, there is no further action 413 if (hostPDRHandler == NULL) 414 { 415 return PLDM_SUCCESS; 416 } 417 418 // Handle PLDM events for which PDR is available 419 SensorEntry sensorEntry{tid, sensorId}; 420 421 pldm::pdr::EntityInfo entityInfo{}; 422 pldm::pdr::CompositeSensorStates compositeSensorStates{}; 423 424 try 425 { 426 std::tie(entityInfo, compositeSensorStates) = 427 hostPDRHandler->lookupSensorInfo(sensorEntry); 428 } 429 catch (const std::out_of_range& e) 430 { 431 // If there is no mapping for tid, sensorId combination, try 432 // PLDM_TID_RESERVED, sensorId for terminus that is yet to 433 // implement TL PDR. 434 try 435 { 436 sensorEntry.terminusID = PLDM_TID_RESERVED; 437 std::tie(entityInfo, compositeSensorStates) = 438 hostPDRHandler->lookupSensorInfo(sensorEntry); 439 } 440 // If there is no mapping for events return PLDM_SUCCESS 441 catch (const std::out_of_range& e) 442 { 443 return PLDM_SUCCESS; 444 } 445 } 446 447 if (sensorOffset >= compositeSensorStates.size()) 448 { 449 return PLDM_ERROR_INVALID_DATA; 450 } 451 452 const auto& possibleStates = compositeSensorStates[sensorOffset]; 453 if (possibleStates.find(eventState) == possibleStates.end()) 454 { 455 return PLDM_ERROR_INVALID_DATA; 456 } 457 458 const auto& [containerId, entityType, entityInstance] = entityInfo; 459 events::StateSensorEntry stateSensorEntry{containerId, entityType, 460 entityInstance, sensorOffset}; 461 return hostPDRHandler->handleStateSensorEvent(stateSensorEntry, 462 eventState); 463 } 464 else 465 { 466 return PLDM_ERROR_INVALID_DATA; 467 } 468 469 return PLDM_SUCCESS; 470 } 471 472 int Handler::pldmPDRRepositoryChgEvent(const pldm_msg* request, 473 size_t payloadLength, 474 uint8_t /*formatVersion*/, uint8_t tid, 475 size_t eventDataOffset) 476 { 477 uint8_t eventDataFormat{}; 478 uint8_t numberOfChangeRecords{}; 479 size_t dataOffset{}; 480 481 auto eventData = 482 reinterpret_cast<const uint8_t*>(request->payload) + eventDataOffset; 483 auto eventDataSize = payloadLength - eventDataOffset; 484 485 auto rc = decode_pldm_pdr_repository_chg_event_data( 486 eventData, eventDataSize, &eventDataFormat, &numberOfChangeRecords, 487 &dataOffset); 488 if (rc != PLDM_SUCCESS) 489 { 490 return rc; 491 } 492 493 PDRRecordHandles pdrRecordHandles; 494 495 if (eventDataFormat == FORMAT_IS_PDR_TYPES) 496 { 497 return PLDM_ERROR_INVALID_DATA; 498 } 499 500 if (eventDataFormat == FORMAT_IS_PDR_HANDLES) 501 { 502 uint8_t eventDataOperation{}; 503 uint8_t numberOfChangeEntries{}; 504 505 auto changeRecordData = eventData + dataOffset; 506 auto changeRecordDataSize = eventDataSize - dataOffset; 507 508 while (changeRecordDataSize) 509 { 510 rc = decode_pldm_pdr_repository_change_record_data( 511 changeRecordData, changeRecordDataSize, &eventDataOperation, 512 &numberOfChangeEntries, &dataOffset); 513 514 if (rc != PLDM_SUCCESS) 515 { 516 return rc; 517 } 518 519 if (eventDataOperation == PLDM_RECORDS_ADDED) 520 { 521 rc = getPDRRecordHandles( 522 reinterpret_cast<const ChangeEntry*>(changeRecordData + 523 dataOffset), 524 changeRecordDataSize - dataOffset, 525 static_cast<size_t>(numberOfChangeEntries), 526 pdrRecordHandles); 527 528 if (rc != PLDM_SUCCESS) 529 { 530 return rc; 531 } 532 } 533 534 if (eventDataOperation == PLDM_RECORDS_MODIFIED) 535 { 536 return PLDM_ERROR_UNSUPPORTED_PLDM_CMD; 537 } 538 539 changeRecordData += 540 dataOffset + (numberOfChangeEntries * sizeof(ChangeEntry)); 541 changeRecordDataSize -= 542 dataOffset + (numberOfChangeEntries * sizeof(ChangeEntry)); 543 } 544 } 545 if (hostPDRHandler) 546 { 547 // if we get a Repository change event with the eventDataFormat 548 // as REFRESH_ENTIRE_REPOSITORY, then delete all the PDR's that 549 // have the matched Terminus handle 550 if (eventDataFormat == REFRESH_ENTIRE_REPOSITORY) 551 { 552 // We cannot get the Repo change event from the Terminus 553 // that is not already added to the BMC repository 554 555 for (const auto& [terminusHandle, terminusInfo] : 556 hostPDRHandler->tlPDRInfo) 557 { 558 if (std::get<0>(terminusInfo) == tid) 559 { 560 pldm_pdr_remove_pdrs_by_terminus_handle(pdrRepo.getPdr(), 561 terminusHandle); 562 } 563 } 564 } 565 hostPDRHandler->fetchPDR(std::move(pdrRecordHandles)); 566 } 567 568 return PLDM_SUCCESS; 569 } 570 571 int Handler::getPDRRecordHandles(const ChangeEntry* changeEntryData, 572 size_t changeEntryDataSize, 573 size_t numberOfChangeEntries, 574 PDRRecordHandles& pdrRecordHandles) 575 { 576 if (numberOfChangeEntries > (changeEntryDataSize / sizeof(ChangeEntry))) 577 { 578 return PLDM_ERROR_INVALID_DATA; 579 } 580 for (size_t i = 0; i < numberOfChangeEntries; i++) 581 { 582 pdrRecordHandles.push_back(changeEntryData[i]); 583 } 584 return PLDM_SUCCESS; 585 } 586 587 Response Handler::setNumericEffecterValue(const pldm_msg* request, 588 size_t payloadLength) 589 { 590 Response response(sizeof(pldm_msg_hdr) + 591 PLDM_SET_NUMERIC_EFFECTER_VALUE_RESP_BYTES); 592 uint16_t effecterId{}; 593 uint8_t effecterDataSize{}; 594 uint8_t effecterValue[4] = {}; 595 596 if ((payloadLength > sizeof(effecterId) + sizeof(effecterDataSize) + 597 sizeof(union_effecter_data_size)) || 598 (payloadLength < sizeof(effecterId) + sizeof(effecterDataSize) + 1)) 599 { 600 return ccOnlyResponse(request, PLDM_ERROR_INVALID_LENGTH); 601 } 602 603 int rc = decode_set_numeric_effecter_value_req( 604 request, payloadLength, &effecterId, &effecterDataSize, 605 reinterpret_cast<uint8_t*>(&effecterValue)); 606 607 if (rc == PLDM_SUCCESS) 608 { 609 const pldm::utils::DBusHandler dBusIntf; 610 rc = platform_numeric_effecter::setNumericEffecterValueHandler< 611 pldm::utils::DBusHandler, Handler>(dBusIntf, *this, effecterId, 612 effecterDataSize, effecterValue, 613 sizeof(effecterValue)); 614 } 615 616 return ccOnlyResponse(request, rc); 617 } 618 619 void Handler::generateTerminusLocatorPDR(Repo& repo) 620 { 621 std::vector<uint8_t> pdrBuffer(sizeof(pldm_terminus_locator_pdr)); 622 623 auto pdr = reinterpret_cast<pldm_terminus_locator_pdr*>(pdrBuffer.data()); 624 625 pdr->hdr.record_handle = 0; 626 pdr->hdr.version = 1; 627 pdr->hdr.type = PLDM_TERMINUS_LOCATOR_PDR; 628 pdr->hdr.record_change_num = 0; 629 pdr->hdr.length = sizeof(pldm_terminus_locator_pdr) - sizeof(pldm_pdr_hdr); 630 pdr->terminus_handle = TERMINUS_HANDLE; 631 pdr->validity = PLDM_TL_PDR_VALID; 632 pdr->tid = TERMINUS_ID; 633 pdr->container_id = 0x0; 634 pdr->terminus_locator_type = PLDM_TERMINUS_LOCATOR_TYPE_MCTP_EID; 635 pdr->terminus_locator_value_size = 636 sizeof(pldm_terminus_locator_type_mctp_eid); 637 auto locatorValue = reinterpret_cast<pldm_terminus_locator_type_mctp_eid*>( 638 pdr->terminus_locator_value); 639 locatorValue->eid = BmcMctpEid; 640 641 PdrEntry pdrEntry{}; 642 pdrEntry.data = pdrBuffer.data(); 643 pdrEntry.size = pdrBuffer.size(); 644 repo.addRecord(pdrEntry); 645 if (hostPDRHandler) 646 { 647 hostPDRHandler->tlPDRInfo.insert_or_assign( 648 pdr->terminus_handle, 649 std::make_tuple(pdr->tid, locatorValue->eid, pdr->validity)); 650 } 651 } 652 653 Response Handler::getStateSensorReadings(const pldm_msg* request, 654 size_t payloadLength) 655 { 656 uint16_t sensorId{}; 657 bitfield8_t sensorRearm{}; 658 uint8_t reserved{}; 659 660 if (payloadLength != PLDM_GET_SENSOR_READING_REQ_BYTES) 661 { 662 return ccOnlyResponse(request, PLDM_ERROR_INVALID_LENGTH); 663 } 664 665 int rc = decode_get_state_sensor_readings_req( 666 request, payloadLength, &sensorId, &sensorRearm, &reserved); 667 668 if (rc != PLDM_SUCCESS) 669 { 670 return ccOnlyResponse(request, rc); 671 } 672 673 // 0x01 to 0x08 674 uint8_t sensorRearmCount = std::popcount(sensorRearm.byte); 675 std::vector<get_sensor_state_field> stateField(sensorRearmCount); 676 uint8_t comSensorCnt{}; 677 const pldm::utils::DBusHandler dBusIntf; 678 679 uint16_t entityType{}; 680 uint16_t entityInstance{}; 681 uint16_t stateSetId{}; 682 683 if (isOemStateSensor(*this, sensorId, sensorRearmCount, comSensorCnt, 684 entityType, entityInstance, stateSetId) && 685 oemPlatformHandler != nullptr && !sensorDbusObjMaps.contains(sensorId)) 686 { 687 rc = oemPlatformHandler->getOemStateSensorReadingsHandler( 688 entityType, entityInstance, stateSetId, comSensorCnt, stateField); 689 } 690 else 691 { 692 rc = platform_state_sensor::getStateSensorReadingsHandler< 693 pldm::utils::DBusHandler, Handler>(dBusIntf, *this, sensorId, 694 sensorRearmCount, comSensorCnt, 695 stateField); 696 } 697 698 if (rc != PLDM_SUCCESS) 699 { 700 return ccOnlyResponse(request, rc); 701 } 702 703 Response response(sizeof(pldm_msg_hdr) + 704 PLDM_GET_STATE_SENSOR_READINGS_MIN_RESP_BYTES + 705 sizeof(get_sensor_state_field) * comSensorCnt); 706 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data()); 707 rc = encode_get_state_sensor_readings_resp(request->hdr.instance_id, rc, 708 comSensorCnt, stateField.data(), 709 responsePtr); 710 if (rc != PLDM_SUCCESS) 711 { 712 return ccOnlyResponse(request, rc); 713 } 714 715 return response; 716 } 717 718 void Handler::_processPostGetPDRActions(sdeventplus::source::EventBase& 719 /*source */) 720 { 721 deferredGetPDREvent.reset(); 722 dbusToPLDMEventHandler->listenSensorEvent(pdrRepo, sensorDbusObjMaps); 723 } 724 725 bool isOemStateSensor(Handler& handler, uint16_t sensorId, 726 uint8_t sensorRearmCount, uint8_t& compSensorCnt, 727 uint16_t& entityType, uint16_t& entityInstance, 728 uint16_t& stateSetId) 729 { 730 pldm_state_sensor_pdr* pdr = nullptr; 731 732 std::unique_ptr<pldm_pdr, decltype(&pldm_pdr_destroy)> stateSensorPdrRepo( 733 pldm_pdr_init(), pldm_pdr_destroy); 734 Repo stateSensorPDRs(stateSensorPdrRepo.get()); 735 getRepoByType(handler.getRepo(), stateSensorPDRs, PLDM_STATE_SENSOR_PDR); 736 if (stateSensorPDRs.empty()) 737 { 738 std::cerr << "Failed to get record by PDR type\n"; 739 return false; 740 } 741 742 PdrEntry pdrEntry{}; 743 auto pdrRecord = stateSensorPDRs.getFirstRecord(pdrEntry); 744 while (pdrRecord) 745 { 746 pdr = reinterpret_cast<pldm_state_sensor_pdr*>(pdrEntry.data); 747 assert(pdr != NULL); 748 if (pdr->sensor_id != sensorId) 749 { 750 pdr = nullptr; 751 pdrRecord = stateSensorPDRs.getNextRecord(pdrRecord, pdrEntry); 752 continue; 753 } 754 auto tmpEntityType = pdr->entity_type; 755 auto tmpEntityInstance = pdr->entity_instance; 756 auto tmpCompSensorCnt = pdr->composite_sensor_count; 757 auto tmpPossibleStates = 758 reinterpret_cast<state_sensor_possible_states*>( 759 pdr->possible_states); 760 auto tmpStateSetId = tmpPossibleStates->state_set_id; 761 762 if (sensorRearmCount > tmpCompSensorCnt) 763 { 764 std::cerr << "The requester sent wrong sensorRearm" 765 << " count for the sensor, SENSOR_ID=" << sensorId 766 << "SENSOR_REARM_COUNT=" << (uint16_t)sensorRearmCount 767 << "\n"; 768 break; 769 } 770 771 if ((tmpEntityType >= PLDM_OEM_ENTITY_TYPE_START && 772 tmpEntityType <= PLDM_OEM_ENTITY_TYPE_END) || 773 (tmpStateSetId >= PLDM_OEM_STATE_SET_ID_START && 774 tmpStateSetId < PLDM_OEM_STATE_SET_ID_END)) 775 { 776 entityType = tmpEntityType; 777 entityInstance = tmpEntityInstance; 778 stateSetId = tmpStateSetId; 779 compSensorCnt = tmpCompSensorCnt; 780 return true; 781 } 782 else 783 { 784 return false; 785 } 786 } 787 return false; 788 } 789 790 bool isOemStateEffecter(Handler& handler, uint16_t effecterId, 791 uint8_t compEffecterCnt, uint16_t& entityType, 792 uint16_t& entityInstance, uint16_t& stateSetId) 793 { 794 pldm_state_effecter_pdr* pdr = nullptr; 795 796 std::unique_ptr<pldm_pdr, decltype(&pldm_pdr_destroy)> stateEffecterPdrRepo( 797 pldm_pdr_init(), pldm_pdr_destroy); 798 Repo stateEffecterPDRs(stateEffecterPdrRepo.get()); 799 getRepoByType(handler.getRepo(), stateEffecterPDRs, 800 PLDM_STATE_EFFECTER_PDR); 801 if (stateEffecterPDRs.empty()) 802 { 803 std::cerr << "Failed to get record by PDR type\n"; 804 return false; 805 } 806 807 PdrEntry pdrEntry{}; 808 auto pdrRecord = stateEffecterPDRs.getFirstRecord(pdrEntry); 809 while (pdrRecord) 810 { 811 pdr = reinterpret_cast<pldm_state_effecter_pdr*>(pdrEntry.data); 812 assert(pdr != NULL); 813 if (pdr->effecter_id != effecterId) 814 { 815 pdr = nullptr; 816 pdrRecord = stateEffecterPDRs.getNextRecord(pdrRecord, pdrEntry); 817 continue; 818 } 819 820 auto tmpEntityType = pdr->entity_type; 821 auto tmpEntityInstance = pdr->entity_instance; 822 auto tmpPossibleStates = 823 reinterpret_cast<state_effecter_possible_states*>( 824 pdr->possible_states); 825 auto tmpStateSetId = tmpPossibleStates->state_set_id; 826 827 if (compEffecterCnt > pdr->composite_effecter_count) 828 { 829 std::cerr << "The requester sent wrong composite effecter" 830 << " count for the effecter, EFFECTER_ID=" << effecterId 831 << "COMP_EFF_CNT=" << (uint16_t)compEffecterCnt << "\n"; 832 return false; 833 } 834 835 if ((tmpEntityType >= PLDM_OEM_ENTITY_TYPE_START && 836 tmpEntityType <= PLDM_OEM_ENTITY_TYPE_END) || 837 (tmpStateSetId >= PLDM_OEM_STATE_SET_ID_START && 838 tmpStateSetId < PLDM_OEM_STATE_SET_ID_END)) 839 { 840 entityType = tmpEntityType; 841 entityInstance = tmpEntityInstance; 842 stateSetId = tmpStateSetId; 843 return true; 844 } 845 else 846 { 847 return false; 848 } 849 } 850 return false; 851 } 852 853 } // namespace platform 854 } // namespace responder 855 } // namespace pldm 856