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