blob: 6ace46b0e7698ccb4d26da7972696723c1c50f1e [file] [log] [blame]
Deepak Kodihalli557dfb02019-05-12 13:11:17 +05301
2#include "platform.hpp"
3
George Liu83409572019-12-24 18:42:54 +08004#include "utils.hpp"
5
Deepak Kodihalli557dfb02019-05-12 13:11:17 +05306namespace pldm
7{
Deepak Kodihalli557dfb02019-05-12 13:11:17 +05308namespace responder
9{
Sampa Misraa2fa0702019-05-31 01:28:55 -050010namespace platform
11{
12
Deepak Kodihallic682fe22020-03-04 00:42:54 -060013using InternalFailure =
14 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
15
16void Handler::generateStateEffecterRepo(const Json& json, Repo& repo)
17{
18 static const std::vector<Json> emptyList{};
19 static const Json empty{};
20 auto entries = json.value("entries", emptyList);
21 for (const auto& e : entries)
22 {
23 size_t pdrSize = 0;
24 auto effecters = e.value("effecters", emptyList);
25 static const Json empty{};
26 for (const auto& effecter : effecters)
27 {
28 auto set = effecter.value("set", empty);
29 auto statesSize = set.value("size", 0);
30 if (!statesSize)
31 {
32 std::cerr << "Malformed PDR JSON return "
33 "pdrEntry;- no state set "
34 "info, TYPE="
35 << PLDM_STATE_EFFECTER_PDR << "\n";
36 throw InternalFailure();
37 }
38 pdrSize += sizeof(state_effecter_possible_states) -
39 sizeof(bitfield8_t) + (sizeof(bitfield8_t) * statesSize);
40 }
41 pdrSize += sizeof(pldm_state_effecter_pdr) - sizeof(uint8_t);
42
43 std::vector<uint8_t> entry{};
44 entry.resize(pdrSize);
45
46 pldm_state_effecter_pdr* pdr =
47 reinterpret_cast<pldm_state_effecter_pdr*>(entry.data());
48 pdr->hdr.record_handle = 0;
49 pdr->hdr.version = 1;
50 pdr->hdr.type = PLDM_STATE_EFFECTER_PDR;
51 pdr->hdr.record_change_num = 0;
52 pdr->hdr.length = pdrSize - sizeof(pldm_pdr_hdr);
53
54 pdr->terminus_handle = 0;
55 pdr->effecter_id = this->getNextEffecterId();
56 pdr->entity_type = e.value("type", 0);
57 pdr->entity_instance = e.value("instance", 0);
58 pdr->container_id = e.value("container", 0);
59 pdr->effecter_semantic_id = 0;
60 pdr->effecter_init = PLDM_NO_INIT;
61 pdr->has_description_pdr = false;
62 pdr->composite_effecter_count = effecters.size();
63
64 EffecterObjs paths{};
65 uint8_t* start =
66 entry.data() + sizeof(pldm_state_effecter_pdr) - sizeof(uint8_t);
67 for (const auto& effecter : effecters)
68 {
69 auto set = effecter.value("set", empty);
70 state_effecter_possible_states* possibleStates =
71 reinterpret_cast<state_effecter_possible_states*>(start);
72 possibleStates->state_set_id = set.value("id", 0);
73 possibleStates->possible_states_size = set.value("size", 0);
74
75 start += sizeof(possibleStates->state_set_id) +
76 sizeof(possibleStates->possible_states_size);
77 static const std::vector<uint8_t> emptyStates{};
78 auto states = set.value("states", emptyStates);
79 for (const auto& state : states)
80 {
81 auto index = state / 8;
82 auto bit = state - (index * 8);
83 bitfield8_t* bf = reinterpret_cast<bitfield8_t*>(start + index);
84 bf->byte |= 1 << bit;
85 }
86 start += possibleStates->possible_states_size;
87
88 auto dbus = effecter.value("dbus", empty);
89 paths.emplace_back(std::move(dbus));
90 }
91 addEffecterObjs(pdr->effecter_id, std::move(paths));
92 PdrEntry pdrEntry{};
93 pdrEntry.data = entry.data();
94 pdrEntry.size = pdrSize;
95 repo.addRecord(pdrEntry);
96 }
97}
98
99void Handler::generate(const std::string& dir, Repo& repo)
100{
101 // A map of PDR type to a lambda that handles creation of that PDR type.
102 // The lambda essentially would parse the platform specific PDR JSONs to
103 // generate the PDR structures. This function iterates through the map to
104 // invoke all lambdas, so that all PDR types can be created.
105 const std::map<Type, std::function<void(const Json& json, Repo& repo)>>
106 generators = {
107 {PLDM_STATE_EFFECTER_PDR, [this](const auto& json, Repo& repo) {
108 generateStateEffecterRepo(json, repo);
109 }}};
110
111 Type pdrType{};
112 for (const auto& dirEntry : fs::directory_iterator(dir))
113 {
114 try
115 {
116 auto json = readJson(dirEntry.path().string());
117 if (!json.empty())
118 {
119 pdrType = json.value("pdrType", 0);
120 generators.at(pdrType)(json, repo);
121 }
122 }
123 catch (const InternalFailure& e)
124 {
125 std::cerr << "PDR config directory does not exist or empty, TYPE= "
126 << pdrType << "PATH= " << dirEntry
127 << " ERROR=" << e.what() << "\n";
128 }
129 catch (const Json::exception& e)
130 {
131 std::cerr << "Failed parsing PDR JSON file, TYPE= " << pdrType
132 << " ERROR=" << e.what() << "\n";
133 pldm::utils::reportError(
134 "xyz.openbmc_project.bmc.pldm.InternalFailure");
135 }
136 catch (const std::exception& e)
137 {
138 std::cerr << "Failed parsing PDR JSON file, TYPE= " << pdrType
139 << " ERROR=" << e.what() << "\n";
140 pldm::utils::reportError(
141 "xyz.openbmc_project.bmc.pldm.InternalFailure");
142 }
143 }
144}
Deepak Kodihalli557dfb02019-05-12 13:11:17 +0530145
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600146Response Handler::getPDR(const pldm_msg* request, size_t payloadLength)
Deepak Kodihalli557dfb02019-05-12 13:11:17 +0530147{
148 Response response(sizeof(pldm_msg_hdr) + PLDM_GET_PDR_MIN_RESP_BYTES, 0);
149 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
150
151 if (payloadLength != PLDM_GET_PDR_REQ_BYTES)
152 {
George Liufb8611d2019-12-06 10:14:15 +0800153 return CmdHandler::ccOnlyResponse(request, PLDM_ERROR_INVALID_LENGTH);
Deepak Kodihalli557dfb02019-05-12 13:11:17 +0530154 }
155
156 uint32_t recordHandle{};
157 uint32_t dataTransferHandle{};
158 uint8_t transferOpFlag{};
159 uint16_t reqSizeBytes{};
160 uint16_t recordChangeNum{};
161
George Liufb8611d2019-12-06 10:14:15 +0800162 auto rc = decode_get_pdr_req(request, payloadLength, &recordHandle,
163 &dataTransferHandle, &transferOpFlag,
164 &reqSizeBytes, &recordChangeNum);
165 if (rc != PLDM_SUCCESS)
166 {
167 return CmdHandler::ccOnlyResponse(request, rc);
168 }
Deepak Kodihalli557dfb02019-05-12 13:11:17 +0530169
Deepak Kodihalli557dfb02019-05-12 13:11:17 +0530170 uint16_t respSizeBytes{};
171 uint8_t* recordData = nullptr;
172 try
173 {
George Liue53193f2020-02-24 09:23:26 +0800174 pdr_utils::PdrEntry e;
175 auto record = pdr::getRecordByHandle(pdrRepo, recordHandle, e);
176 if (record == NULL)
177 {
178 return CmdHandler::ccOnlyResponse(
179 request, PLDM_PLATFORM_INVALID_RECORD_HANDLE);
180 }
181
Deepak Kodihalli557dfb02019-05-12 13:11:17 +0530182 if (reqSizeBytes)
183 {
George Liue53193f2020-02-24 09:23:26 +0800184 respSizeBytes = e.size;
Deepak Kodihalli557dfb02019-05-12 13:11:17 +0530185 if (respSizeBytes > reqSizeBytes)
186 {
187 respSizeBytes = reqSizeBytes;
188 }
George Liue53193f2020-02-24 09:23:26 +0800189 recordData = e.data;
Deepak Kodihalli557dfb02019-05-12 13:11:17 +0530190 }
191 response.resize(sizeof(pldm_msg_hdr) + PLDM_GET_PDR_MIN_RESP_BYTES +
192 respSizeBytes,
193 0);
194 responsePtr = reinterpret_cast<pldm_msg*>(response.data());
Deepak Kodihalli22b5a7d2020-03-17 23:28:41 -0500195 rc = encode_get_pdr_resp(
196 request->hdr.instance_id, PLDM_SUCCESS, e.handle.nextRecordHandle,
197 0, PLDM_START_AND_END, respSizeBytes, recordData, 0, responsePtr);
George Liufb8611d2019-12-06 10:14:15 +0800198 if (rc != PLDM_SUCCESS)
199 {
200 return ccOnlyResponse(request, rc);
201 }
Deepak Kodihalli557dfb02019-05-12 13:11:17 +0530202 }
Deepak Kodihalli557dfb02019-05-12 13:11:17 +0530203 catch (const std::exception& e)
204 {
Sampa Misraaa8ae722019-12-12 03:20:40 -0600205 std::cerr << "Error accessing PDR, HANDLE=" << recordHandle
206 << " ERROR=" << e.what() << "\n";
George Liufb8611d2019-12-06 10:14:15 +0800207 return CmdHandler::ccOnlyResponse(request, PLDM_ERROR);
Deepak Kodihalli557dfb02019-05-12 13:11:17 +0530208 }
209 return response;
210}
211
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600212Response Handler::setStateEffecterStates(const pldm_msg* request,
213 size_t payloadLength)
Sampa Misraa2fa0702019-05-31 01:28:55 -0500214{
215 Response response(
216 sizeof(pldm_msg_hdr) + PLDM_SET_STATE_EFFECTER_STATES_RESP_BYTES, 0);
217 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
218 uint16_t effecterId;
219 uint8_t compEffecterCnt;
220 constexpr auto maxCompositeEffecterCnt = 8;
221 std::vector<set_effecter_state_field> stateField(maxCompositeEffecterCnt,
222 {0, 0});
223
224 if ((payloadLength > PLDM_SET_STATE_EFFECTER_STATES_REQ_BYTES) ||
225 (payloadLength < sizeof(effecterId) + sizeof(compEffecterCnt) +
226 sizeof(set_effecter_state_field)))
227 {
George Liufb8611d2019-12-06 10:14:15 +0800228 return CmdHandler::ccOnlyResponse(request, PLDM_ERROR_INVALID_LENGTH);
Sampa Misraa2fa0702019-05-31 01:28:55 -0500229 }
230
231 int rc = decode_set_state_effecter_states_req(request, payloadLength,
232 &effecterId, &compEffecterCnt,
233 stateField.data());
234
George Liufb8611d2019-12-06 10:14:15 +0800235 if (rc != PLDM_SUCCESS)
Sampa Misraa2fa0702019-05-31 01:28:55 -0500236 {
George Liufb8611d2019-12-06 10:14:15 +0800237 return CmdHandler::ccOnlyResponse(request, rc);
Sampa Misraa2fa0702019-05-31 01:28:55 -0500238 }
239
George Liufb8611d2019-12-06 10:14:15 +0800240 stateField.resize(compEffecterCnt);
241 const pldm::utils::DBusHandler dBusIntf;
242 rc = setStateEffecterStatesHandler<pldm::utils::DBusHandler>(
243 dBusIntf, effecterId, stateField);
244 if (rc != PLDM_SUCCESS)
245 {
246 return CmdHandler::ccOnlyResponse(request, rc);
247 }
248
249 rc = encode_set_state_effecter_states_resp(request->hdr.instance_id, rc,
250 responsePtr);
251 if (rc != PLDM_SUCCESS)
252 {
253 return ccOnlyResponse(request, rc);
254 }
255
Sampa Misraa2fa0702019-05-31 01:28:55 -0500256 return response;
257}
258
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600259} // namespace platform
Deepak Kodihalli557dfb02019-05-12 13:11:17 +0530260} // namespace responder
261} // namespace pldm