blob: 4b44179cd6b5fabb8960cf33868c0d6ccc6cbde7 [file] [log] [blame]
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001#pragma once
2
3#include "event_logger.hpp"
4#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.
22bool processSystemCmdTag(const nlohmann::json& i_parsedConfigJson,
23 const std::string& i_vpdFilePath,
24 const std::string& i_baseAction,
25 const std::string& i_flagToProcess);
26
27// forward declaration of API for function map.
28bool processGpioPresenceTag(
29 const nlohmann::json& i_parsedConfigJson, const std::string& i_vpdFilePath,
30 const std::string& i_baseAction, const std::string& i_flagToProcess);
31
32// forward declaration of API for function map.
33bool procesSetGpioTag(const nlohmann::json& i_parsedConfigJson,
34 const std::string& i_vpdFilePath,
35 const std::string& i_baseAction,
36 const std::string& i_flagToProcess);
37
38// Function pointers to process tags from config JSON.
39typedef bool (*functionPtr)(
40 const nlohmann::json& i_parsedConfigJson, const std::string& i_vpdFilePath,
41 const std::string& i_baseAction, const std::string& i_flagToProcess);
42
43inline std::unordered_map<std::string, functionPtr> funcionMap{
44 {"gpioPresence", processGpioPresenceTag},
45 {"setGpio", procesSetGpioTag},
46 {"systemCmd", processSystemCmdTag}};
47
48/**
49 * @brief API to read VPD offset from JSON file.
50 *
51 * @param[in] i_sysCfgJsonObj - Parsed system config JSON object.
52 * @param[in] i_vpdFilePath - VPD file path.
53 * @return VPD offset if found in JSON, 0 otherwise.
54 */
55inline size_t getVPDOffset(const nlohmann::json& i_sysCfgJsonObj,
56 const std::string& i_vpdFilePath)
57{
58 if (i_vpdFilePath.empty() || (i_sysCfgJsonObj.empty()) ||
59 (!i_sysCfgJsonObj.contains("frus")))
60 {
61 return 0;
62 }
63
64 if (i_sysCfgJsonObj["frus"].contains(i_vpdFilePath))
65 {
66 return i_sysCfgJsonObj["frus"][i_vpdFilePath].at(0).value("offset", 0);
67 }
68
69 const nlohmann::json& l_fruList =
70 i_sysCfgJsonObj["frus"].get_ref<const nlohmann::json::object_t&>();
71
72 for (const auto& l_fru : l_fruList.items())
73 {
74 const auto l_fruPath = l_fru.key();
75
76 // check if given path is redundant FRU path
77 if (i_vpdFilePath == i_sysCfgJsonObj["frus"][l_fruPath].at(0).value(
78 "redundantEeprom", ""))
79 {
80 // Return the offset of redundant EEPROM taken from JSON.
81 return i_sysCfgJsonObj["frus"][l_fruPath].at(0).value("offset", 0);
82 }
83 }
84
85 return 0;
86}
87
88/**
89 * @brief API to parse respective JSON.
90 *
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -050091 * @param[in] pathToJson - Path to JSON.
RekhaAparna011ef21002025-02-18 23:47:36 -060092 * @return on success parsed JSON. On failure empty JSON object.
93 *
94 * Note: Caller has to handle it in case an empty JSON object is received.
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -050095 */
RekhaAparna011ef21002025-02-18 23:47:36 -060096inline nlohmann::json getParsedJson(const std::string& pathToJson) noexcept
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -050097{
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -050098 try
99 {
RekhaAparna011ef21002025-02-18 23:47:36 -0600100 if (pathToJson.empty())
101 {
102 throw std::runtime_error("Path to JSON is missing");
103 }
104
105 if (!std::filesystem::exists(pathToJson) ||
106 std::filesystem::is_empty(pathToJson))
107 {
108 throw std::runtime_error("Incorrect file Path or empty file");
109 }
110
111 std::ifstream l_jsonFile(pathToJson);
112 if (!l_jsonFile)
113 {
114 throw std::runtime_error(
115 "Failed to access Json path = " + pathToJson);
116 }
117
118 return nlohmann::json::parse(l_jsonFile);
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500119 }
RekhaAparna011ef21002025-02-18 23:47:36 -0600120 catch (const std::exception& l_ex)
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500121 {
RekhaAparna011ef21002025-02-18 23:47:36 -0600122 logging::logMessage(
123 "Failed to parse JSON file, error: " + std::string(l_ex.what()));
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500124 }
RekhaAparna011ef21002025-02-18 23:47:36 -0600125
126 return nlohmann::json{};
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500127}
128
129/**
130 * @brief Get inventory object path from system config JSON.
131 *
132 * Given either D-bus inventory path/FRU EEPROM path/redundant EEPROM path,
133 * this API returns D-bus inventory path if present in JSON.
134 *
135 * @param[in] i_sysCfgJsonObj - System config JSON object
136 * @param[in] i_vpdPath - Path to where VPD is stored.
137 *
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500138 * @return On success a valid path is returned, on failure an empty string is
RekhaAparna011ef21002025-02-18 23:47:36 -0600139 * returned.
140 *
141 * Note: Caller has to handle it in case an empty string is received.
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500142 */
143inline std::string getInventoryObjPathFromJson(
RekhaAparna011ef21002025-02-18 23:47:36 -0600144 const nlohmann::json& i_sysCfgJsonObj,
145 const std::string& i_vpdPath) noexcept
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500146{
RekhaAparna011ef21002025-02-18 23:47:36 -0600147 try
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500148 {
RekhaAparna011ef21002025-02-18 23:47:36 -0600149 if (i_vpdPath.empty())
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500150 {
RekhaAparna011ef21002025-02-18 23:47:36 -0600151 throw std::runtime_error("Path parameter is empty.");
152 }
153
154 if (!i_sysCfgJsonObj.contains("frus"))
155 {
156 throw std::runtime_error("Missing frus tag in system config JSON.");
157 }
158
159 // check if given path is FRU path
160 if (i_sysCfgJsonObj["frus"].contains(i_vpdPath))
161 {
162 return i_sysCfgJsonObj["frus"][i_vpdPath].at(0).value(
163 "inventoryPath", "");
164 }
165
166 const nlohmann::json& l_fruList =
167 i_sysCfgJsonObj["frus"].get_ref<const nlohmann::json::object_t&>();
168
169 for (const auto& l_fru : l_fruList.items())
170 {
171 const auto l_fruPath = l_fru.key();
172 const auto l_invObjPath =
173 i_sysCfgJsonObj["frus"][l_fruPath].at(0).value("inventoryPath",
174 "");
175
176 // check if given path is redundant FRU path or inventory path
177 if (i_vpdPath == i_sysCfgJsonObj["frus"][l_fruPath].at(0).value(
178 "redundantEeprom", "") ||
179 (i_vpdPath == l_invObjPath))
180 {
181 return l_invObjPath;
182 }
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500183 }
184 }
RekhaAparna011ef21002025-02-18 23:47:36 -0600185 catch (const std::exception& l_ex)
186 {
187 logging::logMessage(
188 "Failed to get inventory object path from json, error: " +
189 std::string(l_ex.what()));
190 }
191
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500192 return std::string();
193}
194
195/**
196 * @brief Process "PostFailAction" defined in config JSON.
197 *
198 * In case there is some error in the processing of "preAction" execution and a
199 * set of procedure needs to be done as a part of post fail action. This base
200 * action can be defined in the config JSON for that FRU and it will be handled
201 * under this API.
202 *
203 * @param[in] i_parsedConfigJson - config JSON
204 * @param[in] i_vpdFilePath - EEPROM file path
205 * @param[in] i_flagToProcess - To identify which flag(s) needs to be processed
206 * under PostFailAction tag of config JSON.
207 * @return - success or failure
208 */
209inline bool executePostFailAction(const nlohmann::json& i_parsedConfigJson,
210 const std::string& i_vpdFilePath,
211 const std::string& i_flagToProcess)
212{
RekhaAparna01c11e8b62025-02-20 00:34:35 -0600213 try
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500214 {
RekhaAparna01c11e8b62025-02-20 00:34:35 -0600215 if (i_parsedConfigJson.empty() || i_vpdFilePath.empty() ||
216 i_flagToProcess.empty())
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500217 {
RekhaAparna01c11e8b62025-02-20 00:34:35 -0600218 throw std::runtime_error(
219 "Invalid parameters. Abort processing for post fail action");
220 }
221
222 if (!(i_parsedConfigJson["frus"][i_vpdFilePath].at(0))["postFailAction"]
223 .contains(i_flagToProcess))
224 {
225 throw std::runtime_error(
226 "Config JSON missing flag " + i_flagToProcess +
227 " to execute post fail action for path = " + i_vpdFilePath);
228 }
229
230 for (const auto& l_tags : (i_parsedConfigJson["frus"][i_vpdFilePath].at(
231 0))["postFailAction"][i_flagToProcess]
232 .items())
233 {
234 auto itrToFunction = funcionMap.find(l_tags.key());
235 if (itrToFunction != funcionMap.end())
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500236 {
RekhaAparna01c11e8b62025-02-20 00:34:35 -0600237 if (!itrToFunction->second(i_parsedConfigJson, i_vpdFilePath,
238 "postFailAction", i_flagToProcess))
239 {
240 return false;
241 }
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500242 }
243 }
244 }
RekhaAparna01c11e8b62025-02-20 00:34:35 -0600245 catch (const std::exception& l_ex)
246 {
247 logging::logMessage("Execute post fail action failed. Error : " +
248 std::string(l_ex.what()));
249 return false;
250 }
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500251
252 return true;
253}
254
255/**
256 * @brief Process "systemCmd" tag for a given FRU.
257 *
258 * The API will process "systemCmd" tag if it is defined in the config
259 * JSON for the given FRU.
260 *
261 * @param[in] i_parsedConfigJson - config JSON
262 * @param[in] i_vpdFilePath - EEPROM file path
263 * @param[in] i_baseAction - Base action for which this tag has been called.
264 * @param[in] i_flagToProcess - Flag nested under the base action for which this
265 * tag has been called.
266 * @return Execution status.
267 */
268inline bool processSystemCmdTag(
269 const nlohmann::json& i_parsedConfigJson, const std::string& i_vpdFilePath,
270 const std::string& i_baseAction, const std::string& i_flagToProcess)
271{
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500272 try
273 {
RekhaAparna01c11e8b62025-02-20 00:34:35 -0600274 if (i_vpdFilePath.empty() || i_parsedConfigJson.empty() ||
275 i_baseAction.empty() || i_flagToProcess.empty())
276 {
277 throw std::runtime_error(
Sunny Srivastava0a5fce12025-04-09 11:09:51 +0530278 std::string(__FUNCTION__) +
279 " Invalid parameter. Abort processing of processSystemCmd.");
RekhaAparna01c11e8b62025-02-20 00:34:35 -0600280 }
281
282 if (!((i_parsedConfigJson["frus"][i_vpdFilePath].at(
283 0)[i_baseAction][i_flagToProcess]["systemCmd"])
284 .contains("cmd")))
285 {
Sunny Srivastava0a5fce12025-04-09 11:09:51 +0530286 throw JsonException(
287 std::string(__FUNCTION__) +
288 " Config JSON missing required information to execute system command for EEPROM " +
RekhaAparna01c11e8b62025-02-20 00:34:35 -0600289 i_vpdFilePath);
290 }
291
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500292 const std::string& l_systemCommand =
293 i_parsedConfigJson["frus"][i_vpdFilePath].at(
294 0)[i_baseAction][i_flagToProcess]["systemCmd"]["cmd"];
295
296 commonUtility::executeCmd(l_systemCommand);
297 return true;
298 }
RekhaAparna01c11e8b62025-02-20 00:34:35 -0600299 catch (const std::exception& l_ex)
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500300 {
Sunny Srivastava0a5fce12025-04-09 11:09:51 +0530301 EventLogger::createSyncPel(
302 EventLogger::getErrorType(l_ex), types::SeverityType::Informational,
303 __FILE__, __FUNCTION__, 0, EventLogger::getErrorMsg(l_ex),
304 std::nullopt, std::nullopt, std::nullopt, std::nullopt);
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500305 return false;
306 }
307}
308
309/**
310 * @brief Checks for presence of a given FRU using GPIO line.
311 *
312 * This API returns the presence information of the FRU corresponding to the
313 * given VPD file path by setting the presence pin.
314 *
315 * @param[in] i_parsedConfigJson - config JSON
316 * @param[in] i_vpdFilePath - EEPROM file path
317 * @param[in] i_baseAction - Base action for which this tag has been called.
318 * @param[in] i_flagToProcess - Flag nested under the base action for which this
319 * tag has been called.
320 * @return Execution status.
321 */
322inline bool processGpioPresenceTag(
323 const nlohmann::json& i_parsedConfigJson, const std::string& i_vpdFilePath,
324 const std::string& i_baseAction, const std::string& i_flagToProcess)
325{
Sunny Srivastava0a5fce12025-04-09 11:09:51 +0530326 std::string l_presencePinName;
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500327 try
328 {
Sunny Srivastava0a5fce12025-04-09 11:09:51 +0530329 if (i_vpdFilePath.empty() || i_parsedConfigJson.empty() ||
330 i_baseAction.empty() || i_flagToProcess.empty())
331 {
332 throw std::runtime_error(
333 std::string(__FUNCTION__) +
334 "Invalid parameter. Abort processing of processGpioPresence tag");
335 }
336
337 if (!(((i_parsedConfigJson["frus"][i_vpdFilePath].at(
338 0)[i_baseAction][i_flagToProcess]["gpioPresence"])
339 .contains("pin")) &&
340 ((i_parsedConfigJson["frus"][i_vpdFilePath].at(
341 0)[i_baseAction][i_flagToProcess]["gpioPresence"])
342 .contains("value"))))
343 {
344 throw JsonException(
345 std::string(__FUNCTION__) +
346 "Config JSON missing required information to detect presence for EEPROM " +
347 i_vpdFilePath);
348 }
349
350 // get the pin name
351 l_presencePinName = i_parsedConfigJson["frus"][i_vpdFilePath].at(
352 0)[i_baseAction][i_flagToProcess]["gpioPresence"]["pin"];
353
354 // get the pin value
355 uint8_t l_presencePinValue =
356 i_parsedConfigJson["frus"][i_vpdFilePath].at(
357 0)[i_baseAction][i_flagToProcess]["gpioPresence"]["value"];
358
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500359 gpiod::line l_presenceLine = gpiod::find_line(l_presencePinName);
360
361 if (!l_presenceLine)
362 {
363 throw GpioException("Couldn't find the GPIO line.");
364 }
365
366 l_presenceLine.request({"Read the presence line",
367 gpiod::line_request::DIRECTION_INPUT, 0});
368
369 return (l_presencePinValue == l_presenceLine.get_value());
370 }
Sunny Srivastava0a5fce12025-04-09 11:09:51 +0530371 catch (const std::exception& l_ex)
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500372 {
Sunny Srivastavac09e2102025-04-23 10:47:06 +0530373 // No need to continue in case of JSON failure or Firmware error
374 // as these are errors internal to the code and in that case the FRU
375 // should not be processed. Any other error is considered as external
376 // error in this case and a try to read the EEPROM should be done.
377 if (EventLogger::getErrorType(l_ex) == types::ErrorType::JsonFailure ||
378 EventLogger::getErrorType(l_ex) == types::ErrorType::FirmwareError)
Sunny Srivastava0a5fce12025-04-09 11:09:51 +0530379 {
380 EventLogger::createSyncPel(
381 EventLogger::getErrorType(l_ex),
382 types::SeverityType::Informational, __FILE__, __FUNCTION__, 0,
383 EventLogger::getErrorMsg(l_ex), std::nullopt, std::nullopt,
384 std::nullopt, std::nullopt);
385 return false;
386 }
387
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500388 std::string l_errMsg = "Exception on GPIO line: ";
389 l_errMsg += l_presencePinName;
390 l_errMsg += " Reason: ";
Sunny Srivastava0a5fce12025-04-09 11:09:51 +0530391 l_errMsg += l_ex.what();
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500392 l_errMsg += " File: " + i_vpdFilePath + " Pel Logged";
393
394 // ToDo -- Update Internal Rc code.
395 EventLogger::createAsyncPelWithInventoryCallout(
Sunny Srivastava0a5fce12025-04-09 11:09:51 +0530396 EventLogger::getErrorType(l_ex), types::SeverityType::Informational,
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500397 {{getInventoryObjPathFromJson(i_parsedConfigJson, i_vpdFilePath),
398 types::CalloutPriority::High}},
399 std::source_location::current().file_name(),
400 std::source_location::current().function_name(), 0, l_errMsg,
401 std::nullopt, std::nullopt, std::nullopt, std::nullopt);
402
403 logging::logMessage(l_errMsg);
404
405 // Except when GPIO pin value is false, we go and try collecting the
406 // FRU VPD as we couldn't able to read GPIO pin value due to some
407 // error/exception. So returning true in error scenario.
408 return true;
409 }
410}
411
412/**
413 * @brief Process "setGpio" tag for a given FRU.
414 *
415 * This API enables the GPIO line.
416 *
417 * @param[in] i_parsedConfigJson - config JSON
418 * @param[in] i_vpdFilePath - EEPROM file path
419 * @param[in] i_baseAction - Base action for which this tag has been called.
420 * @param[in] i_flagToProcess - Flag nested under the base action for which this
421 * tag has been called.
422 * @return Execution status.
423 */
424inline bool procesSetGpioTag(
425 const nlohmann::json& i_parsedConfigJson, const std::string& i_vpdFilePath,
426 const std::string& i_baseAction, const std::string& i_flagToProcess)
427{
Sunny Srivastava0a5fce12025-04-09 11:09:51 +0530428 std::string l_pinName;
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500429 try
430 {
Sunny Srivastava0a5fce12025-04-09 11:09:51 +0530431 if (i_vpdFilePath.empty() || i_parsedConfigJson.empty() ||
432 i_baseAction.empty() || i_flagToProcess.empty())
433 {
434 throw std::runtime_error(
435 std::string(__FUNCTION__) +
436 " Invalid parameter. Abort processing of procesSetGpio.");
437 }
438
439 if (!(((i_parsedConfigJson["frus"][i_vpdFilePath].at(
440 0)[i_baseAction][i_flagToProcess]["setGpio"])
441 .contains("pin")) &&
442 ((i_parsedConfigJson["frus"][i_vpdFilePath].at(
443 0)[i_baseAction][i_flagToProcess]["setGpio"])
444 .contains("value"))))
445 {
446 throw JsonException(
447 std::string(__FUNCTION__) +
448 " Config JSON missing required information to set gpio line for EEPROM " +
449 i_vpdFilePath);
450 }
451
452 l_pinName = i_parsedConfigJson["frus"][i_vpdFilePath].at(
453 0)[i_baseAction][i_flagToProcess]["setGpio"]["pin"];
454
455 // Get the value to set
456 uint8_t l_pinValue = i_parsedConfigJson["frus"][i_vpdFilePath].at(
457 0)[i_baseAction][i_flagToProcess]["setGpio"]["value"];
458
459 logging::logMessage(
460 "Setting GPIO: " + l_pinName + " to " + std::to_string(l_pinValue));
461
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500462 gpiod::line l_outputLine = gpiod::find_line(l_pinName);
463
464 if (!l_outputLine)
465 {
466 throw GpioException("Couldn't find GPIO line.");
467 }
468
469 l_outputLine.request(
470 {"FRU Action", ::gpiod::line_request::DIRECTION_OUTPUT, 0},
471 l_pinValue);
472 return true;
473 }
Sunny Srivastava0a5fce12025-04-09 11:09:51 +0530474 catch (const std::exception& l_ex)
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500475 {
Sunny Srivastava0a5fce12025-04-09 11:09:51 +0530476 if (EventLogger::getErrorType(l_ex) != types::ErrorType::GpioError)
477 {
478 EventLogger::createSyncPel(
479 EventLogger::getErrorType(l_ex),
480 types::SeverityType::Informational, __FILE__, __FUNCTION__, 0,
481 EventLogger::getErrorMsg(l_ex), std::nullopt, std::nullopt,
482 std::nullopt, std::nullopt);
483 }
484 else
485 {
486 std::string l_errMsg = "Exception on GPIO line: ";
487 l_errMsg += l_pinName;
488 l_errMsg += " Reason: ";
489 l_errMsg += l_ex.what();
490 l_errMsg += " File: " + i_vpdFilePath + " Pel Logged";
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500491
Sunny Srivastava0a5fce12025-04-09 11:09:51 +0530492 // ToDo -- Update Internal RC code
493 EventLogger::createAsyncPelWithInventoryCallout(
494 EventLogger::getErrorType(l_ex),
495 types::SeverityType::Informational,
496 {{getInventoryObjPathFromJson(i_parsedConfigJson,
497 i_vpdFilePath),
498 types::CalloutPriority::High}},
499 std::source_location::current().file_name(),
500 std::source_location::current().function_name(), 0, l_errMsg,
501 std::nullopt, std::nullopt, std::nullopt, std::nullopt);
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500502
Sunny Srivastava0a5fce12025-04-09 11:09:51 +0530503 logging::logMessage(l_errMsg);
504 }
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500505
506 return false;
507 }
508}
509
510/**
511 * @brief Process any action, if defined in config JSON.
512 *
513 * If any FRU(s) requires any special handling, then this base action can be
514 * defined for that FRU in the config JSON, processing of which will be handled
515 * in this API.
516 * Examples of action - preAction, PostAction etc.
517 *
518 * @param[in] i_parsedConfigJson - config JSON
519 * @param[in] i_action - Base action to be performed.
520 * @param[in] i_vpdFilePath - EEPROM file path
521 * @param[in] i_flagToProcess - To identify which flag(s) needs to be processed
522 * under PreAction tag of config JSON.
523 * @return - success or failure
524 */
525inline bool executeBaseAction(
526 const nlohmann::json& i_parsedConfigJson, const std::string& i_action,
527 const std::string& i_vpdFilePath, const std::string& i_flagToProcess)
528{
Sunny Srivastava0a5fce12025-04-09 11:09:51 +0530529 try
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500530 {
Sunny Srivastava0a5fce12025-04-09 11:09:51 +0530531 if (i_flagToProcess.empty() || i_action.empty() ||
532 i_vpdFilePath.empty() || !i_parsedConfigJson.contains("frus"))
533 {
534 throw std::runtime_error(
535 std::string(__FUNCTION__) + " Invalid parameter");
536 }
537
538 if (!i_parsedConfigJson["frus"].contains(i_vpdFilePath))
539 {
540 throw JsonException(std::string(__FUNCTION__) + " File path: " +
541 i_vpdFilePath + " not found in JSON");
542 }
543
544 if (!i_parsedConfigJson["frus"][i_vpdFilePath].at(0).contains(i_action))
545 {
546 throw JsonException(
547 std::string(__FUNCTION__) + " Action [" + i_action +
548 "] not defined for file path:" + i_vpdFilePath);
549 }
550
551 if (!(i_parsedConfigJson["frus"][i_vpdFilePath].at(0))[i_action]
552 .contains(i_flagToProcess))
553 {
554 throw JsonException(
555 std::string(__FUNCTION__) + "Config JSON missing flag [" +
556 i_flagToProcess +
557 "] to execute action for path = " + i_vpdFilePath);
558 }
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500559 }
Sunny Srivastava0a5fce12025-04-09 11:09:51 +0530560 catch (const std::exception& l_ex)
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500561 {
Sunny Srivastava0a5fce12025-04-09 11:09:51 +0530562 EventLogger::createSyncPel(
563 EventLogger::getErrorType(l_ex), types::SeverityType::Informational,
564 __FILE__, __FUNCTION__, 0, EventLogger::getErrorMsg(l_ex),
565 std::nullopt, std::nullopt, std::nullopt, std::nullopt);
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500566 return false;
567 }
568
569 const nlohmann::json& l_tagsJson =
570 (i_parsedConfigJson["frus"][i_vpdFilePath].at(
571 0))[i_action][i_flagToProcess];
572
573 for (const auto& l_tag : l_tagsJson.items())
574 {
575 auto itrToFunction = funcionMap.find(l_tag.key());
576 if (itrToFunction != funcionMap.end())
577 {
578 if (!itrToFunction->second(i_parsedConfigJson, i_vpdFilePath,
579 i_action, i_flagToProcess))
580 {
581 // In case any of the tag fails to execute. Mark action
582 // as failed for that flag.
583 return false;
584 }
585 }
586 }
587
588 return true;
589}
590
591/**
592 * @brief Get redundant FRU path from system config JSON
593 *
594 * Given either D-bus inventory path/FRU path/redundant FRU path, this
595 * API returns the redundant FRU path taken from "redundantEeprom" tag from
596 * system config JSON.
597 *
598 * @param[in] i_sysCfgJsonObj - System config JSON object.
599 * @param[in] i_vpdPath - Path to where VPD is stored.
600 *
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500601 * @return On success return valid path, on failure return empty string.
602 */
603inline std::string getRedundantEepromPathFromJson(
RekhaAparna017fea9f52025-02-17 04:14:02 -0600604 const nlohmann::json& i_sysCfgJsonObj,
605 const std::string& i_vpdPath) noexcept
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500606{
RekhaAparna017fea9f52025-02-17 04:14:02 -0600607 try
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500608 {
RekhaAparna017fea9f52025-02-17 04:14:02 -0600609 if (i_vpdPath.empty())
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500610 {
RekhaAparna017fea9f52025-02-17 04:14:02 -0600611 throw std::runtime_error("Path parameter is empty.");
612 }
613
614 if (!i_sysCfgJsonObj.contains("frus"))
615 {
616 throw std::runtime_error("Missing frus tag in system config JSON.");
617 }
618
619 // check if given path is FRU path
620 if (i_sysCfgJsonObj["frus"].contains(i_vpdPath))
621 {
622 return i_sysCfgJsonObj["frus"][i_vpdPath].at(0).value(
623 "redundantEeprom", "");
624 }
625
626 const nlohmann::json& l_fruList =
627 i_sysCfgJsonObj["frus"].get_ref<const nlohmann::json::object_t&>();
628
629 for (const auto& l_fru : l_fruList.items())
630 {
631 const std::string& l_fruPath = l_fru.key();
632 const std::string& l_redundantFruPath =
633 i_sysCfgJsonObj["frus"][l_fruPath].at(0).value(
634 "redundantEeprom", "");
635
636 // check if given path is inventory path or redundant FRU path
637 if ((i_sysCfgJsonObj["frus"][l_fruPath].at(0).value(
638 "inventoryPath", "") == i_vpdPath) ||
639 (l_redundantFruPath == i_vpdPath))
640 {
641 return l_redundantFruPath;
642 }
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500643 }
644 }
RekhaAparna017fea9f52025-02-17 04:14:02 -0600645 catch (const std::exception& l_ex)
646 {
647 logging::logMessage("Failed to get redundant EEPROM path, error: " +
648 std::string(l_ex.what()));
649 }
650
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500651 return std::string();
652}
653
654/**
655 * @brief Get FRU EEPROM path from system config JSON
656 *
657 * Given either D-bus inventory path/FRU EEPROM path/redundant EEPROM path,
658 * this API returns FRU EEPROM path if present in JSON.
659 *
660 * @param[in] i_sysCfgJsonObj - System config JSON object
661 * @param[in] i_vpdPath - Path to where VPD is stored.
662 *
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500663 * @return On success return valid path, on failure return empty string.
664 */
665inline std::string getFruPathFromJson(const nlohmann::json& i_sysCfgJsonObj,
RekhaAparna017fea9f52025-02-17 04:14:02 -0600666 const std::string& i_vpdPath) noexcept
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500667{
RekhaAparna017fea9f52025-02-17 04:14:02 -0600668 try
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500669 {
RekhaAparna017fea9f52025-02-17 04:14:02 -0600670 if (i_vpdPath.empty())
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500671 {
RekhaAparna017fea9f52025-02-17 04:14:02 -0600672 throw std::runtime_error("Path parameter is empty.");
673 }
674
675 if (!i_sysCfgJsonObj.contains("frus"))
676 {
677 throw std::runtime_error("Missing frus tag in system config JSON.");
678 }
679
680 // check if given path is FRU path
681 if (i_sysCfgJsonObj["frus"].contains(i_vpdPath))
682 {
683 return i_vpdPath;
684 }
685
686 const nlohmann::json& l_fruList =
687 i_sysCfgJsonObj["frus"].get_ref<const nlohmann::json::object_t&>();
688
689 for (const auto& l_fru : l_fruList.items())
690 {
691 const auto l_fruPath = l_fru.key();
692
693 // check if given path is redundant FRU path or inventory path
694 if (i_vpdPath == i_sysCfgJsonObj["frus"][l_fruPath].at(0).value(
695 "redundantEeprom", "") ||
696 (i_vpdPath == i_sysCfgJsonObj["frus"][l_fruPath].at(0).value(
697 "inventoryPath", "")))
698 {
699 return l_fruPath;
700 }
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500701 }
702 }
RekhaAparna017fea9f52025-02-17 04:14:02 -0600703 catch (const std::exception& l_ex)
704 {
705 logging::logMessage("Failed to get FRU path from JSON, error: " +
706 std::string(l_ex.what()));
707 }
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.
721 *
722 * @return true if backup and restore is required, false otherwise.
723 */
724inline bool isBackupAndRestoreRequired(const nlohmann::json& i_sysCfgJsonObj)
725{
726 try
727 {
728 const std::string& l_backupAndRestoreCfgFilePath =
729 i_sysCfgJsonObj.value("backupRestoreConfigPath", "");
730 if (!l_backupAndRestoreCfgFilePath.empty() &&
731 std::filesystem::exists(l_backupAndRestoreCfgFilePath) &&
732 !std::filesystem::is_empty(l_backupAndRestoreCfgFilePath))
733 {
734 return true;
735 }
736 }
737 catch (std::exception& ex)
738 {
739 logging::logMessage(ex.what());
740 }
741 return false;
742}
743
744/** @brief API to check if an action is required for given EEPROM path.
745 *
746 * System config JSON can contain pre-action, post-action etc. like actions
747 * defined for an EEPROM path. The API will check if any such action is defined
748 * for the EEPROM.
749 *
750 * @param[in] i_sysCfgJsonObj - System config JSON object.
751 * @param[in] i_vpdFruPath - EEPROM path.
752 * @param[in] i_action - Action to be checked.
753 * @param[in] i_flowFlag - Denotes the flow w.r.t which the action should be
754 * triggered.
755 * @return - True if action is defined for the flow, false otherwise.
756 */
757inline bool isActionRequired(
758 const nlohmann::json& i_sysCfgJsonObj, const std::string& i_vpdFruPath,
759 const std::string& i_action, const std::string& i_flowFlag)
760{
761 if (i_vpdFruPath.empty() || i_action.empty() || i_flowFlag.empty())
762 {
763 logging::logMessage("Invalid parameters recieved.");
764 return false;
765 }
766
767 if (!i_sysCfgJsonObj.contains("frus"))
768 {
769 logging::logMessage("Invalid JSON object recieved.");
770 return false;
771 }
772
773 if (!i_sysCfgJsonObj["frus"].contains(i_vpdFruPath))
774 {
775 logging::logMessage(
776 "JSON object does not contain EEPROM path " + i_vpdFruPath);
777 return false;
778 }
779
780 if ((i_sysCfgJsonObj["frus"][i_vpdFruPath].at(0)).contains(i_action))
781 {
782 if ((i_sysCfgJsonObj["frus"][i_vpdFruPath].at(0))[i_action].contains(
783 i_flowFlag))
784 {
785 return true;
786 }
787
788 logging::logMessage("Flow flag: [" + i_flowFlag +
789 "], not found in JSON for path: " + i_vpdFruPath);
790 return false;
791 }
792 return false;
793}
794
795/**
796 * @brief An API to return list of FRUs that needs GPIO polling.
797 *
798 * An API that checks for the FRUs that requires GPIO polling and returns
799 * a list of FRUs that needs polling. Returns an empty list if there are
800 * no FRUs that requires polling.
801 *
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500802 * @param[in] i_sysCfgJsonObj - System config JSON object.
803 *
RekhaAparna017fea9f52025-02-17 04:14:02 -0600804 * @return On success list of FRUs parameters that needs polling. On failure,
805 * empty list.
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500806 */
Patrick Williams43fedab2025-02-03 14:28:05 -0500807inline std::vector<std::string> getListOfGpioPollingFrus(
RekhaAparna017fea9f52025-02-17 04:14:02 -0600808 const nlohmann::json& i_sysCfgJsonObj) noexcept
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500809{
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500810 std::vector<std::string> l_gpioPollingRequiredFrusList;
811
RekhaAparna017fea9f52025-02-17 04:14:02 -0600812 try
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500813 {
RekhaAparna017fea9f52025-02-17 04:14:02 -0600814 if (i_sysCfgJsonObj.empty())
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500815 {
RekhaAparna017fea9f52025-02-17 04:14:02 -0600816 throw std::runtime_error("Invalid Parameters");
817 }
818
819 if (!i_sysCfgJsonObj.contains("frus"))
820 {
821 throw std::runtime_error(
822 "Missing frus section in system config JSON");
823 }
824
825 for (const auto& l_fru : i_sysCfgJsonObj["frus"].items())
826 {
827 const auto l_fruPath = l_fru.key();
828
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500829 if (isActionRequired(i_sysCfgJsonObj, l_fruPath, "pollingRequired",
830 "hotPlugging"))
831 {
832 if (i_sysCfgJsonObj["frus"][l_fruPath]
833 .at(0)["pollingRequired"]["hotPlugging"]
834 .contains("gpioPresence"))
835 {
836 l_gpioPollingRequiredFrusList.push_back(l_fruPath);
837 }
838 }
839 }
RekhaAparna017fea9f52025-02-17 04:14:02 -0600840 }
841 catch (const std::exception& l_ex)
842 {
843 logging::logMessage("Failed to get list of GPIO polling FRUs, error: " +
844 std::string(l_ex.what()));
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500845 }
846
847 return l_gpioPollingRequiredFrusList;
848}
849
850/**
851 * @brief Get all related path(s) to update keyword value.
852 *
853 * Given FRU EEPROM path/Inventory path needs keyword's value update, this API
854 * returns tuple of FRU EEPROM path, inventory path and redundant EEPROM path if
855 * exists in the system config JSON.
856 *
857 * Note: If the inventory object path or redundant EEPROM path(s) are not found
858 * in the system config JSON, corresponding fields will have empty value in the
859 * returning tuple.
860 *
861 * @param[in] i_sysCfgJsonObj - System config JSON object.
862 * @param[in,out] io_vpdPath - Inventory object path or FRU EEPROM path.
863 *
864 * @return On success returns tuple of EEPROM path, inventory path & redundant
865 * path, on failure returns tuple with given input path alone.
866 */
867inline std::tuple<std::string, std::string, std::string>
868 getAllPathsToUpdateKeyword(const nlohmann::json& i_sysCfgJsonObj,
869 std::string io_vpdPath)
870{
871 types::Path l_inventoryObjPath;
872 types::Path l_redundantFruPath;
873 try
874 {
875 if (!i_sysCfgJsonObj.empty())
876 {
877 // Get hardware path from system config JSON.
878 const types::Path l_fruPath =
879 jsonUtility::getFruPathFromJson(i_sysCfgJsonObj, io_vpdPath);
880
881 if (!l_fruPath.empty())
882 {
883 io_vpdPath = l_fruPath;
884
885 // Get inventory object path from system config JSON
886 l_inventoryObjPath = jsonUtility::getInventoryObjPathFromJson(
887 i_sysCfgJsonObj, l_fruPath);
888
889 // Get redundant hardware path if present in system config JSON
890 l_redundantFruPath =
891 jsonUtility::getRedundantEepromPathFromJson(i_sysCfgJsonObj,
892 l_fruPath);
893 }
894 }
895 }
896 catch (const std::exception& l_exception)
897 {
898 logging::logMessage(
899 "Failed to get all paths to update keyword value, error " +
900 std::string(l_exception.what()));
901 }
902 return std::make_tuple(io_vpdPath, l_inventoryObjPath, l_redundantFruPath);
903}
904
905/**
906 * @brief An API to get DBus service name.
907 *
908 * Given DBus inventory path, this API returns DBus service name if present in
909 * the JSON.
910 *
911 * @param[in] i_sysCfgJsonObj - System config JSON object.
912 * @param[in] l_inventoryPath - DBus inventory path.
913 *
914 * @return On success returns the service name present in the system config
915 * JSON, otherwise empty string.
916 *
917 * Note: Caller has to handle in case of empty string received.
918 */
919inline std::string getServiceName(const nlohmann::json& i_sysCfgJsonObj,
920 const std::string& l_inventoryPath)
921{
922 try
923 {
924 if (l_inventoryPath.empty())
925 {
926 throw std::runtime_error("Path parameter is empty.");
927 }
928
929 if (!i_sysCfgJsonObj.contains("frus"))
930 {
931 throw std::runtime_error("Missing frus tag in system config JSON.");
932 }
933
934 const nlohmann::json& l_listOfFrus =
935 i_sysCfgJsonObj["frus"].get_ref<const nlohmann::json::object_t&>();
936
937 for (const auto& l_frus : l_listOfFrus.items())
938 {
939 for (const auto& l_inventoryItem : l_frus.value())
940 {
941 if (l_inventoryPath.compare(l_inventoryItem["inventoryPath"]) ==
942 constants::STR_CMP_SUCCESS)
943 {
944 return l_inventoryItem["serviceName"];
945 }
946 }
947 }
948 throw std::runtime_error(
949 "Inventory path not found in the system config JSON");
950 }
951 catch (const std::exception& l_exception)
952 {
953 logging::logMessage(
954 "Error while getting DBus service name for given path " +
955 l_inventoryPath + ", error: " + std::string(l_exception.what()));
956 // TODO:log PEL
957 }
958 return std::string{};
959}
960
961/**
962 * @brief An API to check if a FRU is tagged as "powerOffOnly"
963 *
964 * Given the system config JSON and VPD FRU path, this API checks if the FRU
965 * VPD can be collected at Chassis Power Off state only.
966 *
967 * @param[in] i_sysCfgJsonObj - System config JSON object.
968 * @param[in] i_vpdFruPath - EEPROM path.
969 * @return - True if FRU VPD can be collected at Chassis Power Off state only.
970 * False otherwise
971 */
972inline bool isFruPowerOffOnly(const nlohmann::json& i_sysCfgJsonObj,
973 const std::string& i_vpdFruPath)
974{
975 if (i_vpdFruPath.empty())
976 {
977 logging::logMessage("FRU path is empty.");
978 return false;
979 }
980
981 if (!i_sysCfgJsonObj.contains("frus"))
982 {
983 logging::logMessage("Missing frus tag in system config JSON.");
984 return false;
985 }
986
987 if (!i_sysCfgJsonObj["frus"].contains(i_vpdFruPath))
988 {
989 logging::logMessage("JSON object does not contain EEPROM path \'" +
990 i_vpdFruPath + "\'");
991 return false;
992 }
993
994 return ((i_sysCfgJsonObj["frus"][i_vpdFruPath].at(0))
995 .contains("powerOffOnly") &&
996 (i_sysCfgJsonObj["frus"][i_vpdFruPath].at(0)["powerOffOnly"]));
997}
998
999/**
1000 * @brief API which tells if the FRU is replaceable at runtime
1001 *
1002 * @param[in] i_sysCfgJsonObj - System config JSON object.
1003 * @param[in] i_vpdFruPath - EEPROM path.
1004 *
1005 * @return true if FRU is replaceable at runtime. false otherwise.
1006 */
1007inline bool isFruReplaceableAtRuntime(const nlohmann::json& i_sysCfgJsonObj,
1008 const std::string& i_vpdFruPath)
1009{
1010 try
1011 {
1012 if (i_vpdFruPath.empty())
1013 {
1014 throw std::runtime_error("Given FRU path is empty.");
1015 }
1016
1017 if (i_sysCfgJsonObj.empty() || (!i_sysCfgJsonObj.contains("frus")))
1018 {
1019 throw std::runtime_error("Invalid system config JSON object.");
1020 }
1021
1022 return ((i_sysCfgJsonObj["frus"][i_vpdFruPath].at(0))
1023 .contains("replaceableAtRuntime") &&
1024 (i_sysCfgJsonObj["frus"][i_vpdFruPath].at(
1025 0)["replaceableAtRuntime"]));
1026 }
1027 catch (const std::exception& l_error)
1028 {
1029 // TODO: Log PEL
1030 logging::logMessage(l_error.what());
1031 }
1032
1033 return false;
1034}
1035
1036/**
1037 * @brief API which tells if the FRU is replaceable at standby
1038 *
1039 * @param[in] i_sysCfgJsonObj - System config JSON object.
1040 * @param[in] i_vpdFruPath - EEPROM path.
1041 *
1042 * @return true if FRU is replaceable at standby. false otherwise.
1043 */
1044inline bool isFruReplaceableAtStandby(const nlohmann::json& i_sysCfgJsonObj,
1045 const std::string& i_vpdFruPath)
1046{
1047 try
1048 {
1049 if (i_vpdFruPath.empty())
1050 {
1051 throw std::runtime_error("Given FRU path is empty.");
1052 }
1053
1054 if (i_sysCfgJsonObj.empty() || (!i_sysCfgJsonObj.contains("frus")))
1055 {
1056 throw std::runtime_error("Invalid system config JSON object.");
1057 }
1058
1059 return ((i_sysCfgJsonObj["frus"][i_vpdFruPath].at(0))
1060 .contains("replaceableAtStandby") &&
1061 (i_sysCfgJsonObj["frus"][i_vpdFruPath].at(
1062 0)["replaceableAtStandby"]));
1063 }
1064 catch (const std::exception& l_error)
1065 {
1066 // TODO: Log PEL
1067 logging::logMessage(l_error.what());
1068 }
1069
1070 return false;
1071}
1072
1073/**
1074 * @brief API to get list of FRUs replaceable at standby from JSON.
1075 *
1076 * The API will return a vector of FRUs inventory path which are replaceable at
1077 * standby.
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001078 *
1079 * @param[in] i_sysCfgJsonObj - System config JSON object.
1080 *
RekhaAparna017fea9f52025-02-17 04:14:02 -06001081 * @return - On success, list of FRUs replaceable at standby. On failure, empty
1082 * vector.
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001083 */
Patrick Williams43fedab2025-02-03 14:28:05 -05001084inline std::vector<std::string> getListOfFrusReplaceableAtStandby(
RekhaAparna017fea9f52025-02-17 04:14:02 -06001085 const nlohmann::json& i_sysCfgJsonObj) noexcept
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001086{
1087 std::vector<std::string> l_frusReplaceableAtStandby;
1088
RekhaAparna017fea9f52025-02-17 04:14:02 -06001089 try
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001090 {
RekhaAparna017fea9f52025-02-17 04:14:02 -06001091 if (!i_sysCfgJsonObj.contains("frus"))
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001092 {
RekhaAparna017fea9f52025-02-17 04:14:02 -06001093 throw std::runtime_error("Missing frus tag in system config JSON.");
1094 }
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001095
RekhaAparna017fea9f52025-02-17 04:14:02 -06001096 const nlohmann::json& l_fruList =
1097 i_sysCfgJsonObj["frus"].get_ref<const nlohmann::json::object_t&>();
1098
1099 for (const auto& l_fru : l_fruList.items())
1100 {
1101 if (i_sysCfgJsonObj["frus"][l_fru.key()].at(0).value(
1102 "replaceableAtStandby", false))
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001103 {
RekhaAparna017fea9f52025-02-17 04:14:02 -06001104 const std::string& l_inventoryObjectPath =
1105 i_sysCfgJsonObj["frus"][l_fru.key()].at(0).value(
1106 "inventoryPath", "");
1107
1108 if (!l_inventoryObjectPath.empty())
1109 {
1110 l_frusReplaceableAtStandby.emplace_back(
1111 l_inventoryObjectPath);
1112 }
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001113 }
1114 }
1115 }
RekhaAparna017fea9f52025-02-17 04:14:02 -06001116 catch (const std::exception& l_ex)
1117 {
1118 logging::logMessage(
1119 "Failed to get list of FRUs replaceable at standby, error: " +
1120 std::string(l_ex.what()));
1121 }
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001122
1123 return l_frusReplaceableAtStandby;
1124}
1125
Sunny Srivastava022112b2025-02-19 19:53:29 +05301126/**
1127 * @brief API to select powerVS JSON based on system IM.
1128 *
1129 * The API selects respective JSON based on system IM, parse it and return the
1130 * JSON object. Empty JSON will be returned in case of any error. Caller needs
1131 * to handle empty value.
1132 *
1133 * @param[in] i_imValue - IM value of the system.
1134 * @return Parsed JSON object, empty JSON otherwise.
1135 */
1136inline nlohmann::json getPowerVsJson(const types::BinaryVector& i_imValue)
1137{
1138 try
1139 {
1140 if ((i_imValue.at(0) == constants::HEX_VALUE_50) &&
1141 (i_imValue.at(1) == constants::HEX_VALUE_00) &&
1142 (i_imValue.at(2) == constants::HEX_VALUE_30))
1143 {
1144 return jsonUtility::getParsedJson(constants::power_vs_50003_json);
1145 }
1146 else if (i_imValue.at(0) == constants::HEX_VALUE_50 &&
1147 (i_imValue.at(1) == constants::HEX_VALUE_00) &&
1148 (i_imValue.at(2) == constants::HEX_VALUE_10))
1149 {
1150 return jsonUtility::getParsedJson(constants::power_vs_50001_json);
1151 }
1152 return nlohmann::json{};
1153 }
1154 catch (const std::exception& l_ex)
1155 {
1156 return nlohmann::json{};
1157 }
1158}
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001159} // namespace jsonUtility
1160} // namespace vpd