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*/, 475 uint8_t /*tid*/, 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 hostPDRHandler->fetchPDR(std::move(pdrRecordHandles)); 548 } 549 550 return PLDM_SUCCESS; 551 } 552 553 int Handler::getPDRRecordHandles(const ChangeEntry* changeEntryData, 554 size_t changeEntryDataSize, 555 size_t numberOfChangeEntries, 556 PDRRecordHandles& pdrRecordHandles) 557 { 558 if (numberOfChangeEntries > (changeEntryDataSize / sizeof(ChangeEntry))) 559 { 560 return PLDM_ERROR_INVALID_DATA; 561 } 562 for (size_t i = 0; i < numberOfChangeEntries; i++) 563 { 564 pdrRecordHandles.push_back(changeEntryData[i]); 565 } 566 return PLDM_SUCCESS; 567 } 568 569 Response Handler::setNumericEffecterValue(const pldm_msg* request, 570 size_t payloadLength) 571 { 572 Response response(sizeof(pldm_msg_hdr) + 573 PLDM_SET_NUMERIC_EFFECTER_VALUE_RESP_BYTES); 574 uint16_t effecterId{}; 575 uint8_t effecterDataSize{}; 576 uint8_t effecterValue[4] = {}; 577 578 if ((payloadLength > sizeof(effecterId) + sizeof(effecterDataSize) + 579 sizeof(union_effecter_data_size)) || 580 (payloadLength < sizeof(effecterId) + sizeof(effecterDataSize) + 1)) 581 { 582 return ccOnlyResponse(request, PLDM_ERROR_INVALID_LENGTH); 583 } 584 585 int rc = decode_set_numeric_effecter_value_req( 586 request, payloadLength, &effecterId, &effecterDataSize, 587 reinterpret_cast<uint8_t*>(&effecterValue)); 588 589 if (rc == PLDM_SUCCESS) 590 { 591 const pldm::utils::DBusHandler dBusIntf; 592 rc = platform_numeric_effecter::setNumericEffecterValueHandler< 593 pldm::utils::DBusHandler, Handler>(dBusIntf, *this, effecterId, 594 effecterDataSize, effecterValue, 595 sizeof(effecterValue)); 596 } 597 598 return ccOnlyResponse(request, rc); 599 } 600 601 void Handler::generateTerminusLocatorPDR(Repo& repo) 602 { 603 std::vector<uint8_t> pdrBuffer(sizeof(pldm_terminus_locator_pdr)); 604 605 auto pdr = reinterpret_cast<pldm_terminus_locator_pdr*>(pdrBuffer.data()); 606 607 pdr->hdr.record_handle = 0; 608 pdr->hdr.version = 1; 609 pdr->hdr.type = PLDM_TERMINUS_LOCATOR_PDR; 610 pdr->hdr.record_change_num = 0; 611 pdr->hdr.length = sizeof(pldm_terminus_locator_pdr) - sizeof(pldm_pdr_hdr); 612 pdr->terminus_handle = TERMINUS_HANDLE; 613 pdr->validity = PLDM_TL_PDR_VALID; 614 pdr->tid = TERMINUS_ID; 615 pdr->container_id = 0x0; 616 pdr->terminus_locator_type = PLDM_TERMINUS_LOCATOR_TYPE_MCTP_EID; 617 pdr->terminus_locator_value_size = 618 sizeof(pldm_terminus_locator_type_mctp_eid); 619 auto locatorValue = reinterpret_cast<pldm_terminus_locator_type_mctp_eid*>( 620 pdr->terminus_locator_value); 621 locatorValue->eid = BmcMctpEid; 622 623 PdrEntry pdrEntry{}; 624 pdrEntry.data = pdrBuffer.data(); 625 pdrEntry.size = pdrBuffer.size(); 626 repo.addRecord(pdrEntry); 627 if (hostPDRHandler) 628 { 629 hostPDRHandler->tlPDRInfo.insert_or_assign( 630 pdr->terminus_handle, 631 std::make_tuple(pdr->tid, locatorValue->eid, pdr->validity)); 632 } 633 } 634 635 Response Handler::getStateSensorReadings(const pldm_msg* request, 636 size_t payloadLength) 637 { 638 uint16_t sensorId{}; 639 bitfield8_t sensorRearm{}; 640 uint8_t reserved{}; 641 642 if (payloadLength != PLDM_GET_SENSOR_READING_REQ_BYTES) 643 { 644 return ccOnlyResponse(request, PLDM_ERROR_INVALID_LENGTH); 645 } 646 647 int rc = decode_get_state_sensor_readings_req( 648 request, payloadLength, &sensorId, &sensorRearm, &reserved); 649 650 if (rc != PLDM_SUCCESS) 651 { 652 return ccOnlyResponse(request, rc); 653 } 654 655 // 0x01 to 0x08 656 uint8_t sensorRearmCount = std::popcount(sensorRearm.byte); 657 std::vector<get_sensor_state_field> stateField(sensorRearmCount); 658 uint8_t comSensorCnt{}; 659 const pldm::utils::DBusHandler dBusIntf; 660 661 uint16_t entityType{}; 662 uint16_t entityInstance{}; 663 uint16_t stateSetId{}; 664 665 if (isOemStateSensor(*this, sensorId, sensorRearmCount, comSensorCnt, 666 entityType, entityInstance, stateSetId) && 667 oemPlatformHandler != nullptr && !sensorDbusObjMaps.contains(sensorId)) 668 { 669 rc = oemPlatformHandler->getOemStateSensorReadingsHandler( 670 entityType, entityInstance, stateSetId, comSensorCnt, stateField); 671 } 672 else 673 { 674 rc = platform_state_sensor::getStateSensorReadingsHandler< 675 pldm::utils::DBusHandler, Handler>(dBusIntf, *this, sensorId, 676 sensorRearmCount, comSensorCnt, 677 stateField); 678 } 679 680 if (rc != PLDM_SUCCESS) 681 { 682 return ccOnlyResponse(request, rc); 683 } 684 685 Response response(sizeof(pldm_msg_hdr) + 686 PLDM_GET_STATE_SENSOR_READINGS_MIN_RESP_BYTES + 687 sizeof(get_sensor_state_field) * comSensorCnt); 688 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data()); 689 rc = encode_get_state_sensor_readings_resp(request->hdr.instance_id, rc, 690 comSensorCnt, stateField.data(), 691 responsePtr); 692 if (rc != PLDM_SUCCESS) 693 { 694 return ccOnlyResponse(request, rc); 695 } 696 697 return response; 698 } 699 700 void Handler::_processPostGetPDRActions(sdeventplus::source::EventBase& 701 /*source */) 702 { 703 deferredGetPDREvent.reset(); 704 dbusToPLDMEventHandler->listenSensorEvent(pdrRepo, sensorDbusObjMaps); 705 } 706 707 bool isOemStateSensor(Handler& handler, uint16_t sensorId, 708 uint8_t sensorRearmCount, uint8_t& compSensorCnt, 709 uint16_t& entityType, uint16_t& entityInstance, 710 uint16_t& stateSetId) 711 { 712 pldm_state_sensor_pdr* pdr = nullptr; 713 714 std::unique_ptr<pldm_pdr, decltype(&pldm_pdr_destroy)> stateSensorPdrRepo( 715 pldm_pdr_init(), pldm_pdr_destroy); 716 Repo stateSensorPDRs(stateSensorPdrRepo.get()); 717 getRepoByType(handler.getRepo(), stateSensorPDRs, PLDM_STATE_SENSOR_PDR); 718 if (stateSensorPDRs.empty()) 719 { 720 std::cerr << "Failed to get record by PDR type\n"; 721 return false; 722 } 723 724 PdrEntry pdrEntry{}; 725 auto pdrRecord = stateSensorPDRs.getFirstRecord(pdrEntry); 726 while (pdrRecord) 727 { 728 pdr = reinterpret_cast<pldm_state_sensor_pdr*>(pdrEntry.data); 729 assert(pdr != NULL); 730 if (pdr->sensor_id != sensorId) 731 { 732 pdr = nullptr; 733 pdrRecord = stateSensorPDRs.getNextRecord(pdrRecord, pdrEntry); 734 continue; 735 } 736 auto tmpEntityType = pdr->entity_type; 737 auto tmpEntityInstance = pdr->entity_instance; 738 auto tmpCompSensorCnt = pdr->composite_sensor_count; 739 auto tmpPossibleStates = 740 reinterpret_cast<state_sensor_possible_states*>( 741 pdr->possible_states); 742 auto tmpStateSetId = tmpPossibleStates->state_set_id; 743 744 if (sensorRearmCount > tmpCompSensorCnt) 745 { 746 std::cerr << "The requester sent wrong sensorRearm" 747 << " count for the sensor, SENSOR_ID=" << sensorId 748 << "SENSOR_REARM_COUNT=" << (uint16_t)sensorRearmCount 749 << "\n"; 750 break; 751 } 752 753 if ((tmpEntityType >= PLDM_OEM_ENTITY_TYPE_START && 754 tmpEntityType <= PLDM_OEM_ENTITY_TYPE_END) || 755 (tmpStateSetId >= PLDM_OEM_STATE_SET_ID_START && 756 tmpStateSetId < PLDM_OEM_STATE_SET_ID_END)) 757 { 758 entityType = tmpEntityType; 759 entityInstance = tmpEntityInstance; 760 stateSetId = tmpStateSetId; 761 compSensorCnt = tmpCompSensorCnt; 762 return true; 763 } 764 else 765 { 766 return false; 767 } 768 } 769 return false; 770 } 771 772 bool isOemStateEffecter(Handler& handler, uint16_t effecterId, 773 uint8_t compEffecterCnt, uint16_t& entityType, 774 uint16_t& entityInstance, uint16_t& stateSetId) 775 { 776 pldm_state_effecter_pdr* pdr = nullptr; 777 778 std::unique_ptr<pldm_pdr, decltype(&pldm_pdr_destroy)> stateEffecterPdrRepo( 779 pldm_pdr_init(), pldm_pdr_destroy); 780 Repo stateEffecterPDRs(stateEffecterPdrRepo.get()); 781 getRepoByType(handler.getRepo(), stateEffecterPDRs, 782 PLDM_STATE_EFFECTER_PDR); 783 if (stateEffecterPDRs.empty()) 784 { 785 std::cerr << "Failed to get record by PDR type\n"; 786 return false; 787 } 788 789 PdrEntry pdrEntry{}; 790 auto pdrRecord = stateEffecterPDRs.getFirstRecord(pdrEntry); 791 while (pdrRecord) 792 { 793 pdr = reinterpret_cast<pldm_state_effecter_pdr*>(pdrEntry.data); 794 assert(pdr != NULL); 795 if (pdr->effecter_id != effecterId) 796 { 797 pdr = nullptr; 798 pdrRecord = stateEffecterPDRs.getNextRecord(pdrRecord, pdrEntry); 799 continue; 800 } 801 802 auto tmpEntityType = pdr->entity_type; 803 auto tmpEntityInstance = pdr->entity_instance; 804 auto tmpPossibleStates = 805 reinterpret_cast<state_effecter_possible_states*>( 806 pdr->possible_states); 807 auto tmpStateSetId = tmpPossibleStates->state_set_id; 808 809 if (compEffecterCnt > pdr->composite_effecter_count) 810 { 811 std::cerr << "The requester sent wrong composite effecter" 812 << " count for the effecter, EFFECTER_ID=" << effecterId 813 << "COMP_EFF_CNT=" << (uint16_t)compEffecterCnt << "\n"; 814 return false; 815 } 816 817 if ((tmpEntityType >= PLDM_OEM_ENTITY_TYPE_START && 818 tmpEntityType <= PLDM_OEM_ENTITY_TYPE_END) || 819 (tmpStateSetId >= PLDM_OEM_STATE_SET_ID_START && 820 tmpStateSetId < PLDM_OEM_STATE_SET_ID_END)) 821 { 822 entityType = tmpEntityType; 823 entityInstance = tmpEntityInstance; 824 stateSetId = tmpStateSetId; 825 return true; 826 } 827 else 828 { 829 return false; 830 } 831 } 832 return false; 833 } 834 835 } // namespace platform 836 } // namespace responder 837 } // namespace pldm 838