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