blob: edb7a9f5fb20dd14b772970f45d6d9a6fe143b7e [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>
Alpana Kumari735dee92022-03-25 01:24:40 -050010#include <gpiod.hpp>
Sunny Srivastava6c71c9d2021-04-15 04:43:54 -050011#include <nlohmann/json.hpp>
SunnySrivastava19849094d4f2020-08-05 09:32:29 -050012#include <phosphor-logging/elog-errors.hpp>
Patrick Venturec83c4dc2018-11-01 16:29:18 -070013#include <phosphor-logging/log.hpp>
14#include <sdbusplus/server.hpp>
Patrick Williamsc78d8872023-05-10 07:50:56 -050015#include <xyz/openbmc_project/Common/error.hpp>
16
17#include <filesystem>
18#include <fstream>
19#include <iomanip>
20#include <regex>
PriyangaRamasamyc0a534f2020-08-24 21:29:18 +053021#include <sstream>
22#include <vector>
Deepak Kodihalli76794492017-02-16 23:48:18 -060023
PriyangaRamasamyc0a534f2020-08-24 21:29:18 +053024using json = nlohmann::json;
25
Deepak Kodihalli76794492017-02-16 23:48:18 -060026namespace openpower
27{
28namespace vpd
29{
SunnySrivastava1984945a02d2020-05-06 01:55:41 -050030using namespace openpower::vpd::constants;
SunnySrivastava1984a20be8e2020-08-26 02:00:50 -050031using namespace inventory;
32using namespace phosphor::logging;
SunnySrivastava19849094d4f2020-08-05 09:32:29 -050033using namespace sdbusplus::xyz::openbmc_project::Common::Error;
PriyangaRamasamyc0a534f2020-08-24 21:29:18 +053034using namespace record;
35using namespace openpower::vpd::exceptions;
Sunny Srivastava6c71c9d2021-04-15 04:43:54 -050036using namespace common::utility;
Sunny Srivastava0746eee2021-03-22 13:36:54 -050037using Severity = openpower::vpd::constants::PelSeverity;
PriyangaRamasamyc2fe40f2021-03-02 06:27:33 -060038namespace fs = std::filesystem;
Sunny Srivastava0746eee2021-03-22 13:36:54 -050039
40// mapping of severity enum to severity interface
41static std::unordered_map<Severity, std::string> sevMap = {
42 {Severity::INFORMATIONAL,
43 "xyz.openbmc_project.Logging.Entry.Level.Informational"},
44 {Severity::DEBUG, "xyz.openbmc_project.Logging.Entry.Level.Debug"},
45 {Severity::NOTICE, "xyz.openbmc_project.Logging.Entry.Level.Notice"},
46 {Severity::WARNING, "xyz.openbmc_project.Logging.Entry.Level.Warning"},
47 {Severity::CRITICAL, "xyz.openbmc_project.Logging.Entry.Level.Critical"},
48 {Severity::EMERGENCY, "xyz.openbmc_project.Logging.Entry.Level.Emergency"},
49 {Severity::ERROR, "xyz.openbmc_project.Logging.Entry.Level.Error"},
50 {Severity::ALERT, "xyz.openbmc_project.Logging.Entry.Level.Alert"}};
51
Deepak Kodihalli76794492017-02-16 23:48:18 -060052namespace inventory
53{
54
SunnySrivastava19849094d4f2020-08-05 09:32:29 -050055MapperResponse
56 getObjectSubtreeForInterfaces(const std::string& root, const int32_t depth,
57 const std::vector<std::string>& interfaces)
58{
59 auto bus = sdbusplus::bus::new_default();
60 auto mapperCall = bus.new_method_call(mapperDestination, mapperObjectPath,
61 mapperInterface, "GetSubTree");
62 mapperCall.append(root);
63 mapperCall.append(depth);
64 mapperCall.append(interfaces);
65
66 MapperResponse result = {};
67
68 try
69 {
70 auto response = bus.call(mapperCall);
71
72 response.read(result);
73 }
Patrick Williams2eb01762022-07-22 19:26:56 -050074 catch (const sdbusplus::exception_t& e)
SunnySrivastava19849094d4f2020-08-05 09:32:29 -050075 {
76 log<level::ERR>("Error in mapper GetSubTree",
77 entry("ERROR=%s", e.what()));
78 }
79
80 return result;
81}
82
Deepak Kodihalli76794492017-02-16 23:48:18 -060083} // namespace inventory
84
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -060085LE2ByteData readUInt16LE(Binary::const_iterator iterator)
86{
87 LE2ByteData lowByte = *iterator;
88 LE2ByteData highByte = *(iterator + 1);
89 lowByte |= (highByte << 8);
90 return lowByte;
91}
92
SunnySrivastava1984d076da82020-03-05 05:33:35 -060093/** @brief Encodes a keyword for D-Bus.
94 */
Priyanga Ramasamye0084322022-09-27 06:28:33 -050095std::string encodeKeyword(const std::string& kw, const std::string& encoding)
SunnySrivastava1984d076da82020-03-05 05:33:35 -060096{
97 if (encoding == "MAC")
98 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -050099 std::string res{};
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600100 size_t first = kw[0];
101 res += toHex(first >> 4);
102 res += toHex(first & 0x0f);
103 for (size_t i = 1; i < kw.size(); ++i)
104 {
105 res += ":";
106 res += toHex(kw[i] >> 4);
107 res += toHex(kw[i] & 0x0f);
108 }
109 return res;
110 }
111 else if (encoding == "DATE")
112 {
113 // Date, represent as
114 // <year>-<month>-<day> <hour>:<min>
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500115 std::string res{};
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600116 static constexpr uint8_t skipPrefix = 3;
117
118 auto strItr = kw.begin();
119 advance(strItr, skipPrefix);
120 for_each(strItr, kw.end(), [&res](size_t c) { res += c; });
121
122 res.insert(BD_YEAR_END, 1, '-');
123 res.insert(BD_MONTH_END, 1, '-');
124 res.insert(BD_DAY_END, 1, ' ');
125 res.insert(BD_HOUR_END, 1, ':');
126
127 return res;
128 }
129 else // default to string encoding
130 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500131 return std::string(kw.begin(), kw.end());
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600132 }
133}
SunnySrivastava198443306542020-04-01 02:50:20 -0500134
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500135std::string readBusProperty(const std::string& obj, const std::string& inf,
136 const std::string& prop)
SunnySrivastava198443306542020-04-01 02:50:20 -0500137{
138 std::string propVal{};
139 std::string object = INVENTORY_PATH + obj;
140 auto bus = sdbusplus::bus::new_default();
141 auto properties = bus.new_method_call(
142 "xyz.openbmc_project.Inventory.Manager", object.c_str(),
143 "org.freedesktop.DBus.Properties", "Get");
144 properties.append(inf);
145 properties.append(prop);
146 auto result = bus.call(properties);
147 if (!result.is_method_error())
148 {
Sunny Srivastava28abd6e2021-07-28 02:58:28 -0500149 inventory::Value val;
SunnySrivastava198443306542020-04-01 02:50:20 -0500150 result.read(val);
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500151 if (auto pVal = std::get_if<Binary>(&val))
SunnySrivastava198443306542020-04-01 02:50:20 -0500152 {
153 propVal.assign(reinterpret_cast<const char*>(pVal->data()),
154 pVal->size());
155 }
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500156 else if (auto pVal = std::get_if<std::string>(&val))
SunnySrivastava1984bca5aaa2020-04-21 05:31:04 -0500157 {
158 propVal.assign(pVal->data(), pVal->size());
159 }
Sunny Srivastava28abd6e2021-07-28 02:58:28 -0500160 else if (auto pVal = get_if<bool>(&val))
161 {
162 if (*pVal == false)
163 {
164 propVal = "false";
165 }
166 else
167 {
168 propVal = "true";
169 }
170 }
SunnySrivastava198443306542020-04-01 02:50:20 -0500171 }
172 return propVal;
173}
SunnySrivastava1984a20be8e2020-08-26 02:00:50 -0500174
175void createPEL(const std::map<std::string, std::string>& additionalData,
Sunny Srivastavaa2ddc962022-06-29 08:53:16 -0500176 const Severity& sev, const std::string& errIntf, sd_bus* sdBus)
177{
178 // This pointer will be NULL in case the call is made from ibm-read-vpd. In
179 // that case a sync call will do.
180 if (sdBus == nullptr)
181 {
182 createSyncPEL(additionalData, sev, errIntf);
183 }
184 else
185 {
186 std::string errDescription{};
187 auto pos = additionalData.find("DESCRIPTION");
188 if (pos != additionalData.end())
189 {
190 errDescription = pos->second;
191 }
192 else
193 {
194 errDescription = "Description field missing in additional data";
195 }
196
197 std::string pelSeverity =
198 "xyz.openbmc_project.Logging.Entry.Level.Error";
199 auto itr = sevMap.find(sev);
200 if (itr != sevMap.end())
201 {
202 pelSeverity = itr->second;
203 }
204
205 // Implies this is a call from Manager. Hence we need to make an async
206 // call to avoid deadlock with Phosphor-logging.
207 auto rc = sd_bus_call_method_async(
208 sdBus, NULL, loggerService, loggerObjectPath, loggerCreateInterface,
209 "Create", NULL, NULL, "ssa{ss}", errIntf.c_str(),
210 pelSeverity.c_str(), 1, "DESCRIPTION", errDescription.c_str());
211
212 if (rc < 0)
213 {
214 log<level::ERR>("Error calling sd_bus_call_method_async",
215 entry("RC=%d", rc), entry("MSG=%s", strerror(-rc)));
216 }
217 }
218}
219
220void createSyncPEL(const std::map<std::string, std::string>& additionalData,
221 const Severity& sev, const std::string& errIntf)
SunnySrivastava1984a20be8e2020-08-26 02:00:50 -0500222{
223 try
224 {
Sunny Srivastava0746eee2021-03-22 13:36:54 -0500225 std::string pelSeverity =
226 "xyz.openbmc_project.Logging.Entry.Level.Error";
SunnySrivastava1984a20be8e2020-08-26 02:00:50 -0500227 auto bus = sdbusplus::bus::new_default();
SunnySrivastava1984a20be8e2020-08-26 02:00:50 -0500228 auto service = getService(bus, loggerObjectPath, loggerCreateInterface);
229 auto method = bus.new_method_call(service.c_str(), loggerObjectPath,
230 loggerCreateInterface, "Create");
231
Sunny Srivastava0746eee2021-03-22 13:36:54 -0500232 auto itr = sevMap.find(sev);
233 if (itr != sevMap.end())
234 {
235 pelSeverity = itr->second;
236 }
237
238 method.append(errIntf, pelSeverity, additionalData);
SunnySrivastava1984a20be8e2020-08-26 02:00:50 -0500239 auto resp = bus.call(method);
240 }
Patrick Williams2eb01762022-07-22 19:26:56 -0500241 catch (const sdbusplus::exception_t& e)
SunnySrivastava1984a20be8e2020-08-26 02:00:50 -0500242 {
Sunny Srivastava5ef6ccc2022-05-30 01:35:13 -0500243 std::cerr << "Dbus call to phosphor-logging Create failed. Reason:"
244 << e.what();
SunnySrivastava1984a20be8e2020-08-26 02:00:50 -0500245 }
246}
PriyangaRamasamyc0a534f2020-08-24 21:29:18 +0530247
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500248inventory::VPDfilepath getVpdFilePath(const std::string& jsonFile,
PriyangaRamasamyc0a534f2020-08-24 21:29:18 +0530249 const std::string& ObjPath)
250{
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500251 std::ifstream inventoryJson(jsonFile);
PriyangaRamasamyc0a534f2020-08-24 21:29:18 +0530252 const auto& jsonObject = json::parse(inventoryJson);
253 inventory::VPDfilepath filePath{};
254
255 if (jsonObject.find("frus") == jsonObject.end())
256 {
257 throw(VpdJsonException(
258 "Invalid JSON structure - frus{} object not found in ", jsonFile));
259 }
260
261 const nlohmann::json& groupFRUS =
262 jsonObject["frus"].get_ref<const nlohmann::json::object_t&>();
263 for (const auto& itemFRUS : groupFRUS.items())
264 {
265 const std::vector<nlohmann::json>& groupEEPROM =
266 itemFRUS.value().get_ref<const nlohmann::json::array_t&>();
267 for (const auto& itemEEPROM : groupEEPROM)
268 {
269 if (itemEEPROM["inventoryPath"]
270 .get_ref<const nlohmann::json::string_t&>() == ObjPath)
271 {
272 filePath = itemFRUS.key();
273 return filePath;
274 }
275 }
276 }
277
278 return filePath;
279}
280
281bool isPathInJson(const std::string& eepromPath)
282{
283 bool present = false;
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500284 std::ifstream inventoryJson(INVENTORY_JSON_SYM_LINK);
PriyangaRamasamyc0a534f2020-08-24 21:29:18 +0530285
286 try
287 {
288 auto js = json::parse(inventoryJson);
289 if (js.find("frus") == js.end())
290 {
291 throw(VpdJsonException(
292 "Invalid JSON structure - frus{} object not found in ",
293 INVENTORY_JSON_SYM_LINK));
294 }
295 json fruJson = js["frus"];
296
297 if (fruJson.find(eepromPath) != fruJson.end())
298 {
299 present = true;
300 }
301 }
Patrick Williams8e15b932021-10-06 13:04:22 -0500302 catch (const json::parse_error& ex)
PriyangaRamasamyc0a534f2020-08-24 21:29:18 +0530303 {
304 throw(VpdJsonException("Json Parsing failed", INVENTORY_JSON_SYM_LINK));
305 }
306 return present;
307}
308
309bool isRecKwInDbusJson(const std::string& recordName,
310 const std::string& keyword)
311{
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500312 std::ifstream propertyJson(DBUS_PROP_JSON);
PriyangaRamasamyc0a534f2020-08-24 21:29:18 +0530313 json dbusProperty;
314 bool present = false;
315
316 if (propertyJson.is_open())
317 {
318 try
319 {
320 auto dbusPropertyJson = json::parse(propertyJson);
321 if (dbusPropertyJson.find("dbusProperties") ==
322 dbusPropertyJson.end())
323 {
324 throw(VpdJsonException("dbusProperties{} object not found in "
325 "DbusProperties json : ",
326 DBUS_PROP_JSON));
327 }
328
329 dbusProperty = dbusPropertyJson["dbusProperties"];
330 if (dbusProperty.contains(recordName))
331 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500332 const std::vector<std::string>& kwdsToPublish =
333 dbusProperty[recordName];
PriyangaRamasamyc0a534f2020-08-24 21:29:18 +0530334 if (find(kwdsToPublish.begin(), kwdsToPublish.end(), keyword) !=
335 kwdsToPublish.end()) // present
336 {
337 present = true;
338 }
339 }
340 }
Patrick Williams8e15b932021-10-06 13:04:22 -0500341 catch (const json::parse_error& ex)
PriyangaRamasamyc0a534f2020-08-24 21:29:18 +0530342 {
343 throw(VpdJsonException("Json Parsing failed", DBUS_PROP_JSON));
344 }
345 }
346 else
347 {
348 // If dbus properties json is not available, we assume the given
349 // record-keyword is part of dbus-properties json. So setting the bool
350 // variable to true.
351 present = true;
352 }
353 return present;
354}
355
Sunny Srivastava6c71c9d2021-04-15 04:43:54 -0500356vpdType vpdTypeCheck(const Binary& vpdVector)
357{
358 // Read first 3 Bytes to check the 11S bar code format
359 std::string is11SFormat = "";
360 for (uint8_t i = 0; i < FORMAT_11S_LEN; i++)
361 {
362 is11SFormat += vpdVector[MEMORY_VPD_DATA_START + i];
363 }
364
365 if (vpdVector[IPZ_DATA_START] == KW_VAL_PAIR_START_TAG)
366 {
367 // IPZ VPD FORMAT
368 return vpdType::IPZ_VPD;
369 }
370 else if (vpdVector[KW_VPD_DATA_START] == KW_VPD_START_TAG)
371 {
372 // KEYWORD VPD FORMAT
373 return vpdType::KEYWORD_VPD;
374 }
jinuthomas6555e7e2023-02-14 21:48:00 -0600375 else if (((vpdVector[SPD_BYTE_3] & SPD_BYTE_BIT_0_3_MASK) ==
376 SPD_MODULE_TYPE_DDIMM) &&
jinuthomas0abbb9c2023-05-05 01:37:07 -0500377 (is11SFormat.compare(MEMORY_VPD_START_TAG) == 0))
Sunny Srivastava6c71c9d2021-04-15 04:43:54 -0500378 {
jinuthomas6555e7e2023-02-14 21:48:00 -0600379 // DDIMM Memory VPD format
380 if ((vpdVector[SPD_BYTE_2] & SPD_BYTE_MASK) == SPD_DRAM_TYPE_DDR5)
381 {
382 return vpdType::DDR5_DDIMM_MEMORY_VPD;
383 }
384 else if ((vpdVector[SPD_BYTE_2] & SPD_BYTE_MASK) == SPD_DRAM_TYPE_DDR4)
385 {
386 return vpdType::DDR4_DDIMM_MEMORY_VPD;
387 }
388 }
389 else if ((vpdVector[SPD_BYTE_2] & SPD_BYTE_MASK) == SPD_DRAM_TYPE_DDR5)
390 {
391 // ISDIMM Memory VPD format
392 return vpdType::DDR5_ISDIMM_MEMORY_VPD;
393 }
394 else if ((vpdVector[SPD_BYTE_2] & SPD_BYTE_MASK) == SPD_DRAM_TYPE_DDR4)
395 {
396 // ISDIMM Memory VPD format
397 return vpdType::DDR4_ISDIMM_MEMORY_VPD;
Sunny Srivastava6c71c9d2021-04-15 04:43:54 -0500398 }
399
400 // INVALID VPD FORMAT
401 return vpdType::INVALID_VPD_FORMAT;
402}
403
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500404const std::string getIM(const Parsed& vpdMap)
Alpana Kumarif05effd2021-04-07 07:32:53 -0500405{
406 Binary imVal;
407 auto property = vpdMap.find("VSBP");
408 if (property != vpdMap.end())
409 {
410 auto kw = (property->second).find("IM");
411 if (kw != (property->second).end())
412 {
413 copy(kw->second.begin(), kw->second.end(), back_inserter(imVal));
414 }
415 }
416
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500417 std::ostringstream oss;
Alpana Kumarif05effd2021-04-07 07:32:53 -0500418 for (auto& i : imVal)
419 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500420 oss << std::setw(2) << std::setfill('0') << std::hex
421 << static_cast<int>(i);
Alpana Kumarif05effd2021-04-07 07:32:53 -0500422 }
423
424 return oss.str();
425}
426
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500427const std::string getHW(const Parsed& vpdMap)
Alpana Kumarif05effd2021-04-07 07:32:53 -0500428{
429 Binary hwVal;
430 auto prop = vpdMap.find("VINI");
431 if (prop != vpdMap.end())
432 {
433 auto kw = (prop->second).find("HW");
434 if (kw != (prop->second).end())
435 {
436 copy(kw->second.begin(), kw->second.end(), back_inserter(hwVal));
437 }
438 }
439
Alpana Kumari88d2ae82021-11-10 03:23:31 -0600440 // The planar pass only comes from the LSB of the HW keyword,
441 // where as the MSB is used for other purposes such as signifying clock
442 // termination.
443 hwVal[0] = 0x00;
444
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500445 std::ostringstream hwString;
Alpana Kumarif05effd2021-04-07 07:32:53 -0500446 for (auto& i : hwVal)
447 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500448 hwString << std::setw(2) << std::setfill('0') << std::hex
449 << static_cast<int>(i);
Alpana Kumarif05effd2021-04-07 07:32:53 -0500450 }
451
452 return hwString.str();
453}
454
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500455std::string getSystemsJson(const Parsed& vpdMap)
Alpana Kumarif05effd2021-04-07 07:32:53 -0500456{
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500457 std::string jsonPath = "/usr/share/vpd/";
458 std::string jsonName{};
Alpana Kumarif05effd2021-04-07 07:32:53 -0500459
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500460 std::ifstream systemJson(SYSTEM_JSON);
Alpana Kumarif05effd2021-04-07 07:32:53 -0500461 if (!systemJson)
462 {
463 throw((VpdJsonException("Failed to access Json path", SYSTEM_JSON)));
464 }
465
466 try
467 {
468 auto js = json::parse(systemJson);
469
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500470 std::string hwKeyword = getHW(vpdMap);
471 const std::string imKeyword = getIM(vpdMap);
Alpana Kumarif05effd2021-04-07 07:32:53 -0500472
Alpana Kumari1b026112022-03-02 23:41:38 -0600473 transform(hwKeyword.begin(), hwKeyword.end(), hwKeyword.begin(),
474 ::toupper);
475
Alpana Kumarif05effd2021-04-07 07:32:53 -0500476 if (js.find("system") == js.end())
477 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500478 throw std::runtime_error("Invalid systems Json");
Alpana Kumarif05effd2021-04-07 07:32:53 -0500479 }
480
481 if (js["system"].find(imKeyword) == js["system"].end())
482 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500483 throw std::runtime_error(
Alpana Kumarif05effd2021-04-07 07:32:53 -0500484 "Invalid system. This system type is not present "
485 "in the systemsJson. IM: " +
486 imKeyword);
487 }
488
489 if ((js["system"][imKeyword].find("constraint") !=
490 js["system"][imKeyword].end()) &&
Alpana Kumari1b026112022-03-02 23:41:38 -0600491 js["system"][imKeyword]["constraint"].find("HW") !=
492 js["system"][imKeyword]["constraint"].end())
Alpana Kumarif05effd2021-04-07 07:32:53 -0500493 {
Alpana Kumari1b026112022-03-02 23:41:38 -0600494 // collect hw versions from json, and check hwKeyword is part of it
495 // if hwKeyword is found there then load respective json
496 // otherwise load default one.
497 for (const auto& hwVersion :
498 js["system"][imKeyword]["constraint"]["HW"])
499 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500500 std::string hw = hwVersion;
Alpana Kumari1b026112022-03-02 23:41:38 -0600501 transform(hw.begin(), hw.end(), hw.begin(), ::toupper);
502
503 if (hw == hwKeyword)
504 {
505 jsonName = js["system"][imKeyword]["constraint"]["json"];
506 break;
507 }
508 }
509
510 if (jsonName.empty() && js["system"][imKeyword].find("default") !=
511 js["system"][imKeyword].end())
512 {
513 jsonName = js["system"][imKeyword]["default"];
514 }
Alpana Kumarif05effd2021-04-07 07:32:53 -0500515 }
516 else if (js["system"][imKeyword].find("default") !=
517 js["system"][imKeyword].end())
518 {
519 jsonName = js["system"][imKeyword]["default"];
520 }
521 else
522 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500523 throw std::runtime_error(
Alpana Kumarif05effd2021-04-07 07:32:53 -0500524 "Bad System json. Neither constraint nor default found");
525 }
526
527 jsonPath += jsonName;
528 }
529
Patrick Williams8e15b932021-10-06 13:04:22 -0500530 catch (const json::parse_error& ex)
Alpana Kumarif05effd2021-04-07 07:32:53 -0500531 {
532 throw(VpdJsonException("Json Parsing failed", SYSTEM_JSON));
533 }
534 return jsonPath;
535}
536
jinuthomasf457a3e2023-04-13 12:22:48 -0500537void udevToGenericPath(std::string& file, const std::string& driver)
PriyangaRamasamy647868e2020-09-08 17:03:19 +0530538{
539 // Sample udevEvent i2c path :
540 // "/sys/devices/platform/ahb/ahb:apb/ahb:apb:bus@1e78a000/1e78a480.i2c-bus/i2c-8/8-0051/8-00510/nvmem"
541 // find if the path contains the word i2c in it.
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500542 if (file.find("i2c") != std::string::npos)
PriyangaRamasamy647868e2020-09-08 17:03:19 +0530543 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500544 std::string i2cBusAddr{};
PriyangaRamasamy647868e2020-09-08 17:03:19 +0530545
546 // Every udev i2c path should have the common pattern
547 // "i2c-bus_number/bus_number-vpd_address". Search for
548 // "bus_number-vpd_address".
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500549 std::regex i2cPattern("((i2c)-[0-9]+\\/)([0-9]+-[0-9]{4})");
550 std::smatch match;
551 if (std::regex_search(file, match, i2cPattern))
PriyangaRamasamy647868e2020-09-08 17:03:19 +0530552 {
553 i2cBusAddr = match.str(3);
554 }
555 else
556 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500557 std::cerr << "The given udev path < " << file
558 << " > doesn't match the required pattern. Skipping VPD "
559 "collection."
560 << std::endl;
PriyangaRamasamy647868e2020-09-08 17:03:19 +0530561 exit(EXIT_SUCCESS);
562 }
563 // Forming the generic file path
jinuthomasf457a3e2023-04-13 12:22:48 -0500564 file = i2cPathPrefix + driver + "/" + i2cBusAddr + "/eeprom";
PriyangaRamasamy647868e2020-09-08 17:03:19 +0530565 }
566 // Sample udevEvent spi path :
567 // "/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"
568 // find if the path contains the word spi in it.
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500569 else if (file.find("spi") != std::string::npos)
PriyangaRamasamy647868e2020-09-08 17:03:19 +0530570 {
571 // Every udev spi path will have common pattern "spi<Digit>/", which
572 // describes the spi bus number at which the fru is connected; Followed
573 // by a slash following the vpd address of the fru. Taking the above
574 // input as a common key, we try to search for the pattern "spi<Digit>/"
575 // using regular expression.
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500576 std::regex spiPattern("((spi)[0-9]+)(\\/)");
577 std::string spiBus{};
578 std::smatch match;
579 if (std::regex_search(file, match, spiPattern))
PriyangaRamasamy647868e2020-09-08 17:03:19 +0530580 {
581 spiBus = match.str(1);
582 }
583 else
584 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500585 std::cerr << "The given udev path < " << file
586 << " > doesn't match the required pattern. Skipping VPD "
587 "collection."
588 << std::endl;
PriyangaRamasamy647868e2020-09-08 17:03:19 +0530589 exit(EXIT_SUCCESS);
590 }
591 // Forming the generic path
jinuthomasf457a3e2023-04-13 12:22:48 -0500592 file = spiPathPrefix + driver + "/" + spiBus + ".0/eeprom";
PriyangaRamasamy647868e2020-09-08 17:03:19 +0530593 }
594 else
595 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500596 std::cerr << "\n The given EEPROM path < " << file
597 << " > is not valid. It's neither I2C nor "
598 "SPI path. Skipping VPD collection.."
599 << std::endl;
PriyangaRamasamy647868e2020-09-08 17:03:19 +0530600 exit(EXIT_SUCCESS);
601 }
602}
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500603std::string getBadVpdName(const std::string& file)
PriyangaRamasamyc2fe40f2021-03-02 06:27:33 -0600604{
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500605 std::string badVpd = BAD_VPD_DIR;
606 if (file.find("i2c") != std::string::npos)
PriyangaRamasamyc2fe40f2021-03-02 06:27:33 -0600607 {
608 badVpd += "i2c-";
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500609 std::regex i2cPattern("(at24/)([0-9]+-[0-9]+)\\/");
610 std::smatch match;
611 if (std::regex_search(file, match, i2cPattern))
PriyangaRamasamyc2fe40f2021-03-02 06:27:33 -0600612 {
613 badVpd += match.str(2);
614 }
615 }
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500616 else if (file.find("spi") != std::string::npos)
PriyangaRamasamyc2fe40f2021-03-02 06:27:33 -0600617 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500618 std::regex spiPattern("((spi)[0-9]+)(.0)");
619 std::smatch match;
620 if (std::regex_search(file, match, spiPattern))
PriyangaRamasamyc2fe40f2021-03-02 06:27:33 -0600621 {
622 badVpd += match.str(1);
623 }
624 }
625 return badVpd;
626}
627
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500628void dumpBadVpd(const std::string& file, const Binary& vpdVector)
PriyangaRamasamyc2fe40f2021-03-02 06:27:33 -0600629{
630 fs::path badVpdDir = BAD_VPD_DIR;
631 fs::create_directory(badVpdDir);
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500632 std::string badVpdPath = getBadVpdName(file);
PriyangaRamasamyc2fe40f2021-03-02 06:27:33 -0600633 if (fs::exists(badVpdPath))
634 {
635 std::error_code ec;
636 fs::remove(badVpdPath, ec);
637 if (ec) // error code
638 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500639 std::string error = "Error removing the existing broken vpd in ";
PriyangaRamasamyc2fe40f2021-03-02 06:27:33 -0600640 error += badVpdPath;
641 error += ". Error code : ";
642 error += ec.value();
643 error += ". Error message : ";
644 error += ec.message();
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500645 throw std::runtime_error(error);
PriyangaRamasamyc2fe40f2021-03-02 06:27:33 -0600646 }
647 }
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500648 std::ofstream badVpdFileStream(badVpdPath, std::ofstream::binary);
PriyangaRamasamyc2fe40f2021-03-02 06:27:33 -0600649 if (!badVpdFileStream)
650 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500651 throw std::runtime_error(
652 "Failed to open bad vpd file path in /tmp/bad-vpd. "
653 "Unable to dump the broken/bad vpd file.");
PriyangaRamasamyc2fe40f2021-03-02 06:27:33 -0600654 }
655 badVpdFileStream.write(reinterpret_cast<const char*>(vpdVector.data()),
656 vpdVector.size());
657}
alpana077ce68722021-07-25 13:23:59 -0500658
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500659const std::string getKwVal(const Parsed& vpdMap, const std::string& rec,
660 const std::string& kwd)
alpana077ce68722021-07-25 13:23:59 -0500661{
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500662 std::string kwVal{};
alpana077ce68722021-07-25 13:23:59 -0500663
664 auto findRec = vpdMap.find(rec);
665
666 // check if record is found in map we got by parser
667 if (findRec != vpdMap.end())
668 {
669 auto findKwd = findRec->second.find(kwd);
670
671 if (findKwd != findRec->second.end())
672 {
673 kwVal = findKwd->second;
674 }
675 }
676
677 return kwVal;
678}
679
GiridhariKrishnan63639102023-03-02 05:55:47 -0600680std::string hexString(const std::variant<Binary, std::string>& kw)
Priyanga Ramasamyc9ecf8e2021-10-08 02:28:52 -0500681{
GiridhariKrishnan63639102023-03-02 05:55:47 -0600682 std::string hexString;
683 std::visit(
684 [&hexString](auto&& kw) {
Patrick Williamsc78d8872023-05-10 07:50:56 -0500685 std::stringstream ss;
686 std::string hexRep = "0x";
687 ss << hexRep;
688 for (auto& kwVal : kw)
689 {
690 ss << std::setfill('0') << std::setw(2) << std::hex
691 << static_cast<int>(kwVal);
692 }
693 hexString = ss.str();
GiridhariKrishnan63639102023-03-02 05:55:47 -0600694 },
695 kw);
696 return hexString;
Priyanga Ramasamyc9ecf8e2021-10-08 02:28:52 -0500697}
698
GiridhariKrishnan63639102023-03-02 05:55:47 -0600699std::string getPrintableValue(const std::variant<Binary, std::string>& kwVal)
Priyanga Ramasamy02434932021-10-07 16:26:05 -0500700{
GiridhariKrishnan63639102023-03-02 05:55:47 -0600701 std::string kwString{};
702 std::visit(
703 [&kwString](auto&& kwVal) {
Patrick Williamsc78d8872023-05-10 07:50:56 -0500704 const auto it =
705 std::find_if(kwVal.begin(), kwVal.end(),
706 [](const auto& kw) { return !isprint(kw); });
707 if (it != kwVal.end())
708 {
709 bool printable = true;
710 for (auto itr = it; itr != kwVal.end(); itr++)
Priyanga Ramasamyc9ecf8e2021-10-08 02:28:52 -0500711 {
Patrick Williamsc78d8872023-05-10 07:50:56 -0500712 if (*itr != 0x00)
GiridhariKrishnan63639102023-03-02 05:55:47 -0600713 {
Patrick Williamsc78d8872023-05-10 07:50:56 -0500714 kwString = hexString(kwVal);
715 printable = false;
716 break;
GiridhariKrishnan63639102023-03-02 05:55:47 -0600717 }
Priyanga Ramasamyc9ecf8e2021-10-08 02:28:52 -0500718 }
Patrick Williamsc78d8872023-05-10 07:50:56 -0500719 if (printable)
GiridhariKrishnan63639102023-03-02 05:55:47 -0600720 {
Patrick Williamsc78d8872023-05-10 07:50:56 -0500721 kwString = std::string(kwVal.begin(), it);
GiridhariKrishnan63639102023-03-02 05:55:47 -0600722 }
Patrick Williamsc78d8872023-05-10 07:50:56 -0500723 }
724 else
725 {
726 kwString = std::string(kwVal.begin(), kwVal.end());
727 }
GiridhariKrishnan63639102023-03-02 05:55:47 -0600728 },
729 kwVal);
730 return kwString;
Priyanga Ramasamy02434932021-10-07 16:26:05 -0500731}
732
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500733void executePostFailAction(const nlohmann::json& json, const std::string& file)
Alpana Kumari735dee92022-03-25 01:24:40 -0500734{
735 if ((json["frus"][file].at(0)).find("postActionFail") ==
736 json["frus"][file].at(0).end())
737 {
738 return;
739 }
740
741 uint8_t pinValue = 0;
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500742 std::string pinName;
Alpana Kumari735dee92022-03-25 01:24:40 -0500743
744 for (const auto& postAction :
745 (json["frus"][file].at(0))["postActionFail"].items())
746 {
747 if (postAction.key() == "pin")
748 {
749 pinName = postAction.value();
750 }
751 else if (postAction.key() == "value")
752 {
753 // Get the value to set
754 pinValue = postAction.value();
755 }
756 }
757
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500758 std::cout << "Setting GPIO: " << pinName << " to " << (int)pinValue
759 << std::endl;
Alpana Kumari735dee92022-03-25 01:24:40 -0500760
761 try
762 {
763 gpiod::line outputLine = gpiod::find_line(pinName);
764
765 if (!outputLine)
766 {
Sunny Srivastavaa2ddc962022-06-29 08:53:16 -0500767 throw GpioException(
Alpana Kumari6bd095f2022-02-23 10:20:20 -0600768 "Couldn't find output line for the GPIO. Skipping "
769 "this GPIO action.");
Alpana Kumari735dee92022-03-25 01:24:40 -0500770 }
771 outputLine.request(
772 {"Disable line", ::gpiod::line_request::DIRECTION_OUTPUT, 0},
773 pinValue);
774 }
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500775 catch (const std::exception& e)
Alpana Kumari735dee92022-03-25 01:24:40 -0500776 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500777 std::string i2cBusAddr;
778 std::string errMsg = e.what();
Alpana Kumari6bd095f2022-02-23 10:20:20 -0600779 errMsg += "\nGPIO: " + pinName;
780
781 if ((json["frus"][file].at(0)["postActionFail"].find(
782 "gpioI2CAddress")) !=
783 json["frus"][file].at(0)["postActionFail"].end())
784 {
785 i2cBusAddr =
786 json["frus"][file].at(0)["postActionFail"]["gpioI2CAddress"];
Sunny Srivastavafdf9ff22022-06-15 11:15:54 -0500787 errMsg += " i2cBusAddress: " + i2cBusAddr;
Alpana Kumari6bd095f2022-02-23 10:20:20 -0600788 }
789
Sunny Srivastavaa2ddc962022-06-29 08:53:16 -0500790 throw GpioException(e.what());
Alpana Kumari735dee92022-03-25 01:24:40 -0500791 }
Alpana Kumari6bd095f2022-02-23 10:20:20 -0600792
793 return;
Alpana Kumari735dee92022-03-25 01:24:40 -0500794}
795
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500796std::optional<bool> isPresent(const nlohmann::json& json,
797 const std::string& file)
Santosh Puranik53b38ed2022-04-10 23:15:22 +0530798
Alpana Kumari735dee92022-03-25 01:24:40 -0500799{
800 if ((json["frus"][file].at(0)).find("presence") !=
801 json["frus"][file].at(0).end())
802 {
803 if (((json["frus"][file].at(0)["presence"]).find("pin") !=
804 json["frus"][file].at(0)["presence"].end()) &&
805 ((json["frus"][file].at(0)["presence"]).find("value") !=
806 json["frus"][file].at(0)["presence"].end()))
807 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500808 std::string presPinName =
809 json["frus"][file].at(0)["presence"]["pin"];
Alpana Kumari735dee92022-03-25 01:24:40 -0500810 Byte presPinValue = json["frus"][file].at(0)["presence"]["value"];
811
812 try
813 {
814 gpiod::line presenceLine = gpiod::find_line(presPinName);
815
816 if (!presenceLine)
817 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500818 std::cerr << "Couldn't find the presence line for - "
819 << presPinName << std::endl;
Alpana Kumari40d1c192022-03-09 21:16:02 -0600820
Sunny Srivastavaa2ddc962022-06-29 08:53:16 -0500821 throw GpioException(
Alpana Kumari6bd095f2022-02-23 10:20:20 -0600822 "Couldn't find the presence line for the "
823 "GPIO. Skipping this GPIO action.");
Alpana Kumari735dee92022-03-25 01:24:40 -0500824 }
825
826 presenceLine.request({"Read the presence line",
827 gpiod::line_request::DIRECTION_INPUT, 0});
828
829 Byte gpioData = presenceLine.get_value();
830
Santosh Puranik53b38ed2022-04-10 23:15:22 +0530831 return (gpioData == presPinValue);
Alpana Kumari735dee92022-03-25 01:24:40 -0500832 }
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500833 catch (const std::exception& e)
Alpana Kumari735dee92022-03-25 01:24:40 -0500834 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500835 std::string i2cBusAddr;
836 std::string errMsg = e.what();
Alpana Kumari6bd095f2022-02-23 10:20:20 -0600837 errMsg += " GPIO : " + presPinName;
838
839 if ((json["frus"][file].at(0)["presence"])
840 .find("gpioI2CAddress") !=
841 json["frus"][file].at(0)["presence"].end())
842 {
843 i2cBusAddr =
844 json["frus"][file].at(0)["presence"]["gpioI2CAddress"];
Sunny Srivastavafdf9ff22022-06-15 11:15:54 -0500845 errMsg += " i2cBusAddress: " + i2cBusAddr;
Alpana Kumari6bd095f2022-02-23 10:20:20 -0600846 }
847
Alpana Kumari40d1c192022-03-09 21:16:02 -0600848 // Take failure postAction
849 executePostFailAction(json, file);
Sunny Srivastavaa2ddc962022-06-29 08:53:16 -0500850 throw GpioException(errMsg);
Alpana Kumari735dee92022-03-25 01:24:40 -0500851 }
852 }
Alpana Kumari40d1c192022-03-09 21:16:02 -0600853 else
854 {
855 // missing required informations
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500856 std::cerr
857 << "VPD inventory JSON missing basic informations of presence "
858 "for this FRU : ["
859 << file << "]. Executing executePostFailAction." << std::endl;
Alpana Kumari40d1c192022-03-09 21:16:02 -0600860
861 // Take failure postAction
862 executePostFailAction(json, file);
863
864 return false;
865 }
Alpana Kumari735dee92022-03-25 01:24:40 -0500866 }
Santosh Puranik53b38ed2022-04-10 23:15:22 +0530867 return std::optional<bool>{};
868}
869
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500870bool executePreAction(const nlohmann::json& json, const std::string& file)
Santosh Puranik53b38ed2022-04-10 23:15:22 +0530871{
872 auto present = isPresent(json, file);
873 if (present && !present.value())
874 {
875 executePostFailAction(json, file);
876 return false;
877 }
Alpana Kumari735dee92022-03-25 01:24:40 -0500878
879 if ((json["frus"][file].at(0)).find("preAction") !=
880 json["frus"][file].at(0).end())
881 {
882 if (((json["frus"][file].at(0)["preAction"]).find("pin") !=
883 json["frus"][file].at(0)["preAction"].end()) &&
884 ((json["frus"][file].at(0)["preAction"]).find("value") !=
885 json["frus"][file].at(0)["preAction"].end()))
886 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500887 std::string pinName = json["frus"][file].at(0)["preAction"]["pin"];
Alpana Kumari735dee92022-03-25 01:24:40 -0500888 // Get the value to set
889 Byte pinValue = json["frus"][file].at(0)["preAction"]["value"];
890
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500891 std::cout << "Setting GPIO: " << pinName << " to " << (int)pinValue
892 << std::endl;
Alpana Kumari735dee92022-03-25 01:24:40 -0500893 try
894 {
895 gpiod::line outputLine = gpiod::find_line(pinName);
896
897 if (!outputLine)
898 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500899 std::cerr << "Couldn't find the line for output pin - "
900 << pinName << std::endl;
Sunny Srivastavaa2ddc962022-06-29 08:53:16 -0500901 throw GpioException(
Alpana Kumari6bd095f2022-02-23 10:20:20 -0600902 "Couldn't find output line for the GPIO. "
903 "Skipping this GPIO action.");
Alpana Kumari735dee92022-03-25 01:24:40 -0500904 }
905 outputLine.request({"FRU pre-action",
906 ::gpiod::line_request::DIRECTION_OUTPUT, 0},
907 pinValue);
908 }
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500909 catch (const std::exception& e)
Alpana Kumari735dee92022-03-25 01:24:40 -0500910 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500911 std::string i2cBusAddr;
912 std::string errMsg = e.what();
Alpana Kumari6bd095f2022-02-23 10:20:20 -0600913 errMsg += " GPIO : " + pinName;
914
915 if ((json["frus"][file].at(0)["preAction"])
916 .find("gpioI2CAddress") !=
917 json["frus"][file].at(0)["preAction"].end())
918 {
919 i2cBusAddr =
920 json["frus"][file].at(0)["preAction"]["gpioI2CAddress"];
Sunny Srivastavafdf9ff22022-06-15 11:15:54 -0500921 errMsg += " i2cBusAddress: " + i2cBusAddr;
Alpana Kumari6bd095f2022-02-23 10:20:20 -0600922 }
923
Alpana Kumari40d1c192022-03-09 21:16:02 -0600924 // Take failure postAction
925 executePostFailAction(json, file);
Sunny Srivastavaa2ddc962022-06-29 08:53:16 -0500926 throw GpioException(errMsg);
Alpana Kumari735dee92022-03-25 01:24:40 -0500927 }
928 }
Alpana Kumari40d1c192022-03-09 21:16:02 -0600929 else
930 {
931 // missing required informations
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500932 std::cerr
Alpana Kumari40d1c192022-03-09 21:16:02 -0600933 << "VPD inventory JSON missing basic informations of preAction "
934 "for this FRU : ["
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500935 << file << "]. Executing executePostFailAction." << std::endl;
Alpana Kumari40d1c192022-03-09 21:16:02 -0600936
937 // Take failure postAction
938 executePostFailAction(json, file);
Alpana Kumari40d1c192022-03-09 21:16:02 -0600939 return false;
940 }
Alpana Kumari735dee92022-03-25 01:24:40 -0500941 }
942 return true;
943}
944
Priyanga Ramasamyaa8a8932022-01-27 09:12:41 -0600945void insertOrMerge(inventory::InterfaceMap& map,
946 const inventory::Interface& interface,
947 inventory::PropertyMap&& property)
948{
949 if (map.find(interface) != map.end())
950 {
951 auto& prop = map.at(interface);
952 prop.insert(property.begin(), property.end());
953 }
954 else
955 {
956 map.emplace(interface, property);
957 }
958}
Santosh Puranikf2d3b532022-04-19 06:44:07 -0500959
960BIOSAttrValueType readBIOSAttribute(const std::string& attrName)
961{
962 std::tuple<std::string, BIOSAttrValueType, BIOSAttrValueType> attrVal;
963 auto bus = sdbusplus::bus::new_default();
964 auto method = bus.new_method_call(
965 "xyz.openbmc_project.BIOSConfigManager",
966 "/xyz/openbmc_project/bios_config/manager",
967 "xyz.openbmc_project.BIOSConfig.Manager", "GetAttribute");
968 method.append(attrName);
969 try
970 {
971 auto result = bus.call(method);
972 result.read(std::get<0>(attrVal), std::get<1>(attrVal),
973 std::get<2>(attrVal));
974 }
975 catch (const sdbusplus::exception::SdBusError& e)
976 {
977 std::cerr << "Failed to read BIOS Attribute: " << attrName << std::endl;
978 std::cerr << e.what() << std::endl;
979 }
980 return std::get<1>(attrVal);
981}
Priyanga Ramasamy335873f2022-05-18 01:31:54 -0500982
983std::string getPowerState()
984{
985 // TODO: How do we handle multiple chassis?
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500986 std::string powerState{};
Priyanga Ramasamy335873f2022-05-18 01:31:54 -0500987 auto bus = sdbusplus::bus::new_default();
Patrick Williamsc78d8872023-05-10 07:50:56 -0500988 auto properties = bus.new_method_call("xyz.openbmc_project.State.Chassis",
989 "/xyz/openbmc_project/state/chassis0",
990 "org.freedesktop.DBus.Properties",
991 "Get");
Priyanga Ramasamy335873f2022-05-18 01:31:54 -0500992 properties.append("xyz.openbmc_project.State.Chassis");
993 properties.append("CurrentPowerState");
994 auto result = bus.call(properties);
995 if (!result.is_method_error())
996 {
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500997 std::variant<std::string> val;
Priyanga Ramasamy335873f2022-05-18 01:31:54 -0500998 result.read(val);
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500999 if (auto pVal = std::get_if<std::string>(&val))
Priyanga Ramasamy335873f2022-05-18 01:31:54 -05001000 {
1001 powerState = *pVal;
1002 }
1003 }
Priyanga Ramasamye0084322022-09-27 06:28:33 -05001004 std::cout << "Power state is: " << powerState << std::endl;
Priyanga Ramasamy335873f2022-05-18 01:31:54 -05001005 return powerState;
1006}
Santosh Puranik6b2b5372022-06-02 20:49:02 +05301007
1008Binary getVpdDataInVector(const nlohmann::json& js, const std::string& file)
1009{
1010 uint32_t offset = 0;
1011 // check if offset present?
1012 for (const auto& item : js["frus"][file])
1013 {
1014 if (item.find("offset") != item.end())
1015 {
1016 offset = item["offset"];
1017 }
1018 }
1019
1020 // TODO: Figure out a better way to get max possible VPD size.
1021 auto maxVPDSize = std::min(std::filesystem::file_size(file),
1022 static_cast<uintmax_t>(65504));
1023
1024 Binary vpdVector;
1025 vpdVector.resize(maxVPDSize);
Priyanga Ramasamye0084322022-09-27 06:28:33 -05001026 std::ifstream vpdFile;
1027 vpdFile.open(file, std::ios::binary);
Santosh Puranik6b2b5372022-06-02 20:49:02 +05301028
Priyanga Ramasamye0084322022-09-27 06:28:33 -05001029 vpdFile.seekg(offset, std::ios_base::cur);
Santosh Puranik6b2b5372022-06-02 20:49:02 +05301030 vpdFile.read(reinterpret_cast<char*>(&vpdVector[0]), maxVPDSize);
1031 vpdVector.resize(vpdFile.gcount());
1032
1033 // Make sure we reset the EEPROM pointer to a "safe" location if it was DIMM
1034 // SPD that we just read.
1035 for (const auto& item : js["frus"][file])
1036 {
1037 if (item.find("extraInterfaces") != item.end())
1038 {
1039 if (item["extraInterfaces"].find(
1040 "xyz.openbmc_project.Inventory.Item.Dimm") !=
1041 item["extraInterfaces"].end())
1042 {
1043 // moves the EEPROM pointer to 2048 'th byte.
1044 vpdFile.seekg(2047, std::ios::beg);
1045 // Read that byte and discard - to affirm the move
1046 // operation.
1047 char ch;
1048 vpdFile.read(&ch, sizeof(ch));
1049 break;
1050 }
1051 }
1052 }
1053
1054 return vpdVector;
1055}
Priyanga Ramasamy5629fbc2023-03-01 08:17:19 -06001056
1057std::string getDbusNameForThisKw(const std::string& keyword)
1058{
1059 if (keyword[0] == constants::POUND_KW)
1060 {
1061 return (std::string(constants::POUND_KW_PREFIX) + keyword[1]);
1062 }
1063 else if (isdigit(keyword[0]))
1064 {
1065 return (std::string(constants::NUMERIC_KW_PREFIX) + keyword);
1066 }
1067 return keyword;
1068}
1069
Patrick Venturec83c4dc2018-11-01 16:29:18 -07001070} // namespace vpd
Patrick Williamsc78d8872023-05-10 07:50:56 -05001071} // namespace openpower