blob: 9db93ce631abb6af9bf08b518fa7c416444ecd40 [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
5#include "libpldmresponder/pdr.hpp"
6#include "libpldmresponder/utils.hpp"
7
Deepak Kodihalli557dfb02019-05-12 13:11:17 +05308#include <stdint.h>
9
Sampa Misraa2fa0702019-05-31 01:28:55 -050010#include <map>
Deepak Kodihalli557dfb02019-05-12 13:11:17 +053011
12#include "libpldm/platform.h"
Sampa Misraa2fa0702019-05-31 01:28:55 -050013#include "libpldm/states.h"
Deepak Kodihalli557dfb02019-05-12 13:11:17 +053014
15namespace pldm
16{
17
18using Response = std::vector<uint8_t>;
19
20namespace responder
21{
22
Sampa Misraa2fa0702019-05-31 01:28:55 -050023namespace platform
24{
25
26/** @brief Register handlers for commands from the platform spec
27 */
28void registerHandlers();
29
30} // namespace platform
31
Deepak Kodihalli557dfb02019-05-12 13:11:17 +053032/** @brief Handler for GetPDR
33 *
34 * @param[in] request - Request message payload
35 * @param[in] payloadLength - Request payload length
36 * @param[out] Response - Response message written here
37 */
38Response getPDR(const pldm_msg* request, size_t payloadLength);
39
Sampa Misraa2fa0702019-05-31 01:28:55 -050040/** @brief Handler for setStateEffecterStates
41 *
42 * @param[in] request - Request message
43 * @param[in] payloadLength - Request payload length
44 * @return Response - PLDM Response message
45 */
46Response setStateEffecterStates(const pldm_msg* request, size_t payloadLength);
47
48/** @brief Function to set the effecter requested by pldm requester
49 * @param[in] dBusIntf - The interface object
50 * @param[in] effecterId - Effecter ID sent by the requester to act on
51 * @param[in] stateField - The state field data for each of the states, equal
52 * to composite effecter count in number
53 * @return - Success or failure in setting the states. Returns failure in terms
54 * of PLDM completion codes if atleast one state fails to be set
55 */
56template <class DBusInterface>
57int setStateEffecterStatesHandler(
58 const DBusInterface& dBusIntf, effecter::Id effecterId,
59 const std::vector<set_effecter_state_field>& stateField)
60{
61 using namespace std::string_literals;
62 using DBusProperty = std::variant<std::string, bool>;
63 using StateSetId = uint16_t;
64 using StateSetNum = uint8_t;
65 using PropertyMap =
66 std::map<StateSetId, std::map<StateSetNum, DBusProperty>>;
67 static const PropertyMap stateNumToDbusProp = {
68 {PLDM_BOOT_PROGRESS_STATE,
69 {{PLDM_BOOT_NOT_ACTIVE,
70 "xyz.openbmc_project.State.OperatingSystem.Status.OSStatus."
71 "Standby"s},
72 {PLDM_BOOT_COMPLETED,
73 "xyz.openbmc_project.State.OperatingSystem.Status.OSStatus."
74 "BootComplete"s}}},
75 };
76 using namespace phosphor::logging;
77 using namespace pldm::responder::pdr;
78 using namespace pldm::responder::effecter::dbus_mapping;
79
80 state_effecter_possible_states* states = nullptr;
81 pldm_state_effecter_pdr* pdr = nullptr;
82 uint8_t compEffecterCnt = stateField.size();
83 uint32_t recordHndl{};
84 Repo& pdrRepo = get(PDR_JSONS_DIR);
85 pdr::Entry pdrEntry{};
86
87 while (!pdr)
88 {
89 pdrEntry = pdrRepo.at(recordHndl);
90 pldm_pdr_hdr* header = reinterpret_cast<pldm_pdr_hdr*>(pdrEntry.data());
91 if (header->type != PLDM_STATE_EFFECTER_PDR)
92 {
93 recordHndl = pdrRepo.getNextRecordHandle(recordHndl);
94 if (recordHndl)
95 {
96 continue;
97 }
98 return PLDM_PLATFORM_INVALID_EFFECTER_ID;
99 }
100 pdr = reinterpret_cast<pldm_state_effecter_pdr*>(pdrEntry.data());
101 recordHndl = pdr->hdr.record_handle;
102 if (pdr->effecter_id == effecterId)
103 {
104 states = reinterpret_cast<state_effecter_possible_states*>(
105 pdr->possible_states);
106 if (compEffecterCnt > pdr->composite_effecter_count)
107 {
108 log<level::ERR>("The requester sent wrong composite effecter "
109 "count for the effecter",
110 entry("EFFECTER_ID=%d", effecterId),
111 entry("COMP_EFF_CNT=%d", compEffecterCnt));
112 return PLDM_ERROR_INVALID_DATA;
113 }
114 break;
115 }
116 recordHndl = pdrRepo.getNextRecordHandle(recordHndl);
117 if (!recordHndl)
118 {
119 return PLDM_PLATFORM_INVALID_EFFECTER_ID;
120 }
121 pdr = nullptr;
122 }
123
124 std::map<StateSetId, std::function<int(const std::string& objPath,
125 const uint8_t currState)>>
126 effecterToDbusEntries = {
127 {PLDM_BOOT_PROGRESS_STATE,
128 [&](const std::string& objPath, const uint8_t currState) {
129 auto stateSet =
130 stateNumToDbusProp.find(PLDM_BOOT_PROGRESS_STATE);
131 if (stateSet == stateNumToDbusProp.end())
132 {
133 log<level::ERR>("Couldn't find D-Bus mapping for "
134 "PLDM_BOOT_PROGRESS_STATE",
135 entry("EFFECTER_ID=%d", effecterId));
136 return PLDM_ERROR;
137 }
138 auto iter = stateSet->second.find(
139 stateField[currState].effecter_state);
140 if (iter == stateSet->second.end())
141 {
142 log<level::ERR>(
143 "Invalid state field passed or field not "
144 "found for PLDM_BOOT_PROGRESS_STATE",
145 entry("EFFECTER_ID=%d", effecterId),
146 entry("FIELD=%d",
147 stateField[currState].effecter_state),
148 entry("OBJECT_PATH=%s", objPath.c_str()));
149 return PLDM_ERROR_INVALID_DATA;
150 }
151 auto dbusProp = "OperatingSystemState";
152 std::variant<std::string> value{
153 std::get<std::string>(iter->second)};
154 auto dbusInterface =
155 "xyz.openbmc_project.State.OperatingSystem.Status";
156 try
157 {
158 dBusIntf.setDbusProperty(objPath.c_str(), dbusProp,
159 dbusInterface, value);
160 }
161 catch (const std::exception& e)
162 {
163 log<level::ERR>("Error setting property",
164 entry("ERROR=%s", e.what()),
165 entry("PROPERTY=%s", dbusProp),
166 entry("INTERFACE=%s", dbusInterface),
167 entry("PATH=%s", objPath.c_str()));
168 return PLDM_ERROR;
169 }
170 return PLDM_SUCCESS;
171 }}};
172
173 int rc = PLDM_SUCCESS;
174 auto paths = get(effecterId);
175 for (uint8_t currState = 0; currState < compEffecterCnt; ++currState)
176 {
177 std::vector<StateSetNum> allowed{};
178 // computation is based on table 79 from DSP0248 v1.1.1
179 uint8_t bitfieldIndex = stateField[currState].effecter_state / 8;
180 uint8_t bit =
181 stateField[currState].effecter_state - (8 * bitfieldIndex);
182 if (states->possible_states_size < bitfieldIndex ||
183 !(states->states[bitfieldIndex].byte & (1 << bit)))
184 {
185 log<level::ERR>(
186 "Invalid state set value", entry("EFFECTER_ID=%d", effecterId),
187 entry("VALUE=%d", stateField[currState].effecter_state),
188 entry("COMPOSITE_EFFECTER_ID=%d", currState),
189 entry("DBUS_PATH=%c", paths[currState].c_str()));
190 rc = PLDM_PLATFORM_SET_EFFECTER_UNSUPPORTED_SENSORSTATE;
191 break;
192 }
193 auto iter = effecterToDbusEntries.find(states->state_set_id);
194 if (iter == effecterToDbusEntries.end())
195 {
196 uint16_t setId = states->state_set_id;
197 log<level::ERR>(
198 "Did not find the state set for the state effecter pdr ",
199 entry("STATE=%d", setId), entry("EFFECTER_ID=%d", effecterId));
200 rc = PLDM_PLATFORM_INVALID_STATE_VALUE;
201 break;
202 }
203 if (stateField[currState].set_request == PLDM_REQUEST_SET)
204 {
205 rc = iter->second(paths[currState], currState);
206 if (rc != PLDM_SUCCESS)
207 {
208 break;
209 }
210 }
211 uint8_t* nextState =
212 reinterpret_cast<uint8_t*>(states) +
213 sizeof(state_effecter_possible_states) - sizeof(states->states) +
214 (states->possible_states_size * sizeof(states->states));
215 states = reinterpret_cast<state_effecter_possible_states*>(nextState);
216 }
217 return rc;
218}
219
Deepak Kodihalli557dfb02019-05-12 13:11:17 +0530220} // namespace responder
221} // namespace pldm