1 #pragma once
2
3 #include "error_codes.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
16 namespace vpd
17 {
18 namespace jsonUtility
19 {
20
21 // forward declaration of API for function map.
22 bool 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);
26
27 // forward declaration of API for function map.
28 bool processGpioPresenceTag(
29 const nlohmann::json& i_parsedConfigJson, const std::string& i_vpdFilePath,
30 const std::string& i_baseAction, const std::string& i_flagToProcess,
31 uint16_t& o_errCode);
32
33 // forward declaration of API for function map.
34 bool procesSetGpioTag(const nlohmann::json& i_parsedConfigJson,
35 const std::string& i_vpdFilePath,
36 const std::string& i_baseAction,
37 const std::string& i_flagToProcess, uint16_t& o_errCode);
38
39 // Function pointers to process tags from config JSON.
40 typedef bool (*functionPtr)(
41 const nlohmann::json& i_parsedConfigJson, const std::string& i_vpdFilePath,
42 const std::string& i_baseAction, const std::string& i_flagToProcess,
43 uint16_t& o_errCode);
44
45 inline 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.
55 * @param[in] o_errCode - To set error code in case of error.
56 * @return VPD offset if found in JSON, 0 otherwise.
57 */
getVPDOffset(const nlohmann::json & i_sysCfgJsonObj,const std::string & i_vpdFilePath,uint16_t & o_errCode)58 inline size_t getVPDOffset(const nlohmann::json& i_sysCfgJsonObj,
59 const std::string& i_vpdFilePath,
60 uint16_t& o_errCode)
61 {
62 o_errCode = 0;
63 if (i_vpdFilePath.empty() || (i_sysCfgJsonObj.empty()) ||
64 (!i_sysCfgJsonObj.contains("frus")))
65 {
66 o_errCode = error_code::INVALID_INPUT_PARAMETER;
67 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 *
97 * @param[in] pathToJson - Path to JSON.
98 * @param[out] o_errCode - To set error code in case of error.
99 * @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.
102 */
getParsedJson(const std::string & pathToJson,uint16_t & o_errCode)103 inline nlohmann::json getParsedJson(const std::string& pathToJson,
104 uint16_t& o_errCode) noexcept
105 {
106 o_errCode = 0;
107 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
132 try
133 {
134 return nlohmann::json::parse(l_jsonFile);
135 }
136 catch (const std::exception& l_ex)
137 {
138 o_errCode = error_code::JSON_PARSE_ERROR;
139 return nlohmann::json{};
140 }
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.
151 * @param[in] o_errCode - To set error code in case of error.
152 *
153 * @return On success a valid path is returned, on failure an empty string is
154 * returned.
155 *
156 * Note: Caller has to handle it in case an empty string is received.
157 */
getInventoryObjPathFromJson(const nlohmann::json & i_sysCfgJsonObj,const std::string & i_vpdPath,uint16_t & o_errCode)158 inline std::string getInventoryObjPathFromJson(
159 const nlohmann::json& i_sysCfgJsonObj, const std::string& i_vpdPath,
160 uint16_t& o_errCode) noexcept
161 {
162 o_errCode = 0;
163 if (i_vpdPath.empty())
164 {
165 o_errCode = error_code::INVALID_INPUT_PARAMETER;
166 return std::string{};
167 }
168
169 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{};
201 }
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
214 * @param[out] o_errCode - To set error code in case of error
215 * under PostFailAction tag of config JSON.
216 * @return - success or failure
217 */
executePostFailAction(const nlohmann::json & i_parsedConfigJson,const std::string & i_vpdFilePath,const std::string & i_flagToProcess,uint16_t & o_errCode)218 inline bool executePostFailAction(
219 const nlohmann::json& i_parsedConfigJson, const std::string& i_vpdFilePath,
220 const std::string& i_flagToProcess, uint16_t& o_errCode)
221 {
222 o_errCode = 0;
223 if (i_parsedConfigJson.empty() || i_vpdFilePath.empty() ||
224 i_flagToProcess.empty())
225 {
226 o_errCode = error_code::INVALID_INPUT_PARAMETER;
227 return false;
228 }
229
230 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
249 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 }
255
256 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())
262 {
263 if (!itrToFunction->second(i_parsedConfigJson, i_vpdFilePath,
264 "postFailAction", i_flagToProcess,
265 o_errCode))
266 {
267 if (o_errCode)
268 {
269 logging::logMessage(
270 l_tags.key() + " failed for [" + i_vpdFilePath +
271 "]. Reason " + commonUtility::getErrCodeMsg(o_errCode));
272 }
273 return false;
274 }
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.
292 * @param[out] o_errCode - To set error code in case of error.
293 * @return Execution status.
294 */
processSystemCmdTag(const nlohmann::json & i_parsedConfigJson,const std::string & i_vpdFilePath,const std::string & i_baseAction,const std::string & i_flagToProcess,uint16_t & o_errCode)295 inline bool processSystemCmdTag(
296 const nlohmann::json& i_parsedConfigJson, const std::string& i_vpdFilePath,
297 const std::string& i_baseAction, const std::string& i_flagToProcess,
298 uint16_t& o_errCode)
299 {
300 o_errCode = 0;
301 if (i_vpdFilePath.empty() || i_parsedConfigJson.empty() ||
302 i_baseAction.empty() || i_flagToProcess.empty())
303 {
304 o_errCode = error_code::INVALID_INPUT_PARAMETER;
305 return false;
306 }
307
308 try
309 {
310 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;
327 return false;
328 }
329 return true;
330 }
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.
343 * @param[out] o_errCode - To set error code in case of error
344 * @return Execution status.
345 */
processGpioPresenceTag(const nlohmann::json & i_parsedConfigJson,const std::string & i_vpdFilePath,const std::string & i_baseAction,const std::string & i_flagToProcess,uint16_t & o_errCode)346 inline bool processGpioPresenceTag(
347 const nlohmann::json& i_parsedConfigJson, const std::string& i_vpdFilePath,
348 const std::string& i_baseAction, const std::string& i_flagToProcess,
349 uint16_t& o_errCode)
350 {
351 o_errCode = 0;
352 std::string l_presencePinName;
353 try
354 {
355 if (i_vpdFilePath.empty() || i_parsedConfigJson.empty() ||
356 i_baseAction.empty() || i_flagToProcess.empty())
357 {
358 o_errCode = error_code::INVALID_INPUT_PARAMETER;
359 return false;
360 }
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 {
369 o_errCode = error_code::JSON_MISSING_GPIO_INFO;
370 return false;
371 }
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
382 gpiod::line l_presenceLine = gpiod::find_line(l_presencePinName);
383
384 if (!l_presenceLine)
385 {
386 o_errCode = error_code::DEVICE_PRESENCE_UNKNOWN;
387 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
393 if (l_presencePinValue != l_presenceLine.get_value())
394 {
395 // 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;
399 return false;
400 }
401
402 return true;
403 }
404 catch (const std::exception& l_ex)
405 {
406 std::string l_errMsg = "Exception on GPIO line: ";
407 l_errMsg += l_presencePinName;
408 l_errMsg += " Reason: ";
409 l_errMsg += l_ex.what();
410 l_errMsg += " File: " + i_vpdFilePath + " Pel Logged";
411
412 // ToDo -- Check if PEL is required. Update Internal Rc code.
413 /**
414 uint16_t l_errCode = 0;
415 EventLogger::createAsyncPelWithInventoryCallout(
416 EventLogger::getErrorType(l_ex), types::SeverityType::Informational,
417 {{getInventoryObjPathFromJson(i_parsedConfigJson, i_vpdFilePath,
418 l_errCode),
419 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);
423 */
424
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.
444 * @param[out] o_errCode - To set error code in case of error
445 * @return Execution status.
446 */
procesSetGpioTag(const nlohmann::json & i_parsedConfigJson,const std::string & i_vpdFilePath,const std::string & i_baseAction,const std::string & i_flagToProcess,uint16_t & o_errCode)447 inline bool procesSetGpioTag(
448 const nlohmann::json& i_parsedConfigJson, const std::string& i_vpdFilePath,
449 const std::string& i_baseAction, const std::string& i_flagToProcess,
450 uint16_t& o_errCode)
451 {
452 o_errCode = 0;
453 std::string l_pinName;
454 try
455 {
456 if (i_vpdFilePath.empty() || i_parsedConfigJson.empty() ||
457 i_baseAction.empty() || i_flagToProcess.empty())
458 {
459 o_errCode = error_code::INVALID_INPUT_PARAMETER;
460 return false;
461 }
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 {
470 o_errCode = error_code::JSON_MISSING_GPIO_INFO;
471 return false;
472 }
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
484 gpiod::line l_outputLine = gpiod::find_line(l_pinName);
485
486 if (!l_outputLine)
487 {
488 o_errCode = error_code::GPIO_LINE_EXCEPTION;
489 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 }
497 catch (const std::exception& l_ex)
498 {
499 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";
504
505 // ToDo -- Update Internal RC code
506 /**
507 uint16_t l_errCode = 0;
508 EventLogger::createAsyncPelWithInventoryCallout(
509 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);
516 */
517
518 logging::logMessage(l_errMsg);
519
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.
537 * @param[out] o_errCode - To set error code in case of error.
538 * @return - success or failure
539 */
executeBaseAction(const nlohmann::json & i_parsedConfigJson,const std::string & i_action,const std::string & i_vpdFilePath,const std::string & i_flagToProcess,uint16_t & o_errCode)540 inline bool executeBaseAction(
541 const nlohmann::json& i_parsedConfigJson, const std::string& i_action,
542 const std::string& i_vpdFilePath, const std::string& i_flagToProcess,
543 uint16_t& o_errCode)
544 {
545 o_errCode = 0;
546 if (i_flagToProcess.empty() || i_action.empty() || i_vpdFilePath.empty() ||
547 !i_parsedConfigJson.contains("frus"))
548 {
549 o_errCode = error_code::INVALID_INPUT_PARAMETER;
550 return false;
551 }
552 if (!i_parsedConfigJson["frus"].contains(i_vpdFilePath))
553 {
554 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;
567 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,
580 i_action, i_flagToProcess, o_errCode))
581 {
582 // In case any of the tag fails to execute. Mark action
583 // as failed for that flag.
584 if (o_errCode)
585 {
586 logging::logMessage(
587 l_tag.key() + " failed for [" + i_vpdFilePath +
588 "]. Reason " + commonUtility::getErrCodeMsg(o_errCode));
589 }
590 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.
607 * @param[out] o_errCode - To set error code in case of error.
608 *
609 * @return On success return valid path, on failure return empty string.
610 */
getRedundantEepromPathFromJson(const nlohmann::json & i_sysCfgJsonObj,const std::string & i_vpdPath,uint16_t & o_errCode)611 inline std::string getRedundantEepromPathFromJson(
612 const nlohmann::json& i_sysCfgJsonObj, const std::string& i_vpdPath,
613 uint16_t& o_errCode)
614 {
615 o_errCode = 0;
616 if (i_vpdPath.empty())
617 {
618 o_errCode = error_code::INVALID_INPUT_PARAMETER;
619 return std::string{};
620 }
621
622 if (!i_sysCfgJsonObj.contains("frus"))
623 {
624 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 }
652 }
653
654 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.
665 * @param[out] o_errCode - To set error code in case of error.
666 *
667 * @return On success return valid path, on failure return empty string.
668 */
getFruPathFromJson(const nlohmann::json & i_sysCfgJsonObj,const std::string & i_vpdPath,uint16_t & o_errCode)669 inline std::string getFruPathFromJson(const nlohmann::json& i_sysCfgJsonObj,
670 const std::string& i_vpdPath,
671 uint16_t& o_errCode)
672 {
673 o_errCode = 0;
674 if (i_vpdPath.empty())
675 {
676 o_errCode = error_code::INVALID_INPUT_PARAMETER;
677 return std::string{};
678 }
679
680 if (!i_sysCfgJsonObj.contains("frus"))
681 {
682 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 }
707 }
708
709 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 * @param[out] o_errCode - To set error code in case of error.
722 *
723 * @return true if backup and restore is required, false otherwise.
724 */
isBackupAndRestoreRequired(const nlohmann::json & i_sysCfgJsonObj,uint16_t & o_errCode)725 inline bool isBackupAndRestoreRequired(const nlohmann::json& i_sysCfgJsonObj,
726 uint16_t& o_errCode)
727 {
728 o_errCode = 0;
729 if (i_sysCfgJsonObj.empty())
730 {
731 o_errCode = error_code::INVALID_INPUT_PARAMETER;
732 return false;
733 }
734
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))
741 {
742 return true;
743 }
744
745 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.
759 * @param[out] o_errCode - To set error code in case of error.
760 * @return - True if action is defined for the flow, false otherwise.
761 */
isActionRequired(const nlohmann::json & i_sysCfgJsonObj,const std::string & i_vpdFruPath,const std::string & i_action,const std::string & i_flowFlag,uint16_t & o_errCode)762 inline 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)
766 {
767 o_errCode = 0;
768 if (i_vpdFruPath.empty() || i_action.empty() || i_flowFlag.empty())
769 {
770 o_errCode = error_code::INVALID_INPUT_PARAMETER;
771 return false;
772 }
773
774 if (!i_sysCfgJsonObj.contains("frus"))
775 {
776 o_errCode = error_code::INVALID_JSON;
777 return false;
778 }
779
780 if (!i_sysCfgJsonObj["frus"].contains(i_vpdFruPath))
781 {
782 o_errCode = error_code::FRU_PATH_NOT_FOUND;
783 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 }
793 }
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 *
804 * @param[in] i_sysCfgJsonObj - System config JSON object.
805 * @param[out] o_errCode - To set error codes in case of error.
806 *
807 * @return On success list of FRUs parameters that needs polling. On failure,
808 * empty list.
809 */
getListOfGpioPollingFrus(const nlohmann::json & i_sysCfgJsonObj,uint16_t & o_errCode)810 inline std::vector<std::string> getListOfGpioPollingFrus(
811 const nlohmann::json& i_sysCfgJsonObj, uint16_t& o_errCode)
812 {
813 std::vector<std::string> l_gpioPollingRequiredFrusList;
814 o_errCode = 0;
815
816 if (i_sysCfgJsonObj.empty())
817 {
818 o_errCode = error_code::INVALID_INPUT_PARAMETER;
819 return l_gpioPollingRequiredFrusList;
820 }
821
822 if (!i_sysCfgJsonObj.contains("frus"))
823 {
824 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) +
841 "], error : " + commonUtility::getErrCodeMsg(o_errCode));
842
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 }
855 }
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.
873 * @param[out] o_errCode - To set error code in case of error.
874 *
875 * @return On success returns tuple of EEPROM path, inventory path & redundant
876 * path, on failure returns tuple with given input path alone.
877 */
878 inline std::tuple<std::string, std::string, std::string>
getAllPathsToUpdateKeyword(const nlohmann::json & i_sysCfgJsonObj,std::string io_vpdPath,uint16_t & o_errCode)879 getAllPathsToUpdateKeyword(const nlohmann::json& i_sysCfgJsonObj,
880 std::string io_vpdPath, uint16_t& o_errCode)
881 {
882 types::Path l_inventoryObjPath;
883 types::Path l_redundantFruPath;
884 o_errCode = 0;
885
886 if (i_sysCfgJsonObj.empty() || io_vpdPath.empty())
887 {
888 o_errCode = error_code::INVALID_INPUT_PARAMETER;
889 return std::make_tuple(io_vpdPath, l_inventoryObjPath,
890 l_redundantFruPath);
891 }
892
893 // 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())
906 {
907 if (o_errCode)
908 {
909 logging::logMessage(
910 "Failed to get inventory path from JSON for [" +
911 io_vpdPath +
912 "], error : " + commonUtility::getErrCodeMsg(o_errCode));
913 }
914 else
915 {
916 o_errCode = error_code::FRU_PATH_NOT_FOUND;
917 }
918
919 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 [" +
933 l_fruPath +
934 "], error : " + commonUtility::getErrCodeMsg(o_errCode));
935
936 o_errCode = error_code::ERROR_GETTING_REDUNDANT_PATH;
937 }
938 else
939 {
940 o_errCode = error_code::REDUNDANT_PATH_NOT_FOUND;
941 }
942
943 return std::make_tuple(io_vpdPath, l_inventoryObjPath,
944 l_redundantFruPath);
945 }
946 }
947 else if (o_errCode)
948 {
949 logging::logMessage(
950 "Failed to get FRU path from JSON for [" + io_vpdPath +
951 "], error : " + commonUtility::getErrCodeMsg(o_errCode));
952 }
953 else
954 {
955 o_errCode = error_code::NO_EEPROM_PATH;
956 }
957
958 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.
969 * @param[out] o_errCode - To set error code in case of error.
970 *
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 */
getServiceName(const nlohmann::json & i_sysCfgJsonObj,const std::string & l_inventoryPath,uint16_t & o_errCode)976 inline std::string getServiceName(const nlohmann::json& i_sysCfgJsonObj,
977 const std::string& l_inventoryPath,
978 uint16_t& o_errCode)
979 {
980 o_errCode = 0;
981 if (l_inventoryPath.empty())
982 {
983 o_errCode = error_code::INVALID_INPUT_PARAMETER;
984 return std::string{};
985 }
986
987 if (!i_sysCfgJsonObj.contains("frus"))
988 {
989 o_errCode = error_code::INVALID_JSON;
990 return std::string{};
991 }
992
993 const nlohmann::json& l_listOfFrus =
994 i_sysCfgJsonObj["frus"].get_ref<const nlohmann::json::object_t&>();
995
996 for (const auto& l_frus : l_listOfFrus.items())
997 {
998 for (const auto& l_inventoryItem : l_frus.value())
999 {
1000 if (l_inventoryPath.compare(l_inventoryItem["inventoryPath"]) ==
1001 constants::STR_CMP_SUCCESS)
1002 {
1003 if (l_inventoryItem.contains("serviceName"))
1004 {
1005 return l_inventoryItem.value("serviceName", "");
1006 }
1007
1008 o_errCode = error_code::JSON_MISSING_SERVICE_NAME;
1009 return std::string{};
1010 }
1011 }
1012 }
1013
1014 o_errCode = error_code::FRU_PATH_NOT_FOUND;
1015 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.
1026 * @param[out] o_errCode - To set error code for the error.
1027 * @return - True if FRU VPD can be collected at Chassis Power Off state only.
1028 * False otherwise
1029 */
isFruPowerOffOnly(const nlohmann::json & i_sysCfgJsonObj,const std::string & i_vpdFruPath,uint16_t & o_errCode)1030 inline bool isFruPowerOffOnly(const nlohmann::json& i_sysCfgJsonObj,
1031 const std::string& i_vpdFruPath,
1032 uint16_t& o_errCode)
1033 {
1034 o_errCode = 0;
1035 if (i_vpdFruPath.empty())
1036 {
1037 o_errCode = error_code::INVALID_INPUT_PARAMETER;
1038 return false;
1039 }
1040
1041 if (!i_sysCfgJsonObj.contains("frus"))
1042 {
1043 o_errCode = error_code::INVALID_JSON;
1044 return false;
1045 }
1046
1047 if (!i_sysCfgJsonObj["frus"].contains(i_vpdFruPath))
1048 {
1049 o_errCode = error_code::FRU_PATH_NOT_FOUND;
1050 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.
1063 * @param[out] o_errCode - to set error code in case of error.
1064 *
1065 * @return true if FRU is replaceable at runtime. false otherwise.
1066 */
isFruReplaceableAtRuntime(const nlohmann::json & i_sysCfgJsonObj,const std::string & i_vpdFruPath,uint16_t & o_errCode)1067 inline bool isFruReplaceableAtRuntime(const nlohmann::json& i_sysCfgJsonObj,
1068 const std::string& i_vpdFruPath,
1069 uint16_t& o_errCode)
1070 {
1071 o_errCode = 0;
1072 if (i_vpdFruPath.empty())
1073 {
1074 o_errCode = error_code::INVALID_INPUT_PARAMETER;
1075 return false;
1076 }
1077
1078 if (i_sysCfgJsonObj.empty() || (!i_sysCfgJsonObj.contains("frus")))
1079 {
1080 o_errCode = error_code::INVALID_JSON;
1081 return false;
1082 }
1083
1084 if (!i_sysCfgJsonObj["frus"].contains(i_vpdFruPath))
1085 {
1086 o_errCode = error_code::FRU_PATH_NOT_FOUND;
1087 return false;
1088 }
1089
1090 return (
1091 (i_sysCfgJsonObj["frus"][i_vpdFruPath].at(0))
1092 .contains("replaceableAtRuntime") &&
1093 (i_sysCfgJsonObj["frus"][i_vpdFruPath].at(0)["replaceableAtRuntime"]));
1094
1095 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.
1103 * @param[out] o_errCode - set error code in case of error.
1104 *
1105 * @return true if FRU is replaceable at standby. false otherwise.
1106 */
isFruReplaceableAtStandby(const nlohmann::json & i_sysCfgJsonObj,const std::string & i_vpdFruPath,uint16_t & o_errCode)1107 inline bool isFruReplaceableAtStandby(const nlohmann::json& i_sysCfgJsonObj,
1108 const std::string& i_vpdFruPath,
1109 uint16_t& o_errCode)
1110 {
1111 o_errCode = 0;
1112 if (i_vpdFruPath.empty())
1113 {
1114 o_errCode = error_code::INVALID_INPUT_PARAMETER;
1115 return false;
1116 }
1117
1118 if (i_sysCfgJsonObj.empty() || (!i_sysCfgJsonObj.contains("frus")))
1119 {
1120 o_errCode = error_code::INVALID_JSON;
1121 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;
1128 }
1129
1130 return (
1131 (i_sysCfgJsonObj["frus"][i_vpdFruPath].at(0))
1132 .contains("replaceableAtStandby") &&
1133 (i_sysCfgJsonObj["frus"][i_vpdFruPath].at(0)["replaceableAtStandby"]));
1134
1135 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.
1143 *
1144 * @param[in] i_sysCfgJsonObj - System config JSON object.
1145 * @param[out] o_errCode - To set error code in case of error.
1146 *
1147 * @return - On success, list of FRUs replaceable at standby. On failure, empty
1148 * vector.
1149 */
getListOfFrusReplaceableAtStandby(const nlohmann::json & i_sysCfgJsonObj,uint16_t & o_errCode)1150 inline std::vector<std::string> getListOfFrusReplaceableAtStandby(
1151 const nlohmann::json& i_sysCfgJsonObj, uint16_t& o_errCode)
1152 {
1153 std::vector<std::string> l_frusReplaceableAtStandby;
1154 o_errCode = 0;
1155
1156 if (!i_sysCfgJsonObj.contains("frus"))
1157 {
1158 o_errCode = error_code::INVALID_JSON;
1159 return l_frusReplaceableAtStandby;
1160 }
1161
1162 const nlohmann::json& l_fruList =
1163 i_sysCfgJsonObj["frus"].get_ref<const nlohmann::json::object_t&>();
1164
1165 for (const auto& l_fru : l_fruList.items())
1166 {
1167 if (i_sysCfgJsonObj["frus"][l_fru.key()].at(0).value(
1168 "replaceableAtStandby", false))
1169 {
1170 const std::string& l_inventoryObjectPath =
1171 i_sysCfgJsonObj["frus"][l_fru.key()].at(0).value(
1172 "inventoryPath", "");
1173
1174 if (!l_inventoryObjectPath.empty())
1175 {
1176 l_frusReplaceableAtStandby.emplace_back(l_inventoryObjectPath);
1177 }
1178 }
1179 }
1180
1181 return l_frusReplaceableAtStandby;
1182 }
1183
1184 /**
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.
1192 * @param[out] o_errCode - to set error code in case of error.
1193 * @return Parsed JSON object, empty JSON otherwise.
1194 */
getPowerVsJson(const types::BinaryVector & i_imValue,uint16_t & o_errCode)1195 inline nlohmann::json getPowerVsJson(const types::BinaryVector& i_imValue,
1196 uint16_t& o_errCode)
1197 {
1198 o_errCode = 0;
1199 if (i_imValue.empty() || i_imValue.size() < 4)
1200 {
1201 o_errCode = error_code::INVALID_INPUT_PARAMETER;
1202 return nlohmann::json{};
1203 }
1204
1205 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))
1208 {
1209 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) +
1217 " ], error : " + commonUtility::getErrCodeMsg(o_errCode));
1218 }
1219
1220 return l_parsedJson;
1221 }
1222 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) +
1234 " ], error : " + commonUtility::getErrCodeMsg(o_errCode));
1235 }
1236
1237 return l_parsedJson;
1238 }
1239 return nlohmann::json{};
1240 }
1241
1242 /**
1243 * @brief API to get list of FRUs for which "monitorPresence" is true.
1244 *
1245 * @param[in] i_sysCfgJsonObj - System config JSON object.
1246 * @param[out] o_errCode - To set error code in case of error.
1247 *
1248 * @return On success, returns list of FRUs for which "monitorPresence" is true,
1249 * empty list on error.
1250 */
getFrusWithPresenceMonitoring(const nlohmann::json & i_sysCfgJsonObj,uint16_t & o_errCode)1251 inline std::vector<types::Path> getFrusWithPresenceMonitoring(
1252 const nlohmann::json& i_sysCfgJsonObj, uint16_t& o_errCode)
1253 {
1254 std::vector<types::Path> l_frusWithPresenceMonitoring;
1255 o_errCode = 0;
1256
1257 if (!i_sysCfgJsonObj.contains("frus"))
1258 {
1259 o_errCode = error_code::INVALID_JSON;
1260 return l_frusWithPresenceMonitoring;
1261 }
1262
1263 const nlohmann::json& l_listOfFrus =
1264 i_sysCfgJsonObj["frus"].get_ref<const nlohmann::json::object_t&>();
1265
1266 for (const auto& l_aFru : l_listOfFrus)
1267 {
1268 if (l_aFru.at(0).value("monitorPresence", false))
1269 {
1270 l_frusWithPresenceMonitoring.emplace_back(
1271 l_aFru.at(0).value("inventoryPath", ""));
1272 }
1273 }
1274
1275 return l_frusWithPresenceMonitoring;
1276 }
1277
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.
1286 * @param[out] o_errCode - To set error code in case of failure.
1287 *
1288 * @return true if FRU presence is handled, false otherwise.
1289 */
isFruPresenceHandled(const nlohmann::json & i_sysCfgJsonObj,const std::string & i_vpdFruPath,uint16_t & o_errCode)1290 inline bool isFruPresenceHandled(const nlohmann::json& i_sysCfgJsonObj,
1291 const std::string& i_vpdFruPath,
1292 uint16_t& o_errCode)
1293 {
1294 o_errCode = 0;
1295 if (i_vpdFruPath.empty())
1296 {
1297 o_errCode = error_code::INVALID_INPUT_PARAMETER;
1298 return false;
1299 }
1300
1301 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);
1315 }
1316 } // namespace jsonUtility
1317 } // namespace vpd
1318