blob: 8c9e45c1fca3bdee4b2533a55d67a142d660807d [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"
George Liue53193f2020-02-24 09:23:26 +08007#include "libpldmresponder/pdr_utils.hpp"
George Liu83409572019-12-24 18:42:54 +08008#include "utils.hpp"
Sampa Misraa2fa0702019-05-31 01:28:55 -05009
Deepak Kodihalli557dfb02019-05-12 13:11:17 +053010#include <stdint.h>
11
Sampa Misraa2fa0702019-05-31 01:28:55 -050012#include <map>
Deepak Kodihalli557dfb02019-05-12 13:11:17 +053013
14#include "libpldm/platform.h"
Sampa Misraa2fa0702019-05-31 01:28:55 -050015#include "libpldm/states.h"
Deepak Kodihalli557dfb02019-05-12 13:11:17 +053016
17namespace pldm
18{
Deepak Kodihalli557dfb02019-05-12 13:11:17 +053019namespace responder
20{
Sampa Misraa2fa0702019-05-31 01:28:55 -050021namespace platform
22{
23
Deepak Kodihallic682fe22020-03-04 00:42:54 -060024using DbusPath = std::string;
25using EffecterObjs = std::vector<DbusPath>;
26
Deepak Kodihallibc669f12019-11-28 08:52:07 -060027class Handler : public CmdHandler
Sampa Misraa2fa0702019-05-31 01:28:55 -050028{
Deepak Kodihallibc669f12019-11-28 08:52:07 -060029 public:
Deepak Kodihallic682fe22020-03-04 00:42:54 -060030 Handler(const std::string& dir, pldm_pdr* repo) : pdrRepo(repo)
Sampa Misraa2fa0702019-05-31 01:28:55 -050031 {
Deepak Kodihallic682fe22020-03-04 00:42:54 -060032 generate(dir, pdrRepo);
33
Deepak Kodihallibc669f12019-11-28 08:52:07 -060034 handlers.emplace(PLDM_GET_PDR,
35 [this](const pldm_msg* request, size_t payloadLength) {
36 return this->getPDR(request, payloadLength);
37 });
38 handlers.emplace(PLDM_SET_STATE_EFFECTER_STATES,
39 [this](const pldm_msg* request, size_t payloadLength) {
40 return this->setStateEffecterStates(request,
41 payloadLength);
42 });
Sampa Misraa2fa0702019-05-31 01:28:55 -050043 }
44
Deepak Kodihallic682fe22020-03-04 00:42:54 -060045 const EffecterObjs& getEffecterObjs(uint16_t effecterId) const
46 {
47 return effecterObjs.at(effecterId);
48 }
49
50 void addEffecterObjs(uint16_t effecterId, EffecterObjs&& paths)
51 {
52 effecterObjs.emplace(effecterId, std::move(paths));
53 }
54
55 uint16_t getNextEffecterId()
56 {
57 return ++nextEffecterId;
58 }
59
60 /** @brief Parse PDR JSONs and build PDR repository
61 *
62 * @param[in] dir - directory housing platform specific PDR JSON files
63 * @param[in] repo - instance of concrete implementation of Repo
64 */
65 void generate(const std::string& dir, Repo& repo);
66
67 /** @brief Parse PDR JSONs and build state effecter PDR repository
68 *
69 * @param[in] json - platform specific PDR JSON files
70 * @param[in] repo - instance of state effecter implementation of Repo
71 */
72 void generateStateEffecterRepo(const Json& json, Repo& repo);
73
Deepak Kodihallibc669f12019-11-28 08:52:07 -060074 /** @brief Handler for GetPDR
75 *
76 * @param[in] request - Request message payload
77 * @param[in] payloadLength - Request payload length
78 * @param[out] Response - Response message written here
79 */
80 Response getPDR(const pldm_msg* request, size_t payloadLength);
Sampa Misraa2fa0702019-05-31 01:28:55 -050081
Deepak Kodihallibc669f12019-11-28 08:52:07 -060082 /** @brief Handler for setStateEffecterStates
83 *
84 * @param[in] request - Request message
85 * @param[in] payloadLength - Request payload length
86 * @return Response - PLDM Response message
87 */
88 Response setStateEffecterStates(const pldm_msg* request,
89 size_t payloadLength);
90
91 /** @brief Function to set the effecter requested by pldm requester
92 * @param[in] dBusIntf - The interface object
93 * @param[in] effecterId - Effecter ID sent by the requester to act on
94 * @param[in] stateField - The state field data for each of the states,
95 * equal to composite effecter count in number
96 * @return - Success or failure in setting the states. Returns failure in
97 * terms of PLDM completion codes if atleast one state fails to be set
98 */
99 template <class DBusInterface>
100 int setStateEffecterStatesHandler(
Deepak Kodihallic682fe22020-03-04 00:42:54 -0600101 const DBusInterface& dBusIntf, uint16_t effecterId,
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600102 const std::vector<set_effecter_state_field>& stateField)
Sampa Misraa2fa0702019-05-31 01:28:55 -0500103 {
George Liue53193f2020-02-24 09:23:26 +0800104 using namespace pldm::responder::pdr;
George Liu1e44c732020-02-28 20:20:06 +0800105 using namespace pldm::utils;
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600106 using namespace std::string_literals;
107 using DBusProperty = std::variant<std::string, bool>;
108 using StateSetId = uint16_t;
109 using StateSetNum = uint8_t;
110 using PropertyMap =
111 std::map<StateSetId, std::map<StateSetNum, DBusProperty>>;
112 static const PropertyMap stateNumToDbusProp = {
113 {PLDM_BOOT_PROGRESS_STATE,
114 {{PLDM_BOOT_NOT_ACTIVE,
115 "xyz.openbmc_project.State.OperatingSystem.Status.OSStatus."
116 "Standby"s},
117 {PLDM_BOOT_COMPLETED,
118 "xyz.openbmc_project.State.OperatingSystem.Status.OSStatus."
119 "BootComplete"s}}},
120 {PLDM_SYSTEM_POWER_STATE,
121 {{PLDM_OFF_SOFT_GRACEFUL,
122 "xyz.openbmc_project.State.Chassis.Transition.Off"s}}}};
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600123 using namespace pldm::responder::pdr;
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600124
125 state_effecter_possible_states* states = nullptr;
126 pldm_state_effecter_pdr* pdr = nullptr;
127 uint8_t compEffecterCnt = stateField.size();
George Liue53193f2020-02-24 09:23:26 +0800128 PdrEntry pdrEntry{};
Deepak Kodihallic682fe22020-03-04 00:42:54 -0600129 auto pdrRecord = pdrRepo.getFirstRecord(pdrEntry);
George Liue53193f2020-02-24 09:23:26 +0800130 while (pdrRecord)
131 {
132 pdr = reinterpret_cast<pldm_state_effecter_pdr*>(pdrEntry.data);
133 if (pdr->effecter_id != effecterId)
Sampa Misraa2fa0702019-05-31 01:28:55 -0500134 {
George Liue53193f2020-02-24 09:23:26 +0800135 pdr = nullptr;
Deepak Kodihallic682fe22020-03-04 00:42:54 -0600136 pdrRecord = pdrRepo.getNextRecord(pdrRecord, pdrEntry);
George Liue53193f2020-02-24 09:23:26 +0800137 continue;
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600138 }
George Liue53193f2020-02-24 09:23:26 +0800139
140 states = reinterpret_cast<state_effecter_possible_states*>(
141 pdr->possible_states);
142 if (compEffecterCnt > pdr->composite_effecter_count)
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600143 {
George Liue53193f2020-02-24 09:23:26 +0800144 std::cerr << "The requester sent wrong composite effecter"
145 << " count for the effecter, EFFECTER_ID="
146 << effecterId << "COMP_EFF_CNT=" << compEffecterCnt
147 << "\n";
148 return PLDM_ERROR_INVALID_DATA;
Sampa Misraa2fa0702019-05-31 01:28:55 -0500149 }
George Liue53193f2020-02-24 09:23:26 +0800150 break;
151 }
152
153 if (!pdr)
154 {
155 return PLDM_PLATFORM_INVALID_EFFECTER_ID;
Sampa Misraa2fa0702019-05-31 01:28:55 -0500156 }
Sampa Misraa2fa0702019-05-31 01:28:55 -0500157
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600158 std::map<StateSetId, std::function<int(const std::string& objPath,
159 const uint8_t currState)>>
160 effecterToDbusEntries = {
161 {PLDM_BOOT_PROGRESS_STATE,
162 [&](const std::string& objPath, const uint8_t currState) {
163 auto stateSet =
164 stateNumToDbusProp.find(PLDM_BOOT_PROGRESS_STATE);
165 if (stateSet == stateNumToDbusProp.end())
166 {
Sampa Misraaa8ae722019-12-12 03:20:40 -0600167 std::cerr << "Couldn't find D-Bus mapping for "
168 << "PLDM_BOOT_PROGRESS_STATE, EFFECTER_ID="
169 << effecterId << "\n";
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600170 return PLDM_ERROR;
171 }
172 auto iter = stateSet->second.find(
173 stateField[currState].effecter_state);
174 if (iter == stateSet->second.end())
175 {
Sampa Misraaa8ae722019-12-12 03:20:40 -0600176 std::cerr << "Invalid state field passed or field not "
177 << "found for PLDM_BOOT_PROGRESS_STATE, "
178 "EFFECTER_ID="
179 << effecterId << " FIELD="
180 << stateField[currState].effecter_state
181 << " OBJECT_PATH=" << objPath.c_str()
182 << "\n";
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600183 return PLDM_ERROR_INVALID_DATA;
184 }
George Liu1e44c732020-02-28 20:20:06 +0800185 PropertyValue value{std::get<std::string>(iter->second)};
186 DBusMapping dbusMapping{
187 objPath,
188 "xyz.openbmc_project.State.OperatingSystem.Status",
189 "OperatingSystemState", "string"};
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600190 try
191 {
George Liu1e44c732020-02-28 20:20:06 +0800192 dBusIntf.setDbusProperty(dbusMapping, value);
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600193 }
194 catch (const std::exception& e)
195 {
Sampa Misraaa8ae722019-12-12 03:20:40 -0600196 std::cerr
197 << "Error setting property, ERROR=" << e.what()
George Liu1e44c732020-02-28 20:20:06 +0800198 << " PROPERTY=" << dbusMapping.propertyName
199 << " INTERFACE="
200 << dbusMapping.interface << " PATH="
201 << dbusMapping.objectPath << "\n";
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600202 return PLDM_ERROR;
203 }
204 return PLDM_SUCCESS;
205 }},
206 {PLDM_SYSTEM_POWER_STATE,
207 [&](const std::string& objPath, const uint8_t currState) {
208 auto stateSet =
209 stateNumToDbusProp.find(PLDM_SYSTEM_POWER_STATE);
210 if (stateSet == stateNumToDbusProp.end())
211 {
Sampa Misraaa8ae722019-12-12 03:20:40 -0600212 std::cerr << "Couldn't find D-Bus mapping for "
213 << "PLDM_SYSTEM_POWER_STATE, EFFECTER_ID="
214 << effecterId << "\n";
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600215 return PLDM_ERROR;
216 }
217 auto iter = stateSet->second.find(
218 stateField[currState].effecter_state);
219 if (iter == stateSet->second.end())
220 {
Sampa Misraaa8ae722019-12-12 03:20:40 -0600221 std::cerr << "Invalid state field passed or field not "
222 << "found for PLDM_SYSTEM_POWER_STATE, "
223 "EFFECTER_ID="
224 << effecterId << " FIELD="
225 << stateField[currState].effecter_state
226 << " OBJECT_PATH=" << objPath.c_str()
227 << "\n";
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600228 return PLDM_ERROR_INVALID_DATA;
229 }
George Liu1e44c732020-02-28 20:20:06 +0800230 PropertyValue value{std::get<std::string>(iter->second)};
231 DBusMapping dbusMapping{
232 objPath, "xyz.openbmc_project.State.Chassis",
233 "RequestedPowerTransition", "string"};
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600234 try
235 {
George Liu1e44c732020-02-28 20:20:06 +0800236 dBusIntf.setDbusProperty(dbusMapping, value);
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600237 }
238 catch (const std::exception& e)
239 {
Sampa Misraaa8ae722019-12-12 03:20:40 -0600240 std::cerr
241 << "Error setting property, ERROR=" << e.what()
George Liu1e44c732020-02-28 20:20:06 +0800242 << " PROPERTY=" << dbusMapping.propertyName
243 << " INTERFACE="
244 << dbusMapping.interface << " PATH="
245 << dbusMapping.objectPath << "\n";
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600246 return PLDM_ERROR;
247 }
248 return PLDM_SUCCESS;
249 }}};
250
251 int rc = PLDM_SUCCESS;
Deepak Kodihallic682fe22020-03-04 00:42:54 -0600252 const auto& paths = getEffecterObjs(effecterId);
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600253 for (uint8_t currState = 0; currState < compEffecterCnt; ++currState)
254 {
255 std::vector<StateSetNum> allowed{};
256 // computation is based on table 79 from DSP0248 v1.1.1
257 uint8_t bitfieldIndex = stateField[currState].effecter_state / 8;
258 uint8_t bit =
259 stateField[currState].effecter_state - (8 * bitfieldIndex);
260 if (states->possible_states_size < bitfieldIndex ||
261 !(states->states[bitfieldIndex].byte & (1 << bit)))
262 {
Sampa Misraaa8ae722019-12-12 03:20:40 -0600263 std::cerr << "Invalid state set value, EFFECTER_ID="
264 << effecterId
265 << " VALUE=" << stateField[currState].effecter_state
266 << " COMPOSITE_EFFECTER_ID=" << currState
267 << " DBUS_PATH=" << paths[currState].c_str() << "\n";
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600268 rc = PLDM_PLATFORM_SET_EFFECTER_UNSUPPORTED_SENSORSTATE;
269 break;
270 }
271 auto iter = effecterToDbusEntries.find(states->state_set_id);
272 if (iter == effecterToDbusEntries.end())
273 {
274 uint16_t setId = states->state_set_id;
Sampa Misraaa8ae722019-12-12 03:20:40 -0600275 std::cerr << "Did not find the state set for the"
276 << " state effecter pdr, STATE=" << setId
277 << " EFFECTER_ID=" << effecterId << "\n";
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600278 rc = PLDM_PLATFORM_INVALID_STATE_VALUE;
279 break;
280 }
281 if (stateField[currState].set_request == PLDM_REQUEST_SET)
282 {
283 rc = iter->second(paths[currState], currState);
284 if (rc != PLDM_SUCCESS)
285 {
286 break;
287 }
288 }
289 uint8_t* nextState =
290 reinterpret_cast<uint8_t*>(states) +
291 sizeof(state_effecter_possible_states) -
292 sizeof(states->states) +
293 (states->possible_states_size * sizeof(states->states));
294 states =
295 reinterpret_cast<state_effecter_possible_states*>(nextState);
296 }
297 return rc;
298 }
Deepak Kodihallic682fe22020-03-04 00:42:54 -0600299
300 private:
301 pdr_utils::Repo pdrRepo;
302 uint16_t nextEffecterId{};
303 std::map<uint16_t, EffecterObjs> effecterObjs{};
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600304};
305
306} // namespace platform
Deepak Kodihalli557dfb02019-05-12 13:11:17 +0530307} // namespace responder
308} // namespace pldm