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