blob: 9f5e12a65c05091745ab72cb29a5d9e6cd6d1c87 [file] [log] [blame]
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001#pragma once
2
Rekha Aparna017567a2025-08-13 02:07:06 -05003#include "error_codes.hpp"
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05004#include "exceptions.hpp"
5#include "logger.hpp"
6#include "types.hpp"
7
8#include <gpiod.hpp>
9#include <nlohmann/json.hpp>
10#include <utility/common_utility.hpp>
11
12#include <fstream>
13#include <type_traits>
14#include <unordered_map>
15
16namespace vpd
17{
18namespace jsonUtility
19{
20
21// forward declaration of API for function map.
Sunny Srivastava84c3d232025-09-03 00:47:10 -050022bool processSystemCmdTag(
23 const nlohmann::json& i_parsedConfigJson, const std::string& i_vpdFilePath,
24 const std::string& i_baseAction, const std::string& i_flagToProcess,
25 uint16_t& o_errCode);
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -050026
27// forward declaration of API for function map.
28bool processGpioPresenceTag(
29 const nlohmann::json& i_parsedConfigJson, const std::string& i_vpdFilePath,
Sunny Srivastava84c3d232025-09-03 00:47:10 -050030 const std::string& i_baseAction, const std::string& i_flagToProcess,
31 uint16_t& o_errCode);
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -050032
33// forward declaration of API for function map.
34bool procesSetGpioTag(const nlohmann::json& i_parsedConfigJson,
35 const std::string& i_vpdFilePath,
36 const std::string& i_baseAction,
Sunny Srivastava84c3d232025-09-03 00:47:10 -050037 const std::string& i_flagToProcess, uint16_t& o_errCode);
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -050038
39// Function pointers to process tags from config JSON.
40typedef bool (*functionPtr)(
41 const nlohmann::json& i_parsedConfigJson, const std::string& i_vpdFilePath,
Sunny Srivastava84c3d232025-09-03 00:47:10 -050042 const std::string& i_baseAction, const std::string& i_flagToProcess,
43 uint16_t& o_errCode);
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -050044
45inline std::unordered_map<std::string, functionPtr> funcionMap{
46 {"gpioPresence", processGpioPresenceTag},
47 {"setGpio", procesSetGpioTag},
48 {"systemCmd", processSystemCmdTag}};
49
50/**
51 * @brief API to read VPD offset from JSON file.
52 *
53 * @param[in] i_sysCfgJsonObj - Parsed system config JSON object.
54 * @param[in] i_vpdFilePath - VPD file path.
Rekha Aparna017567a2025-08-13 02:07:06 -050055 * @param[in] o_errCode - To set error code in case of error.
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -050056 * @return VPD offset if found in JSON, 0 otherwise.
57 */
58inline size_t getVPDOffset(const nlohmann::json& i_sysCfgJsonObj,
Rekha Aparna017567a2025-08-13 02:07:06 -050059 const std::string& i_vpdFilePath,
60 uint16_t& o_errCode)
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -050061{
Sunny Srivastava47085a22025-11-05 18:11:30 +053062 o_errCode = 0;
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -050063 if (i_vpdFilePath.empty() || (i_sysCfgJsonObj.empty()) ||
64 (!i_sysCfgJsonObj.contains("frus")))
65 {
Rekha Aparna017567a2025-08-13 02:07:06 -050066 o_errCode = error_code::INVALID_INPUT_PARAMETER;
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -050067 return 0;
68 }
69
70 if (i_sysCfgJsonObj["frus"].contains(i_vpdFilePath))
71 {
72 return i_sysCfgJsonObj["frus"][i_vpdFilePath].at(0).value("offset", 0);
73 }
74
75 const nlohmann::json& l_fruList =
76 i_sysCfgJsonObj["frus"].get_ref<const nlohmann::json::object_t&>();
77
78 for (const auto& l_fru : l_fruList.items())
79 {
80 const auto l_fruPath = l_fru.key();
81
82 // check if given path is redundant FRU path
83 if (i_vpdFilePath == i_sysCfgJsonObj["frus"][l_fruPath].at(0).value(
84 "redundantEeprom", ""))
85 {
86 // Return the offset of redundant EEPROM taken from JSON.
87 return i_sysCfgJsonObj["frus"][l_fruPath].at(0).value("offset", 0);
88 }
89 }
90
91 return 0;
92}
93
94/**
95 * @brief API to parse respective JSON.
96 *
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -050097 * @param[in] pathToJson - Path to JSON.
Rekha Aparnaca9a0862025-08-29 04:08:33 -050098 * @param[out] o_errCode - To set error code in case of error.
RekhaAparna011ef21002025-02-18 23:47:36 -060099 * @return on success parsed JSON. On failure empty JSON object.
100 *
101 * Note: Caller has to handle it in case an empty JSON object is received.
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500102 */
Rekha Aparnaca9a0862025-08-29 04:08:33 -0500103inline nlohmann::json getParsedJson(const std::string& pathToJson,
104 uint16_t& o_errCode) noexcept
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500105{
Sunny Srivastava47085a22025-11-05 18:11:30 +0530106 o_errCode = 0;
Rekha Aparnaca9a0862025-08-29 04:08:33 -0500107 if (pathToJson.empty())
108 {
109 o_errCode = error_code::INVALID_INPUT_PARAMETER;
110 return nlohmann::json{};
111 }
112
113 if (!std::filesystem::exists(pathToJson))
114 {
115 o_errCode = error_code::FILE_NOT_FOUND;
116 return nlohmann::json{};
117 }
118
119 if (std::filesystem::is_empty(pathToJson))
120 {
121 o_errCode = error_code::EMPTY_FILE;
122 return nlohmann::json{};
123 }
124
125 std::ifstream l_jsonFile(pathToJson);
126 if (!l_jsonFile)
127 {
128 o_errCode = error_code::FILE_ACCESS_ERROR;
129 return nlohmann::json{};
130 }
131
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500132 try
133 {
RekhaAparna011ef21002025-02-18 23:47:36 -0600134 return nlohmann::json::parse(l_jsonFile);
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500135 }
RekhaAparna011ef21002025-02-18 23:47:36 -0600136 catch (const std::exception& l_ex)
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500137 {
Rekha Aparnaca9a0862025-08-29 04:08:33 -0500138 o_errCode = error_code::JSON_PARSE_ERROR;
139 return nlohmann::json{};
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500140 }
141}
142
143/**
144 * @brief Get inventory object path from system config JSON.
145 *
146 * Given either D-bus inventory path/FRU EEPROM path/redundant EEPROM path,
147 * this API returns D-bus inventory path if present in JSON.
148 *
149 * @param[in] i_sysCfgJsonObj - System config JSON object
150 * @param[in] i_vpdPath - Path to where VPD is stored.
Rekha Aparna017567a2025-08-13 02:07:06 -0500151 * @param[in] o_errCode - To set error code in case of error.
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500152 *
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500153 * @return On success a valid path is returned, on failure an empty string is
RekhaAparna011ef21002025-02-18 23:47:36 -0600154 * returned.
155 *
156 * Note: Caller has to handle it in case an empty string is received.
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500157 */
158inline std::string getInventoryObjPathFromJson(
Rekha Aparna017567a2025-08-13 02:07:06 -0500159 const nlohmann::json& i_sysCfgJsonObj, const std::string& i_vpdPath,
160 uint16_t& o_errCode) noexcept
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500161{
Sunny Srivastava47085a22025-11-05 18:11:30 +0530162 o_errCode = 0;
Rekha Aparna017567a2025-08-13 02:07:06 -0500163 if (i_vpdPath.empty())
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500164 {
Rekha Aparna017567a2025-08-13 02:07:06 -0500165 o_errCode = error_code::INVALID_INPUT_PARAMETER;
166 return std::string{};
RekhaAparna011ef21002025-02-18 23:47:36 -0600167 }
168
Rekha Aparna017567a2025-08-13 02:07:06 -0500169 if (!i_sysCfgJsonObj.contains("frus"))
170 {
171 o_errCode = error_code::INVALID_JSON;
172 return std::string{};
173 }
174
175 // check if given path is FRU path
176 if (i_sysCfgJsonObj["frus"].contains(i_vpdPath))
177 {
178 return i_sysCfgJsonObj["frus"][i_vpdPath].at(0).value(
179 "inventoryPath", "");
180 }
181
182 const nlohmann::json& l_fruList =
183 i_sysCfgJsonObj["frus"].get_ref<const nlohmann::json::object_t&>();
184
185 for (const auto& l_fru : l_fruList.items())
186 {
187 const auto l_fruPath = l_fru.key();
188 const auto l_invObjPath =
189 i_sysCfgJsonObj["frus"][l_fruPath].at(0).value("inventoryPath", "");
190
191 // check if given path is redundant FRU path or inventory path
192 if (i_vpdPath == i_sysCfgJsonObj["frus"][l_fruPath].at(0).value(
193 "redundantEeprom", "") ||
194 (i_vpdPath == l_invObjPath))
195 {
196 return l_invObjPath;
197 }
198 }
199
200 return std::string{};
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500201}
202
203/**
204 * @brief Process "PostFailAction" defined in config JSON.
205 *
206 * In case there is some error in the processing of "preAction" execution and a
207 * set of procedure needs to be done as a part of post fail action. This base
208 * action can be defined in the config JSON for that FRU and it will be handled
209 * under this API.
210 *
211 * @param[in] i_parsedConfigJson - config JSON
212 * @param[in] i_vpdFilePath - EEPROM file path
213 * @param[in] i_flagToProcess - To identify which flag(s) needs to be processed
Rekha Aparnaff7d7992025-09-01 11:08:53 -0500214 * @param[out] o_errCode - To set error code in case of error
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500215 * under PostFailAction tag of config JSON.
216 * @return - success or failure
217 */
Rekha Aparnaff7d7992025-09-01 11:08:53 -0500218inline bool executePostFailAction(
219 const nlohmann::json& i_parsedConfigJson, const std::string& i_vpdFilePath,
220 const std::string& i_flagToProcess, uint16_t& o_errCode)
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500221{
Sunny Srivastava47085a22025-11-05 18:11:30 +0530222 o_errCode = 0;
Rekha Aparnaff7d7992025-09-01 11:08:53 -0500223 if (i_parsedConfigJson.empty() || i_vpdFilePath.empty() ||
224 i_flagToProcess.empty())
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500225 {
Rekha Aparnaff7d7992025-09-01 11:08:53 -0500226 o_errCode = error_code::INVALID_INPUT_PARAMETER;
227 return false;
228 }
RekhaAparna01c11e8b62025-02-20 00:34:35 -0600229
Rekha Aparna41f47e72025-09-18 01:44:09 -0500230 if (!i_parsedConfigJson.contains("frus"))
231 {
232 o_errCode = error_code::INVALID_JSON;
233 return false;
234 }
235
236 if (!i_parsedConfigJson["frus"].contains(i_vpdFilePath))
237 {
238 o_errCode = error_code::FRU_PATH_NOT_FOUND;
239 return false;
240 }
241
242 if (!i_parsedConfigJson["frus"][i_vpdFilePath].at(0).contains(
243 "postFailAction"))
244 {
245 o_errCode = error_code::MISSING_ACTION_TAG;
246 return false;
247 }
248
Rekha Aparnaff7d7992025-09-01 11:08:53 -0500249 if (!(i_parsedConfigJson["frus"][i_vpdFilePath].at(0))["postFailAction"]
250 .contains(i_flagToProcess))
251 {
252 o_errCode = error_code::MISSING_FLAG;
253 return false;
254 }
RekhaAparna01c11e8b62025-02-20 00:34:35 -0600255
Rekha Aparnaff7d7992025-09-01 11:08:53 -0500256 for (const auto& l_tags : (i_parsedConfigJson["frus"][i_vpdFilePath].at(
257 0))["postFailAction"][i_flagToProcess]
258 .items())
259 {
260 auto itrToFunction = funcionMap.find(l_tags.key());
261 if (itrToFunction != funcionMap.end())
RekhaAparna01c11e8b62025-02-20 00:34:35 -0600262 {
Rekha Aparnaff7d7992025-09-01 11:08:53 -0500263 if (!itrToFunction->second(i_parsedConfigJson, i_vpdFilePath,
Sunny Srivastava84c3d232025-09-03 00:47:10 -0500264 "postFailAction", i_flagToProcess,
265 o_errCode))
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500266 {
Sunny Srivastava84c3d232025-09-03 00:47:10 -0500267 if (o_errCode)
268 {
269 logging::logMessage(
270 l_tags.key() + " failed for [" + i_vpdFilePath +
Rekha Aparnac6159a22025-10-09 12:20:20 +0530271 "]. Reason " + commonUtility::getErrCodeMsg(o_errCode));
Sunny Srivastava84c3d232025-09-03 00:47:10 -0500272 }
Rekha Aparnaff7d7992025-09-01 11:08:53 -0500273 return false;
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500274 }
275 }
276 }
277
278 return true;
279}
280
281/**
282 * @brief Process "systemCmd" tag for a given FRU.
283 *
284 * The API will process "systemCmd" tag if it is defined in the config
285 * JSON for the given FRU.
286 *
287 * @param[in] i_parsedConfigJson - config JSON
288 * @param[in] i_vpdFilePath - EEPROM file path
289 * @param[in] i_baseAction - Base action for which this tag has been called.
290 * @param[in] i_flagToProcess - Flag nested under the base action for which this
291 * tag has been called.
Sunny Srivastava84c3d232025-09-03 00:47:10 -0500292 * @param[out] o_errCode - To set error code in case of error.
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500293 * @return Execution status.
294 */
295inline bool processSystemCmdTag(
296 const nlohmann::json& i_parsedConfigJson, const std::string& i_vpdFilePath,
Sunny Srivastava84c3d232025-09-03 00:47:10 -0500297 const std::string& i_baseAction, const std::string& i_flagToProcess,
298 uint16_t& o_errCode)
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500299{
Sunny Srivastava47085a22025-11-05 18:11:30 +0530300 o_errCode = 0;
Sunny Srivastava84c3d232025-09-03 00:47:10 -0500301 if (i_vpdFilePath.empty() || i_parsedConfigJson.empty() ||
302 i_baseAction.empty() || i_flagToProcess.empty())
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500303 {
Sunny Srivastava84c3d232025-09-03 00:47:10 -0500304 o_errCode = error_code::INVALID_INPUT_PARAMETER;
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500305 return false;
306 }
Sunny Srivastava84c3d232025-09-03 00:47:10 -0500307
Rekha Aparna41f47e72025-09-18 01:44:09 -0500308 try
Sunny Srivastava84c3d232025-09-03 00:47:10 -0500309 {
Rekha Aparna41f47e72025-09-18 01:44:09 -0500310 if (!((i_parsedConfigJson["frus"][i_vpdFilePath].at(
311 0)[i_baseAction][i_flagToProcess]["systemCmd"])
312 .contains("cmd")))
313 {
314 o_errCode = error_code::MISSING_FLAG;
315 return false;
316 }
317
318 const std::string& l_systemCommand =
319 i_parsedConfigJson["frus"][i_vpdFilePath].at(
320 0)[i_baseAction][i_flagToProcess]["systemCmd"]["cmd"];
321
322 commonUtility::executeCmd(l_systemCommand);
323 }
324 catch (const std::exception& l_ex)
325 {
326 o_errCode = error_code::ERROR_PROCESSING_SYSTEM_CMD;
Sunny Srivastava84c3d232025-09-03 00:47:10 -0500327 return false;
328 }
Sunny Srivastava84c3d232025-09-03 00:47:10 -0500329 return true;
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500330}
331
332/**
333 * @brief Checks for presence of a given FRU using GPIO line.
334 *
335 * This API returns the presence information of the FRU corresponding to the
336 * given VPD file path by setting the presence pin.
337 *
338 * @param[in] i_parsedConfigJson - config JSON
339 * @param[in] i_vpdFilePath - EEPROM file path
340 * @param[in] i_baseAction - Base action for which this tag has been called.
341 * @param[in] i_flagToProcess - Flag nested under the base action for which this
342 * tag has been called.
Sunny Srivastava84c3d232025-09-03 00:47:10 -0500343 * @param[out] o_errCode - To set error code in case of error
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500344 * @return Execution status.
345 */
346inline bool processGpioPresenceTag(
347 const nlohmann::json& i_parsedConfigJson, const std::string& i_vpdFilePath,
Sunny Srivastava84c3d232025-09-03 00:47:10 -0500348 const std::string& i_baseAction, const std::string& i_flagToProcess,
349 uint16_t& o_errCode)
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500350{
Sunny Srivastava47085a22025-11-05 18:11:30 +0530351 o_errCode = 0;
Sunny Srivastava0a5fce12025-04-09 11:09:51 +0530352 std::string l_presencePinName;
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500353 try
354 {
Sunny Srivastava0a5fce12025-04-09 11:09:51 +0530355 if (i_vpdFilePath.empty() || i_parsedConfigJson.empty() ||
356 i_baseAction.empty() || i_flagToProcess.empty())
357 {
Sunny Srivastava84c3d232025-09-03 00:47:10 -0500358 o_errCode = error_code::INVALID_INPUT_PARAMETER;
359 return false;
Sunny Srivastava0a5fce12025-04-09 11:09:51 +0530360 }
361
362 if (!(((i_parsedConfigJson["frus"][i_vpdFilePath].at(
363 0)[i_baseAction][i_flagToProcess]["gpioPresence"])
364 .contains("pin")) &&
365 ((i_parsedConfigJson["frus"][i_vpdFilePath].at(
366 0)[i_baseAction][i_flagToProcess]["gpioPresence"])
367 .contains("value"))))
368 {
Sunny Srivastava84c3d232025-09-03 00:47:10 -0500369 o_errCode = error_code::JSON_MISSING_GPIO_INFO;
370 return false;
Sunny Srivastava0a5fce12025-04-09 11:09:51 +0530371 }
372
373 // get the pin name
374 l_presencePinName = i_parsedConfigJson["frus"][i_vpdFilePath].at(
375 0)[i_baseAction][i_flagToProcess]["gpioPresence"]["pin"];
376
377 // get the pin value
378 uint8_t l_presencePinValue =
379 i_parsedConfigJson["frus"][i_vpdFilePath].at(
380 0)[i_baseAction][i_flagToProcess]["gpioPresence"]["value"];
381
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500382 gpiod::line l_presenceLine = gpiod::find_line(l_presencePinName);
383
384 if (!l_presenceLine)
385 {
Sunny Srivastava84c3d232025-09-03 00:47:10 -0500386 o_errCode = error_code::DEVICE_PRESENCE_UNKNOWN;
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500387 throw GpioException("Couldn't find the GPIO line.");
388 }
389
390 l_presenceLine.request({"Read the presence line",
391 gpiod::line_request::DIRECTION_INPUT, 0});
392
Sunny Srivastava84c3d232025-09-03 00:47:10 -0500393 if (l_presencePinValue != l_presenceLine.get_value())
Sunny Srivastava0a5fce12025-04-09 11:09:51 +0530394 {
Sunny Srivastava84c3d232025-09-03 00:47:10 -0500395 // As false is being returned in this case, caller needs to know
396 // that it is not due to some exception. It is because the pin was
397 // read correctly but was not having expected value.
398 o_errCode = error_code::DEVICE_NOT_PRESENT;
Sunny Srivastava0a5fce12025-04-09 11:09:51 +0530399 return false;
400 }
401
Sunny Srivastava84c3d232025-09-03 00:47:10 -0500402 return true;
403 }
404 catch (const std::exception& l_ex)
405 {
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500406 std::string l_errMsg = "Exception on GPIO line: ";
407 l_errMsg += l_presencePinName;
408 l_errMsg += " Reason: ";
Sunny Srivastava0a5fce12025-04-09 11:09:51 +0530409 l_errMsg += l_ex.what();
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500410 l_errMsg += " File: " + i_vpdFilePath + " Pel Logged";
411
Rekha Aparnaa39aafa2025-11-04 00:06:12 -0600412 // ToDo -- Check if PEL is required. Update Internal Rc code.
413 /**
414 uint16_t l_errCode = 0;
415 EventLogger::createAsyncPelWithInventoryCallout(
Sunny Srivastava0a5fce12025-04-09 11:09:51 +0530416 EventLogger::getErrorType(l_ex), types::SeverityType::Informational,
Rekha Aparna017567a2025-08-13 02:07:06 -0500417 {{getInventoryObjPathFromJson(i_parsedConfigJson, i_vpdFilePath,
418 l_errCode),
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500419 types::CalloutPriority::High}},
420 std::source_location::current().file_name(),
421 std::source_location::current().function_name(), 0, l_errMsg,
422 std::nullopt, std::nullopt, std::nullopt, std::nullopt);
Rekha Aparnaa39aafa2025-11-04 00:06:12 -0600423 */
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500424
425 logging::logMessage(l_errMsg);
426
427 // Except when GPIO pin value is false, we go and try collecting the
428 // FRU VPD as we couldn't able to read GPIO pin value due to some
429 // error/exception. So returning true in error scenario.
430 return true;
431 }
432}
433
434/**
435 * @brief Process "setGpio" tag for a given FRU.
436 *
437 * This API enables the GPIO line.
438 *
439 * @param[in] i_parsedConfigJson - config JSON
440 * @param[in] i_vpdFilePath - EEPROM file path
441 * @param[in] i_baseAction - Base action for which this tag has been called.
442 * @param[in] i_flagToProcess - Flag nested under the base action for which this
443 * tag has been called.
Sunny Srivastava84c3d232025-09-03 00:47:10 -0500444 * @param[out] o_errCode - To set error code in case of error
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500445 * @return Execution status.
446 */
447inline bool procesSetGpioTag(
448 const nlohmann::json& i_parsedConfigJson, const std::string& i_vpdFilePath,
Sunny Srivastava84c3d232025-09-03 00:47:10 -0500449 const std::string& i_baseAction, const std::string& i_flagToProcess,
450 uint16_t& o_errCode)
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500451{
Sunny Srivastava47085a22025-11-05 18:11:30 +0530452 o_errCode = 0;
Sunny Srivastava0a5fce12025-04-09 11:09:51 +0530453 std::string l_pinName;
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500454 try
455 {
Sunny Srivastava0a5fce12025-04-09 11:09:51 +0530456 if (i_vpdFilePath.empty() || i_parsedConfigJson.empty() ||
457 i_baseAction.empty() || i_flagToProcess.empty())
458 {
Sunny Srivastava84c3d232025-09-03 00:47:10 -0500459 o_errCode = error_code::INVALID_INPUT_PARAMETER;
460 return false;
Sunny Srivastava0a5fce12025-04-09 11:09:51 +0530461 }
462
463 if (!(((i_parsedConfigJson["frus"][i_vpdFilePath].at(
464 0)[i_baseAction][i_flagToProcess]["setGpio"])
465 .contains("pin")) &&
466 ((i_parsedConfigJson["frus"][i_vpdFilePath].at(
467 0)[i_baseAction][i_flagToProcess]["setGpio"])
468 .contains("value"))))
469 {
Sunny Srivastava84c3d232025-09-03 00:47:10 -0500470 o_errCode = error_code::JSON_MISSING_GPIO_INFO;
471 return false;
Sunny Srivastava0a5fce12025-04-09 11:09:51 +0530472 }
473
474 l_pinName = i_parsedConfigJson["frus"][i_vpdFilePath].at(
475 0)[i_baseAction][i_flagToProcess]["setGpio"]["pin"];
476
477 // Get the value to set
478 uint8_t l_pinValue = i_parsedConfigJson["frus"][i_vpdFilePath].at(
479 0)[i_baseAction][i_flagToProcess]["setGpio"]["value"];
480
481 logging::logMessage(
482 "Setting GPIO: " + l_pinName + " to " + std::to_string(l_pinValue));
483
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500484 gpiod::line l_outputLine = gpiod::find_line(l_pinName);
485
486 if (!l_outputLine)
487 {
Sunny Srivastava84c3d232025-09-03 00:47:10 -0500488 o_errCode = error_code::GPIO_LINE_EXCEPTION;
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500489 throw GpioException("Couldn't find GPIO line.");
490 }
491
492 l_outputLine.request(
493 {"FRU Action", ::gpiod::line_request::DIRECTION_OUTPUT, 0},
494 l_pinValue);
495 return true;
496 }
Sunny Srivastava0a5fce12025-04-09 11:09:51 +0530497 catch (const std::exception& l_ex)
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500498 {
Sunny Srivastava84c3d232025-09-03 00:47:10 -0500499 std::string l_errMsg = "Exception on GPIO line: ";
500 l_errMsg += l_pinName;
501 l_errMsg += " Reason: ";
502 l_errMsg += l_ex.what();
503 l_errMsg += " File: " + i_vpdFilePath + " Pel Logged";
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500504
Sunny Srivastava84c3d232025-09-03 00:47:10 -0500505 // ToDo -- Update Internal RC code
Rekha Aparnaa39aafa2025-11-04 00:06:12 -0600506 /**
507 uint16_t l_errCode = 0;
508 EventLogger::createAsyncPelWithInventoryCallout(
Sunny Srivastava84c3d232025-09-03 00:47:10 -0500509 EventLogger::getErrorType(l_ex), types::SeverityType::Informational,
510 {{getInventoryObjPathFromJson(i_parsedConfigJson, i_vpdFilePath,
511 l_errCode),
512 types::CalloutPriority::High}},
513 std::source_location::current().file_name(),
514 std::source_location::current().function_name(), 0, l_errMsg,
515 std::nullopt, std::nullopt, std::nullopt, std::nullopt);
Rekha Aparnaa39aafa2025-11-04 00:06:12 -0600516 */
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500517
Sunny Srivastava84c3d232025-09-03 00:47:10 -0500518 logging::logMessage(l_errMsg);
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500519
520 return false;
521 }
522}
523
524/**
525 * @brief Process any action, if defined in config JSON.
526 *
527 * If any FRU(s) requires any special handling, then this base action can be
528 * defined for that FRU in the config JSON, processing of which will be handled
529 * in this API.
530 * Examples of action - preAction, PostAction etc.
531 *
532 * @param[in] i_parsedConfigJson - config JSON
533 * @param[in] i_action - Base action to be performed.
534 * @param[in] i_vpdFilePath - EEPROM file path
535 * @param[in] i_flagToProcess - To identify which flag(s) needs to be processed
536 * under PreAction tag of config JSON.
Sunny Srivastava4f053df2025-09-03 02:27:37 -0500537 * @param[out] o_errCode - To set error code in case of error.
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500538 * @return - success or failure
539 */
540inline bool executeBaseAction(
541 const nlohmann::json& i_parsedConfigJson, const std::string& i_action,
Sunny Srivastava4f053df2025-09-03 02:27:37 -0500542 const std::string& i_vpdFilePath, const std::string& i_flagToProcess,
543 uint16_t& o_errCode)
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500544{
Sunny Srivastava47085a22025-11-05 18:11:30 +0530545 o_errCode = 0;
Sunny Srivastava4f053df2025-09-03 02:27:37 -0500546 if (i_flagToProcess.empty() || i_action.empty() || i_vpdFilePath.empty() ||
547 !i_parsedConfigJson.contains("frus"))
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500548 {
Sunny Srivastava4f053df2025-09-03 02:27:37 -0500549 o_errCode = error_code::INVALID_INPUT_PARAMETER;
550 return false;
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500551 }
Sunny Srivastava4f053df2025-09-03 02:27:37 -0500552 if (!i_parsedConfigJson["frus"].contains(i_vpdFilePath))
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500553 {
Sunny Srivastava4f053df2025-09-03 02:27:37 -0500554 o_errCode = error_code::FILE_NOT_FOUND;
555 return false;
556 }
557 if (!i_parsedConfigJson["frus"][i_vpdFilePath].at(0).contains(i_action))
558 {
559 o_errCode = error_code::MISSING_ACTION_TAG;
560 return false;
561 }
562
563 if (!(i_parsedConfigJson["frus"][i_vpdFilePath].at(0))[i_action].contains(
564 i_flagToProcess))
565 {
566 o_errCode = error_code::MISSING_FLAG;
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500567 return false;
568 }
569
570 const nlohmann::json& l_tagsJson =
571 (i_parsedConfigJson["frus"][i_vpdFilePath].at(
572 0))[i_action][i_flagToProcess];
573
574 for (const auto& l_tag : l_tagsJson.items())
575 {
576 auto itrToFunction = funcionMap.find(l_tag.key());
577 if (itrToFunction != funcionMap.end())
578 {
579 if (!itrToFunction->second(i_parsedConfigJson, i_vpdFilePath,
Sunny Srivastava84c3d232025-09-03 00:47:10 -0500580 i_action, i_flagToProcess, o_errCode))
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500581 {
582 // In case any of the tag fails to execute. Mark action
583 // as failed for that flag.
Sunny Srivastava84c3d232025-09-03 00:47:10 -0500584 if (o_errCode)
585 {
586 logging::logMessage(
587 l_tag.key() + " failed for [" + i_vpdFilePath +
Rekha Aparnac6159a22025-10-09 12:20:20 +0530588 "]. Reason " + commonUtility::getErrCodeMsg(o_errCode));
Sunny Srivastava84c3d232025-09-03 00:47:10 -0500589 }
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500590 return false;
591 }
592 }
593 }
594
595 return true;
596}
597
598/**
599 * @brief Get redundant FRU path from system config JSON
600 *
601 * Given either D-bus inventory path/FRU path/redundant FRU path, this
602 * API returns the redundant FRU path taken from "redundantEeprom" tag from
603 * system config JSON.
604 *
605 * @param[in] i_sysCfgJsonObj - System config JSON object.
606 * @param[in] i_vpdPath - Path to where VPD is stored.
Rekha Aparnabb52af42025-09-02 04:05:18 -0500607 * @param[out] o_errCode - To set error code in case of error.
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500608 *
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500609 * @return On success return valid path, on failure return empty string.
610 */
611inline std::string getRedundantEepromPathFromJson(
Rekha Aparnabb52af42025-09-02 04:05:18 -0500612 const nlohmann::json& i_sysCfgJsonObj, const std::string& i_vpdPath,
613 uint16_t& o_errCode)
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500614{
Sunny Srivastava47085a22025-11-05 18:11:30 +0530615 o_errCode = 0;
Rekha Aparnabb52af42025-09-02 04:05:18 -0500616 if (i_vpdPath.empty())
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500617 {
Rekha Aparnabb52af42025-09-02 04:05:18 -0500618 o_errCode = error_code::INVALID_INPUT_PARAMETER;
619 return std::string{};
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500620 }
Rekha Aparnabb52af42025-09-02 04:05:18 -0500621
622 if (!i_sysCfgJsonObj.contains("frus"))
RekhaAparna017fea9f52025-02-17 04:14:02 -0600623 {
Rekha Aparnabb52af42025-09-02 04:05:18 -0500624 o_errCode = error_code::INVALID_JSON;
625 return std::string{};
626 }
627
628 // check if given path is FRU path
629 if (i_sysCfgJsonObj["frus"].contains(i_vpdPath))
630 {
631 return i_sysCfgJsonObj["frus"][i_vpdPath].at(0).value(
632 "redundantEeprom", "");
633 }
634
635 const nlohmann::json& l_fruList =
636 i_sysCfgJsonObj["frus"].get_ref<const nlohmann::json::object_t&>();
637
638 for (const auto& l_fru : l_fruList.items())
639 {
640 const std::string& l_fruPath = l_fru.key();
641 const std::string& l_redundantFruPath =
642 i_sysCfgJsonObj["frus"][l_fruPath].at(0).value("redundantEeprom",
643 "");
644
645 // check if given path is inventory path or redundant FRU path
646 if ((i_sysCfgJsonObj["frus"][l_fruPath].at(0).value("inventoryPath",
647 "") == i_vpdPath) ||
648 (l_redundantFruPath == i_vpdPath))
649 {
650 return l_redundantFruPath;
651 }
RekhaAparna017fea9f52025-02-17 04:14:02 -0600652 }
653
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500654 return std::string();
655}
656
657/**
658 * @brief Get FRU EEPROM path from system config JSON
659 *
660 * Given either D-bus inventory path/FRU EEPROM path/redundant EEPROM path,
661 * this API returns FRU EEPROM path if present in JSON.
662 *
663 * @param[in] i_sysCfgJsonObj - System config JSON object
664 * @param[in] i_vpdPath - Path to where VPD is stored.
Rekha Aparna0578dd22025-09-02 08:20:21 -0500665 * @param[out] o_errCode - To set error code in case of error.
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500666 *
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500667 * @return On success return valid path, on failure return empty string.
668 */
669inline std::string getFruPathFromJson(const nlohmann::json& i_sysCfgJsonObj,
Rekha Aparna0578dd22025-09-02 08:20:21 -0500670 const std::string& i_vpdPath,
671 uint16_t& o_errCode)
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500672{
Sunny Srivastava47085a22025-11-05 18:11:30 +0530673 o_errCode = 0;
Rekha Aparna0578dd22025-09-02 08:20:21 -0500674 if (i_vpdPath.empty())
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500675 {
Rekha Aparna0578dd22025-09-02 08:20:21 -0500676 o_errCode = error_code::INVALID_INPUT_PARAMETER;
677 return std::string{};
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500678 }
Rekha Aparna0578dd22025-09-02 08:20:21 -0500679
680 if (!i_sysCfgJsonObj.contains("frus"))
RekhaAparna017fea9f52025-02-17 04:14:02 -0600681 {
Rekha Aparna0578dd22025-09-02 08:20:21 -0500682 o_errCode = error_code::INVALID_JSON;
683 return std::string{};
684 }
685
686 // check if given path is FRU path
687 if (i_sysCfgJsonObj["frus"].contains(i_vpdPath))
688 {
689 return i_vpdPath;
690 }
691
692 const nlohmann::json& l_fruList =
693 i_sysCfgJsonObj["frus"].get_ref<const nlohmann::json::object_t&>();
694
695 for (const auto& l_fru : l_fruList.items())
696 {
697 const auto l_fruPath = l_fru.key();
698
699 // check if given path is redundant FRU path or inventory path
700 if (i_vpdPath == i_sysCfgJsonObj["frus"][l_fruPath].at(0).value(
701 "redundantEeprom", "") ||
702 (i_vpdPath == i_sysCfgJsonObj["frus"][l_fruPath].at(0).value(
703 "inventoryPath", "")))
704 {
705 return l_fruPath;
706 }
RekhaAparna017fea9f52025-02-17 04:14:02 -0600707 }
708
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500709 return std::string();
710}
711
712/**
713 * @brief An API to check backup and restore VPD is required.
714 *
715 * The API checks if there is provision for backup and restore mentioned in the
716 * system config JSON, by looking "backupRestoreConfigPath" tag.
717 * Checks if the path mentioned is a hardware path, by checking if the file path
718 * exists and size of contents in the path.
719 *
720 * @param[in] i_sysCfgJsonObj - System config JSON object.
Rekha Aparna196e3082025-09-08 20:40:35 -0500721 * @param[out] o_errCode - To set error code in case of error.
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500722 *
723 * @return true if backup and restore is required, false otherwise.
724 */
Rekha Aparna196e3082025-09-08 20:40:35 -0500725inline bool isBackupAndRestoreRequired(const nlohmann::json& i_sysCfgJsonObj,
726 uint16_t& o_errCode)
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500727{
Sunny Srivastava47085a22025-11-05 18:11:30 +0530728 o_errCode = 0;
Rekha Aparna196e3082025-09-08 20:40:35 -0500729 if (i_sysCfgJsonObj.empty())
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500730 {
Rekha Aparna196e3082025-09-08 20:40:35 -0500731 o_errCode = error_code::INVALID_INPUT_PARAMETER;
732 return false;
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500733 }
Rekha Aparna196e3082025-09-08 20:40:35 -0500734
735 const std::string& l_backupAndRestoreCfgFilePath =
736 i_sysCfgJsonObj.value("backupRestoreConfigPath", "");
737
738 if (!l_backupAndRestoreCfgFilePath.empty() &&
739 std::filesystem::exists(l_backupAndRestoreCfgFilePath) &&
740 !std::filesystem::is_empty(l_backupAndRestoreCfgFilePath))
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500741 {
Rekha Aparna196e3082025-09-08 20:40:35 -0500742 return true;
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500743 }
Rekha Aparna196e3082025-09-08 20:40:35 -0500744
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500745 return false;
746}
747
748/** @brief API to check if an action is required for given EEPROM path.
749 *
750 * System config JSON can contain pre-action, post-action etc. like actions
751 * defined for an EEPROM path. The API will check if any such action is defined
752 * for the EEPROM.
753 *
754 * @param[in] i_sysCfgJsonObj - System config JSON object.
755 * @param[in] i_vpdFruPath - EEPROM path.
756 * @param[in] i_action - Action to be checked.
757 * @param[in] i_flowFlag - Denotes the flow w.r.t which the action should be
758 * triggered.
Rekha Aparnab50bf0e2025-09-02 21:13:26 -0500759 * @param[out] o_errCode - To set error code in case of error.
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500760 * @return - True if action is defined for the flow, false otherwise.
761 */
Rekha Aparnab50bf0e2025-09-02 21:13:26 -0500762inline bool isActionRequired(const nlohmann::json& i_sysCfgJsonObj,
763 const std::string& i_vpdFruPath,
764 const std::string& i_action,
765 const std::string& i_flowFlag, uint16_t& o_errCode)
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500766{
Sunny Srivastava47085a22025-11-05 18:11:30 +0530767 o_errCode = 0;
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500768 if (i_vpdFruPath.empty() || i_action.empty() || i_flowFlag.empty())
769 {
Rekha Aparnab50bf0e2025-09-02 21:13:26 -0500770 o_errCode = error_code::INVALID_INPUT_PARAMETER;
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500771 return false;
772 }
773
774 if (!i_sysCfgJsonObj.contains("frus"))
775 {
Rekha Aparnab50bf0e2025-09-02 21:13:26 -0500776 o_errCode = error_code::INVALID_JSON;
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500777 return false;
778 }
779
780 if (!i_sysCfgJsonObj["frus"].contains(i_vpdFruPath))
781 {
Rekha Aparnab50bf0e2025-09-02 21:13:26 -0500782 o_errCode = error_code::FRU_PATH_NOT_FOUND;
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500783 return false;
784 }
785
786 if ((i_sysCfgJsonObj["frus"][i_vpdFruPath].at(0)).contains(i_action))
787 {
788 if ((i_sysCfgJsonObj["frus"][i_vpdFruPath].at(0))[i_action].contains(
789 i_flowFlag))
790 {
791 return true;
792 }
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500793 }
794 return false;
795}
796
797/**
798 * @brief An API to return list of FRUs that needs GPIO polling.
799 *
800 * An API that checks for the FRUs that requires GPIO polling and returns
801 * a list of FRUs that needs polling. Returns an empty list if there are
802 * no FRUs that requires polling.
803 *
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500804 * @param[in] i_sysCfgJsonObj - System config JSON object.
Rekha Aparnadc47adb2025-09-08 11:29:58 -0500805 * @param[out] o_errCode - To set error codes in case of error.
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500806 *
RekhaAparna017fea9f52025-02-17 04:14:02 -0600807 * @return On success list of FRUs parameters that needs polling. On failure,
808 * empty list.
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500809 */
Patrick Williams43fedab2025-02-03 14:28:05 -0500810inline std::vector<std::string> getListOfGpioPollingFrus(
Rekha Aparnadc47adb2025-09-08 11:29:58 -0500811 const nlohmann::json& i_sysCfgJsonObj, uint16_t& o_errCode)
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500812{
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500813 std::vector<std::string> l_gpioPollingRequiredFrusList;
Sunny Srivastava47085a22025-11-05 18:11:30 +0530814 o_errCode = 0;
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500815
Rekha Aparnadc47adb2025-09-08 11:29:58 -0500816 if (i_sysCfgJsonObj.empty())
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500817 {
Rekha Aparnadc47adb2025-09-08 11:29:58 -0500818 o_errCode = error_code::INVALID_INPUT_PARAMETER;
819 return l_gpioPollingRequiredFrusList;
RekhaAparna017fea9f52025-02-17 04:14:02 -0600820 }
Rekha Aparnadc47adb2025-09-08 11:29:58 -0500821
822 if (!i_sysCfgJsonObj.contains("frus"))
RekhaAparna017fea9f52025-02-17 04:14:02 -0600823 {
Rekha Aparnadc47adb2025-09-08 11:29:58 -0500824 o_errCode = error_code::INVALID_JSON;
825 return l_gpioPollingRequiredFrusList;
826 }
827
828 for (const auto& l_fru : i_sysCfgJsonObj["frus"].items())
829 {
830 const auto l_fruPath = l_fru.key();
831
832 bool l_isHotPluggableFru =
833 isActionRequired(i_sysCfgJsonObj, l_fruPath, "pollingRequired",
834 "hotPlugging", o_errCode);
835
836 if (o_errCode)
837 {
838 logging::logMessage(
839 "Error while checking if action required for FRU [" +
840 std::string(l_fruPath) +
Rekha Aparnac6159a22025-10-09 12:20:20 +0530841 "], error : " + commonUtility::getErrCodeMsg(o_errCode));
Rekha Aparnadc47adb2025-09-08 11:29:58 -0500842
843 return l_gpioPollingRequiredFrusList;
844 }
845
846 if (l_isHotPluggableFru)
847 {
848 if (i_sysCfgJsonObj["frus"][l_fruPath]
849 .at(0)["pollingRequired"]["hotPlugging"]
850 .contains("gpioPresence"))
851 {
852 l_gpioPollingRequiredFrusList.push_back(l_fruPath);
853 }
854 }
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500855 }
856
857 return l_gpioPollingRequiredFrusList;
858}
859
860/**
861 * @brief Get all related path(s) to update keyword value.
862 *
863 * Given FRU EEPROM path/Inventory path needs keyword's value update, this API
864 * returns tuple of FRU EEPROM path, inventory path and redundant EEPROM path if
865 * exists in the system config JSON.
866 *
867 * Note: If the inventory object path or redundant EEPROM path(s) are not found
868 * in the system config JSON, corresponding fields will have empty value in the
869 * returning tuple.
870 *
871 * @param[in] i_sysCfgJsonObj - System config JSON object.
872 * @param[in,out] io_vpdPath - Inventory object path or FRU EEPROM path.
Rekha Aparna2d6f0712025-09-02 03:52:57 -0500873 * @param[out] o_errCode - To set error code in case of error.
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500874 *
875 * @return On success returns tuple of EEPROM path, inventory path & redundant
876 * path, on failure returns tuple with given input path alone.
877 */
878inline std::tuple<std::string, std::string, std::string>
879 getAllPathsToUpdateKeyword(const nlohmann::json& i_sysCfgJsonObj,
Rekha Aparna2d6f0712025-09-02 03:52:57 -0500880 std::string io_vpdPath, uint16_t& o_errCode)
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500881{
882 types::Path l_inventoryObjPath;
883 types::Path l_redundantFruPath;
Rekha Aparna2d6f0712025-09-02 03:52:57 -0500884 o_errCode = 0;
885
886 if (i_sysCfgJsonObj.empty() || io_vpdPath.empty())
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500887 {
Rekha Aparna2d6f0712025-09-02 03:52:57 -0500888 o_errCode = error_code::INVALID_INPUT_PARAMETER;
889 return std::make_tuple(io_vpdPath, l_inventoryObjPath,
890 l_redundantFruPath);
891 }
Rekha Aparna0578dd22025-09-02 08:20:21 -0500892
Rekha Aparna2d6f0712025-09-02 03:52:57 -0500893 // Get hardware path from system config JSON.
894 const types::Path l_fruPath =
895 jsonUtility::getFruPathFromJson(i_sysCfgJsonObj, io_vpdPath, o_errCode);
896
897 if (!l_fruPath.empty())
898 {
899 io_vpdPath = l_fruPath;
900
901 // Get inventory object path from system config JSON
902 l_inventoryObjPath = jsonUtility::getInventoryObjPathFromJson(
903 i_sysCfgJsonObj, l_fruPath, o_errCode);
904
905 if (l_inventoryObjPath.empty())
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500906 {
Rekha Aparna2d6f0712025-09-02 03:52:57 -0500907 if (o_errCode)
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500908 {
Rekha Aparna2d6f0712025-09-02 03:52:57 -0500909 logging::logMessage(
910 "Failed to get inventory path from JSON for [" +
Rekha Aparnac6159a22025-10-09 12:20:20 +0530911 io_vpdPath +
912 "], error : " + commonUtility::getErrCodeMsg(o_errCode));
Rekha Aparna2d6f0712025-09-02 03:52:57 -0500913 }
914 else
915 {
916 o_errCode = error_code::FRU_PATH_NOT_FOUND;
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500917 }
Rekha Aparna0578dd22025-09-02 08:20:21 -0500918
Rekha Aparna2d6f0712025-09-02 03:52:57 -0500919 return std::make_tuple(io_vpdPath, l_inventoryObjPath,
920 l_redundantFruPath);
921 }
922
923 // Get redundant hardware path if present in system config JSON
924 l_redundantFruPath = jsonUtility::getRedundantEepromPathFromJson(
925 i_sysCfgJsonObj, l_fruPath, o_errCode);
926
927 if (l_redundantFruPath.empty())
928 {
929 if (o_errCode)
930 {
931 logging::logMessage(
932 "Failed to get redundant EEPROM path for FRU [" +
Rekha Aparnac6159a22025-10-09 12:20:20 +0530933 l_fruPath +
934 "], error : " + commonUtility::getErrCodeMsg(o_errCode));
Rekha Aparna2d6f0712025-09-02 03:52:57 -0500935
936 o_errCode = error_code::ERROR_GETTING_REDUNDANT_PATH;
937 }
938 else
939 {
940 o_errCode = error_code::REDUNDANT_PATH_NOT_FOUND;
941 }
Rekha Aparna0578dd22025-09-02 08:20:21 -0500942
943 return std::make_tuple(io_vpdPath, l_inventoryObjPath,
944 l_redundantFruPath);
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500945 }
946 }
Rekha Aparna2d6f0712025-09-02 03:52:57 -0500947 else if (o_errCode)
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500948 {
949 logging::logMessage(
Rekha Aparna2d6f0712025-09-02 03:52:57 -0500950 "Failed to get FRU path from JSON for [" + io_vpdPath +
Rekha Aparnac6159a22025-10-09 12:20:20 +0530951 "], error : " + commonUtility::getErrCodeMsg(o_errCode));
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500952 }
Rekha Aparna2d6f0712025-09-02 03:52:57 -0500953 else
954 {
955 o_errCode = error_code::NO_EEPROM_PATH;
956 }
957
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500958 return std::make_tuple(io_vpdPath, l_inventoryObjPath, l_redundantFruPath);
959}
960
961/**
962 * @brief An API to get DBus service name.
963 *
964 * Given DBus inventory path, this API returns DBus service name if present in
965 * the JSON.
966 *
967 * @param[in] i_sysCfgJsonObj - System config JSON object.
968 * @param[in] l_inventoryPath - DBus inventory path.
Rekha Aparnae0d24c02025-09-02 00:15:06 -0500969 * @param[out] o_errCode - To set error code in case of error.
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500970 *
971 * @return On success returns the service name present in the system config
972 * JSON, otherwise empty string.
973 *
974 * Note: Caller has to handle in case of empty string received.
975 */
976inline std::string getServiceName(const nlohmann::json& i_sysCfgJsonObj,
Rekha Aparnae0d24c02025-09-02 00:15:06 -0500977 const std::string& l_inventoryPath,
978 uint16_t& o_errCode)
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500979{
Sunny Srivastava47085a22025-11-05 18:11:30 +0530980 o_errCode = 0;
Rekha Aparnae0d24c02025-09-02 00:15:06 -0500981 if (l_inventoryPath.empty())
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500982 {
Rekha Aparnae0d24c02025-09-02 00:15:06 -0500983 o_errCode = error_code::INVALID_INPUT_PARAMETER;
984 return std::string{};
985 }
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500986
Rekha Aparnae0d24c02025-09-02 00:15:06 -0500987 if (!i_sysCfgJsonObj.contains("frus"))
988 {
989 o_errCode = error_code::INVALID_JSON;
990 return std::string{};
991 }
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500992
Rekha Aparnae0d24c02025-09-02 00:15:06 -0500993 const nlohmann::json& l_listOfFrus =
994 i_sysCfgJsonObj["frus"].get_ref<const nlohmann::json::object_t&>();
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500995
Rekha Aparnae0d24c02025-09-02 00:15:06 -0500996 for (const auto& l_frus : l_listOfFrus.items())
997 {
998 for (const auto& l_inventoryItem : l_frus.value())
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500999 {
Rekha Aparnae0d24c02025-09-02 00:15:06 -05001000 if (l_inventoryPath.compare(l_inventoryItem["inventoryPath"]) ==
1001 constants::STR_CMP_SUCCESS)
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001002 {
Rekha Aparnae0d24c02025-09-02 00:15:06 -05001003 if (l_inventoryItem.contains("serviceName"))
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001004 {
Rekha Aparnae0d24c02025-09-02 00:15:06 -05001005 return l_inventoryItem.value("serviceName", "");
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001006 }
Rekha Aparnae0d24c02025-09-02 00:15:06 -05001007
1008 o_errCode = error_code::JSON_MISSING_SERVICE_NAME;
1009 return std::string{};
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001010 }
1011 }
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001012 }
Rekha Aparnae0d24c02025-09-02 00:15:06 -05001013
1014 o_errCode = error_code::FRU_PATH_NOT_FOUND;
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001015 return std::string{};
1016}
1017
1018/**
1019 * @brief An API to check if a FRU is tagged as "powerOffOnly"
1020 *
1021 * Given the system config JSON and VPD FRU path, this API checks if the FRU
1022 * VPD can be collected at Chassis Power Off state only.
1023 *
1024 * @param[in] i_sysCfgJsonObj - System config JSON object.
1025 * @param[in] i_vpdFruPath - EEPROM path.
Rekha Aparna52041882025-09-01 20:48:07 -05001026 * @param[out] o_errCode - To set error code for the error.
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001027 * @return - True if FRU VPD can be collected at Chassis Power Off state only.
1028 * False otherwise
1029 */
1030inline bool isFruPowerOffOnly(const nlohmann::json& i_sysCfgJsonObj,
Rekha Aparna52041882025-09-01 20:48:07 -05001031 const std::string& i_vpdFruPath,
1032 uint16_t& o_errCode)
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001033{
Sunny Srivastava47085a22025-11-05 18:11:30 +05301034 o_errCode = 0;
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001035 if (i_vpdFruPath.empty())
1036 {
Rekha Aparna52041882025-09-01 20:48:07 -05001037 o_errCode = error_code::INVALID_INPUT_PARAMETER;
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001038 return false;
1039 }
1040
1041 if (!i_sysCfgJsonObj.contains("frus"))
1042 {
Rekha Aparna52041882025-09-01 20:48:07 -05001043 o_errCode = error_code::INVALID_JSON;
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001044 return false;
1045 }
1046
1047 if (!i_sysCfgJsonObj["frus"].contains(i_vpdFruPath))
1048 {
Rekha Aparna52041882025-09-01 20:48:07 -05001049 o_errCode = error_code::FRU_PATH_NOT_FOUND;
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001050 return false;
1051 }
1052
1053 return ((i_sysCfgJsonObj["frus"][i_vpdFruPath].at(0))
1054 .contains("powerOffOnly") &&
1055 (i_sysCfgJsonObj["frus"][i_vpdFruPath].at(0)["powerOffOnly"]));
1056}
1057
1058/**
1059 * @brief API which tells if the FRU is replaceable at runtime
1060 *
1061 * @param[in] i_sysCfgJsonObj - System config JSON object.
1062 * @param[in] i_vpdFruPath - EEPROM path.
Rekha Aparnaad0db9e2025-09-01 20:29:18 -05001063 * @param[out] o_errCode - to set error code in case of error.
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001064 *
1065 * @return true if FRU is replaceable at runtime. false otherwise.
1066 */
1067inline bool isFruReplaceableAtRuntime(const nlohmann::json& i_sysCfgJsonObj,
Rekha Aparnaad0db9e2025-09-01 20:29:18 -05001068 const std::string& i_vpdFruPath,
1069 uint16_t& o_errCode)
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001070{
Sunny Srivastava47085a22025-11-05 18:11:30 +05301071 o_errCode = 0;
Rekha Aparnaad0db9e2025-09-01 20:29:18 -05001072 if (i_vpdFruPath.empty())
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001073 {
Rekha Aparnaad0db9e2025-09-01 20:29:18 -05001074 o_errCode = error_code::INVALID_INPUT_PARAMETER;
1075 return false;
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001076 }
Rekha Aparnaad0db9e2025-09-01 20:29:18 -05001077
1078 if (i_sysCfgJsonObj.empty() || (!i_sysCfgJsonObj.contains("frus")))
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001079 {
Rekha Aparnaad0db9e2025-09-01 20:29:18 -05001080 o_errCode = error_code::INVALID_JSON;
1081 return false;
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001082 }
1083
Rekha Aparna41f47e72025-09-18 01:44:09 -05001084 if (!i_sysCfgJsonObj["frus"].contains(i_vpdFruPath))
1085 {
1086 o_errCode = error_code::FRU_PATH_NOT_FOUND;
1087 return false;
1088 }
1089
Rekha Aparnaad0db9e2025-09-01 20:29:18 -05001090 return (
1091 (i_sysCfgJsonObj["frus"][i_vpdFruPath].at(0))
1092 .contains("replaceableAtRuntime") &&
1093 (i_sysCfgJsonObj["frus"][i_vpdFruPath].at(0)["replaceableAtRuntime"]));
1094
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001095 return false;
1096}
1097
1098/**
1099 * @brief API which tells if the FRU is replaceable at standby
1100 *
1101 * @param[in] i_sysCfgJsonObj - System config JSON object.
1102 * @param[in] i_vpdFruPath - EEPROM path.
Rekha Aparna40845612025-09-01 19:58:56 -05001103 * @param[out] o_errCode - set error code in case of error.
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001104 *
1105 * @return true if FRU is replaceable at standby. false otherwise.
1106 */
1107inline bool isFruReplaceableAtStandby(const nlohmann::json& i_sysCfgJsonObj,
Rekha Aparna40845612025-09-01 19:58:56 -05001108 const std::string& i_vpdFruPath,
1109 uint16_t& o_errCode)
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001110{
Sunny Srivastava47085a22025-11-05 18:11:30 +05301111 o_errCode = 0;
Rekha Aparna40845612025-09-01 19:58:56 -05001112 if (i_vpdFruPath.empty())
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001113 {
Rekha Aparna40845612025-09-01 19:58:56 -05001114 o_errCode = error_code::INVALID_INPUT_PARAMETER;
1115 return false;
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001116 }
Rekha Aparna40845612025-09-01 19:58:56 -05001117
1118 if (i_sysCfgJsonObj.empty() || (!i_sysCfgJsonObj.contains("frus")))
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001119 {
Rekha Aparna40845612025-09-01 19:58:56 -05001120 o_errCode = error_code::INVALID_JSON;
Rekha Aparna41f47e72025-09-18 01:44:09 -05001121 return false;
1122 }
1123
1124 if (!i_sysCfgJsonObj["frus"].contains(i_vpdFruPath))
1125 {
1126 o_errCode = error_code::FRU_PATH_NOT_FOUND;
1127 return false;
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001128 }
1129
Rekha Aparna40845612025-09-01 19:58:56 -05001130 return (
1131 (i_sysCfgJsonObj["frus"][i_vpdFruPath].at(0))
1132 .contains("replaceableAtStandby") &&
1133 (i_sysCfgJsonObj["frus"][i_vpdFruPath].at(0)["replaceableAtStandby"]));
1134
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001135 return false;
1136}
1137
1138/**
1139 * @brief API to get list of FRUs replaceable at standby from JSON.
1140 *
1141 * The API will return a vector of FRUs inventory path which are replaceable at
1142 * standby.
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001143 *
1144 * @param[in] i_sysCfgJsonObj - System config JSON object.
Rekha Aparna88d53302025-09-01 18:16:55 -05001145 * @param[out] o_errCode - To set error code in case of error.
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001146 *
RekhaAparna017fea9f52025-02-17 04:14:02 -06001147 * @return - On success, list of FRUs replaceable at standby. On failure, empty
1148 * vector.
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001149 */
Patrick Williams43fedab2025-02-03 14:28:05 -05001150inline std::vector<std::string> getListOfFrusReplaceableAtStandby(
Rekha Aparna88d53302025-09-01 18:16:55 -05001151 const nlohmann::json& i_sysCfgJsonObj, uint16_t& o_errCode)
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001152{
1153 std::vector<std::string> l_frusReplaceableAtStandby;
Sunny Srivastava47085a22025-11-05 18:11:30 +05301154 o_errCode = 0;
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001155
Rekha Aparna88d53302025-09-01 18:16:55 -05001156 if (!i_sysCfgJsonObj.contains("frus"))
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001157 {
Rekha Aparna88d53302025-09-01 18:16:55 -05001158 o_errCode = error_code::INVALID_JSON;
1159 return l_frusReplaceableAtStandby;
1160 }
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001161
Rekha Aparna88d53302025-09-01 18:16:55 -05001162 const nlohmann::json& l_fruList =
1163 i_sysCfgJsonObj["frus"].get_ref<const nlohmann::json::object_t&>();
RekhaAparna017fea9f52025-02-17 04:14:02 -06001164
Rekha Aparna88d53302025-09-01 18:16:55 -05001165 for (const auto& l_fru : l_fruList.items())
1166 {
1167 if (i_sysCfgJsonObj["frus"][l_fru.key()].at(0).value(
1168 "replaceableAtStandby", false))
RekhaAparna017fea9f52025-02-17 04:14:02 -06001169 {
Rekha Aparna88d53302025-09-01 18:16:55 -05001170 const std::string& l_inventoryObjectPath =
1171 i_sysCfgJsonObj["frus"][l_fru.key()].at(0).value(
1172 "inventoryPath", "");
1173
1174 if (!l_inventoryObjectPath.empty())
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001175 {
Rekha Aparna88d53302025-09-01 18:16:55 -05001176 l_frusReplaceableAtStandby.emplace_back(l_inventoryObjectPath);
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001177 }
1178 }
1179 }
1180
1181 return l_frusReplaceableAtStandby;
1182}
1183
Sunny Srivastava022112b2025-02-19 19:53:29 +05301184/**
1185 * @brief API to select powerVS JSON based on system IM.
1186 *
1187 * The API selects respective JSON based on system IM, parse it and return the
1188 * JSON object. Empty JSON will be returned in case of any error. Caller needs
1189 * to handle empty value.
1190 *
1191 * @param[in] i_imValue - IM value of the system.
Rekha Aparnaadf85262025-09-09 00:41:00 -05001192 * @param[out] o_errCode - to set error code in case of error.
Sunny Srivastava022112b2025-02-19 19:53:29 +05301193 * @return Parsed JSON object, empty JSON otherwise.
1194 */
Rekha Aparnaadf85262025-09-09 00:41:00 -05001195inline nlohmann::json getPowerVsJson(const types::BinaryVector& i_imValue,
1196 uint16_t& o_errCode)
Sunny Srivastava022112b2025-02-19 19:53:29 +05301197{
Sunny Srivastava47085a22025-11-05 18:11:30 +05301198 o_errCode = 0;
Rekha Aparnaadf85262025-09-09 00:41:00 -05001199 if (i_imValue.empty() || i_imValue.size() < 4)
Sunny Srivastava022112b2025-02-19 19:53:29 +05301200 {
Rekha Aparnaadf85262025-09-09 00:41:00 -05001201 o_errCode = error_code::INVALID_INPUT_PARAMETER;
Sunny Srivastava022112b2025-02-19 19:53:29 +05301202 return nlohmann::json{};
1203 }
Rekha Aparnaadf85262025-09-09 00:41:00 -05001204
Rekha Aparnaadf85262025-09-09 00:41:00 -05001205 if ((i_imValue.at(0) == constants::HEX_VALUE_50) &&
1206 (i_imValue.at(1) == constants::HEX_VALUE_00) &&
1207 (i_imValue.at(2) == constants::HEX_VALUE_30))
Sunny Srivastava022112b2025-02-19 19:53:29 +05301208 {
Rekha Aparnaadf85262025-09-09 00:41:00 -05001209 nlohmann::json l_parsedJson = jsonUtility::getParsedJson(
1210 constants::power_vs_50003_json, o_errCode);
1211
1212 if (o_errCode)
1213 {
1214 logging::logMessage(
1215 "Failed to parse JSON file [ " +
1216 std::string(constants::power_vs_50003_json) +
Rekha Aparnac6159a22025-10-09 12:20:20 +05301217 " ], error : " + commonUtility::getErrCodeMsg(o_errCode));
Rekha Aparnaadf85262025-09-09 00:41:00 -05001218 }
1219
1220 return l_parsedJson;
Sunny Srivastava022112b2025-02-19 19:53:29 +05301221 }
Rekha Aparnaadf85262025-09-09 00:41:00 -05001222 else if (i_imValue.at(0) == constants::HEX_VALUE_50 &&
1223 (i_imValue.at(1) == constants::HEX_VALUE_00) &&
1224 (i_imValue.at(2) == constants::HEX_VALUE_10))
1225 {
1226 nlohmann::json l_parsedJson = jsonUtility::getParsedJson(
1227 constants::power_vs_50001_json, o_errCode);
1228
1229 if (o_errCode)
1230 {
1231 logging::logMessage(
1232 "Failed to parse JSON file [ " +
1233 std::string(constants::power_vs_50001_json) +
Rekha Aparnac6159a22025-10-09 12:20:20 +05301234 " ], error : " + commonUtility::getErrCodeMsg(o_errCode));
Rekha Aparnaadf85262025-09-09 00:41:00 -05001235 }
1236
1237 return l_parsedJson;
1238 }
1239 return nlohmann::json{};
Sunny Srivastava022112b2025-02-19 19:53:29 +05301240}
Souvik Roy495eedd2025-07-02 02:13:43 -05001241
1242/**
1243 * @brief API to get list of FRUs for which "monitorPresence" is true.
1244 *
1245 * @param[in] i_sysCfgJsonObj - System config JSON object.
Rekha Aparna2362bed2025-09-01 13:18:40 -05001246 * @param[out] o_errCode - To set error code in case of error.
Souvik Roy495eedd2025-07-02 02:13:43 -05001247 *
1248 * @return On success, returns list of FRUs for which "monitorPresence" is true,
1249 * empty list on error.
1250 */
1251inline std::vector<types::Path> getFrusWithPresenceMonitoring(
Rekha Aparna2362bed2025-09-01 13:18:40 -05001252 const nlohmann::json& i_sysCfgJsonObj, uint16_t& o_errCode)
Souvik Roy495eedd2025-07-02 02:13:43 -05001253{
1254 std::vector<types::Path> l_frusWithPresenceMonitoring;
Sunny Srivastava47085a22025-11-05 18:11:30 +05301255 o_errCode = 0;
Rekha Aparna2362bed2025-09-01 13:18:40 -05001256
1257 if (!i_sysCfgJsonObj.contains("frus"))
Souvik Roy495eedd2025-07-02 02:13:43 -05001258 {
Rekha Aparna2362bed2025-09-01 13:18:40 -05001259 o_errCode = error_code::INVALID_JSON;
1260 return l_frusWithPresenceMonitoring;
1261 }
Souvik Roy495eedd2025-07-02 02:13:43 -05001262
Rekha Aparna2362bed2025-09-01 13:18:40 -05001263 const nlohmann::json& l_listOfFrus =
1264 i_sysCfgJsonObj["frus"].get_ref<const nlohmann::json::object_t&>();
Souvik Roy495eedd2025-07-02 02:13:43 -05001265
Rekha Aparna2362bed2025-09-01 13:18:40 -05001266 for (const auto& l_aFru : l_listOfFrus)
1267 {
1268 if (l_aFru.at(0).value("monitorPresence", false))
Souvik Roy495eedd2025-07-02 02:13:43 -05001269 {
Rekha Aparna2362bed2025-09-01 13:18:40 -05001270 l_frusWithPresenceMonitoring.emplace_back(
1271 l_aFru.at(0).value("inventoryPath", ""));
Souvik Roy495eedd2025-07-02 02:13:43 -05001272 }
1273 }
Rekha Aparna2362bed2025-09-01 13:18:40 -05001274
Souvik Roy495eedd2025-07-02 02:13:43 -05001275 return l_frusWithPresenceMonitoring;
1276}
Souvik Roye9120152025-07-02 08:24:38 -05001277
1278/**
1279 * @brief API which tells if the FRU's presence is handled
1280 *
1281 * For a given FRU, this API checks if it's presence is handled by vpd-manager
1282 * by checking the "handlePresence" tag.
1283 *
1284 * @param[in] i_sysCfgJsonObj - System config JSON object.
1285 * @param[in] i_vpdFruPath - EEPROM path.
Rekha Aparnaa1187a52025-09-01 12:42:19 -05001286 * @param[out] o_errCode - To set error code in case of failure.
Souvik Roye9120152025-07-02 08:24:38 -05001287 *
1288 * @return true if FRU presence is handled, false otherwise.
1289 */
1290inline bool isFruPresenceHandled(const nlohmann::json& i_sysCfgJsonObj,
Rekha Aparnaa1187a52025-09-01 12:42:19 -05001291 const std::string& i_vpdFruPath,
1292 uint16_t& o_errCode)
Souvik Roye9120152025-07-02 08:24:38 -05001293{
Sunny Srivastava47085a22025-11-05 18:11:30 +05301294 o_errCode = 0;
Rekha Aparnaa1187a52025-09-01 12:42:19 -05001295 if (i_vpdFruPath.empty())
Souvik Roye9120152025-07-02 08:24:38 -05001296 {
Rekha Aparnaa1187a52025-09-01 12:42:19 -05001297 o_errCode = error_code::INVALID_INPUT_PARAMETER;
1298 return false;
Souvik Roye9120152025-07-02 08:24:38 -05001299 }
1300
Rekha Aparnaa1187a52025-09-01 12:42:19 -05001301 if (!i_sysCfgJsonObj.contains("frus"))
1302 {
1303 o_errCode = error_code::INVALID_JSON;
1304 return false;
1305 }
1306
1307 if (!i_sysCfgJsonObj["frus"].contains(i_vpdFruPath))
1308 {
1309 o_errCode = error_code::FRU_PATH_NOT_FOUND;
1310 return false;
1311 }
1312
1313 return i_sysCfgJsonObj["frus"][i_vpdFruPath].at(0).value(
1314 "handlePresence", true);
Souvik Roye9120152025-07-02 08:24:38 -05001315}
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001316} // namespace jsonUtility
1317} // namespace vpd