blob: f0395a9f263f63e43d8645bb4488d2d6494539aa [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"
Jinu Joy Thomase2b03832023-08-22 19:51:31 +05306#include "const.hpp"
SunnySrivastava1984d076da82020-03-05 05:33:35 -06007#include "defines.hpp"
PriyangaRamasamyc0a534f2020-08-24 21:29:18 +05308#include "vpd_exceptions.hpp"
SunnySrivastava1984d076da82020-03-05 05:33:35 -06009
Alpana Kumari6bd095f2022-02-23 10:20:20 -060010#include <boost/algorithm/string.hpp>
Alpana Kumari735dee92022-03-25 01:24:40 -050011#include <gpiod.hpp>
Sunny Srivastava6c71c9d2021-04-15 04:43:54 -050012#include <nlohmann/json.hpp>
SunnySrivastava19849094d4f2020-08-05 09:32:29 -050013#include <phosphor-logging/elog-errors.hpp>
Patrick Venturec83c4dc2018-11-01 16:29:18 -070014#include <phosphor-logging/log.hpp>
15#include <sdbusplus/server.hpp>
Patrick Williamsc78d8872023-05-10 07:50:56 -050016#include <xyz/openbmc_project/Common/error.hpp>
17
18#include <filesystem>
19#include <fstream>
20#include <iomanip>
21#include <regex>
PriyangaRamasamyc0a534f2020-08-24 21:29:18 +053022#include <sstream>
23#include <vector>
Deepak Kodihalli76794492017-02-16 23:48:18 -060024
PriyangaRamasamyc0a534f2020-08-24 21:29:18 +053025using json = nlohmann::json;
26
Deepak Kodihalli76794492017-02-16 23:48:18 -060027namespace openpower
28{
29namespace vpd
30{
SunnySrivastava1984945a02d2020-05-06 01:55:41 -050031using namespace openpower::vpd::constants;
SunnySrivastava1984a20be8e2020-08-26 02:00:50 -050032using namespace inventory;
33using namespace phosphor::logging;
SunnySrivastava19849094d4f2020-08-05 09:32:29 -050034using namespace sdbusplus::xyz::openbmc_project::Common::Error;
PriyangaRamasamyc0a534f2020-08-24 21:29:18 +053035using namespace record;
36using namespace openpower::vpd::exceptions;
Sunny Srivastava6c71c9d2021-04-15 04:43:54 -050037using namespace common::utility;
Sunny Srivastava0746eee2021-03-22 13:36:54 -050038using Severity = openpower::vpd::constants::PelSeverity;
PriyangaRamasamyc2fe40f2021-03-02 06:27:33 -060039namespace fs = std::filesystem;
Sunny Srivastava0746eee2021-03-22 13:36:54 -050040
41// mapping of severity enum to severity interface
42static std::unordered_map<Severity, std::string> sevMap = {
43 {Severity::INFORMATIONAL,
44 "xyz.openbmc_project.Logging.Entry.Level.Informational"},
45 {Severity::DEBUG, "xyz.openbmc_project.Logging.Entry.Level.Debug"},
46 {Severity::NOTICE, "xyz.openbmc_project.Logging.Entry.Level.Notice"},
47 {Severity::WARNING, "xyz.openbmc_project.Logging.Entry.Level.Warning"},
48 {Severity::CRITICAL, "xyz.openbmc_project.Logging.Entry.Level.Critical"},
49 {Severity::EMERGENCY, "xyz.openbmc_project.Logging.Entry.Level.Emergency"},
50 {Severity::ERROR, "xyz.openbmc_project.Logging.Entry.Level.Error"},
51 {Severity::ALERT, "xyz.openbmc_project.Logging.Entry.Level.Alert"}};
52
Deepak Kodihalli76794492017-02-16 23:48:18 -060053namespace inventory
54{
55
SunnySrivastava19849094d4f2020-08-05 09:32:29 -050056MapperResponse
57 getObjectSubtreeForInterfaces(const std::string& root, const int32_t depth,
58 const std::vector<std::string>& interfaces)
59{
60 auto bus = sdbusplus::bus::new_default();
61 auto mapperCall = bus.new_method_call(mapperDestination, mapperObjectPath,
62 mapperInterface, "GetSubTree");
63 mapperCall.append(root);
64 mapperCall.append(depth);
65 mapperCall.append(interfaces);
66
67 MapperResponse result = {};
68
69 try
70 {
71 auto response = bus.call(mapperCall);
72
73 response.read(result);
74 }
Patrick Williams2eb01762022-07-22 19:26:56 -050075 catch (const sdbusplus::exception_t& e)
SunnySrivastava19849094d4f2020-08-05 09:32:29 -050076 {
77 log<level::ERR>("Error in mapper GetSubTree",
78 entry("ERROR=%s", e.what()));
79 }
80
81 return result;
82}
83
Deepak Kodihalli76794492017-02-16 23:48:18 -060084} // namespace inventory
85
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -060086LE2ByteData readUInt16LE(Binary::const_iterator iterator)
87{
88 LE2ByteData lowByte = *iterator;
89 LE2ByteData highByte = *(iterator + 1);
90 lowByte |= (highByte << 8);
91 return lowByte;
92}
93
SunnySrivastava1984d076da82020-03-05 05:33:35 -060094/** @brief Encodes a keyword for D-Bus.
95 */
Priyanga Ramasamye0084322022-09-27 06:28:33 -050096std::string encodeKeyword(const std::string& kw, const std::string& encoding)
SunnySrivastava1984d076da82020-03-05 05:33:35 -060097{
98 if (encoding == "MAC")
99 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500100 std::string res{};
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600101 size_t first = kw[0];
102 res += toHex(first >> 4);
103 res += toHex(first & 0x0f);
104 for (size_t i = 1; i < kw.size(); ++i)
105 {
106 res += ":";
107 res += toHex(kw[i] >> 4);
108 res += toHex(kw[i] & 0x0f);
109 }
110 return res;
111 }
112 else if (encoding == "DATE")
113 {
114 // Date, represent as
115 // <year>-<month>-<day> <hour>:<min>
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500116 std::string res{};
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600117 static constexpr uint8_t skipPrefix = 3;
118
119 auto strItr = kw.begin();
120 advance(strItr, skipPrefix);
121 for_each(strItr, kw.end(), [&res](size_t c) { res += c; });
122
123 res.insert(BD_YEAR_END, 1, '-');
124 res.insert(BD_MONTH_END, 1, '-');
125 res.insert(BD_DAY_END, 1, ' ');
126 res.insert(BD_HOUR_END, 1, ':');
127
128 return res;
129 }
130 else // default to string encoding
131 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500132 return std::string(kw.begin(), kw.end());
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600133 }
134}
SunnySrivastava198443306542020-04-01 02:50:20 -0500135
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500136std::string readBusProperty(const std::string& obj, const std::string& inf,
137 const std::string& prop)
SunnySrivastava198443306542020-04-01 02:50:20 -0500138{
139 std::string propVal{};
140 std::string object = INVENTORY_PATH + obj;
141 auto bus = sdbusplus::bus::new_default();
142 auto properties = bus.new_method_call(
143 "xyz.openbmc_project.Inventory.Manager", object.c_str(),
144 "org.freedesktop.DBus.Properties", "Get");
145 properties.append(inf);
146 properties.append(prop);
147 auto result = bus.call(properties);
148 if (!result.is_method_error())
149 {
Sunny Srivastava28abd6e2021-07-28 02:58:28 -0500150 inventory::Value val;
SunnySrivastava198443306542020-04-01 02:50:20 -0500151 result.read(val);
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500152 if (auto pVal = std::get_if<Binary>(&val))
SunnySrivastava198443306542020-04-01 02:50:20 -0500153 {
154 propVal.assign(reinterpret_cast<const char*>(pVal->data()),
155 pVal->size());
156 }
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500157 else if (auto pVal = std::get_if<std::string>(&val))
SunnySrivastava1984bca5aaa2020-04-21 05:31:04 -0500158 {
159 propVal.assign(pVal->data(), pVal->size());
160 }
Sunny Srivastava28abd6e2021-07-28 02:58:28 -0500161 else if (auto pVal = get_if<bool>(&val))
162 {
163 if (*pVal == false)
164 {
165 propVal = "false";
166 }
167 else
168 {
169 propVal = "true";
170 }
171 }
SunnySrivastava198443306542020-04-01 02:50:20 -0500172 }
173 return propVal;
174}
SunnySrivastava1984a20be8e2020-08-26 02:00:50 -0500175
176void createPEL(const std::map<std::string, std::string>& additionalData,
Sunny Srivastavaa2ddc962022-06-29 08:53:16 -0500177 const Severity& sev, const std::string& errIntf, sd_bus* sdBus)
178{
179 // This pointer will be NULL in case the call is made from ibm-read-vpd. In
180 // that case a sync call will do.
181 if (sdBus == nullptr)
182 {
183 createSyncPEL(additionalData, sev, errIntf);
184 }
185 else
186 {
187 std::string errDescription{};
188 auto pos = additionalData.find("DESCRIPTION");
189 if (pos != additionalData.end())
190 {
191 errDescription = pos->second;
192 }
193 else
194 {
195 errDescription = "Description field missing in additional data";
196 }
197
198 std::string pelSeverity =
199 "xyz.openbmc_project.Logging.Entry.Level.Error";
200 auto itr = sevMap.find(sev);
201 if (itr != sevMap.end())
202 {
203 pelSeverity = itr->second;
204 }
205
206 // Implies this is a call from Manager. Hence we need to make an async
207 // call to avoid deadlock with Phosphor-logging.
208 auto rc = sd_bus_call_method_async(
209 sdBus, NULL, loggerService, loggerObjectPath, loggerCreateInterface,
210 "Create", NULL, NULL, "ssa{ss}", errIntf.c_str(),
211 pelSeverity.c_str(), 1, "DESCRIPTION", errDescription.c_str());
212
213 if (rc < 0)
214 {
215 log<level::ERR>("Error calling sd_bus_call_method_async",
216 entry("RC=%d", rc), entry("MSG=%s", strerror(-rc)));
217 }
218 }
219}
220
221void createSyncPEL(const std::map<std::string, std::string>& additionalData,
222 const Severity& sev, const std::string& errIntf)
SunnySrivastava1984a20be8e2020-08-26 02:00:50 -0500223{
224 try
225 {
Sunny Srivastava0746eee2021-03-22 13:36:54 -0500226 std::string pelSeverity =
227 "xyz.openbmc_project.Logging.Entry.Level.Error";
SunnySrivastava1984a20be8e2020-08-26 02:00:50 -0500228 auto bus = sdbusplus::bus::new_default();
SunnySrivastava1984a20be8e2020-08-26 02:00:50 -0500229 auto service = getService(bus, loggerObjectPath, loggerCreateInterface);
230 auto method = bus.new_method_call(service.c_str(), loggerObjectPath,
231 loggerCreateInterface, "Create");
232
Sunny Srivastava0746eee2021-03-22 13:36:54 -0500233 auto itr = sevMap.find(sev);
234 if (itr != sevMap.end())
235 {
236 pelSeverity = itr->second;
237 }
238
239 method.append(errIntf, pelSeverity, additionalData);
SunnySrivastava1984a20be8e2020-08-26 02:00:50 -0500240 auto resp = bus.call(method);
241 }
Patrick Williams2eb01762022-07-22 19:26:56 -0500242 catch (const sdbusplus::exception_t& e)
SunnySrivastava1984a20be8e2020-08-26 02:00:50 -0500243 {
Sunny Srivastava5ef6ccc2022-05-30 01:35:13 -0500244 std::cerr << "Dbus call to phosphor-logging Create failed. Reason:"
245 << e.what();
SunnySrivastava1984a20be8e2020-08-26 02:00:50 -0500246 }
247}
PriyangaRamasamyc0a534f2020-08-24 21:29:18 +0530248
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500249inventory::VPDfilepath getVpdFilePath(const std::string& jsonFile,
PriyangaRamasamyc0a534f2020-08-24 21:29:18 +0530250 const std::string& ObjPath)
251{
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500252 std::ifstream inventoryJson(jsonFile);
PriyangaRamasamyc0a534f2020-08-24 21:29:18 +0530253 const auto& jsonObject = json::parse(inventoryJson);
254 inventory::VPDfilepath filePath{};
255
256 if (jsonObject.find("frus") == jsonObject.end())
257 {
258 throw(VpdJsonException(
259 "Invalid JSON structure - frus{} object not found in ", jsonFile));
260 }
261
262 const nlohmann::json& groupFRUS =
263 jsonObject["frus"].get_ref<const nlohmann::json::object_t&>();
264 for (const auto& itemFRUS : groupFRUS.items())
265 {
266 const std::vector<nlohmann::json>& groupEEPROM =
267 itemFRUS.value().get_ref<const nlohmann::json::array_t&>();
268 for (const auto& itemEEPROM : groupEEPROM)
269 {
270 if (itemEEPROM["inventoryPath"]
271 .get_ref<const nlohmann::json::string_t&>() == ObjPath)
272 {
273 filePath = itemFRUS.key();
274 return filePath;
275 }
276 }
277 }
278
279 return filePath;
280}
281
282bool isPathInJson(const std::string& eepromPath)
283{
284 bool present = false;
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500285 std::ifstream inventoryJson(INVENTORY_JSON_SYM_LINK);
PriyangaRamasamyc0a534f2020-08-24 21:29:18 +0530286
287 try
288 {
289 auto js = json::parse(inventoryJson);
290 if (js.find("frus") == js.end())
291 {
292 throw(VpdJsonException(
293 "Invalid JSON structure - frus{} object not found in ",
294 INVENTORY_JSON_SYM_LINK));
295 }
296 json fruJson = js["frus"];
297
298 if (fruJson.find(eepromPath) != fruJson.end())
299 {
300 present = true;
301 }
302 }
Patrick Williams8e15b932021-10-06 13:04:22 -0500303 catch (const json::parse_error& ex)
PriyangaRamasamyc0a534f2020-08-24 21:29:18 +0530304 {
305 throw(VpdJsonException("Json Parsing failed", INVENTORY_JSON_SYM_LINK));
306 }
307 return present;
308}
309
310bool isRecKwInDbusJson(const std::string& recordName,
311 const std::string& keyword)
312{
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500313 std::ifstream propertyJson(DBUS_PROP_JSON);
PriyangaRamasamyc0a534f2020-08-24 21:29:18 +0530314 json dbusProperty;
315 bool present = false;
316
317 if (propertyJson.is_open())
318 {
319 try
320 {
321 auto dbusPropertyJson = json::parse(propertyJson);
322 if (dbusPropertyJson.find("dbusProperties") ==
323 dbusPropertyJson.end())
324 {
325 throw(VpdJsonException("dbusProperties{} object not found in "
326 "DbusProperties json : ",
327 DBUS_PROP_JSON));
328 }
329
330 dbusProperty = dbusPropertyJson["dbusProperties"];
331 if (dbusProperty.contains(recordName))
332 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500333 const std::vector<std::string>& kwdsToPublish =
334 dbusProperty[recordName];
PriyangaRamasamyc0a534f2020-08-24 21:29:18 +0530335 if (find(kwdsToPublish.begin(), kwdsToPublish.end(), keyword) !=
336 kwdsToPublish.end()) // present
337 {
338 present = true;
339 }
340 }
341 }
Patrick Williams8e15b932021-10-06 13:04:22 -0500342 catch (const json::parse_error& ex)
PriyangaRamasamyc0a534f2020-08-24 21:29:18 +0530343 {
344 throw(VpdJsonException("Json Parsing failed", DBUS_PROP_JSON));
345 }
346 }
347 else
348 {
349 // If dbus properties json is not available, we assume the given
350 // record-keyword is part of dbus-properties json. So setting the bool
351 // variable to true.
352 present = true;
353 }
354 return present;
355}
356
Sunny Srivastava6c71c9d2021-04-15 04:43:54 -0500357vpdType vpdTypeCheck(const Binary& vpdVector)
358{
359 // Read first 3 Bytes to check the 11S bar code format
360 std::string is11SFormat = "";
361 for (uint8_t i = 0; i < FORMAT_11S_LEN; i++)
362 {
363 is11SFormat += vpdVector[MEMORY_VPD_DATA_START + i];
364 }
365
366 if (vpdVector[IPZ_DATA_START] == KW_VAL_PAIR_START_TAG)
367 {
368 // IPZ VPD FORMAT
369 return vpdType::IPZ_VPD;
370 }
371 else if (vpdVector[KW_VPD_DATA_START] == KW_VPD_START_TAG)
372 {
373 // KEYWORD VPD FORMAT
374 return vpdType::KEYWORD_VPD;
375 }
jinuthomas6555e7e2023-02-14 21:48:00 -0600376 else if (((vpdVector[SPD_BYTE_3] & SPD_BYTE_BIT_0_3_MASK) ==
377 SPD_MODULE_TYPE_DDIMM) &&
jinuthomas0abbb9c2023-05-05 01:37:07 -0500378 (is11SFormat.compare(MEMORY_VPD_START_TAG) == 0))
Sunny Srivastava6c71c9d2021-04-15 04:43:54 -0500379 {
jinuthomas6555e7e2023-02-14 21:48:00 -0600380 // DDIMM Memory VPD format
381 if ((vpdVector[SPD_BYTE_2] & SPD_BYTE_MASK) == SPD_DRAM_TYPE_DDR5)
382 {
383 return vpdType::DDR5_DDIMM_MEMORY_VPD;
384 }
385 else if ((vpdVector[SPD_BYTE_2] & SPD_BYTE_MASK) == SPD_DRAM_TYPE_DDR4)
386 {
387 return vpdType::DDR4_DDIMM_MEMORY_VPD;
388 }
389 }
390 else if ((vpdVector[SPD_BYTE_2] & SPD_BYTE_MASK) == SPD_DRAM_TYPE_DDR5)
391 {
392 // ISDIMM Memory VPD format
393 return vpdType::DDR5_ISDIMM_MEMORY_VPD;
394 }
395 else if ((vpdVector[SPD_BYTE_2] & SPD_BYTE_MASK) == SPD_DRAM_TYPE_DDR4)
396 {
397 // ISDIMM Memory VPD format
398 return vpdType::DDR4_ISDIMM_MEMORY_VPD;
Sunny Srivastava6c71c9d2021-04-15 04:43:54 -0500399 }
400
401 // INVALID VPD FORMAT
402 return vpdType::INVALID_VPD_FORMAT;
403}
404
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500405const std::string getIM(const Parsed& vpdMap)
Alpana Kumarif05effd2021-04-07 07:32:53 -0500406{
407 Binary imVal;
408 auto property = vpdMap.find("VSBP");
409 if (property != vpdMap.end())
410 {
411 auto kw = (property->second).find("IM");
412 if (kw != (property->second).end())
413 {
414 copy(kw->second.begin(), kw->second.end(), back_inserter(imVal));
415 }
416 }
417
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500418 std::ostringstream oss;
Alpana Kumarif05effd2021-04-07 07:32:53 -0500419 for (auto& i : imVal)
420 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500421 oss << std::setw(2) << std::setfill('0') << std::hex
422 << static_cast<int>(i);
Alpana Kumarif05effd2021-04-07 07:32:53 -0500423 }
424
425 return oss.str();
426}
427
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500428const std::string getHW(const Parsed& vpdMap)
Alpana Kumarif05effd2021-04-07 07:32:53 -0500429{
430 Binary hwVal;
431 auto prop = vpdMap.find("VINI");
432 if (prop != vpdMap.end())
433 {
434 auto kw = (prop->second).find("HW");
435 if (kw != (prop->second).end())
436 {
437 copy(kw->second.begin(), kw->second.end(), back_inserter(hwVal));
438 }
439 }
440
Alpana Kumari88d2ae82021-11-10 03:23:31 -0600441 // The planar pass only comes from the LSB of the HW keyword,
442 // where as the MSB is used for other purposes such as signifying clock
443 // termination.
444 hwVal[0] = 0x00;
445
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500446 std::ostringstream hwString;
Alpana Kumarif05effd2021-04-07 07:32:53 -0500447 for (auto& i : hwVal)
448 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500449 hwString << std::setw(2) << std::setfill('0') << std::hex
450 << static_cast<int>(i);
Alpana Kumarif05effd2021-04-07 07:32:53 -0500451 }
452
453 return hwString.str();
454}
455
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500456std::string getSystemsJson(const Parsed& vpdMap)
Alpana Kumarif05effd2021-04-07 07:32:53 -0500457{
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500458 std::string jsonPath = "/usr/share/vpd/";
459 std::string jsonName{};
Alpana Kumarif05effd2021-04-07 07:32:53 -0500460
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500461 std::ifstream systemJson(SYSTEM_JSON);
Alpana Kumarif05effd2021-04-07 07:32:53 -0500462 if (!systemJson)
463 {
464 throw((VpdJsonException("Failed to access Json path", SYSTEM_JSON)));
465 }
466
467 try
468 {
469 auto js = json::parse(systemJson);
470
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500471 std::string hwKeyword = getHW(vpdMap);
472 const std::string imKeyword = getIM(vpdMap);
Alpana Kumarif05effd2021-04-07 07:32:53 -0500473
Alpana Kumari1b026112022-03-02 23:41:38 -0600474 transform(hwKeyword.begin(), hwKeyword.end(), hwKeyword.begin(),
475 ::toupper);
476
Alpana Kumarif05effd2021-04-07 07:32:53 -0500477 if (js.find("system") == js.end())
478 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500479 throw std::runtime_error("Invalid systems Json");
Alpana Kumarif05effd2021-04-07 07:32:53 -0500480 }
481
482 if (js["system"].find(imKeyword) == js["system"].end())
483 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500484 throw std::runtime_error(
Alpana Kumarif05effd2021-04-07 07:32:53 -0500485 "Invalid system. This system type is not present "
486 "in the systemsJson. IM: " +
487 imKeyword);
488 }
489
490 if ((js["system"][imKeyword].find("constraint") !=
491 js["system"][imKeyword].end()) &&
Alpana Kumari1b026112022-03-02 23:41:38 -0600492 js["system"][imKeyword]["constraint"].find("HW") !=
493 js["system"][imKeyword]["constraint"].end())
Alpana Kumarif05effd2021-04-07 07:32:53 -0500494 {
Alpana Kumari1b026112022-03-02 23:41:38 -0600495 // collect hw versions from json, and check hwKeyword is part of it
496 // if hwKeyword is found there then load respective json
497 // otherwise load default one.
498 for (const auto& hwVersion :
499 js["system"][imKeyword]["constraint"]["HW"])
500 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500501 std::string hw = hwVersion;
Alpana Kumari1b026112022-03-02 23:41:38 -0600502 transform(hw.begin(), hw.end(), hw.begin(), ::toupper);
503
504 if (hw == hwKeyword)
505 {
506 jsonName = js["system"][imKeyword]["constraint"]["json"];
507 break;
508 }
509 }
510
511 if (jsonName.empty() && js["system"][imKeyword].find("default") !=
512 js["system"][imKeyword].end())
513 {
514 jsonName = js["system"][imKeyword]["default"];
515 }
Alpana Kumarif05effd2021-04-07 07:32:53 -0500516 }
517 else if (js["system"][imKeyword].find("default") !=
518 js["system"][imKeyword].end())
519 {
520 jsonName = js["system"][imKeyword]["default"];
521 }
522 else
523 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500524 throw std::runtime_error(
Alpana Kumarif05effd2021-04-07 07:32:53 -0500525 "Bad System json. Neither constraint nor default found");
526 }
527
528 jsonPath += jsonName;
529 }
530
Patrick Williams8e15b932021-10-06 13:04:22 -0500531 catch (const json::parse_error& ex)
Alpana Kumarif05effd2021-04-07 07:32:53 -0500532 {
533 throw(VpdJsonException("Json Parsing failed", SYSTEM_JSON));
534 }
535 return jsonPath;
536}
537
jinuthomasf457a3e2023-04-13 12:22:48 -0500538void udevToGenericPath(std::string& file, const std::string& driver)
PriyangaRamasamy647868e2020-09-08 17:03:19 +0530539{
540 // Sample udevEvent i2c path :
541 // "/sys/devices/platform/ahb/ahb:apb/ahb:apb:bus@1e78a000/1e78a480.i2c-bus/i2c-8/8-0051/8-00510/nvmem"
542 // find if the path contains the word i2c in it.
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500543 if (file.find("i2c") != std::string::npos)
PriyangaRamasamy647868e2020-09-08 17:03:19 +0530544 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500545 std::string i2cBusAddr{};
PriyangaRamasamy647868e2020-09-08 17:03:19 +0530546
547 // Every udev i2c path should have the common pattern
548 // "i2c-bus_number/bus_number-vpd_address". Search for
549 // "bus_number-vpd_address".
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500550 std::regex i2cPattern("((i2c)-[0-9]+\\/)([0-9]+-[0-9]{4})");
551 std::smatch match;
552 if (std::regex_search(file, match, i2cPattern))
PriyangaRamasamy647868e2020-09-08 17:03:19 +0530553 {
554 i2cBusAddr = match.str(3);
555 }
556 else
557 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500558 std::cerr << "The given udev path < " << file
559 << " > doesn't match the required pattern. Skipping VPD "
560 "collection."
561 << std::endl;
PriyangaRamasamy647868e2020-09-08 17:03:19 +0530562 exit(EXIT_SUCCESS);
563 }
564 // Forming the generic file path
jinuthomasf457a3e2023-04-13 12:22:48 -0500565 file = i2cPathPrefix + driver + "/" + i2cBusAddr + "/eeprom";
PriyangaRamasamy647868e2020-09-08 17:03:19 +0530566 }
567 // Sample udevEvent spi path :
568 // "/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"
569 // find if the path contains the word spi in it.
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500570 else if (file.find("spi") != std::string::npos)
PriyangaRamasamy647868e2020-09-08 17:03:19 +0530571 {
572 // Every udev spi path will have common pattern "spi<Digit>/", which
573 // describes the spi bus number at which the fru is connected; Followed
574 // by a slash following the vpd address of the fru. Taking the above
575 // input as a common key, we try to search for the pattern "spi<Digit>/"
576 // using regular expression.
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500577 std::regex spiPattern("((spi)[0-9]+)(\\/)");
578 std::string spiBus{};
579 std::smatch match;
580 if (std::regex_search(file, match, spiPattern))
PriyangaRamasamy647868e2020-09-08 17:03:19 +0530581 {
582 spiBus = match.str(1);
583 }
584 else
585 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500586 std::cerr << "The given udev path < " << file
587 << " > doesn't match the required pattern. Skipping VPD "
588 "collection."
589 << std::endl;
PriyangaRamasamy647868e2020-09-08 17:03:19 +0530590 exit(EXIT_SUCCESS);
591 }
592 // Forming the generic path
jinuthomasf457a3e2023-04-13 12:22:48 -0500593 file = spiPathPrefix + driver + "/" + spiBus + ".0/eeprom";
PriyangaRamasamy647868e2020-09-08 17:03:19 +0530594 }
595 else
596 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500597 std::cerr << "\n The given EEPROM path < " << file
598 << " > is not valid. It's neither I2C nor "
599 "SPI path. Skipping VPD collection.."
600 << std::endl;
PriyangaRamasamy647868e2020-09-08 17:03:19 +0530601 exit(EXIT_SUCCESS);
602 }
603}
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500604std::string getBadVpdName(const std::string& file)
PriyangaRamasamyc2fe40f2021-03-02 06:27:33 -0600605{
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500606 std::string badVpd = BAD_VPD_DIR;
607 if (file.find("i2c") != std::string::npos)
PriyangaRamasamyc2fe40f2021-03-02 06:27:33 -0600608 {
609 badVpd += "i2c-";
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500610 std::regex i2cPattern("(at24/)([0-9]+-[0-9]+)\\/");
611 std::smatch match;
612 if (std::regex_search(file, match, i2cPattern))
PriyangaRamasamyc2fe40f2021-03-02 06:27:33 -0600613 {
614 badVpd += match.str(2);
615 }
616 }
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500617 else if (file.find("spi") != std::string::npos)
PriyangaRamasamyc2fe40f2021-03-02 06:27:33 -0600618 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500619 std::regex spiPattern("((spi)[0-9]+)(.0)");
620 std::smatch match;
621 if (std::regex_search(file, match, spiPattern))
PriyangaRamasamyc2fe40f2021-03-02 06:27:33 -0600622 {
623 badVpd += match.str(1);
624 }
625 }
626 return badVpd;
627}
628
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500629void dumpBadVpd(const std::string& file, const Binary& vpdVector)
PriyangaRamasamyc2fe40f2021-03-02 06:27:33 -0600630{
631 fs::path badVpdDir = BAD_VPD_DIR;
632 fs::create_directory(badVpdDir);
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500633 std::string badVpdPath = getBadVpdName(file);
PriyangaRamasamyc2fe40f2021-03-02 06:27:33 -0600634 if (fs::exists(badVpdPath))
635 {
636 std::error_code ec;
637 fs::remove(badVpdPath, ec);
638 if (ec) // error code
639 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500640 std::string error = "Error removing the existing broken vpd in ";
PriyangaRamasamyc2fe40f2021-03-02 06:27:33 -0600641 error += badVpdPath;
642 error += ". Error code : ";
643 error += ec.value();
644 error += ". Error message : ";
645 error += ec.message();
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500646 throw std::runtime_error(error);
PriyangaRamasamyc2fe40f2021-03-02 06:27:33 -0600647 }
648 }
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500649 std::ofstream badVpdFileStream(badVpdPath, std::ofstream::binary);
PriyangaRamasamyc2fe40f2021-03-02 06:27:33 -0600650 if (!badVpdFileStream)
651 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500652 throw std::runtime_error(
653 "Failed to open bad vpd file path in /tmp/bad-vpd. "
654 "Unable to dump the broken/bad vpd file.");
PriyangaRamasamyc2fe40f2021-03-02 06:27:33 -0600655 }
656 badVpdFileStream.write(reinterpret_cast<const char*>(vpdVector.data()),
657 vpdVector.size());
658}
alpana077ce68722021-07-25 13:23:59 -0500659
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500660const std::string getKwVal(const Parsed& vpdMap, const std::string& rec,
661 const std::string& kwd)
alpana077ce68722021-07-25 13:23:59 -0500662{
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500663 std::string kwVal{};
alpana077ce68722021-07-25 13:23:59 -0500664
665 auto findRec = vpdMap.find(rec);
666
667 // check if record is found in map we got by parser
668 if (findRec != vpdMap.end())
669 {
670 auto findKwd = findRec->second.find(kwd);
671
672 if (findKwd != findRec->second.end())
673 {
674 kwVal = findKwd->second;
675 }
Sunny Srivastava37992a62023-07-11 05:18:41 -0500676 else
677 {
678 std::cout << "Keyword not found" << std::endl;
679 }
680 }
681 else
682 {
683 std::cerr << "Record not found" << std::endl;
alpana077ce68722021-07-25 13:23:59 -0500684 }
685
686 return kwVal;
687}
688
GiridhariKrishnan63639102023-03-02 05:55:47 -0600689std::string hexString(const std::variant<Binary, std::string>& kw)
Priyanga Ramasamyc9ecf8e2021-10-08 02:28:52 -0500690{
GiridhariKrishnan63639102023-03-02 05:55:47 -0600691 std::string hexString;
692 std::visit(
693 [&hexString](auto&& kw) {
Patrick Williamsc78d8872023-05-10 07:50:56 -0500694 std::stringstream ss;
695 std::string hexRep = "0x";
696 ss << hexRep;
697 for (auto& kwVal : kw)
698 {
699 ss << std::setfill('0') << std::setw(2) << std::hex
700 << static_cast<int>(kwVal);
701 }
702 hexString = ss.str();
Patrick Williamsb7b352a2023-10-20 11:19:19 -0500703 },
GiridhariKrishnan63639102023-03-02 05:55:47 -0600704 kw);
705 return hexString;
Priyanga Ramasamyc9ecf8e2021-10-08 02:28:52 -0500706}
707
GiridhariKrishnan63639102023-03-02 05:55:47 -0600708std::string getPrintableValue(const std::variant<Binary, std::string>& kwVal)
Priyanga Ramasamy02434932021-10-07 16:26:05 -0500709{
GiridhariKrishnan63639102023-03-02 05:55:47 -0600710 std::string kwString{};
711 std::visit(
712 [&kwString](auto&& kwVal) {
Patrick Williamsc78d8872023-05-10 07:50:56 -0500713 const auto it =
714 std::find_if(kwVal.begin(), kwVal.end(),
715 [](const auto& kw) { return !isprint(kw); });
716 if (it != kwVal.end())
717 {
girik390fccb2023-05-02 07:42:47 -0500718 kwString = hexString(kwVal);
Patrick Williamsc78d8872023-05-10 07:50:56 -0500719 }
720 else
721 {
722 kwString = std::string(kwVal.begin(), kwVal.end());
723 }
Patrick Williamsb7b352a2023-10-20 11:19:19 -0500724 },
GiridhariKrishnan63639102023-03-02 05:55:47 -0600725 kwVal);
726 return kwString;
Priyanga Ramasamy02434932021-10-07 16:26:05 -0500727}
728
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500729void executePostFailAction(const nlohmann::json& json, const std::string& file)
Alpana Kumari735dee92022-03-25 01:24:40 -0500730{
731 if ((json["frus"][file].at(0)).find("postActionFail") ==
732 json["frus"][file].at(0).end())
733 {
734 return;
735 }
736
737 uint8_t pinValue = 0;
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500738 std::string pinName;
Alpana Kumari735dee92022-03-25 01:24:40 -0500739
740 for (const auto& postAction :
741 (json["frus"][file].at(0))["postActionFail"].items())
742 {
743 if (postAction.key() == "pin")
744 {
745 pinName = postAction.value();
746 }
747 else if (postAction.key() == "value")
748 {
749 // Get the value to set
750 pinValue = postAction.value();
751 }
752 }
753
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500754 std::cout << "Setting GPIO: " << pinName << " to " << (int)pinValue
755 << std::endl;
Alpana Kumari735dee92022-03-25 01:24:40 -0500756
757 try
758 {
759 gpiod::line outputLine = gpiod::find_line(pinName);
760
761 if (!outputLine)
762 {
Sunny Srivastavaa2ddc962022-06-29 08:53:16 -0500763 throw GpioException(
Alpana Kumari6bd095f2022-02-23 10:20:20 -0600764 "Couldn't find output line for the GPIO. Skipping "
765 "this GPIO action.");
Alpana Kumari735dee92022-03-25 01:24:40 -0500766 }
767 outputLine.request(
768 {"Disable line", ::gpiod::line_request::DIRECTION_OUTPUT, 0},
769 pinValue);
770 }
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500771 catch (const std::exception& e)
Alpana Kumari735dee92022-03-25 01:24:40 -0500772 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500773 std::string i2cBusAddr;
774 std::string errMsg = e.what();
Alpana Kumari6bd095f2022-02-23 10:20:20 -0600775 errMsg += "\nGPIO: " + pinName;
776
777 if ((json["frus"][file].at(0)["postActionFail"].find(
778 "gpioI2CAddress")) !=
779 json["frus"][file].at(0)["postActionFail"].end())
780 {
781 i2cBusAddr =
782 json["frus"][file].at(0)["postActionFail"]["gpioI2CAddress"];
Sunny Srivastavafdf9ff22022-06-15 11:15:54 -0500783 errMsg += " i2cBusAddress: " + i2cBusAddr;
Alpana Kumari6bd095f2022-02-23 10:20:20 -0600784 }
785
Sunny Srivastavaa2ddc962022-06-29 08:53:16 -0500786 throw GpioException(e.what());
Alpana Kumari735dee92022-03-25 01:24:40 -0500787 }
Alpana Kumari6bd095f2022-02-23 10:20:20 -0600788
789 return;
Alpana Kumari735dee92022-03-25 01:24:40 -0500790}
791
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500792std::optional<bool> isPresent(const nlohmann::json& json,
793 const std::string& file)
Santosh Puranik53b38ed2022-04-10 23:15:22 +0530794
Alpana Kumari735dee92022-03-25 01:24:40 -0500795{
796 if ((json["frus"][file].at(0)).find("presence") !=
797 json["frus"][file].at(0).end())
798 {
799 if (((json["frus"][file].at(0)["presence"]).find("pin") !=
800 json["frus"][file].at(0)["presence"].end()) &&
801 ((json["frus"][file].at(0)["presence"]).find("value") !=
802 json["frus"][file].at(0)["presence"].end()))
803 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500804 std::string presPinName =
805 json["frus"][file].at(0)["presence"]["pin"];
Alpana Kumari735dee92022-03-25 01:24:40 -0500806 Byte presPinValue = json["frus"][file].at(0)["presence"]["value"];
807
808 try
809 {
810 gpiod::line presenceLine = gpiod::find_line(presPinName);
811
812 if (!presenceLine)
813 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500814 std::cerr << "Couldn't find the presence line for - "
815 << presPinName << std::endl;
Alpana Kumari40d1c192022-03-09 21:16:02 -0600816
Sunny Srivastavaa2ddc962022-06-29 08:53:16 -0500817 throw GpioException(
Alpana Kumari6bd095f2022-02-23 10:20:20 -0600818 "Couldn't find the presence line for the "
819 "GPIO. Skipping this GPIO action.");
Alpana Kumari735dee92022-03-25 01:24:40 -0500820 }
821
822 presenceLine.request({"Read the presence line",
823 gpiod::line_request::DIRECTION_INPUT, 0});
824
825 Byte gpioData = presenceLine.get_value();
826
Santosh Puranik53b38ed2022-04-10 23:15:22 +0530827 return (gpioData == presPinValue);
Alpana Kumari735dee92022-03-25 01:24:40 -0500828 }
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500829 catch (const std::exception& e)
Alpana Kumari735dee92022-03-25 01:24:40 -0500830 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500831 std::string i2cBusAddr;
832 std::string errMsg = e.what();
Alpana Kumari6bd095f2022-02-23 10:20:20 -0600833 errMsg += " GPIO : " + presPinName;
834
835 if ((json["frus"][file].at(0)["presence"])
836 .find("gpioI2CAddress") !=
837 json["frus"][file].at(0)["presence"].end())
838 {
839 i2cBusAddr =
840 json["frus"][file].at(0)["presence"]["gpioI2CAddress"];
Sunny Srivastavafdf9ff22022-06-15 11:15:54 -0500841 errMsg += " i2cBusAddress: " + i2cBusAddr;
Alpana Kumari6bd095f2022-02-23 10:20:20 -0600842 }
843
Alpana Kumari40d1c192022-03-09 21:16:02 -0600844 // Take failure postAction
845 executePostFailAction(json, file);
Sunny Srivastavaa2ddc962022-06-29 08:53:16 -0500846 throw GpioException(errMsg);
Alpana Kumari735dee92022-03-25 01:24:40 -0500847 }
848 }
Alpana Kumari40d1c192022-03-09 21:16:02 -0600849 else
850 {
851 // missing required informations
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500852 std::cerr
853 << "VPD inventory JSON missing basic informations of presence "
854 "for this FRU : ["
855 << file << "]. Executing executePostFailAction." << std::endl;
Alpana Kumari40d1c192022-03-09 21:16:02 -0600856
857 // Take failure postAction
858 executePostFailAction(json, file);
859
860 return false;
861 }
Alpana Kumari735dee92022-03-25 01:24:40 -0500862 }
Santosh Puranik53b38ed2022-04-10 23:15:22 +0530863 return std::optional<bool>{};
864}
865
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500866bool executePreAction(const nlohmann::json& json, const std::string& file)
Santosh Puranik53b38ed2022-04-10 23:15:22 +0530867{
868 auto present = isPresent(json, file);
869 if (present && !present.value())
870 {
871 executePostFailAction(json, file);
872 return false;
873 }
Alpana Kumari735dee92022-03-25 01:24:40 -0500874
875 if ((json["frus"][file].at(0)).find("preAction") !=
876 json["frus"][file].at(0).end())
877 {
878 if (((json["frus"][file].at(0)["preAction"]).find("pin") !=
879 json["frus"][file].at(0)["preAction"].end()) &&
880 ((json["frus"][file].at(0)["preAction"]).find("value") !=
881 json["frus"][file].at(0)["preAction"].end()))
882 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500883 std::string pinName = json["frus"][file].at(0)["preAction"]["pin"];
Alpana Kumari735dee92022-03-25 01:24:40 -0500884 // Get the value to set
885 Byte pinValue = json["frus"][file].at(0)["preAction"]["value"];
886
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500887 std::cout << "Setting GPIO: " << pinName << " to " << (int)pinValue
888 << std::endl;
Alpana Kumari735dee92022-03-25 01:24:40 -0500889 try
890 {
891 gpiod::line outputLine = gpiod::find_line(pinName);
892
893 if (!outputLine)
894 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500895 std::cerr << "Couldn't find the line for output pin - "
896 << pinName << std::endl;
Sunny Srivastavaa2ddc962022-06-29 08:53:16 -0500897 throw GpioException(
Alpana Kumari6bd095f2022-02-23 10:20:20 -0600898 "Couldn't find output line for the GPIO. "
899 "Skipping this GPIO action.");
Alpana Kumari735dee92022-03-25 01:24:40 -0500900 }
901 outputLine.request({"FRU pre-action",
902 ::gpiod::line_request::DIRECTION_OUTPUT, 0},
903 pinValue);
904 }
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500905 catch (const std::exception& e)
Alpana Kumari735dee92022-03-25 01:24:40 -0500906 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500907 std::string i2cBusAddr;
908 std::string errMsg = e.what();
Alpana Kumari6bd095f2022-02-23 10:20:20 -0600909 errMsg += " GPIO : " + pinName;
910
911 if ((json["frus"][file].at(0)["preAction"])
912 .find("gpioI2CAddress") !=
913 json["frus"][file].at(0)["preAction"].end())
914 {
915 i2cBusAddr =
916 json["frus"][file].at(0)["preAction"]["gpioI2CAddress"];
Sunny Srivastavafdf9ff22022-06-15 11:15:54 -0500917 errMsg += " i2cBusAddress: " + i2cBusAddr;
Alpana Kumari6bd095f2022-02-23 10:20:20 -0600918 }
919
Alpana Kumari40d1c192022-03-09 21:16:02 -0600920 // Take failure postAction
921 executePostFailAction(json, file);
Sunny Srivastavaa2ddc962022-06-29 08:53:16 -0500922 throw GpioException(errMsg);
Alpana Kumari735dee92022-03-25 01:24:40 -0500923 }
924 }
Alpana Kumari40d1c192022-03-09 21:16:02 -0600925 else
926 {
927 // missing required informations
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500928 std::cerr
Alpana Kumari40d1c192022-03-09 21:16:02 -0600929 << "VPD inventory JSON missing basic informations of preAction "
930 "for this FRU : ["
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500931 << file << "]. Executing executePostFailAction." << std::endl;
Alpana Kumari40d1c192022-03-09 21:16:02 -0600932
933 // Take failure postAction
934 executePostFailAction(json, file);
Alpana Kumari40d1c192022-03-09 21:16:02 -0600935 return false;
936 }
Alpana Kumari735dee92022-03-25 01:24:40 -0500937 }
938 return true;
939}
940
Priyanga Ramasamyaa8a8932022-01-27 09:12:41 -0600941void insertOrMerge(inventory::InterfaceMap& map,
942 const inventory::Interface& interface,
943 inventory::PropertyMap&& property)
944{
945 if (map.find(interface) != map.end())
946 {
947 auto& prop = map.at(interface);
948 prop.insert(property.begin(), property.end());
949 }
950 else
951 {
952 map.emplace(interface, property);
953 }
954}
Santosh Puranikf2d3b532022-04-19 06:44:07 -0500955
956BIOSAttrValueType readBIOSAttribute(const std::string& attrName)
957{
958 std::tuple<std::string, BIOSAttrValueType, BIOSAttrValueType> attrVal;
959 auto bus = sdbusplus::bus::new_default();
960 auto method = bus.new_method_call(
961 "xyz.openbmc_project.BIOSConfigManager",
962 "/xyz/openbmc_project/bios_config/manager",
963 "xyz.openbmc_project.BIOSConfig.Manager", "GetAttribute");
964 method.append(attrName);
965 try
966 {
967 auto result = bus.call(method);
968 result.read(std::get<0>(attrVal), std::get<1>(attrVal),
969 std::get<2>(attrVal));
970 }
971 catch (const sdbusplus::exception::SdBusError& e)
972 {
973 std::cerr << "Failed to read BIOS Attribute: " << attrName << std::endl;
974 std::cerr << e.what() << std::endl;
975 }
976 return std::get<1>(attrVal);
977}
Priyanga Ramasamy335873f2022-05-18 01:31:54 -0500978
979std::string getPowerState()
980{
981 // TODO: How do we handle multiple chassis?
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500982 std::string powerState{};
Priyanga Ramasamy335873f2022-05-18 01:31:54 -0500983 auto bus = sdbusplus::bus::new_default();
Patrick Williamsc78d8872023-05-10 07:50:56 -0500984 auto properties = bus.new_method_call("xyz.openbmc_project.State.Chassis",
985 "/xyz/openbmc_project/state/chassis0",
986 "org.freedesktop.DBus.Properties",
987 "Get");
Priyanga Ramasamy335873f2022-05-18 01:31:54 -0500988 properties.append("xyz.openbmc_project.State.Chassis");
989 properties.append("CurrentPowerState");
990 auto result = bus.call(properties);
991 if (!result.is_method_error())
992 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500993 std::variant<std::string> val;
Priyanga Ramasamy335873f2022-05-18 01:31:54 -0500994 result.read(val);
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500995 if (auto pVal = std::get_if<std::string>(&val))
Priyanga Ramasamy335873f2022-05-18 01:31:54 -0500996 {
997 powerState = *pVal;
998 }
999 }
Priyanga Ramasamye0084322022-09-27 06:28:33 -05001000 std::cout << "Power state is: " << powerState << std::endl;
Priyanga Ramasamy335873f2022-05-18 01:31:54 -05001001 return powerState;
1002}
Santosh Puranik6b2b5372022-06-02 20:49:02 +05301003
1004Binary getVpdDataInVector(const nlohmann::json& js, const std::string& file)
1005{
1006 uint32_t offset = 0;
1007 // check if offset present?
1008 for (const auto& item : js["frus"][file])
1009 {
1010 if (item.find("offset") != item.end())
1011 {
1012 offset = item["offset"];
1013 }
1014 }
1015
1016 // TODO: Figure out a better way to get max possible VPD size.
1017 auto maxVPDSize = std::min(std::filesystem::file_size(file),
1018 static_cast<uintmax_t>(65504));
1019
1020 Binary vpdVector;
1021 vpdVector.resize(maxVPDSize);
Priyanga Ramasamye0084322022-09-27 06:28:33 -05001022 std::ifstream vpdFile;
jinuthomas45d54972023-07-03 04:36:29 -05001023 vpdFile.exceptions(std::ifstream::badbit | std::ifstream::failbit);
1024 try
1025 {
Jinu Joy Thomase2b03832023-08-22 19:51:31 +05301026 vpdFile.open(file, std::ios::binary | std::ios::in);
jinuthomas45d54972023-07-03 04:36:29 -05001027 vpdFile.seekg(offset, std::ios_base::cur);
1028 vpdFile.read(reinterpret_cast<char*>(&vpdVector[0]), maxVPDSize);
1029 vpdVector.resize(vpdFile.gcount());
1030 }
1031 catch (const std::ifstream::failure& fail)
1032 {
1033 std::cerr << "Exception in file handling [" << file
1034 << "] error : " << fail.what();
1035 std::cerr << "EEPROM file size =" << std::filesystem::file_size(file)
1036 << std::endl;
1037 std::cerr << "Stream file size = " << vpdFile.gcount() << std::endl;
1038 std::cerr << " Vector size" << vpdVector.size() << std::endl;
1039 throw;
1040 }
Santosh Puranik6b2b5372022-06-02 20:49:02 +05301041
Jinu Joy Thomase2b03832023-08-22 19:51:31 +05301042 // Make sure we reset the EEPROM pointer to a "safe" location if it was
1043 // a DDIMM SPD that we just read.
Santosh Puranik6b2b5372022-06-02 20:49:02 +05301044 for (const auto& item : js["frus"][file])
1045 {
1046 if (item.find("extraInterfaces") != item.end())
1047 {
1048 if (item["extraInterfaces"].find(
1049 "xyz.openbmc_project.Inventory.Item.Dimm") !=
1050 item["extraInterfaces"].end())
1051 {
Jinu Joy Thomase2b03832023-08-22 19:51:31 +05301052 // check added here for DDIMM only workarround
1053 vpdType dimmType = vpdTypeCheck(vpdVector);
1054 if (dimmType == constants::DDR4_DDIMM_MEMORY_VPD ||
1055 dimmType == constants::DDR5_DDIMM_MEMORY_VPD)
jinuthomas45d54972023-07-03 04:36:29 -05001056 {
Jinu Joy Thomase2b03832023-08-22 19:51:31 +05301057 try
1058 {
1059 // moves the EEPROM pointer to 2048 'th byte.
1060 vpdFile.seekg(2047, std::ios::beg);
1061 // Read that byte and discard - to affirm the move
1062 // operation.
1063 char ch;
1064 vpdFile.read(&ch, sizeof(ch));
1065 }
1066 catch (const std::ifstream::failure& fail)
1067 {
1068 std::cerr << "Exception in file handling [" << file
1069 << "] error : " << fail.what();
1070 std::cerr << "Stream file size = " << vpdFile.gcount()
1071 << std::endl;
1072 throw;
1073 }
jinuthomas45d54972023-07-03 04:36:29 -05001074 }
Santosh Puranik6b2b5372022-06-02 20:49:02 +05301075 break;
1076 }
1077 }
1078 }
1079
1080 return vpdVector;
1081}
Priyanga Ramasamy5629fbc2023-03-01 08:17:19 -06001082
1083std::string getDbusNameForThisKw(const std::string& keyword)
1084{
1085 if (keyword[0] == constants::POUND_KW)
1086 {
1087 return (std::string(constants::POUND_KW_PREFIX) + keyword[1]);
1088 }
1089 else if (isdigit(keyword[0]))
1090 {
1091 return (std::string(constants::NUMERIC_KW_PREFIX) + keyword);
1092 }
1093 return keyword;
1094}
1095
Patrick Venturec83c4dc2018-11-01 16:29:18 -07001096} // namespace vpd
Patrick Williamsc78d8872023-05-10 07:50:56 -05001097} // namespace openpower