blob: 2eba0b13c3acc8f8784e051210710480f8df731e [file] [log] [blame]
SunnySrivastava198443306542020-04-01 02:50:20 -05001#include "config.h"
2
Sunny Srivastava6c71c9d2021-04-15 04:43:54 -05003#include "ibm_vpd_utils.hpp"
Patrick Venturec83c4dc2018-11-01 16:29:18 -07004
Sunny Srivastava6c71c9d2021-04-15 04:43:54 -05005#include "common_utility.hpp"
SunnySrivastava1984d076da82020-03-05 05:33:35 -06006#include "defines.hpp"
PriyangaRamasamyc0a534f2020-08-24 21:29:18 +05307#include "vpd_exceptions.hpp"
SunnySrivastava1984d076da82020-03-05 05:33:35 -06008
Alpana Kumari6bd095f2022-02-23 10:20:20 -06009#include <boost/algorithm/string.hpp>
PriyangaRamasamyc2fe40f2021-03-02 06:27:33 -060010#include <filesystem>
PriyangaRamasamyc0a534f2020-08-24 21:29:18 +053011#include <fstream>
Alpana Kumari735dee92022-03-25 01:24:40 -050012#include <gpiod.hpp>
PriyangaRamasamyc0a534f2020-08-24 21:29:18 +053013#include <iomanip>
Sunny Srivastava6c71c9d2021-04-15 04:43:54 -050014#include <nlohmann/json.hpp>
SunnySrivastava19849094d4f2020-08-05 09:32:29 -050015#include <phosphor-logging/elog-errors.hpp>
Patrick Venturec83c4dc2018-11-01 16:29:18 -070016#include <phosphor-logging/log.hpp>
PriyangaRamasamy647868e2020-09-08 17:03:19 +053017#include <regex>
Patrick Venturec83c4dc2018-11-01 16:29:18 -070018#include <sdbusplus/server.hpp>
PriyangaRamasamyc0a534f2020-08-24 21:29:18 +053019#include <sstream>
20#include <vector>
SunnySrivastava19849094d4f2020-08-05 09:32:29 -050021#include <xyz/openbmc_project/Common/error.hpp>
Deepak Kodihalli76794492017-02-16 23:48:18 -060022
PriyangaRamasamyc0a534f2020-08-24 21:29:18 +053023using json = nlohmann::json;
24
Deepak Kodihalli76794492017-02-16 23:48:18 -060025namespace openpower
26{
27namespace vpd
28{
SunnySrivastava1984945a02d2020-05-06 01:55:41 -050029using namespace openpower::vpd::constants;
SunnySrivastava1984a20be8e2020-08-26 02:00:50 -050030using namespace inventory;
31using namespace phosphor::logging;
SunnySrivastava19849094d4f2020-08-05 09:32:29 -050032using namespace sdbusplus::xyz::openbmc_project::Common::Error;
PriyangaRamasamyc0a534f2020-08-24 21:29:18 +053033using namespace record;
34using namespace openpower::vpd::exceptions;
Sunny Srivastava6c71c9d2021-04-15 04:43:54 -050035using namespace common::utility;
Sunny Srivastava0746eee2021-03-22 13:36:54 -050036using Severity = openpower::vpd::constants::PelSeverity;
PriyangaRamasamyc2fe40f2021-03-02 06:27:33 -060037namespace fs = std::filesystem;
Sunny Srivastava0746eee2021-03-22 13:36:54 -050038
39// mapping of severity enum to severity interface
40static std::unordered_map<Severity, std::string> sevMap = {
41 {Severity::INFORMATIONAL,
42 "xyz.openbmc_project.Logging.Entry.Level.Informational"},
43 {Severity::DEBUG, "xyz.openbmc_project.Logging.Entry.Level.Debug"},
44 {Severity::NOTICE, "xyz.openbmc_project.Logging.Entry.Level.Notice"},
45 {Severity::WARNING, "xyz.openbmc_project.Logging.Entry.Level.Warning"},
46 {Severity::CRITICAL, "xyz.openbmc_project.Logging.Entry.Level.Critical"},
47 {Severity::EMERGENCY, "xyz.openbmc_project.Logging.Entry.Level.Emergency"},
48 {Severity::ERROR, "xyz.openbmc_project.Logging.Entry.Level.Error"},
49 {Severity::ALERT, "xyz.openbmc_project.Logging.Entry.Level.Alert"}};
50
Deepak Kodihalli76794492017-02-16 23:48:18 -060051namespace inventory
52{
53
SunnySrivastava19849094d4f2020-08-05 09:32:29 -050054MapperResponse
55 getObjectSubtreeForInterfaces(const std::string& root, const int32_t depth,
56 const std::vector<std::string>& interfaces)
57{
58 auto bus = sdbusplus::bus::new_default();
59 auto mapperCall = bus.new_method_call(mapperDestination, mapperObjectPath,
60 mapperInterface, "GetSubTree");
61 mapperCall.append(root);
62 mapperCall.append(depth);
63 mapperCall.append(interfaces);
64
65 MapperResponse result = {};
66
67 try
68 {
69 auto response = bus.call(mapperCall);
70
71 response.read(result);
72 }
Patrick Williams2eb01762022-07-22 19:26:56 -050073 catch (const sdbusplus::exception_t& e)
SunnySrivastava19849094d4f2020-08-05 09:32:29 -050074 {
75 log<level::ERR>("Error in mapper GetSubTree",
76 entry("ERROR=%s", e.what()));
77 }
78
79 return result;
80}
81
Deepak Kodihalli76794492017-02-16 23:48:18 -060082} // namespace inventory
83
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -060084LE2ByteData readUInt16LE(Binary::const_iterator iterator)
85{
86 LE2ByteData lowByte = *iterator;
87 LE2ByteData highByte = *(iterator + 1);
88 lowByte |= (highByte << 8);
89 return lowByte;
90}
91
SunnySrivastava1984d076da82020-03-05 05:33:35 -060092/** @brief Encodes a keyword for D-Bus.
93 */
Priyanga Ramasamye0084322022-09-27 06:28:33 -050094std::string encodeKeyword(const std::string& kw, const std::string& encoding)
SunnySrivastava1984d076da82020-03-05 05:33:35 -060095{
96 if (encoding == "MAC")
97 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -050098 std::string res{};
SunnySrivastava1984d076da82020-03-05 05:33:35 -060099 size_t first = kw[0];
100 res += toHex(first >> 4);
101 res += toHex(first & 0x0f);
102 for (size_t i = 1; i < kw.size(); ++i)
103 {
104 res += ":";
105 res += toHex(kw[i] >> 4);
106 res += toHex(kw[i] & 0x0f);
107 }
108 return res;
109 }
110 else if (encoding == "DATE")
111 {
112 // Date, represent as
113 // <year>-<month>-<day> <hour>:<min>
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500114 std::string res{};
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600115 static constexpr uint8_t skipPrefix = 3;
116
117 auto strItr = kw.begin();
118 advance(strItr, skipPrefix);
119 for_each(strItr, kw.end(), [&res](size_t c) { res += c; });
120
121 res.insert(BD_YEAR_END, 1, '-');
122 res.insert(BD_MONTH_END, 1, '-');
123 res.insert(BD_DAY_END, 1, ' ');
124 res.insert(BD_HOUR_END, 1, ':');
125
126 return res;
127 }
128 else // default to string encoding
129 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500130 return std::string(kw.begin(), kw.end());
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600131 }
132}
SunnySrivastava198443306542020-04-01 02:50:20 -0500133
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500134std::string readBusProperty(const std::string& obj, const std::string& inf,
135 const std::string& prop)
SunnySrivastava198443306542020-04-01 02:50:20 -0500136{
137 std::string propVal{};
138 std::string object = INVENTORY_PATH + obj;
139 auto bus = sdbusplus::bus::new_default();
140 auto properties = bus.new_method_call(
141 "xyz.openbmc_project.Inventory.Manager", object.c_str(),
142 "org.freedesktop.DBus.Properties", "Get");
143 properties.append(inf);
144 properties.append(prop);
145 auto result = bus.call(properties);
146 if (!result.is_method_error())
147 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500148 std::variant<Binary, std::string> val;
SunnySrivastava198443306542020-04-01 02:50:20 -0500149 result.read(val);
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500150 if (auto pVal = std::get_if<Binary>(&val))
SunnySrivastava198443306542020-04-01 02:50:20 -0500151 {
152 propVal.assign(reinterpret_cast<const char*>(pVal->data()),
153 pVal->size());
154 }
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500155 else if (auto pVal = std::get_if<std::string>(&val))
SunnySrivastava1984bca5aaa2020-04-21 05:31:04 -0500156 {
157 propVal.assign(pVal->data(), pVal->size());
158 }
SunnySrivastava198443306542020-04-01 02:50:20 -0500159 }
160 return propVal;
161}
SunnySrivastava1984a20be8e2020-08-26 02:00:50 -0500162
163void createPEL(const std::map<std::string, std::string>& additionalData,
Sunny Srivastava0746eee2021-03-22 13:36:54 -0500164 const Severity& sev, const std::string& errIntf)
SunnySrivastava1984a20be8e2020-08-26 02:00:50 -0500165{
166 try
167 {
Sunny Srivastava0746eee2021-03-22 13:36:54 -0500168 std::string pelSeverity =
169 "xyz.openbmc_project.Logging.Entry.Level.Error";
SunnySrivastava1984a20be8e2020-08-26 02:00:50 -0500170 auto bus = sdbusplus::bus::new_default();
SunnySrivastava1984a20be8e2020-08-26 02:00:50 -0500171 auto service = getService(bus, loggerObjectPath, loggerCreateInterface);
172 auto method = bus.new_method_call(service.c_str(), loggerObjectPath,
173 loggerCreateInterface, "Create");
174
Sunny Srivastava0746eee2021-03-22 13:36:54 -0500175 auto itr = sevMap.find(sev);
176 if (itr != sevMap.end())
177 {
178 pelSeverity = itr->second;
179 }
180
181 method.append(errIntf, pelSeverity, additionalData);
SunnySrivastava1984a20be8e2020-08-26 02:00:50 -0500182 auto resp = bus.call(method);
183 }
Patrick Williams2eb01762022-07-22 19:26:56 -0500184 catch (const sdbusplus::exception_t& e)
SunnySrivastava1984a20be8e2020-08-26 02:00:50 -0500185 {
186 throw std::runtime_error(
187 "Error in invoking D-Bus logging create interface to register PEL");
188 }
189}
PriyangaRamasamyc0a534f2020-08-24 21:29:18 +0530190
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500191inventory::VPDfilepath getVpdFilePath(const std::string& jsonFile,
PriyangaRamasamyc0a534f2020-08-24 21:29:18 +0530192 const std::string& ObjPath)
193{
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500194 std::ifstream inventoryJson(jsonFile);
PriyangaRamasamyc0a534f2020-08-24 21:29:18 +0530195 const auto& jsonObject = json::parse(inventoryJson);
196 inventory::VPDfilepath filePath{};
197
198 if (jsonObject.find("frus") == jsonObject.end())
199 {
200 throw(VpdJsonException(
201 "Invalid JSON structure - frus{} object not found in ", jsonFile));
202 }
203
204 const nlohmann::json& groupFRUS =
205 jsonObject["frus"].get_ref<const nlohmann::json::object_t&>();
206 for (const auto& itemFRUS : groupFRUS.items())
207 {
208 const std::vector<nlohmann::json>& groupEEPROM =
209 itemFRUS.value().get_ref<const nlohmann::json::array_t&>();
210 for (const auto& itemEEPROM : groupEEPROM)
211 {
212 if (itemEEPROM["inventoryPath"]
213 .get_ref<const nlohmann::json::string_t&>() == ObjPath)
214 {
215 filePath = itemFRUS.key();
216 return filePath;
217 }
218 }
219 }
220
221 return filePath;
222}
223
224bool isPathInJson(const std::string& eepromPath)
225{
226 bool present = false;
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500227 std::ifstream inventoryJson(INVENTORY_JSON_SYM_LINK);
PriyangaRamasamyc0a534f2020-08-24 21:29:18 +0530228
229 try
230 {
231 auto js = json::parse(inventoryJson);
232 if (js.find("frus") == js.end())
233 {
234 throw(VpdJsonException(
235 "Invalid JSON structure - frus{} object not found in ",
236 INVENTORY_JSON_SYM_LINK));
237 }
238 json fruJson = js["frus"];
239
240 if (fruJson.find(eepromPath) != fruJson.end())
241 {
242 present = true;
243 }
244 }
Patrick Williams8e15b932021-10-06 13:04:22 -0500245 catch (const json::parse_error& ex)
PriyangaRamasamyc0a534f2020-08-24 21:29:18 +0530246 {
247 throw(VpdJsonException("Json Parsing failed", INVENTORY_JSON_SYM_LINK));
248 }
249 return present;
250}
251
252bool isRecKwInDbusJson(const std::string& recordName,
253 const std::string& keyword)
254{
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500255 std::ifstream propertyJson(DBUS_PROP_JSON);
PriyangaRamasamyc0a534f2020-08-24 21:29:18 +0530256 json dbusProperty;
257 bool present = false;
258
259 if (propertyJson.is_open())
260 {
261 try
262 {
263 auto dbusPropertyJson = json::parse(propertyJson);
264 if (dbusPropertyJson.find("dbusProperties") ==
265 dbusPropertyJson.end())
266 {
267 throw(VpdJsonException("dbusProperties{} object not found in "
268 "DbusProperties json : ",
269 DBUS_PROP_JSON));
270 }
271
272 dbusProperty = dbusPropertyJson["dbusProperties"];
273 if (dbusProperty.contains(recordName))
274 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500275 const std::vector<std::string>& kwdsToPublish =
276 dbusProperty[recordName];
PriyangaRamasamyc0a534f2020-08-24 21:29:18 +0530277 if (find(kwdsToPublish.begin(), kwdsToPublish.end(), keyword) !=
278 kwdsToPublish.end()) // present
279 {
280 present = true;
281 }
282 }
283 }
Patrick Williams8e15b932021-10-06 13:04:22 -0500284 catch (const json::parse_error& ex)
PriyangaRamasamyc0a534f2020-08-24 21:29:18 +0530285 {
286 throw(VpdJsonException("Json Parsing failed", DBUS_PROP_JSON));
287 }
288 }
289 else
290 {
291 // If dbus properties json is not available, we assume the given
292 // record-keyword is part of dbus-properties json. So setting the bool
293 // variable to true.
294 present = true;
295 }
296 return present;
297}
298
Sunny Srivastava6c71c9d2021-04-15 04:43:54 -0500299vpdType vpdTypeCheck(const Binary& vpdVector)
300{
301 // Read first 3 Bytes to check the 11S bar code format
302 std::string is11SFormat = "";
303 for (uint8_t i = 0; i < FORMAT_11S_LEN; i++)
304 {
305 is11SFormat += vpdVector[MEMORY_VPD_DATA_START + i];
306 }
307
308 if (vpdVector[IPZ_DATA_START] == KW_VAL_PAIR_START_TAG)
309 {
310 // IPZ VPD FORMAT
311 return vpdType::IPZ_VPD;
312 }
313 else if (vpdVector[KW_VPD_DATA_START] == KW_VPD_START_TAG)
314 {
315 // KEYWORD VPD FORMAT
316 return vpdType::KEYWORD_VPD;
317 }
318 else if (is11SFormat.compare(MEMORY_VPD_START_TAG) == 0)
319 {
320 // Memory VPD format
321 return vpdType::MEMORY_VPD;
322 }
323
324 // INVALID VPD FORMAT
325 return vpdType::INVALID_VPD_FORMAT;
326}
327
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500328const std::string getIM(const Parsed& vpdMap)
Alpana Kumarif05effd2021-04-07 07:32:53 -0500329{
330 Binary imVal;
331 auto property = vpdMap.find("VSBP");
332 if (property != vpdMap.end())
333 {
334 auto kw = (property->second).find("IM");
335 if (kw != (property->second).end())
336 {
337 copy(kw->second.begin(), kw->second.end(), back_inserter(imVal));
338 }
339 }
340
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500341 std::ostringstream oss;
Alpana Kumarif05effd2021-04-07 07:32:53 -0500342 for (auto& i : imVal)
343 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500344 oss << std::setw(2) << std::setfill('0') << std::hex
345 << static_cast<int>(i);
Alpana Kumarif05effd2021-04-07 07:32:53 -0500346 }
347
348 return oss.str();
349}
350
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500351const std::string getHW(const Parsed& vpdMap)
Alpana Kumarif05effd2021-04-07 07:32:53 -0500352{
353 Binary hwVal;
354 auto prop = vpdMap.find("VINI");
355 if (prop != vpdMap.end())
356 {
357 auto kw = (prop->second).find("HW");
358 if (kw != (prop->second).end())
359 {
360 copy(kw->second.begin(), kw->second.end(), back_inserter(hwVal));
361 }
362 }
363
Alpana Kumari88d2ae82021-11-10 03:23:31 -0600364 // The planar pass only comes from the LSB of the HW keyword,
365 // where as the MSB is used for other purposes such as signifying clock
366 // termination.
367 hwVal[0] = 0x00;
368
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500369 std::ostringstream hwString;
Alpana Kumarif05effd2021-04-07 07:32:53 -0500370 for (auto& i : hwVal)
371 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500372 hwString << std::setw(2) << std::setfill('0') << std::hex
373 << static_cast<int>(i);
Alpana Kumarif05effd2021-04-07 07:32:53 -0500374 }
375
376 return hwString.str();
377}
378
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500379std::string getSystemsJson(const Parsed& vpdMap)
Alpana Kumarif05effd2021-04-07 07:32:53 -0500380{
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500381 std::string jsonPath = "/usr/share/vpd/";
382 std::string jsonName{};
Alpana Kumarif05effd2021-04-07 07:32:53 -0500383
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500384 std::ifstream systemJson(SYSTEM_JSON);
Alpana Kumarif05effd2021-04-07 07:32:53 -0500385 if (!systemJson)
386 {
387 throw((VpdJsonException("Failed to access Json path", SYSTEM_JSON)));
388 }
389
390 try
391 {
392 auto js = json::parse(systemJson);
393
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500394 std::string hwKeyword = getHW(vpdMap);
395 const std::string imKeyword = getIM(vpdMap);
Alpana Kumarif05effd2021-04-07 07:32:53 -0500396
Alpana Kumari1b026112022-03-02 23:41:38 -0600397 transform(hwKeyword.begin(), hwKeyword.end(), hwKeyword.begin(),
398 ::toupper);
399
Alpana Kumarif05effd2021-04-07 07:32:53 -0500400 if (js.find("system") == js.end())
401 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500402 throw std::runtime_error("Invalid systems Json");
Alpana Kumarif05effd2021-04-07 07:32:53 -0500403 }
404
405 if (js["system"].find(imKeyword) == js["system"].end())
406 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500407 throw std::runtime_error(
Alpana Kumarif05effd2021-04-07 07:32:53 -0500408 "Invalid system. This system type is not present "
409 "in the systemsJson. IM: " +
410 imKeyword);
411 }
412
413 if ((js["system"][imKeyword].find("constraint") !=
414 js["system"][imKeyword].end()) &&
Alpana Kumari1b026112022-03-02 23:41:38 -0600415 js["system"][imKeyword]["constraint"].find("HW") !=
416 js["system"][imKeyword]["constraint"].end())
Alpana Kumarif05effd2021-04-07 07:32:53 -0500417 {
Alpana Kumari1b026112022-03-02 23:41:38 -0600418 // collect hw versions from json, and check hwKeyword is part of it
419 // if hwKeyword is found there then load respective json
420 // otherwise load default one.
421 for (const auto& hwVersion :
422 js["system"][imKeyword]["constraint"]["HW"])
423 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500424 std::string hw = hwVersion;
Alpana Kumari1b026112022-03-02 23:41:38 -0600425 transform(hw.begin(), hw.end(), hw.begin(), ::toupper);
426
427 if (hw == hwKeyword)
428 {
429 jsonName = js["system"][imKeyword]["constraint"]["json"];
430 break;
431 }
432 }
433
434 if (jsonName.empty() && js["system"][imKeyword].find("default") !=
435 js["system"][imKeyword].end())
436 {
437 jsonName = js["system"][imKeyword]["default"];
438 }
Alpana Kumarif05effd2021-04-07 07:32:53 -0500439 }
440 else if (js["system"][imKeyword].find("default") !=
441 js["system"][imKeyword].end())
442 {
443 jsonName = js["system"][imKeyword]["default"];
444 }
445 else
446 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500447 throw std::runtime_error(
Alpana Kumarif05effd2021-04-07 07:32:53 -0500448 "Bad System json. Neither constraint nor default found");
449 }
450
451 jsonPath += jsonName;
452 }
453
Patrick Williams8e15b932021-10-06 13:04:22 -0500454 catch (const json::parse_error& ex)
Alpana Kumarif05effd2021-04-07 07:32:53 -0500455 {
456 throw(VpdJsonException("Json Parsing failed", SYSTEM_JSON));
457 }
458 return jsonPath;
459}
460
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500461void udevToGenericPath(std::string& file)
PriyangaRamasamy647868e2020-09-08 17:03:19 +0530462{
463 // Sample udevEvent i2c path :
464 // "/sys/devices/platform/ahb/ahb:apb/ahb:apb:bus@1e78a000/1e78a480.i2c-bus/i2c-8/8-0051/8-00510/nvmem"
465 // find if the path contains the word i2c in it.
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500466 if (file.find("i2c") != std::string::npos)
PriyangaRamasamy647868e2020-09-08 17:03:19 +0530467 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500468 std::string i2cBusAddr{};
PriyangaRamasamy647868e2020-09-08 17:03:19 +0530469
470 // Every udev i2c path should have the common pattern
471 // "i2c-bus_number/bus_number-vpd_address". Search for
472 // "bus_number-vpd_address".
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500473 std::regex i2cPattern("((i2c)-[0-9]+\\/)([0-9]+-[0-9]{4})");
474 std::smatch match;
475 if (std::regex_search(file, match, i2cPattern))
PriyangaRamasamy647868e2020-09-08 17:03:19 +0530476 {
477 i2cBusAddr = match.str(3);
478 }
479 else
480 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500481 std::cerr << "The given udev path < " << file
482 << " > doesn't match the required pattern. Skipping VPD "
483 "collection."
484 << std::endl;
PriyangaRamasamy647868e2020-09-08 17:03:19 +0530485 exit(EXIT_SUCCESS);
486 }
487 // Forming the generic file path
488 file = i2cPathPrefix + i2cBusAddr + "/eeprom";
489 }
490 // Sample udevEvent spi path :
491 // "/sys/devices/platform/ahb/ahb:apb/1e79b000.fsi/fsi-master/fsi0/slave@00:00/00:00:00:04/spi_master/spi2/spi2.0/spi2.00/nvmem"
492 // find if the path contains the word spi in it.
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500493 else if (file.find("spi") != std::string::npos)
PriyangaRamasamy647868e2020-09-08 17:03:19 +0530494 {
495 // Every udev spi path will have common pattern "spi<Digit>/", which
496 // describes the spi bus number at which the fru is connected; Followed
497 // by a slash following the vpd address of the fru. Taking the above
498 // input as a common key, we try to search for the pattern "spi<Digit>/"
499 // using regular expression.
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500500 std::regex spiPattern("((spi)[0-9]+)(\\/)");
501 std::string spiBus{};
502 std::smatch match;
503 if (std::regex_search(file, match, spiPattern))
PriyangaRamasamy647868e2020-09-08 17:03:19 +0530504 {
505 spiBus = match.str(1);
506 }
507 else
508 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500509 std::cerr << "The given udev path < " << file
510 << " > doesn't match the required pattern. Skipping VPD "
511 "collection."
512 << std::endl;
PriyangaRamasamy647868e2020-09-08 17:03:19 +0530513 exit(EXIT_SUCCESS);
514 }
515 // Forming the generic path
516 file = spiPathPrefix + spiBus + ".0/eeprom";
517 }
518 else
519 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500520 std::cerr << "\n The given EEPROM path < " << file
521 << " > is not valid. It's neither I2C nor "
522 "SPI path. Skipping VPD collection.."
523 << std::endl;
PriyangaRamasamy647868e2020-09-08 17:03:19 +0530524 exit(EXIT_SUCCESS);
525 }
526}
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500527std::string getBadVpdName(const std::string& file)
PriyangaRamasamyc2fe40f2021-03-02 06:27:33 -0600528{
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500529 std::string badVpd = BAD_VPD_DIR;
530 if (file.find("i2c") != std::string::npos)
PriyangaRamasamyc2fe40f2021-03-02 06:27:33 -0600531 {
532 badVpd += "i2c-";
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500533 std::regex i2cPattern("(at24/)([0-9]+-[0-9]+)\\/");
534 std::smatch match;
535 if (std::regex_search(file, match, i2cPattern))
PriyangaRamasamyc2fe40f2021-03-02 06:27:33 -0600536 {
537 badVpd += match.str(2);
538 }
539 }
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500540 else if (file.find("spi") != std::string::npos)
PriyangaRamasamyc2fe40f2021-03-02 06:27:33 -0600541 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500542 std::regex spiPattern("((spi)[0-9]+)(.0)");
543 std::smatch match;
544 if (std::regex_search(file, match, spiPattern))
PriyangaRamasamyc2fe40f2021-03-02 06:27:33 -0600545 {
546 badVpd += match.str(1);
547 }
548 }
549 return badVpd;
550}
551
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500552void dumpBadVpd(const std::string& file, const Binary& vpdVector)
PriyangaRamasamyc2fe40f2021-03-02 06:27:33 -0600553{
554 fs::path badVpdDir = BAD_VPD_DIR;
555 fs::create_directory(badVpdDir);
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500556 std::string badVpdPath = getBadVpdName(file);
PriyangaRamasamyc2fe40f2021-03-02 06:27:33 -0600557 if (fs::exists(badVpdPath))
558 {
559 std::error_code ec;
560 fs::remove(badVpdPath, ec);
561 if (ec) // error code
562 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500563 std::string error = "Error removing the existing broken vpd in ";
PriyangaRamasamyc2fe40f2021-03-02 06:27:33 -0600564 error += badVpdPath;
565 error += ". Error code : ";
566 error += ec.value();
567 error += ". Error message : ";
568 error += ec.message();
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500569 throw std::runtime_error(error);
PriyangaRamasamyc2fe40f2021-03-02 06:27:33 -0600570 }
571 }
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500572 std::ofstream badVpdFileStream(badVpdPath, std::ofstream::binary);
PriyangaRamasamyc2fe40f2021-03-02 06:27:33 -0600573 if (!badVpdFileStream)
574 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500575 throw std::runtime_error(
576 "Failed to open bad vpd file path in /tmp/bad-vpd. "
577 "Unable to dump the broken/bad vpd file.");
PriyangaRamasamyc2fe40f2021-03-02 06:27:33 -0600578 }
579 badVpdFileStream.write(reinterpret_cast<const char*>(vpdVector.data()),
580 vpdVector.size());
581}
alpana077ce68722021-07-25 13:23:59 -0500582
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500583const std::string getKwVal(const Parsed& vpdMap, const std::string& rec,
584 const std::string& kwd)
alpana077ce68722021-07-25 13:23:59 -0500585{
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500586 std::string kwVal{};
alpana077ce68722021-07-25 13:23:59 -0500587
588 auto findRec = vpdMap.find(rec);
589
590 // check if record is found in map we got by parser
591 if (findRec != vpdMap.end())
592 {
593 auto findKwd = findRec->second.find(kwd);
594
595 if (findKwd != findRec->second.end())
596 {
597 kwVal = findKwd->second;
598 }
599 }
600
601 return kwVal;
602}
603
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500604std::string byteArrayToHexString(const Binary& vec)
Priyanga Ramasamyc9ecf8e2021-10-08 02:28:52 -0500605{
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500606 std::stringstream ss;
607 std::string hexRep = "0x";
Priyanga Ramasamyc9ecf8e2021-10-08 02:28:52 -0500608 ss << hexRep;
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500609 std::string str = ss.str();
Priyanga Ramasamyc9ecf8e2021-10-08 02:28:52 -0500610
611 // convert Decimal to Hex string
612 for (auto& v : vec)
613 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500614 ss << std::setfill('0') << std::setw(2) << std::hex << (int)v;
Priyanga Ramasamyc9ecf8e2021-10-08 02:28:52 -0500615 str = ss.str();
616 }
617 return str;
618}
619
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500620std::string getPrintableValue(const Binary& vec)
Priyanga Ramasamy02434932021-10-07 16:26:05 -0500621{
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500622 std::string str{};
Priyanga Ramasamy02434932021-10-07 16:26:05 -0500623
Priyanga Ramasamyc9ecf8e2021-10-08 02:28:52 -0500624 // find for a non printable value in the vector
625 const auto it = std::find_if(vec.begin(), vec.end(),
626 [](const auto& ele) { return !isprint(ele); });
Priyanga Ramasamy02434932021-10-07 16:26:05 -0500627
Priyanga Ramasamyc9ecf8e2021-10-08 02:28:52 -0500628 if (it != vec.end()) // if the given vector has any non printable value
629 {
630 for (auto itr = it; itr != vec.end(); itr++)
Priyanga Ramasamy02434932021-10-07 16:26:05 -0500631 {
Priyanga Ramasamyc9ecf8e2021-10-08 02:28:52 -0500632 if (*itr != 0x00)
633 {
634 str = byteArrayToHexString(vec);
635 return str;
636 }
Priyanga Ramasamy02434932021-10-07 16:26:05 -0500637 }
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500638 str = std::string(vec.begin(), it);
Priyanga Ramasamy02434932021-10-07 16:26:05 -0500639 }
640 else
641 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500642 str = std::string(vec.begin(), vec.end());
Priyanga Ramasamy02434932021-10-07 16:26:05 -0500643 }
644 return str;
645}
646
Alpana Kumari6bd095f2022-02-23 10:20:20 -0600647/*
648 * @brief Log PEL for GPIO exception
649 *
650 * @param[in] gpioErr gpioError type exception
651 * @param[in] i2cBusAddr I2C bus and address
652 */
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500653void logGpioPel(const std::string& gpioErr, const std::string& i2cBusAddr)
Alpana Kumari6bd095f2022-02-23 10:20:20 -0600654{
655 // Get the IIC details
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500656 std::vector<std::string> i2cReg;
Alpana Kumari6bd095f2022-02-23 10:20:20 -0600657 boost::split(i2cReg, i2cBusAddr, boost::is_any_of("-"));
658
659 PelAdditionalData additionalData{};
660 if (i2cReg.size() == 2)
661 {
662 additionalData.emplace("CALLOUT_IIC_BUS", i2cReg[0]);
663 additionalData.emplace("CALLOUT_IIC_ADDR", "0x" + i2cReg[1]);
664 }
665
666 additionalData.emplace("DESCRIPTION", gpioErr);
667 createPEL(additionalData, PelSeverity::WARNING, errIntfForGpioError);
668}
669
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500670void executePostFailAction(const nlohmann::json& json, const std::string& file)
Alpana Kumari735dee92022-03-25 01:24:40 -0500671{
672 if ((json["frus"][file].at(0)).find("postActionFail") ==
673 json["frus"][file].at(0).end())
674 {
675 return;
676 }
677
678 uint8_t pinValue = 0;
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500679 std::string pinName;
Alpana Kumari735dee92022-03-25 01:24:40 -0500680
681 for (const auto& postAction :
682 (json["frus"][file].at(0))["postActionFail"].items())
683 {
684 if (postAction.key() == "pin")
685 {
686 pinName = postAction.value();
687 }
688 else if (postAction.key() == "value")
689 {
690 // Get the value to set
691 pinValue = postAction.value();
692 }
693 }
694
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500695 std::cout << "Setting GPIO: " << pinName << " to " << (int)pinValue
696 << std::endl;
Alpana Kumari735dee92022-03-25 01:24:40 -0500697
698 try
699 {
700 gpiod::line outputLine = gpiod::find_line(pinName);
701
702 if (!outputLine)
703 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500704 throw std::runtime_error(
Alpana Kumari6bd095f2022-02-23 10:20:20 -0600705 "Couldn't find output line for the GPIO. Skipping "
706 "this GPIO action.");
Alpana Kumari735dee92022-03-25 01:24:40 -0500707 }
708 outputLine.request(
709 {"Disable line", ::gpiod::line_request::DIRECTION_OUTPUT, 0},
710 pinValue);
711 }
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500712 catch (const std::exception& e)
Alpana Kumari735dee92022-03-25 01:24:40 -0500713 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500714 std::string i2cBusAddr;
715 std::string errMsg = e.what();
Alpana Kumari6bd095f2022-02-23 10:20:20 -0600716 errMsg += "\nGPIO: " + pinName;
717
718 if ((json["frus"][file].at(0)["postActionFail"].find(
719 "gpioI2CAddress")) !=
720 json["frus"][file].at(0)["postActionFail"].end())
721 {
722 i2cBusAddr =
723 json["frus"][file].at(0)["postActionFail"]["gpioI2CAddress"];
724 }
725
726 logGpioPel(errMsg, i2cBusAddr);
Alpana Kumari735dee92022-03-25 01:24:40 -0500727 }
Alpana Kumari6bd095f2022-02-23 10:20:20 -0600728
729 return;
Alpana Kumari735dee92022-03-25 01:24:40 -0500730}
731
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500732std::optional<bool> isPresent(const nlohmann::json& json,
733 const std::string& file)
Santosh Puranik53b38ed2022-04-10 23:15:22 +0530734
Alpana Kumari735dee92022-03-25 01:24:40 -0500735{
736 if ((json["frus"][file].at(0)).find("presence") !=
737 json["frus"][file].at(0).end())
738 {
739 if (((json["frus"][file].at(0)["presence"]).find("pin") !=
740 json["frus"][file].at(0)["presence"].end()) &&
741 ((json["frus"][file].at(0)["presence"]).find("value") !=
742 json["frus"][file].at(0)["presence"].end()))
743 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500744 std::string presPinName =
745 json["frus"][file].at(0)["presence"]["pin"];
Alpana Kumari735dee92022-03-25 01:24:40 -0500746 Byte presPinValue = json["frus"][file].at(0)["presence"]["value"];
747
748 try
749 {
750 gpiod::line presenceLine = gpiod::find_line(presPinName);
751
752 if (!presenceLine)
753 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500754 std::cerr << "Couldn't find the presence line for - "
755 << presPinName << std::endl;
Alpana Kumari40d1c192022-03-09 21:16:02 -0600756
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500757 throw std::runtime_error(
Alpana Kumari6bd095f2022-02-23 10:20:20 -0600758 "Couldn't find the presence line for the "
759 "GPIO. Skipping this GPIO action.");
Alpana Kumari735dee92022-03-25 01:24:40 -0500760 }
761
762 presenceLine.request({"Read the presence line",
763 gpiod::line_request::DIRECTION_INPUT, 0});
764
765 Byte gpioData = presenceLine.get_value();
766
Santosh Puranik53b38ed2022-04-10 23:15:22 +0530767 return (gpioData == presPinValue);
Alpana Kumari735dee92022-03-25 01:24:40 -0500768 }
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500769 catch (const std::exception& e)
Alpana Kumari735dee92022-03-25 01:24:40 -0500770 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500771 std::string i2cBusAddr;
772 std::string errMsg = e.what();
Alpana Kumari6bd095f2022-02-23 10:20:20 -0600773 errMsg += " GPIO : " + presPinName;
774
775 if ((json["frus"][file].at(0)["presence"])
776 .find("gpioI2CAddress") !=
777 json["frus"][file].at(0)["presence"].end())
778 {
779 i2cBusAddr =
780 json["frus"][file].at(0)["presence"]["gpioI2CAddress"];
781 }
782
783 logGpioPel(errMsg, i2cBusAddr);
Alpana Kumari40d1c192022-03-09 21:16:02 -0600784 // Take failure postAction
785 executePostFailAction(json, file);
Alpana Kumari735dee92022-03-25 01:24:40 -0500786 return false;
787 }
788 }
Alpana Kumari40d1c192022-03-09 21:16:02 -0600789 else
790 {
791 // missing required informations
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500792 std::cerr
793 << "VPD inventory JSON missing basic informations of presence "
794 "for this FRU : ["
795 << file << "]. Executing executePostFailAction." << std::endl;
Alpana Kumari40d1c192022-03-09 21:16:02 -0600796
797 // Take failure postAction
798 executePostFailAction(json, file);
799
800 return false;
801 }
Alpana Kumari735dee92022-03-25 01:24:40 -0500802 }
Santosh Puranik53b38ed2022-04-10 23:15:22 +0530803 return std::optional<bool>{};
804}
805
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500806bool executePreAction(const nlohmann::json& json, const std::string& file)
Santosh Puranik53b38ed2022-04-10 23:15:22 +0530807{
808 auto present = isPresent(json, file);
809 if (present && !present.value())
810 {
811 executePostFailAction(json, file);
812 return false;
813 }
Alpana Kumari735dee92022-03-25 01:24:40 -0500814
815 if ((json["frus"][file].at(0)).find("preAction") !=
816 json["frus"][file].at(0).end())
817 {
818 if (((json["frus"][file].at(0)["preAction"]).find("pin") !=
819 json["frus"][file].at(0)["preAction"].end()) &&
820 ((json["frus"][file].at(0)["preAction"]).find("value") !=
821 json["frus"][file].at(0)["preAction"].end()))
822 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500823 std::string pinName = json["frus"][file].at(0)["preAction"]["pin"];
Alpana Kumari735dee92022-03-25 01:24:40 -0500824 // Get the value to set
825 Byte pinValue = json["frus"][file].at(0)["preAction"]["value"];
826
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500827 std::cout << "Setting GPIO: " << pinName << " to " << (int)pinValue
828 << std::endl;
Alpana Kumari735dee92022-03-25 01:24:40 -0500829 try
830 {
831 gpiod::line outputLine = gpiod::find_line(pinName);
832
833 if (!outputLine)
834 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500835 std::cerr << "Couldn't find the line for output pin - "
836 << pinName << std::endl;
837 throw std::runtime_error(
Alpana Kumari6bd095f2022-02-23 10:20:20 -0600838 "Couldn't find output line for the GPIO. "
839 "Skipping this GPIO action.");
Alpana Kumari735dee92022-03-25 01:24:40 -0500840 }
841 outputLine.request({"FRU pre-action",
842 ::gpiod::line_request::DIRECTION_OUTPUT, 0},
843 pinValue);
844 }
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500845 catch (const std::exception& e)
Alpana Kumari735dee92022-03-25 01:24:40 -0500846 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500847 std::string i2cBusAddr;
848 std::string errMsg = e.what();
Alpana Kumari6bd095f2022-02-23 10:20:20 -0600849 errMsg += " GPIO : " + pinName;
850
851 if ((json["frus"][file].at(0)["preAction"])
852 .find("gpioI2CAddress") !=
853 json["frus"][file].at(0)["preAction"].end())
854 {
855 i2cBusAddr =
856 json["frus"][file].at(0)["preAction"]["gpioI2CAddress"];
857 }
858
859 logGpioPel(errMsg, i2cBusAddr);
Alpana Kumari40d1c192022-03-09 21:16:02 -0600860
861 // Take failure postAction
862 executePostFailAction(json, file);
863
Alpana Kumari735dee92022-03-25 01:24:40 -0500864 return false;
865 }
866 }
Alpana Kumari40d1c192022-03-09 21:16:02 -0600867 else
868 {
869 // missing required informations
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500870 std::cerr
Alpana Kumari40d1c192022-03-09 21:16:02 -0600871 << "VPD inventory JSON missing basic informations of preAction "
872 "for this FRU : ["
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500873 << file << "]. Executing executePostFailAction." << std::endl;
Alpana Kumari40d1c192022-03-09 21:16:02 -0600874
875 // Take failure postAction
876 executePostFailAction(json, file);
877
878 return false;
879 }
Alpana Kumari735dee92022-03-25 01:24:40 -0500880 }
881 return true;
882}
883
Priyanga Ramasamyaa8a8932022-01-27 09:12:41 -0600884void insertOrMerge(inventory::InterfaceMap& map,
885 const inventory::Interface& interface,
886 inventory::PropertyMap&& property)
887{
888 if (map.find(interface) != map.end())
889 {
890 auto& prop = map.at(interface);
891 prop.insert(property.begin(), property.end());
892 }
893 else
894 {
895 map.emplace(interface, property);
896 }
897}
Santosh Puranikf2d3b532022-04-19 06:44:07 -0500898
899BIOSAttrValueType readBIOSAttribute(const std::string& attrName)
900{
901 std::tuple<std::string, BIOSAttrValueType, BIOSAttrValueType> attrVal;
902 auto bus = sdbusplus::bus::new_default();
903 auto method = bus.new_method_call(
904 "xyz.openbmc_project.BIOSConfigManager",
905 "/xyz/openbmc_project/bios_config/manager",
906 "xyz.openbmc_project.BIOSConfig.Manager", "GetAttribute");
907 method.append(attrName);
908 try
909 {
910 auto result = bus.call(method);
911 result.read(std::get<0>(attrVal), std::get<1>(attrVal),
912 std::get<2>(attrVal));
913 }
914 catch (const sdbusplus::exception::SdBusError& e)
915 {
916 std::cerr << "Failed to read BIOS Attribute: " << attrName << std::endl;
917 std::cerr << e.what() << std::endl;
918 }
919 return std::get<1>(attrVal);
920}
Priyanga Ramasamy335873f2022-05-18 01:31:54 -0500921
922std::string getPowerState()
923{
924 // TODO: How do we handle multiple chassis?
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500925 std::string powerState{};
Priyanga Ramasamy335873f2022-05-18 01:31:54 -0500926 auto bus = sdbusplus::bus::new_default();
927 auto properties =
928 bus.new_method_call("xyz.openbmc_project.State.Chassis",
929 "/xyz/openbmc_project/state/chassis0",
930 "org.freedesktop.DBus.Properties", "Get");
931 properties.append("xyz.openbmc_project.State.Chassis");
932 properties.append("CurrentPowerState");
933 auto result = bus.call(properties);
934 if (!result.is_method_error())
935 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500936 std::variant<std::string> val;
Priyanga Ramasamy335873f2022-05-18 01:31:54 -0500937 result.read(val);
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500938 if (auto pVal = std::get_if<std::string>(&val))
Priyanga Ramasamy335873f2022-05-18 01:31:54 -0500939 {
940 powerState = *pVal;
941 }
942 }
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500943 std::cout << "Power state is: " << powerState << std::endl;
Priyanga Ramasamy335873f2022-05-18 01:31:54 -0500944 return powerState;
945}
Santosh Puranik6b2b5372022-06-02 20:49:02 +0530946
947Binary getVpdDataInVector(const nlohmann::json& js, const std::string& file)
948{
949 uint32_t offset = 0;
950 // check if offset present?
951 for (const auto& item : js["frus"][file])
952 {
953 if (item.find("offset") != item.end())
954 {
955 offset = item["offset"];
956 }
957 }
958
959 // TODO: Figure out a better way to get max possible VPD size.
960 auto maxVPDSize = std::min(std::filesystem::file_size(file),
961 static_cast<uintmax_t>(65504));
962
963 Binary vpdVector;
964 vpdVector.resize(maxVPDSize);
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500965 std::ifstream vpdFile;
966 vpdFile.open(file, std::ios::binary);
Santosh Puranik6b2b5372022-06-02 20:49:02 +0530967
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500968 vpdFile.seekg(offset, std::ios_base::cur);
Santosh Puranik6b2b5372022-06-02 20:49:02 +0530969 vpdFile.read(reinterpret_cast<char*>(&vpdVector[0]), maxVPDSize);
970 vpdVector.resize(vpdFile.gcount());
971
972 // Make sure we reset the EEPROM pointer to a "safe" location if it was DIMM
973 // SPD that we just read.
974 for (const auto& item : js["frus"][file])
975 {
976 if (item.find("extraInterfaces") != item.end())
977 {
978 if (item["extraInterfaces"].find(
979 "xyz.openbmc_project.Inventory.Item.Dimm") !=
980 item["extraInterfaces"].end())
981 {
982 // moves the EEPROM pointer to 2048 'th byte.
983 vpdFile.seekg(2047, std::ios::beg);
984 // Read that byte and discard - to affirm the move
985 // operation.
986 char ch;
987 vpdFile.read(&ch, sizeof(ch));
988 break;
989 }
990 }
991 }
992
993 return vpdVector;
994}
Patrick Venturec83c4dc2018-11-01 16:29:18 -0700995} // namespace vpd
Alpana Kumari735dee92022-03-25 01:24:40 -0500996} // namespace openpower