blob: c4d983812a33f9772a8454948d0483b9a332f9b5 [file] [log] [blame]
SunnySrivastava1984b59fd092020-02-03 09:58:56 -06001#include "config.h"
2
3#include "manager.hpp"
4
Santosh Puranikbf78ed82022-04-20 13:17:04 +05305#include "common_utility.hpp"
SunnySrivastava1984d076da82020-03-05 05:33:35 -06006#include "editor_impl.hpp"
Sunny Srivastava6c71c9d2021-04-15 04:43:54 -05007#include "ibm_vpd_utils.hpp"
SunnySrivastava1984e12b1812020-05-26 02:23:11 -05008#include "ipz_parser.hpp"
Santosh Puranik6b2b5372022-06-02 20:49:02 +05309#include "parser_factory.hpp"
SunnySrivastava1984bca5aaa2020-04-21 05:31:04 -050010#include "reader_impl.hpp"
SunnySrivastava19849a195542020-09-07 06:04:50 -050011#include "vpd_exceptions.hpp"
12
Santosh Puranikd40e42d2022-03-23 13:58:06 +053013#include <filesystem>
SunnySrivastava19849a195542020-09-07 06:04:50 -050014#include <phosphor-logging/elog-errors.hpp>
Sunny Srivastava28abd6e2021-07-28 02:58:28 -050015#include <xyz/openbmc_project/Common/error.hpp>
SunnySrivastava1984b59fd092020-02-03 09:58:56 -060016
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -060017using namespace openpower::vpd::constants;
SunnySrivastava19841356d7e2020-04-24 04:29:35 -050018using namespace openpower::vpd::inventory;
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -060019using namespace openpower::vpd::manager::editor;
SunnySrivastava1984bca5aaa2020-04-21 05:31:04 -050020using namespace openpower::vpd::manager::reader;
SunnySrivastava19849a195542020-09-07 06:04:50 -050021using namespace std;
22using namespace openpower::vpd::parser;
Santosh Puranik6b2b5372022-06-02 20:49:02 +053023using namespace openpower::vpd::parser::factory;
24using namespace openpower::vpd::ipz::parser;
SunnySrivastava19849a195542020-09-07 06:04:50 -050025using namespace openpower::vpd::exceptions;
26using namespace phosphor::logging;
SunnySrivastava1984b59fd092020-02-03 09:58:56 -060027
28namespace openpower
29{
30namespace vpd
31{
32namespace manager
33{
Sunny Srivastava523af2e2022-02-14 07:30:10 -060034Manager::Manager(std::shared_ptr<boost::asio::io_context>& ioCon,
35 std::shared_ptr<sdbusplus::asio::dbus_interface>& iFace,
36 std::shared_ptr<sdbusplus::asio::connection>& conn) :
37 ioContext(ioCon),
38 interface(iFace), conn(conn)
SunnySrivastava1984b59fd092020-02-03 09:58:56 -060039{
Sunny Srivastava523af2e2022-02-14 07:30:10 -060040 interface->register_method(
41 "WriteKeyword",
42 [this](const sdbusplus::message::object_path& path,
43 const std::string& recordName, const std::string& keyword,
44 const Binary& value) {
45 this->writeKeyword(path, recordName, keyword, value);
46 });
47
48 interface->register_method(
49 "GetFRUsByUnexpandedLocationCode",
50 [this](const std::string& locationCode,
51 const uint16_t nodeNumber) -> inventory::ListOfPaths {
52 return this->getFRUsByUnexpandedLocationCode(locationCode,
53 nodeNumber);
54 });
55
56 interface->register_method(
57 "GetFRUsByExpandedLocationCode",
58 [this](const std::string& locationCode) -> inventory::ListOfPaths {
59 return this->getFRUsByExpandedLocationCode(locationCode);
60 });
61
62 interface->register_method(
63 "GetExpandedLocationCode",
64 [this](const std::string& locationCode,
65 const uint16_t nodeNumber) -> std::string {
66 return this->getExpandedLocationCode(locationCode, nodeNumber);
67 });
68
69 interface->register_method("PerformVPDRecollection",
70 [this]() { this->performVPDRecollection(); });
71
Sunny Srivastava28abd6e2021-07-28 02:58:28 -050072 interface->register_method(
73 "deleteFRUVPD", [this](const sdbusplus::message::object_path& path) {
74 this->deleteFRUVPD(path);
75 });
76
Sunny Srivastava6a1bd392021-06-02 04:39:24 -050077 interface->register_method(
78 "CollectFRUVPD", [this](const sdbusplus::message::object_path& path) {
79 this->collectFRUVPD(path);
80 });
81
Sunny Srivastavafdf9ff22022-06-15 11:15:54 -050082 sd_bus_default(&sdBus);
Sunny Srivastava523af2e2022-02-14 07:30:10 -060083 initManager();
SunnySrivastava1984b59fd092020-02-03 09:58:56 -060084}
85
Sunny Srivastava523af2e2022-02-14 07:30:10 -060086void Manager::initManager()
SunnySrivastava1984b59fd092020-02-03 09:58:56 -060087{
SunnySrivastava1984de3c60d2020-02-03 10:34:33 -060088 try
89 {
90 processJSON();
Santosh Puranik6b2b5372022-06-02 20:49:02 +053091 restoreSystemVpd();
Sunny Srivastavaecb5c7d2021-09-02 07:20:24 -050092 listenHostState();
Santosh Puranikb62f6052022-04-06 18:37:54 +053093 listenAssetTag();
Alpana Kumarib17dd3b2020-10-01 00:18:10 -050094
Santosh Puranikf2d3b532022-04-19 06:44:07 -050095 // Create an instance of the BIOS handler
Sunny Srivastava523af2e2022-02-14 07:30:10 -060096 biosHandler = std::make_shared<BiosHandler>(conn, *this);
Santosh Puranikf2d3b532022-04-19 06:44:07 -050097
Sunny Srivastava523af2e2022-02-14 07:30:10 -060098 // instantiate gpioMonitor class
99 gpioMon = std::make_shared<GpioMonitor>(jsonFile, ioContext);
SunnySrivastava1984de3c60d2020-02-03 10:34:33 -0600100 }
101 catch (const std::exception& e)
102 {
103 std::cerr << e.what() << "\n";
104 }
SunnySrivastava1984de3c60d2020-02-03 10:34:33 -0600105}
106
Santosh Puranik6b2b5372022-06-02 20:49:02 +0530107/**
108 * @brief An api to get list of blank system VPD properties.
109 * @param[in] vpdMap - IPZ vpd map.
110 * @param[in] objectPath - Object path for the FRU.
111 * @param[out] blankPropertyList - Properties which are blank in System VPD and
112 * needs to be updated as standby.
113 */
114static void
115 getListOfBlankSystemVpd(Parsed& vpdMap, const string& objectPath,
116 std::vector<RestoredEeproms>& blankPropertyList)
117{
118 for (const auto& systemRecKwdPair : svpdKwdMap)
119 {
120 auto it = vpdMap.find(systemRecKwdPair.first);
121
122 // check if record is found in map we got by parser
123 if (it != vpdMap.end())
124 {
125 const auto& kwdListForRecord = systemRecKwdPair.second;
126 for (const auto& keyword : kwdListForRecord)
127 {
128 DbusPropertyMap& kwdValMap = it->second;
129 auto iterator = kwdValMap.find(keyword);
130
131 if (iterator != kwdValMap.end())
132 {
133 string& kwdValue = iterator->second;
134
135 // check bus data
136 const string& recordName = systemRecKwdPair.first;
137 const string& busValue = readBusProperty(
138 objectPath, ipzVpdInf + recordName, keyword);
139
140 if (busValue.find_first_not_of(' ') != string::npos)
141 {
142 if (kwdValue.find_first_not_of(' ') == string::npos)
143 {
144 // implies data is blank on EEPROM but not on cache.
145 // So EEPROM vpd update is required.
146 Binary busData(busValue.begin(), busValue.end());
147
148 blankPropertyList.push_back(std::make_tuple(
149 objectPath, recordName, keyword, busData));
150 }
151 }
152 }
153 }
154 }
155 }
156}
157
158void Manager::restoreSystemVpd()
159{
160 std::cout << "Attempting system VPD restore" << std::endl;
161 ParserInterface* parser = nullptr;
162 try
163 {
164 auto vpdVector = getVpdDataInVector(jsonFile, systemVpdFilePath);
Sunny Srivastavaf31a91b2022-06-09 08:11:29 -0500165 const auto& inventoryPath =
166 jsonFile["frus"][systemVpdFilePath][0]["inventoryPath"]
167 .get_ref<const nlohmann::json::string_t&>();
168
169 parser = ParserFactory::getParser(vpdVector, (pimPath + inventoryPath));
Santosh Puranik6b2b5372022-06-02 20:49:02 +0530170 auto parseResult = parser->parse();
171
172 if (auto pVal = std::get_if<Store>(&parseResult))
173 {
174 // map to hold all the keywords whose value is blank and
175 // needs to be updated at standby.
176 std::vector<RestoredEeproms> blankSystemVpdProperties{};
177 getListOfBlankSystemVpd(pVal->getVpdMap(), SYSTEM_OBJECT,
178 blankSystemVpdProperties);
179
180 // if system VPD restore is required, update the
181 // EEPROM
182 for (const auto& item : blankSystemVpdProperties)
183 {
184 std::cout << "Restoring keyword: " << std::get<2>(item)
185 << std::endl;
186 writeKeyword(std::get<0>(item), std::get<1>(item),
187 std::get<2>(item), std::get<3>(item));
188 }
189 }
190 else
191 {
192 std::cerr << "Not a valid format to restore system VPD"
193 << std::endl;
194 }
195 }
196 catch (const std::exception& e)
197 {
198 std::cerr << "Failed to restore system VPD due to exception: "
199 << e.what() << std::endl;
200 }
201 // release the parser object
202 ParserFactory::freeParser(parser);
203}
204
Sunny Srivastavaecb5c7d2021-09-02 07:20:24 -0500205void Manager::listenHostState()
206{
Patrick Williams2eb01762022-07-22 19:26:56 -0500207 static std::shared_ptr<sdbusplus::bus::match_t> hostState =
208 std::make_shared<sdbusplus::bus::match_t>(
Sunny Srivastava523af2e2022-02-14 07:30:10 -0600209 *conn,
Sunny Srivastavaecb5c7d2021-09-02 07:20:24 -0500210 sdbusplus::bus::match::rules::propertiesChanged(
211 "/xyz/openbmc_project/state/host0",
212 "xyz.openbmc_project.State.Host"),
Patrick Williams2eb01762022-07-22 19:26:56 -0500213 [this](sdbusplus::message_t& msg) { hostStateCallBack(msg); });
Sunny Srivastavaecb5c7d2021-09-02 07:20:24 -0500214}
215
Sunny Srivastavafdf9ff22022-06-15 11:15:54 -0500216void Manager::checkEssentialFrus()
217{
218 for (const auto& invPath : essentialFrus)
219 {
220 const auto res = readBusProperty(invPath, invItemIntf, "Present");
221
222 // implies the essential FRU is missing. Log PEL.
223 if (res == "false")
224 {
225 auto rc = sd_bus_call_method_async(
226 sdBus, NULL, loggerService, loggerObjectPath,
227 loggerCreateInterface, "Create", NULL, NULL, "ssa{ss}",
228 errIntfForEssentialFru,
229 "xyz.openbmc_project.Logging.Entry.Level.Warning", 2,
230 "DESCRIPTION", "Essential fru missing from the system.",
231 "CALLOUT_INVENTORY_PATH", (pimPath + invPath).c_str());
232
233 if (rc < 0)
234 {
235 log<level::ERR>("Error calling sd_bus_call_method_async",
236 entry("RC=%d", rc),
237 entry("MSG=%s", strerror(-rc)));
238 }
239 }
240 }
241}
242
Patrick Williams7a975f02022-12-07 03:19:53 -0600243void Manager::hostStateCallBack(sdbusplus::message_t& msg)
Sunny Srivastavaecb5c7d2021-09-02 07:20:24 -0500244{
245 if (msg.is_method_error())
246 {
247 std::cerr << "Error in reading signal " << std::endl;
248 }
249
250 Path object;
251 PropertyMap propMap;
252 msg.read(object, propMap);
253 const auto itr = propMap.find("CurrentHostState");
254 if (itr != propMap.end())
255 {
256 if (auto hostState = std::get_if<std::string>(&(itr->second)))
257 {
258 // implies system is moving from standby to power on state
259 if (*hostState == "xyz.openbmc_project.State.Host.HostState."
260 "TransitioningToRunning")
261 {
Sunny Srivastavafdf9ff22022-06-15 11:15:54 -0500262 // detect if essential frus are present in the system.
263 checkEssentialFrus();
264
Sunny Srivastavaecb5c7d2021-09-02 07:20:24 -0500265 // check and perfrom recollection for FRUs replaceable at
266 // standby.
267 performVPDRecollection();
268 return;
269 }
270 }
Sunny Srivastavaecb5c7d2021-09-02 07:20:24 -0500271 }
272}
273
Santosh Puranikb62f6052022-04-06 18:37:54 +0530274void Manager::listenAssetTag()
275{
Patrick Williams2eb01762022-07-22 19:26:56 -0500276 static std::shared_ptr<sdbusplus::bus::match_t> assetMatcher =
277 std::make_shared<sdbusplus::bus::match_t>(
Sunny Srivastava523af2e2022-02-14 07:30:10 -0600278 *conn,
Santosh Puranikb62f6052022-04-06 18:37:54 +0530279 sdbusplus::bus::match::rules::propertiesChanged(
280 "/xyz/openbmc_project/inventory/system",
281 "xyz.openbmc_project.Inventory.Decorator.AssetTag"),
Patrick Williams2eb01762022-07-22 19:26:56 -0500282 [this](sdbusplus::message_t& msg) { assetTagCallback(msg); });
Santosh Puranikb62f6052022-04-06 18:37:54 +0530283}
284
Patrick Williams2eb01762022-07-22 19:26:56 -0500285void Manager::assetTagCallback(sdbusplus::message_t& msg)
Santosh Puranikb62f6052022-04-06 18:37:54 +0530286{
287 if (msg.is_method_error())
288 {
289 std::cerr << "Error in reading signal " << std::endl;
290 }
291
292 Path object;
293 PropertyMap propMap;
294 msg.read(object, propMap);
295 const auto itr = propMap.find("AssetTag");
296 if (itr != propMap.end())
297 {
298 if (auto assetTag = std::get_if<std::string>(&(itr->second)))
299 {
300 // Call Notify to persist the AssetTag
301 inventory::ObjectMap objectMap = {
302 {std::string{"/system"},
303 {{"xyz.openbmc_project.Inventory.Decorator.AssetTag",
304 {{"AssetTag", *assetTag}}}}}};
305
306 common::utility::callPIM(std::move(objectMap));
307 }
308 else
309 {
310 std::cerr << "Failed to read asset tag" << std::endl;
311 }
312 }
313}
314
SunnySrivastava1984de3c60d2020-02-03 10:34:33 -0600315void Manager::processJSON()
316{
Santosh Puranik0246a4d2020-11-04 16:57:39 +0530317 std::ifstream json(INVENTORY_JSON_SYM_LINK, std::ios::binary);
SunnySrivastava1984de3c60d2020-02-03 10:34:33 -0600318
319 if (!json)
320 {
321 throw std::runtime_error("json file not found");
322 }
323
324 jsonFile = nlohmann::json::parse(json);
325 if (jsonFile.find("frus") == jsonFile.end())
326 {
327 throw std::runtime_error("frus group not found in json");
328 }
329
330 const nlohmann::json& groupFRUS =
331 jsonFile["frus"].get_ref<const nlohmann::json::object_t&>();
332 for (const auto& itemFRUS : groupFRUS.items())
333 {
334 const std::vector<nlohmann::json>& groupEEPROM =
335 itemFRUS.value().get_ref<const nlohmann::json::array_t&>();
336 for (const auto& itemEEPROM : groupEEPROM)
SunnySrivastava1984b59fd092020-02-03 09:58:56 -0600337 {
SunnySrivastava198443306542020-04-01 02:50:20 -0500338 bool isMotherboard = false;
Santosh Puranika0b23912022-02-10 13:37:09 +0530339 std::string redundantPath;
340
SunnySrivastava198443306542020-04-01 02:50:20 -0500341 if (itemEEPROM["extraInterfaces"].find(
342 "xyz.openbmc_project.Inventory.Item.Board.Motherboard") !=
343 itemEEPROM["extraInterfaces"].end())
344 {
345 isMotherboard = true;
346 }
Santosh Puranika0b23912022-02-10 13:37:09 +0530347 if (itemEEPROM.find("redundantEeprom") != itemEEPROM.end())
348 {
349 redundantPath = itemEEPROM["redundantEeprom"]
350 .get_ref<const nlohmann::json::string_t&>();
351 }
352 frus.emplace(
353 itemEEPROM["inventoryPath"]
354 .get_ref<const nlohmann::json::string_t&>(),
355 std::make_tuple(itemFRUS.key(), redundantPath, isMotherboard));
SunnySrivastava1984bca5aaa2020-04-21 05:31:04 -0500356
Alpana Kumari414d5ae2021-03-04 21:06:35 +0000357 if (itemEEPROM["extraInterfaces"].find(IBM_LOCATION_CODE_INF) !=
Alpana Kumari920408d2020-05-14 00:07:03 -0500358 itemEEPROM["extraInterfaces"].end())
359 {
360 fruLocationCode.emplace(
Alpana Kumari414d5ae2021-03-04 21:06:35 +0000361 itemEEPROM["extraInterfaces"][IBM_LOCATION_CODE_INF]
Alpana Kumari920408d2020-05-14 00:07:03 -0500362 ["LocationCode"]
363 .get_ref<const nlohmann::json::string_t&>(),
364 itemEEPROM["inventoryPath"]
365 .get_ref<const nlohmann::json::string_t&>());
366 }
SunnySrivastava19849a195542020-09-07 06:04:50 -0500367
Sunny Srivastavaecb5c7d2021-09-02 07:20:24 -0500368 if (itemEEPROM.value("replaceableAtStandby", false))
SunnySrivastava19849a195542020-09-07 06:04:50 -0500369 {
370 replaceableFrus.emplace_back(itemFRUS.key());
371 }
Sunny Srivastavafdf9ff22022-06-15 11:15:54 -0500372
373 if (itemEEPROM.value("essentialFru", false))
374 {
375 essentialFrus.emplace_back(itemEEPROM["inventoryPath"]);
376 }
SunnySrivastava1984b59fd092020-02-03 09:58:56 -0600377 }
378 }
379}
380
Sunny Srivastava523af2e2022-02-14 07:30:10 -0600381void Manager::writeKeyword(const sdbusplus::message::object_path& path,
382 const std::string& recordName,
383 const std::string& keyword, const Binary& value)
SunnySrivastava1984b59fd092020-02-03 09:58:56 -0600384{
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600385 try
386 {
Santosh Puranik8c796812021-12-01 19:17:56 +0530387 std::string objPath{path};
388 // Strip any inventory prefix in path
389 if (objPath.find(INVENTORY_PATH) == 0)
390 {
391 objPath = objPath.substr(sizeof(INVENTORY_PATH) - 1);
392 }
393
394 if (frus.find(objPath) == frus.end())
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600395 {
396 throw std::runtime_error("Inventory path not found");
397 }
398
Santosh Puranika0b23912022-02-10 13:37:09 +0530399 inventory::Path vpdFilePath = std::get<0>(frus.find(objPath)->second);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600400
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500401 // instantiate editor class to update the data
Santosh Puranik8c796812021-12-01 19:17:56 +0530402 EditorImpl edit(vpdFilePath, jsonFile, recordName, keyword, objPath);
Santosh Puranika0b23912022-02-10 13:37:09 +0530403
404 uint32_t offset = 0;
405 // Setup offset, if any
406 for (const auto& item : jsonFile["frus"][vpdFilePath])
407 {
408 if (item.find("offset") != item.end())
409 {
410 offset = item["offset"];
411 break;
412 }
413 }
414
415 edit.updateKeyword(value, offset, true);
416
417 // If we have a redundant EEPROM to update, then update just the EEPROM,
418 // not the cache since that is already done when we updated the primary
419 if (!std::get<1>(frus.find(objPath)->second).empty())
420 {
421 EditorImpl edit(std::get<1>(frus.find(objPath)->second), jsonFile,
Sunny Srivastavaf31a91b2022-06-09 08:11:29 -0500422 recordName, keyword, objPath);
Santosh Puranika0b23912022-02-10 13:37:09 +0530423 edit.updateKeyword(value, offset, false);
424 }
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600425
SunnySrivastava198443306542020-04-01 02:50:20 -0500426 // if it is a motehrboard FRU need to check for location expansion
Santosh Puranika0b23912022-02-10 13:37:09 +0530427 if (std::get<2>(frus.find(objPath)->second))
SunnySrivastava198443306542020-04-01 02:50:20 -0500428 {
429 if (recordName == "VCEN" && (keyword == "FC" || keyword == "SE"))
430 {
431 edit.expandLocationCode("fcs");
432 }
433 else if (recordName == "VSYS" &&
434 (keyword == "TM" || keyword == "SE"))
435 {
436 edit.expandLocationCode("mts");
437 }
438 }
439
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500440 return;
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600441 }
442 catch (const std::exception& e)
443 {
444 std::cerr << e.what() << std::endl;
445 }
SunnySrivastava1984b59fd092020-02-03 09:58:56 -0600446}
447
SunnySrivastava19841356d7e2020-04-24 04:29:35 -0500448ListOfPaths
Sunny Srivastava523af2e2022-02-14 07:30:10 -0600449 Manager::getFRUsByUnexpandedLocationCode(const LocationCode& locationCode,
SunnySrivastava1984fb5815a2020-04-24 08:03:52 -0500450 const NodeNumber nodeNumber)
SunnySrivastava1984b59fd092020-02-03 09:58:56 -0600451{
SunnySrivastava19841356d7e2020-04-24 04:29:35 -0500452 ReaderImpl read;
453 return read.getFrusAtLocation(locationCode, nodeNumber, fruLocationCode);
SunnySrivastava1984b59fd092020-02-03 09:58:56 -0600454}
455
SunnySrivastava19841356d7e2020-04-24 04:29:35 -0500456ListOfPaths
Sunny Srivastava523af2e2022-02-14 07:30:10 -0600457 Manager::getFRUsByExpandedLocationCode(const LocationCode& locationCode)
SunnySrivastava1984b59fd092020-02-03 09:58:56 -0600458{
SunnySrivastava1984fb5815a2020-04-24 08:03:52 -0500459 ReaderImpl read;
460 return read.getFRUsByExpandedLocationCode(locationCode, fruLocationCode);
SunnySrivastava1984b59fd092020-02-03 09:58:56 -0600461}
462
Sunny Srivastava523af2e2022-02-14 07:30:10 -0600463LocationCode Manager::getExpandedLocationCode(const LocationCode& locationCode,
SunnySrivastava1984fb5815a2020-04-24 08:03:52 -0500464 const NodeNumber nodeNumber)
SunnySrivastava1984b59fd092020-02-03 09:58:56 -0600465{
SunnySrivastava1984bca5aaa2020-04-21 05:31:04 -0500466 ReaderImpl read;
467 return read.getExpandedLocationCode(locationCode, nodeNumber,
468 fruLocationCode);
SunnySrivastava1984b59fd092020-02-03 09:58:56 -0600469}
SunnySrivastava1984de3c60d2020-02-03 10:34:33 -0600470
SunnySrivastava19849a195542020-09-07 06:04:50 -0500471void Manager::performVPDRecollection()
472{
473 // get list of FRUs replaceable at standby
474 for (const auto& item : replaceableFrus)
475 {
476 const vector<nlohmann::json>& groupEEPROM = jsonFile["frus"][item];
477 const nlohmann::json& singleFru = groupEEPROM[0];
478
479 const string& inventoryPath =
480 singleFru["inventoryPath"]
481 .get_ref<const nlohmann::json::string_t&>();
482
Santosh Puranikd40e42d2022-03-23 13:58:06 +0530483 bool prePostActionRequired = false;
484
485 if ((jsonFile["frus"][item].at(0)).find("preAction") !=
486 jsonFile["frus"][item].at(0).end())
487 {
Sunny Srivastavaa2ddc962022-06-29 08:53:16 -0500488 try
Santosh Puranikd40e42d2022-03-23 13:58:06 +0530489 {
Sunny Srivastavaa2ddc962022-06-29 08:53:16 -0500490 if (!executePreAction(jsonFile, item))
491 {
492 // if the FRU has preAction defined then its execution
493 // should pass to ensure bind/unbind of data.
494 // preAction execution failed. should not call
495 // bind/unbind.
496 log<level::ERR>(
497 "Pre-Action execution failed for the FRU",
498 entry("ERROR=%s",
499 ("Inventory path: " + inventoryPath).c_str()));
500 continue;
501 }
502 }
503 catch (const GpioException& e)
504 {
505 log<level::ERR>(e.what());
506 PelAdditionalData additionalData{};
507 additionalData.emplace("DESCRIPTION", e.what());
508 createPEL(additionalData, PelSeverity::WARNING,
509 errIntfForGpioError, sdBus);
Santosh Puranikd40e42d2022-03-23 13:58:06 +0530510 continue;
511 }
512 prePostActionRequired = true;
513 }
514
Sunny Srivastava6a1bd392021-06-02 04:39:24 -0500515 // unbind, bind the driver to trigger parser.
516 triggerVpdCollection(singleFru, inventoryPath);
Santosh Puranikd40e42d2022-03-23 13:58:06 +0530517
518 // this check is added to avoid file system expensive call in case not
519 // required.
520 if (prePostActionRequired)
521 {
522 // Check if device showed up (test for file)
523 if (!filesystem::exists(item))
524 {
Sunny Srivastavaa2ddc962022-06-29 08:53:16 -0500525 try
526 {
527 // If not, then take failure postAction
528 executePostFailAction(jsonFile, item);
529 }
530 catch (const GpioException& e)
531 {
532 PelAdditionalData additionalData{};
533 additionalData.emplace("DESCRIPTION", e.what());
534 createPEL(additionalData, PelSeverity::WARNING,
535 errIntfForGpioError, sdBus);
536 }
Santosh Puranikd40e42d2022-03-23 13:58:06 +0530537 }
Alpana Kumari41d498c2021-09-16 00:29:12 -0500538 else
539 {
540 // bind the LED driver
541 string chipAddr = singleFru.value("pcaChipAddress", "");
542 cout << "performVPDRecollection: Executing driver binding for "
543 "chip "
544 "address - "
545 << chipAddr << endl;
546
547 executeCmd(createBindUnbindDriverCmnd(chipAddr, "i2c",
548 "leds-pca955x", "/bind"));
549 }
Santosh Puranikd40e42d2022-03-23 13:58:06 +0530550 }
SunnySrivastava19849a195542020-09-07 06:04:50 -0500551 }
552}
553
Sunny Srivastava6a1bd392021-06-02 04:39:24 -0500554void Manager::collectFRUVPD(const sdbusplus::message::object_path& path)
555{
Sunny Srivastava5ef6ccc2022-05-30 01:35:13 -0500556 std::cout << "Manager called to collect vpd for fru: " << std::string{path}
557 << std::endl;
558
Sunny Srivastava6a1bd392021-06-02 04:39:24 -0500559 using InvalidArgument =
560 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument;
561 using Argument = xyz::openbmc_project::Common::InvalidArgument;
562
Santosh Puranikbc599472022-12-19 20:17:10 +0530563 std::string objPath{path};
564
565 // Strip any inventory prefix in path
566 if (objPath.find(INVENTORY_PATH) == 0)
Sunny Srivastava6a1bd392021-06-02 04:39:24 -0500567 {
Santosh Puranikbc599472022-12-19 20:17:10 +0530568 objPath = objPath.substr(sizeof(INVENTORY_PATH) - 1);
Sunny Srivastava6a1bd392021-06-02 04:39:24 -0500569 }
570
Santosh Puranikbc599472022-12-19 20:17:10 +0530571 // if path not found in Json.
572 if (frus.find(objPath) == frus.end())
573 {
574 elog<InvalidArgument>(Argument::ARGUMENT_NAME("Object Path"),
575 Argument::ARGUMENT_VALUE(objPath.c_str()));
576 }
577
578 inventory::Path vpdFilePath = std::get<0>(frus.find(objPath)->second);
Sunny Srivastava6a1bd392021-06-02 04:39:24 -0500579
580 const std::vector<nlohmann::json>& groupEEPROM =
581 jsonFile["frus"][vpdFilePath].get_ref<const nlohmann::json::array_t&>();
582
Sunny Srivastavaab2304d2023-01-10 23:30:05 -0600583 nlohmann::json singleFru{};
584 for (const auto& item : groupEEPROM)
585 {
586 if (item["inventoryPath"] == objPath)
587 {
588 // this is the inventory we are looking for
589 singleFru = item;
590 break;
591 }
592 }
Sunny Srivastava6a1bd392021-06-02 04:39:24 -0500593
594 // check if the device qualifies for CM.
595 if (singleFru.value("concurrentlyMaintainable", false))
596 {
597 bool prePostActionRequired = false;
598
599 if ((jsonFile["frus"][vpdFilePath].at(0)).find("preAction") !=
600 jsonFile["frus"][vpdFilePath].at(0).end())
601 {
602 if (!executePreAction(jsonFile, vpdFilePath))
603 {
604 // if the FRU has preAction defined then its execution should
605 // pass to ensure bind/unbind of data.
606 // preAction execution failed. should not call bind/unbind.
607 log<level::ERR>("Pre-Action execution failed for the FRU");
608 return;
609 }
610
611 prePostActionRequired = true;
612 }
613
614 // unbind, bind the driver to trigger parser.
Santosh Puranikbc599472022-12-19 20:17:10 +0530615 triggerVpdCollection(singleFru, objPath);
Sunny Srivastava6a1bd392021-06-02 04:39:24 -0500616
617 // this check is added to avoid file system expensive call in case not
618 // required.
619 if (prePostActionRequired)
620 {
621 // Check if device showed up (test for file)
622 if (!filesystem::exists(vpdFilePath))
623 {
Santosh Puranikbc599472022-12-19 20:17:10 +0530624 try
625 {
626 // If not, then take failure postAction
627 executePostFailAction(jsonFile, vpdFilePath);
628 }
629 catch (const GpioException& e)
630 {
631 PelAdditionalData additionalData{};
632 additionalData.emplace("DESCRIPTION", e.what());
633 createPEL(additionalData, PelSeverity::WARNING,
634 errIntfForGpioError, sdBus);
635 }
Sunny Srivastava6a1bd392021-06-02 04:39:24 -0500636 }
Alpana Kumari41d498c2021-09-16 00:29:12 -0500637 else
638 {
639 // bind the LED driver
640 string chipAddr = jsonFile["frus"][vpdFilePath].at(0).value(
641 "pcaChipAddress", "");
642 cout << "Executing driver binding for chip address - "
643 << chipAddr << endl;
644
645 executeCmd(createBindUnbindDriverCmnd(chipAddr, "i2c",
646 "leds-pca955x", "/bind"));
647 }
Sunny Srivastava6a1bd392021-06-02 04:39:24 -0500648 }
649 return;
650 }
651 else
652 {
Santosh Puranikbc599472022-12-19 20:17:10 +0530653 elog<InvalidArgument>(Argument::ARGUMENT_NAME("Object Path"),
654 Argument::ARGUMENT_VALUE(objPath.c_str()));
Sunny Srivastava6a1bd392021-06-02 04:39:24 -0500655 }
656}
657
658void Manager::triggerVpdCollection(const nlohmann::json& singleFru,
659 const std::string& path)
660{
661 if ((singleFru.find("devAddress") == singleFru.end()) ||
662 (singleFru.find("driverType") == singleFru.end()) ||
663 (singleFru.find("busType") == singleFru.end()))
664 {
665 // The FRUs is marked for collection but missing mandatory
666 // fields for collection. Log error and return.
667 log<level::ERR>(
668 "Collection Failed as mandatory field missing in Json",
669 entry("ERROR=%s", ("Recollection failed for " + (path)).c_str()));
670
671 return;
672 }
673
674 string deviceAddress = singleFru["devAddress"];
675 const string& driverType = singleFru["driverType"];
676 const string& busType = singleFru["busType"];
677
678 // devTreeStatus flag is present in json as false to mention
679 // that the EEPROM is not mentioned in device tree. If this flag
680 // is absent consider the value to be true, i.e EEPROM is
681 // mentioned in device tree
682 if (!singleFru.value("devTreeStatus", true))
683 {
684 auto pos = deviceAddress.find('-');
685 if (pos != string::npos)
686 {
687 string busNum = deviceAddress.substr(0, pos);
688 deviceAddress = "0x" + deviceAddress.substr(pos + 1, string::npos);
689
690 string deleteDevice = "echo" + deviceAddress + " > /sys/bus/" +
691 busType + "/devices/" + busType + "-" +
692 busNum + "/delete_device";
693 executeCmd(deleteDevice);
694
695 string addDevice = "echo" + driverType + " " + deviceAddress +
696 " > /sys/bus/" + busType + "/devices/" +
697 busType + "-" + busNum + "/new_device";
698 executeCmd(addDevice);
699 }
700 else
701 {
702 const string& inventoryPath =
703 singleFru["inventoryPath"]
704 .get_ref<const nlohmann::json::string_t&>();
705
706 log<level::ERR>(
707 "Wrong format of device address in Json",
708 entry("ERROR=%s",
709 ("Recollection failed for " + inventoryPath).c_str()));
710 }
711 }
712 else
713 {
714 executeCmd(createBindUnbindDriverCmnd(deviceAddress, busType,
715 driverType, "/unbind"));
716 executeCmd(createBindUnbindDriverCmnd(deviceAddress, busType,
717 driverType, "/bind"));
718 }
719}
720
Sunny Srivastava28abd6e2021-07-28 02:58:28 -0500721void Manager::deleteFRUVPD(const sdbusplus::message::object_path& path)
722{
Sunny Srivastava5ef6ccc2022-05-30 01:35:13 -0500723 std::cout << "Manager called to delete vpd for fru: " << std::string{path}
724 << std::endl;
725
Sunny Srivastava28abd6e2021-07-28 02:58:28 -0500726 using InvalidArgument =
727 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument;
728 using Argument = xyz::openbmc_project::Common::InvalidArgument;
729
Santosh Puranikbc599472022-12-19 20:17:10 +0530730 std::string objPath{path};
731
732 // Strip any inventory prefix in path
733 if (objPath.find(INVENTORY_PATH) == 0)
Sunny Srivastava28abd6e2021-07-28 02:58:28 -0500734 {
Santosh Puranikbc599472022-12-19 20:17:10 +0530735 objPath = objPath.substr(sizeof(INVENTORY_PATH) - 1);
Sunny Srivastava28abd6e2021-07-28 02:58:28 -0500736 }
737
Santosh Puranikbc599472022-12-19 20:17:10 +0530738 // if path not found in Json.
739 if (frus.find(objPath) == frus.end())
740 {
741 elog<InvalidArgument>(Argument::ARGUMENT_NAME("Object Path"),
742 Argument::ARGUMENT_VALUE(objPath.c_str()));
743 }
744
745 inventory::Path& vpdFilePath = std::get<0>(frus.find(objPath)->second);
Alpana Kumari41d498c2021-09-16 00:29:12 -0500746
747 string chipAddress =
748 jsonFile["frus"][vpdFilePath].at(0).value("pcaChipAddress", "");
749
750 // Unbind the LED driver for this FRU
751 cout << "Unbinding device- " << chipAddress << endl;
752 executeCmd(createBindUnbindDriverCmnd(chipAddress, "i2c", "leds-pca955x",
753 "/unbind"));
754
Sunny Srivastava28abd6e2021-07-28 02:58:28 -0500755 // if the FRU is not present then log error
Santosh Puranikbc599472022-12-19 20:17:10 +0530756 if (readBusProperty(objPath, "xyz.openbmc_project.Inventory.Item",
Sunny Srivastava28abd6e2021-07-28 02:58:28 -0500757 "Present") == "false")
758 {
Santosh Puranikbc599472022-12-19 20:17:10 +0530759 elog<InvalidArgument>(Argument::ARGUMENT_NAME("FRU not preset"),
760 Argument::ARGUMENT_VALUE(objPath.c_str()));
Sunny Srivastava28abd6e2021-07-28 02:58:28 -0500761 }
762 else
763 {
Santosh Puranikbc599472022-12-19 20:17:10 +0530764 // Set present property of FRU as false as it has been removed.
765 // CC data for FRU is also removed as
766 // a) FRU is not there so CC does not make sense.
767 // b) Sensors dependent on Panel uses CC data.
768 inventory::InterfaceMap interfaces{
769 {"xyz.openbmc_project.Inventory.Item", {{"Present", false}}},
770 {"com.ibm.ipzvpd.VINI", {{"CC", Binary{}}}}};
771
772 inventory::ObjectMap objectMap;
773 objectMap.emplace(objPath, move(interfaces));
Sunny Srivastava28abd6e2021-07-28 02:58:28 -0500774
775 common::utility::callPIM(move(objectMap));
776 }
777}
778
SunnySrivastava1984b59fd092020-02-03 09:58:56 -0600779} // namespace manager
780} // namespace vpd
Alpana Kumarib17dd3b2020-10-01 00:18:10 -0500781} // namespace openpower