1557dfb00SDeepak Kodihalli 
2557dfb00SDeepak Kodihalli #include "platform.hpp"
3557dfb00SDeepak Kodihalli 
483409573SGeorge Liu #include "utils.hpp"
583409573SGeorge Liu 
6557dfb00SDeepak Kodihalli namespace pldm
7557dfb00SDeepak Kodihalli {
8557dfb00SDeepak Kodihalli namespace responder
9557dfb00SDeepak Kodihalli {
10a2fa0709SSampa Misra namespace platform
11a2fa0709SSampa Misra {
12a2fa0709SSampa Misra 
13c682fe2dSDeepak Kodihalli using InternalFailure =
14c682fe2dSDeepak Kodihalli     sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
15c682fe2dSDeepak Kodihalli 
16c682fe2dSDeepak Kodihalli void Handler::generateStateEffecterRepo(const Json& json, Repo& repo)
17c682fe2dSDeepak Kodihalli {
18c682fe2dSDeepak Kodihalli     static const std::vector<Json> emptyList{};
19c682fe2dSDeepak Kodihalli     static const Json empty{};
20c682fe2dSDeepak Kodihalli     auto entries = json.value("entries", emptyList);
21c682fe2dSDeepak Kodihalli     for (const auto& e : entries)
22c682fe2dSDeepak Kodihalli     {
23c682fe2dSDeepak Kodihalli         size_t pdrSize = 0;
24c682fe2dSDeepak Kodihalli         auto effecters = e.value("effecters", emptyList);
25c682fe2dSDeepak Kodihalli         static const Json empty{};
26c682fe2dSDeepak Kodihalli         for (const auto& effecter : effecters)
27c682fe2dSDeepak Kodihalli         {
28c682fe2dSDeepak Kodihalli             auto set = effecter.value("set", empty);
29c682fe2dSDeepak Kodihalli             auto statesSize = set.value("size", 0);
30c682fe2dSDeepak Kodihalli             if (!statesSize)
31c682fe2dSDeepak Kodihalli             {
32c682fe2dSDeepak Kodihalli                 std::cerr << "Malformed PDR JSON return "
33c682fe2dSDeepak Kodihalli                              "pdrEntry;- no state set "
34c682fe2dSDeepak Kodihalli                              "info, TYPE="
35c682fe2dSDeepak Kodihalli                           << PLDM_STATE_EFFECTER_PDR << "\n";
36c682fe2dSDeepak Kodihalli                 throw InternalFailure();
37c682fe2dSDeepak Kodihalli             }
38c682fe2dSDeepak Kodihalli             pdrSize += sizeof(state_effecter_possible_states) -
39c682fe2dSDeepak Kodihalli                        sizeof(bitfield8_t) + (sizeof(bitfield8_t) * statesSize);
40c682fe2dSDeepak Kodihalli         }
41c682fe2dSDeepak Kodihalli         pdrSize += sizeof(pldm_state_effecter_pdr) - sizeof(uint8_t);
42c682fe2dSDeepak Kodihalli 
43c682fe2dSDeepak Kodihalli         std::vector<uint8_t> entry{};
44c682fe2dSDeepak Kodihalli         entry.resize(pdrSize);
45c682fe2dSDeepak Kodihalli 
46c682fe2dSDeepak Kodihalli         pldm_state_effecter_pdr* pdr =
47c682fe2dSDeepak Kodihalli             reinterpret_cast<pldm_state_effecter_pdr*>(entry.data());
48c682fe2dSDeepak Kodihalli         pdr->hdr.record_handle = 0;
49c682fe2dSDeepak Kodihalli         pdr->hdr.version = 1;
50c682fe2dSDeepak Kodihalli         pdr->hdr.type = PLDM_STATE_EFFECTER_PDR;
51c682fe2dSDeepak Kodihalli         pdr->hdr.record_change_num = 0;
52c682fe2dSDeepak Kodihalli         pdr->hdr.length = pdrSize - sizeof(pldm_pdr_hdr);
53c682fe2dSDeepak Kodihalli 
54c682fe2dSDeepak Kodihalli         pdr->terminus_handle = 0;
55c682fe2dSDeepak Kodihalli         pdr->effecter_id = this->getNextEffecterId();
56c682fe2dSDeepak Kodihalli         pdr->entity_type = e.value("type", 0);
57c682fe2dSDeepak Kodihalli         pdr->entity_instance = e.value("instance", 0);
58c682fe2dSDeepak Kodihalli         pdr->container_id = e.value("container", 0);
59c682fe2dSDeepak Kodihalli         pdr->effecter_semantic_id = 0;
60c682fe2dSDeepak Kodihalli         pdr->effecter_init = PLDM_NO_INIT;
61c682fe2dSDeepak Kodihalli         pdr->has_description_pdr = false;
62c682fe2dSDeepak Kodihalli         pdr->composite_effecter_count = effecters.size();
63c682fe2dSDeepak Kodihalli 
64c682fe2dSDeepak Kodihalli         EffecterObjs paths{};
65c682fe2dSDeepak Kodihalli         uint8_t* start =
66c682fe2dSDeepak Kodihalli             entry.data() + sizeof(pldm_state_effecter_pdr) - sizeof(uint8_t);
67c682fe2dSDeepak Kodihalli         for (const auto& effecter : effecters)
68c682fe2dSDeepak Kodihalli         {
69c682fe2dSDeepak Kodihalli             auto set = effecter.value("set", empty);
70c682fe2dSDeepak Kodihalli             state_effecter_possible_states* possibleStates =
71c682fe2dSDeepak Kodihalli                 reinterpret_cast<state_effecter_possible_states*>(start);
72c682fe2dSDeepak Kodihalli             possibleStates->state_set_id = set.value("id", 0);
73c682fe2dSDeepak Kodihalli             possibleStates->possible_states_size = set.value("size", 0);
74c682fe2dSDeepak Kodihalli 
75c682fe2dSDeepak Kodihalli             start += sizeof(possibleStates->state_set_id) +
76c682fe2dSDeepak Kodihalli                      sizeof(possibleStates->possible_states_size);
77c682fe2dSDeepak Kodihalli             static const std::vector<uint8_t> emptyStates{};
78c682fe2dSDeepak Kodihalli             auto states = set.value("states", emptyStates);
79c682fe2dSDeepak Kodihalli             for (const auto& state : states)
80c682fe2dSDeepak Kodihalli             {
81c682fe2dSDeepak Kodihalli                 auto index = state / 8;
82c682fe2dSDeepak Kodihalli                 auto bit = state - (index * 8);
83c682fe2dSDeepak Kodihalli                 bitfield8_t* bf = reinterpret_cast<bitfield8_t*>(start + index);
84c682fe2dSDeepak Kodihalli                 bf->byte |= 1 << bit;
85c682fe2dSDeepak Kodihalli             }
86c682fe2dSDeepak Kodihalli             start += possibleStates->possible_states_size;
87c682fe2dSDeepak Kodihalli 
88c682fe2dSDeepak Kodihalli             auto dbus = effecter.value("dbus", empty);
89c682fe2dSDeepak Kodihalli             paths.emplace_back(std::move(dbus));
90c682fe2dSDeepak Kodihalli         }
91c682fe2dSDeepak Kodihalli         addEffecterObjs(pdr->effecter_id, std::move(paths));
92c682fe2dSDeepak Kodihalli         PdrEntry pdrEntry{};
93c682fe2dSDeepak Kodihalli         pdrEntry.data = entry.data();
94c682fe2dSDeepak Kodihalli         pdrEntry.size = pdrSize;
95c682fe2dSDeepak Kodihalli         repo.addRecord(pdrEntry);
96c682fe2dSDeepak Kodihalli     }
97c682fe2dSDeepak Kodihalli }
98c682fe2dSDeepak Kodihalli 
99c682fe2dSDeepak Kodihalli void Handler::generate(const std::string& dir, Repo& repo)
100c682fe2dSDeepak Kodihalli {
101c682fe2dSDeepak Kodihalli     // A map of PDR type to a lambda that handles creation of that PDR type.
102c682fe2dSDeepak Kodihalli     // The lambda essentially would parse the platform specific PDR JSONs to
103c682fe2dSDeepak Kodihalli     // generate the PDR structures. This function iterates through the map to
104c682fe2dSDeepak Kodihalli     // invoke all lambdas, so that all PDR types can be created.
105c682fe2dSDeepak Kodihalli     const std::map<Type, std::function<void(const Json& json, Repo& repo)>>
106c682fe2dSDeepak Kodihalli         generators = {
107c682fe2dSDeepak Kodihalli             {PLDM_STATE_EFFECTER_PDR, [this](const auto& json, Repo& repo) {
108c682fe2dSDeepak Kodihalli                  generateStateEffecterRepo(json, repo);
109c682fe2dSDeepak Kodihalli              }}};
110c682fe2dSDeepak Kodihalli 
111c682fe2dSDeepak Kodihalli     Type pdrType{};
112c682fe2dSDeepak Kodihalli     for (const auto& dirEntry : fs::directory_iterator(dir))
113c682fe2dSDeepak Kodihalli     {
114c682fe2dSDeepak Kodihalli         try
115c682fe2dSDeepak Kodihalli         {
116c682fe2dSDeepak Kodihalli             auto json = readJson(dirEntry.path().string());
117c682fe2dSDeepak Kodihalli             if (!json.empty())
118c682fe2dSDeepak Kodihalli             {
119c682fe2dSDeepak Kodihalli                 pdrType = json.value("pdrType", 0);
120c682fe2dSDeepak Kodihalli                 generators.at(pdrType)(json, repo);
121c682fe2dSDeepak Kodihalli             }
122c682fe2dSDeepak Kodihalli         }
123c682fe2dSDeepak Kodihalli         catch (const InternalFailure& e)
124c682fe2dSDeepak Kodihalli         {
125c682fe2dSDeepak Kodihalli             std::cerr << "PDR config directory does not exist or empty, TYPE= "
126c682fe2dSDeepak Kodihalli                       << pdrType << "PATH= " << dirEntry
127c682fe2dSDeepak Kodihalli                       << " ERROR=" << e.what() << "\n";
128c682fe2dSDeepak Kodihalli         }
129c682fe2dSDeepak Kodihalli         catch (const Json::exception& e)
130c682fe2dSDeepak Kodihalli         {
131c682fe2dSDeepak Kodihalli             std::cerr << "Failed parsing PDR JSON file, TYPE= " << pdrType
132c682fe2dSDeepak Kodihalli                       << " ERROR=" << e.what() << "\n";
133c682fe2dSDeepak Kodihalli             pldm::utils::reportError(
134c682fe2dSDeepak Kodihalli                 "xyz.openbmc_project.bmc.pldm.InternalFailure");
135c682fe2dSDeepak Kodihalli         }
136c682fe2dSDeepak Kodihalli         catch (const std::exception& e)
137c682fe2dSDeepak Kodihalli         {
138c682fe2dSDeepak Kodihalli             std::cerr << "Failed parsing PDR JSON file, TYPE= " << pdrType
139c682fe2dSDeepak Kodihalli                       << " ERROR=" << e.what() << "\n";
140c682fe2dSDeepak Kodihalli             pldm::utils::reportError(
141c682fe2dSDeepak Kodihalli                 "xyz.openbmc_project.bmc.pldm.InternalFailure");
142c682fe2dSDeepak Kodihalli         }
143c682fe2dSDeepak Kodihalli     }
144c682fe2dSDeepak Kodihalli }
145557dfb00SDeepak Kodihalli 
146bc669f1bSDeepak Kodihalli Response Handler::getPDR(const pldm_msg* request, size_t payloadLength)
147557dfb00SDeepak Kodihalli {
148557dfb00SDeepak Kodihalli     Response response(sizeof(pldm_msg_hdr) + PLDM_GET_PDR_MIN_RESP_BYTES, 0);
149557dfb00SDeepak Kodihalli     auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
150557dfb00SDeepak Kodihalli 
151557dfb00SDeepak Kodihalli     if (payloadLength != PLDM_GET_PDR_REQ_BYTES)
152557dfb00SDeepak Kodihalli     {
153fb8611dcSGeorge Liu         return CmdHandler::ccOnlyResponse(request, PLDM_ERROR_INVALID_LENGTH);
154557dfb00SDeepak Kodihalli     }
155557dfb00SDeepak Kodihalli 
156557dfb00SDeepak Kodihalli     uint32_t recordHandle{};
157557dfb00SDeepak Kodihalli     uint32_t dataTransferHandle{};
158557dfb00SDeepak Kodihalli     uint8_t transferOpFlag{};
159557dfb00SDeepak Kodihalli     uint16_t reqSizeBytes{};
160557dfb00SDeepak Kodihalli     uint16_t recordChangeNum{};
161557dfb00SDeepak Kodihalli 
162fb8611dcSGeorge Liu     auto rc = decode_get_pdr_req(request, payloadLength, &recordHandle,
163fb8611dcSGeorge Liu                                  &dataTransferHandle, &transferOpFlag,
164fb8611dcSGeorge Liu                                  &reqSizeBytes, &recordChangeNum);
165fb8611dcSGeorge Liu     if (rc != PLDM_SUCCESS)
166fb8611dcSGeorge Liu     {
167fb8611dcSGeorge Liu         return CmdHandler::ccOnlyResponse(request, rc);
168fb8611dcSGeorge Liu     }
169557dfb00SDeepak Kodihalli 
170557dfb00SDeepak Kodihalli     uint16_t respSizeBytes{};
171557dfb00SDeepak Kodihalli     uint8_t* recordData = nullptr;
172557dfb00SDeepak Kodihalli     try
173557dfb00SDeepak Kodihalli     {
174e53193faSGeorge Liu         pdr_utils::PdrEntry e;
175e53193faSGeorge Liu         auto record = pdr::getRecordByHandle(pdrRepo, recordHandle, e);
176e53193faSGeorge Liu         if (record == NULL)
177e53193faSGeorge Liu         {
178e53193faSGeorge Liu             return CmdHandler::ccOnlyResponse(
179e53193faSGeorge Liu                 request, PLDM_PLATFORM_INVALID_RECORD_HANDLE);
180e53193faSGeorge Liu         }
181e53193faSGeorge Liu 
182557dfb00SDeepak Kodihalli         if (reqSizeBytes)
183557dfb00SDeepak Kodihalli         {
184e53193faSGeorge Liu             respSizeBytes = e.size;
185557dfb00SDeepak Kodihalli             if (respSizeBytes > reqSizeBytes)
186557dfb00SDeepak Kodihalli             {
187557dfb00SDeepak Kodihalli                 respSizeBytes = reqSizeBytes;
188557dfb00SDeepak Kodihalli             }
189e53193faSGeorge Liu             recordData = e.data;
190557dfb00SDeepak Kodihalli         }
191557dfb00SDeepak Kodihalli         response.resize(sizeof(pldm_msg_hdr) + PLDM_GET_PDR_MIN_RESP_BYTES +
192557dfb00SDeepak Kodihalli                             respSizeBytes,
193557dfb00SDeepak Kodihalli                         0);
194557dfb00SDeepak Kodihalli         responsePtr = reinterpret_cast<pldm_msg*>(response.data());
195*22b5a7d7SDeepak Kodihalli         rc = encode_get_pdr_resp(
196*22b5a7d7SDeepak Kodihalli             request->hdr.instance_id, PLDM_SUCCESS, e.handle.nextRecordHandle,
197*22b5a7d7SDeepak Kodihalli             0, PLDM_START_AND_END, respSizeBytes, recordData, 0, responsePtr);
198fb8611dcSGeorge Liu         if (rc != PLDM_SUCCESS)
199fb8611dcSGeorge Liu         {
200fb8611dcSGeorge Liu             return ccOnlyResponse(request, rc);
201fb8611dcSGeorge Liu         }
202557dfb00SDeepak Kodihalli     }
203557dfb00SDeepak Kodihalli     catch (const std::exception& e)
204557dfb00SDeepak Kodihalli     {
205aa8ae72fSSampa Misra         std::cerr << "Error accessing PDR, HANDLE=" << recordHandle
206aa8ae72fSSampa Misra                   << " ERROR=" << e.what() << "\n";
207fb8611dcSGeorge Liu         return CmdHandler::ccOnlyResponse(request, PLDM_ERROR);
208557dfb00SDeepak Kodihalli     }
209557dfb00SDeepak Kodihalli     return response;
210557dfb00SDeepak Kodihalli }
211557dfb00SDeepak Kodihalli 
212bc669f1bSDeepak Kodihalli Response Handler::setStateEffecterStates(const pldm_msg* request,
213bc669f1bSDeepak Kodihalli                                          size_t payloadLength)
214a2fa0709SSampa Misra {
215a2fa0709SSampa Misra     Response response(
216a2fa0709SSampa Misra         sizeof(pldm_msg_hdr) + PLDM_SET_STATE_EFFECTER_STATES_RESP_BYTES, 0);
217a2fa0709SSampa Misra     auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
218a2fa0709SSampa Misra     uint16_t effecterId;
219a2fa0709SSampa Misra     uint8_t compEffecterCnt;
220a2fa0709SSampa Misra     constexpr auto maxCompositeEffecterCnt = 8;
221a2fa0709SSampa Misra     std::vector<set_effecter_state_field> stateField(maxCompositeEffecterCnt,
222a2fa0709SSampa Misra                                                      {0, 0});
223a2fa0709SSampa Misra 
224a2fa0709SSampa Misra     if ((payloadLength > PLDM_SET_STATE_EFFECTER_STATES_REQ_BYTES) ||
225a2fa0709SSampa Misra         (payloadLength < sizeof(effecterId) + sizeof(compEffecterCnt) +
226a2fa0709SSampa Misra                              sizeof(set_effecter_state_field)))
227a2fa0709SSampa Misra     {
228fb8611dcSGeorge Liu         return CmdHandler::ccOnlyResponse(request, PLDM_ERROR_INVALID_LENGTH);
229a2fa0709SSampa Misra     }
230a2fa0709SSampa Misra 
231a2fa0709SSampa Misra     int rc = decode_set_state_effecter_states_req(request, payloadLength,
232a2fa0709SSampa Misra                                                   &effecterId, &compEffecterCnt,
233a2fa0709SSampa Misra                                                   stateField.data());
234a2fa0709SSampa Misra 
235fb8611dcSGeorge Liu     if (rc != PLDM_SUCCESS)
236a2fa0709SSampa Misra     {
237fb8611dcSGeorge Liu         return CmdHandler::ccOnlyResponse(request, rc);
238fb8611dcSGeorge Liu     }
23983409573SGeorge Liu 
240fb8611dcSGeorge Liu     stateField.resize(compEffecterCnt);
24183409573SGeorge Liu     const pldm::utils::DBusHandler dBusIntf;
24283409573SGeorge Liu     rc = setStateEffecterStatesHandler<pldm::utils::DBusHandler>(
24383409573SGeorge Liu         dBusIntf, effecterId, stateField);
244fb8611dcSGeorge Liu     if (rc != PLDM_SUCCESS)
245fb8611dcSGeorge Liu     {
246fb8611dcSGeorge Liu         return CmdHandler::ccOnlyResponse(request, rc);
247a2fa0709SSampa Misra     }
248a2fa0709SSampa Misra 
249fb8611dcSGeorge Liu     rc = encode_set_state_effecter_states_resp(request->hdr.instance_id, rc,
250a2fa0709SSampa Misra                                                responsePtr);
251fb8611dcSGeorge Liu     if (rc != PLDM_SUCCESS)
252fb8611dcSGeorge Liu     {
253fb8611dcSGeorge Liu         return ccOnlyResponse(request, rc);
254fb8611dcSGeorge Liu     }
255fb8611dcSGeorge Liu 
256a2fa0709SSampa Misra     return response;
257a2fa0709SSampa Misra }
258a2fa0709SSampa Misra 
259bc669f1bSDeepak Kodihalli } // namespace platform
260557dfb00SDeepak Kodihalli } // namespace responder
261557dfb00SDeepak Kodihalli } // namespace pldm
262