blob: 388d8696a119a4596c74bcb284b70ec7bc2a410e [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 {
Sunny Srivastava28abd6e2021-07-28 02:58:28 -0500148 inventory::Value 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 }
Sunny Srivastava28abd6e2021-07-28 02:58:28 -0500159 else if (auto pVal = get_if<bool>(&val))
160 {
161 if (*pVal == false)
162 {
163 propVal = "false";
164 }
165 else
166 {
167 propVal = "true";
168 }
169 }
SunnySrivastava198443306542020-04-01 02:50:20 -0500170 }
171 return propVal;
172}
SunnySrivastava1984a20be8e2020-08-26 02:00:50 -0500173
174void createPEL(const std::map<std::string, std::string>& additionalData,
Sunny Srivastavaa2ddc962022-06-29 08:53:16 -0500175 const Severity& sev, const std::string& errIntf, sd_bus* sdBus)
176{
177 // This pointer will be NULL in case the call is made from ibm-read-vpd. In
178 // that case a sync call will do.
179 if (sdBus == nullptr)
180 {
181 createSyncPEL(additionalData, sev, errIntf);
182 }
183 else
184 {
185 std::string errDescription{};
186 auto pos = additionalData.find("DESCRIPTION");
187 if (pos != additionalData.end())
188 {
189 errDescription = pos->second;
190 }
191 else
192 {
193 errDescription = "Description field missing in additional data";
194 }
195
196 std::string pelSeverity =
197 "xyz.openbmc_project.Logging.Entry.Level.Error";
198 auto itr = sevMap.find(sev);
199 if (itr != sevMap.end())
200 {
201 pelSeverity = itr->second;
202 }
203
204 // Implies this is a call from Manager. Hence we need to make an async
205 // call to avoid deadlock with Phosphor-logging.
206 auto rc = sd_bus_call_method_async(
207 sdBus, NULL, loggerService, loggerObjectPath, loggerCreateInterface,
208 "Create", NULL, NULL, "ssa{ss}", errIntf.c_str(),
209 pelSeverity.c_str(), 1, "DESCRIPTION", errDescription.c_str());
210
211 if (rc < 0)
212 {
213 log<level::ERR>("Error calling sd_bus_call_method_async",
214 entry("RC=%d", rc), entry("MSG=%s", strerror(-rc)));
215 }
216 }
217}
218
219void createSyncPEL(const std::map<std::string, std::string>& additionalData,
220 const Severity& sev, const std::string& errIntf)
SunnySrivastava1984a20be8e2020-08-26 02:00:50 -0500221{
222 try
223 {
Sunny Srivastava0746eee2021-03-22 13:36:54 -0500224 std::string pelSeverity =
225 "xyz.openbmc_project.Logging.Entry.Level.Error";
SunnySrivastava1984a20be8e2020-08-26 02:00:50 -0500226 auto bus = sdbusplus::bus::new_default();
SunnySrivastava1984a20be8e2020-08-26 02:00:50 -0500227 auto service = getService(bus, loggerObjectPath, loggerCreateInterface);
228 auto method = bus.new_method_call(service.c_str(), loggerObjectPath,
229 loggerCreateInterface, "Create");
230
Sunny Srivastava0746eee2021-03-22 13:36:54 -0500231 auto itr = sevMap.find(sev);
232 if (itr != sevMap.end())
233 {
234 pelSeverity = itr->second;
235 }
236
237 method.append(errIntf, pelSeverity, additionalData);
SunnySrivastava1984a20be8e2020-08-26 02:00:50 -0500238 auto resp = bus.call(method);
239 }
Patrick Williams2eb01762022-07-22 19:26:56 -0500240 catch (const sdbusplus::exception_t& e)
SunnySrivastava1984a20be8e2020-08-26 02:00:50 -0500241 {
Sunny Srivastava5ef6ccc2022-05-30 01:35:13 -0500242 std::cerr << "Dbus call to phosphor-logging Create failed. Reason:"
243 << e.what();
SunnySrivastava1984a20be8e2020-08-26 02:00:50 -0500244 }
245}
PriyangaRamasamyc0a534f2020-08-24 21:29:18 +0530246
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500247inventory::VPDfilepath getVpdFilePath(const std::string& jsonFile,
PriyangaRamasamyc0a534f2020-08-24 21:29:18 +0530248 const std::string& ObjPath)
249{
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500250 std::ifstream inventoryJson(jsonFile);
PriyangaRamasamyc0a534f2020-08-24 21:29:18 +0530251 const auto& jsonObject = json::parse(inventoryJson);
252 inventory::VPDfilepath filePath{};
253
254 if (jsonObject.find("frus") == jsonObject.end())
255 {
256 throw(VpdJsonException(
257 "Invalid JSON structure - frus{} object not found in ", jsonFile));
258 }
259
260 const nlohmann::json& groupFRUS =
261 jsonObject["frus"].get_ref<const nlohmann::json::object_t&>();
262 for (const auto& itemFRUS : groupFRUS.items())
263 {
264 const std::vector<nlohmann::json>& groupEEPROM =
265 itemFRUS.value().get_ref<const nlohmann::json::array_t&>();
266 for (const auto& itemEEPROM : groupEEPROM)
267 {
268 if (itemEEPROM["inventoryPath"]
269 .get_ref<const nlohmann::json::string_t&>() == ObjPath)
270 {
271 filePath = itemFRUS.key();
272 return filePath;
273 }
274 }
275 }
276
277 return filePath;
278}
279
280bool isPathInJson(const std::string& eepromPath)
281{
282 bool present = false;
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500283 std::ifstream inventoryJson(INVENTORY_JSON_SYM_LINK);
PriyangaRamasamyc0a534f2020-08-24 21:29:18 +0530284
285 try
286 {
287 auto js = json::parse(inventoryJson);
288 if (js.find("frus") == js.end())
289 {
290 throw(VpdJsonException(
291 "Invalid JSON structure - frus{} object not found in ",
292 INVENTORY_JSON_SYM_LINK));
293 }
294 json fruJson = js["frus"];
295
296 if (fruJson.find(eepromPath) != fruJson.end())
297 {
298 present = true;
299 }
300 }
Patrick Williams8e15b932021-10-06 13:04:22 -0500301 catch (const json::parse_error& ex)
PriyangaRamasamyc0a534f2020-08-24 21:29:18 +0530302 {
303 throw(VpdJsonException("Json Parsing failed", INVENTORY_JSON_SYM_LINK));
304 }
305 return present;
306}
307
308bool isRecKwInDbusJson(const std::string& recordName,
309 const std::string& keyword)
310{
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500311 std::ifstream propertyJson(DBUS_PROP_JSON);
PriyangaRamasamyc0a534f2020-08-24 21:29:18 +0530312 json dbusProperty;
313 bool present = false;
314
315 if (propertyJson.is_open())
316 {
317 try
318 {
319 auto dbusPropertyJson = json::parse(propertyJson);
320 if (dbusPropertyJson.find("dbusProperties") ==
321 dbusPropertyJson.end())
322 {
323 throw(VpdJsonException("dbusProperties{} object not found in "
324 "DbusProperties json : ",
325 DBUS_PROP_JSON));
326 }
327
328 dbusProperty = dbusPropertyJson["dbusProperties"];
329 if (dbusProperty.contains(recordName))
330 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500331 const std::vector<std::string>& kwdsToPublish =
332 dbusProperty[recordName];
PriyangaRamasamyc0a534f2020-08-24 21:29:18 +0530333 if (find(kwdsToPublish.begin(), kwdsToPublish.end(), keyword) !=
334 kwdsToPublish.end()) // present
335 {
336 present = true;
337 }
338 }
339 }
Patrick Williams8e15b932021-10-06 13:04:22 -0500340 catch (const json::parse_error& ex)
PriyangaRamasamyc0a534f2020-08-24 21:29:18 +0530341 {
342 throw(VpdJsonException("Json Parsing failed", DBUS_PROP_JSON));
343 }
344 }
345 else
346 {
347 // If dbus properties json is not available, we assume the given
348 // record-keyword is part of dbus-properties json. So setting the bool
349 // variable to true.
350 present = true;
351 }
352 return present;
353}
354
Sunny Srivastava6c71c9d2021-04-15 04:43:54 -0500355vpdType vpdTypeCheck(const Binary& vpdVector)
356{
357 // Read first 3 Bytes to check the 11S bar code format
358 std::string is11SFormat = "";
359 for (uint8_t i = 0; i < FORMAT_11S_LEN; i++)
360 {
361 is11SFormat += vpdVector[MEMORY_VPD_DATA_START + i];
362 }
363
364 if (vpdVector[IPZ_DATA_START] == KW_VAL_PAIR_START_TAG)
365 {
366 // IPZ VPD FORMAT
367 return vpdType::IPZ_VPD;
368 }
369 else if (vpdVector[KW_VPD_DATA_START] == KW_VPD_START_TAG)
370 {
371 // KEYWORD VPD FORMAT
372 return vpdType::KEYWORD_VPD;
373 }
jinuthomas6555e7e2023-02-14 21:48:00 -0600374 else if (((vpdVector[SPD_BYTE_3] & SPD_BYTE_BIT_0_3_MASK) ==
375 SPD_MODULE_TYPE_DDIMM) &&
376 (is11SFormat.compare(MEMORY_VPD_START_TAG)))
Sunny Srivastava6c71c9d2021-04-15 04:43:54 -0500377 {
jinuthomas6555e7e2023-02-14 21:48:00 -0600378 // DDIMM Memory VPD format
379 if ((vpdVector[SPD_BYTE_2] & SPD_BYTE_MASK) == SPD_DRAM_TYPE_DDR5)
380 {
381 return vpdType::DDR5_DDIMM_MEMORY_VPD;
382 }
383 else if ((vpdVector[SPD_BYTE_2] & SPD_BYTE_MASK) == SPD_DRAM_TYPE_DDR4)
384 {
385 return vpdType::DDR4_DDIMM_MEMORY_VPD;
386 }
387 }
388 else if ((vpdVector[SPD_BYTE_2] & SPD_BYTE_MASK) == SPD_DRAM_TYPE_DDR5)
389 {
390 // ISDIMM Memory VPD format
391 return vpdType::DDR5_ISDIMM_MEMORY_VPD;
392 }
393 else if ((vpdVector[SPD_BYTE_2] & SPD_BYTE_MASK) == SPD_DRAM_TYPE_DDR4)
394 {
395 // ISDIMM Memory VPD format
396 return vpdType::DDR4_ISDIMM_MEMORY_VPD;
Sunny Srivastava6c71c9d2021-04-15 04:43:54 -0500397 }
398
399 // INVALID VPD FORMAT
400 return vpdType::INVALID_VPD_FORMAT;
401}
402
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500403const std::string getIM(const Parsed& vpdMap)
Alpana Kumarif05effd2021-04-07 07:32:53 -0500404{
405 Binary imVal;
406 auto property = vpdMap.find("VSBP");
407 if (property != vpdMap.end())
408 {
409 auto kw = (property->second).find("IM");
410 if (kw != (property->second).end())
411 {
412 copy(kw->second.begin(), kw->second.end(), back_inserter(imVal));
413 }
414 }
415
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500416 std::ostringstream oss;
Alpana Kumarif05effd2021-04-07 07:32:53 -0500417 for (auto& i : imVal)
418 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500419 oss << std::setw(2) << std::setfill('0') << std::hex
420 << static_cast<int>(i);
Alpana Kumarif05effd2021-04-07 07:32:53 -0500421 }
422
423 return oss.str();
424}
425
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500426const std::string getHW(const Parsed& vpdMap)
Alpana Kumarif05effd2021-04-07 07:32:53 -0500427{
428 Binary hwVal;
429 auto prop = vpdMap.find("VINI");
430 if (prop != vpdMap.end())
431 {
432 auto kw = (prop->second).find("HW");
433 if (kw != (prop->second).end())
434 {
435 copy(kw->second.begin(), kw->second.end(), back_inserter(hwVal));
436 }
437 }
438
Alpana Kumari88d2ae82021-11-10 03:23:31 -0600439 // The planar pass only comes from the LSB of the HW keyword,
440 // where as the MSB is used for other purposes such as signifying clock
441 // termination.
442 hwVal[0] = 0x00;
443
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500444 std::ostringstream hwString;
Alpana Kumarif05effd2021-04-07 07:32:53 -0500445 for (auto& i : hwVal)
446 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500447 hwString << std::setw(2) << std::setfill('0') << std::hex
448 << static_cast<int>(i);
Alpana Kumarif05effd2021-04-07 07:32:53 -0500449 }
450
451 return hwString.str();
452}
453
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500454std::string getSystemsJson(const Parsed& vpdMap)
Alpana Kumarif05effd2021-04-07 07:32:53 -0500455{
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500456 std::string jsonPath = "/usr/share/vpd/";
457 std::string jsonName{};
Alpana Kumarif05effd2021-04-07 07:32:53 -0500458
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500459 std::ifstream systemJson(SYSTEM_JSON);
Alpana Kumarif05effd2021-04-07 07:32:53 -0500460 if (!systemJson)
461 {
462 throw((VpdJsonException("Failed to access Json path", SYSTEM_JSON)));
463 }
464
465 try
466 {
467 auto js = json::parse(systemJson);
468
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500469 std::string hwKeyword = getHW(vpdMap);
470 const std::string imKeyword = getIM(vpdMap);
Alpana Kumarif05effd2021-04-07 07:32:53 -0500471
Alpana Kumari1b026112022-03-02 23:41:38 -0600472 transform(hwKeyword.begin(), hwKeyword.end(), hwKeyword.begin(),
473 ::toupper);
474
Alpana Kumarif05effd2021-04-07 07:32:53 -0500475 if (js.find("system") == js.end())
476 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500477 throw std::runtime_error("Invalid systems Json");
Alpana Kumarif05effd2021-04-07 07:32:53 -0500478 }
479
480 if (js["system"].find(imKeyword) == js["system"].end())
481 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500482 throw std::runtime_error(
Alpana Kumarif05effd2021-04-07 07:32:53 -0500483 "Invalid system. This system type is not present "
484 "in the systemsJson. IM: " +
485 imKeyword);
486 }
487
488 if ((js["system"][imKeyword].find("constraint") !=
489 js["system"][imKeyword].end()) &&
Alpana Kumari1b026112022-03-02 23:41:38 -0600490 js["system"][imKeyword]["constraint"].find("HW") !=
491 js["system"][imKeyword]["constraint"].end())
Alpana Kumarif05effd2021-04-07 07:32:53 -0500492 {
Alpana Kumari1b026112022-03-02 23:41:38 -0600493 // collect hw versions from json, and check hwKeyword is part of it
494 // if hwKeyword is found there then load respective json
495 // otherwise load default one.
496 for (const auto& hwVersion :
497 js["system"][imKeyword]["constraint"]["HW"])
498 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500499 std::string hw = hwVersion;
Alpana Kumari1b026112022-03-02 23:41:38 -0600500 transform(hw.begin(), hw.end(), hw.begin(), ::toupper);
501
502 if (hw == hwKeyword)
503 {
504 jsonName = js["system"][imKeyword]["constraint"]["json"];
505 break;
506 }
507 }
508
509 if (jsonName.empty() && js["system"][imKeyword].find("default") !=
510 js["system"][imKeyword].end())
511 {
512 jsonName = js["system"][imKeyword]["default"];
513 }
Alpana Kumarif05effd2021-04-07 07:32:53 -0500514 }
515 else if (js["system"][imKeyword].find("default") !=
516 js["system"][imKeyword].end())
517 {
518 jsonName = js["system"][imKeyword]["default"];
519 }
520 else
521 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500522 throw std::runtime_error(
Alpana Kumarif05effd2021-04-07 07:32:53 -0500523 "Bad System json. Neither constraint nor default found");
524 }
525
526 jsonPath += jsonName;
527 }
528
Patrick Williams8e15b932021-10-06 13:04:22 -0500529 catch (const json::parse_error& ex)
Alpana Kumarif05effd2021-04-07 07:32:53 -0500530 {
531 throw(VpdJsonException("Json Parsing failed", SYSTEM_JSON));
532 }
533 return jsonPath;
534}
535
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500536void udevToGenericPath(std::string& file)
PriyangaRamasamy647868e2020-09-08 17:03:19 +0530537{
538 // Sample udevEvent i2c path :
539 // "/sys/devices/platform/ahb/ahb:apb/ahb:apb:bus@1e78a000/1e78a480.i2c-bus/i2c-8/8-0051/8-00510/nvmem"
540 // find if the path contains the word i2c in it.
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500541 if (file.find("i2c") != std::string::npos)
PriyangaRamasamy647868e2020-09-08 17:03:19 +0530542 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500543 std::string i2cBusAddr{};
PriyangaRamasamy647868e2020-09-08 17:03:19 +0530544
545 // Every udev i2c path should have the common pattern
546 // "i2c-bus_number/bus_number-vpd_address". Search for
547 // "bus_number-vpd_address".
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500548 std::regex i2cPattern("((i2c)-[0-9]+\\/)([0-9]+-[0-9]{4})");
549 std::smatch match;
550 if (std::regex_search(file, match, i2cPattern))
PriyangaRamasamy647868e2020-09-08 17:03:19 +0530551 {
552 i2cBusAddr = match.str(3);
553 }
554 else
555 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500556 std::cerr << "The given udev path < " << file
557 << " > doesn't match the required pattern. Skipping VPD "
558 "collection."
559 << std::endl;
PriyangaRamasamy647868e2020-09-08 17:03:19 +0530560 exit(EXIT_SUCCESS);
561 }
562 // Forming the generic file path
563 file = i2cPathPrefix + i2cBusAddr + "/eeprom";
564 }
565 // Sample udevEvent spi path :
566 // "/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"
567 // find if the path contains the word spi in it.
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500568 else if (file.find("spi") != std::string::npos)
PriyangaRamasamy647868e2020-09-08 17:03:19 +0530569 {
570 // Every udev spi path will have common pattern "spi<Digit>/", which
571 // describes the spi bus number at which the fru is connected; Followed
572 // by a slash following the vpd address of the fru. Taking the above
573 // input as a common key, we try to search for the pattern "spi<Digit>/"
574 // using regular expression.
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500575 std::regex spiPattern("((spi)[0-9]+)(\\/)");
576 std::string spiBus{};
577 std::smatch match;
578 if (std::regex_search(file, match, spiPattern))
PriyangaRamasamy647868e2020-09-08 17:03:19 +0530579 {
580 spiBus = match.str(1);
581 }
582 else
583 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500584 std::cerr << "The given udev path < " << file
585 << " > doesn't match the required pattern. Skipping VPD "
586 "collection."
587 << std::endl;
PriyangaRamasamy647868e2020-09-08 17:03:19 +0530588 exit(EXIT_SUCCESS);
589 }
590 // Forming the generic path
591 file = spiPathPrefix + spiBus + ".0/eeprom";
592 }
593 else
594 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500595 std::cerr << "\n The given EEPROM path < " << file
596 << " > is not valid. It's neither I2C nor "
597 "SPI path. Skipping VPD collection.."
598 << std::endl;
PriyangaRamasamy647868e2020-09-08 17:03:19 +0530599 exit(EXIT_SUCCESS);
600 }
601}
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500602std::string getBadVpdName(const std::string& file)
PriyangaRamasamyc2fe40f2021-03-02 06:27:33 -0600603{
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500604 std::string badVpd = BAD_VPD_DIR;
605 if (file.find("i2c") != std::string::npos)
PriyangaRamasamyc2fe40f2021-03-02 06:27:33 -0600606 {
607 badVpd += "i2c-";
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500608 std::regex i2cPattern("(at24/)([0-9]+-[0-9]+)\\/");
609 std::smatch match;
610 if (std::regex_search(file, match, i2cPattern))
PriyangaRamasamyc2fe40f2021-03-02 06:27:33 -0600611 {
612 badVpd += match.str(2);
613 }
614 }
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500615 else if (file.find("spi") != std::string::npos)
PriyangaRamasamyc2fe40f2021-03-02 06:27:33 -0600616 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500617 std::regex spiPattern("((spi)[0-9]+)(.0)");
618 std::smatch match;
619 if (std::regex_search(file, match, spiPattern))
PriyangaRamasamyc2fe40f2021-03-02 06:27:33 -0600620 {
621 badVpd += match.str(1);
622 }
623 }
624 return badVpd;
625}
626
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500627void dumpBadVpd(const std::string& file, const Binary& vpdVector)
PriyangaRamasamyc2fe40f2021-03-02 06:27:33 -0600628{
629 fs::path badVpdDir = BAD_VPD_DIR;
630 fs::create_directory(badVpdDir);
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500631 std::string badVpdPath = getBadVpdName(file);
PriyangaRamasamyc2fe40f2021-03-02 06:27:33 -0600632 if (fs::exists(badVpdPath))
633 {
634 std::error_code ec;
635 fs::remove(badVpdPath, ec);
636 if (ec) // error code
637 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500638 std::string error = "Error removing the existing broken vpd in ";
PriyangaRamasamyc2fe40f2021-03-02 06:27:33 -0600639 error += badVpdPath;
640 error += ". Error code : ";
641 error += ec.value();
642 error += ". Error message : ";
643 error += ec.message();
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500644 throw std::runtime_error(error);
PriyangaRamasamyc2fe40f2021-03-02 06:27:33 -0600645 }
646 }
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500647 std::ofstream badVpdFileStream(badVpdPath, std::ofstream::binary);
PriyangaRamasamyc2fe40f2021-03-02 06:27:33 -0600648 if (!badVpdFileStream)
649 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500650 throw std::runtime_error(
651 "Failed to open bad vpd file path in /tmp/bad-vpd. "
652 "Unable to dump the broken/bad vpd file.");
PriyangaRamasamyc2fe40f2021-03-02 06:27:33 -0600653 }
654 badVpdFileStream.write(reinterpret_cast<const char*>(vpdVector.data()),
655 vpdVector.size());
656}
alpana077ce68722021-07-25 13:23:59 -0500657
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500658const std::string getKwVal(const Parsed& vpdMap, const std::string& rec,
659 const std::string& kwd)
alpana077ce68722021-07-25 13:23:59 -0500660{
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500661 std::string kwVal{};
alpana077ce68722021-07-25 13:23:59 -0500662
663 auto findRec = vpdMap.find(rec);
664
665 // check if record is found in map we got by parser
666 if (findRec != vpdMap.end())
667 {
668 auto findKwd = findRec->second.find(kwd);
669
670 if (findKwd != findRec->second.end())
671 {
672 kwVal = findKwd->second;
673 }
674 }
675
676 return kwVal;
677}
678
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500679std::string byteArrayToHexString(const Binary& vec)
Priyanga Ramasamyc9ecf8e2021-10-08 02:28:52 -0500680{
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500681 std::stringstream ss;
682 std::string hexRep = "0x";
Priyanga Ramasamyc9ecf8e2021-10-08 02:28:52 -0500683 ss << hexRep;
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500684 std::string str = ss.str();
Priyanga Ramasamyc9ecf8e2021-10-08 02:28:52 -0500685
686 // convert Decimal to Hex string
687 for (auto& v : vec)
688 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500689 ss << std::setfill('0') << std::setw(2) << std::hex << (int)v;
Priyanga Ramasamyc9ecf8e2021-10-08 02:28:52 -0500690 str = ss.str();
691 }
692 return str;
693}
694
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500695std::string getPrintableValue(const Binary& vec)
Priyanga Ramasamy02434932021-10-07 16:26:05 -0500696{
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500697 std::string str{};
Priyanga Ramasamy02434932021-10-07 16:26:05 -0500698
Priyanga Ramasamyc9ecf8e2021-10-08 02:28:52 -0500699 // find for a non printable value in the vector
700 const auto it = std::find_if(vec.begin(), vec.end(),
701 [](const auto& ele) { return !isprint(ele); });
Priyanga Ramasamy02434932021-10-07 16:26:05 -0500702
Priyanga Ramasamyc9ecf8e2021-10-08 02:28:52 -0500703 if (it != vec.end()) // if the given vector has any non printable value
704 {
705 for (auto itr = it; itr != vec.end(); itr++)
Priyanga Ramasamy02434932021-10-07 16:26:05 -0500706 {
Priyanga Ramasamyc9ecf8e2021-10-08 02:28:52 -0500707 if (*itr != 0x00)
708 {
709 str = byteArrayToHexString(vec);
710 return str;
711 }
Priyanga Ramasamy02434932021-10-07 16:26:05 -0500712 }
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500713 str = std::string(vec.begin(), it);
Priyanga Ramasamy02434932021-10-07 16:26:05 -0500714 }
715 else
716 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500717 str = std::string(vec.begin(), vec.end());
Priyanga Ramasamy02434932021-10-07 16:26:05 -0500718 }
719 return str;
720}
721
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500722void executePostFailAction(const nlohmann::json& json, const std::string& file)
Alpana Kumari735dee92022-03-25 01:24:40 -0500723{
724 if ((json["frus"][file].at(0)).find("postActionFail") ==
725 json["frus"][file].at(0).end())
726 {
727 return;
728 }
729
730 uint8_t pinValue = 0;
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500731 std::string pinName;
Alpana Kumari735dee92022-03-25 01:24:40 -0500732
733 for (const auto& postAction :
734 (json["frus"][file].at(0))["postActionFail"].items())
735 {
736 if (postAction.key() == "pin")
737 {
738 pinName = postAction.value();
739 }
740 else if (postAction.key() == "value")
741 {
742 // Get the value to set
743 pinValue = postAction.value();
744 }
745 }
746
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500747 std::cout << "Setting GPIO: " << pinName << " to " << (int)pinValue
748 << std::endl;
Alpana Kumari735dee92022-03-25 01:24:40 -0500749
750 try
751 {
752 gpiod::line outputLine = gpiod::find_line(pinName);
753
754 if (!outputLine)
755 {
Sunny Srivastavaa2ddc962022-06-29 08:53:16 -0500756 throw GpioException(
Alpana Kumari6bd095f2022-02-23 10:20:20 -0600757 "Couldn't find output line for the GPIO. Skipping "
758 "this GPIO action.");
Alpana Kumari735dee92022-03-25 01:24:40 -0500759 }
760 outputLine.request(
761 {"Disable line", ::gpiod::line_request::DIRECTION_OUTPUT, 0},
762 pinValue);
763 }
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500764 catch (const std::exception& e)
Alpana Kumari735dee92022-03-25 01:24:40 -0500765 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500766 std::string i2cBusAddr;
767 std::string errMsg = e.what();
Alpana Kumari6bd095f2022-02-23 10:20:20 -0600768 errMsg += "\nGPIO: " + pinName;
769
770 if ((json["frus"][file].at(0)["postActionFail"].find(
771 "gpioI2CAddress")) !=
772 json["frus"][file].at(0)["postActionFail"].end())
773 {
774 i2cBusAddr =
775 json["frus"][file].at(0)["postActionFail"]["gpioI2CAddress"];
Sunny Srivastavafdf9ff22022-06-15 11:15:54 -0500776 errMsg += " i2cBusAddress: " + i2cBusAddr;
Alpana Kumari6bd095f2022-02-23 10:20:20 -0600777 }
778
Sunny Srivastavaa2ddc962022-06-29 08:53:16 -0500779 throw GpioException(e.what());
Alpana Kumari735dee92022-03-25 01:24:40 -0500780 }
Alpana Kumari6bd095f2022-02-23 10:20:20 -0600781
782 return;
Alpana Kumari735dee92022-03-25 01:24:40 -0500783}
784
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500785std::optional<bool> isPresent(const nlohmann::json& json,
786 const std::string& file)
Santosh Puranik53b38ed2022-04-10 23:15:22 +0530787
Alpana Kumari735dee92022-03-25 01:24:40 -0500788{
789 if ((json["frus"][file].at(0)).find("presence") !=
790 json["frus"][file].at(0).end())
791 {
792 if (((json["frus"][file].at(0)["presence"]).find("pin") !=
793 json["frus"][file].at(0)["presence"].end()) &&
794 ((json["frus"][file].at(0)["presence"]).find("value") !=
795 json["frus"][file].at(0)["presence"].end()))
796 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500797 std::string presPinName =
798 json["frus"][file].at(0)["presence"]["pin"];
Alpana Kumari735dee92022-03-25 01:24:40 -0500799 Byte presPinValue = json["frus"][file].at(0)["presence"]["value"];
800
801 try
802 {
803 gpiod::line presenceLine = gpiod::find_line(presPinName);
804
805 if (!presenceLine)
806 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500807 std::cerr << "Couldn't find the presence line for - "
808 << presPinName << std::endl;
Alpana Kumari40d1c192022-03-09 21:16:02 -0600809
Sunny Srivastavaa2ddc962022-06-29 08:53:16 -0500810 throw GpioException(
Alpana Kumari6bd095f2022-02-23 10:20:20 -0600811 "Couldn't find the presence line for the "
812 "GPIO. Skipping this GPIO action.");
Alpana Kumari735dee92022-03-25 01:24:40 -0500813 }
814
815 presenceLine.request({"Read the presence line",
816 gpiod::line_request::DIRECTION_INPUT, 0});
817
818 Byte gpioData = presenceLine.get_value();
819
Santosh Puranik53b38ed2022-04-10 23:15:22 +0530820 return (gpioData == presPinValue);
Alpana Kumari735dee92022-03-25 01:24:40 -0500821 }
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500822 catch (const std::exception& e)
Alpana Kumari735dee92022-03-25 01:24:40 -0500823 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500824 std::string i2cBusAddr;
825 std::string errMsg = e.what();
Alpana Kumari6bd095f2022-02-23 10:20:20 -0600826 errMsg += " GPIO : " + presPinName;
827
828 if ((json["frus"][file].at(0)["presence"])
829 .find("gpioI2CAddress") !=
830 json["frus"][file].at(0)["presence"].end())
831 {
832 i2cBusAddr =
833 json["frus"][file].at(0)["presence"]["gpioI2CAddress"];
Sunny Srivastavafdf9ff22022-06-15 11:15:54 -0500834 errMsg += " i2cBusAddress: " + i2cBusAddr;
Alpana Kumari6bd095f2022-02-23 10:20:20 -0600835 }
836
Alpana Kumari40d1c192022-03-09 21:16:02 -0600837 // Take failure postAction
838 executePostFailAction(json, file);
Sunny Srivastavaa2ddc962022-06-29 08:53:16 -0500839 throw GpioException(errMsg);
Alpana Kumari735dee92022-03-25 01:24:40 -0500840 }
841 }
Alpana Kumari40d1c192022-03-09 21:16:02 -0600842 else
843 {
844 // missing required informations
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500845 std::cerr
846 << "VPD inventory JSON missing basic informations of presence "
847 "for this FRU : ["
848 << file << "]. Executing executePostFailAction." << std::endl;
Alpana Kumari40d1c192022-03-09 21:16:02 -0600849
850 // Take failure postAction
851 executePostFailAction(json, file);
852
853 return false;
854 }
Alpana Kumari735dee92022-03-25 01:24:40 -0500855 }
Santosh Puranik53b38ed2022-04-10 23:15:22 +0530856 return std::optional<bool>{};
857}
858
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500859bool executePreAction(const nlohmann::json& json, const std::string& file)
Santosh Puranik53b38ed2022-04-10 23:15:22 +0530860{
861 auto present = isPresent(json, file);
862 if (present && !present.value())
863 {
864 executePostFailAction(json, file);
865 return false;
866 }
Alpana Kumari735dee92022-03-25 01:24:40 -0500867
868 if ((json["frus"][file].at(0)).find("preAction") !=
869 json["frus"][file].at(0).end())
870 {
871 if (((json["frus"][file].at(0)["preAction"]).find("pin") !=
872 json["frus"][file].at(0)["preAction"].end()) &&
873 ((json["frus"][file].at(0)["preAction"]).find("value") !=
874 json["frus"][file].at(0)["preAction"].end()))
875 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500876 std::string pinName = json["frus"][file].at(0)["preAction"]["pin"];
Alpana Kumari735dee92022-03-25 01:24:40 -0500877 // Get the value to set
878 Byte pinValue = json["frus"][file].at(0)["preAction"]["value"];
879
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500880 std::cout << "Setting GPIO: " << pinName << " to " << (int)pinValue
881 << std::endl;
Alpana Kumari735dee92022-03-25 01:24:40 -0500882 try
883 {
884 gpiod::line outputLine = gpiod::find_line(pinName);
885
886 if (!outputLine)
887 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500888 std::cerr << "Couldn't find the line for output pin - "
889 << pinName << std::endl;
Sunny Srivastavaa2ddc962022-06-29 08:53:16 -0500890 throw GpioException(
Alpana Kumari6bd095f2022-02-23 10:20:20 -0600891 "Couldn't find output line for the GPIO. "
892 "Skipping this GPIO action.");
Alpana Kumari735dee92022-03-25 01:24:40 -0500893 }
894 outputLine.request({"FRU pre-action",
895 ::gpiod::line_request::DIRECTION_OUTPUT, 0},
896 pinValue);
897 }
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500898 catch (const std::exception& e)
Alpana Kumari735dee92022-03-25 01:24:40 -0500899 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500900 std::string i2cBusAddr;
901 std::string errMsg = e.what();
Alpana Kumari6bd095f2022-02-23 10:20:20 -0600902 errMsg += " GPIO : " + pinName;
903
904 if ((json["frus"][file].at(0)["preAction"])
905 .find("gpioI2CAddress") !=
906 json["frus"][file].at(0)["preAction"].end())
907 {
908 i2cBusAddr =
909 json["frus"][file].at(0)["preAction"]["gpioI2CAddress"];
Sunny Srivastavafdf9ff22022-06-15 11:15:54 -0500910 errMsg += " i2cBusAddress: " + i2cBusAddr;
Alpana Kumari6bd095f2022-02-23 10:20:20 -0600911 }
912
Alpana Kumari40d1c192022-03-09 21:16:02 -0600913 // Take failure postAction
914 executePostFailAction(json, file);
Sunny Srivastavaa2ddc962022-06-29 08:53:16 -0500915 throw GpioException(errMsg);
Alpana Kumari735dee92022-03-25 01:24:40 -0500916 }
917 }
Alpana Kumari40d1c192022-03-09 21:16:02 -0600918 else
919 {
920 // missing required informations
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500921 std::cerr
Alpana Kumari40d1c192022-03-09 21:16:02 -0600922 << "VPD inventory JSON missing basic informations of preAction "
923 "for this FRU : ["
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500924 << file << "]. Executing executePostFailAction." << std::endl;
Alpana Kumari40d1c192022-03-09 21:16:02 -0600925
926 // Take failure postAction
927 executePostFailAction(json, file);
Alpana Kumari40d1c192022-03-09 21:16:02 -0600928 return false;
929 }
Alpana Kumari735dee92022-03-25 01:24:40 -0500930 }
931 return true;
932}
933
Priyanga Ramasamyaa8a8932022-01-27 09:12:41 -0600934void insertOrMerge(inventory::InterfaceMap& map,
935 const inventory::Interface& interface,
936 inventory::PropertyMap&& property)
937{
938 if (map.find(interface) != map.end())
939 {
940 auto& prop = map.at(interface);
941 prop.insert(property.begin(), property.end());
942 }
943 else
944 {
945 map.emplace(interface, property);
946 }
947}
Santosh Puranikf2d3b532022-04-19 06:44:07 -0500948
949BIOSAttrValueType readBIOSAttribute(const std::string& attrName)
950{
951 std::tuple<std::string, BIOSAttrValueType, BIOSAttrValueType> attrVal;
952 auto bus = sdbusplus::bus::new_default();
953 auto method = bus.new_method_call(
954 "xyz.openbmc_project.BIOSConfigManager",
955 "/xyz/openbmc_project/bios_config/manager",
956 "xyz.openbmc_project.BIOSConfig.Manager", "GetAttribute");
957 method.append(attrName);
958 try
959 {
960 auto result = bus.call(method);
961 result.read(std::get<0>(attrVal), std::get<1>(attrVal),
962 std::get<2>(attrVal));
963 }
964 catch (const sdbusplus::exception::SdBusError& e)
965 {
966 std::cerr << "Failed to read BIOS Attribute: " << attrName << std::endl;
967 std::cerr << e.what() << std::endl;
968 }
969 return std::get<1>(attrVal);
970}
Priyanga Ramasamy335873f2022-05-18 01:31:54 -0500971
972std::string getPowerState()
973{
974 // TODO: How do we handle multiple chassis?
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500975 std::string powerState{};
Priyanga Ramasamy335873f2022-05-18 01:31:54 -0500976 auto bus = sdbusplus::bus::new_default();
977 auto properties =
978 bus.new_method_call("xyz.openbmc_project.State.Chassis",
979 "/xyz/openbmc_project/state/chassis0",
980 "org.freedesktop.DBus.Properties", "Get");
981 properties.append("xyz.openbmc_project.State.Chassis");
982 properties.append("CurrentPowerState");
983 auto result = bus.call(properties);
984 if (!result.is_method_error())
985 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500986 std::variant<std::string> val;
Priyanga Ramasamy335873f2022-05-18 01:31:54 -0500987 result.read(val);
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500988 if (auto pVal = std::get_if<std::string>(&val))
Priyanga Ramasamy335873f2022-05-18 01:31:54 -0500989 {
990 powerState = *pVal;
991 }
992 }
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500993 std::cout << "Power state is: " << powerState << std::endl;
Priyanga Ramasamy335873f2022-05-18 01:31:54 -0500994 return powerState;
995}
Santosh Puranik6b2b5372022-06-02 20:49:02 +0530996
997Binary getVpdDataInVector(const nlohmann::json& js, const std::string& file)
998{
999 uint32_t offset = 0;
1000 // check if offset present?
1001 for (const auto& item : js["frus"][file])
1002 {
1003 if (item.find("offset") != item.end())
1004 {
1005 offset = item["offset"];
1006 }
1007 }
1008
1009 // TODO: Figure out a better way to get max possible VPD size.
1010 auto maxVPDSize = std::min(std::filesystem::file_size(file),
1011 static_cast<uintmax_t>(65504));
1012
1013 Binary vpdVector;
1014 vpdVector.resize(maxVPDSize);
Priyanga Ramasamye0084322022-09-27 06:28:33 -05001015 std::ifstream vpdFile;
1016 vpdFile.open(file, std::ios::binary);
Santosh Puranik6b2b5372022-06-02 20:49:02 +05301017
Priyanga Ramasamye0084322022-09-27 06:28:33 -05001018 vpdFile.seekg(offset, std::ios_base::cur);
Santosh Puranik6b2b5372022-06-02 20:49:02 +05301019 vpdFile.read(reinterpret_cast<char*>(&vpdVector[0]), maxVPDSize);
1020 vpdVector.resize(vpdFile.gcount());
1021
1022 // Make sure we reset the EEPROM pointer to a "safe" location if it was DIMM
1023 // SPD that we just read.
1024 for (const auto& item : js["frus"][file])
1025 {
1026 if (item.find("extraInterfaces") != item.end())
1027 {
1028 if (item["extraInterfaces"].find(
1029 "xyz.openbmc_project.Inventory.Item.Dimm") !=
1030 item["extraInterfaces"].end())
1031 {
1032 // moves the EEPROM pointer to 2048 'th byte.
1033 vpdFile.seekg(2047, std::ios::beg);
1034 // Read that byte and discard - to affirm the move
1035 // operation.
1036 char ch;
1037 vpdFile.read(&ch, sizeof(ch));
1038 break;
1039 }
1040 }
1041 }
1042
1043 return vpdVector;
1044}
Patrick Venturec83c4dc2018-11-01 16:29:18 -07001045} // namespace vpd
Alpana Kumari735dee92022-03-25 01:24:40 -05001046} // namespace openpower