blob: de255288ca15d4a890b90f6b99621ed26a177961 [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 Srivastavaa2ddc962022-06-29 08:53:16 -0500164 const Severity& sev, const std::string& errIntf, sd_bus* sdBus)
165{
166 // This pointer will be NULL in case the call is made from ibm-read-vpd. In
167 // that case a sync call will do.
168 if (sdBus == nullptr)
169 {
170 createSyncPEL(additionalData, sev, errIntf);
171 }
172 else
173 {
174 std::string errDescription{};
175 auto pos = additionalData.find("DESCRIPTION");
176 if (pos != additionalData.end())
177 {
178 errDescription = pos->second;
179 }
180 else
181 {
182 errDescription = "Description field missing in additional data";
183 }
184
185 std::string pelSeverity =
186 "xyz.openbmc_project.Logging.Entry.Level.Error";
187 auto itr = sevMap.find(sev);
188 if (itr != sevMap.end())
189 {
190 pelSeverity = itr->second;
191 }
192
193 // Implies this is a call from Manager. Hence we need to make an async
194 // call to avoid deadlock with Phosphor-logging.
195 auto rc = sd_bus_call_method_async(
196 sdBus, NULL, loggerService, loggerObjectPath, loggerCreateInterface,
197 "Create", NULL, NULL, "ssa{ss}", errIntf.c_str(),
198 pelSeverity.c_str(), 1, "DESCRIPTION", errDescription.c_str());
199
200 if (rc < 0)
201 {
202 log<level::ERR>("Error calling sd_bus_call_method_async",
203 entry("RC=%d", rc), entry("MSG=%s", strerror(-rc)));
204 }
205 }
206}
207
208void createSyncPEL(const std::map<std::string, std::string>& additionalData,
209 const Severity& sev, const std::string& errIntf)
SunnySrivastava1984a20be8e2020-08-26 02:00:50 -0500210{
211 try
212 {
Sunny Srivastava0746eee2021-03-22 13:36:54 -0500213 std::string pelSeverity =
214 "xyz.openbmc_project.Logging.Entry.Level.Error";
SunnySrivastava1984a20be8e2020-08-26 02:00:50 -0500215 auto bus = sdbusplus::bus::new_default();
SunnySrivastava1984a20be8e2020-08-26 02:00:50 -0500216 auto service = getService(bus, loggerObjectPath, loggerCreateInterface);
217 auto method = bus.new_method_call(service.c_str(), loggerObjectPath,
218 loggerCreateInterface, "Create");
219
Sunny Srivastava0746eee2021-03-22 13:36:54 -0500220 auto itr = sevMap.find(sev);
221 if (itr != sevMap.end())
222 {
223 pelSeverity = itr->second;
224 }
225
226 method.append(errIntf, pelSeverity, additionalData);
SunnySrivastava1984a20be8e2020-08-26 02:00:50 -0500227 auto resp = bus.call(method);
228 }
Patrick Williams2eb01762022-07-22 19:26:56 -0500229 catch (const sdbusplus::exception_t& e)
SunnySrivastava1984a20be8e2020-08-26 02:00:50 -0500230 {
231 throw std::runtime_error(
232 "Error in invoking D-Bus logging create interface to register PEL");
233 }
234}
PriyangaRamasamyc0a534f2020-08-24 21:29:18 +0530235
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500236inventory::VPDfilepath getVpdFilePath(const std::string& jsonFile,
PriyangaRamasamyc0a534f2020-08-24 21:29:18 +0530237 const std::string& ObjPath)
238{
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500239 std::ifstream inventoryJson(jsonFile);
PriyangaRamasamyc0a534f2020-08-24 21:29:18 +0530240 const auto& jsonObject = json::parse(inventoryJson);
241 inventory::VPDfilepath filePath{};
242
243 if (jsonObject.find("frus") == jsonObject.end())
244 {
245 throw(VpdJsonException(
246 "Invalid JSON structure - frus{} object not found in ", jsonFile));
247 }
248
249 const nlohmann::json& groupFRUS =
250 jsonObject["frus"].get_ref<const nlohmann::json::object_t&>();
251 for (const auto& itemFRUS : groupFRUS.items())
252 {
253 const std::vector<nlohmann::json>& groupEEPROM =
254 itemFRUS.value().get_ref<const nlohmann::json::array_t&>();
255 for (const auto& itemEEPROM : groupEEPROM)
256 {
257 if (itemEEPROM["inventoryPath"]
258 .get_ref<const nlohmann::json::string_t&>() == ObjPath)
259 {
260 filePath = itemFRUS.key();
261 return filePath;
262 }
263 }
264 }
265
266 return filePath;
267}
268
269bool isPathInJson(const std::string& eepromPath)
270{
271 bool present = false;
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500272 std::ifstream inventoryJson(INVENTORY_JSON_SYM_LINK);
PriyangaRamasamyc0a534f2020-08-24 21:29:18 +0530273
274 try
275 {
276 auto js = json::parse(inventoryJson);
277 if (js.find("frus") == js.end())
278 {
279 throw(VpdJsonException(
280 "Invalid JSON structure - frus{} object not found in ",
281 INVENTORY_JSON_SYM_LINK));
282 }
283 json fruJson = js["frus"];
284
285 if (fruJson.find(eepromPath) != fruJson.end())
286 {
287 present = true;
288 }
289 }
Patrick Williams8e15b932021-10-06 13:04:22 -0500290 catch (const json::parse_error& ex)
PriyangaRamasamyc0a534f2020-08-24 21:29:18 +0530291 {
292 throw(VpdJsonException("Json Parsing failed", INVENTORY_JSON_SYM_LINK));
293 }
294 return present;
295}
296
297bool isRecKwInDbusJson(const std::string& recordName,
298 const std::string& keyword)
299{
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500300 std::ifstream propertyJson(DBUS_PROP_JSON);
PriyangaRamasamyc0a534f2020-08-24 21:29:18 +0530301 json dbusProperty;
302 bool present = false;
303
304 if (propertyJson.is_open())
305 {
306 try
307 {
308 auto dbusPropertyJson = json::parse(propertyJson);
309 if (dbusPropertyJson.find("dbusProperties") ==
310 dbusPropertyJson.end())
311 {
312 throw(VpdJsonException("dbusProperties{} object not found in "
313 "DbusProperties json : ",
314 DBUS_PROP_JSON));
315 }
316
317 dbusProperty = dbusPropertyJson["dbusProperties"];
318 if (dbusProperty.contains(recordName))
319 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500320 const std::vector<std::string>& kwdsToPublish =
321 dbusProperty[recordName];
PriyangaRamasamyc0a534f2020-08-24 21:29:18 +0530322 if (find(kwdsToPublish.begin(), kwdsToPublish.end(), keyword) !=
323 kwdsToPublish.end()) // present
324 {
325 present = true;
326 }
327 }
328 }
Patrick Williams8e15b932021-10-06 13:04:22 -0500329 catch (const json::parse_error& ex)
PriyangaRamasamyc0a534f2020-08-24 21:29:18 +0530330 {
331 throw(VpdJsonException("Json Parsing failed", DBUS_PROP_JSON));
332 }
333 }
334 else
335 {
336 // If dbus properties json is not available, we assume the given
337 // record-keyword is part of dbus-properties json. So setting the bool
338 // variable to true.
339 present = true;
340 }
341 return present;
342}
343
Sunny Srivastava6c71c9d2021-04-15 04:43:54 -0500344vpdType vpdTypeCheck(const Binary& vpdVector)
345{
346 // Read first 3 Bytes to check the 11S bar code format
347 std::string is11SFormat = "";
348 for (uint8_t i = 0; i < FORMAT_11S_LEN; i++)
349 {
350 is11SFormat += vpdVector[MEMORY_VPD_DATA_START + i];
351 }
352
353 if (vpdVector[IPZ_DATA_START] == KW_VAL_PAIR_START_TAG)
354 {
355 // IPZ VPD FORMAT
356 return vpdType::IPZ_VPD;
357 }
358 else if (vpdVector[KW_VPD_DATA_START] == KW_VPD_START_TAG)
359 {
360 // KEYWORD VPD FORMAT
361 return vpdType::KEYWORD_VPD;
362 }
363 else if (is11SFormat.compare(MEMORY_VPD_START_TAG) == 0)
364 {
365 // Memory VPD format
366 return vpdType::MEMORY_VPD;
367 }
368
369 // INVALID VPD FORMAT
370 return vpdType::INVALID_VPD_FORMAT;
371}
372
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500373const std::string getIM(const Parsed& vpdMap)
Alpana Kumarif05effd2021-04-07 07:32:53 -0500374{
375 Binary imVal;
376 auto property = vpdMap.find("VSBP");
377 if (property != vpdMap.end())
378 {
379 auto kw = (property->second).find("IM");
380 if (kw != (property->second).end())
381 {
382 copy(kw->second.begin(), kw->second.end(), back_inserter(imVal));
383 }
384 }
385
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500386 std::ostringstream oss;
Alpana Kumarif05effd2021-04-07 07:32:53 -0500387 for (auto& i : imVal)
388 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500389 oss << std::setw(2) << std::setfill('0') << std::hex
390 << static_cast<int>(i);
Alpana Kumarif05effd2021-04-07 07:32:53 -0500391 }
392
393 return oss.str();
394}
395
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500396const std::string getHW(const Parsed& vpdMap)
Alpana Kumarif05effd2021-04-07 07:32:53 -0500397{
398 Binary hwVal;
399 auto prop = vpdMap.find("VINI");
400 if (prop != vpdMap.end())
401 {
402 auto kw = (prop->second).find("HW");
403 if (kw != (prop->second).end())
404 {
405 copy(kw->second.begin(), kw->second.end(), back_inserter(hwVal));
406 }
407 }
408
Alpana Kumari88d2ae82021-11-10 03:23:31 -0600409 // The planar pass only comes from the LSB of the HW keyword,
410 // where as the MSB is used for other purposes such as signifying clock
411 // termination.
412 hwVal[0] = 0x00;
413
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500414 std::ostringstream hwString;
Alpana Kumarif05effd2021-04-07 07:32:53 -0500415 for (auto& i : hwVal)
416 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500417 hwString << std::setw(2) << std::setfill('0') << std::hex
418 << static_cast<int>(i);
Alpana Kumarif05effd2021-04-07 07:32:53 -0500419 }
420
421 return hwString.str();
422}
423
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500424std::string getSystemsJson(const Parsed& vpdMap)
Alpana Kumarif05effd2021-04-07 07:32:53 -0500425{
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500426 std::string jsonPath = "/usr/share/vpd/";
427 std::string jsonName{};
Alpana Kumarif05effd2021-04-07 07:32:53 -0500428
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500429 std::ifstream systemJson(SYSTEM_JSON);
Alpana Kumarif05effd2021-04-07 07:32:53 -0500430 if (!systemJson)
431 {
432 throw((VpdJsonException("Failed to access Json path", SYSTEM_JSON)));
433 }
434
435 try
436 {
437 auto js = json::parse(systemJson);
438
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500439 std::string hwKeyword = getHW(vpdMap);
440 const std::string imKeyword = getIM(vpdMap);
Alpana Kumarif05effd2021-04-07 07:32:53 -0500441
Alpana Kumari1b026112022-03-02 23:41:38 -0600442 transform(hwKeyword.begin(), hwKeyword.end(), hwKeyword.begin(),
443 ::toupper);
444
Alpana Kumarif05effd2021-04-07 07:32:53 -0500445 if (js.find("system") == js.end())
446 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500447 throw std::runtime_error("Invalid systems Json");
Alpana Kumarif05effd2021-04-07 07:32:53 -0500448 }
449
450 if (js["system"].find(imKeyword) == js["system"].end())
451 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500452 throw std::runtime_error(
Alpana Kumarif05effd2021-04-07 07:32:53 -0500453 "Invalid system. This system type is not present "
454 "in the systemsJson. IM: " +
455 imKeyword);
456 }
457
458 if ((js["system"][imKeyword].find("constraint") !=
459 js["system"][imKeyword].end()) &&
Alpana Kumari1b026112022-03-02 23:41:38 -0600460 js["system"][imKeyword]["constraint"].find("HW") !=
461 js["system"][imKeyword]["constraint"].end())
Alpana Kumarif05effd2021-04-07 07:32:53 -0500462 {
Alpana Kumari1b026112022-03-02 23:41:38 -0600463 // collect hw versions from json, and check hwKeyword is part of it
464 // if hwKeyword is found there then load respective json
465 // otherwise load default one.
466 for (const auto& hwVersion :
467 js["system"][imKeyword]["constraint"]["HW"])
468 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500469 std::string hw = hwVersion;
Alpana Kumari1b026112022-03-02 23:41:38 -0600470 transform(hw.begin(), hw.end(), hw.begin(), ::toupper);
471
472 if (hw == hwKeyword)
473 {
474 jsonName = js["system"][imKeyword]["constraint"]["json"];
475 break;
476 }
477 }
478
479 if (jsonName.empty() && js["system"][imKeyword].find("default") !=
480 js["system"][imKeyword].end())
481 {
482 jsonName = js["system"][imKeyword]["default"];
483 }
Alpana Kumarif05effd2021-04-07 07:32:53 -0500484 }
485 else if (js["system"][imKeyword].find("default") !=
486 js["system"][imKeyword].end())
487 {
488 jsonName = js["system"][imKeyword]["default"];
489 }
490 else
491 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500492 throw std::runtime_error(
Alpana Kumarif05effd2021-04-07 07:32:53 -0500493 "Bad System json. Neither constraint nor default found");
494 }
495
496 jsonPath += jsonName;
497 }
498
Patrick Williams8e15b932021-10-06 13:04:22 -0500499 catch (const json::parse_error& ex)
Alpana Kumarif05effd2021-04-07 07:32:53 -0500500 {
501 throw(VpdJsonException("Json Parsing failed", SYSTEM_JSON));
502 }
503 return jsonPath;
504}
505
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500506void udevToGenericPath(std::string& file)
PriyangaRamasamy647868e2020-09-08 17:03:19 +0530507{
508 // Sample udevEvent i2c path :
509 // "/sys/devices/platform/ahb/ahb:apb/ahb:apb:bus@1e78a000/1e78a480.i2c-bus/i2c-8/8-0051/8-00510/nvmem"
510 // find if the path contains the word i2c in it.
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500511 if (file.find("i2c") != std::string::npos)
PriyangaRamasamy647868e2020-09-08 17:03:19 +0530512 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500513 std::string i2cBusAddr{};
PriyangaRamasamy647868e2020-09-08 17:03:19 +0530514
515 // Every udev i2c path should have the common pattern
516 // "i2c-bus_number/bus_number-vpd_address". Search for
517 // "bus_number-vpd_address".
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500518 std::regex i2cPattern("((i2c)-[0-9]+\\/)([0-9]+-[0-9]{4})");
519 std::smatch match;
520 if (std::regex_search(file, match, i2cPattern))
PriyangaRamasamy647868e2020-09-08 17:03:19 +0530521 {
522 i2cBusAddr = match.str(3);
523 }
524 else
525 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500526 std::cerr << "The given udev path < " << file
527 << " > doesn't match the required pattern. Skipping VPD "
528 "collection."
529 << std::endl;
PriyangaRamasamy647868e2020-09-08 17:03:19 +0530530 exit(EXIT_SUCCESS);
531 }
532 // Forming the generic file path
533 file = i2cPathPrefix + i2cBusAddr + "/eeprom";
534 }
535 // Sample udevEvent spi path :
536 // "/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"
537 // find if the path contains the word spi in it.
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500538 else if (file.find("spi") != std::string::npos)
PriyangaRamasamy647868e2020-09-08 17:03:19 +0530539 {
540 // Every udev spi path will have common pattern "spi<Digit>/", which
541 // describes the spi bus number at which the fru is connected; Followed
542 // by a slash following the vpd address of the fru. Taking the above
543 // input as a common key, we try to search for the pattern "spi<Digit>/"
544 // using regular expression.
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500545 std::regex spiPattern("((spi)[0-9]+)(\\/)");
546 std::string spiBus{};
547 std::smatch match;
548 if (std::regex_search(file, match, spiPattern))
PriyangaRamasamy647868e2020-09-08 17:03:19 +0530549 {
550 spiBus = match.str(1);
551 }
552 else
553 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500554 std::cerr << "The given udev path < " << file
555 << " > doesn't match the required pattern. Skipping VPD "
556 "collection."
557 << std::endl;
PriyangaRamasamy647868e2020-09-08 17:03:19 +0530558 exit(EXIT_SUCCESS);
559 }
560 // Forming the generic path
561 file = spiPathPrefix + spiBus + ".0/eeprom";
562 }
563 else
564 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500565 std::cerr << "\n The given EEPROM path < " << file
566 << " > is not valid. It's neither I2C nor "
567 "SPI path. Skipping VPD collection.."
568 << std::endl;
PriyangaRamasamy647868e2020-09-08 17:03:19 +0530569 exit(EXIT_SUCCESS);
570 }
571}
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500572std::string getBadVpdName(const std::string& file)
PriyangaRamasamyc2fe40f2021-03-02 06:27:33 -0600573{
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500574 std::string badVpd = BAD_VPD_DIR;
575 if (file.find("i2c") != std::string::npos)
PriyangaRamasamyc2fe40f2021-03-02 06:27:33 -0600576 {
577 badVpd += "i2c-";
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500578 std::regex i2cPattern("(at24/)([0-9]+-[0-9]+)\\/");
579 std::smatch match;
580 if (std::regex_search(file, match, i2cPattern))
PriyangaRamasamyc2fe40f2021-03-02 06:27:33 -0600581 {
582 badVpd += match.str(2);
583 }
584 }
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500585 else if (file.find("spi") != std::string::npos)
PriyangaRamasamyc2fe40f2021-03-02 06:27:33 -0600586 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500587 std::regex spiPattern("((spi)[0-9]+)(.0)");
588 std::smatch match;
589 if (std::regex_search(file, match, spiPattern))
PriyangaRamasamyc2fe40f2021-03-02 06:27:33 -0600590 {
591 badVpd += match.str(1);
592 }
593 }
594 return badVpd;
595}
596
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500597void dumpBadVpd(const std::string& file, const Binary& vpdVector)
PriyangaRamasamyc2fe40f2021-03-02 06:27:33 -0600598{
599 fs::path badVpdDir = BAD_VPD_DIR;
600 fs::create_directory(badVpdDir);
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500601 std::string badVpdPath = getBadVpdName(file);
PriyangaRamasamyc2fe40f2021-03-02 06:27:33 -0600602 if (fs::exists(badVpdPath))
603 {
604 std::error_code ec;
605 fs::remove(badVpdPath, ec);
606 if (ec) // error code
607 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500608 std::string error = "Error removing the existing broken vpd in ";
PriyangaRamasamyc2fe40f2021-03-02 06:27:33 -0600609 error += badVpdPath;
610 error += ". Error code : ";
611 error += ec.value();
612 error += ". Error message : ";
613 error += ec.message();
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500614 throw std::runtime_error(error);
PriyangaRamasamyc2fe40f2021-03-02 06:27:33 -0600615 }
616 }
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500617 std::ofstream badVpdFileStream(badVpdPath, std::ofstream::binary);
PriyangaRamasamyc2fe40f2021-03-02 06:27:33 -0600618 if (!badVpdFileStream)
619 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500620 throw std::runtime_error(
621 "Failed to open bad vpd file path in /tmp/bad-vpd. "
622 "Unable to dump the broken/bad vpd file.");
PriyangaRamasamyc2fe40f2021-03-02 06:27:33 -0600623 }
624 badVpdFileStream.write(reinterpret_cast<const char*>(vpdVector.data()),
625 vpdVector.size());
626}
alpana077ce68722021-07-25 13:23:59 -0500627
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500628const std::string getKwVal(const Parsed& vpdMap, const std::string& rec,
629 const std::string& kwd)
alpana077ce68722021-07-25 13:23:59 -0500630{
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500631 std::string kwVal{};
alpana077ce68722021-07-25 13:23:59 -0500632
633 auto findRec = vpdMap.find(rec);
634
635 // check if record is found in map we got by parser
636 if (findRec != vpdMap.end())
637 {
638 auto findKwd = findRec->second.find(kwd);
639
640 if (findKwd != findRec->second.end())
641 {
642 kwVal = findKwd->second;
643 }
644 }
645
646 return kwVal;
647}
648
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500649std::string byteArrayToHexString(const Binary& vec)
Priyanga Ramasamyc9ecf8e2021-10-08 02:28:52 -0500650{
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500651 std::stringstream ss;
652 std::string hexRep = "0x";
Priyanga Ramasamyc9ecf8e2021-10-08 02:28:52 -0500653 ss << hexRep;
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500654 std::string str = ss.str();
Priyanga Ramasamyc9ecf8e2021-10-08 02:28:52 -0500655
656 // convert Decimal to Hex string
657 for (auto& v : vec)
658 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500659 ss << std::setfill('0') << std::setw(2) << std::hex << (int)v;
Priyanga Ramasamyc9ecf8e2021-10-08 02:28:52 -0500660 str = ss.str();
661 }
662 return str;
663}
664
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500665std::string getPrintableValue(const Binary& vec)
Priyanga Ramasamy02434932021-10-07 16:26:05 -0500666{
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500667 std::string str{};
Priyanga Ramasamy02434932021-10-07 16:26:05 -0500668
Priyanga Ramasamyc9ecf8e2021-10-08 02:28:52 -0500669 // find for a non printable value in the vector
670 const auto it = std::find_if(vec.begin(), vec.end(),
671 [](const auto& ele) { return !isprint(ele); });
Priyanga Ramasamy02434932021-10-07 16:26:05 -0500672
Priyanga Ramasamyc9ecf8e2021-10-08 02:28:52 -0500673 if (it != vec.end()) // if the given vector has any non printable value
674 {
675 for (auto itr = it; itr != vec.end(); itr++)
Priyanga Ramasamy02434932021-10-07 16:26:05 -0500676 {
Priyanga Ramasamyc9ecf8e2021-10-08 02:28:52 -0500677 if (*itr != 0x00)
678 {
679 str = byteArrayToHexString(vec);
680 return str;
681 }
Priyanga Ramasamy02434932021-10-07 16:26:05 -0500682 }
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500683 str = std::string(vec.begin(), it);
Priyanga Ramasamy02434932021-10-07 16:26:05 -0500684 }
685 else
686 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500687 str = std::string(vec.begin(), vec.end());
Priyanga Ramasamy02434932021-10-07 16:26:05 -0500688 }
689 return str;
690}
691
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500692void executePostFailAction(const nlohmann::json& json, const std::string& file)
Alpana Kumari735dee92022-03-25 01:24:40 -0500693{
694 if ((json["frus"][file].at(0)).find("postActionFail") ==
695 json["frus"][file].at(0).end())
696 {
697 return;
698 }
699
700 uint8_t pinValue = 0;
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500701 std::string pinName;
Alpana Kumari735dee92022-03-25 01:24:40 -0500702
703 for (const auto& postAction :
704 (json["frus"][file].at(0))["postActionFail"].items())
705 {
706 if (postAction.key() == "pin")
707 {
708 pinName = postAction.value();
709 }
710 else if (postAction.key() == "value")
711 {
712 // Get the value to set
713 pinValue = postAction.value();
714 }
715 }
716
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500717 std::cout << "Setting GPIO: " << pinName << " to " << (int)pinValue
718 << std::endl;
Alpana Kumari735dee92022-03-25 01:24:40 -0500719
720 try
721 {
722 gpiod::line outputLine = gpiod::find_line(pinName);
723
724 if (!outputLine)
725 {
Sunny Srivastavaa2ddc962022-06-29 08:53:16 -0500726 throw GpioException(
Alpana Kumari6bd095f2022-02-23 10:20:20 -0600727 "Couldn't find output line for the GPIO. Skipping "
728 "this GPIO action.");
Alpana Kumari735dee92022-03-25 01:24:40 -0500729 }
730 outputLine.request(
731 {"Disable line", ::gpiod::line_request::DIRECTION_OUTPUT, 0},
732 pinValue);
733 }
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500734 catch (const std::exception& e)
Alpana Kumari735dee92022-03-25 01:24:40 -0500735 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500736 std::string i2cBusAddr;
737 std::string errMsg = e.what();
Alpana Kumari6bd095f2022-02-23 10:20:20 -0600738 errMsg += "\nGPIO: " + pinName;
739
740 if ((json["frus"][file].at(0)["postActionFail"].find(
741 "gpioI2CAddress")) !=
742 json["frus"][file].at(0)["postActionFail"].end())
743 {
744 i2cBusAddr =
745 json["frus"][file].at(0)["postActionFail"]["gpioI2CAddress"];
Sunny Srivastavafdf9ff22022-06-15 11:15:54 -0500746 errMsg += " i2cBusAddress: " + i2cBusAddr;
Alpana Kumari6bd095f2022-02-23 10:20:20 -0600747 }
748
Sunny Srivastavaa2ddc962022-06-29 08:53:16 -0500749 throw GpioException(e.what());
Alpana Kumari735dee92022-03-25 01:24:40 -0500750 }
Alpana Kumari6bd095f2022-02-23 10:20:20 -0600751
752 return;
Alpana Kumari735dee92022-03-25 01:24:40 -0500753}
754
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500755std::optional<bool> isPresent(const nlohmann::json& json,
756 const std::string& file)
Santosh Puranik53b38ed2022-04-10 23:15:22 +0530757
Alpana Kumari735dee92022-03-25 01:24:40 -0500758{
759 if ((json["frus"][file].at(0)).find("presence") !=
760 json["frus"][file].at(0).end())
761 {
762 if (((json["frus"][file].at(0)["presence"]).find("pin") !=
763 json["frus"][file].at(0)["presence"].end()) &&
764 ((json["frus"][file].at(0)["presence"]).find("value") !=
765 json["frus"][file].at(0)["presence"].end()))
766 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500767 std::string presPinName =
768 json["frus"][file].at(0)["presence"]["pin"];
Alpana Kumari735dee92022-03-25 01:24:40 -0500769 Byte presPinValue = json["frus"][file].at(0)["presence"]["value"];
770
771 try
772 {
773 gpiod::line presenceLine = gpiod::find_line(presPinName);
774
775 if (!presenceLine)
776 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500777 std::cerr << "Couldn't find the presence line for - "
778 << presPinName << std::endl;
Alpana Kumari40d1c192022-03-09 21:16:02 -0600779
Sunny Srivastavaa2ddc962022-06-29 08:53:16 -0500780 throw GpioException(
Alpana Kumari6bd095f2022-02-23 10:20:20 -0600781 "Couldn't find the presence line for the "
782 "GPIO. Skipping this GPIO action.");
Alpana Kumari735dee92022-03-25 01:24:40 -0500783 }
784
785 presenceLine.request({"Read the presence line",
786 gpiod::line_request::DIRECTION_INPUT, 0});
787
788 Byte gpioData = presenceLine.get_value();
789
Santosh Puranik53b38ed2022-04-10 23:15:22 +0530790 return (gpioData == presPinValue);
Alpana Kumari735dee92022-03-25 01:24:40 -0500791 }
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500792 catch (const std::exception& e)
Alpana Kumari735dee92022-03-25 01:24:40 -0500793 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500794 std::string i2cBusAddr;
795 std::string errMsg = e.what();
Alpana Kumari6bd095f2022-02-23 10:20:20 -0600796 errMsg += " GPIO : " + presPinName;
797
798 if ((json["frus"][file].at(0)["presence"])
799 .find("gpioI2CAddress") !=
800 json["frus"][file].at(0)["presence"].end())
801 {
802 i2cBusAddr =
803 json["frus"][file].at(0)["presence"]["gpioI2CAddress"];
Sunny Srivastavafdf9ff22022-06-15 11:15:54 -0500804 errMsg += " i2cBusAddress: " + i2cBusAddr;
Alpana Kumari6bd095f2022-02-23 10:20:20 -0600805 }
806
Alpana Kumari40d1c192022-03-09 21:16:02 -0600807 // Take failure postAction
808 executePostFailAction(json, file);
Sunny Srivastavaa2ddc962022-06-29 08:53:16 -0500809 throw GpioException(errMsg);
Alpana Kumari735dee92022-03-25 01:24:40 -0500810 }
811 }
Alpana Kumari40d1c192022-03-09 21:16:02 -0600812 else
813 {
814 // missing required informations
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500815 std::cerr
816 << "VPD inventory JSON missing basic informations of presence "
817 "for this FRU : ["
818 << file << "]. Executing executePostFailAction." << std::endl;
Alpana Kumari40d1c192022-03-09 21:16:02 -0600819
820 // Take failure postAction
821 executePostFailAction(json, file);
822
823 return false;
824 }
Alpana Kumari735dee92022-03-25 01:24:40 -0500825 }
Santosh Puranik53b38ed2022-04-10 23:15:22 +0530826 return std::optional<bool>{};
827}
828
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500829bool executePreAction(const nlohmann::json& json, const std::string& file)
Santosh Puranik53b38ed2022-04-10 23:15:22 +0530830{
831 auto present = isPresent(json, file);
832 if (present && !present.value())
833 {
834 executePostFailAction(json, file);
835 return false;
836 }
Alpana Kumari735dee92022-03-25 01:24:40 -0500837
838 if ((json["frus"][file].at(0)).find("preAction") !=
839 json["frus"][file].at(0).end())
840 {
841 if (((json["frus"][file].at(0)["preAction"]).find("pin") !=
842 json["frus"][file].at(0)["preAction"].end()) &&
843 ((json["frus"][file].at(0)["preAction"]).find("value") !=
844 json["frus"][file].at(0)["preAction"].end()))
845 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500846 std::string pinName = json["frus"][file].at(0)["preAction"]["pin"];
Alpana Kumari735dee92022-03-25 01:24:40 -0500847 // Get the value to set
848 Byte pinValue = json["frus"][file].at(0)["preAction"]["value"];
849
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500850 std::cout << "Setting GPIO: " << pinName << " to " << (int)pinValue
851 << std::endl;
Alpana Kumari735dee92022-03-25 01:24:40 -0500852 try
853 {
854 gpiod::line outputLine = gpiod::find_line(pinName);
855
856 if (!outputLine)
857 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500858 std::cerr << "Couldn't find the line for output pin - "
859 << pinName << std::endl;
Sunny Srivastavaa2ddc962022-06-29 08:53:16 -0500860 throw GpioException(
Alpana Kumari6bd095f2022-02-23 10:20:20 -0600861 "Couldn't find output line for the GPIO. "
862 "Skipping this GPIO action.");
Alpana Kumari735dee92022-03-25 01:24:40 -0500863 }
864 outputLine.request({"FRU pre-action",
865 ::gpiod::line_request::DIRECTION_OUTPUT, 0},
866 pinValue);
867 }
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500868 catch (const std::exception& e)
Alpana Kumari735dee92022-03-25 01:24:40 -0500869 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500870 std::string i2cBusAddr;
871 std::string errMsg = e.what();
Alpana Kumari6bd095f2022-02-23 10:20:20 -0600872 errMsg += " GPIO : " + pinName;
873
874 if ((json["frus"][file].at(0)["preAction"])
875 .find("gpioI2CAddress") !=
876 json["frus"][file].at(0)["preAction"].end())
877 {
878 i2cBusAddr =
879 json["frus"][file].at(0)["preAction"]["gpioI2CAddress"];
Sunny Srivastavafdf9ff22022-06-15 11:15:54 -0500880 errMsg += " i2cBusAddress: " + i2cBusAddr;
Alpana Kumari6bd095f2022-02-23 10:20:20 -0600881 }
882
Alpana Kumari40d1c192022-03-09 21:16:02 -0600883 // Take failure postAction
884 executePostFailAction(json, file);
Sunny Srivastavaa2ddc962022-06-29 08:53:16 -0500885 throw GpioException(errMsg);
Alpana Kumari735dee92022-03-25 01:24:40 -0500886 }
887 }
Alpana Kumari40d1c192022-03-09 21:16:02 -0600888 else
889 {
890 // missing required informations
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500891 std::cerr
Alpana Kumari40d1c192022-03-09 21:16:02 -0600892 << "VPD inventory JSON missing basic informations of preAction "
893 "for this FRU : ["
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500894 << file << "]. Executing executePostFailAction." << std::endl;
Alpana Kumari40d1c192022-03-09 21:16:02 -0600895
896 // Take failure postAction
897 executePostFailAction(json, file);
Alpana Kumari40d1c192022-03-09 21:16:02 -0600898 return false;
899 }
Alpana Kumari735dee92022-03-25 01:24:40 -0500900 }
901 return true;
902}
903
Priyanga Ramasamyaa8a8932022-01-27 09:12:41 -0600904void insertOrMerge(inventory::InterfaceMap& map,
905 const inventory::Interface& interface,
906 inventory::PropertyMap&& property)
907{
908 if (map.find(interface) != map.end())
909 {
910 auto& prop = map.at(interface);
911 prop.insert(property.begin(), property.end());
912 }
913 else
914 {
915 map.emplace(interface, property);
916 }
917}
Santosh Puranikf2d3b532022-04-19 06:44:07 -0500918
919BIOSAttrValueType readBIOSAttribute(const std::string& attrName)
920{
921 std::tuple<std::string, BIOSAttrValueType, BIOSAttrValueType> attrVal;
922 auto bus = sdbusplus::bus::new_default();
923 auto method = bus.new_method_call(
924 "xyz.openbmc_project.BIOSConfigManager",
925 "/xyz/openbmc_project/bios_config/manager",
926 "xyz.openbmc_project.BIOSConfig.Manager", "GetAttribute");
927 method.append(attrName);
928 try
929 {
930 auto result = bus.call(method);
931 result.read(std::get<0>(attrVal), std::get<1>(attrVal),
932 std::get<2>(attrVal));
933 }
934 catch (const sdbusplus::exception::SdBusError& e)
935 {
936 std::cerr << "Failed to read BIOS Attribute: " << attrName << std::endl;
937 std::cerr << e.what() << std::endl;
938 }
939 return std::get<1>(attrVal);
940}
Priyanga Ramasamy335873f2022-05-18 01:31:54 -0500941
942std::string getPowerState()
943{
944 // TODO: How do we handle multiple chassis?
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500945 std::string powerState{};
Priyanga Ramasamy335873f2022-05-18 01:31:54 -0500946 auto bus = sdbusplus::bus::new_default();
947 auto properties =
948 bus.new_method_call("xyz.openbmc_project.State.Chassis",
949 "/xyz/openbmc_project/state/chassis0",
950 "org.freedesktop.DBus.Properties", "Get");
951 properties.append("xyz.openbmc_project.State.Chassis");
952 properties.append("CurrentPowerState");
953 auto result = bus.call(properties);
954 if (!result.is_method_error())
955 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500956 std::variant<std::string> val;
Priyanga Ramasamy335873f2022-05-18 01:31:54 -0500957 result.read(val);
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500958 if (auto pVal = std::get_if<std::string>(&val))
Priyanga Ramasamy335873f2022-05-18 01:31:54 -0500959 {
960 powerState = *pVal;
961 }
962 }
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500963 std::cout << "Power state is: " << powerState << std::endl;
Priyanga Ramasamy335873f2022-05-18 01:31:54 -0500964 return powerState;
965}
Santosh Puranik6b2b5372022-06-02 20:49:02 +0530966
967Binary getVpdDataInVector(const nlohmann::json& js, const std::string& file)
968{
969 uint32_t offset = 0;
970 // check if offset present?
971 for (const auto& item : js["frus"][file])
972 {
973 if (item.find("offset") != item.end())
974 {
975 offset = item["offset"];
976 }
977 }
978
979 // TODO: Figure out a better way to get max possible VPD size.
980 auto maxVPDSize = std::min(std::filesystem::file_size(file),
981 static_cast<uintmax_t>(65504));
982
983 Binary vpdVector;
984 vpdVector.resize(maxVPDSize);
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500985 std::ifstream vpdFile;
986 vpdFile.open(file, std::ios::binary);
Santosh Puranik6b2b5372022-06-02 20:49:02 +0530987
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500988 vpdFile.seekg(offset, std::ios_base::cur);
Santosh Puranik6b2b5372022-06-02 20:49:02 +0530989 vpdFile.read(reinterpret_cast<char*>(&vpdVector[0]), maxVPDSize);
990 vpdVector.resize(vpdFile.gcount());
991
992 // Make sure we reset the EEPROM pointer to a "safe" location if it was DIMM
993 // SPD that we just read.
994 for (const auto& item : js["frus"][file])
995 {
996 if (item.find("extraInterfaces") != item.end())
997 {
998 if (item["extraInterfaces"].find(
999 "xyz.openbmc_project.Inventory.Item.Dimm") !=
1000 item["extraInterfaces"].end())
1001 {
1002 // moves the EEPROM pointer to 2048 'th byte.
1003 vpdFile.seekg(2047, std::ios::beg);
1004 // Read that byte and discard - to affirm the move
1005 // operation.
1006 char ch;
1007 vpdFile.read(&ch, sizeof(ch));
1008 break;
1009 }
1010 }
1011 }
1012
1013 return vpdVector;
1014}
Patrick Venturec83c4dc2018-11-01 16:29:18 -07001015} // namespace vpd
Alpana Kumari735dee92022-03-25 01:24:40 -05001016} // namespace openpower