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