blob: d8b2089431cd7786bfc7d92891161995d238ba80 [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 }
271 std::cerr << "Failed to read Host state" << std::endl;
272 }
273}
274
Santosh Puranikb62f6052022-04-06 18:37:54 +0530275void Manager::listenAssetTag()
276{
Patrick Williams2eb01762022-07-22 19:26:56 -0500277 static std::shared_ptr<sdbusplus::bus::match_t> assetMatcher =
278 std::make_shared<sdbusplus::bus::match_t>(
Sunny Srivastava523af2e2022-02-14 07:30:10 -0600279 *conn,
Santosh Puranikb62f6052022-04-06 18:37:54 +0530280 sdbusplus::bus::match::rules::propertiesChanged(
281 "/xyz/openbmc_project/inventory/system",
282 "xyz.openbmc_project.Inventory.Decorator.AssetTag"),
Patrick Williams2eb01762022-07-22 19:26:56 -0500283 [this](sdbusplus::message_t& msg) { assetTagCallback(msg); });
Santosh Puranikb62f6052022-04-06 18:37:54 +0530284}
285
Patrick Williams2eb01762022-07-22 19:26:56 -0500286void Manager::assetTagCallback(sdbusplus::message_t& msg)
Santosh Puranikb62f6052022-04-06 18:37:54 +0530287{
288 if (msg.is_method_error())
289 {
290 std::cerr << "Error in reading signal " << std::endl;
291 }
292
293 Path object;
294 PropertyMap propMap;
295 msg.read(object, propMap);
296 const auto itr = propMap.find("AssetTag");
297 if (itr != propMap.end())
298 {
299 if (auto assetTag = std::get_if<std::string>(&(itr->second)))
300 {
301 // Call Notify to persist the AssetTag
302 inventory::ObjectMap objectMap = {
303 {std::string{"/system"},
304 {{"xyz.openbmc_project.Inventory.Decorator.AssetTag",
305 {{"AssetTag", *assetTag}}}}}};
306
307 common::utility::callPIM(std::move(objectMap));
308 }
309 else
310 {
311 std::cerr << "Failed to read asset tag" << std::endl;
312 }
313 }
314}
315
SunnySrivastava1984de3c60d2020-02-03 10:34:33 -0600316void Manager::processJSON()
317{
Santosh Puranik0246a4d2020-11-04 16:57:39 +0530318 std::ifstream json(INVENTORY_JSON_SYM_LINK, std::ios::binary);
SunnySrivastava1984de3c60d2020-02-03 10:34:33 -0600319
320 if (!json)
321 {
322 throw std::runtime_error("json file not found");
323 }
324
325 jsonFile = nlohmann::json::parse(json);
326 if (jsonFile.find("frus") == jsonFile.end())
327 {
328 throw std::runtime_error("frus group not found in json");
329 }
330
331 const nlohmann::json& groupFRUS =
332 jsonFile["frus"].get_ref<const nlohmann::json::object_t&>();
333 for (const auto& itemFRUS : groupFRUS.items())
334 {
335 const std::vector<nlohmann::json>& groupEEPROM =
336 itemFRUS.value().get_ref<const nlohmann::json::array_t&>();
337 for (const auto& itemEEPROM : groupEEPROM)
SunnySrivastava1984b59fd092020-02-03 09:58:56 -0600338 {
SunnySrivastava198443306542020-04-01 02:50:20 -0500339 bool isMotherboard = false;
Santosh Puranika0b23912022-02-10 13:37:09 +0530340 std::string redundantPath;
341
SunnySrivastava198443306542020-04-01 02:50:20 -0500342 if (itemEEPROM["extraInterfaces"].find(
343 "xyz.openbmc_project.Inventory.Item.Board.Motherboard") !=
344 itemEEPROM["extraInterfaces"].end())
345 {
346 isMotherboard = true;
347 }
Santosh Puranika0b23912022-02-10 13:37:09 +0530348 if (itemEEPROM.find("redundantEeprom") != itemEEPROM.end())
349 {
350 redundantPath = itemEEPROM["redundantEeprom"]
351 .get_ref<const nlohmann::json::string_t&>();
352 }
353 frus.emplace(
354 itemEEPROM["inventoryPath"]
355 .get_ref<const nlohmann::json::string_t&>(),
356 std::make_tuple(itemFRUS.key(), redundantPath, isMotherboard));
SunnySrivastava1984bca5aaa2020-04-21 05:31:04 -0500357
Alpana Kumari414d5ae2021-03-04 21:06:35 +0000358 if (itemEEPROM["extraInterfaces"].find(IBM_LOCATION_CODE_INF) !=
Alpana Kumari920408d2020-05-14 00:07:03 -0500359 itemEEPROM["extraInterfaces"].end())
360 {
361 fruLocationCode.emplace(
Alpana Kumari414d5ae2021-03-04 21:06:35 +0000362 itemEEPROM["extraInterfaces"][IBM_LOCATION_CODE_INF]
Alpana Kumari920408d2020-05-14 00:07:03 -0500363 ["LocationCode"]
364 .get_ref<const nlohmann::json::string_t&>(),
365 itemEEPROM["inventoryPath"]
366 .get_ref<const nlohmann::json::string_t&>());
367 }
SunnySrivastava19849a195542020-09-07 06:04:50 -0500368
Sunny Srivastavaecb5c7d2021-09-02 07:20:24 -0500369 if (itemEEPROM.value("replaceableAtStandby", false))
SunnySrivastava19849a195542020-09-07 06:04:50 -0500370 {
371 replaceableFrus.emplace_back(itemFRUS.key());
372 }
Sunny Srivastavafdf9ff22022-06-15 11:15:54 -0500373
374 if (itemEEPROM.value("essentialFru", false))
375 {
376 essentialFrus.emplace_back(itemEEPROM["inventoryPath"]);
377 }
SunnySrivastava1984b59fd092020-02-03 09:58:56 -0600378 }
379 }
380}
381
Sunny Srivastava523af2e2022-02-14 07:30:10 -0600382void Manager::writeKeyword(const sdbusplus::message::object_path& path,
383 const std::string& recordName,
384 const std::string& keyword, const Binary& value)
SunnySrivastava1984b59fd092020-02-03 09:58:56 -0600385{
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600386 try
387 {
Santosh Puranik8c796812021-12-01 19:17:56 +0530388 std::string objPath{path};
389 // Strip any inventory prefix in path
390 if (objPath.find(INVENTORY_PATH) == 0)
391 {
392 objPath = objPath.substr(sizeof(INVENTORY_PATH) - 1);
393 }
394
395 if (frus.find(objPath) == frus.end())
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600396 {
397 throw std::runtime_error("Inventory path not found");
398 }
399
Santosh Puranika0b23912022-02-10 13:37:09 +0530400 inventory::Path vpdFilePath = std::get<0>(frus.find(objPath)->second);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600401
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500402 // instantiate editor class to update the data
Santosh Puranik8c796812021-12-01 19:17:56 +0530403 EditorImpl edit(vpdFilePath, jsonFile, recordName, keyword, objPath);
Santosh Puranika0b23912022-02-10 13:37:09 +0530404
405 uint32_t offset = 0;
406 // Setup offset, if any
407 for (const auto& item : jsonFile["frus"][vpdFilePath])
408 {
409 if (item.find("offset") != item.end())
410 {
411 offset = item["offset"];
412 break;
413 }
414 }
415
416 edit.updateKeyword(value, offset, true);
417
418 // If we have a redundant EEPROM to update, then update just the EEPROM,
419 // not the cache since that is already done when we updated the primary
420 if (!std::get<1>(frus.find(objPath)->second).empty())
421 {
422 EditorImpl edit(std::get<1>(frus.find(objPath)->second), jsonFile,
Sunny Srivastavaf31a91b2022-06-09 08:11:29 -0500423 recordName, keyword, objPath);
Santosh Puranika0b23912022-02-10 13:37:09 +0530424 edit.updateKeyword(value, offset, false);
425 }
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600426
SunnySrivastava198443306542020-04-01 02:50:20 -0500427 // if it is a motehrboard FRU need to check for location expansion
Santosh Puranika0b23912022-02-10 13:37:09 +0530428 if (std::get<2>(frus.find(objPath)->second))
SunnySrivastava198443306542020-04-01 02:50:20 -0500429 {
430 if (recordName == "VCEN" && (keyword == "FC" || keyword == "SE"))
431 {
432 edit.expandLocationCode("fcs");
433 }
434 else if (recordName == "VSYS" &&
435 (keyword == "TM" || keyword == "SE"))
436 {
437 edit.expandLocationCode("mts");
438 }
439 }
440
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500441 return;
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600442 }
443 catch (const std::exception& e)
444 {
445 std::cerr << e.what() << std::endl;
446 }
SunnySrivastava1984b59fd092020-02-03 09:58:56 -0600447}
448
SunnySrivastava19841356d7e2020-04-24 04:29:35 -0500449ListOfPaths
Sunny Srivastava523af2e2022-02-14 07:30:10 -0600450 Manager::getFRUsByUnexpandedLocationCode(const LocationCode& locationCode,
SunnySrivastava1984fb5815a2020-04-24 08:03:52 -0500451 const NodeNumber nodeNumber)
SunnySrivastava1984b59fd092020-02-03 09:58:56 -0600452{
SunnySrivastava19841356d7e2020-04-24 04:29:35 -0500453 ReaderImpl read;
454 return read.getFrusAtLocation(locationCode, nodeNumber, fruLocationCode);
SunnySrivastava1984b59fd092020-02-03 09:58:56 -0600455}
456
SunnySrivastava19841356d7e2020-04-24 04:29:35 -0500457ListOfPaths
Sunny Srivastava523af2e2022-02-14 07:30:10 -0600458 Manager::getFRUsByExpandedLocationCode(const LocationCode& locationCode)
SunnySrivastava1984b59fd092020-02-03 09:58:56 -0600459{
SunnySrivastava1984fb5815a2020-04-24 08:03:52 -0500460 ReaderImpl read;
461 return read.getFRUsByExpandedLocationCode(locationCode, fruLocationCode);
SunnySrivastava1984b59fd092020-02-03 09:58:56 -0600462}
463
Sunny Srivastava523af2e2022-02-14 07:30:10 -0600464LocationCode Manager::getExpandedLocationCode(const LocationCode& locationCode,
SunnySrivastava1984fb5815a2020-04-24 08:03:52 -0500465 const NodeNumber nodeNumber)
SunnySrivastava1984b59fd092020-02-03 09:58:56 -0600466{
SunnySrivastava1984bca5aaa2020-04-21 05:31:04 -0500467 ReaderImpl read;
468 return read.getExpandedLocationCode(locationCode, nodeNumber,
469 fruLocationCode);
SunnySrivastava1984b59fd092020-02-03 09:58:56 -0600470}
SunnySrivastava1984de3c60d2020-02-03 10:34:33 -0600471
SunnySrivastava19849a195542020-09-07 06:04:50 -0500472void Manager::performVPDRecollection()
473{
474 // get list of FRUs replaceable at standby
475 for (const auto& item : replaceableFrus)
476 {
477 const vector<nlohmann::json>& groupEEPROM = jsonFile["frus"][item];
478 const nlohmann::json& singleFru = groupEEPROM[0];
479
480 const string& inventoryPath =
481 singleFru["inventoryPath"]
482 .get_ref<const nlohmann::json::string_t&>();
483
Santosh Puranikd40e42d2022-03-23 13:58:06 +0530484 bool prePostActionRequired = false;
485
486 if ((jsonFile["frus"][item].at(0)).find("preAction") !=
487 jsonFile["frus"][item].at(0).end())
488 {
Sunny Srivastavaa2ddc962022-06-29 08:53:16 -0500489 try
Santosh Puranikd40e42d2022-03-23 13:58:06 +0530490 {
Sunny Srivastavaa2ddc962022-06-29 08:53:16 -0500491 if (!executePreAction(jsonFile, item))
492 {
493 // if the FRU has preAction defined then its execution
494 // should pass to ensure bind/unbind of data.
495 // preAction execution failed. should not call
496 // bind/unbind.
497 log<level::ERR>(
498 "Pre-Action execution failed for the FRU",
499 entry("ERROR=%s",
500 ("Inventory path: " + inventoryPath).c_str()));
501 continue;
502 }
503 }
504 catch (const GpioException& e)
505 {
506 log<level::ERR>(e.what());
507 PelAdditionalData additionalData{};
508 additionalData.emplace("DESCRIPTION", e.what());
509 createPEL(additionalData, PelSeverity::WARNING,
510 errIntfForGpioError, sdBus);
Santosh Puranikd40e42d2022-03-23 13:58:06 +0530511 continue;
512 }
513 prePostActionRequired = true;
514 }
515
Sunny Srivastava6a1bd392021-06-02 04:39:24 -0500516 // unbind, bind the driver to trigger parser.
517 triggerVpdCollection(singleFru, inventoryPath);
Santosh Puranikd40e42d2022-03-23 13:58:06 +0530518
519 // this check is added to avoid file system expensive call in case not
520 // required.
521 if (prePostActionRequired)
522 {
523 // Check if device showed up (test for file)
524 if (!filesystem::exists(item))
525 {
Sunny Srivastavaa2ddc962022-06-29 08:53:16 -0500526 try
527 {
528 // If not, then take failure postAction
529 executePostFailAction(jsonFile, item);
530 }
531 catch (const GpioException& e)
532 {
533 PelAdditionalData additionalData{};
534 additionalData.emplace("DESCRIPTION", e.what());
535 createPEL(additionalData, PelSeverity::WARNING,
536 errIntfForGpioError, sdBus);
537 }
Santosh Puranikd40e42d2022-03-23 13:58:06 +0530538 }
Alpana Kumari41d498c2021-09-16 00:29:12 -0500539 else
540 {
541 // bind the LED driver
542 string chipAddr = singleFru.value("pcaChipAddress", "");
543 cout << "performVPDRecollection: Executing driver binding for "
544 "chip "
545 "address - "
546 << chipAddr << endl;
547
548 executeCmd(createBindUnbindDriverCmnd(chipAddr, "i2c",
549 "leds-pca955x", "/bind"));
550 }
Santosh Puranikd40e42d2022-03-23 13:58:06 +0530551 }
SunnySrivastava19849a195542020-09-07 06:04:50 -0500552 }
553}
554
Sunny Srivastava6a1bd392021-06-02 04:39:24 -0500555void Manager::collectFRUVPD(const sdbusplus::message::object_path& path)
556{
Sunny Srivastava5ef6ccc2022-05-30 01:35:13 -0500557 std::cout << "Manager called to collect vpd for fru: " << std::string{path}
558 << std::endl;
559
Sunny Srivastava6a1bd392021-06-02 04:39:24 -0500560 using InvalidArgument =
561 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument;
562 using Argument = xyz::openbmc_project::Common::InvalidArgument;
563
564 // if path not found in Json.
565 if (frus.find(path) == frus.end())
566 {
567 elog<InvalidArgument>(
568 Argument::ARGUMENT_NAME("Object Path"),
569 Argument::ARGUMENT_VALUE(std::string(path).c_str()));
570 }
571
572 inventory::Path vpdFilePath = std::get<0>(frus.find(path)->second);
573
574 const std::vector<nlohmann::json>& groupEEPROM =
575 jsonFile["frus"][vpdFilePath].get_ref<const nlohmann::json::array_t&>();
576
577 const nlohmann::json& singleFru = groupEEPROM[0];
578
579 // check if the device qualifies for CM.
580 if (singleFru.value("concurrentlyMaintainable", false))
581 {
582 bool prePostActionRequired = false;
583
584 if ((jsonFile["frus"][vpdFilePath].at(0)).find("preAction") !=
585 jsonFile["frus"][vpdFilePath].at(0).end())
586 {
587 if (!executePreAction(jsonFile, vpdFilePath))
588 {
589 // if the FRU has preAction defined then its execution should
590 // pass to ensure bind/unbind of data.
591 // preAction execution failed. should not call bind/unbind.
592 log<level::ERR>("Pre-Action execution failed for the FRU");
593 return;
594 }
595
596 prePostActionRequired = true;
597 }
598
599 // unbind, bind the driver to trigger parser.
600 triggerVpdCollection(singleFru, std::string(path));
601
602 // this check is added to avoid file system expensive call in case not
603 // required.
604 if (prePostActionRequired)
605 {
606 // Check if device showed up (test for file)
607 if (!filesystem::exists(vpdFilePath))
608 {
609 // If not, then take failure postAction
610 executePostFailAction(jsonFile, vpdFilePath);
611 }
Alpana Kumari41d498c2021-09-16 00:29:12 -0500612 else
613 {
614 // bind the LED driver
615 string chipAddr = jsonFile["frus"][vpdFilePath].at(0).value(
616 "pcaChipAddress", "");
617 cout << "Executing driver binding for chip address - "
618 << chipAddr << endl;
619
620 executeCmd(createBindUnbindDriverCmnd(chipAddr, "i2c",
621 "leds-pca955x", "/bind"));
622 }
Sunny Srivastava6a1bd392021-06-02 04:39:24 -0500623 }
624 return;
625 }
626 else
627 {
628 elog<InvalidArgument>(
629 Argument::ARGUMENT_NAME("Object Path"),
630 Argument::ARGUMENT_VALUE(std::string(path).c_str()));
631 }
632}
633
634void Manager::triggerVpdCollection(const nlohmann::json& singleFru,
635 const std::string& path)
636{
637 if ((singleFru.find("devAddress") == singleFru.end()) ||
638 (singleFru.find("driverType") == singleFru.end()) ||
639 (singleFru.find("busType") == singleFru.end()))
640 {
641 // The FRUs is marked for collection but missing mandatory
642 // fields for collection. Log error and return.
643 log<level::ERR>(
644 "Collection Failed as mandatory field missing in Json",
645 entry("ERROR=%s", ("Recollection failed for " + (path)).c_str()));
646
647 return;
648 }
649
650 string deviceAddress = singleFru["devAddress"];
651 const string& driverType = singleFru["driverType"];
652 const string& busType = singleFru["busType"];
653
654 // devTreeStatus flag is present in json as false to mention
655 // that the EEPROM is not mentioned in device tree. If this flag
656 // is absent consider the value to be true, i.e EEPROM is
657 // mentioned in device tree
658 if (!singleFru.value("devTreeStatus", true))
659 {
660 auto pos = deviceAddress.find('-');
661 if (pos != string::npos)
662 {
663 string busNum = deviceAddress.substr(0, pos);
664 deviceAddress = "0x" + deviceAddress.substr(pos + 1, string::npos);
665
666 string deleteDevice = "echo" + deviceAddress + " > /sys/bus/" +
667 busType + "/devices/" + busType + "-" +
668 busNum + "/delete_device";
669 executeCmd(deleteDevice);
670
671 string addDevice = "echo" + driverType + " " + deviceAddress +
672 " > /sys/bus/" + busType + "/devices/" +
673 busType + "-" + busNum + "/new_device";
674 executeCmd(addDevice);
675 }
676 else
677 {
678 const string& inventoryPath =
679 singleFru["inventoryPath"]
680 .get_ref<const nlohmann::json::string_t&>();
681
682 log<level::ERR>(
683 "Wrong format of device address in Json",
684 entry("ERROR=%s",
685 ("Recollection failed for " + inventoryPath).c_str()));
686 }
687 }
688 else
689 {
690 executeCmd(createBindUnbindDriverCmnd(deviceAddress, busType,
691 driverType, "/unbind"));
692 executeCmd(createBindUnbindDriverCmnd(deviceAddress, busType,
693 driverType, "/bind"));
694 }
695}
696
Sunny Srivastava28abd6e2021-07-28 02:58:28 -0500697void Manager::deleteFRUVPD(const sdbusplus::message::object_path& path)
698{
Sunny Srivastava5ef6ccc2022-05-30 01:35:13 -0500699 std::cout << "Manager called to delete vpd for fru: " << std::string{path}
700 << std::endl;
701
Sunny Srivastava28abd6e2021-07-28 02:58:28 -0500702 using InvalidArgument =
703 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument;
704 using Argument = xyz::openbmc_project::Common::InvalidArgument;
705
706 // if path not found in Json.
707 if (frus.find(path) == frus.end())
708 {
709 elog<InvalidArgument>(
710 Argument::ARGUMENT_NAME("Object Path"),
711 Argument::ARGUMENT_VALUE(std::string(path).c_str()));
712 }
713
Alpana Kumari41d498c2021-09-16 00:29:12 -0500714 inventory::Path& vpdFilePath = std::get<0>(frus.find(path)->second);
715
716 string chipAddress =
717 jsonFile["frus"][vpdFilePath].at(0).value("pcaChipAddress", "");
718
719 // Unbind the LED driver for this FRU
720 cout << "Unbinding device- " << chipAddress << endl;
721 executeCmd(createBindUnbindDriverCmnd(chipAddress, "i2c", "leds-pca955x",
722 "/unbind"));
723
Sunny Srivastava28abd6e2021-07-28 02:58:28 -0500724 // if the FRU is not present then log error
725 if (readBusProperty(path, "xyz.openbmc_project.Inventory.Item",
726 "Present") == "false")
727 {
728 elog<InvalidArgument>(
729 Argument::ARGUMENT_NAME("FRU not preset"),
730 Argument::ARGUMENT_VALUE(std::string(path).c_str()));
731 }
732 else
733 {
734 inventory::ObjectMap objectMap = {
735 {path,
736 {{"xyz.openbmc_project.Inventory.Item", {{"Present", false}}}}}};
737
738 common::utility::callPIM(move(objectMap));
739 }
740}
741
SunnySrivastava1984b59fd092020-02-03 09:58:56 -0600742} // namespace manager
743} // namespace vpd
Alpana Kumarib17dd3b2020-10-01 00:18:10 -0500744} // namespace openpower