xref: /openbmc/openpower-vpd-parser/vpd-manager/include/utility/json_utility.hpp (revision ef069f7e2a9e5f41c4324305690b876c43a7e0ff)
1fa5e4d32SSunny Srivastava #pragma once
2fa5e4d32SSunny Srivastava 
3fa5e4d32SSunny Srivastava #include "event_logger.hpp"
4fa5e4d32SSunny Srivastava #include "exceptions.hpp"
5fa5e4d32SSunny Srivastava #include "logger.hpp"
6fa5e4d32SSunny Srivastava #include "types.hpp"
7fa5e4d32SSunny Srivastava 
8fa5e4d32SSunny Srivastava #include <gpiod.hpp>
9fa5e4d32SSunny Srivastava #include <nlohmann/json.hpp>
10fa5e4d32SSunny Srivastava #include <utility/common_utility.hpp>
11fa5e4d32SSunny Srivastava 
12fa5e4d32SSunny Srivastava #include <fstream>
13fa5e4d32SSunny Srivastava #include <type_traits>
14fa5e4d32SSunny Srivastava #include <unordered_map>
15fa5e4d32SSunny Srivastava 
16fa5e4d32SSunny Srivastava namespace vpd
17fa5e4d32SSunny Srivastava {
18fa5e4d32SSunny Srivastava namespace jsonUtility
19fa5e4d32SSunny Srivastava {
20fa5e4d32SSunny Srivastava 
21fa5e4d32SSunny Srivastava // forward declaration of API for function map.
22fa5e4d32SSunny Srivastava bool processSystemCmdTag(const nlohmann::json& i_parsedConfigJson,
23fa5e4d32SSunny Srivastava                          const std::string& i_vpdFilePath,
24fa5e4d32SSunny Srivastava                          const std::string& i_baseAction,
25fa5e4d32SSunny Srivastava                          const std::string& i_flagToProcess);
26fa5e4d32SSunny Srivastava 
27fa5e4d32SSunny Srivastava // forward declaration of API for function map.
28fa5e4d32SSunny Srivastava bool processGpioPresenceTag(
29fa5e4d32SSunny Srivastava     const nlohmann::json& i_parsedConfigJson, const std::string& i_vpdFilePath,
30fa5e4d32SSunny Srivastava     const std::string& i_baseAction, const std::string& i_flagToProcess);
31fa5e4d32SSunny Srivastava 
32fa5e4d32SSunny Srivastava // forward declaration of API for function map.
33fa5e4d32SSunny Srivastava bool procesSetGpioTag(const nlohmann::json& i_parsedConfigJson,
34fa5e4d32SSunny Srivastava                       const std::string& i_vpdFilePath,
35fa5e4d32SSunny Srivastava                       const std::string& i_baseAction,
36fa5e4d32SSunny Srivastava                       const std::string& i_flagToProcess);
37fa5e4d32SSunny Srivastava 
38fa5e4d32SSunny Srivastava // Function pointers to process tags from config JSON.
39fa5e4d32SSunny Srivastava typedef bool (*functionPtr)(
40fa5e4d32SSunny Srivastava     const nlohmann::json& i_parsedConfigJson, const std::string& i_vpdFilePath,
41fa5e4d32SSunny Srivastava     const std::string& i_baseAction, const std::string& i_flagToProcess);
42fa5e4d32SSunny Srivastava 
43fa5e4d32SSunny Srivastava inline std::unordered_map<std::string, functionPtr> funcionMap{
44fa5e4d32SSunny Srivastava     {"gpioPresence", processGpioPresenceTag},
45fa5e4d32SSunny Srivastava     {"setGpio", procesSetGpioTag},
46fa5e4d32SSunny Srivastava     {"systemCmd", processSystemCmdTag}};
47fa5e4d32SSunny Srivastava 
48fa5e4d32SSunny Srivastava /**
49fa5e4d32SSunny Srivastava  * @brief API to read VPD offset from JSON file.
50fa5e4d32SSunny Srivastava  *
51fa5e4d32SSunny Srivastava  * @param[in] i_sysCfgJsonObj - Parsed system config JSON object.
52fa5e4d32SSunny Srivastava  * @param[in] i_vpdFilePath - VPD file path.
53fa5e4d32SSunny Srivastava  * @return VPD offset if found in JSON, 0 otherwise.
54fa5e4d32SSunny Srivastava  */
getVPDOffset(const nlohmann::json & i_sysCfgJsonObj,const std::string & i_vpdFilePath)55fa5e4d32SSunny Srivastava inline size_t getVPDOffset(const nlohmann::json& i_sysCfgJsonObj,
56fa5e4d32SSunny Srivastava                            const std::string& i_vpdFilePath)
57fa5e4d32SSunny Srivastava {
58fa5e4d32SSunny Srivastava     if (i_vpdFilePath.empty() || (i_sysCfgJsonObj.empty()) ||
59fa5e4d32SSunny Srivastava         (!i_sysCfgJsonObj.contains("frus")))
60fa5e4d32SSunny Srivastava     {
61fa5e4d32SSunny Srivastava         return 0;
62fa5e4d32SSunny Srivastava     }
63fa5e4d32SSunny Srivastava 
64fa5e4d32SSunny Srivastava     if (i_sysCfgJsonObj["frus"].contains(i_vpdFilePath))
65fa5e4d32SSunny Srivastava     {
66fa5e4d32SSunny Srivastava         return i_sysCfgJsonObj["frus"][i_vpdFilePath].at(0).value("offset", 0);
67fa5e4d32SSunny Srivastava     }
68fa5e4d32SSunny Srivastava 
69fa5e4d32SSunny Srivastava     const nlohmann::json& l_fruList =
70fa5e4d32SSunny Srivastava         i_sysCfgJsonObj["frus"].get_ref<const nlohmann::json::object_t&>();
71fa5e4d32SSunny Srivastava 
72fa5e4d32SSunny Srivastava     for (const auto& l_fru : l_fruList.items())
73fa5e4d32SSunny Srivastava     {
74fa5e4d32SSunny Srivastava         const auto l_fruPath = l_fru.key();
75fa5e4d32SSunny Srivastava 
76fa5e4d32SSunny Srivastava         // check if given path is redundant FRU path
77fa5e4d32SSunny Srivastava         if (i_vpdFilePath == i_sysCfgJsonObj["frus"][l_fruPath].at(0).value(
78fa5e4d32SSunny Srivastava                                  "redundantEeprom", ""))
79fa5e4d32SSunny Srivastava         {
80fa5e4d32SSunny Srivastava             // Return the offset of redundant EEPROM taken from JSON.
81fa5e4d32SSunny Srivastava             return i_sysCfgJsonObj["frus"][l_fruPath].at(0).value("offset", 0);
82fa5e4d32SSunny Srivastava         }
83fa5e4d32SSunny Srivastava     }
84fa5e4d32SSunny Srivastava 
85fa5e4d32SSunny Srivastava     return 0;
86fa5e4d32SSunny Srivastava }
87fa5e4d32SSunny Srivastava 
88fa5e4d32SSunny Srivastava /**
89fa5e4d32SSunny Srivastava  * @brief API to parse respective JSON.
90fa5e4d32SSunny Srivastava  *
91fa5e4d32SSunny Srivastava  * @param[in] pathToJson - Path to JSON.
921ef21008SRekhaAparna01  * @return on success parsed JSON. On failure empty JSON object.
931ef21008SRekhaAparna01  *
941ef21008SRekhaAparna01  * Note: Caller has to handle it in case an empty JSON object is received.
95fa5e4d32SSunny Srivastava  */
getParsedJson(const std::string & pathToJson)961ef21008SRekhaAparna01 inline nlohmann::json getParsedJson(const std::string& pathToJson) noexcept
971ef21008SRekhaAparna01 {
981ef21008SRekhaAparna01     try
99fa5e4d32SSunny Srivastava     {
100fa5e4d32SSunny Srivastava         if (pathToJson.empty())
101fa5e4d32SSunny Srivastava         {
102fa5e4d32SSunny Srivastava             throw std::runtime_error("Path to JSON is missing");
103fa5e4d32SSunny Srivastava         }
104fa5e4d32SSunny Srivastava 
105fa5e4d32SSunny Srivastava         if (!std::filesystem::exists(pathToJson) ||
106fa5e4d32SSunny Srivastava             std::filesystem::is_empty(pathToJson))
107fa5e4d32SSunny Srivastava         {
1081ef21008SRekhaAparna01             throw std::runtime_error("Incorrect file Path or empty file");
109fa5e4d32SSunny Srivastava         }
110fa5e4d32SSunny Srivastava 
1111ef21008SRekhaAparna01         std::ifstream l_jsonFile(pathToJson);
1121ef21008SRekhaAparna01         if (!l_jsonFile)
113fa5e4d32SSunny Srivastava         {
1141ef21008SRekhaAparna01             throw std::runtime_error(
1151ef21008SRekhaAparna01                 "Failed to access Json path = " + pathToJson);
116fa5e4d32SSunny Srivastava         }
117fa5e4d32SSunny Srivastava 
1181ef21008SRekhaAparna01         return nlohmann::json::parse(l_jsonFile);
119fa5e4d32SSunny Srivastava     }
1201ef21008SRekhaAparna01     catch (const std::exception& l_ex)
121fa5e4d32SSunny Srivastava     {
1221ef21008SRekhaAparna01         logging::logMessage(
1231ef21008SRekhaAparna01             "Failed to parse JSON file, error: " + std::string(l_ex.what()));
124fa5e4d32SSunny Srivastava     }
1251ef21008SRekhaAparna01 
1261ef21008SRekhaAparna01     return nlohmann::json{};
127fa5e4d32SSunny Srivastava }
128fa5e4d32SSunny Srivastava 
129fa5e4d32SSunny Srivastava /**
130fa5e4d32SSunny Srivastava  * @brief Get inventory object path from system config JSON.
131fa5e4d32SSunny Srivastava  *
132fa5e4d32SSunny Srivastava  * Given either D-bus inventory path/FRU EEPROM path/redundant EEPROM path,
133fa5e4d32SSunny Srivastava  * this API returns D-bus inventory path if present in JSON.
134fa5e4d32SSunny Srivastava  *
135fa5e4d32SSunny Srivastava  * @param[in] i_sysCfgJsonObj - System config JSON object
136fa5e4d32SSunny Srivastava  * @param[in] i_vpdPath - Path to where VPD is stored.
137fa5e4d32SSunny Srivastava  *
138fa5e4d32SSunny Srivastava  * @return On success a valid path is returned, on failure an empty string is
1391ef21008SRekhaAparna01  * returned.
1401ef21008SRekhaAparna01  *
1411ef21008SRekhaAparna01  * Note: Caller has to handle it in case an empty string is received.
142fa5e4d32SSunny Srivastava  */
getInventoryObjPathFromJson(const nlohmann::json & i_sysCfgJsonObj,const std::string & i_vpdPath)143fa5e4d32SSunny Srivastava inline std::string getInventoryObjPathFromJson(
1441ef21008SRekhaAparna01     const nlohmann::json& i_sysCfgJsonObj,
1451ef21008SRekhaAparna01     const std::string& i_vpdPath) noexcept
1461ef21008SRekhaAparna01 {
1471ef21008SRekhaAparna01     try
148fa5e4d32SSunny Srivastava     {
149fa5e4d32SSunny Srivastava         if (i_vpdPath.empty())
150fa5e4d32SSunny Srivastava         {
151fa5e4d32SSunny Srivastava             throw std::runtime_error("Path parameter is empty.");
152fa5e4d32SSunny Srivastava         }
153fa5e4d32SSunny Srivastava 
154fa5e4d32SSunny Srivastava         if (!i_sysCfgJsonObj.contains("frus"))
155fa5e4d32SSunny Srivastava         {
156fa5e4d32SSunny Srivastava             throw std::runtime_error("Missing frus tag in system config JSON.");
157fa5e4d32SSunny Srivastava         }
158fa5e4d32SSunny Srivastava 
159fa5e4d32SSunny Srivastava         // check if given path is FRU path
160fa5e4d32SSunny Srivastava         if (i_sysCfgJsonObj["frus"].contains(i_vpdPath))
161fa5e4d32SSunny Srivastava         {
162fa5e4d32SSunny Srivastava             return i_sysCfgJsonObj["frus"][i_vpdPath].at(0).value(
163fa5e4d32SSunny Srivastava                 "inventoryPath", "");
164fa5e4d32SSunny Srivastava         }
165fa5e4d32SSunny Srivastava 
166fa5e4d32SSunny Srivastava         const nlohmann::json& l_fruList =
167fa5e4d32SSunny Srivastava             i_sysCfgJsonObj["frus"].get_ref<const nlohmann::json::object_t&>();
168fa5e4d32SSunny Srivastava 
169fa5e4d32SSunny Srivastava         for (const auto& l_fru : l_fruList.items())
170fa5e4d32SSunny Srivastava         {
171fa5e4d32SSunny Srivastava             const auto l_fruPath = l_fru.key();
172fa5e4d32SSunny Srivastava             const auto l_invObjPath =
1731ef21008SRekhaAparna01                 i_sysCfgJsonObj["frus"][l_fruPath].at(0).value("inventoryPath",
1741ef21008SRekhaAparna01                                                                "");
175fa5e4d32SSunny Srivastava 
176fa5e4d32SSunny Srivastava             // check if given path is redundant FRU path or inventory path
177fa5e4d32SSunny Srivastava             if (i_vpdPath == i_sysCfgJsonObj["frus"][l_fruPath].at(0).value(
178fa5e4d32SSunny Srivastava                                  "redundantEeprom", "") ||
179fa5e4d32SSunny Srivastava                 (i_vpdPath == l_invObjPath))
180fa5e4d32SSunny Srivastava             {
181fa5e4d32SSunny Srivastava                 return l_invObjPath;
182fa5e4d32SSunny Srivastava             }
183fa5e4d32SSunny Srivastava         }
1841ef21008SRekhaAparna01     }
1851ef21008SRekhaAparna01     catch (const std::exception& l_ex)
1861ef21008SRekhaAparna01     {
1871ef21008SRekhaAparna01         logging::logMessage(
1881ef21008SRekhaAparna01             "Failed to get inventory object path from json, error: " +
1891ef21008SRekhaAparna01             std::string(l_ex.what()));
1901ef21008SRekhaAparna01     }
1911ef21008SRekhaAparna01 
192fa5e4d32SSunny Srivastava     return std::string();
193fa5e4d32SSunny Srivastava }
194fa5e4d32SSunny Srivastava 
195fa5e4d32SSunny Srivastava /**
196fa5e4d32SSunny Srivastava  * @brief Process "PostFailAction" defined in config JSON.
197fa5e4d32SSunny Srivastava  *
198fa5e4d32SSunny Srivastava  * In case there is some error in the processing of "preAction" execution and a
199fa5e4d32SSunny Srivastava  * set of procedure needs to be done as a part of post fail action. This base
200fa5e4d32SSunny Srivastava  * action can be defined in the config JSON for that FRU and it will be handled
201fa5e4d32SSunny Srivastava  * under this API.
202fa5e4d32SSunny Srivastava  *
203fa5e4d32SSunny Srivastava  * @param[in] i_parsedConfigJson - config JSON
204fa5e4d32SSunny Srivastava  * @param[in] i_vpdFilePath - EEPROM file path
205fa5e4d32SSunny Srivastava  * @param[in] i_flagToProcess - To identify which flag(s) needs to be processed
206fa5e4d32SSunny Srivastava  * under PostFailAction tag of config JSON.
207fa5e4d32SSunny Srivastava  * @return - success or failure
208fa5e4d32SSunny Srivastava  */
executePostFailAction(const nlohmann::json & i_parsedConfigJson,const std::string & i_vpdFilePath,const std::string & i_flagToProcess)209fa5e4d32SSunny Srivastava inline bool executePostFailAction(const nlohmann::json& i_parsedConfigJson,
210fa5e4d32SSunny Srivastava                                   const std::string& i_vpdFilePath,
211fa5e4d32SSunny Srivastava                                   const std::string& i_flagToProcess)
212fa5e4d32SSunny Srivastava {
213c11e8b61SRekhaAparna01     try
214c11e8b61SRekhaAparna01     {
215fa5e4d32SSunny Srivastava         if (i_parsedConfigJson.empty() || i_vpdFilePath.empty() ||
216fa5e4d32SSunny Srivastava             i_flagToProcess.empty())
217fa5e4d32SSunny Srivastava         {
218c11e8b61SRekhaAparna01             throw std::runtime_error(
219fa5e4d32SSunny Srivastava                 "Invalid parameters. Abort processing for post fail action");
220fa5e4d32SSunny Srivastava         }
221fa5e4d32SSunny Srivastava 
2224c164381SSunny Srivastava         if (!(i_parsedConfigJson["frus"][i_vpdFilePath].at(0))["postFailAction"]
223fa5e4d32SSunny Srivastava                  .contains(i_flagToProcess))
224fa5e4d32SSunny Srivastava         {
225c11e8b61SRekhaAparna01             throw std::runtime_error(
226fa5e4d32SSunny Srivastava                 "Config JSON missing flag " + i_flagToProcess +
227fa5e4d32SSunny Srivastava                 " to execute post fail action for path = " + i_vpdFilePath);
228fa5e4d32SSunny Srivastava         }
229fa5e4d32SSunny Srivastava 
230fa5e4d32SSunny Srivastava         for (const auto& l_tags : (i_parsedConfigJson["frus"][i_vpdFilePath].at(
2314c164381SSunny Srivastava                  0))["postFailAction"][i_flagToProcess]
232fa5e4d32SSunny Srivastava                                       .items())
233fa5e4d32SSunny Srivastava         {
234fa5e4d32SSunny Srivastava             auto itrToFunction = funcionMap.find(l_tags.key());
235fa5e4d32SSunny Srivastava             if (itrToFunction != funcionMap.end())
236fa5e4d32SSunny Srivastava             {
237fa5e4d32SSunny Srivastava                 if (!itrToFunction->second(i_parsedConfigJson, i_vpdFilePath,
2384c164381SSunny Srivastava                                            "postFailAction", i_flagToProcess))
239fa5e4d32SSunny Srivastava                 {
240fa5e4d32SSunny Srivastava                     return false;
241fa5e4d32SSunny Srivastava                 }
242fa5e4d32SSunny Srivastava             }
243fa5e4d32SSunny Srivastava         }
244c11e8b61SRekhaAparna01     }
245c11e8b61SRekhaAparna01     catch (const std::exception& l_ex)
246c11e8b61SRekhaAparna01     {
247c11e8b61SRekhaAparna01         logging::logMessage("Execute post fail action failed. Error : " +
248c11e8b61SRekhaAparna01                             std::string(l_ex.what()));
249c11e8b61SRekhaAparna01         return false;
250c11e8b61SRekhaAparna01     }
251fa5e4d32SSunny Srivastava 
252fa5e4d32SSunny Srivastava     return true;
253fa5e4d32SSunny Srivastava }
254fa5e4d32SSunny Srivastava 
255fa5e4d32SSunny Srivastava /**
256fa5e4d32SSunny Srivastava  * @brief Process "systemCmd" tag for a given FRU.
257fa5e4d32SSunny Srivastava  *
258fa5e4d32SSunny Srivastava  * The API will process "systemCmd" tag if it is defined in the config
259fa5e4d32SSunny Srivastava  * JSON for the given FRU.
260fa5e4d32SSunny Srivastava  *
261fa5e4d32SSunny Srivastava  * @param[in] i_parsedConfigJson - config JSON
262fa5e4d32SSunny Srivastava  * @param[in] i_vpdFilePath - EEPROM file path
263fa5e4d32SSunny Srivastava  * @param[in] i_baseAction - Base action for which this tag has been called.
264fa5e4d32SSunny Srivastava  * @param[in] i_flagToProcess - Flag nested under the base action for which this
265fa5e4d32SSunny Srivastava  * tag has been called.
266fa5e4d32SSunny Srivastava  * @return Execution status.
267fa5e4d32SSunny Srivastava  */
processSystemCmdTag(const nlohmann::json & i_parsedConfigJson,const std::string & i_vpdFilePath,const std::string & i_baseAction,const std::string & i_flagToProcess)268fa5e4d32SSunny Srivastava inline bool processSystemCmdTag(
269fa5e4d32SSunny Srivastava     const nlohmann::json& i_parsedConfigJson, const std::string& i_vpdFilePath,
270fa5e4d32SSunny Srivastava     const std::string& i_baseAction, const std::string& i_flagToProcess)
271fa5e4d32SSunny Srivastava {
272c11e8b61SRekhaAparna01     try
273c11e8b61SRekhaAparna01     {
274fa5e4d32SSunny Srivastava         if (i_vpdFilePath.empty() || i_parsedConfigJson.empty() ||
275fa5e4d32SSunny Srivastava             i_baseAction.empty() || i_flagToProcess.empty())
276fa5e4d32SSunny Srivastava         {
277c11e8b61SRekhaAparna01             throw std::runtime_error(
278fa5e4d32SSunny Srivastava                 "Invalid parameter. Abort processing of processSystemCmd.");
279fa5e4d32SSunny Srivastava         }
280fa5e4d32SSunny Srivastava 
281fa5e4d32SSunny Srivastava         if (!((i_parsedConfigJson["frus"][i_vpdFilePath].at(
282fa5e4d32SSunny Srivastava                    0)[i_baseAction][i_flagToProcess]["systemCmd"])
283fa5e4d32SSunny Srivastava                   .contains("cmd")))
284fa5e4d32SSunny Srivastava         {
285c11e8b61SRekhaAparna01             throw std::runtime_error(
286fa5e4d32SSunny Srivastava                 "Config JSON missing required information to execute system command for EEPROM " +
287fa5e4d32SSunny Srivastava                 i_vpdFilePath);
288fa5e4d32SSunny Srivastava         }
289fa5e4d32SSunny Srivastava 
290fa5e4d32SSunny Srivastava         const std::string& l_systemCommand =
291fa5e4d32SSunny Srivastava             i_parsedConfigJson["frus"][i_vpdFilePath].at(
292fa5e4d32SSunny Srivastava                 0)[i_baseAction][i_flagToProcess]["systemCmd"]["cmd"];
293fa5e4d32SSunny Srivastava 
294fa5e4d32SSunny Srivastava         commonUtility::executeCmd(l_systemCommand);
295fa5e4d32SSunny Srivastava         return true;
296fa5e4d32SSunny Srivastava     }
297c11e8b61SRekhaAparna01     catch (const std::exception& l_ex)
298fa5e4d32SSunny Srivastava     {
299c11e8b61SRekhaAparna01         logging::logMessage("Process system command tag failed. Error : " +
300c11e8b61SRekhaAparna01                             std::string(l_ex.what()));
301fa5e4d32SSunny Srivastava         return false;
302fa5e4d32SSunny Srivastava     }
303fa5e4d32SSunny Srivastava }
304fa5e4d32SSunny Srivastava 
305fa5e4d32SSunny Srivastava /**
306fa5e4d32SSunny Srivastava  * @brief Checks for presence of a given FRU using GPIO line.
307fa5e4d32SSunny Srivastava  *
308fa5e4d32SSunny Srivastava  * This API returns the presence information of the FRU corresponding to the
309fa5e4d32SSunny Srivastava  * given VPD file path by setting the presence pin.
310fa5e4d32SSunny Srivastava  *
311fa5e4d32SSunny Srivastava  * @param[in] i_parsedConfigJson - config JSON
312fa5e4d32SSunny Srivastava  * @param[in] i_vpdFilePath - EEPROM file path
313fa5e4d32SSunny Srivastava  * @param[in] i_baseAction - Base action for which this tag has been called.
314fa5e4d32SSunny Srivastava  * @param[in] i_flagToProcess - Flag nested under the base action for which this
315fa5e4d32SSunny Srivastava  * tag has been called.
316fa5e4d32SSunny Srivastava  * @return Execution status.
317fa5e4d32SSunny Srivastava  */
processGpioPresenceTag(const nlohmann::json & i_parsedConfigJson,const std::string & i_vpdFilePath,const std::string & i_baseAction,const std::string & i_flagToProcess)318fa5e4d32SSunny Srivastava inline bool processGpioPresenceTag(
319fa5e4d32SSunny Srivastava     const nlohmann::json& i_parsedConfigJson, const std::string& i_vpdFilePath,
320fa5e4d32SSunny Srivastava     const std::string& i_baseAction, const std::string& i_flagToProcess)
321fa5e4d32SSunny Srivastava {
322fa5e4d32SSunny Srivastava     if (i_vpdFilePath.empty() || i_parsedConfigJson.empty() ||
323fa5e4d32SSunny Srivastava         i_baseAction.empty() || i_flagToProcess.empty())
324fa5e4d32SSunny Srivastava     {
325fa5e4d32SSunny Srivastava         logging::logMessage(
326fa5e4d32SSunny Srivastava             "Invalid parameter. Abort processing of processGpioPresence tag");
327fa5e4d32SSunny Srivastava         return false;
328fa5e4d32SSunny Srivastava     }
329fa5e4d32SSunny Srivastava 
330fa5e4d32SSunny Srivastava     if (!(((i_parsedConfigJson["frus"][i_vpdFilePath].at(
331fa5e4d32SSunny Srivastava                 0)[i_baseAction][i_flagToProcess]["gpioPresence"])
332fa5e4d32SSunny Srivastava                .contains("pin")) &&
333fa5e4d32SSunny Srivastava           ((i_parsedConfigJson["frus"][i_vpdFilePath].at(
334fa5e4d32SSunny Srivastava                 0)[i_baseAction][i_flagToProcess]["gpioPresence"])
335fa5e4d32SSunny Srivastava                .contains("value"))))
336fa5e4d32SSunny Srivastava     {
337fa5e4d32SSunny Srivastava         logging::logMessage(
338fa5e4d32SSunny Srivastava             "Config JSON missing required information to detect presence for EEPROM " +
339fa5e4d32SSunny Srivastava             i_vpdFilePath);
340fa5e4d32SSunny Srivastava 
341fa5e4d32SSunny Srivastava         return false;
342fa5e4d32SSunny Srivastava     }
343fa5e4d32SSunny Srivastava 
344fa5e4d32SSunny Srivastava     // get the pin name
345fa5e4d32SSunny Srivastava     const std::string& l_presencePinName =
346fa5e4d32SSunny Srivastava         i_parsedConfigJson["frus"][i_vpdFilePath].at(
347fa5e4d32SSunny Srivastava             0)[i_baseAction][i_flagToProcess]["gpioPresence"]["pin"];
348fa5e4d32SSunny Srivastava 
349fa5e4d32SSunny Srivastava     // get the pin value
350fa5e4d32SSunny Srivastava     uint8_t l_presencePinValue = i_parsedConfigJson["frus"][i_vpdFilePath].at(
351fa5e4d32SSunny Srivastava         0)[i_baseAction][i_flagToProcess]["gpioPresence"]["value"];
352fa5e4d32SSunny Srivastava 
353fa5e4d32SSunny Srivastava     try
354fa5e4d32SSunny Srivastava     {
355fa5e4d32SSunny Srivastava         gpiod::line l_presenceLine = gpiod::find_line(l_presencePinName);
356fa5e4d32SSunny Srivastava 
357fa5e4d32SSunny Srivastava         if (!l_presenceLine)
358fa5e4d32SSunny Srivastava         {
359fa5e4d32SSunny Srivastava             throw GpioException("Couldn't find the GPIO line.");
360fa5e4d32SSunny Srivastava         }
361fa5e4d32SSunny Srivastava 
362fa5e4d32SSunny Srivastava         l_presenceLine.request({"Read the presence line",
363fa5e4d32SSunny Srivastava                                 gpiod::line_request::DIRECTION_INPUT, 0});
364fa5e4d32SSunny Srivastava 
365fa5e4d32SSunny Srivastava         return (l_presencePinValue == l_presenceLine.get_value());
366fa5e4d32SSunny Srivastava     }
367fa5e4d32SSunny Srivastava     catch (const std::exception& ex)
368fa5e4d32SSunny Srivastava     {
369fa5e4d32SSunny Srivastava         std::string l_errMsg = "Exception on GPIO line: ";
370fa5e4d32SSunny Srivastava         l_errMsg += l_presencePinName;
371fa5e4d32SSunny Srivastava         l_errMsg += " Reason: ";
372fa5e4d32SSunny Srivastava         l_errMsg += ex.what();
373fa5e4d32SSunny Srivastava         l_errMsg += " File: " + i_vpdFilePath + " Pel Logged";
374fa5e4d32SSunny Srivastava 
375fa5e4d32SSunny Srivastava         // ToDo -- Update Internal Rc code.
376fa5e4d32SSunny Srivastava         EventLogger::createAsyncPelWithInventoryCallout(
377fa5e4d32SSunny Srivastava             types::ErrorType::GpioError, types::SeverityType::Informational,
378fa5e4d32SSunny Srivastava             {{getInventoryObjPathFromJson(i_parsedConfigJson, i_vpdFilePath),
379fa5e4d32SSunny Srivastava               types::CalloutPriority::High}},
380fa5e4d32SSunny Srivastava             std::source_location::current().file_name(),
381fa5e4d32SSunny Srivastava             std::source_location::current().function_name(), 0, l_errMsg,
382fa5e4d32SSunny Srivastava             std::nullopt, std::nullopt, std::nullopt, std::nullopt);
383fa5e4d32SSunny Srivastava 
384fa5e4d32SSunny Srivastava         logging::logMessage(l_errMsg);
385fa5e4d32SSunny Srivastava 
386fa5e4d32SSunny Srivastava         // Except when GPIO pin value is false, we go and try collecting the
387fa5e4d32SSunny Srivastava         // FRU VPD as we couldn't able to read GPIO pin value due to some
388fa5e4d32SSunny Srivastava         // error/exception. So returning true in error scenario.
389fa5e4d32SSunny Srivastava         return true;
390fa5e4d32SSunny Srivastava     }
391fa5e4d32SSunny Srivastava }
392fa5e4d32SSunny Srivastava 
393fa5e4d32SSunny Srivastava /**
394fa5e4d32SSunny Srivastava  * @brief Process "setGpio" tag for a given FRU.
395fa5e4d32SSunny Srivastava  *
396fa5e4d32SSunny Srivastava  * This API enables the GPIO line.
397fa5e4d32SSunny Srivastava  *
398fa5e4d32SSunny Srivastava  * @param[in] i_parsedConfigJson - config JSON
399fa5e4d32SSunny Srivastava  * @param[in] i_vpdFilePath - EEPROM file path
400fa5e4d32SSunny Srivastava  * @param[in] i_baseAction - Base action for which this tag has been called.
401fa5e4d32SSunny Srivastava  * @param[in] i_flagToProcess - Flag nested under the base action for which this
402fa5e4d32SSunny Srivastava  * tag has been called.
403fa5e4d32SSunny Srivastava  * @return Execution status.
404fa5e4d32SSunny Srivastava  */
procesSetGpioTag(const nlohmann::json & i_parsedConfigJson,const std::string & i_vpdFilePath,const std::string & i_baseAction,const std::string & i_flagToProcess)405fa5e4d32SSunny Srivastava inline bool procesSetGpioTag(
406fa5e4d32SSunny Srivastava     const nlohmann::json& i_parsedConfigJson, const std::string& i_vpdFilePath,
407fa5e4d32SSunny Srivastava     const std::string& i_baseAction, const std::string& i_flagToProcess)
408fa5e4d32SSunny Srivastava {
409fa5e4d32SSunny Srivastava     if (i_vpdFilePath.empty() || i_parsedConfigJson.empty() ||
410fa5e4d32SSunny Srivastava         i_baseAction.empty() || i_flagToProcess.empty())
411fa5e4d32SSunny Srivastava     {
412fa5e4d32SSunny Srivastava         logging::logMessage(
413fa5e4d32SSunny Srivastava             "Invalid parameter. Abort processing of procesSetGpio.");
414fa5e4d32SSunny Srivastava         return false;
415fa5e4d32SSunny Srivastava     }
416fa5e4d32SSunny Srivastava 
417fa5e4d32SSunny Srivastava     if (!(((i_parsedConfigJson["frus"][i_vpdFilePath].at(
418fa5e4d32SSunny Srivastava                 0)[i_baseAction][i_flagToProcess]["setGpio"])
419fa5e4d32SSunny Srivastava                .contains("pin")) &&
420fa5e4d32SSunny Srivastava           ((i_parsedConfigJson["frus"][i_vpdFilePath].at(
421fa5e4d32SSunny Srivastava                 0)[i_baseAction][i_flagToProcess]["setGpio"])
422fa5e4d32SSunny Srivastava                .contains("value"))))
423fa5e4d32SSunny Srivastava     {
424fa5e4d32SSunny Srivastava         logging::logMessage(
425fa5e4d32SSunny Srivastava             "Config JSON missing required information to set gpio line for EEPROM " +
426fa5e4d32SSunny Srivastava             i_vpdFilePath);
427fa5e4d32SSunny Srivastava 
428fa5e4d32SSunny Srivastava         return false;
429fa5e4d32SSunny Srivastava     }
430fa5e4d32SSunny Srivastava 
431fa5e4d32SSunny Srivastava     const std::string& l_pinName = i_parsedConfigJson["frus"][i_vpdFilePath].at(
432fa5e4d32SSunny Srivastava         0)[i_baseAction][i_flagToProcess]["setGpio"]["pin"];
433fa5e4d32SSunny Srivastava 
434fa5e4d32SSunny Srivastava     // Get the value to set
435fa5e4d32SSunny Srivastava     uint8_t l_pinValue = i_parsedConfigJson["frus"][i_vpdFilePath].at(
436fa5e4d32SSunny Srivastava         0)[i_baseAction][i_flagToProcess]["setGpio"]["value"];
437fa5e4d32SSunny Srivastava 
438fa5e4d32SSunny Srivastava     logging::logMessage(
439fa5e4d32SSunny Srivastava         "Setting GPIO: " + l_pinName + " to " + std::to_string(l_pinValue));
440fa5e4d32SSunny Srivastava     try
441fa5e4d32SSunny Srivastava     {
442fa5e4d32SSunny Srivastava         gpiod::line l_outputLine = gpiod::find_line(l_pinName);
443fa5e4d32SSunny Srivastava 
444fa5e4d32SSunny Srivastava         if (!l_outputLine)
445fa5e4d32SSunny Srivastava         {
446fa5e4d32SSunny Srivastava             throw GpioException("Couldn't find GPIO line.");
447fa5e4d32SSunny Srivastava         }
448fa5e4d32SSunny Srivastava 
449fa5e4d32SSunny Srivastava         l_outputLine.request(
450fa5e4d32SSunny Srivastava             {"FRU Action", ::gpiod::line_request::DIRECTION_OUTPUT, 0},
451fa5e4d32SSunny Srivastava             l_pinValue);
452fa5e4d32SSunny Srivastava         return true;
453fa5e4d32SSunny Srivastava     }
454fa5e4d32SSunny Srivastava     catch (const std::exception& ex)
455fa5e4d32SSunny Srivastava     {
456fa5e4d32SSunny Srivastava         std::string l_errMsg = "Exception on GPIO line: ";
457fa5e4d32SSunny Srivastava         l_errMsg += l_pinName;
458fa5e4d32SSunny Srivastava         l_errMsg += " Reason: ";
459fa5e4d32SSunny Srivastava         l_errMsg += ex.what();
460fa5e4d32SSunny Srivastava         l_errMsg += " File: " + i_vpdFilePath + " Pel Logged";
461fa5e4d32SSunny Srivastava 
462fa5e4d32SSunny Srivastava         // ToDo -- Update Internal RC code
463fa5e4d32SSunny Srivastava         EventLogger::createAsyncPelWithInventoryCallout(
464fa5e4d32SSunny Srivastava             types::ErrorType::GpioError, types::SeverityType::Informational,
465fa5e4d32SSunny Srivastava             {{getInventoryObjPathFromJson(i_parsedConfigJson, i_vpdFilePath),
466fa5e4d32SSunny Srivastava               types::CalloutPriority::High}},
467fa5e4d32SSunny Srivastava             std::source_location::current().file_name(),
468fa5e4d32SSunny Srivastava             std::source_location::current().function_name(), 0, l_errMsg,
469fa5e4d32SSunny Srivastava             std::nullopt, std::nullopt, std::nullopt, std::nullopt);
470fa5e4d32SSunny Srivastava 
471fa5e4d32SSunny Srivastava         logging::logMessage(l_errMsg);
472fa5e4d32SSunny Srivastava 
473fa5e4d32SSunny Srivastava         return false;
474fa5e4d32SSunny Srivastava     }
475fa5e4d32SSunny Srivastava }
476fa5e4d32SSunny Srivastava 
477fa5e4d32SSunny Srivastava /**
478fa5e4d32SSunny Srivastava  * @brief Process any action, if defined in config JSON.
479fa5e4d32SSunny Srivastava  *
480fa5e4d32SSunny Srivastava  * If any FRU(s) requires any special handling, then this base action can be
481fa5e4d32SSunny Srivastava  * defined for that FRU in the config JSON, processing of which will be handled
482fa5e4d32SSunny Srivastava  * in this API.
483fa5e4d32SSunny Srivastava  * Examples of action - preAction, PostAction etc.
484fa5e4d32SSunny Srivastava  *
485fa5e4d32SSunny Srivastava  * @param[in] i_parsedConfigJson - config JSON
486fa5e4d32SSunny Srivastava  * @param[in] i_action - Base action to be performed.
487fa5e4d32SSunny Srivastava  * @param[in] i_vpdFilePath - EEPROM file path
488fa5e4d32SSunny Srivastava  * @param[in] i_flagToProcess - To identify which flag(s) needs to be processed
489fa5e4d32SSunny Srivastava  * under PreAction tag of config JSON.
490fa5e4d32SSunny Srivastava  * @return - success or failure
491fa5e4d32SSunny Srivastava  */
executeBaseAction(const nlohmann::json & i_parsedConfigJson,const std::string & i_action,const std::string & i_vpdFilePath,const std::string & i_flagToProcess)492fa5e4d32SSunny Srivastava inline bool executeBaseAction(
493fa5e4d32SSunny Srivastava     const nlohmann::json& i_parsedConfigJson, const std::string& i_action,
494fa5e4d32SSunny Srivastava     const std::string& i_vpdFilePath, const std::string& i_flagToProcess)
495fa5e4d32SSunny Srivastava {
496fa5e4d32SSunny Srivastava     if (i_flagToProcess.empty() || i_action.empty() || i_vpdFilePath.empty() ||
497fa5e4d32SSunny Srivastava         !i_parsedConfigJson.contains("frus"))
498fa5e4d32SSunny Srivastava     {
499fa5e4d32SSunny Srivastava         logging::logMessage("Invalid parameter");
500fa5e4d32SSunny Srivastava         return false;
501fa5e4d32SSunny Srivastava     }
502fa5e4d32SSunny Srivastava 
503fa5e4d32SSunny Srivastava     if (!i_parsedConfigJson["frus"].contains(i_vpdFilePath))
504fa5e4d32SSunny Srivastava     {
505fa5e4d32SSunny Srivastava         logging::logMessage(
506fa5e4d32SSunny Srivastava             "File path: " + i_vpdFilePath + " not found in JSON");
507fa5e4d32SSunny Srivastava         return false;
508fa5e4d32SSunny Srivastava     }
509fa5e4d32SSunny Srivastava 
510fa5e4d32SSunny Srivastava     if (!i_parsedConfigJson["frus"][i_vpdFilePath].at(0).contains(i_action))
511fa5e4d32SSunny Srivastava     {
512fa5e4d32SSunny Srivastava         logging::logMessage("Action [" + i_action +
513fa5e4d32SSunny Srivastava                             "] not defined for file path:" + i_vpdFilePath);
514fa5e4d32SSunny Srivastava         return false;
515fa5e4d32SSunny Srivastava     }
516fa5e4d32SSunny Srivastava 
517fa5e4d32SSunny Srivastava     if (!(i_parsedConfigJson["frus"][i_vpdFilePath].at(0))[i_action].contains(
518fa5e4d32SSunny Srivastava             i_flagToProcess))
519fa5e4d32SSunny Srivastava     {
520fa5e4d32SSunny Srivastava         logging::logMessage("Config JSON missing flag [" + i_flagToProcess +
521fa5e4d32SSunny Srivastava                             "] to execute action for path = " + i_vpdFilePath);
522fa5e4d32SSunny Srivastava 
523fa5e4d32SSunny Srivastava         return false;
524fa5e4d32SSunny Srivastava     }
525fa5e4d32SSunny Srivastava 
526fa5e4d32SSunny Srivastava     const nlohmann::json& l_tagsJson =
527fa5e4d32SSunny Srivastava         (i_parsedConfigJson["frus"][i_vpdFilePath].at(
528fa5e4d32SSunny Srivastava             0))[i_action][i_flagToProcess];
529fa5e4d32SSunny Srivastava 
530fa5e4d32SSunny Srivastava     for (const auto& l_tag : l_tagsJson.items())
531fa5e4d32SSunny Srivastava     {
532fa5e4d32SSunny Srivastava         auto itrToFunction = funcionMap.find(l_tag.key());
533fa5e4d32SSunny Srivastava         if (itrToFunction != funcionMap.end())
534fa5e4d32SSunny Srivastava         {
535fa5e4d32SSunny Srivastava             if (!itrToFunction->second(i_parsedConfigJson, i_vpdFilePath,
536fa5e4d32SSunny Srivastava                                        i_action, i_flagToProcess))
537fa5e4d32SSunny Srivastava             {
538fa5e4d32SSunny Srivastava                 // In case any of the tag fails to execute. Mark action
539fa5e4d32SSunny Srivastava                 // as failed for that flag.
540fa5e4d32SSunny Srivastava                 return false;
541fa5e4d32SSunny Srivastava             }
542fa5e4d32SSunny Srivastava         }
543fa5e4d32SSunny Srivastava     }
544fa5e4d32SSunny Srivastava 
545fa5e4d32SSunny Srivastava     return true;
546fa5e4d32SSunny Srivastava }
547fa5e4d32SSunny Srivastava 
548fa5e4d32SSunny Srivastava /**
549fa5e4d32SSunny Srivastava  * @brief Get redundant FRU path from system config JSON
550fa5e4d32SSunny Srivastava  *
551fa5e4d32SSunny Srivastava  * Given either D-bus inventory path/FRU path/redundant FRU path, this
552fa5e4d32SSunny Srivastava  * API returns the redundant FRU path taken from "redundantEeprom" tag from
553fa5e4d32SSunny Srivastava  * system config JSON.
554fa5e4d32SSunny Srivastava  *
555fa5e4d32SSunny Srivastava  * @param[in] i_sysCfgJsonObj - System config JSON object.
556fa5e4d32SSunny Srivastava  * @param[in] i_vpdPath - Path to where VPD is stored.
557fa5e4d32SSunny Srivastava  *
558fa5e4d32SSunny Srivastava  * @throw std::runtime_error.
559fa5e4d32SSunny Srivastava  * @return On success return valid path, on failure return empty string.
560fa5e4d32SSunny Srivastava  */
getRedundantEepromPathFromJson(const nlohmann::json & i_sysCfgJsonObj,const std::string & i_vpdPath)561fa5e4d32SSunny Srivastava inline std::string getRedundantEepromPathFromJson(
562fa5e4d32SSunny Srivastava     const nlohmann::json& i_sysCfgJsonObj, const std::string& i_vpdPath)
563fa5e4d32SSunny Srivastava {
564fa5e4d32SSunny Srivastava     if (i_vpdPath.empty())
565fa5e4d32SSunny Srivastava     {
566fa5e4d32SSunny Srivastava         throw std::runtime_error("Path parameter is empty.");
567fa5e4d32SSunny Srivastava     }
568fa5e4d32SSunny Srivastava 
569fa5e4d32SSunny Srivastava     if (!i_sysCfgJsonObj.contains("frus"))
570fa5e4d32SSunny Srivastava     {
571fa5e4d32SSunny Srivastava         throw std::runtime_error("Missing frus tag in system config JSON.");
572fa5e4d32SSunny Srivastava     }
573fa5e4d32SSunny Srivastava 
574fa5e4d32SSunny Srivastava     // check if given path is FRU path
575fa5e4d32SSunny Srivastava     if (i_sysCfgJsonObj["frus"].contains(i_vpdPath))
576fa5e4d32SSunny Srivastava     {
577fa5e4d32SSunny Srivastava         return i_sysCfgJsonObj["frus"][i_vpdPath].at(0).value(
578fa5e4d32SSunny Srivastava             "redundantEeprom", "");
579fa5e4d32SSunny Srivastava     }
580fa5e4d32SSunny Srivastava 
581fa5e4d32SSunny Srivastava     const nlohmann::json& l_fruList =
582fa5e4d32SSunny Srivastava         i_sysCfgJsonObj["frus"].get_ref<const nlohmann::json::object_t&>();
583fa5e4d32SSunny Srivastava 
584fa5e4d32SSunny Srivastava     for (const auto& l_fru : l_fruList.items())
585fa5e4d32SSunny Srivastava     {
586fa5e4d32SSunny Srivastava         const std::string& l_fruPath = l_fru.key();
587fa5e4d32SSunny Srivastava         const std::string& l_redundantFruPath =
588fa5e4d32SSunny Srivastava             i_sysCfgJsonObj["frus"][l_fruPath].at(0).value("redundantEeprom",
589fa5e4d32SSunny Srivastava                                                            "");
590fa5e4d32SSunny Srivastava 
591fa5e4d32SSunny Srivastava         // check if given path is inventory path or redundant FRU path
592fa5e4d32SSunny Srivastava         if ((i_sysCfgJsonObj["frus"][l_fruPath].at(0).value("inventoryPath",
593fa5e4d32SSunny Srivastava                                                             "") == i_vpdPath) ||
594fa5e4d32SSunny Srivastava             (l_redundantFruPath == i_vpdPath))
595fa5e4d32SSunny Srivastava         {
596fa5e4d32SSunny Srivastava             return l_redundantFruPath;
597fa5e4d32SSunny Srivastava         }
598fa5e4d32SSunny Srivastava     }
599fa5e4d32SSunny Srivastava     return std::string();
600fa5e4d32SSunny Srivastava }
601fa5e4d32SSunny Srivastava 
602fa5e4d32SSunny Srivastava /**
603fa5e4d32SSunny Srivastava  * @brief Get FRU EEPROM path from system config JSON
604fa5e4d32SSunny Srivastava  *
605fa5e4d32SSunny Srivastava  * Given either D-bus inventory path/FRU EEPROM path/redundant EEPROM path,
606fa5e4d32SSunny Srivastava  * this API returns FRU EEPROM path if present in JSON.
607fa5e4d32SSunny Srivastava  *
608fa5e4d32SSunny Srivastava  * @param[in] i_sysCfgJsonObj - System config JSON object
609fa5e4d32SSunny Srivastava  * @param[in] i_vpdPath - Path to where VPD is stored.
610fa5e4d32SSunny Srivastava  *
611fa5e4d32SSunny Srivastava  * @throw std::runtime_error.
612fa5e4d32SSunny Srivastava  *
613fa5e4d32SSunny Srivastava  * @return On success return valid path, on failure return empty string.
614fa5e4d32SSunny Srivastava  */
getFruPathFromJson(const nlohmann::json & i_sysCfgJsonObj,const std::string & i_vpdPath)615fa5e4d32SSunny Srivastava inline std::string getFruPathFromJson(const nlohmann::json& i_sysCfgJsonObj,
616fa5e4d32SSunny Srivastava                                       const std::string& i_vpdPath)
617fa5e4d32SSunny Srivastava {
618fa5e4d32SSunny Srivastava     if (i_vpdPath.empty())
619fa5e4d32SSunny Srivastava     {
620fa5e4d32SSunny Srivastava         throw std::runtime_error("Path parameter is empty.");
621fa5e4d32SSunny Srivastava     }
622fa5e4d32SSunny Srivastava 
623fa5e4d32SSunny Srivastava     if (!i_sysCfgJsonObj.contains("frus"))
624fa5e4d32SSunny Srivastava     {
625fa5e4d32SSunny Srivastava         throw std::runtime_error("Missing frus tag in system config JSON.");
626fa5e4d32SSunny Srivastava     }
627fa5e4d32SSunny Srivastava 
628fa5e4d32SSunny Srivastava     // check if given path is FRU path
629fa5e4d32SSunny Srivastava     if (i_sysCfgJsonObj["frus"].contains(i_vpdPath))
630fa5e4d32SSunny Srivastava     {
631fa5e4d32SSunny Srivastava         return i_vpdPath;
632fa5e4d32SSunny Srivastava     }
633fa5e4d32SSunny Srivastava 
634fa5e4d32SSunny Srivastava     const nlohmann::json& l_fruList =
635fa5e4d32SSunny Srivastava         i_sysCfgJsonObj["frus"].get_ref<const nlohmann::json::object_t&>();
636fa5e4d32SSunny Srivastava 
637fa5e4d32SSunny Srivastava     for (const auto& l_fru : l_fruList.items())
638fa5e4d32SSunny Srivastava     {
639fa5e4d32SSunny Srivastava         const auto l_fruPath = l_fru.key();
640fa5e4d32SSunny Srivastava 
641fa5e4d32SSunny Srivastava         // check if given path is redundant FRU path or inventory path
642fa5e4d32SSunny Srivastava         if (i_vpdPath == i_sysCfgJsonObj["frus"][l_fruPath].at(0).value(
643fa5e4d32SSunny Srivastava                              "redundantEeprom", "") ||
644fa5e4d32SSunny Srivastava             (i_vpdPath == i_sysCfgJsonObj["frus"][l_fruPath].at(0).value(
645fa5e4d32SSunny Srivastava                               "inventoryPath", "")))
646fa5e4d32SSunny Srivastava         {
647fa5e4d32SSunny Srivastava             return l_fruPath;
648fa5e4d32SSunny Srivastava         }
649fa5e4d32SSunny Srivastava     }
650fa5e4d32SSunny Srivastava     return std::string();
651fa5e4d32SSunny Srivastava }
652fa5e4d32SSunny Srivastava 
653fa5e4d32SSunny Srivastava /**
654fa5e4d32SSunny Srivastava  * @brief An API to check backup and restore VPD is required.
655fa5e4d32SSunny Srivastava  *
656fa5e4d32SSunny Srivastava  * The API checks if there is provision for backup and restore mentioned in the
657fa5e4d32SSunny Srivastava  * system config JSON, by looking "backupRestoreConfigPath" tag.
658fa5e4d32SSunny Srivastava  * Checks if the path mentioned is a hardware path, by checking if the file path
659fa5e4d32SSunny Srivastava  * exists and size of contents in the path.
660fa5e4d32SSunny Srivastava  *
661fa5e4d32SSunny Srivastava  * @param[in] i_sysCfgJsonObj - System config JSON object.
662fa5e4d32SSunny Srivastava  *
663fa5e4d32SSunny Srivastava  * @return true if backup and restore is required, false otherwise.
664fa5e4d32SSunny Srivastava  */
isBackupAndRestoreRequired(const nlohmann::json & i_sysCfgJsonObj)665fa5e4d32SSunny Srivastava inline bool isBackupAndRestoreRequired(const nlohmann::json& i_sysCfgJsonObj)
666fa5e4d32SSunny Srivastava {
667fa5e4d32SSunny Srivastava     try
668fa5e4d32SSunny Srivastava     {
669fa5e4d32SSunny Srivastava         const std::string& l_backupAndRestoreCfgFilePath =
670fa5e4d32SSunny Srivastava             i_sysCfgJsonObj.value("backupRestoreConfigPath", "");
671fa5e4d32SSunny Srivastava         if (!l_backupAndRestoreCfgFilePath.empty() &&
672fa5e4d32SSunny Srivastava             std::filesystem::exists(l_backupAndRestoreCfgFilePath) &&
673fa5e4d32SSunny Srivastava             !std::filesystem::is_empty(l_backupAndRestoreCfgFilePath))
674fa5e4d32SSunny Srivastava         {
675fa5e4d32SSunny Srivastava             return true;
676fa5e4d32SSunny Srivastava         }
677fa5e4d32SSunny Srivastava     }
678fa5e4d32SSunny Srivastava     catch (std::exception& ex)
679fa5e4d32SSunny Srivastava     {
680fa5e4d32SSunny Srivastava         logging::logMessage(ex.what());
681fa5e4d32SSunny Srivastava     }
682fa5e4d32SSunny Srivastava     return false;
683fa5e4d32SSunny Srivastava }
684fa5e4d32SSunny Srivastava 
685fa5e4d32SSunny Srivastava /** @brief API to check if an action is required for given EEPROM path.
686fa5e4d32SSunny Srivastava  *
687fa5e4d32SSunny Srivastava  * System config JSON can contain pre-action, post-action etc. like actions
688fa5e4d32SSunny Srivastava  * defined for an EEPROM path. The API will check if any such action is defined
689fa5e4d32SSunny Srivastava  * for the EEPROM.
690fa5e4d32SSunny Srivastava  *
691fa5e4d32SSunny Srivastava  * @param[in] i_sysCfgJsonObj - System config JSON object.
692fa5e4d32SSunny Srivastava  * @param[in] i_vpdFruPath - EEPROM path.
693fa5e4d32SSunny Srivastava  * @param[in] i_action - Action to be checked.
694fa5e4d32SSunny Srivastava  * @param[in] i_flowFlag - Denotes the flow w.r.t which the action should be
695fa5e4d32SSunny Srivastava  * triggered.
696fa5e4d32SSunny Srivastava  * @return - True if action is defined for the flow, false otherwise.
697fa5e4d32SSunny Srivastava  */
isActionRequired(const nlohmann::json & i_sysCfgJsonObj,const std::string & i_vpdFruPath,const std::string & i_action,const std::string & i_flowFlag)698fa5e4d32SSunny Srivastava inline bool isActionRequired(
699fa5e4d32SSunny Srivastava     const nlohmann::json& i_sysCfgJsonObj, const std::string& i_vpdFruPath,
700fa5e4d32SSunny Srivastava     const std::string& i_action, const std::string& i_flowFlag)
701fa5e4d32SSunny Srivastava {
702fa5e4d32SSunny Srivastava     if (i_vpdFruPath.empty() || i_action.empty() || i_flowFlag.empty())
703fa5e4d32SSunny Srivastava     {
704fa5e4d32SSunny Srivastava         logging::logMessage("Invalid parameters recieved.");
705fa5e4d32SSunny Srivastava         return false;
706fa5e4d32SSunny Srivastava     }
707fa5e4d32SSunny Srivastava 
708fa5e4d32SSunny Srivastava     if (!i_sysCfgJsonObj.contains("frus"))
709fa5e4d32SSunny Srivastava     {
710fa5e4d32SSunny Srivastava         logging::logMessage("Invalid JSON object recieved.");
711fa5e4d32SSunny Srivastava         return false;
712fa5e4d32SSunny Srivastava     }
713fa5e4d32SSunny Srivastava 
714fa5e4d32SSunny Srivastava     if (!i_sysCfgJsonObj["frus"].contains(i_vpdFruPath))
715fa5e4d32SSunny Srivastava     {
716fa5e4d32SSunny Srivastava         logging::logMessage(
717fa5e4d32SSunny Srivastava             "JSON object does not contain EEPROM path " + i_vpdFruPath);
718fa5e4d32SSunny Srivastava         return false;
719fa5e4d32SSunny Srivastava     }
720fa5e4d32SSunny Srivastava 
721fa5e4d32SSunny Srivastava     if ((i_sysCfgJsonObj["frus"][i_vpdFruPath].at(0)).contains(i_action))
722fa5e4d32SSunny Srivastava     {
723fa5e4d32SSunny Srivastava         if ((i_sysCfgJsonObj["frus"][i_vpdFruPath].at(0))[i_action].contains(
724fa5e4d32SSunny Srivastava                 i_flowFlag))
725fa5e4d32SSunny Srivastava         {
726fa5e4d32SSunny Srivastava             return true;
727fa5e4d32SSunny Srivastava         }
728fa5e4d32SSunny Srivastava 
729fa5e4d32SSunny Srivastava         logging::logMessage("Flow flag: [" + i_flowFlag +
730fa5e4d32SSunny Srivastava                             "], not found in JSON for path: " + i_vpdFruPath);
731fa5e4d32SSunny Srivastava         return false;
732fa5e4d32SSunny Srivastava     }
733fa5e4d32SSunny Srivastava     return false;
734fa5e4d32SSunny Srivastava }
735fa5e4d32SSunny Srivastava 
736fa5e4d32SSunny Srivastava /**
737fa5e4d32SSunny Srivastava  * @brief An API to return list of FRUs that needs GPIO polling.
738fa5e4d32SSunny Srivastava  *
739fa5e4d32SSunny Srivastava  * An API that checks for the FRUs that requires GPIO polling and returns
740fa5e4d32SSunny Srivastava  * a list of FRUs that needs polling. Returns an empty list if there are
741fa5e4d32SSunny Srivastava  * no FRUs that requires polling.
742fa5e4d32SSunny Srivastava  *
743fa5e4d32SSunny Srivastava  * @throw std::runtime_error
744fa5e4d32SSunny Srivastava  *
745fa5e4d32SSunny Srivastava  * @param[in] i_sysCfgJsonObj - System config JSON object.
746fa5e4d32SSunny Srivastava  *
747fa5e4d32SSunny Srivastava  * @return list of FRUs parameters that needs polling.
748fa5e4d32SSunny Srivastava  */
getListOfGpioPollingFrus(const nlohmann::json & i_sysCfgJsonObj)74943fedabcSPatrick Williams inline std::vector<std::string> getListOfGpioPollingFrus(
75043fedabcSPatrick Williams     const nlohmann::json& i_sysCfgJsonObj)
751fa5e4d32SSunny Srivastava {
752fa5e4d32SSunny Srivastava     if (i_sysCfgJsonObj.empty())
753fa5e4d32SSunny Srivastava     {
754fa5e4d32SSunny Srivastava         throw std::runtime_error("Invalid Parameters");
755fa5e4d32SSunny Srivastava     }
756fa5e4d32SSunny Srivastava 
757fa5e4d32SSunny Srivastava     if (!i_sysCfgJsonObj.contains("frus"))
758fa5e4d32SSunny Srivastava     {
759fa5e4d32SSunny Srivastava         throw std::runtime_error("Missing frus section in system config JSON");
760fa5e4d32SSunny Srivastava     }
761fa5e4d32SSunny Srivastava 
762fa5e4d32SSunny Srivastava     std::vector<std::string> l_gpioPollingRequiredFrusList;
763fa5e4d32SSunny Srivastava 
764fa5e4d32SSunny Srivastava     for (const auto& l_fru : i_sysCfgJsonObj["frus"].items())
765fa5e4d32SSunny Srivastava     {
766fa5e4d32SSunny Srivastava         const auto l_fruPath = l_fru.key();
767fa5e4d32SSunny Srivastava 
768fa5e4d32SSunny Srivastava         try
769fa5e4d32SSunny Srivastava         {
770fa5e4d32SSunny Srivastava             if (isActionRequired(i_sysCfgJsonObj, l_fruPath, "pollingRequired",
771fa5e4d32SSunny Srivastava                                  "hotPlugging"))
772fa5e4d32SSunny Srivastava             {
773fa5e4d32SSunny Srivastava                 if (i_sysCfgJsonObj["frus"][l_fruPath]
774fa5e4d32SSunny Srivastava                         .at(0)["pollingRequired"]["hotPlugging"]
775fa5e4d32SSunny Srivastava                         .contains("gpioPresence"))
776fa5e4d32SSunny Srivastava                 {
777fa5e4d32SSunny Srivastava                     l_gpioPollingRequiredFrusList.push_back(l_fruPath);
778fa5e4d32SSunny Srivastava                 }
779fa5e4d32SSunny Srivastava             }
780fa5e4d32SSunny Srivastava         }
781fa5e4d32SSunny Srivastava         catch (const std::exception& l_ex)
782fa5e4d32SSunny Srivastava         {
783fa5e4d32SSunny Srivastava             logging::logMessage(l_ex.what());
784fa5e4d32SSunny Srivastava         }
785fa5e4d32SSunny Srivastava     }
786fa5e4d32SSunny Srivastava 
787fa5e4d32SSunny Srivastava     return l_gpioPollingRequiredFrusList;
788fa5e4d32SSunny Srivastava }
789fa5e4d32SSunny Srivastava 
790fa5e4d32SSunny Srivastava /**
791fa5e4d32SSunny Srivastava  * @brief Get all related path(s) to update keyword value.
792fa5e4d32SSunny Srivastava  *
793fa5e4d32SSunny Srivastava  * Given FRU EEPROM path/Inventory path needs keyword's value update, this API
794fa5e4d32SSunny Srivastava  * returns tuple of FRU EEPROM path, inventory path and redundant EEPROM path if
795fa5e4d32SSunny Srivastava  * exists in the system config JSON.
796fa5e4d32SSunny Srivastava  *
797fa5e4d32SSunny Srivastava  * Note: If the inventory object path or redundant EEPROM path(s) are not found
798fa5e4d32SSunny Srivastava  * in the system config JSON, corresponding fields will have empty value in the
799fa5e4d32SSunny Srivastava  * returning tuple.
800fa5e4d32SSunny Srivastava  *
801fa5e4d32SSunny Srivastava  * @param[in] i_sysCfgJsonObj - System config JSON object.
802fa5e4d32SSunny Srivastava  * @param[in,out] io_vpdPath - Inventory object path or FRU EEPROM path.
803fa5e4d32SSunny Srivastava  *
804fa5e4d32SSunny Srivastava  * @return On success returns tuple of EEPROM path, inventory path & redundant
805fa5e4d32SSunny Srivastava  * path, on failure returns tuple with given input path alone.
806fa5e4d32SSunny Srivastava  */
807fa5e4d32SSunny Srivastava inline std::tuple<std::string, std::string, std::string>
getAllPathsToUpdateKeyword(const nlohmann::json & i_sysCfgJsonObj,std::string io_vpdPath)808fa5e4d32SSunny Srivastava     getAllPathsToUpdateKeyword(const nlohmann::json& i_sysCfgJsonObj,
809fa5e4d32SSunny Srivastava                                std::string io_vpdPath)
810fa5e4d32SSunny Srivastava {
811fa5e4d32SSunny Srivastava     types::Path l_inventoryObjPath;
812fa5e4d32SSunny Srivastava     types::Path l_redundantFruPath;
813fa5e4d32SSunny Srivastava     try
814fa5e4d32SSunny Srivastava     {
815fa5e4d32SSunny Srivastava         if (!i_sysCfgJsonObj.empty())
816fa5e4d32SSunny Srivastava         {
817fa5e4d32SSunny Srivastava             // Get hardware path from system config JSON.
818fa5e4d32SSunny Srivastava             const types::Path l_fruPath =
819fa5e4d32SSunny Srivastava                 jsonUtility::getFruPathFromJson(i_sysCfgJsonObj, io_vpdPath);
820fa5e4d32SSunny Srivastava 
821fa5e4d32SSunny Srivastava             if (!l_fruPath.empty())
822fa5e4d32SSunny Srivastava             {
823fa5e4d32SSunny Srivastava                 io_vpdPath = l_fruPath;
824fa5e4d32SSunny Srivastava 
825fa5e4d32SSunny Srivastava                 // Get inventory object path from system config JSON
826fa5e4d32SSunny Srivastava                 l_inventoryObjPath = jsonUtility::getInventoryObjPathFromJson(
827fa5e4d32SSunny Srivastava                     i_sysCfgJsonObj, l_fruPath);
828fa5e4d32SSunny Srivastava 
829fa5e4d32SSunny Srivastava                 // Get redundant hardware path if present in system config JSON
830fa5e4d32SSunny Srivastava                 l_redundantFruPath =
831fa5e4d32SSunny Srivastava                     jsonUtility::getRedundantEepromPathFromJson(i_sysCfgJsonObj,
832fa5e4d32SSunny Srivastava                                                                 l_fruPath);
833fa5e4d32SSunny Srivastava             }
834fa5e4d32SSunny Srivastava         }
835fa5e4d32SSunny Srivastava     }
836fa5e4d32SSunny Srivastava     catch (const std::exception& l_exception)
837fa5e4d32SSunny Srivastava     {
838fa5e4d32SSunny Srivastava         logging::logMessage(
839fa5e4d32SSunny Srivastava             "Failed to get all paths to update keyword value, error " +
840fa5e4d32SSunny Srivastava             std::string(l_exception.what()));
841fa5e4d32SSunny Srivastava     }
842fa5e4d32SSunny Srivastava     return std::make_tuple(io_vpdPath, l_inventoryObjPath, l_redundantFruPath);
843fa5e4d32SSunny Srivastava }
844fa5e4d32SSunny Srivastava 
845fa5e4d32SSunny Srivastava /**
846fa5e4d32SSunny Srivastava  * @brief An API to get DBus service name.
847fa5e4d32SSunny Srivastava  *
848fa5e4d32SSunny Srivastava  * Given DBus inventory path, this API returns DBus service name if present in
849fa5e4d32SSunny Srivastava  * the JSON.
850fa5e4d32SSunny Srivastava  *
851fa5e4d32SSunny Srivastava  * @param[in] i_sysCfgJsonObj - System config JSON object.
852fa5e4d32SSunny Srivastava  * @param[in] l_inventoryPath - DBus inventory path.
853fa5e4d32SSunny Srivastava  *
854fa5e4d32SSunny Srivastava  * @return On success returns the service name present in the system config
855fa5e4d32SSunny Srivastava  * JSON, otherwise empty string.
856fa5e4d32SSunny Srivastava  *
857fa5e4d32SSunny Srivastava  * Note: Caller has to handle in case of empty string received.
858fa5e4d32SSunny Srivastava  */
getServiceName(const nlohmann::json & i_sysCfgJsonObj,const std::string & l_inventoryPath)859fa5e4d32SSunny Srivastava inline std::string getServiceName(const nlohmann::json& i_sysCfgJsonObj,
860fa5e4d32SSunny Srivastava                                   const std::string& l_inventoryPath)
861fa5e4d32SSunny Srivastava {
862fa5e4d32SSunny Srivastava     try
863fa5e4d32SSunny Srivastava     {
864fa5e4d32SSunny Srivastava         if (l_inventoryPath.empty())
865fa5e4d32SSunny Srivastava         {
866fa5e4d32SSunny Srivastava             throw std::runtime_error("Path parameter is empty.");
867fa5e4d32SSunny Srivastava         }
868fa5e4d32SSunny Srivastava 
869fa5e4d32SSunny Srivastava         if (!i_sysCfgJsonObj.contains("frus"))
870fa5e4d32SSunny Srivastava         {
871fa5e4d32SSunny Srivastava             throw std::runtime_error("Missing frus tag in system config JSON.");
872fa5e4d32SSunny Srivastava         }
873fa5e4d32SSunny Srivastava 
874fa5e4d32SSunny Srivastava         const nlohmann::json& l_listOfFrus =
875fa5e4d32SSunny Srivastava             i_sysCfgJsonObj["frus"].get_ref<const nlohmann::json::object_t&>();
876fa5e4d32SSunny Srivastava 
877fa5e4d32SSunny Srivastava         for (const auto& l_frus : l_listOfFrus.items())
878fa5e4d32SSunny Srivastava         {
879fa5e4d32SSunny Srivastava             for (const auto& l_inventoryItem : l_frus.value())
880fa5e4d32SSunny Srivastava             {
881fa5e4d32SSunny Srivastava                 if (l_inventoryPath.compare(l_inventoryItem["inventoryPath"]) ==
882fa5e4d32SSunny Srivastava                     constants::STR_CMP_SUCCESS)
883fa5e4d32SSunny Srivastava                 {
884fa5e4d32SSunny Srivastava                     return l_inventoryItem["serviceName"];
885fa5e4d32SSunny Srivastava                 }
886fa5e4d32SSunny Srivastava             }
887fa5e4d32SSunny Srivastava         }
888fa5e4d32SSunny Srivastava         throw std::runtime_error(
889fa5e4d32SSunny Srivastava             "Inventory path not found in the system config JSON");
890fa5e4d32SSunny Srivastava     }
891fa5e4d32SSunny Srivastava     catch (const std::exception& l_exception)
892fa5e4d32SSunny Srivastava     {
893fa5e4d32SSunny Srivastava         logging::logMessage(
894fa5e4d32SSunny Srivastava             "Error while getting DBus service name for given path " +
895fa5e4d32SSunny Srivastava             l_inventoryPath + ", error: " + std::string(l_exception.what()));
896fa5e4d32SSunny Srivastava         // TODO:log PEL
897fa5e4d32SSunny Srivastava     }
898fa5e4d32SSunny Srivastava     return std::string{};
899fa5e4d32SSunny Srivastava }
900fa5e4d32SSunny Srivastava 
901fa5e4d32SSunny Srivastava /**
902fa5e4d32SSunny Srivastava  * @brief An API to check if a FRU is tagged as "powerOffOnly"
903fa5e4d32SSunny Srivastava  *
904fa5e4d32SSunny Srivastava  * Given the system config JSON and VPD FRU path, this API checks if the FRU
905fa5e4d32SSunny Srivastava  * VPD can be collected at Chassis Power Off state only.
906fa5e4d32SSunny Srivastava  *
907fa5e4d32SSunny Srivastava  * @param[in] i_sysCfgJsonObj - System config JSON object.
908fa5e4d32SSunny Srivastava  * @param[in] i_vpdFruPath - EEPROM path.
909fa5e4d32SSunny Srivastava  * @return - True if FRU VPD can be collected at Chassis Power Off state only.
910fa5e4d32SSunny Srivastava  *           False otherwise
911fa5e4d32SSunny Srivastava  */
isFruPowerOffOnly(const nlohmann::json & i_sysCfgJsonObj,const std::string & i_vpdFruPath)912fa5e4d32SSunny Srivastava inline bool isFruPowerOffOnly(const nlohmann::json& i_sysCfgJsonObj,
913fa5e4d32SSunny Srivastava                               const std::string& i_vpdFruPath)
914fa5e4d32SSunny Srivastava {
915fa5e4d32SSunny Srivastava     if (i_vpdFruPath.empty())
916fa5e4d32SSunny Srivastava     {
917fa5e4d32SSunny Srivastava         logging::logMessage("FRU path is empty.");
918fa5e4d32SSunny Srivastava         return false;
919fa5e4d32SSunny Srivastava     }
920fa5e4d32SSunny Srivastava 
921fa5e4d32SSunny Srivastava     if (!i_sysCfgJsonObj.contains("frus"))
922fa5e4d32SSunny Srivastava     {
923fa5e4d32SSunny Srivastava         logging::logMessage("Missing frus tag in system config JSON.");
924fa5e4d32SSunny Srivastava         return false;
925fa5e4d32SSunny Srivastava     }
926fa5e4d32SSunny Srivastava 
927fa5e4d32SSunny Srivastava     if (!i_sysCfgJsonObj["frus"].contains(i_vpdFruPath))
928fa5e4d32SSunny Srivastava     {
929fa5e4d32SSunny Srivastava         logging::logMessage("JSON object does not contain EEPROM path \'" +
930fa5e4d32SSunny Srivastava                             i_vpdFruPath + "\'");
931fa5e4d32SSunny Srivastava         return false;
932fa5e4d32SSunny Srivastava     }
933fa5e4d32SSunny Srivastava 
934fa5e4d32SSunny Srivastava     return ((i_sysCfgJsonObj["frus"][i_vpdFruPath].at(0))
935fa5e4d32SSunny Srivastava                 .contains("powerOffOnly") &&
936fa5e4d32SSunny Srivastava             (i_sysCfgJsonObj["frus"][i_vpdFruPath].at(0)["powerOffOnly"]));
937fa5e4d32SSunny Srivastava }
938fa5e4d32SSunny Srivastava 
939fa5e4d32SSunny Srivastava /**
940fa5e4d32SSunny Srivastava  * @brief API which tells if the FRU is replaceable at runtime
941fa5e4d32SSunny Srivastava  *
942fa5e4d32SSunny Srivastava  * @param[in] i_sysCfgJsonObj - System config JSON object.
943fa5e4d32SSunny Srivastava  * @param[in] i_vpdFruPath - EEPROM path.
944fa5e4d32SSunny Srivastava  *
945fa5e4d32SSunny Srivastava  * @return true if FRU is replaceable at runtime. false otherwise.
946fa5e4d32SSunny Srivastava  */
isFruReplaceableAtRuntime(const nlohmann::json & i_sysCfgJsonObj,const std::string & i_vpdFruPath)947fa5e4d32SSunny Srivastava inline bool isFruReplaceableAtRuntime(const nlohmann::json& i_sysCfgJsonObj,
948fa5e4d32SSunny Srivastava                                       const std::string& i_vpdFruPath)
949fa5e4d32SSunny Srivastava {
950fa5e4d32SSunny Srivastava     try
951fa5e4d32SSunny Srivastava     {
952fa5e4d32SSunny Srivastava         if (i_vpdFruPath.empty())
953fa5e4d32SSunny Srivastava         {
954fa5e4d32SSunny Srivastava             throw std::runtime_error("Given FRU path is empty.");
955fa5e4d32SSunny Srivastava         }
956fa5e4d32SSunny Srivastava 
957fa5e4d32SSunny Srivastava         if (i_sysCfgJsonObj.empty() || (!i_sysCfgJsonObj.contains("frus")))
958fa5e4d32SSunny Srivastava         {
959fa5e4d32SSunny Srivastava             throw std::runtime_error("Invalid system config JSON object.");
960fa5e4d32SSunny Srivastava         }
961fa5e4d32SSunny Srivastava 
962fa5e4d32SSunny Srivastava         return ((i_sysCfgJsonObj["frus"][i_vpdFruPath].at(0))
963fa5e4d32SSunny Srivastava                     .contains("replaceableAtRuntime") &&
964fa5e4d32SSunny Srivastava                 (i_sysCfgJsonObj["frus"][i_vpdFruPath].at(
965fa5e4d32SSunny Srivastava                     0)["replaceableAtRuntime"]));
966fa5e4d32SSunny Srivastava     }
967fa5e4d32SSunny Srivastava     catch (const std::exception& l_error)
968fa5e4d32SSunny Srivastava     {
969fa5e4d32SSunny Srivastava         // TODO: Log PEL
970fa5e4d32SSunny Srivastava         logging::logMessage(l_error.what());
971fa5e4d32SSunny Srivastava     }
972fa5e4d32SSunny Srivastava 
973fa5e4d32SSunny Srivastava     return false;
974fa5e4d32SSunny Srivastava }
975fa5e4d32SSunny Srivastava 
976fa5e4d32SSunny Srivastava /**
977fa5e4d32SSunny Srivastava  * @brief API which tells if the FRU is replaceable at standby
978fa5e4d32SSunny Srivastava  *
979fa5e4d32SSunny Srivastava  * @param[in] i_sysCfgJsonObj - System config JSON object.
980fa5e4d32SSunny Srivastava  * @param[in] i_vpdFruPath - EEPROM path.
981fa5e4d32SSunny Srivastava  *
982fa5e4d32SSunny Srivastava  * @return true if FRU is replaceable at standby. false otherwise.
983fa5e4d32SSunny Srivastava  */
isFruReplaceableAtStandby(const nlohmann::json & i_sysCfgJsonObj,const std::string & i_vpdFruPath)984fa5e4d32SSunny Srivastava inline bool isFruReplaceableAtStandby(const nlohmann::json& i_sysCfgJsonObj,
985fa5e4d32SSunny Srivastava                                       const std::string& i_vpdFruPath)
986fa5e4d32SSunny Srivastava {
987fa5e4d32SSunny Srivastava     try
988fa5e4d32SSunny Srivastava     {
989fa5e4d32SSunny Srivastava         if (i_vpdFruPath.empty())
990fa5e4d32SSunny Srivastava         {
991fa5e4d32SSunny Srivastava             throw std::runtime_error("Given FRU path is empty.");
992fa5e4d32SSunny Srivastava         }
993fa5e4d32SSunny Srivastava 
994fa5e4d32SSunny Srivastava         if (i_sysCfgJsonObj.empty() || (!i_sysCfgJsonObj.contains("frus")))
995fa5e4d32SSunny Srivastava         {
996fa5e4d32SSunny Srivastava             throw std::runtime_error("Invalid system config JSON object.");
997fa5e4d32SSunny Srivastava         }
998fa5e4d32SSunny Srivastava 
999fa5e4d32SSunny Srivastava         return ((i_sysCfgJsonObj["frus"][i_vpdFruPath].at(0))
1000fa5e4d32SSunny Srivastava                     .contains("replaceableAtStandby") &&
1001fa5e4d32SSunny Srivastava                 (i_sysCfgJsonObj["frus"][i_vpdFruPath].at(
1002fa5e4d32SSunny Srivastava                     0)["replaceableAtStandby"]));
1003fa5e4d32SSunny Srivastava     }
1004fa5e4d32SSunny Srivastava     catch (const std::exception& l_error)
1005fa5e4d32SSunny Srivastava     {
1006fa5e4d32SSunny Srivastava         // TODO: Log PEL
1007fa5e4d32SSunny Srivastava         logging::logMessage(l_error.what());
1008fa5e4d32SSunny Srivastava     }
1009fa5e4d32SSunny Srivastava 
1010fa5e4d32SSunny Srivastava     return false;
1011fa5e4d32SSunny Srivastava }
1012fa5e4d32SSunny Srivastava 
1013fa5e4d32SSunny Srivastava /**
1014fa5e4d32SSunny Srivastava  * @brief API to get list of FRUs replaceable at standby from JSON.
1015fa5e4d32SSunny Srivastava  *
1016fa5e4d32SSunny Srivastava  * The API will return a vector of FRUs inventory path which are replaceable at
1017fa5e4d32SSunny Srivastava  * standby.
1018fa5e4d32SSunny Srivastava  * The API can throw exception in case of error scenarios. Caller's
1019fa5e4d32SSunny Srivastava  * responsibility to handle those exceptions.
1020fa5e4d32SSunny Srivastava  *
1021fa5e4d32SSunny Srivastava  * @param[in] i_sysCfgJsonObj - System config JSON object.
1022fa5e4d32SSunny Srivastava  *
1023fa5e4d32SSunny Srivastava  * @return - List of FRUs replaceable at standby.
1024fa5e4d32SSunny Srivastava  */
getListOfFrusReplaceableAtStandby(const nlohmann::json & i_sysCfgJsonObj)102543fedabcSPatrick Williams inline std::vector<std::string> getListOfFrusReplaceableAtStandby(
102643fedabcSPatrick Williams     const nlohmann::json& i_sysCfgJsonObj)
1027fa5e4d32SSunny Srivastava {
1028fa5e4d32SSunny Srivastava     std::vector<std::string> l_frusReplaceableAtStandby;
1029fa5e4d32SSunny Srivastava 
1030fa5e4d32SSunny Srivastava     if (!i_sysCfgJsonObj.contains("frus"))
1031fa5e4d32SSunny Srivastava     {
1032fa5e4d32SSunny Srivastava         logging::logMessage("Missing frus tag in system config JSON.");
1033fa5e4d32SSunny Srivastava         return l_frusReplaceableAtStandby;
1034fa5e4d32SSunny Srivastava     }
1035fa5e4d32SSunny Srivastava 
1036fa5e4d32SSunny Srivastava     const nlohmann::json& l_fruList =
1037fa5e4d32SSunny Srivastava         i_sysCfgJsonObj["frus"].get_ref<const nlohmann::json::object_t&>();
1038fa5e4d32SSunny Srivastava 
1039fa5e4d32SSunny Srivastava     for (const auto& l_fru : l_fruList.items())
1040fa5e4d32SSunny Srivastava     {
1041fa5e4d32SSunny Srivastava         if (i_sysCfgJsonObj["frus"][l_fru.key()].at(0).value(
1042fa5e4d32SSunny Srivastava                 "replaceableAtStandby", false))
1043fa5e4d32SSunny Srivastava         {
1044fa5e4d32SSunny Srivastava             const std::string& l_inventoryObjectPath =
1045fa5e4d32SSunny Srivastava                 i_sysCfgJsonObj["frus"][l_fru.key()].at(0).value(
1046fa5e4d32SSunny Srivastava                     "inventoryPath", "");
1047fa5e4d32SSunny Srivastava 
1048fa5e4d32SSunny Srivastava             if (!l_inventoryObjectPath.empty())
1049fa5e4d32SSunny Srivastava             {
1050fa5e4d32SSunny Srivastava                 l_frusReplaceableAtStandby.emplace_back(l_inventoryObjectPath);
1051fa5e4d32SSunny Srivastava             }
1052fa5e4d32SSunny Srivastava         }
1053fa5e4d32SSunny Srivastava     }
1054fa5e4d32SSunny Srivastava 
1055fa5e4d32SSunny Srivastava     return l_frusReplaceableAtStandby;
1056fa5e4d32SSunny Srivastava }
1057fa5e4d32SSunny Srivastava 
1058022112bcSSunny Srivastava /**
1059022112bcSSunny Srivastava  * @brief API to select powerVS JSON based on system IM.
1060022112bcSSunny Srivastava  *
1061022112bcSSunny Srivastava  * The API selects respective JSON based on system IM, parse it and return the
1062022112bcSSunny Srivastava  * JSON object. Empty JSON will be returned in case of any error. Caller needs
1063022112bcSSunny Srivastava  * to handle empty value.
1064022112bcSSunny Srivastava  *
1065022112bcSSunny Srivastava  * @param[in] i_imValue - IM value of the system.
1066022112bcSSunny Srivastava  * @return Parsed JSON object, empty JSON otherwise.
1067022112bcSSunny Srivastava  */
getPowerVsJson(const types::BinaryVector & i_imValue)1068022112bcSSunny Srivastava inline nlohmann::json getPowerVsJson(const types::BinaryVector& i_imValue)
1069022112bcSSunny Srivastava {
1070022112bcSSunny Srivastava     try
1071022112bcSSunny Srivastava     {
1072022112bcSSunny Srivastava         if ((i_imValue.at(0) == constants::HEX_VALUE_50) &&
1073022112bcSSunny Srivastava             (i_imValue.at(1) == constants::HEX_VALUE_00) &&
1074022112bcSSunny Srivastava             (i_imValue.at(2) == constants::HEX_VALUE_30))
1075022112bcSSunny Srivastava         {
1076022112bcSSunny Srivastava             return jsonUtility::getParsedJson(constants::power_vs_50003_json);
1077022112bcSSunny Srivastava         }
1078022112bcSSunny Srivastava         else if (i_imValue.at(0) == constants::HEX_VALUE_50 &&
1079022112bcSSunny Srivastava                  (i_imValue.at(1) == constants::HEX_VALUE_00) &&
1080022112bcSSunny Srivastava                  (i_imValue.at(2) == constants::HEX_VALUE_10))
1081022112bcSSunny Srivastava         {
1082022112bcSSunny Srivastava             return jsonUtility::getParsedJson(constants::power_vs_50001_json);
1083022112bcSSunny Srivastava         }
1084022112bcSSunny Srivastava         return nlohmann::json{};
1085022112bcSSunny Srivastava     }
1086022112bcSSunny Srivastava     catch (const std::exception& l_ex)
1087022112bcSSunny Srivastava     {
1088022112bcSSunny Srivastava         return nlohmann::json{};
1089022112bcSSunny Srivastava     }
1090022112bcSSunny Srivastava }
1091*ef069f7eSAnupama B R 
1092*ef069f7eSAnupama B R /** @brief API to get IM value from persisted data location.
1093*ef069f7eSAnupama B R  *
1094*ef069f7eSAnupama B R  * @return IM value on success, empty string otherwise.
1095*ef069f7eSAnupama B R  */
1096*ef069f7eSAnupama B R inline std::string getImFromPersistedLocation() noexcept
1097*ef069f7eSAnupama B R {
1098*ef069f7eSAnupama B R     std::string l_imFilePath{constants::pimPersistVsbpPath};
1099*ef069f7eSAnupama B R 
1100*ef069f7eSAnupama B R     try
1101*ef069f7eSAnupama B R     {
1102*ef069f7eSAnupama B R         auto l_parsedVsbpJsonObj = getParsedJson(l_imFilePath);
1103*ef069f7eSAnupama B R         if (!l_parsedVsbpJsonObj.contains("value0") ||
1104*ef069f7eSAnupama B R             !l_parsedVsbpJsonObj["value0"].contains(constants::kwdIM) ||
1105*ef069f7eSAnupama B R             !l_parsedVsbpJsonObj["value0"][constants::kwdIM].is_array())
1106*ef069f7eSAnupama B R         {
1107*ef069f7eSAnupama B R             throw std::runtime_error(
1108*ef069f7eSAnupama B R                 "Json is empty or mandatory tag(s) missing from JSON");
1109*ef069f7eSAnupama B R         }
1110*ef069f7eSAnupama B R 
1111*ef069f7eSAnupama B R         types::BinaryVector l_imValue =
1112*ef069f7eSAnupama B R             l_parsedVsbpJsonObj["value0"][constants::kwdIM]
1113*ef069f7eSAnupama B R                 .get<types::BinaryVector>();
1114*ef069f7eSAnupama B R 
1115*ef069f7eSAnupama B R         std::ostringstream l_imData;
1116*ef069f7eSAnupama B R         for (auto& l_byte : l_imValue)
1117*ef069f7eSAnupama B R         {
1118*ef069f7eSAnupama B R             l_imData << std::setw(2) << std::setfill('0') << std::hex
1119*ef069f7eSAnupama B R                      << static_cast<int>(l_byte);
1120*ef069f7eSAnupama B R         }
1121*ef069f7eSAnupama B R         return l_imData.str();
1122*ef069f7eSAnupama B R     }
1123*ef069f7eSAnupama B R     catch (const std::exception& l_ex)
1124*ef069f7eSAnupama B R     {
1125*ef069f7eSAnupama B R         logging::logMessage(
1126*ef069f7eSAnupama B R             "Error while getting IM value from PIM persisted file: " +
1127*ef069f7eSAnupama B R             l_imFilePath + ", reason: " + std::string(l_ex.what()));
1128*ef069f7eSAnupama B R     }
1129*ef069f7eSAnupama B R 
1130*ef069f7eSAnupama B R     return std::string();
1131*ef069f7eSAnupama B R }
1132fa5e4d32SSunny Srivastava } // namespace jsonUtility
1133fa5e4d32SSunny Srivastava } // namespace vpd
1134