blob: c75c0ded4bdde9cc8bb7e06d9f35a88c429633e4 [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
PriyangaRamasamyc2fe40f2021-03-02 06:27:33 -06009#include <filesystem>
PriyangaRamasamyc0a534f2020-08-24 21:29:18 +053010#include <fstream>
Alpana Kumari735dee92022-03-25 01:24:40 -050011#include <gpiod.hpp>
PriyangaRamasamyc0a534f2020-08-24 21:29:18 +053012#include <iomanip>
Sunny Srivastava6c71c9d2021-04-15 04:43:54 -050013#include <nlohmann/json.hpp>
SunnySrivastava19849094d4f2020-08-05 09:32:29 -050014#include <phosphor-logging/elog-errors.hpp>
Patrick Venturec83c4dc2018-11-01 16:29:18 -070015#include <phosphor-logging/log.hpp>
PriyangaRamasamy647868e2020-09-08 17:03:19 +053016#include <regex>
Patrick Venturec83c4dc2018-11-01 16:29:18 -070017#include <sdbusplus/server.hpp>
PriyangaRamasamyc0a534f2020-08-24 21:29:18 +053018#include <sstream>
19#include <vector>
SunnySrivastava19849094d4f2020-08-05 09:32:29 -050020#include <xyz/openbmc_project/Common/error.hpp>
Deepak Kodihalli76794492017-02-16 23:48:18 -060021
PriyangaRamasamyc0a534f2020-08-24 21:29:18 +053022using json = nlohmann::json;
23
Deepak Kodihalli76794492017-02-16 23:48:18 -060024namespace openpower
25{
26namespace vpd
27{
SunnySrivastava1984945a02d2020-05-06 01:55:41 -050028using namespace openpower::vpd::constants;
SunnySrivastava1984a20be8e2020-08-26 02:00:50 -050029using namespace inventory;
30using namespace phosphor::logging;
SunnySrivastava19849094d4f2020-08-05 09:32:29 -050031using namespace sdbusplus::xyz::openbmc_project::Common::Error;
PriyangaRamasamyc0a534f2020-08-24 21:29:18 +053032using namespace record;
33using namespace openpower::vpd::exceptions;
Sunny Srivastava6c71c9d2021-04-15 04:43:54 -050034using namespace common::utility;
Sunny Srivastava0746eee2021-03-22 13:36:54 -050035using Severity = openpower::vpd::constants::PelSeverity;
PriyangaRamasamyc2fe40f2021-03-02 06:27:33 -060036namespace fs = std::filesystem;
Sunny Srivastava0746eee2021-03-22 13:36:54 -050037
38// mapping of severity enum to severity interface
39static std::unordered_map<Severity, std::string> sevMap = {
40 {Severity::INFORMATIONAL,
41 "xyz.openbmc_project.Logging.Entry.Level.Informational"},
42 {Severity::DEBUG, "xyz.openbmc_project.Logging.Entry.Level.Debug"},
43 {Severity::NOTICE, "xyz.openbmc_project.Logging.Entry.Level.Notice"},
44 {Severity::WARNING, "xyz.openbmc_project.Logging.Entry.Level.Warning"},
45 {Severity::CRITICAL, "xyz.openbmc_project.Logging.Entry.Level.Critical"},
46 {Severity::EMERGENCY, "xyz.openbmc_project.Logging.Entry.Level.Emergency"},
47 {Severity::ERROR, "xyz.openbmc_project.Logging.Entry.Level.Error"},
48 {Severity::ALERT, "xyz.openbmc_project.Logging.Entry.Level.Alert"}};
49
Deepak Kodihalli76794492017-02-16 23:48:18 -060050namespace inventory
51{
52
SunnySrivastava19849094d4f2020-08-05 09:32:29 -050053MapperResponse
54 getObjectSubtreeForInterfaces(const std::string& root, const int32_t depth,
55 const std::vector<std::string>& interfaces)
56{
57 auto bus = sdbusplus::bus::new_default();
58 auto mapperCall = bus.new_method_call(mapperDestination, mapperObjectPath,
59 mapperInterface, "GetSubTree");
60 mapperCall.append(root);
61 mapperCall.append(depth);
62 mapperCall.append(interfaces);
63
64 MapperResponse result = {};
65
66 try
67 {
68 auto response = bus.call(mapperCall);
69
70 response.read(result);
71 }
Patrick Williams8be43342021-09-02 09:33:36 -050072 catch (const sdbusplus::exception::exception& e)
SunnySrivastava19849094d4f2020-08-05 09:32:29 -050073 {
74 log<level::ERR>("Error in mapper GetSubTree",
75 entry("ERROR=%s", e.what()));
76 }
77
78 return result;
79}
80
Deepak Kodihalli76794492017-02-16 23:48:18 -060081} // namespace inventory
82
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -060083LE2ByteData readUInt16LE(Binary::const_iterator iterator)
84{
85 LE2ByteData lowByte = *iterator;
86 LE2ByteData highByte = *(iterator + 1);
87 lowByte |= (highByte << 8);
88 return lowByte;
89}
90
SunnySrivastava1984d076da82020-03-05 05:33:35 -060091/** @brief Encodes a keyword for D-Bus.
92 */
93string encodeKeyword(const string& kw, const string& encoding)
94{
95 if (encoding == "MAC")
96 {
97 string res{};
98 size_t first = kw[0];
99 res += toHex(first >> 4);
100 res += toHex(first & 0x0f);
101 for (size_t i = 1; i < kw.size(); ++i)
102 {
103 res += ":";
104 res += toHex(kw[i] >> 4);
105 res += toHex(kw[i] & 0x0f);
106 }
107 return res;
108 }
109 else if (encoding == "DATE")
110 {
111 // Date, represent as
112 // <year>-<month>-<day> <hour>:<min>
113 string res{};
114 static constexpr uint8_t skipPrefix = 3;
115
116 auto strItr = kw.begin();
117 advance(strItr, skipPrefix);
118 for_each(strItr, kw.end(), [&res](size_t c) { res += c; });
119
120 res.insert(BD_YEAR_END, 1, '-');
121 res.insert(BD_MONTH_END, 1, '-');
122 res.insert(BD_DAY_END, 1, ' ');
123 res.insert(BD_HOUR_END, 1, ':');
124
125 return res;
126 }
127 else // default to string encoding
128 {
129 return string(kw.begin(), kw.end());
130 }
131}
SunnySrivastava198443306542020-04-01 02:50:20 -0500132
133string readBusProperty(const string& obj, const string& inf, const string& prop)
134{
135 std::string propVal{};
136 std::string object = INVENTORY_PATH + obj;
137 auto bus = sdbusplus::bus::new_default();
138 auto properties = bus.new_method_call(
139 "xyz.openbmc_project.Inventory.Manager", object.c_str(),
140 "org.freedesktop.DBus.Properties", "Get");
141 properties.append(inf);
142 properties.append(prop);
143 auto result = bus.call(properties);
144 if (!result.is_method_error())
145 {
SunnySrivastava1984bca5aaa2020-04-21 05:31:04 -0500146 variant<Binary, string> val;
SunnySrivastava198443306542020-04-01 02:50:20 -0500147 result.read(val);
SunnySrivastava198443306542020-04-01 02:50:20 -0500148 if (auto pVal = get_if<Binary>(&val))
149 {
150 propVal.assign(reinterpret_cast<const char*>(pVal->data()),
151 pVal->size());
152 }
SunnySrivastava1984bca5aaa2020-04-21 05:31:04 -0500153 else if (auto pVal = get_if<string>(&val))
154 {
155 propVal.assign(pVal->data(), pVal->size());
156 }
SunnySrivastava198443306542020-04-01 02:50:20 -0500157 }
158 return propVal;
159}
SunnySrivastava1984a20be8e2020-08-26 02:00:50 -0500160
161void createPEL(const std::map<std::string, std::string>& additionalData,
Sunny Srivastava0746eee2021-03-22 13:36:54 -0500162 const Severity& sev, const std::string& errIntf)
SunnySrivastava1984a20be8e2020-08-26 02:00:50 -0500163{
164 try
165 {
Sunny Srivastava0746eee2021-03-22 13:36:54 -0500166 std::string pelSeverity =
167 "xyz.openbmc_project.Logging.Entry.Level.Error";
SunnySrivastava1984a20be8e2020-08-26 02:00:50 -0500168 auto bus = sdbusplus::bus::new_default();
SunnySrivastava1984a20be8e2020-08-26 02:00:50 -0500169 auto service = getService(bus, loggerObjectPath, loggerCreateInterface);
170 auto method = bus.new_method_call(service.c_str(), loggerObjectPath,
171 loggerCreateInterface, "Create");
172
Sunny Srivastava0746eee2021-03-22 13:36:54 -0500173 auto itr = sevMap.find(sev);
174 if (itr != sevMap.end())
175 {
176 pelSeverity = itr->second;
177 }
178
179 method.append(errIntf, pelSeverity, additionalData);
SunnySrivastava1984a20be8e2020-08-26 02:00:50 -0500180 auto resp = bus.call(method);
181 }
Patrick Williams8be43342021-09-02 09:33:36 -0500182 catch (const sdbusplus::exception::exception& e)
SunnySrivastava1984a20be8e2020-08-26 02:00:50 -0500183 {
184 throw std::runtime_error(
185 "Error in invoking D-Bus logging create interface to register PEL");
186 }
187}
PriyangaRamasamyc0a534f2020-08-24 21:29:18 +0530188
189inventory::VPDfilepath getVpdFilePath(const string& jsonFile,
190 const std::string& ObjPath)
191{
192 ifstream inventoryJson(jsonFile);
193 const auto& jsonObject = json::parse(inventoryJson);
194 inventory::VPDfilepath filePath{};
195
196 if (jsonObject.find("frus") == jsonObject.end())
197 {
198 throw(VpdJsonException(
199 "Invalid JSON structure - frus{} object not found in ", jsonFile));
200 }
201
202 const nlohmann::json& groupFRUS =
203 jsonObject["frus"].get_ref<const nlohmann::json::object_t&>();
204 for (const auto& itemFRUS : groupFRUS.items())
205 {
206 const std::vector<nlohmann::json>& groupEEPROM =
207 itemFRUS.value().get_ref<const nlohmann::json::array_t&>();
208 for (const auto& itemEEPROM : groupEEPROM)
209 {
210 if (itemEEPROM["inventoryPath"]
211 .get_ref<const nlohmann::json::string_t&>() == ObjPath)
212 {
213 filePath = itemFRUS.key();
214 return filePath;
215 }
216 }
217 }
218
219 return filePath;
220}
221
222bool isPathInJson(const std::string& eepromPath)
223{
224 bool present = false;
225 ifstream inventoryJson(INVENTORY_JSON_SYM_LINK);
226
227 try
228 {
229 auto js = json::parse(inventoryJson);
230 if (js.find("frus") == js.end())
231 {
232 throw(VpdJsonException(
233 "Invalid JSON structure - frus{} object not found in ",
234 INVENTORY_JSON_SYM_LINK));
235 }
236 json fruJson = js["frus"];
237
238 if (fruJson.find(eepromPath) != fruJson.end())
239 {
240 present = true;
241 }
242 }
Patrick Williams8e15b932021-10-06 13:04:22 -0500243 catch (const json::parse_error& ex)
PriyangaRamasamyc0a534f2020-08-24 21:29:18 +0530244 {
245 throw(VpdJsonException("Json Parsing failed", INVENTORY_JSON_SYM_LINK));
246 }
247 return present;
248}
249
250bool isRecKwInDbusJson(const std::string& recordName,
251 const std::string& keyword)
252{
253 ifstream propertyJson(DBUS_PROP_JSON);
254 json dbusProperty;
255 bool present = false;
256
257 if (propertyJson.is_open())
258 {
259 try
260 {
261 auto dbusPropertyJson = json::parse(propertyJson);
262 if (dbusPropertyJson.find("dbusProperties") ==
263 dbusPropertyJson.end())
264 {
265 throw(VpdJsonException("dbusProperties{} object not found in "
266 "DbusProperties json : ",
267 DBUS_PROP_JSON));
268 }
269
270 dbusProperty = dbusPropertyJson["dbusProperties"];
271 if (dbusProperty.contains(recordName))
272 {
273 const vector<string>& kwdsToPublish = dbusProperty[recordName];
274 if (find(kwdsToPublish.begin(), kwdsToPublish.end(), keyword) !=
275 kwdsToPublish.end()) // present
276 {
277 present = true;
278 }
279 }
280 }
Patrick Williams8e15b932021-10-06 13:04:22 -0500281 catch (const json::parse_error& ex)
PriyangaRamasamyc0a534f2020-08-24 21:29:18 +0530282 {
283 throw(VpdJsonException("Json Parsing failed", DBUS_PROP_JSON));
284 }
285 }
286 else
287 {
288 // If dbus properties json is not available, we assume the given
289 // record-keyword is part of dbus-properties json. So setting the bool
290 // variable to true.
291 present = true;
292 }
293 return present;
294}
295
Sunny Srivastava6c71c9d2021-04-15 04:43:54 -0500296vpdType vpdTypeCheck(const Binary& vpdVector)
297{
298 // Read first 3 Bytes to check the 11S bar code format
299 std::string is11SFormat = "";
300 for (uint8_t i = 0; i < FORMAT_11S_LEN; i++)
301 {
302 is11SFormat += vpdVector[MEMORY_VPD_DATA_START + i];
303 }
304
305 if (vpdVector[IPZ_DATA_START] == KW_VAL_PAIR_START_TAG)
306 {
307 // IPZ VPD FORMAT
308 return vpdType::IPZ_VPD;
309 }
310 else if (vpdVector[KW_VPD_DATA_START] == KW_VPD_START_TAG)
311 {
312 // KEYWORD VPD FORMAT
313 return vpdType::KEYWORD_VPD;
314 }
315 else if (is11SFormat.compare(MEMORY_VPD_START_TAG) == 0)
316 {
317 // Memory VPD format
318 return vpdType::MEMORY_VPD;
319 }
320
321 // INVALID VPD FORMAT
322 return vpdType::INVALID_VPD_FORMAT;
323}
324
Alpana Kumarif05effd2021-04-07 07:32:53 -0500325const string getIM(const Parsed& vpdMap)
326{
327 Binary imVal;
328 auto property = vpdMap.find("VSBP");
329 if (property != vpdMap.end())
330 {
331 auto kw = (property->second).find("IM");
332 if (kw != (property->second).end())
333 {
334 copy(kw->second.begin(), kw->second.end(), back_inserter(imVal));
335 }
336 }
337
338 ostringstream oss;
339 for (auto& i : imVal)
340 {
341 oss << setw(2) << setfill('0') << hex << static_cast<int>(i);
342 }
343
344 return oss.str();
345}
346
347const string getHW(const Parsed& vpdMap)
348{
349 Binary hwVal;
350 auto prop = vpdMap.find("VINI");
351 if (prop != vpdMap.end())
352 {
353 auto kw = (prop->second).find("HW");
354 if (kw != (prop->second).end())
355 {
356 copy(kw->second.begin(), kw->second.end(), back_inserter(hwVal));
357 }
358 }
359
Alpana Kumari88d2ae82021-11-10 03:23:31 -0600360 // The planar pass only comes from the LSB of the HW keyword,
361 // where as the MSB is used for other purposes such as signifying clock
362 // termination.
363 hwVal[0] = 0x00;
364
Alpana Kumarif05effd2021-04-07 07:32:53 -0500365 ostringstream hwString;
366 for (auto& i : hwVal)
367 {
368 hwString << setw(2) << setfill('0') << hex << static_cast<int>(i);
369 }
370
371 return hwString.str();
372}
373
374string getSystemsJson(const Parsed& vpdMap)
375{
376 string jsonPath = "/usr/share/vpd/";
377 string jsonName{};
378
379 ifstream systemJson(SYSTEM_JSON);
380 if (!systemJson)
381 {
382 throw((VpdJsonException("Failed to access Json path", SYSTEM_JSON)));
383 }
384
385 try
386 {
387 auto js = json::parse(systemJson);
388
389 const string hwKeyword = getHW(vpdMap);
390 const string imKeyword = getIM(vpdMap);
391
392 if (js.find("system") == js.end())
393 {
394 throw runtime_error("Invalid systems Json");
395 }
396
397 if (js["system"].find(imKeyword) == js["system"].end())
398 {
399 throw runtime_error(
400 "Invalid system. This system type is not present "
401 "in the systemsJson. IM: " +
402 imKeyword);
403 }
404
405 if ((js["system"][imKeyword].find("constraint") !=
406 js["system"][imKeyword].end()) &&
407 (hwKeyword == js["system"][imKeyword]["constraint"]["HW"]))
408 {
409 jsonName = js["system"][imKeyword]["constraint"]["json"];
410 }
411 else if (js["system"][imKeyword].find("default") !=
412 js["system"][imKeyword].end())
413 {
414 jsonName = js["system"][imKeyword]["default"];
415 }
416 else
417 {
418 throw runtime_error(
419 "Bad System json. Neither constraint nor default found");
420 }
421
422 jsonPath += jsonName;
423 }
424
Patrick Williams8e15b932021-10-06 13:04:22 -0500425 catch (const json::parse_error& ex)
Alpana Kumarif05effd2021-04-07 07:32:53 -0500426 {
427 throw(VpdJsonException("Json Parsing failed", SYSTEM_JSON));
428 }
429 return jsonPath;
430}
431
PriyangaRamasamy647868e2020-09-08 17:03:19 +0530432void udevToGenericPath(string& file)
433{
434 // Sample udevEvent i2c path :
435 // "/sys/devices/platform/ahb/ahb:apb/ahb:apb:bus@1e78a000/1e78a480.i2c-bus/i2c-8/8-0051/8-00510/nvmem"
436 // find if the path contains the word i2c in it.
437 if (file.find("i2c") != string::npos)
438 {
439 string i2cBusAddr{};
440
441 // Every udev i2c path should have the common pattern
442 // "i2c-bus_number/bus_number-vpd_address". Search for
443 // "bus_number-vpd_address".
444 regex i2cPattern("((i2c)-[0-9]+\\/)([0-9]+-[0-9]{4})");
445 smatch match;
446 if (regex_search(file, match, i2cPattern))
447 {
448 i2cBusAddr = match.str(3);
449 }
450 else
451 {
452 cerr << "The given udev path < " << file
453 << " > doesn't match the required pattern. Skipping VPD "
454 "collection."
455 << endl;
456 exit(EXIT_SUCCESS);
457 }
458 // Forming the generic file path
459 file = i2cPathPrefix + i2cBusAddr + "/eeprom";
460 }
461 // Sample udevEvent spi path :
462 // "/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"
463 // find if the path contains the word spi in it.
464 else if (file.find("spi") != string::npos)
465 {
466 // Every udev spi path will have common pattern "spi<Digit>/", which
467 // describes the spi bus number at which the fru is connected; Followed
468 // by a slash following the vpd address of the fru. Taking the above
469 // input as a common key, we try to search for the pattern "spi<Digit>/"
470 // using regular expression.
471 regex spiPattern("((spi)[0-9]+)(\\/)");
472 string spiBus{};
473 smatch match;
474 if (regex_search(file, match, spiPattern))
475 {
476 spiBus = match.str(1);
477 }
478 else
479 {
480 cerr << "The given udev path < " << file
481 << " > doesn't match the required pattern. Skipping VPD "
482 "collection."
483 << endl;
484 exit(EXIT_SUCCESS);
485 }
486 // Forming the generic path
487 file = spiPathPrefix + spiBus + ".0/eeprom";
488 }
489 else
490 {
491 cerr << "\n The given EEPROM path < " << file
492 << " > is not valid. It's neither I2C nor "
493 "SPI path. Skipping VPD collection.."
494 << endl;
495 exit(EXIT_SUCCESS);
496 }
497}
PriyangaRamasamyc2fe40f2021-03-02 06:27:33 -0600498string getBadVpdName(const string& file)
499{
500 string badVpd = BAD_VPD_DIR;
501 if (file.find("i2c") != string::npos)
502 {
503 badVpd += "i2c-";
504 regex i2cPattern("(at24/)([0-9]+-[0-9]+)\\/");
505 smatch match;
506 if (regex_search(file, match, i2cPattern))
507 {
508 badVpd += match.str(2);
509 }
510 }
511 else if (file.find("spi") != string::npos)
512 {
513 regex spiPattern("((spi)[0-9]+)(.0)");
514 smatch match;
515 if (regex_search(file, match, spiPattern))
516 {
517 badVpd += match.str(1);
518 }
519 }
520 return badVpd;
521}
522
523void dumpBadVpd(const string& file, const Binary& vpdVector)
524{
525 fs::path badVpdDir = BAD_VPD_DIR;
526 fs::create_directory(badVpdDir);
527 string badVpdPath = getBadVpdName(file);
528 if (fs::exists(badVpdPath))
529 {
530 std::error_code ec;
531 fs::remove(badVpdPath, ec);
532 if (ec) // error code
533 {
534 string error = "Error removing the existing broken vpd in ";
535 error += badVpdPath;
536 error += ". Error code : ";
537 error += ec.value();
538 error += ". Error message : ";
539 error += ec.message();
540 throw runtime_error(error);
541 }
542 }
543 ofstream badVpdFileStream(badVpdPath, ofstream::binary);
544 if (!badVpdFileStream)
545 {
546 throw runtime_error("Failed to open bad vpd file path in /tmp/bad-vpd. "
547 "Unable to dump the broken/bad vpd file.");
548 }
549 badVpdFileStream.write(reinterpret_cast<const char*>(vpdVector.data()),
550 vpdVector.size());
551}
alpana077ce68722021-07-25 13:23:59 -0500552
553const string getKwVal(const Parsed& vpdMap, const string& rec,
554 const string& kwd)
555{
556 string kwVal{};
557
558 auto findRec = vpdMap.find(rec);
559
560 // check if record is found in map we got by parser
561 if (findRec != vpdMap.end())
562 {
563 auto findKwd = findRec->second.find(kwd);
564
565 if (findKwd != findRec->second.end())
566 {
567 kwVal = findKwd->second;
568 }
569 }
570
571 return kwVal;
572}
573
Priyanga Ramasamyc9ecf8e2021-10-08 02:28:52 -0500574string byteArrayToHexString(const Binary& vec)
575{
576 stringstream ss;
577 string hexRep = "0x";
578 ss << hexRep;
579 string str = ss.str();
580
581 // convert Decimal to Hex string
582 for (auto& v : vec)
583 {
584 ss << setfill('0') << setw(2) << hex << (int)v;
585 str = ss.str();
586 }
587 return str;
588}
589
590string getPrintableValue(const Binary& vec)
Priyanga Ramasamy02434932021-10-07 16:26:05 -0500591{
592 string str{};
Priyanga Ramasamy02434932021-10-07 16:26:05 -0500593
Priyanga Ramasamyc9ecf8e2021-10-08 02:28:52 -0500594 // find for a non printable value in the vector
595 const auto it = std::find_if(vec.begin(), vec.end(),
596 [](const auto& ele) { return !isprint(ele); });
Priyanga Ramasamy02434932021-10-07 16:26:05 -0500597
Priyanga Ramasamyc9ecf8e2021-10-08 02:28:52 -0500598 if (it != vec.end()) // if the given vector has any non printable value
599 {
600 for (auto itr = it; itr != vec.end(); itr++)
Priyanga Ramasamy02434932021-10-07 16:26:05 -0500601 {
Priyanga Ramasamyc9ecf8e2021-10-08 02:28:52 -0500602 if (*itr != 0x00)
603 {
604 str = byteArrayToHexString(vec);
605 return str;
606 }
Priyanga Ramasamy02434932021-10-07 16:26:05 -0500607 }
Priyanga Ramasamyc9ecf8e2021-10-08 02:28:52 -0500608 str = string(vec.begin(), it);
Priyanga Ramasamy02434932021-10-07 16:26:05 -0500609 }
610 else
611 {
612 str = string(vec.begin(), vec.end());
613 }
614 return str;
615}
616
Alpana Kumari735dee92022-03-25 01:24:40 -0500617void executePostFailAction(const nlohmann::json& json, const string& file)
618{
619 if ((json["frus"][file].at(0)).find("postActionFail") ==
620 json["frus"][file].at(0).end())
621 {
622 return;
623 }
624
625 uint8_t pinValue = 0;
626 string pinName;
627
628 for (const auto& postAction :
629 (json["frus"][file].at(0))["postActionFail"].items())
630 {
631 if (postAction.key() == "pin")
632 {
633 pinName = postAction.value();
634 }
635 else if (postAction.key() == "value")
636 {
637 // Get the value to set
638 pinValue = postAction.value();
639 }
640 }
641
642 cout << "Setting GPIO: " << pinName << " to " << (int)pinValue << endl;
643
644 try
645 {
646 gpiod::line outputLine = gpiod::find_line(pinName);
647
648 if (!outputLine)
649 {
650 cout << "Couldn't find output line:" << pinName
651 << " on GPIO. Skipping...\n";
652
653 return;
654 }
655 outputLine.request(
656 {"Disable line", ::gpiod::line_request::DIRECTION_OUTPUT, 0},
657 pinValue);
658 }
659 catch (const system_error&)
660 {
661 cerr << "Failed to set post-action GPIO" << endl;
662 }
663}
664
Santosh Puranik53b38ed2022-04-10 23:15:22 +0530665std::optional<bool> isPresent(const nlohmann::json& json, const string& file)
666
Alpana Kumari735dee92022-03-25 01:24:40 -0500667{
668 if ((json["frus"][file].at(0)).find("presence") !=
669 json["frus"][file].at(0).end())
670 {
671 if (((json["frus"][file].at(0)["presence"]).find("pin") !=
672 json["frus"][file].at(0)["presence"].end()) &&
673 ((json["frus"][file].at(0)["presence"]).find("value") !=
674 json["frus"][file].at(0)["presence"].end()))
675 {
676 string presPinName = json["frus"][file].at(0)["presence"]["pin"];
677 Byte presPinValue = json["frus"][file].at(0)["presence"]["value"];
678
679 try
680 {
681 gpiod::line presenceLine = gpiod::find_line(presPinName);
682
683 if (!presenceLine)
684 {
685 cerr << "couldn't find presence line:" << presPinName
686 << "\n";
Alpana Kumari735dee92022-03-25 01:24:40 -0500687 return false;
688 }
689
690 presenceLine.request({"Read the presence line",
691 gpiod::line_request::DIRECTION_INPUT, 0});
692
693 Byte gpioData = presenceLine.get_value();
694
Santosh Puranik53b38ed2022-04-10 23:15:22 +0530695 return (gpioData == presPinValue);
Alpana Kumari735dee92022-03-25 01:24:40 -0500696 }
697 catch (system_error&)
698 {
699 cerr << "Failed to get the presence GPIO for - " << presPinName
700 << endl;
Alpana Kumari735dee92022-03-25 01:24:40 -0500701 return false;
702 }
703 }
704 }
Santosh Puranik53b38ed2022-04-10 23:15:22 +0530705 return std::optional<bool>{};
706}
707
708bool executePreAction(const nlohmann::json& json, const string& file)
709{
710 auto present = isPresent(json, file);
711 if (present && !present.value())
712 {
713 executePostFailAction(json, file);
714 return false;
715 }
Alpana Kumari735dee92022-03-25 01:24:40 -0500716
717 if ((json["frus"][file].at(0)).find("preAction") !=
718 json["frus"][file].at(0).end())
719 {
720 if (((json["frus"][file].at(0)["preAction"]).find("pin") !=
721 json["frus"][file].at(0)["preAction"].end()) &&
722 ((json["frus"][file].at(0)["preAction"]).find("value") !=
723 json["frus"][file].at(0)["preAction"].end()))
724 {
725 string pinName = json["frus"][file].at(0)["preAction"]["pin"];
726 // Get the value to set
727 Byte pinValue = json["frus"][file].at(0)["preAction"]["value"];
728
729 cout << "Setting GPIO: " << pinName << " to " << (int)pinValue
730 << endl;
731 try
732 {
733 gpiod::line outputLine = gpiod::find_line(pinName);
734
735 if (!outputLine)
736 {
737 cout << "Couldn't find output line:" << pinName
738 << " on GPIO. Skipping...\n";
739
740 return false;
741 }
742 outputLine.request({"FRU pre-action",
743 ::gpiod::line_request::DIRECTION_OUTPUT, 0},
744 pinValue);
745 }
746 catch (system_error&)
747 {
748 cerr << "Failed to set pre-action for GPIO - " << pinName
749 << endl;
750 return false;
751 }
752 }
753 }
754 return true;
755}
756
Priyanga Ramasamyaa8a8932022-01-27 09:12:41 -0600757void insertOrMerge(inventory::InterfaceMap& map,
758 const inventory::Interface& interface,
759 inventory::PropertyMap&& property)
760{
761 if (map.find(interface) != map.end())
762 {
763 auto& prop = map.at(interface);
764 prop.insert(property.begin(), property.end());
765 }
766 else
767 {
768 map.emplace(interface, property);
769 }
770}
Patrick Venturec83c4dc2018-11-01 16:29:18 -0700771} // namespace vpd
Alpana Kumari735dee92022-03-25 01:24:40 -0500772} // namespace openpower