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