blob: bab9f8ade8d93319f539e1a26b2e2ebd4c1fdf2a [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
583 const nlohmann::json& singleFru = groupEEPROM[0];
584
585 // check if the device qualifies for CM.
586 if (singleFru.value("concurrentlyMaintainable", false))
587 {
588 bool prePostActionRequired = false;
589
590 if ((jsonFile["frus"][vpdFilePath].at(0)).find("preAction") !=
591 jsonFile["frus"][vpdFilePath].at(0).end())
592 {
593 if (!executePreAction(jsonFile, vpdFilePath))
594 {
595 // if the FRU has preAction defined then its execution should
596 // pass to ensure bind/unbind of data.
597 // preAction execution failed. should not call bind/unbind.
598 log<level::ERR>("Pre-Action execution failed for the FRU");
599 return;
600 }
601
602 prePostActionRequired = true;
603 }
604
605 // unbind, bind the driver to trigger parser.
Santosh Puranikbc599472022-12-19 20:17:10 +0530606 triggerVpdCollection(singleFru, objPath);
Sunny Srivastava6a1bd392021-06-02 04:39:24 -0500607
608 // this check is added to avoid file system expensive call in case not
609 // required.
610 if (prePostActionRequired)
611 {
612 // Check if device showed up (test for file)
613 if (!filesystem::exists(vpdFilePath))
614 {
Santosh Puranikbc599472022-12-19 20:17:10 +0530615 try
616 {
617 // If not, then take failure postAction
618 executePostFailAction(jsonFile, vpdFilePath);
619 }
620 catch (const GpioException& e)
621 {
622 PelAdditionalData additionalData{};
623 additionalData.emplace("DESCRIPTION", e.what());
624 createPEL(additionalData, PelSeverity::WARNING,
625 errIntfForGpioError, sdBus);
626 }
Sunny Srivastava6a1bd392021-06-02 04:39:24 -0500627 }
Alpana Kumari41d498c2021-09-16 00:29:12 -0500628 else
629 {
630 // bind the LED driver
631 string chipAddr = jsonFile["frus"][vpdFilePath].at(0).value(
632 "pcaChipAddress", "");
633 cout << "Executing driver binding for chip address - "
634 << chipAddr << endl;
635
636 executeCmd(createBindUnbindDriverCmnd(chipAddr, "i2c",
637 "leds-pca955x", "/bind"));
638 }
Sunny Srivastava6a1bd392021-06-02 04:39:24 -0500639 }
640 return;
641 }
642 else
643 {
Santosh Puranikbc599472022-12-19 20:17:10 +0530644 elog<InvalidArgument>(Argument::ARGUMENT_NAME("Object Path"),
645 Argument::ARGUMENT_VALUE(objPath.c_str()));
Sunny Srivastava6a1bd392021-06-02 04:39:24 -0500646 }
647}
648
649void Manager::triggerVpdCollection(const nlohmann::json& singleFru,
650 const std::string& path)
651{
652 if ((singleFru.find("devAddress") == singleFru.end()) ||
653 (singleFru.find("driverType") == singleFru.end()) ||
654 (singleFru.find("busType") == singleFru.end()))
655 {
656 // The FRUs is marked for collection but missing mandatory
657 // fields for collection. Log error and return.
658 log<level::ERR>(
659 "Collection Failed as mandatory field missing in Json",
660 entry("ERROR=%s", ("Recollection failed for " + (path)).c_str()));
661
662 return;
663 }
664
665 string deviceAddress = singleFru["devAddress"];
666 const string& driverType = singleFru["driverType"];
667 const string& busType = singleFru["busType"];
668
669 // devTreeStatus flag is present in json as false to mention
670 // that the EEPROM is not mentioned in device tree. If this flag
671 // is absent consider the value to be true, i.e EEPROM is
672 // mentioned in device tree
673 if (!singleFru.value("devTreeStatus", true))
674 {
675 auto pos = deviceAddress.find('-');
676 if (pos != string::npos)
677 {
678 string busNum = deviceAddress.substr(0, pos);
679 deviceAddress = "0x" + deviceAddress.substr(pos + 1, string::npos);
680
681 string deleteDevice = "echo" + deviceAddress + " > /sys/bus/" +
682 busType + "/devices/" + busType + "-" +
683 busNum + "/delete_device";
684 executeCmd(deleteDevice);
685
686 string addDevice = "echo" + driverType + " " + deviceAddress +
687 " > /sys/bus/" + busType + "/devices/" +
688 busType + "-" + busNum + "/new_device";
689 executeCmd(addDevice);
690 }
691 else
692 {
693 const string& inventoryPath =
694 singleFru["inventoryPath"]
695 .get_ref<const nlohmann::json::string_t&>();
696
697 log<level::ERR>(
698 "Wrong format of device address in Json",
699 entry("ERROR=%s",
700 ("Recollection failed for " + inventoryPath).c_str()));
701 }
702 }
703 else
704 {
705 executeCmd(createBindUnbindDriverCmnd(deviceAddress, busType,
706 driverType, "/unbind"));
707 executeCmd(createBindUnbindDriverCmnd(deviceAddress, busType,
708 driverType, "/bind"));
709 }
710}
711
Sunny Srivastava28abd6e2021-07-28 02:58:28 -0500712void Manager::deleteFRUVPD(const sdbusplus::message::object_path& path)
713{
Sunny Srivastava5ef6ccc2022-05-30 01:35:13 -0500714 std::cout << "Manager called to delete vpd for fru: " << std::string{path}
715 << std::endl;
716
Sunny Srivastava28abd6e2021-07-28 02:58:28 -0500717 using InvalidArgument =
718 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument;
719 using Argument = xyz::openbmc_project::Common::InvalidArgument;
720
Santosh Puranikbc599472022-12-19 20:17:10 +0530721 std::string objPath{path};
722
723 // Strip any inventory prefix in path
724 if (objPath.find(INVENTORY_PATH) == 0)
Sunny Srivastava28abd6e2021-07-28 02:58:28 -0500725 {
Santosh Puranikbc599472022-12-19 20:17:10 +0530726 objPath = objPath.substr(sizeof(INVENTORY_PATH) - 1);
Sunny Srivastava28abd6e2021-07-28 02:58:28 -0500727 }
728
Santosh Puranikbc599472022-12-19 20:17:10 +0530729 // if path not found in Json.
730 if (frus.find(objPath) == frus.end())
731 {
732 elog<InvalidArgument>(Argument::ARGUMENT_NAME("Object Path"),
733 Argument::ARGUMENT_VALUE(objPath.c_str()));
734 }
735
736 inventory::Path& vpdFilePath = std::get<0>(frus.find(objPath)->second);
Alpana Kumari41d498c2021-09-16 00:29:12 -0500737
738 string chipAddress =
739 jsonFile["frus"][vpdFilePath].at(0).value("pcaChipAddress", "");
740
741 // Unbind the LED driver for this FRU
742 cout << "Unbinding device- " << chipAddress << endl;
743 executeCmd(createBindUnbindDriverCmnd(chipAddress, "i2c", "leds-pca955x",
744 "/unbind"));
745
Sunny Srivastava28abd6e2021-07-28 02:58:28 -0500746 // if the FRU is not present then log error
Santosh Puranikbc599472022-12-19 20:17:10 +0530747 if (readBusProperty(objPath, "xyz.openbmc_project.Inventory.Item",
Sunny Srivastava28abd6e2021-07-28 02:58:28 -0500748 "Present") == "false")
749 {
Santosh Puranikbc599472022-12-19 20:17:10 +0530750 elog<InvalidArgument>(Argument::ARGUMENT_NAME("FRU not preset"),
751 Argument::ARGUMENT_VALUE(objPath.c_str()));
Sunny Srivastava28abd6e2021-07-28 02:58:28 -0500752 }
753 else
754 {
Santosh Puranikbc599472022-12-19 20:17:10 +0530755 // Set present property of FRU as false as it has been removed.
756 // CC data for FRU is also removed as
757 // a) FRU is not there so CC does not make sense.
758 // b) Sensors dependent on Panel uses CC data.
759 inventory::InterfaceMap interfaces{
760 {"xyz.openbmc_project.Inventory.Item", {{"Present", false}}},
761 {"com.ibm.ipzvpd.VINI", {{"CC", Binary{}}}}};
762
763 inventory::ObjectMap objectMap;
764 objectMap.emplace(objPath, move(interfaces));
Sunny Srivastava28abd6e2021-07-28 02:58:28 -0500765
766 common::utility::callPIM(move(objectMap));
767 }
768}
769
SunnySrivastava1984b59fd092020-02-03 09:58:56 -0600770} // namespace manager
771} // namespace vpd
Alpana Kumarib17dd3b2020-10-01 00:18:10 -0500772} // namespace openpower