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