blob: dde51e05d6845642a6557b160a37ce202bacb3ae [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 Kodihallibc669f12019-11-28 08:52:07 -060024class Handler : public CmdHandler
Sampa Misraa2fa0702019-05-31 01:28:55 -050025{
Deepak Kodihallibc669f12019-11-28 08:52:07 -060026 public:
27 Handler()
Sampa Misraa2fa0702019-05-31 01:28:55 -050028 {
Deepak Kodihallibc669f12019-11-28 08:52:07 -060029 handlers.emplace(PLDM_GET_PDR,
30 [this](const pldm_msg* request, size_t payloadLength) {
31 return this->getPDR(request, payloadLength);
32 });
33 handlers.emplace(PLDM_SET_STATE_EFFECTER_STATES,
34 [this](const pldm_msg* request, size_t payloadLength) {
35 return this->setStateEffecterStates(request,
36 payloadLength);
37 });
Sampa Misraa2fa0702019-05-31 01:28:55 -050038 }
39
Deepak Kodihallibc669f12019-11-28 08:52:07 -060040 /** @brief Handler for GetPDR
41 *
42 * @param[in] request - Request message payload
43 * @param[in] payloadLength - Request payload length
44 * @param[out] Response - Response message written here
45 */
46 Response getPDR(const pldm_msg* request, size_t payloadLength);
Sampa Misraa2fa0702019-05-31 01:28:55 -050047
Deepak Kodihallibc669f12019-11-28 08:52:07 -060048 /** @brief Handler for setStateEffecterStates
49 *
50 * @param[in] request - Request message
51 * @param[in] payloadLength - Request payload length
52 * @return Response - PLDM Response message
53 */
54 Response setStateEffecterStates(const pldm_msg* request,
55 size_t payloadLength);
56
57 /** @brief Function to set the effecter requested by pldm requester
58 * @param[in] dBusIntf - The interface object
59 * @param[in] effecterId - Effecter ID sent by the requester to act on
60 * @param[in] stateField - The state field data for each of the states,
61 * equal to composite effecter count in number
62 * @return - Success or failure in setting the states. Returns failure in
63 * terms of PLDM completion codes if atleast one state fails to be set
64 */
65 template <class DBusInterface>
66 int setStateEffecterStatesHandler(
67 const DBusInterface& dBusIntf, effecter::Id effecterId,
68 const std::vector<set_effecter_state_field>& stateField)
Sampa Misraa2fa0702019-05-31 01:28:55 -050069 {
George Liue53193f2020-02-24 09:23:26 +080070 using namespace pldm::responder::pdr;
Deepak Kodihallibc669f12019-11-28 08:52:07 -060071 using namespace std::string_literals;
72 using DBusProperty = std::variant<std::string, bool>;
73 using StateSetId = uint16_t;
74 using StateSetNum = uint8_t;
75 using PropertyMap =
76 std::map<StateSetId, std::map<StateSetNum, DBusProperty>>;
77 static const PropertyMap stateNumToDbusProp = {
78 {PLDM_BOOT_PROGRESS_STATE,
79 {{PLDM_BOOT_NOT_ACTIVE,
80 "xyz.openbmc_project.State.OperatingSystem.Status.OSStatus."
81 "Standby"s},
82 {PLDM_BOOT_COMPLETED,
83 "xyz.openbmc_project.State.OperatingSystem.Status.OSStatus."
84 "BootComplete"s}}},
85 {PLDM_SYSTEM_POWER_STATE,
86 {{PLDM_OFF_SOFT_GRACEFUL,
87 "xyz.openbmc_project.State.Chassis.Transition.Off"s}}}};
Deepak Kodihallibc669f12019-11-28 08:52:07 -060088 using namespace pldm::responder::pdr;
89 using namespace pldm::responder::effecter::dbus_mapping;
90
91 state_effecter_possible_states* states = nullptr;
92 pldm_state_effecter_pdr* pdr = nullptr;
93 uint8_t compEffecterCnt = stateField.size();
Deepak Kodihallibc669f12019-11-28 08:52:07 -060094
George Liue53193f2020-02-24 09:23:26 +080095 pdr_utils::Repo repo =
96 getRepoByType(PDR_JSONS_DIR, PLDM_STATE_EFFECTER_PDR);
97 if (repo.empty())
Sampa Misraa2fa0702019-05-31 01:28:55 -050098 {
George Liue53193f2020-02-24 09:23:26 +080099 std::cerr << "Failed to get record by PDR type\n";
100 return PLDM_PLATFORM_INVALID_EFFECTER_ID;
101 }
102 PdrEntry pdrEntry{};
103 auto pdrRecord = repo.getFirstRecord(pdrEntry);
104 while (pdrRecord)
105 {
106 pdr = reinterpret_cast<pldm_state_effecter_pdr*>(pdrEntry.data);
107 if (pdr->effecter_id != effecterId)
Sampa Misraa2fa0702019-05-31 01:28:55 -0500108 {
George Liue53193f2020-02-24 09:23:26 +0800109 pdr = nullptr;
110 pdrRecord = repo.getNextRecord(pdrRecord, pdrEntry);
111 continue;
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600112 }
George Liue53193f2020-02-24 09:23:26 +0800113
114 states = reinterpret_cast<state_effecter_possible_states*>(
115 pdr->possible_states);
116 if (compEffecterCnt > pdr->composite_effecter_count)
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600117 {
George Liue53193f2020-02-24 09:23:26 +0800118 std::cerr << "The requester sent wrong composite effecter"
119 << " count for the effecter, EFFECTER_ID="
120 << effecterId << "COMP_EFF_CNT=" << compEffecterCnt
121 << "\n";
122 return PLDM_ERROR_INVALID_DATA;
Sampa Misraa2fa0702019-05-31 01:28:55 -0500123 }
George Liue53193f2020-02-24 09:23:26 +0800124 break;
125 }
126
127 if (!pdr)
128 {
129 return PLDM_PLATFORM_INVALID_EFFECTER_ID;
Sampa Misraa2fa0702019-05-31 01:28:55 -0500130 }
Sampa Misraa2fa0702019-05-31 01:28:55 -0500131
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600132 std::map<StateSetId, std::function<int(const std::string& objPath,
133 const uint8_t currState)>>
134 effecterToDbusEntries = {
135 {PLDM_BOOT_PROGRESS_STATE,
136 [&](const std::string& objPath, const uint8_t currState) {
137 auto stateSet =
138 stateNumToDbusProp.find(PLDM_BOOT_PROGRESS_STATE);
139 if (stateSet == stateNumToDbusProp.end())
140 {
Sampa Misraaa8ae722019-12-12 03:20:40 -0600141 std::cerr << "Couldn't find D-Bus mapping for "
142 << "PLDM_BOOT_PROGRESS_STATE, EFFECTER_ID="
143 << effecterId << "\n";
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600144 return PLDM_ERROR;
145 }
146 auto iter = stateSet->second.find(
147 stateField[currState].effecter_state);
148 if (iter == stateSet->second.end())
149 {
Sampa Misraaa8ae722019-12-12 03:20:40 -0600150 std::cerr << "Invalid state field passed or field not "
151 << "found for PLDM_BOOT_PROGRESS_STATE, "
152 "EFFECTER_ID="
153 << effecterId << " FIELD="
154 << stateField[currState].effecter_state
155 << " OBJECT_PATH=" << objPath.c_str()
156 << "\n";
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600157 return PLDM_ERROR_INVALID_DATA;
158 }
159 auto dbusProp = "OperatingSystemState";
160 std::variant<std::string> value{
161 std::get<std::string>(iter->second)};
162 auto dbusInterface =
163 "xyz.openbmc_project.State.OperatingSystem.Status";
164 try
165 {
166 dBusIntf.setDbusProperty(objPath.c_str(), dbusProp,
167 dbusInterface, value);
168 }
169 catch (const std::exception& e)
170 {
Sampa Misraaa8ae722019-12-12 03:20:40 -0600171 std::cerr
172 << "Error setting property, ERROR=" << e.what()
173 << " PROPERTY=" << dbusProp
174 << " INTERFACE=" << dbusInterface
175 << " PATH=" << objPath.c_str() << "\n";
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600176 return PLDM_ERROR;
177 }
178 return PLDM_SUCCESS;
179 }},
180 {PLDM_SYSTEM_POWER_STATE,
181 [&](const std::string& objPath, const uint8_t currState) {
182 auto stateSet =
183 stateNumToDbusProp.find(PLDM_SYSTEM_POWER_STATE);
184 if (stateSet == stateNumToDbusProp.end())
185 {
Sampa Misraaa8ae722019-12-12 03:20:40 -0600186 std::cerr << "Couldn't find D-Bus mapping for "
187 << "PLDM_SYSTEM_POWER_STATE, EFFECTER_ID="
188 << effecterId << "\n";
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600189 return PLDM_ERROR;
190 }
191 auto iter = stateSet->second.find(
192 stateField[currState].effecter_state);
193 if (iter == stateSet->second.end())
194 {
Sampa Misraaa8ae722019-12-12 03:20:40 -0600195 std::cerr << "Invalid state field passed or field not "
196 << "found for PLDM_SYSTEM_POWER_STATE, "
197 "EFFECTER_ID="
198 << effecterId << " FIELD="
199 << stateField[currState].effecter_state
200 << " OBJECT_PATH=" << objPath.c_str()
201 << "\n";
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600202 return PLDM_ERROR_INVALID_DATA;
203 }
204 auto dbusProp = "RequestedPowerTransition";
205 std::variant<std::string> value{
206 std::get<std::string>(iter->second)};
207 auto dbusInterface = "xyz.openbmc_project.State.Chassis";
208 try
209 {
210 dBusIntf.setDbusProperty(objPath.c_str(), dbusProp,
211 dbusInterface, value);
212 }
213 catch (const std::exception& e)
214 {
Sampa Misraaa8ae722019-12-12 03:20:40 -0600215 std::cerr
216 << "Error setting property, ERROR=" << e.what()
217 << " PROPERTY=" << dbusProp
218 << " INTERFACE=" << dbusInterface
219 << " PATH=" << objPath.c_str() << "\n";
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600220 return PLDM_ERROR;
221 }
222 return PLDM_SUCCESS;
223 }}};
224
225 int rc = PLDM_SUCCESS;
226 auto paths = get(effecterId);
227 for (uint8_t currState = 0; currState < compEffecterCnt; ++currState)
228 {
229 std::vector<StateSetNum> allowed{};
230 // computation is based on table 79 from DSP0248 v1.1.1
231 uint8_t bitfieldIndex = stateField[currState].effecter_state / 8;
232 uint8_t bit =
233 stateField[currState].effecter_state - (8 * bitfieldIndex);
234 if (states->possible_states_size < bitfieldIndex ||
235 !(states->states[bitfieldIndex].byte & (1 << bit)))
236 {
Sampa Misraaa8ae722019-12-12 03:20:40 -0600237 std::cerr << "Invalid state set value, EFFECTER_ID="
238 << effecterId
239 << " VALUE=" << stateField[currState].effecter_state
240 << " COMPOSITE_EFFECTER_ID=" << currState
241 << " DBUS_PATH=" << paths[currState].c_str() << "\n";
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600242 rc = PLDM_PLATFORM_SET_EFFECTER_UNSUPPORTED_SENSORSTATE;
243 break;
244 }
245 auto iter = effecterToDbusEntries.find(states->state_set_id);
246 if (iter == effecterToDbusEntries.end())
247 {
248 uint16_t setId = states->state_set_id;
Sampa Misraaa8ae722019-12-12 03:20:40 -0600249 std::cerr << "Did not find the state set for the"
250 << " state effecter pdr, STATE=" << setId
251 << " EFFECTER_ID=" << effecterId << "\n";
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600252 rc = PLDM_PLATFORM_INVALID_STATE_VALUE;
253 break;
254 }
255 if (stateField[currState].set_request == PLDM_REQUEST_SET)
256 {
257 rc = iter->second(paths[currState], currState);
258 if (rc != PLDM_SUCCESS)
259 {
260 break;
261 }
262 }
263 uint8_t* nextState =
264 reinterpret_cast<uint8_t*>(states) +
265 sizeof(state_effecter_possible_states) -
266 sizeof(states->states) +
267 (states->possible_states_size * sizeof(states->states));
268 states =
269 reinterpret_cast<state_effecter_possible_states*>(nextState);
270 }
271 return rc;
272 }
273};
274
275} // namespace platform
Deepak Kodihalli557dfb02019-05-12 13:11:17 +0530276} // namespace responder
277} // namespace pldm