blob: 4a2a7415790ce796dddbc490ff8bd16cda5c8377 [file] [log] [blame]
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001#pragma once
2
3#include "config.h"
4
5#include "constants.hpp"
6#include "exceptions.hpp"
7#include "logger.hpp"
8#include "types.hpp"
9
10#include <nlohmann/json.hpp>
11#include <utility/common_utility.hpp>
12#include <utility/dbus_utility.hpp>
13
14#include <filesystem>
15#include <fstream>
16#include <regex>
17
18namespace vpd
19{
20namespace vpdSpecificUtility
21{
22/**
23 * @brief API to generate file name for bad VPD.
24 *
25 * For i2c eeproms - the pattern of the vpd-name will be
26 * i2c-<bus-number>-<eeprom-address>.
27 * For spi eeproms - the pattern of the vpd-name will be spi-<spi-number>.
28 *
Souvik Roy8fc12522025-02-19 01:28:38 -060029 * @param[in] i_vpdFilePath - file path of the vpd.
30 *
31 * @return On success, returns generated file name, otherwise returns empty
32 * string.
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -050033 */
Souvik Roy8fc12522025-02-19 01:28:38 -060034inline std::string generateBadVPDFileName(
35 const std::string& i_vpdFilePath) noexcept
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -050036{
Souvik Roy8fc12522025-02-19 01:28:38 -060037 std::string l_badVpdFileName{BAD_VPD_DIR};
38 try
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -050039 {
Souvik Roy8fc12522025-02-19 01:28:38 -060040 if (i_vpdFilePath.find("i2c") != std::string::npos)
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -050041 {
Souvik Roy8fc12522025-02-19 01:28:38 -060042 l_badVpdFileName += "i2c-";
43 std::regex l_i2cPattern("(at24/)([0-9]+-[0-9]+)\\/");
44 std::smatch l_match;
45 if (std::regex_search(i_vpdFilePath, l_match, l_i2cPattern))
46 {
47 l_badVpdFileName += l_match.str(2);
48 }
49 }
50 else if (i_vpdFilePath.find("spi") != std::string::npos)
51 {
52 std::regex l_spiPattern("((spi)[0-9]+)(.0)");
53 std::smatch l_match;
54 if (std::regex_search(i_vpdFilePath, l_match, l_spiPattern))
55 {
56 l_badVpdFileName += l_match.str(1);
57 }
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -050058 }
59 }
Souvik Roy8fc12522025-02-19 01:28:38 -060060 catch (const std::exception& l_ex)
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -050061 {
Souvik Roy8fc12522025-02-19 01:28:38 -060062 l_badVpdFileName.clear();
63 logging::logMessage("Failed to generate bad VPD file name for [" +
64 i_vpdFilePath + "]. Error: " + l_ex.what());
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -050065 }
Souvik Roy8fc12522025-02-19 01:28:38 -060066 return l_badVpdFileName;
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -050067}
68
69/**
70 * @brief API which dumps the broken/bad vpd in a directory.
71 * When the vpd is bad, this API places the bad vpd file inside
72 * "/tmp/bad-vpd" in BMC, in order to collect bad VPD data as a part of user
73 * initiated BMC dump.
74 *
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -050075 *
Souvik Roy8fc12522025-02-19 01:28:38 -060076 * @param[in] i_vpdFilePath - vpd file path
77 * @param[in] i_vpdVector - vpd vector
78 *
79 * @return On success returns 0, otherwise returns -1.
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -050080 */
Souvik Roy8fc12522025-02-19 01:28:38 -060081inline int dumpBadVpd(const std::string& i_vpdFilePath,
82 const types::BinaryVector& i_vpdVector) noexcept
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -050083{
Souvik Roy8fc12522025-02-19 01:28:38 -060084 int l_rc{constants::FAILURE};
85 try
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -050086 {
Souvik Roy8fc12522025-02-19 01:28:38 -060087 std::filesystem::create_directory(BAD_VPD_DIR);
88 auto l_badVpdPath = generateBadVPDFileName(i_vpdFilePath);
89
90 if (l_badVpdPath.empty())
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -050091 {
Souvik Roy8fc12522025-02-19 01:28:38 -060092 throw std::runtime_error("Failed to generate bad VPD file name");
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -050093 }
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -050094
Souvik Roy8fc12522025-02-19 01:28:38 -060095 if (std::filesystem::exists(l_badVpdPath))
96 {
97 std::error_code l_ec;
98 std::filesystem::remove(l_badVpdPath, l_ec);
99 if (l_ec) // error code
100 {
101 const std::string l_errorMsg{
102 "Error removing the existing broken vpd in " +
103 l_badVpdPath +
104 ". Error code : " + std::to_string(l_ec.value()) +
105 ". Error message : " + l_ec.message()};
106
107 throw std::runtime_error(l_errorMsg);
108 }
109 }
110
111 std::ofstream l_badVpdFileStream(l_badVpdPath, std::ofstream::binary);
112 if (!l_badVpdFileStream.is_open())
113 {
114 throw std::runtime_error(
115 "Failed to open bad vpd file path in /tmp/bad-vpd. "
116 "Unable to dump the broken/bad vpd file.");
117 }
118
119 l_badVpdFileStream.write(
120 reinterpret_cast<const char*>(i_vpdVector.data()),
121 i_vpdVector.size());
122
123 l_rc = constants::SUCCESS;
124 }
125 catch (const std::exception& l_ex)
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500126 {
Souvik Roy8fc12522025-02-19 01:28:38 -0600127 logging::logMessage("Failed to dump bad VPD for [" + i_vpdFilePath +
128 "]. Error: " + l_ex.what());
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500129 }
Souvik Roy8fc12522025-02-19 01:28:38 -0600130 return l_rc;
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500131}
132
133/**
134 * @brief An API to read value of a keyword.
135 *
136 * Note: Throws exception. Caller needs to handle.
137 *
138 * @param[in] kwdValueMap - A map having Kwd value pair.
139 * @param[in] kwd - keyword name.
140 * @param[out] kwdValue - Value of the keyword read from map.
141 */
142inline void getKwVal(const types::IPZKwdValueMap& kwdValueMap,
143 const std::string& kwd, std::string& kwdValue)
144{
145 if (kwd.empty())
146 {
147 logging::logMessage("Invalid parameters");
148 throw std::runtime_error("Invalid parameters");
149 }
150
151 auto itrToKwd = kwdValueMap.find(kwd);
152 if (itrToKwd != kwdValueMap.end())
153 {
154 kwdValue = itrToKwd->second;
155 return;
156 }
157
158 throw std::runtime_error("Keyword not found");
159}
160
161/**
162 * @brief An API to process encoding of a keyword.
163 *
Souvik Royf277d6a2025-02-20 00:08:43 -0600164 * @param[in] i_keyword - Keyword to be processed.
165 * @param[in] i_encoding - Type of encoding.
166 *
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500167 * @return Value after being processed for encoded type.
168 */
Souvik Royf277d6a2025-02-20 00:08:43 -0600169inline std::string encodeKeyword(const std::string& i_keyword,
170 const std::string& i_encoding) noexcept
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500171{
172 // Default value is keyword value
Souvik Royf277d6a2025-02-20 00:08:43 -0600173 std::string l_result(i_keyword.begin(), i_keyword.end());
174 try
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500175 {
Souvik Royf277d6a2025-02-20 00:08:43 -0600176 if (i_encoding == "MAC")
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500177 {
Souvik Royf277d6a2025-02-20 00:08:43 -0600178 l_result.clear();
179 size_t l_firstByte = i_keyword[0];
180 l_result += commonUtility::toHex(l_firstByte >> 4);
181 l_result += commonUtility::toHex(l_firstByte & 0x0f);
182 for (size_t i = 1; i < i_keyword.size(); ++i)
183 {
184 l_result += ":";
185 l_result += commonUtility::toHex(i_keyword[i] >> 4);
186 l_result += commonUtility::toHex(i_keyword[i] & 0x0f);
187 }
188 }
189 else if (i_encoding == "DATE")
190 {
191 // Date, represent as
192 // <year>-<month>-<day> <hour>:<min>
193 l_result.clear();
194 static constexpr uint8_t skipPrefix = 3;
195
196 auto strItr = i_keyword.begin();
197 advance(strItr, skipPrefix);
198 for_each(strItr, i_keyword.end(),
199 [&l_result](size_t c) { l_result += c; });
200
201 l_result.insert(constants::BD_YEAR_END, 1, '-');
202 l_result.insert(constants::BD_MONTH_END, 1, '-');
203 l_result.insert(constants::BD_DAY_END, 1, ' ');
204 l_result.insert(constants::BD_HOUR_END, 1, ':');
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500205 }
206 }
Souvik Royf277d6a2025-02-20 00:08:43 -0600207 catch (const std::exception& l_ex)
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500208 {
Souvik Royf277d6a2025-02-20 00:08:43 -0600209 l_result.clear();
210 logging::logMessage("Failed to encode keyword [" + i_keyword +
211 "]. Error: " + l_ex.what());
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500212 }
213
Souvik Royf277d6a2025-02-20 00:08:43 -0600214 return l_result;
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500215}
216
217/**
218 * @brief Helper function to insert or merge in map.
219 *
220 * This method checks in an interface if the given interface exists. If the
221 * interface key already exists, property map is inserted corresponding to it.
222 * If the key does'nt exist then given interface and property map pair is newly
223 * created. If the property present in propertymap already exist in the
224 * InterfaceMap, then the new property value is ignored.
225 *
226 * @param[in,out] map - Interface map.
227 * @param[in] interface - Interface to be processed.
228 * @param[in] propertyMap - new property map that needs to be emplaced.
229 */
230inline void insertOrMerge(types::InterfaceMap& map,
231 const std::string& interface,
232 types::PropertyMap&& propertyMap)
233{
234 if (map.find(interface) != map.end())
235 {
236 try
237 {
238 auto& prop = map.at(interface);
239 std::for_each(propertyMap.begin(), propertyMap.end(),
240 [&prop](auto l_keyValue) {
241 prop[l_keyValue.first] = l_keyValue.second;
242 });
243 }
244 catch (const std::exception& l_ex)
245 {
246 // ToDo:: Log PEL
247 logging::logMessage(
248 "Inserting properties into interface[" + interface +
249 "] map is failed, reason: " + std::string(l_ex.what()));
250 }
251 }
252 else
253 {
254 map.emplace(interface, propertyMap);
255 }
256}
257
258/**
259 * @brief API to expand unpanded location code.
260 *
261 * Note: The API handles all the exception internally, in case of any error
262 * unexpanded location code will be returned as it is.
263 *
264 * @param[in] unexpandedLocationCode - Unexpanded location code.
265 * @param[in] parsedVpdMap - Parsed VPD map.
266 * @return Expanded location code. In case of any error, unexpanded is returned
267 * as it is.
268 */
Patrick Williams43fedab2025-02-03 14:28:05 -0500269inline std::string getExpandedLocationCode(
270 const std::string& unexpandedLocationCode,
271 const types::VPDMapVariant& parsedVpdMap)
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500272{
273 auto expanded{unexpandedLocationCode};
274
275 try
276 {
277 // Expanded location code is formed by combining two keywords
278 // depending on type in unexpanded one. Second one is always "SE".
279 std::string kwd1, kwd2{constants::kwdSE};
280
281 // interface to search for required keywords;
282 std::string kwdInterface;
283
284 // record which holds the required keywords.
285 std::string recordName;
286
287 auto pos = unexpandedLocationCode.find("fcs");
288 if (pos != std::string::npos)
289 {
290 kwd1 = constants::kwdFC;
291 kwdInterface = constants::vcenInf;
292 recordName = constants::recVCEN;
293 }
294 else
295 {
296 pos = unexpandedLocationCode.find("mts");
297 if (pos != std::string::npos)
298 {
299 kwd1 = constants::kwdTM;
300 kwdInterface = constants::vsysInf;
301 recordName = constants::recVSYS;
302 }
303 else
304 {
305 throw std::runtime_error(
306 "Error detecting type of unexpanded location code.");
307 }
308 }
309
310 std::string firstKwdValue, secondKwdValue;
311
312 if (auto ipzVpdMap = std::get_if<types::IPZVpdMap>(&parsedVpdMap);
313 ipzVpdMap && (*ipzVpdMap).find(recordName) != (*ipzVpdMap).end())
314 {
315 auto itrToVCEN = (*ipzVpdMap).find(recordName);
316 // The exceptions will be cautght at end.
317 getKwVal(itrToVCEN->second, kwd1, firstKwdValue);
318 getKwVal(itrToVCEN->second, kwd2, secondKwdValue);
319 }
320 else
321 {
322 std::array<const char*, 1> interfaceList = {kwdInterface.c_str()};
323
324 types::MapperGetObject mapperRetValue = dbusUtility::getObjectMap(
325 std::string(constants::systemVpdInvPath), interfaceList);
326
327 if (mapperRetValue.empty())
328 {
329 throw std::runtime_error("Mapper failed to get service");
330 }
331
332 const std::string& serviceName = std::get<0>(mapperRetValue.at(0));
333
334 auto retVal = dbusUtility::readDbusProperty(
335 serviceName, std::string(constants::systemVpdInvPath),
336 kwdInterface, kwd1);
337
338 if (auto kwdVal = std::get_if<types::BinaryVector>(&retVal))
339 {
340 firstKwdValue.assign(
341 reinterpret_cast<const char*>(kwdVal->data()),
342 kwdVal->size());
343 }
344 else
345 {
346 throw std::runtime_error(
347 "Failed to read value of " + kwd1 + " from Bus");
348 }
349
350 retVal = dbusUtility::readDbusProperty(
351 serviceName, std::string(constants::systemVpdInvPath),
352 kwdInterface, kwd2);
353
354 if (auto kwdVal = std::get_if<types::BinaryVector>(&retVal))
355 {
356 secondKwdValue.assign(
357 reinterpret_cast<const char*>(kwdVal->data()),
358 kwdVal->size());
359 }
360 else
361 {
362 throw std::runtime_error(
363 "Failed to read value of " + kwd2 + " from Bus");
364 }
365 }
366
367 if (unexpandedLocationCode.find("fcs") != std::string::npos)
368 {
369 // TODO: See if ND0 can be placed in the JSON
370 expanded.replace(
371 pos, 3, firstKwdValue.substr(0, 4) + ".ND0." + secondKwdValue);
372 }
373 else
374 {
375 replace(firstKwdValue.begin(), firstKwdValue.end(), '-', '.');
376 expanded.replace(pos, 3, firstKwdValue + "." + secondKwdValue);
377 }
378 }
379 catch (const std::exception& ex)
380 {
381 logging::logMessage("Failed to expand location code with exception: " +
382 std::string(ex.what()));
383 }
384
385 return expanded;
386}
387
388/**
389 * @brief An API to get VPD in a vector.
390 *
391 * The vector is required by the respective parser to fill the VPD map.
392 * Note: API throws exception in case of failure. Caller needs to handle.
393 *
394 * @param[in] vpdFilePath - EEPROM path of the FRU.
395 * @param[out] vpdVector - VPD in vector form.
396 * @param[in] vpdStartOffset - Offset of VPD data in EEPROM.
397 */
398inline void getVpdDataInVector(const std::string& vpdFilePath,
399 types::BinaryVector& vpdVector,
400 size_t& vpdStartOffset)
401{
402 try
403 {
404 std::fstream vpdFileStream;
405 vpdFileStream.exceptions(
406 std::ifstream::badbit | std::ifstream::failbit);
407 vpdFileStream.open(vpdFilePath, std::ios::in | std::ios::binary);
408 auto vpdSizeToRead = std::min(std::filesystem::file_size(vpdFilePath),
409 static_cast<uintmax_t>(65504));
410 vpdVector.resize(vpdSizeToRead);
411
412 vpdFileStream.seekg(vpdStartOffset, std::ios_base::beg);
413 vpdFileStream.read(reinterpret_cast<char*>(&vpdVector[0]),
414 vpdSizeToRead);
415
416 vpdVector.resize(vpdFileStream.gcount());
417 vpdFileStream.clear(std::ios_base::eofbit);
418 }
419 catch (const std::ifstream::failure& fail)
420 {
421 std::cerr << "Exception in file handling [" << vpdFilePath
422 << "] error : " << fail.what();
423 throw;
424 }
425}
426
427/**
428 * @brief An API to get D-bus representation of given VPD keyword.
429 *
430 * @param[in] i_keywordName - VPD keyword name.
431 *
432 * @return D-bus representation of given keyword.
433 */
434inline std::string getDbusPropNameForGivenKw(const std::string& i_keywordName)
435{
436 // Check for "#" prefixed VPD keyword.
437 if ((i_keywordName.size() == vpd::constants::TWO_BYTES) &&
438 (i_keywordName.at(0) == constants::POUND_KW))
439 {
440 // D-bus doesn't support "#". Replace "#" with "PD_" for those "#"
441 // prefixed keywords.
442 return (std::string(constants::POUND_KW_PREFIX) +
443 i_keywordName.substr(1));
444 }
445
446 // Return the keyword name back, if D-bus representation is same as the VPD
447 // keyword name.
448 return i_keywordName;
449}
450
451/**
452 * @brief API to find CCIN in parsed VPD map.
453 *
454 * Few FRUs need some special handling. To identify those FRUs CCIN are used.
455 * The API will check from parsed VPD map if the FRU is the one with desired
456 * CCIN.
457 *
458 * @throw std::runtime_error
459 * @throw DataException
460 *
461 * @param[in] i_JsonObject - Any JSON which contains CCIN tag to match.
462 * @param[in] i_parsedVpdMap - Parsed VPD map.
463 * @return True if found, false otherwise.
464 */
465inline bool findCcinInVpd(const nlohmann::json& i_JsonObject,
466 const types::VPDMapVariant& i_parsedVpdMap)
467{
468 if (i_JsonObject.empty())
469 {
470 throw std::runtime_error("Json object is empty. Can't find CCIN");
471 }
472
473 if (auto l_ipzVPDMap = std::get_if<types::IPZVpdMap>(&i_parsedVpdMap))
474 {
475 auto l_itrToRec = (*l_ipzVPDMap).find("VINI");
476 if (l_itrToRec == (*l_ipzVPDMap).end())
477 {
478 throw DataException(
479 "VINI record not found in parsed VPD. Can't find CCIN");
480 }
481
482 std::string l_ccinFromVpd;
483 vpdSpecificUtility::getKwVal(l_itrToRec->second, "CC", l_ccinFromVpd);
484 if (l_ccinFromVpd.empty())
485 {
486 throw DataException("Empty CCIN value in VPD map. Can't find CCIN");
487 }
488
489 transform(l_ccinFromVpd.begin(), l_ccinFromVpd.end(),
490 l_ccinFromVpd.begin(), ::toupper);
491
492 for (std::string l_ccinValue : i_JsonObject["ccin"])
493 {
494 transform(l_ccinValue.begin(), l_ccinValue.end(),
495 l_ccinValue.begin(), ::toupper);
496
497 if (l_ccinValue.compare(l_ccinFromVpd) ==
498 constants::STR_CMP_SUCCESS)
499 {
500 // CCIN found
501 return true;
502 }
503 }
504
505 logging::logMessage("No match found for CCIN");
506 return false;
507 }
508
509 logging::logMessage("VPD type not supported. Can't find CCIN");
510 return false;
511}
512
513/**
514 * @brief API to reset data of a FRU populated under PIM.
515 *
516 * This API resets the data for particular interfaces of a FRU under PIM.
517 *
518 * @param[in] i_objectPath - DBus object path of the FRU.
519 * @param[in] io_interfaceMap - Interface and its properties map.
520 */
521inline void resetDataUnderPIM(const std::string& i_objectPath,
522 types::InterfaceMap& io_interfaceMap)
523{
524 try
525 {
526 std::array<const char*, 0> l_interfaces;
527 const types::MapperGetObject& l_getObjectMap =
528 dbusUtility::getObjectMap(i_objectPath, l_interfaces);
529
530 const std::vector<std::string>& l_vpdRelatedInterfaces{
531 constants::operationalStatusInf, constants::inventoryItemInf,
532 constants::assetInf};
533
534 for (const auto& [l_service, l_interfaceList] : l_getObjectMap)
535 {
536 if (l_service.compare(constants::pimServiceName) !=
537 constants::STR_CMP_SUCCESS)
538 {
539 continue;
540 }
541
542 for (const auto& l_interface : l_interfaceList)
543 {
544 if ((l_interface.find(constants::ipzVpdInf) !=
545 std::string::npos) ||
546 ((std::find(l_vpdRelatedInterfaces.begin(),
547 l_vpdRelatedInterfaces.end(), l_interface)) !=
548 l_vpdRelatedInterfaces.end()))
549 {
550 const types::PropertyMap& l_propertyValueMap =
551 dbusUtility::getPropertyMap(l_service, i_objectPath,
552 l_interface);
553
554 types::PropertyMap l_propertyMap;
555
556 for (const auto& l_aProperty : l_propertyValueMap)
557 {
558 const std::string& l_propertyName = l_aProperty.first;
559 const auto& l_propertyValue = l_aProperty.second;
560
561 if (std::holds_alternative<types::BinaryVector>(
562 l_propertyValue))
563 {
564 l_propertyMap.emplace(l_propertyName,
565 types::BinaryVector{});
566 }
567 else if (std::holds_alternative<std::string>(
568 l_propertyValue))
569 {
570 l_propertyMap.emplace(l_propertyName,
571 std::string{});
572 }
573 else if (std::holds_alternative<bool>(l_propertyValue))
574 {
575 // ToDo -- Update the functional status property
576 // to true.
577 if (l_propertyName.compare("Present") ==
578 constants::STR_CMP_SUCCESS)
579 {
580 l_propertyMap.emplace(l_propertyName, false);
581 }
582 }
583 }
584 io_interfaceMap.emplace(l_interface,
585 std::move(l_propertyMap));
586 }
587 }
588 }
589 }
590 catch (const std::exception& l_ex)
591 {
592 logging::logMessage("Failed to remove VPD for FRU: " + i_objectPath +
593 " with error: " + std::string(l_ex.what()));
594 }
595}
Sunny Srivastava78c91072025-02-05 14:09:50 +0530596
597/**
598 * @brief API to detect pass1 planar type.
599 *
600 * Based on HW version and IM keyword, This API detects is it is a pass1 planar
601 * or not.
602 *
603 * @return True if pass 1 planar, false otherwise.
604 */
605inline bool isPass1Planar()
606{
607 auto l_retVal = dbusUtility::readDbusProperty(
608 constants::pimServiceName, constants::systemVpdInvPath,
609 constants::viniInf, constants::kwdHW);
610
611 auto l_hwVer = std::get_if<types::BinaryVector>(&l_retVal);
612
613 l_retVal = dbusUtility::readDbusProperty(
614 constants::pimServiceName, constants::systemInvPath, constants::vsbpInf,
615 constants::kwdIM);
616
617 auto l_imValue = std::get_if<types::BinaryVector>(&l_retVal);
618
619 if (l_hwVer && l_imValue)
620 {
621 types::BinaryVector everest{80, 00, 48, 00};
622 types::BinaryVector fuji{96, 00, 32, 00};
623
624 if (((*l_imValue) == everest) || ((*l_imValue) == fuji))
625 {
626 if ((*l_hwVer).at(1) < constants::VALUE_21)
627 {
628 return true;
629 }
630 }
631 else if ((*l_hwVer).at(1) < constants::VALUE_2)
632 {
633 return true;
634 }
635 }
636
637 return false;
638}
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500639} // namespace vpdSpecificUtility
640} // namespace vpd