blob: d3e7e9ca8b8327196b03eb14f1d6846f9c6f0d86 [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 }
539 }
SunnySrivastava19849a195542020-09-07 06:04:50 -0500540 }
541}
542
Sunny Srivastava6a1bd392021-06-02 04:39:24 -0500543void Manager::collectFRUVPD(const sdbusplus::message::object_path& path)
544{
545 using InvalidArgument =
546 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument;
547 using Argument = xyz::openbmc_project::Common::InvalidArgument;
548
549 // if path not found in Json.
550 if (frus.find(path) == frus.end())
551 {
552 elog<InvalidArgument>(
553 Argument::ARGUMENT_NAME("Object Path"),
554 Argument::ARGUMENT_VALUE(std::string(path).c_str()));
555 }
556
557 inventory::Path vpdFilePath = std::get<0>(frus.find(path)->second);
558
559 const std::vector<nlohmann::json>& groupEEPROM =
560 jsonFile["frus"][vpdFilePath].get_ref<const nlohmann::json::array_t&>();
561
562 const nlohmann::json& singleFru = groupEEPROM[0];
563
564 // check if the device qualifies for CM.
565 if (singleFru.value("concurrentlyMaintainable", false))
566 {
567 bool prePostActionRequired = false;
568
569 if ((jsonFile["frus"][vpdFilePath].at(0)).find("preAction") !=
570 jsonFile["frus"][vpdFilePath].at(0).end())
571 {
572 if (!executePreAction(jsonFile, vpdFilePath))
573 {
574 // if the FRU has preAction defined then its execution should
575 // pass to ensure bind/unbind of data.
576 // preAction execution failed. should not call bind/unbind.
577 log<level::ERR>("Pre-Action execution failed for the FRU");
578 return;
579 }
580
581 prePostActionRequired = true;
582 }
583
584 // unbind, bind the driver to trigger parser.
585 triggerVpdCollection(singleFru, std::string(path));
586
587 // this check is added to avoid file system expensive call in case not
588 // required.
589 if (prePostActionRequired)
590 {
591 // Check if device showed up (test for file)
592 if (!filesystem::exists(vpdFilePath))
593 {
594 // If not, then take failure postAction
595 executePostFailAction(jsonFile, vpdFilePath);
596 }
597 }
598 return;
599 }
600 else
601 {
602 elog<InvalidArgument>(
603 Argument::ARGUMENT_NAME("Object Path"),
604 Argument::ARGUMENT_VALUE(std::string(path).c_str()));
605 }
606}
607
608void Manager::triggerVpdCollection(const nlohmann::json& singleFru,
609 const std::string& path)
610{
611 if ((singleFru.find("devAddress") == singleFru.end()) ||
612 (singleFru.find("driverType") == singleFru.end()) ||
613 (singleFru.find("busType") == singleFru.end()))
614 {
615 // The FRUs is marked for collection but missing mandatory
616 // fields for collection. Log error and return.
617 log<level::ERR>(
618 "Collection Failed as mandatory field missing in Json",
619 entry("ERROR=%s", ("Recollection failed for " + (path)).c_str()));
620
621 return;
622 }
623
624 string deviceAddress = singleFru["devAddress"];
625 const string& driverType = singleFru["driverType"];
626 const string& busType = singleFru["busType"];
627
628 // devTreeStatus flag is present in json as false to mention
629 // that the EEPROM is not mentioned in device tree. If this flag
630 // is absent consider the value to be true, i.e EEPROM is
631 // mentioned in device tree
632 if (!singleFru.value("devTreeStatus", true))
633 {
634 auto pos = deviceAddress.find('-');
635 if (pos != string::npos)
636 {
637 string busNum = deviceAddress.substr(0, pos);
638 deviceAddress = "0x" + deviceAddress.substr(pos + 1, string::npos);
639
640 string deleteDevice = "echo" + deviceAddress + " > /sys/bus/" +
641 busType + "/devices/" + busType + "-" +
642 busNum + "/delete_device";
643 executeCmd(deleteDevice);
644
645 string addDevice = "echo" + driverType + " " + deviceAddress +
646 " > /sys/bus/" + busType + "/devices/" +
647 busType + "-" + busNum + "/new_device";
648 executeCmd(addDevice);
649 }
650 else
651 {
652 const string& inventoryPath =
653 singleFru["inventoryPath"]
654 .get_ref<const nlohmann::json::string_t&>();
655
656 log<level::ERR>(
657 "Wrong format of device address in Json",
658 entry("ERROR=%s",
659 ("Recollection failed for " + inventoryPath).c_str()));
660 }
661 }
662 else
663 {
664 executeCmd(createBindUnbindDriverCmnd(deviceAddress, busType,
665 driverType, "/unbind"));
666 executeCmd(createBindUnbindDriverCmnd(deviceAddress, busType,
667 driverType, "/bind"));
668 }
669}
670
Sunny Srivastava28abd6e2021-07-28 02:58:28 -0500671void Manager::deleteFRUVPD(const sdbusplus::message::object_path& path)
672{
673 using InvalidArgument =
674 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument;
675 using Argument = xyz::openbmc_project::Common::InvalidArgument;
676
677 // if path not found in Json.
678 if (frus.find(path) == frus.end())
679 {
680 elog<InvalidArgument>(
681 Argument::ARGUMENT_NAME("Object Path"),
682 Argument::ARGUMENT_VALUE(std::string(path).c_str()));
683 }
684
685 // if the FRU is not present then log error
686 if (readBusProperty(path, "xyz.openbmc_project.Inventory.Item",
687 "Present") == "false")
688 {
689 elog<InvalidArgument>(
690 Argument::ARGUMENT_NAME("FRU not preset"),
691 Argument::ARGUMENT_VALUE(std::string(path).c_str()));
692 }
693 else
694 {
695 inventory::ObjectMap objectMap = {
696 {path,
697 {{"xyz.openbmc_project.Inventory.Item", {{"Present", false}}}}}};
698
699 common::utility::callPIM(move(objectMap));
700 }
701}
702
SunnySrivastava1984b59fd092020-02-03 09:58:56 -0600703} // namespace manager
704} // namespace vpd
Alpana Kumarib17dd3b2020-10-01 00:18:10 -0500705} // namespace openpower