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