1 #pragma once 2 3 #include "config.h" 4 5 #include "libpldm/platform.h" 6 #include "libpldm/states.h" 7 8 #include "common/utils.hpp" 9 #include "libpldmresponder/pdr.hpp" 10 #include "pdr_utils.hpp" 11 #include "pldmd/handler.hpp" 12 13 #include <cstdint> 14 #include <map> 15 16 namespace pldm 17 { 18 namespace responder 19 { 20 namespace platform_state_effecter 21 { 22 /** @brief Function to set the effecter requested by pldm requester 23 * 24 * @tparam[in] DBusInterface - DBus interface type 25 * @tparam[in] Handler - pldm::responder::platform::Handler 26 * @param[in] dBusIntf - The interface object of DBusInterface 27 * @param[in] handler - The interface object of 28 * pldm::responder::platform::Handler 29 * @param[in] effecterId - Effecter ID sent by the requester to act on 30 * @param[in] stateField - The state field data for each of the states, 31 * equal to composite effecter count in number 32 * @return - Success or failure in setting the states. Returns failure in 33 * terms of PLDM completion codes if atleast one state fails to be set 34 */ 35 template <class DBusInterface, class Handler> 36 int setStateEffecterStatesHandler( 37 const DBusInterface& dBusIntf, Handler& handler, uint16_t effecterId, 38 const std::vector<set_effecter_state_field>& stateField) 39 { 40 using namespace pldm::responder::pdr; 41 using namespace pldm::utils; 42 using StateSetNum = uint8_t; 43 44 state_effecter_possible_states* states = nullptr; 45 pldm_state_effecter_pdr* pdr = nullptr; 46 uint8_t compEffecterCnt = stateField.size(); 47 48 std::unique_ptr<pldm_pdr, decltype(&pldm_pdr_destroy)> stateEffecterPdrRepo( 49 pldm_pdr_init(), pldm_pdr_destroy); 50 pldm::responder::pdr_utils::Repo stateEffecterPDRs( 51 stateEffecterPdrRepo.get()); 52 getRepoByType(handler.getRepo(), stateEffecterPDRs, 53 PLDM_STATE_EFFECTER_PDR); 54 if (stateEffecterPDRs.empty()) 55 { 56 std::cerr << "Failed to get record by PDR type\n"; 57 return PLDM_PLATFORM_INVALID_EFFECTER_ID; 58 } 59 60 pldm::responder::pdr_utils::PdrEntry pdrEntry{}; 61 auto pdrRecord = stateEffecterPDRs.getFirstRecord(pdrEntry); 62 while (pdrRecord) 63 { 64 pdr = reinterpret_cast<pldm_state_effecter_pdr*>(pdrEntry.data); 65 if (pdr->effecter_id != effecterId) 66 { 67 pdr = nullptr; 68 pdrRecord = stateEffecterPDRs.getNextRecord(pdrRecord, pdrEntry); 69 continue; 70 } 71 72 states = reinterpret_cast<state_effecter_possible_states*>( 73 pdr->possible_states); 74 if (compEffecterCnt > pdr->composite_effecter_count) 75 { 76 std::cerr << "The requester sent wrong composite effecter" 77 << " count for the effecter, EFFECTER_ID=" << effecterId 78 << "COMP_EFF_CNT=" << compEffecterCnt << "\n"; 79 return PLDM_ERROR_INVALID_DATA; 80 } 81 break; 82 } 83 84 if (!pdr) 85 { 86 return PLDM_PLATFORM_INVALID_EFFECTER_ID; 87 } 88 89 int rc = PLDM_SUCCESS; 90 try 91 { 92 const auto& [dbusMappings, dbusValMaps] = 93 handler.getDbusObjMaps(effecterId); 94 for (uint8_t currState = 0; currState < compEffecterCnt; ++currState) 95 { 96 std::vector<StateSetNum> allowed{}; 97 // computation is based on table 79 from DSP0248 v1.1.1 98 uint8_t bitfieldIndex = stateField[currState].effecter_state / 8; 99 uint8_t bit = 100 stateField[currState].effecter_state - (8 * bitfieldIndex); 101 if (states->possible_states_size < bitfieldIndex || 102 !(states->states[bitfieldIndex].byte & (1 << bit))) 103 { 104 std::cerr << "Invalid state set value, EFFECTER_ID=" 105 << effecterId 106 << " VALUE=" << stateField[currState].effecter_state 107 << " COMPOSITE_EFFECTER_ID=" << currState 108 << " DBUS_PATH=" << dbusMappings[currState].objectPath 109 << "\n"; 110 rc = PLDM_PLATFORM_SET_EFFECTER_UNSUPPORTED_SENSORSTATE; 111 break; 112 } 113 const DBusMapping& dbusMapping = dbusMappings[currState]; 114 const pldm::responder::pdr_utils::StatestoDbusVal& dbusValToMap = 115 dbusValMaps[currState]; 116 117 if (stateField[currState].set_request == PLDM_REQUEST_SET) 118 { 119 try 120 { 121 dBusIntf.setDbusProperty( 122 dbusMapping, 123 dbusValToMap.at(stateField[currState].effecter_state)); 124 } 125 catch (const std::exception& e) 126 { 127 std::cerr 128 << "Error setting property, ERROR=" << e.what() 129 << " PROPERTY=" << dbusMapping.propertyName 130 << " INTERFACE=" << dbusMapping.interface << " PATH=" 131 << dbusMapping.objectPath << "\n"; 132 return PLDM_ERROR; 133 } 134 } 135 uint8_t* nextState = 136 reinterpret_cast<uint8_t*>(states) + 137 sizeof(state_effecter_possible_states) - 138 sizeof(states->states) + 139 (states->possible_states_size * sizeof(states->states)); 140 states = 141 reinterpret_cast<state_effecter_possible_states*>(nextState); 142 } 143 } 144 catch (const std::out_of_range& e) 145 { 146 std::cerr << "Unknown effecter ID : " << effecterId << e.what() << '\n'; 147 return PLDM_ERROR; 148 } 149 150 return rc; 151 } 152 153 } // namespace platform_state_effecter 154 } // namespace responder 155 } // namespace pldm 156