blob: be489507ccfecb0b302cb4528c84adda41f25a32 [file] [log] [blame]
Deepak Kodihalli557dfb02019-05-12 13:11:17 +05301#pragma once
2
Sampa Misraa2fa0702019-05-31 01:28:55 -05003#include "config.h"
4
Deepak Kodihallibc669f12019-11-28 08:52:07 -06005#include "handler.hpp"
Sampa Misraa2fa0702019-05-31 01:28:55 -05006#include "libpldmresponder/pdr.hpp"
7#include "libpldmresponder/utils.hpp"
8
Deepak Kodihalli557dfb02019-05-12 13:11:17 +05309#include <stdint.h>
10
Sampa Misraa2fa0702019-05-31 01:28:55 -050011#include <map>
Deepak Kodihalli557dfb02019-05-12 13:11:17 +053012
13#include "libpldm/platform.h"
Sampa Misraa2fa0702019-05-31 01:28:55 -050014#include "libpldm/states.h"
Deepak Kodihalli557dfb02019-05-12 13:11:17 +053015
16namespace pldm
17{
Deepak Kodihalli557dfb02019-05-12 13:11:17 +053018namespace responder
19{
Sampa Misraa2fa0702019-05-31 01:28:55 -050020namespace platform
21{
22
Deepak Kodihallibc669f12019-11-28 08:52:07 -060023class Handler : public CmdHandler
Sampa Misraa2fa0702019-05-31 01:28:55 -050024{
Deepak Kodihallibc669f12019-11-28 08:52:07 -060025 public:
26 Handler()
Sampa Misraa2fa0702019-05-31 01:28:55 -050027 {
Deepak Kodihallibc669f12019-11-28 08:52:07 -060028 handlers.emplace(PLDM_GET_PDR,
29 [this](const pldm_msg* request, size_t payloadLength) {
30 return this->getPDR(request, payloadLength);
31 });
32 handlers.emplace(PLDM_SET_STATE_EFFECTER_STATES,
33 [this](const pldm_msg* request, size_t payloadLength) {
34 return this->setStateEffecterStates(request,
35 payloadLength);
36 });
Sampa Misraa2fa0702019-05-31 01:28:55 -050037 }
38
Deepak Kodihallibc669f12019-11-28 08:52:07 -060039 /** @brief Handler for GetPDR
40 *
41 * @param[in] request - Request message payload
42 * @param[in] payloadLength - Request payload length
43 * @param[out] Response - Response message written here
44 */
45 Response getPDR(const pldm_msg* request, size_t payloadLength);
Sampa Misraa2fa0702019-05-31 01:28:55 -050046
Deepak Kodihallibc669f12019-11-28 08:52:07 -060047 /** @brief Handler for setStateEffecterStates
48 *
49 * @param[in] request - Request message
50 * @param[in] payloadLength - Request payload length
51 * @return Response - PLDM Response message
52 */
53 Response setStateEffecterStates(const pldm_msg* request,
54 size_t payloadLength);
55
56 /** @brief Function to set the effecter requested by pldm requester
57 * @param[in] dBusIntf - The interface object
58 * @param[in] effecterId - Effecter ID sent by the requester to act on
59 * @param[in] stateField - The state field data for each of the states,
60 * equal to composite effecter count in number
61 * @return - Success or failure in setting the states. Returns failure in
62 * terms of PLDM completion codes if atleast one state fails to be set
63 */
64 template <class DBusInterface>
65 int setStateEffecterStatesHandler(
66 const DBusInterface& dBusIntf, effecter::Id effecterId,
67 const std::vector<set_effecter_state_field>& stateField)
Sampa Misraa2fa0702019-05-31 01:28:55 -050068 {
Deepak Kodihallibc669f12019-11-28 08:52:07 -060069 using namespace std::string_literals;
70 using DBusProperty = std::variant<std::string, bool>;
71 using StateSetId = uint16_t;
72 using StateSetNum = uint8_t;
73 using PropertyMap =
74 std::map<StateSetId, std::map<StateSetNum, DBusProperty>>;
75 static const PropertyMap stateNumToDbusProp = {
76 {PLDM_BOOT_PROGRESS_STATE,
77 {{PLDM_BOOT_NOT_ACTIVE,
78 "xyz.openbmc_project.State.OperatingSystem.Status.OSStatus."
79 "Standby"s},
80 {PLDM_BOOT_COMPLETED,
81 "xyz.openbmc_project.State.OperatingSystem.Status.OSStatus."
82 "BootComplete"s}}},
83 {PLDM_SYSTEM_POWER_STATE,
84 {{PLDM_OFF_SOFT_GRACEFUL,
85 "xyz.openbmc_project.State.Chassis.Transition.Off"s}}}};
86 using namespace phosphor::logging;
87 using namespace pldm::responder::pdr;
88 using namespace pldm::responder::effecter::dbus_mapping;
89
90 state_effecter_possible_states* states = nullptr;
91 pldm_state_effecter_pdr* pdr = nullptr;
92 uint8_t compEffecterCnt = stateField.size();
93 uint32_t recordHndl{};
94 Repo& pdrRepo = get(PDR_JSONS_DIR);
95 pdr::Entry pdrEntry{};
96
97 while (!pdr)
Sampa Misraa2fa0702019-05-31 01:28:55 -050098 {
Deepak Kodihallibc669f12019-11-28 08:52:07 -060099 pdrEntry = pdrRepo.at(recordHndl);
100 pldm_pdr_hdr* header =
101 reinterpret_cast<pldm_pdr_hdr*>(pdrEntry.data());
102 if (header->type != PLDM_STATE_EFFECTER_PDR)
Sampa Misraa2fa0702019-05-31 01:28:55 -0500103 {
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600104 recordHndl = pdrRepo.getNextRecordHandle(recordHndl);
105 if (recordHndl)
106 {
107 continue;
108 }
109 return PLDM_PLATFORM_INVALID_EFFECTER_ID;
110 }
111 pdr = reinterpret_cast<pldm_state_effecter_pdr*>(pdrEntry.data());
112 recordHndl = pdr->hdr.record_handle;
113 if (pdr->effecter_id == effecterId)
114 {
115 states = reinterpret_cast<state_effecter_possible_states*>(
116 pdr->possible_states);
117 if (compEffecterCnt > pdr->composite_effecter_count)
118 {
119 log<level::ERR>(
120 "The requester sent wrong composite effecter "
121 "count for the effecter",
122 entry("EFFECTER_ID=%d", effecterId),
123 entry("COMP_EFF_CNT=%d", compEffecterCnt));
124 return PLDM_ERROR_INVALID_DATA;
125 }
Sampa Misraa2fa0702019-05-31 01:28:55 -0500126 break;
127 }
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600128 recordHndl = pdrRepo.getNextRecordHandle(recordHndl);
129 if (!recordHndl)
130 {
131 return PLDM_PLATFORM_INVALID_EFFECTER_ID;
132 }
133 pdr = nullptr;
Sampa Misraa2fa0702019-05-31 01:28:55 -0500134 }
Sampa Misraa2fa0702019-05-31 01:28:55 -0500135
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600136 std::map<StateSetId, std::function<int(const std::string& objPath,
137 const uint8_t currState)>>
138 effecterToDbusEntries = {
139 {PLDM_BOOT_PROGRESS_STATE,
140 [&](const std::string& objPath, const uint8_t currState) {
141 auto stateSet =
142 stateNumToDbusProp.find(PLDM_BOOT_PROGRESS_STATE);
143 if (stateSet == stateNumToDbusProp.end())
144 {
145 log<level::ERR>("Couldn't find D-Bus mapping for "
146 "PLDM_BOOT_PROGRESS_STATE",
147 entry("EFFECTER_ID=%d", effecterId));
148 return PLDM_ERROR;
149 }
150 auto iter = stateSet->second.find(
151 stateField[currState].effecter_state);
152 if (iter == stateSet->second.end())
153 {
154 log<level::ERR>(
155 "Invalid state field passed or field not "
156 "found for PLDM_BOOT_PROGRESS_STATE",
157 entry("EFFECTER_ID=%d", effecterId),
158 entry("FIELD=%d",
159 stateField[currState].effecter_state),
160 entry("OBJECT_PATH=%s", objPath.c_str()));
161 return PLDM_ERROR_INVALID_DATA;
162 }
163 auto dbusProp = "OperatingSystemState";
164 std::variant<std::string> value{
165 std::get<std::string>(iter->second)};
166 auto dbusInterface =
167 "xyz.openbmc_project.State.OperatingSystem.Status";
168 try
169 {
170 dBusIntf.setDbusProperty(objPath.c_str(), dbusProp,
171 dbusInterface, value);
172 }
173 catch (const std::exception& e)
174 {
175 log<level::ERR>("Error setting property",
176 entry("ERROR=%s", e.what()),
177 entry("PROPERTY=%s", dbusProp),
178 entry("INTERFACE=%s", dbusInterface),
179 entry("PATH=%s", objPath.c_str()));
180 return PLDM_ERROR;
181 }
182 return PLDM_SUCCESS;
183 }},
184 {PLDM_SYSTEM_POWER_STATE,
185 [&](const std::string& objPath, const uint8_t currState) {
186 auto stateSet =
187 stateNumToDbusProp.find(PLDM_SYSTEM_POWER_STATE);
188 if (stateSet == stateNumToDbusProp.end())
189 {
190 log<level::ERR>("Couldn't find D-Bus mapping for "
191 "PLDM_SYSTEM_POWER_STATE",
192 entry("EFFECTER_ID=%d", effecterId));
193 return PLDM_ERROR;
194 }
195 auto iter = stateSet->second.find(
196 stateField[currState].effecter_state);
197 if (iter == stateSet->second.end())
198 {
199 log<level::ERR>(
200 "Invalid state field passed or field not "
201 "found for PLDM_SYSTEM_POWER_STATE",
202 entry("EFFECTER_ID=%d", effecterId),
203 entry("FIELD=%d",
204 stateField[currState].effecter_state),
205 entry("OBJECT_PATH=%s", objPath.c_str()));
206 return PLDM_ERROR_INVALID_DATA;
207 }
208 auto dbusProp = "RequestedPowerTransition";
209 std::variant<std::string> value{
210 std::get<std::string>(iter->second)};
211 auto dbusInterface = "xyz.openbmc_project.State.Chassis";
212 try
213 {
214 dBusIntf.setDbusProperty(objPath.c_str(), dbusProp,
215 dbusInterface, value);
216 }
217 catch (const std::exception& e)
218 {
219 log<level::ERR>("Error setting property",
220 entry("ERROR=%s", e.what()),
221 entry("PROPERTY=%s", dbusProp),
222 entry("INTERFACE=%s", dbusInterface),
223 entry("PATH=%s", objPath.c_str()));
224 return PLDM_ERROR;
225 }
226 return PLDM_SUCCESS;
227 }}};
228
229 int rc = PLDM_SUCCESS;
230 auto paths = get(effecterId);
231 for (uint8_t currState = 0; currState < compEffecterCnt; ++currState)
232 {
233 std::vector<StateSetNum> allowed{};
234 // computation is based on table 79 from DSP0248 v1.1.1
235 uint8_t bitfieldIndex = stateField[currState].effecter_state / 8;
236 uint8_t bit =
237 stateField[currState].effecter_state - (8 * bitfieldIndex);
238 if (states->possible_states_size < bitfieldIndex ||
239 !(states->states[bitfieldIndex].byte & (1 << bit)))
240 {
241 log<level::ERR>(
242 "Invalid state set value",
243 entry("EFFECTER_ID=%d", effecterId),
244 entry("VALUE=%d", stateField[currState].effecter_state),
245 entry("COMPOSITE_EFFECTER_ID=%d", currState),
246 entry("DBUS_PATH=%c", paths[currState].c_str()));
247 rc = PLDM_PLATFORM_SET_EFFECTER_UNSUPPORTED_SENSORSTATE;
248 break;
249 }
250 auto iter = effecterToDbusEntries.find(states->state_set_id);
251 if (iter == effecterToDbusEntries.end())
252 {
253 uint16_t setId = states->state_set_id;
254 log<level::ERR>(
255 "Did not find the state set for the state effecter pdr ",
256 entry("STATE=%d", setId),
257 entry("EFFECTER_ID=%d", effecterId));
258 rc = PLDM_PLATFORM_INVALID_STATE_VALUE;
259 break;
260 }
261 if (stateField[currState].set_request == PLDM_REQUEST_SET)
262 {
263 rc = iter->second(paths[currState], currState);
264 if (rc != PLDM_SUCCESS)
265 {
266 break;
267 }
268 }
269 uint8_t* nextState =
270 reinterpret_cast<uint8_t*>(states) +
271 sizeof(state_effecter_possible_states) -
272 sizeof(states->states) +
273 (states->possible_states_size * sizeof(states->states));
274 states =
275 reinterpret_cast<state_effecter_possible_states*>(nextState);
276 }
277 return rc;
278 }
279};
280
281} // namespace platform
Deepak Kodihalli557dfb02019-05-12 13:11:17 +0530282} // namespace responder
283} // namespace pldm