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