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, o_errCode);
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 o_errCode = error_code::FRU_PATH_NOT_FOUND;
710 return std::string();
711 }
712
713 /**
714 * @brief An API to check backup and restore VPD is required.
715 *
716 * The API checks if there is provision for backup and restore mentioned in the
717 * system config JSON, by looking "backupRestoreConfigPath" tag.
718 * Checks if the path mentioned is a hardware path, by checking if the file path
719 * exists and size of contents in the path.
720 *
721 * @param[in] i_sysCfgJsonObj - System config JSON object.
722 * @param[out] o_errCode - To set error code in case of error.
723 *
724 * @return true if backup and restore is required, false otherwise.
725 */
isBackupAndRestoreRequired(const nlohmann::json & i_sysCfgJsonObj,uint16_t & o_errCode)726 inline bool isBackupAndRestoreRequired(const nlohmann::json& i_sysCfgJsonObj,
727 uint16_t& o_errCode)
728 {
729 o_errCode = 0;
730 if (i_sysCfgJsonObj.empty())
731 {
732 o_errCode = error_code::INVALID_INPUT_PARAMETER;
733 return false;
734 }
735
736 const std::string& l_backupAndRestoreCfgFilePath =
737 i_sysCfgJsonObj.value("backupRestoreConfigPath", "");
738
739 if (!l_backupAndRestoreCfgFilePath.empty() &&
740 std::filesystem::exists(l_backupAndRestoreCfgFilePath) &&
741 !std::filesystem::is_empty(l_backupAndRestoreCfgFilePath))
742 {
743 return true;
744 }
745
746 return false;
747 }
748
749 /** @brief API to check if an action is required for given EEPROM path.
750 *
751 * System config JSON can contain pre-action, post-action etc. like actions
752 * defined for an EEPROM path. The API will check if any such action is defined
753 * for the EEPROM.
754 *
755 * @param[in] i_sysCfgJsonObj - System config JSON object.
756 * @param[in] i_vpdFruPath - EEPROM path.
757 * @param[in] i_action - Action to be checked.
758 * @param[in] i_flowFlag - Denotes the flow w.r.t which the action should be
759 * triggered.
760 * @param[out] o_errCode - To set error code in case of error.
761 * @return - True if action is defined for the flow, false otherwise.
762 */
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)763 inline bool isActionRequired(const nlohmann::json& i_sysCfgJsonObj,
764 const std::string& i_vpdFruPath,
765 const std::string& i_action,
766 const std::string& i_flowFlag, uint16_t& o_errCode)
767 {
768 o_errCode = 0;
769 if (i_vpdFruPath.empty() || i_action.empty() || i_flowFlag.empty())
770 {
771 o_errCode = error_code::INVALID_INPUT_PARAMETER;
772 return false;
773 }
774
775 if (!i_sysCfgJsonObj.contains("frus"))
776 {
777 o_errCode = error_code::INVALID_JSON;
778 return false;
779 }
780
781 if (!i_sysCfgJsonObj["frus"].contains(i_vpdFruPath))
782 {
783 o_errCode = error_code::FRU_PATH_NOT_FOUND;
784 return false;
785 }
786
787 if ((i_sysCfgJsonObj["frus"][i_vpdFruPath].at(0)).contains(i_action))
788 {
789 if ((i_sysCfgJsonObj["frus"][i_vpdFruPath].at(0))[i_action].contains(
790 i_flowFlag))
791 {
792 return true;
793 }
794 }
795 return false;
796 }
797
798 /**
799 * @brief An API to return list of FRUs that needs GPIO polling.
800 *
801 * An API that checks for the FRUs that requires GPIO polling and returns
802 * a list of FRUs that needs polling. Returns an empty list if there are
803 * no FRUs that requires polling.
804 *
805 * @param[in] i_sysCfgJsonObj - System config JSON object.
806 * @param[out] o_errCode - To set error codes in case of error.
807 *
808 * @return On success list of FRUs parameters that needs polling. On failure,
809 * empty list.
810 */
getListOfGpioPollingFrus(const nlohmann::json & i_sysCfgJsonObj,uint16_t & o_errCode)811 inline std::vector<std::string> getListOfGpioPollingFrus(
812 const nlohmann::json& i_sysCfgJsonObj, uint16_t& o_errCode)
813 {
814 std::vector<std::string> l_gpioPollingRequiredFrusList;
815 o_errCode = 0;
816
817 if (i_sysCfgJsonObj.empty())
818 {
819 o_errCode = error_code::INVALID_INPUT_PARAMETER;
820 return l_gpioPollingRequiredFrusList;
821 }
822
823 if (!i_sysCfgJsonObj.contains("frus"))
824 {
825 o_errCode = error_code::INVALID_JSON;
826 return l_gpioPollingRequiredFrusList;
827 }
828
829 for (const auto& l_fru : i_sysCfgJsonObj["frus"].items())
830 {
831 const auto l_fruPath = l_fru.key();
832
833 bool l_isHotPluggableFru =
834 isActionRequired(i_sysCfgJsonObj, l_fruPath, "pollingRequired",
835 "hotPlugging", o_errCode);
836
837 if (o_errCode)
838 {
839 logging::logMessage(
840 "Error while checking if action required for FRU [" +
841 std::string(l_fruPath) +
842 "], error : " + commonUtility::getErrCodeMsg(o_errCode));
843
844 return l_gpioPollingRequiredFrusList;
845 }
846
847 if (l_isHotPluggableFru)
848 {
849 if (i_sysCfgJsonObj["frus"][l_fruPath]
850 .at(0)["pollingRequired"]["hotPlugging"]
851 .contains("gpioPresence"))
852 {
853 l_gpioPollingRequiredFrusList.push_back(l_fruPath);
854 }
855 }
856 }
857
858 return l_gpioPollingRequiredFrusList;
859 }
860
861 /**
862 * @brief Get all related path(s) to update keyword value.
863 *
864 * Given FRU EEPROM path/Inventory path needs keyword's value update, this API
865 * returns tuple of FRU EEPROM path, inventory path and redundant EEPROM path if
866 * exists in the system config JSON.
867 *
868 * Note: If the inventory object path or redundant EEPROM path(s) are not found
869 * in the system config JSON, corresponding fields will have empty value in the
870 * returning tuple.
871 *
872 * @param[in] i_sysCfgJsonObj - System config JSON object.
873 * @param[in,out] io_vpdPath - Inventory object path or FRU EEPROM path.
874 * @param[out] o_errCode - To set error code in case of error.
875 *
876 * @return On success returns tuple of EEPROM path, inventory path & redundant
877 * path, on failure returns tuple with given input path alone.
878 */
879 inline std::tuple<std::string, std::string, std::string>
getAllPathsToUpdateKeyword(const nlohmann::json & i_sysCfgJsonObj,std::string io_vpdPath,uint16_t & o_errCode)880 getAllPathsToUpdateKeyword(const nlohmann::json& i_sysCfgJsonObj,
881 std::string io_vpdPath, uint16_t& o_errCode)
882 {
883 types::Path l_inventoryObjPath;
884 types::Path l_redundantFruPath;
885 o_errCode = 0;
886
887 if (i_sysCfgJsonObj.empty() || io_vpdPath.empty())
888 {
889 o_errCode = error_code::INVALID_INPUT_PARAMETER;
890 return std::make_tuple(io_vpdPath, l_inventoryObjPath,
891 l_redundantFruPath);
892 }
893
894 // Get hardware path from system config JSON.
895 const types::Path l_fruPath =
896 jsonUtility::getFruPathFromJson(i_sysCfgJsonObj, io_vpdPath, o_errCode);
897
898 if (!l_fruPath.empty())
899 {
900 io_vpdPath = l_fruPath;
901
902 // Get inventory object path from system config JSON
903 l_inventoryObjPath = jsonUtility::getInventoryObjPathFromJson(
904 i_sysCfgJsonObj, l_fruPath, o_errCode);
905
906 if (l_inventoryObjPath.empty())
907 {
908 if (o_errCode)
909 {
910 logging::logMessage(
911 "Failed to get inventory path from JSON for [" +
912 io_vpdPath +
913 "], error : " + commonUtility::getErrCodeMsg(o_errCode));
914 }
915 else
916 {
917 o_errCode = error_code::FRU_PATH_NOT_FOUND;
918 }
919
920 return std::make_tuple(io_vpdPath, l_inventoryObjPath,
921 l_redundantFruPath);
922 }
923
924 // Get redundant hardware path if present in system config JSON
925 l_redundantFruPath = jsonUtility::getRedundantEepromPathFromJson(
926 i_sysCfgJsonObj, l_fruPath, o_errCode);
927
928 if (l_redundantFruPath.empty())
929 {
930 if (o_errCode)
931 {
932 logging::logMessage(
933 "Failed to get redundant EEPROM path for FRU [" +
934 l_fruPath +
935 "], error : " + commonUtility::getErrCodeMsg(o_errCode));
936
937 o_errCode = error_code::ERROR_GETTING_REDUNDANT_PATH;
938 }
939 else
940 {
941 o_errCode = error_code::REDUNDANT_PATH_NOT_FOUND;
942 }
943
944 return std::make_tuple(io_vpdPath, l_inventoryObjPath,
945 l_redundantFruPath);
946 }
947 }
948 else if (o_errCode)
949 {
950 logging::logMessage(
951 "Failed to get FRU path from JSON for [" + io_vpdPath +
952 "], error : " + commonUtility::getErrCodeMsg(o_errCode));
953 }
954 else
955 {
956 o_errCode = error_code::NO_EEPROM_PATH;
957 }
958
959 return std::make_tuple(io_vpdPath, l_inventoryObjPath, l_redundantFruPath);
960 }
961
962 /**
963 * @brief An API to get DBus service name.
964 *
965 * Given DBus inventory path, this API returns DBus service name if present in
966 * the JSON.
967 *
968 * @param[in] i_sysCfgJsonObj - System config JSON object.
969 * @param[in] l_inventoryPath - DBus inventory path.
970 * @param[out] o_errCode - To set error code in case of error.
971 *
972 * @return On success returns the service name present in the system config
973 * JSON, otherwise empty string.
974 *
975 * Note: Caller has to handle in case of empty string received.
976 */
getServiceName(const nlohmann::json & i_sysCfgJsonObj,const std::string & l_inventoryPath,uint16_t & o_errCode)977 inline std::string getServiceName(const nlohmann::json& i_sysCfgJsonObj,
978 const std::string& l_inventoryPath,
979 uint16_t& o_errCode)
980 {
981 o_errCode = 0;
982 if (l_inventoryPath.empty())
983 {
984 o_errCode = error_code::INVALID_INPUT_PARAMETER;
985 return std::string{};
986 }
987
988 if (!i_sysCfgJsonObj.contains("frus"))
989 {
990 o_errCode = error_code::INVALID_JSON;
991 return std::string{};
992 }
993
994 const nlohmann::json& l_listOfFrus =
995 i_sysCfgJsonObj["frus"].get_ref<const nlohmann::json::object_t&>();
996
997 for (const auto& l_frus : l_listOfFrus.items())
998 {
999 for (const auto& l_inventoryItem : l_frus.value())
1000 {
1001 if (l_inventoryPath.compare(l_inventoryItem["inventoryPath"]) ==
1002 constants::STR_CMP_SUCCESS)
1003 {
1004 if (l_inventoryItem.contains("serviceName"))
1005 {
1006 return l_inventoryItem.value("serviceName", "");
1007 }
1008
1009 o_errCode = error_code::JSON_MISSING_SERVICE_NAME;
1010 return std::string{};
1011 }
1012 }
1013 }
1014
1015 o_errCode = error_code::FRU_PATH_NOT_FOUND;
1016 return std::string{};
1017 }
1018
1019 /**
1020 * @brief An API to check if a FRU is tagged as "powerOffOnly"
1021 *
1022 * Given the system config JSON and VPD FRU path, this API checks if the FRU
1023 * VPD can be collected at Chassis Power Off state only.
1024 *
1025 * @param[in] i_sysCfgJsonObj - System config JSON object.
1026 * @param[in] i_vpdFruPath - EEPROM path.
1027 * @param[out] o_errCode - To set error code for the error.
1028 * @return - True if FRU VPD can be collected at Chassis Power Off state only.
1029 * False otherwise
1030 */
isFruPowerOffOnly(const nlohmann::json & i_sysCfgJsonObj,const std::string & i_vpdFruPath,uint16_t & o_errCode)1031 inline bool isFruPowerOffOnly(const nlohmann::json& i_sysCfgJsonObj,
1032 const std::string& i_vpdFruPath,
1033 uint16_t& o_errCode)
1034 {
1035 o_errCode = 0;
1036 if (i_vpdFruPath.empty())
1037 {
1038 o_errCode = error_code::INVALID_INPUT_PARAMETER;
1039 return false;
1040 }
1041
1042 if (!i_sysCfgJsonObj.contains("frus"))
1043 {
1044 o_errCode = error_code::INVALID_JSON;
1045 return false;
1046 }
1047
1048 if (!i_sysCfgJsonObj["frus"].contains(i_vpdFruPath))
1049 {
1050 o_errCode = error_code::FRU_PATH_NOT_FOUND;
1051 return false;
1052 }
1053
1054 return ((i_sysCfgJsonObj["frus"][i_vpdFruPath].at(0))
1055 .contains("powerOffOnly") &&
1056 (i_sysCfgJsonObj["frus"][i_vpdFruPath].at(0)["powerOffOnly"]));
1057 }
1058
1059 /**
1060 * @brief API which tells if the FRU is replaceable at runtime
1061 *
1062 * @param[in] i_sysCfgJsonObj - System config JSON object.
1063 * @param[in] i_vpdFruPath - EEPROM path.
1064 * @param[out] o_errCode - to set error code in case of error.
1065 *
1066 * @return true if FRU is replaceable at runtime. false otherwise.
1067 */
isFruReplaceableAtRuntime(const nlohmann::json & i_sysCfgJsonObj,const std::string & i_vpdFruPath,uint16_t & o_errCode)1068 inline bool isFruReplaceableAtRuntime(const nlohmann::json& i_sysCfgJsonObj,
1069 const std::string& i_vpdFruPath,
1070 uint16_t& o_errCode)
1071 {
1072 o_errCode = 0;
1073 if (i_vpdFruPath.empty())
1074 {
1075 o_errCode = error_code::INVALID_INPUT_PARAMETER;
1076 return false;
1077 }
1078
1079 if (i_sysCfgJsonObj.empty() || (!i_sysCfgJsonObj.contains("frus")))
1080 {
1081 o_errCode = error_code::INVALID_JSON;
1082 return false;
1083 }
1084
1085 if (!i_sysCfgJsonObj["frus"].contains(i_vpdFruPath))
1086 {
1087 o_errCode = error_code::FRU_PATH_NOT_FOUND;
1088 return false;
1089 }
1090
1091 return (
1092 (i_sysCfgJsonObj["frus"][i_vpdFruPath].at(0))
1093 .contains("replaceableAtRuntime") &&
1094 (i_sysCfgJsonObj["frus"][i_vpdFruPath].at(0)["replaceableAtRuntime"]));
1095
1096 return false;
1097 }
1098
1099 /**
1100 * @brief API which tells if the FRU is replaceable at standby
1101 *
1102 * @param[in] i_sysCfgJsonObj - System config JSON object.
1103 * @param[in] i_vpdFruPath - EEPROM path.
1104 * @param[out] o_errCode - set error code in case of error.
1105 *
1106 * @return true if FRU is replaceable at standby. false otherwise.
1107 */
isFruReplaceableAtStandby(const nlohmann::json & i_sysCfgJsonObj,const std::string & i_vpdFruPath,uint16_t & o_errCode)1108 inline bool isFruReplaceableAtStandby(const nlohmann::json& i_sysCfgJsonObj,
1109 const std::string& i_vpdFruPath,
1110 uint16_t& o_errCode)
1111 {
1112 o_errCode = 0;
1113 if (i_vpdFruPath.empty())
1114 {
1115 o_errCode = error_code::INVALID_INPUT_PARAMETER;
1116 return false;
1117 }
1118
1119 if (i_sysCfgJsonObj.empty() || (!i_sysCfgJsonObj.contains("frus")))
1120 {
1121 o_errCode = error_code::INVALID_JSON;
1122 return false;
1123 }
1124
1125 if (!i_sysCfgJsonObj["frus"].contains(i_vpdFruPath))
1126 {
1127 o_errCode = error_code::FRU_PATH_NOT_FOUND;
1128 return false;
1129 }
1130
1131 return (
1132 (i_sysCfgJsonObj["frus"][i_vpdFruPath].at(0))
1133 .contains("replaceableAtStandby") &&
1134 (i_sysCfgJsonObj["frus"][i_vpdFruPath].at(0)["replaceableAtStandby"]));
1135
1136 return false;
1137 }
1138
1139 /**
1140 * @brief API to get list of FRUs replaceable at standby from JSON.
1141 *
1142 * The API will return a vector of FRUs inventory path which are replaceable at
1143 * standby.
1144 *
1145 * @param[in] i_sysCfgJsonObj - System config JSON object.
1146 * @param[out] o_errCode - To set error code in case of error.
1147 *
1148 * @return - On success, list of FRUs replaceable at standby. On failure, empty
1149 * vector.
1150 */
getListOfFrusReplaceableAtStandby(const nlohmann::json & i_sysCfgJsonObj,uint16_t & o_errCode)1151 inline std::vector<std::string> getListOfFrusReplaceableAtStandby(
1152 const nlohmann::json& i_sysCfgJsonObj, uint16_t& o_errCode)
1153 {
1154 std::vector<std::string> l_frusReplaceableAtStandby;
1155 o_errCode = 0;
1156
1157 if (!i_sysCfgJsonObj.contains("frus"))
1158 {
1159 o_errCode = error_code::INVALID_JSON;
1160 return l_frusReplaceableAtStandby;
1161 }
1162
1163 const nlohmann::json& l_fruList =
1164 i_sysCfgJsonObj["frus"].get_ref<const nlohmann::json::object_t&>();
1165
1166 for (const auto& l_fru : l_fruList.items())
1167 {
1168 if (i_sysCfgJsonObj["frus"][l_fru.key()].at(0).value(
1169 "replaceableAtStandby", false))
1170 {
1171 const std::string& l_inventoryObjectPath =
1172 i_sysCfgJsonObj["frus"][l_fru.key()].at(0).value(
1173 "inventoryPath", "");
1174
1175 if (!l_inventoryObjectPath.empty())
1176 {
1177 l_frusReplaceableAtStandby.emplace_back(l_inventoryObjectPath);
1178 }
1179 }
1180 }
1181
1182 return l_frusReplaceableAtStandby;
1183 }
1184
1185 /**
1186 * @brief API to select powerVS JSON based on system IM.
1187 *
1188 * The API selects respective JSON based on system IM, parse it and return the
1189 * JSON object. Empty JSON will be returned in case of any error. Caller needs
1190 * to handle empty value.
1191 *
1192 * @param[in] i_imValue - IM value of the system.
1193 * @param[out] o_errCode - to set error code in case of error.
1194 * @return Parsed JSON object, empty JSON otherwise.
1195 */
getPowerVsJson(const types::BinaryVector & i_imValue,uint16_t & o_errCode)1196 inline nlohmann::json getPowerVsJson(const types::BinaryVector& i_imValue,
1197 uint16_t& o_errCode)
1198 {
1199 o_errCode = 0;
1200 if (i_imValue.empty() || i_imValue.size() < 4)
1201 {
1202 o_errCode = error_code::INVALID_INPUT_PARAMETER;
1203 return nlohmann::json{};
1204 }
1205
1206 if ((i_imValue.at(0) == constants::HEX_VALUE_50) &&
1207 (i_imValue.at(1) == constants::HEX_VALUE_00) &&
1208 (i_imValue.at(2) == constants::HEX_VALUE_30))
1209 {
1210 nlohmann::json l_parsedJson = jsonUtility::getParsedJson(
1211 constants::power_vs_50003_json, o_errCode);
1212
1213 if (o_errCode)
1214 {
1215 logging::logMessage(
1216 "Failed to parse JSON file [ " +
1217 std::string(constants::power_vs_50003_json) +
1218 " ], error : " + commonUtility::getErrCodeMsg(o_errCode));
1219 }
1220
1221 return l_parsedJson;
1222 }
1223 else if (i_imValue.at(0) == constants::HEX_VALUE_50 &&
1224 (i_imValue.at(1) == constants::HEX_VALUE_00) &&
1225 (i_imValue.at(2) == constants::HEX_VALUE_10))
1226 {
1227 nlohmann::json l_parsedJson = jsonUtility::getParsedJson(
1228 constants::power_vs_50001_json, o_errCode);
1229
1230 if (o_errCode)
1231 {
1232 logging::logMessage(
1233 "Failed to parse JSON file [ " +
1234 std::string(constants::power_vs_50001_json) +
1235 " ], error : " + commonUtility::getErrCodeMsg(o_errCode));
1236 }
1237
1238 return l_parsedJson;
1239 }
1240 return nlohmann::json{};
1241 }
1242
1243 /**
1244 * @brief API to get list of FRUs for which "monitorPresence" is true.
1245 *
1246 * @param[in] i_sysCfgJsonObj - System config JSON object.
1247 * @param[out] o_errCode - To set error code in case of error.
1248 *
1249 * @return On success, returns list of FRUs for which "monitorPresence" is true,
1250 * empty list on error.
1251 */
getFrusWithPresenceMonitoring(const nlohmann::json & i_sysCfgJsonObj,uint16_t & o_errCode)1252 inline std::vector<types::Path> getFrusWithPresenceMonitoring(
1253 const nlohmann::json& i_sysCfgJsonObj, uint16_t& o_errCode)
1254 {
1255 std::vector<types::Path> l_frusWithPresenceMonitoring;
1256 o_errCode = 0;
1257
1258 if (!i_sysCfgJsonObj.contains("frus"))
1259 {
1260 o_errCode = error_code::INVALID_JSON;
1261 return l_frusWithPresenceMonitoring;
1262 }
1263
1264 const nlohmann::json& l_listOfFrus =
1265 i_sysCfgJsonObj["frus"].get_ref<const nlohmann::json::object_t&>();
1266
1267 for (const auto& l_aFru : l_listOfFrus)
1268 {
1269 if (l_aFru.at(0).value("monitorPresence", false))
1270 {
1271 l_frusWithPresenceMonitoring.emplace_back(
1272 l_aFru.at(0).value("inventoryPath", ""));
1273 }
1274 }
1275
1276 return l_frusWithPresenceMonitoring;
1277 }
1278
1279 /**
1280 * @brief API which tells if the FRU's presence is handled
1281 *
1282 * For a given FRU, this API checks if it's presence is handled by vpd-manager
1283 * by checking the "handlePresence" tag.
1284 *
1285 * @param[in] i_sysCfgJsonObj - System config JSON object.
1286 * @param[in] i_vpdFruPath - EEPROM path.
1287 * @param[out] o_errCode - To set error code in case of failure.
1288 *
1289 * @return true if FRU presence is handled, false otherwise.
1290 */
isFruPresenceHandled(const nlohmann::json & i_sysCfgJsonObj,const std::string & i_vpdFruPath,uint16_t & o_errCode)1291 inline bool isFruPresenceHandled(const nlohmann::json& i_sysCfgJsonObj,
1292 const std::string& i_vpdFruPath,
1293 uint16_t& o_errCode)
1294 {
1295 o_errCode = 0;
1296 if (i_vpdFruPath.empty())
1297 {
1298 o_errCode = error_code::INVALID_INPUT_PARAMETER;
1299 return false;
1300 }
1301
1302 if (!i_sysCfgJsonObj.contains("frus"))
1303 {
1304 o_errCode = error_code::INVALID_JSON;
1305 return false;
1306 }
1307
1308 if (!i_sysCfgJsonObj["frus"].contains(i_vpdFruPath))
1309 {
1310 o_errCode = error_code::FRU_PATH_NOT_FOUND;
1311 return false;
1312 }
1313
1314 return i_sysCfgJsonObj["frus"][i_vpdFruPath].at(0).value(
1315 "handlePresence", true);
1316 }
1317 } // namespace jsonUtility
1318 } // namespace vpd
1319