blob: 53c9ad8406e1931b03b093db7ab848e50a3ddc7f [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;
Priyanga Ramasamy952d6c52022-11-07 07:20:24 -0600126 for (const auto& keywordInfo : kwdListForRecord)
Santosh Puranik6b2b5372022-06-02 20:49:02 +0530127 {
Priyanga Ramasamy952d6c52022-11-07 07:20:24 -0600128 const auto& keyword = get<0>(keywordInfo);
129
Santosh Puranik6b2b5372022-06-02 20:49:02 +0530130 DbusPropertyMap& kwdValMap = it->second;
131 auto iterator = kwdValMap.find(keyword);
132
133 if (iterator != kwdValMap.end())
134 {
135 string& kwdValue = iterator->second;
136
137 // check bus data
138 const string& recordName = systemRecKwdPair.first;
139 const string& busValue = readBusProperty(
140 objectPath, ipzVpdInf + recordName, keyword);
141
Priyanga Ramasamy834c0782023-02-14 12:22:39 -0600142 const auto& defaultValue = get<1>(keywordInfo);
143
144 if (Binary(busValue.begin(), busValue.end()) !=
145 defaultValue)
Santosh Puranik6b2b5372022-06-02 20:49:02 +0530146 {
Priyanga Ramasamy834c0782023-02-14 12:22:39 -0600147 if (Binary(kwdValue.begin(), kwdValue.end()) ==
148 defaultValue)
Santosh Puranik6b2b5372022-06-02 20:49:02 +0530149 {
150 // implies data is blank on EEPROM but not on cache.
151 // So EEPROM vpd update is required.
152 Binary busData(busValue.begin(), busValue.end());
153
154 blankPropertyList.push_back(std::make_tuple(
155 objectPath, recordName, keyword, busData));
156 }
157 }
158 }
159 }
160 }
161 }
162}
163
164void Manager::restoreSystemVpd()
165{
166 std::cout << "Attempting system VPD restore" << std::endl;
167 ParserInterface* parser = nullptr;
168 try
169 {
170 auto vpdVector = getVpdDataInVector(jsonFile, systemVpdFilePath);
Sunny Srivastavaf31a91b2022-06-09 08:11:29 -0500171 const auto& inventoryPath =
172 jsonFile["frus"][systemVpdFilePath][0]["inventoryPath"]
173 .get_ref<const nlohmann::json::string_t&>();
174
175 parser = ParserFactory::getParser(vpdVector, (pimPath + inventoryPath));
Santosh Puranik6b2b5372022-06-02 20:49:02 +0530176 auto parseResult = parser->parse();
177
178 if (auto pVal = std::get_if<Store>(&parseResult))
179 {
180 // map to hold all the keywords whose value is blank and
181 // needs to be updated at standby.
182 std::vector<RestoredEeproms> blankSystemVpdProperties{};
183 getListOfBlankSystemVpd(pVal->getVpdMap(), SYSTEM_OBJECT,
184 blankSystemVpdProperties);
185
186 // if system VPD restore is required, update the
187 // EEPROM
188 for (const auto& item : blankSystemVpdProperties)
189 {
190 std::cout << "Restoring keyword: " << std::get<2>(item)
191 << std::endl;
192 writeKeyword(std::get<0>(item), std::get<1>(item),
193 std::get<2>(item), std::get<3>(item));
194 }
195 }
196 else
197 {
198 std::cerr << "Not a valid format to restore system VPD"
199 << std::endl;
200 }
201 }
202 catch (const std::exception& e)
203 {
204 std::cerr << "Failed to restore system VPD due to exception: "
205 << e.what() << std::endl;
206 }
207 // release the parser object
208 ParserFactory::freeParser(parser);
209}
210
Sunny Srivastavaecb5c7d2021-09-02 07:20:24 -0500211void Manager::listenHostState()
212{
Patrick Williams2eb01762022-07-22 19:26:56 -0500213 static std::shared_ptr<sdbusplus::bus::match_t> hostState =
214 std::make_shared<sdbusplus::bus::match_t>(
Sunny Srivastava523af2e2022-02-14 07:30:10 -0600215 *conn,
Sunny Srivastavaecb5c7d2021-09-02 07:20:24 -0500216 sdbusplus::bus::match::rules::propertiesChanged(
217 "/xyz/openbmc_project/state/host0",
218 "xyz.openbmc_project.State.Host"),
Patrick Williams2eb01762022-07-22 19:26:56 -0500219 [this](sdbusplus::message_t& msg) { hostStateCallBack(msg); });
Sunny Srivastavaecb5c7d2021-09-02 07:20:24 -0500220}
221
Sunny Srivastavafdf9ff22022-06-15 11:15:54 -0500222void Manager::checkEssentialFrus()
223{
224 for (const auto& invPath : essentialFrus)
225 {
226 const auto res = readBusProperty(invPath, invItemIntf, "Present");
227
228 // implies the essential FRU is missing. Log PEL.
229 if (res == "false")
230 {
231 auto rc = sd_bus_call_method_async(
232 sdBus, NULL, loggerService, loggerObjectPath,
233 loggerCreateInterface, "Create", NULL, NULL, "ssa{ss}",
234 errIntfForEssentialFru,
235 "xyz.openbmc_project.Logging.Entry.Level.Warning", 2,
236 "DESCRIPTION", "Essential fru missing from the system.",
237 "CALLOUT_INVENTORY_PATH", (pimPath + invPath).c_str());
238
239 if (rc < 0)
240 {
241 log<level::ERR>("Error calling sd_bus_call_method_async",
242 entry("RC=%d", rc),
243 entry("MSG=%s", strerror(-rc)));
244 }
245 }
246 }
247}
248
Patrick Williams7a975f02022-12-07 03:19:53 -0600249void Manager::hostStateCallBack(sdbusplus::message_t& msg)
Sunny Srivastavaecb5c7d2021-09-02 07:20:24 -0500250{
251 if (msg.is_method_error())
252 {
253 std::cerr << "Error in reading signal " << std::endl;
254 }
255
256 Path object;
257 PropertyMap propMap;
258 msg.read(object, propMap);
259 const auto itr = propMap.find("CurrentHostState");
260 if (itr != propMap.end())
261 {
262 if (auto hostState = std::get_if<std::string>(&(itr->second)))
263 {
264 // implies system is moving from standby to power on state
265 if (*hostState == "xyz.openbmc_project.State.Host.HostState."
266 "TransitioningToRunning")
267 {
Sunny Srivastavafdf9ff22022-06-15 11:15:54 -0500268 // detect if essential frus are present in the system.
269 checkEssentialFrus();
270
Sunny Srivastavaecb5c7d2021-09-02 07:20:24 -0500271 // check and perfrom recollection for FRUs replaceable at
272 // standby.
273 performVPDRecollection();
274 return;
275 }
276 }
Sunny Srivastavaecb5c7d2021-09-02 07:20:24 -0500277 }
278}
279
Santosh Puranikb62f6052022-04-06 18:37:54 +0530280void Manager::listenAssetTag()
281{
Patrick Williams2eb01762022-07-22 19:26:56 -0500282 static std::shared_ptr<sdbusplus::bus::match_t> assetMatcher =
283 std::make_shared<sdbusplus::bus::match_t>(
Sunny Srivastava523af2e2022-02-14 07:30:10 -0600284 *conn,
Santosh Puranikb62f6052022-04-06 18:37:54 +0530285 sdbusplus::bus::match::rules::propertiesChanged(
286 "/xyz/openbmc_project/inventory/system",
287 "xyz.openbmc_project.Inventory.Decorator.AssetTag"),
Patrick Williams2eb01762022-07-22 19:26:56 -0500288 [this](sdbusplus::message_t& msg) { assetTagCallback(msg); });
Santosh Puranikb62f6052022-04-06 18:37:54 +0530289}
290
Patrick Williams2eb01762022-07-22 19:26:56 -0500291void Manager::assetTagCallback(sdbusplus::message_t& msg)
Santosh Puranikb62f6052022-04-06 18:37:54 +0530292{
293 if (msg.is_method_error())
294 {
295 std::cerr << "Error in reading signal " << std::endl;
296 }
297
298 Path object;
299 PropertyMap propMap;
300 msg.read(object, propMap);
301 const auto itr = propMap.find("AssetTag");
302 if (itr != propMap.end())
303 {
304 if (auto assetTag = std::get_if<std::string>(&(itr->second)))
305 {
306 // Call Notify to persist the AssetTag
307 inventory::ObjectMap objectMap = {
308 {std::string{"/system"},
309 {{"xyz.openbmc_project.Inventory.Decorator.AssetTag",
310 {{"AssetTag", *assetTag}}}}}};
311
312 common::utility::callPIM(std::move(objectMap));
313 }
314 else
315 {
316 std::cerr << "Failed to read asset tag" << std::endl;
317 }
318 }
319}
320
SunnySrivastava1984de3c60d2020-02-03 10:34:33 -0600321void Manager::processJSON()
322{
Santosh Puranik0246a4d2020-11-04 16:57:39 +0530323 std::ifstream json(INVENTORY_JSON_SYM_LINK, std::ios::binary);
SunnySrivastava1984de3c60d2020-02-03 10:34:33 -0600324
325 if (!json)
326 {
327 throw std::runtime_error("json file not found");
328 }
329
330 jsonFile = nlohmann::json::parse(json);
331 if (jsonFile.find("frus") == jsonFile.end())
332 {
333 throw std::runtime_error("frus group not found in json");
334 }
335
336 const nlohmann::json& groupFRUS =
337 jsonFile["frus"].get_ref<const nlohmann::json::object_t&>();
338 for (const auto& itemFRUS : groupFRUS.items())
339 {
340 const std::vector<nlohmann::json>& groupEEPROM =
341 itemFRUS.value().get_ref<const nlohmann::json::array_t&>();
342 for (const auto& itemEEPROM : groupEEPROM)
SunnySrivastava1984b59fd092020-02-03 09:58:56 -0600343 {
SunnySrivastava198443306542020-04-01 02:50:20 -0500344 bool isMotherboard = false;
Santosh Puranika0b23912022-02-10 13:37:09 +0530345 std::string redundantPath;
346
SunnySrivastava198443306542020-04-01 02:50:20 -0500347 if (itemEEPROM["extraInterfaces"].find(
348 "xyz.openbmc_project.Inventory.Item.Board.Motherboard") !=
349 itemEEPROM["extraInterfaces"].end())
350 {
351 isMotherboard = true;
352 }
Santosh Puranika0b23912022-02-10 13:37:09 +0530353 if (itemEEPROM.find("redundantEeprom") != itemEEPROM.end())
354 {
355 redundantPath = itemEEPROM["redundantEeprom"]
356 .get_ref<const nlohmann::json::string_t&>();
357 }
358 frus.emplace(
359 itemEEPROM["inventoryPath"]
360 .get_ref<const nlohmann::json::string_t&>(),
361 std::make_tuple(itemFRUS.key(), redundantPath, isMotherboard));
SunnySrivastava1984bca5aaa2020-04-21 05:31:04 -0500362
Alpana Kumari414d5ae2021-03-04 21:06:35 +0000363 if (itemEEPROM["extraInterfaces"].find(IBM_LOCATION_CODE_INF) !=
Alpana Kumari920408d2020-05-14 00:07:03 -0500364 itemEEPROM["extraInterfaces"].end())
365 {
366 fruLocationCode.emplace(
Alpana Kumari414d5ae2021-03-04 21:06:35 +0000367 itemEEPROM["extraInterfaces"][IBM_LOCATION_CODE_INF]
Alpana Kumari920408d2020-05-14 00:07:03 -0500368 ["LocationCode"]
369 .get_ref<const nlohmann::json::string_t&>(),
370 itemEEPROM["inventoryPath"]
371 .get_ref<const nlohmann::json::string_t&>());
372 }
SunnySrivastava19849a195542020-09-07 06:04:50 -0500373
Sunny Srivastavaecb5c7d2021-09-02 07:20:24 -0500374 if (itemEEPROM.value("replaceableAtStandby", false))
SunnySrivastava19849a195542020-09-07 06:04:50 -0500375 {
376 replaceableFrus.emplace_back(itemFRUS.key());
377 }
Sunny Srivastavafdf9ff22022-06-15 11:15:54 -0500378
379 if (itemEEPROM.value("essentialFru", false))
380 {
381 essentialFrus.emplace_back(itemEEPROM["inventoryPath"]);
382 }
SunnySrivastava1984b59fd092020-02-03 09:58:56 -0600383 }
384 }
385}
386
Sunny Srivastava523af2e2022-02-14 07:30:10 -0600387void Manager::writeKeyword(const sdbusplus::message::object_path& path,
388 const std::string& recordName,
389 const std::string& keyword, const Binary& value)
SunnySrivastava1984b59fd092020-02-03 09:58:56 -0600390{
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600391 try
392 {
Santosh Puranik8c796812021-12-01 19:17:56 +0530393 std::string objPath{path};
394 // Strip any inventory prefix in path
395 if (objPath.find(INVENTORY_PATH) == 0)
396 {
397 objPath = objPath.substr(sizeof(INVENTORY_PATH) - 1);
398 }
399
400 if (frus.find(objPath) == frus.end())
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600401 {
402 throw std::runtime_error("Inventory path not found");
403 }
404
Santosh Puranika0b23912022-02-10 13:37:09 +0530405 inventory::Path vpdFilePath = std::get<0>(frus.find(objPath)->second);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600406
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500407 // instantiate editor class to update the data
Santosh Puranik8c796812021-12-01 19:17:56 +0530408 EditorImpl edit(vpdFilePath, jsonFile, recordName, keyword, objPath);
Santosh Puranika0b23912022-02-10 13:37:09 +0530409
410 uint32_t offset = 0;
411 // Setup offset, if any
412 for (const auto& item : jsonFile["frus"][vpdFilePath])
413 {
414 if (item.find("offset") != item.end())
415 {
416 offset = item["offset"];
417 break;
418 }
419 }
420
421 edit.updateKeyword(value, offset, true);
422
423 // If we have a redundant EEPROM to update, then update just the EEPROM,
424 // not the cache since that is already done when we updated the primary
425 if (!std::get<1>(frus.find(objPath)->second).empty())
426 {
427 EditorImpl edit(std::get<1>(frus.find(objPath)->second), jsonFile,
Sunny Srivastavaf31a91b2022-06-09 08:11:29 -0500428 recordName, keyword, objPath);
Santosh Puranika0b23912022-02-10 13:37:09 +0530429 edit.updateKeyword(value, offset, false);
430 }
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600431
SunnySrivastava198443306542020-04-01 02:50:20 -0500432 // if it is a motehrboard FRU need to check for location expansion
Santosh Puranika0b23912022-02-10 13:37:09 +0530433 if (std::get<2>(frus.find(objPath)->second))
SunnySrivastava198443306542020-04-01 02:50:20 -0500434 {
435 if (recordName == "VCEN" && (keyword == "FC" || keyword == "SE"))
436 {
437 edit.expandLocationCode("fcs");
438 }
439 else if (recordName == "VSYS" &&
440 (keyword == "TM" || keyword == "SE"))
441 {
442 edit.expandLocationCode("mts");
443 }
444 }
445
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500446 return;
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600447 }
448 catch (const std::exception& e)
449 {
450 std::cerr << e.what() << std::endl;
451 }
SunnySrivastava1984b59fd092020-02-03 09:58:56 -0600452}
453
SunnySrivastava19841356d7e2020-04-24 04:29:35 -0500454ListOfPaths
Sunny Srivastava523af2e2022-02-14 07:30:10 -0600455 Manager::getFRUsByUnexpandedLocationCode(const LocationCode& locationCode,
SunnySrivastava1984fb5815a2020-04-24 08:03:52 -0500456 const NodeNumber nodeNumber)
SunnySrivastava1984b59fd092020-02-03 09:58:56 -0600457{
SunnySrivastava19841356d7e2020-04-24 04:29:35 -0500458 ReaderImpl read;
459 return read.getFrusAtLocation(locationCode, nodeNumber, fruLocationCode);
SunnySrivastava1984b59fd092020-02-03 09:58:56 -0600460}
461
SunnySrivastava19841356d7e2020-04-24 04:29:35 -0500462ListOfPaths
Sunny Srivastava523af2e2022-02-14 07:30:10 -0600463 Manager::getFRUsByExpandedLocationCode(const LocationCode& locationCode)
SunnySrivastava1984b59fd092020-02-03 09:58:56 -0600464{
SunnySrivastava1984fb5815a2020-04-24 08:03:52 -0500465 ReaderImpl read;
466 return read.getFRUsByExpandedLocationCode(locationCode, fruLocationCode);
SunnySrivastava1984b59fd092020-02-03 09:58:56 -0600467}
468
Sunny Srivastava523af2e2022-02-14 07:30:10 -0600469LocationCode Manager::getExpandedLocationCode(const LocationCode& locationCode,
SunnySrivastava1984fb5815a2020-04-24 08:03:52 -0500470 const NodeNumber nodeNumber)
SunnySrivastava1984b59fd092020-02-03 09:58:56 -0600471{
SunnySrivastava1984bca5aaa2020-04-21 05:31:04 -0500472 ReaderImpl read;
473 return read.getExpandedLocationCode(locationCode, nodeNumber,
474 fruLocationCode);
SunnySrivastava1984b59fd092020-02-03 09:58:56 -0600475}
SunnySrivastava1984de3c60d2020-02-03 10:34:33 -0600476
SunnySrivastava19849a195542020-09-07 06:04:50 -0500477void Manager::performVPDRecollection()
478{
479 // get list of FRUs replaceable at standby
480 for (const auto& item : replaceableFrus)
481 {
482 const vector<nlohmann::json>& groupEEPROM = jsonFile["frus"][item];
483 const nlohmann::json& singleFru = groupEEPROM[0];
484
485 const string& inventoryPath =
486 singleFru["inventoryPath"]
487 .get_ref<const nlohmann::json::string_t&>();
488
Santosh Puranikd40e42d2022-03-23 13:58:06 +0530489 bool prePostActionRequired = false;
490
491 if ((jsonFile["frus"][item].at(0)).find("preAction") !=
492 jsonFile["frus"][item].at(0).end())
493 {
Sunny Srivastavaa2ddc962022-06-29 08:53:16 -0500494 try
Santosh Puranikd40e42d2022-03-23 13:58:06 +0530495 {
Sunny Srivastavaa2ddc962022-06-29 08:53:16 -0500496 if (!executePreAction(jsonFile, item))
497 {
498 // if the FRU has preAction defined then its execution
499 // should pass to ensure bind/unbind of data.
500 // preAction execution failed. should not call
501 // bind/unbind.
502 log<level::ERR>(
503 "Pre-Action execution failed for the FRU",
504 entry("ERROR=%s",
505 ("Inventory path: " + inventoryPath).c_str()));
506 continue;
507 }
508 }
509 catch (const GpioException& e)
510 {
511 log<level::ERR>(e.what());
512 PelAdditionalData additionalData{};
513 additionalData.emplace("DESCRIPTION", e.what());
514 createPEL(additionalData, PelSeverity::WARNING,
515 errIntfForGpioError, sdBus);
Santosh Puranikd40e42d2022-03-23 13:58:06 +0530516 continue;
517 }
518 prePostActionRequired = true;
519 }
520
Sunny Srivastava6a1bd392021-06-02 04:39:24 -0500521 // unbind, bind the driver to trigger parser.
522 triggerVpdCollection(singleFru, inventoryPath);
Santosh Puranikd40e42d2022-03-23 13:58:06 +0530523
524 // this check is added to avoid file system expensive call in case not
525 // required.
526 if (prePostActionRequired)
527 {
528 // Check if device showed up (test for file)
529 if (!filesystem::exists(item))
530 {
Sunny Srivastavaa2ddc962022-06-29 08:53:16 -0500531 try
532 {
533 // If not, then take failure postAction
534 executePostFailAction(jsonFile, item);
535 }
536 catch (const GpioException& e)
537 {
538 PelAdditionalData additionalData{};
539 additionalData.emplace("DESCRIPTION", e.what());
540 createPEL(additionalData, PelSeverity::WARNING,
541 errIntfForGpioError, sdBus);
542 }
Santosh Puranikd40e42d2022-03-23 13:58:06 +0530543 }
Alpana Kumari41d498c2021-09-16 00:29:12 -0500544 else
545 {
546 // bind the LED driver
547 string chipAddr = singleFru.value("pcaChipAddress", "");
548 cout << "performVPDRecollection: Executing driver binding for "
549 "chip "
550 "address - "
551 << chipAddr << endl;
552
553 executeCmd(createBindUnbindDriverCmnd(chipAddr, "i2c",
554 "leds-pca955x", "/bind"));
555 }
Santosh Puranikd40e42d2022-03-23 13:58:06 +0530556 }
SunnySrivastava19849a195542020-09-07 06:04:50 -0500557 }
558}
559
Sunny Srivastava6a1bd392021-06-02 04:39:24 -0500560void Manager::collectFRUVPD(const sdbusplus::message::object_path& path)
561{
Sunny Srivastava5ef6ccc2022-05-30 01:35:13 -0500562 std::cout << "Manager called to collect vpd for fru: " << std::string{path}
563 << std::endl;
564
Sunny Srivastava6a1bd392021-06-02 04:39:24 -0500565 using InvalidArgument =
566 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument;
567 using Argument = xyz::openbmc_project::Common::InvalidArgument;
568
Santosh Puranikbc599472022-12-19 20:17:10 +0530569 std::string objPath{path};
570
571 // Strip any inventory prefix in path
572 if (objPath.find(INVENTORY_PATH) == 0)
Sunny Srivastava6a1bd392021-06-02 04:39:24 -0500573 {
Santosh Puranikbc599472022-12-19 20:17:10 +0530574 objPath = objPath.substr(sizeof(INVENTORY_PATH) - 1);
Sunny Srivastava6a1bd392021-06-02 04:39:24 -0500575 }
576
Santosh Puranikbc599472022-12-19 20:17:10 +0530577 // if path not found in Json.
578 if (frus.find(objPath) == frus.end())
579 {
580 elog<InvalidArgument>(Argument::ARGUMENT_NAME("Object Path"),
581 Argument::ARGUMENT_VALUE(objPath.c_str()));
582 }
583
584 inventory::Path vpdFilePath = std::get<0>(frus.find(objPath)->second);
Sunny Srivastava6a1bd392021-06-02 04:39:24 -0500585
586 const std::vector<nlohmann::json>& groupEEPROM =
587 jsonFile["frus"][vpdFilePath].get_ref<const nlohmann::json::array_t&>();
588
Sunny Srivastavaab2304d2023-01-10 23:30:05 -0600589 nlohmann::json singleFru{};
590 for (const auto& item : groupEEPROM)
591 {
592 if (item["inventoryPath"] == objPath)
593 {
594 // this is the inventory we are looking for
595 singleFru = item;
596 break;
597 }
598 }
Sunny Srivastava6a1bd392021-06-02 04:39:24 -0500599
600 // check if the device qualifies for CM.
601 if (singleFru.value("concurrentlyMaintainable", false))
602 {
603 bool prePostActionRequired = false;
604
605 if ((jsonFile["frus"][vpdFilePath].at(0)).find("preAction") !=
606 jsonFile["frus"][vpdFilePath].at(0).end())
607 {
608 if (!executePreAction(jsonFile, vpdFilePath))
609 {
610 // if the FRU has preAction defined then its execution should
611 // pass to ensure bind/unbind of data.
612 // preAction execution failed. should not call bind/unbind.
613 log<level::ERR>("Pre-Action execution failed for the FRU");
614 return;
615 }
616
617 prePostActionRequired = true;
618 }
619
620 // unbind, bind the driver to trigger parser.
Santosh Puranikbc599472022-12-19 20:17:10 +0530621 triggerVpdCollection(singleFru, objPath);
Sunny Srivastava6a1bd392021-06-02 04:39:24 -0500622
623 // this check is added to avoid file system expensive call in case not
624 // required.
625 if (prePostActionRequired)
626 {
627 // Check if device showed up (test for file)
628 if (!filesystem::exists(vpdFilePath))
629 {
Santosh Puranikbc599472022-12-19 20:17:10 +0530630 try
631 {
632 // If not, then take failure postAction
633 executePostFailAction(jsonFile, vpdFilePath);
634 }
635 catch (const GpioException& e)
636 {
637 PelAdditionalData additionalData{};
638 additionalData.emplace("DESCRIPTION", e.what());
639 createPEL(additionalData, PelSeverity::WARNING,
640 errIntfForGpioError, sdBus);
641 }
Sunny Srivastava6a1bd392021-06-02 04:39:24 -0500642 }
Alpana Kumari41d498c2021-09-16 00:29:12 -0500643 else
644 {
645 // bind the LED driver
646 string chipAddr = jsonFile["frus"][vpdFilePath].at(0).value(
647 "pcaChipAddress", "");
648 cout << "Executing driver binding for chip address - "
649 << chipAddr << endl;
650
651 executeCmd(createBindUnbindDriverCmnd(chipAddr, "i2c",
652 "leds-pca955x", "/bind"));
653 }
Sunny Srivastava6a1bd392021-06-02 04:39:24 -0500654 }
655 return;
656 }
657 else
658 {
Santosh Puranikbc599472022-12-19 20:17:10 +0530659 elog<InvalidArgument>(Argument::ARGUMENT_NAME("Object Path"),
660 Argument::ARGUMENT_VALUE(objPath.c_str()));
Sunny Srivastava6a1bd392021-06-02 04:39:24 -0500661 }
662}
663
664void Manager::triggerVpdCollection(const nlohmann::json& singleFru,
665 const std::string& path)
666{
667 if ((singleFru.find("devAddress") == singleFru.end()) ||
668 (singleFru.find("driverType") == singleFru.end()) ||
669 (singleFru.find("busType") == singleFru.end()))
670 {
671 // The FRUs is marked for collection but missing mandatory
672 // fields for collection. Log error and return.
673 log<level::ERR>(
674 "Collection Failed as mandatory field missing in Json",
675 entry("ERROR=%s", ("Recollection failed for " + (path)).c_str()));
676
677 return;
678 }
679
680 string deviceAddress = singleFru["devAddress"];
681 const string& driverType = singleFru["driverType"];
682 const string& busType = singleFru["busType"];
683
684 // devTreeStatus flag is present in json as false to mention
685 // that the EEPROM is not mentioned in device tree. If this flag
686 // is absent consider the value to be true, i.e EEPROM is
687 // mentioned in device tree
688 if (!singleFru.value("devTreeStatus", true))
689 {
690 auto pos = deviceAddress.find('-');
691 if (pos != string::npos)
692 {
693 string busNum = deviceAddress.substr(0, pos);
694 deviceAddress = "0x" + deviceAddress.substr(pos + 1, string::npos);
695
696 string deleteDevice = "echo" + deviceAddress + " > /sys/bus/" +
697 busType + "/devices/" + busType + "-" +
698 busNum + "/delete_device";
699 executeCmd(deleteDevice);
700
701 string addDevice = "echo" + driverType + " " + deviceAddress +
702 " > /sys/bus/" + busType + "/devices/" +
703 busType + "-" + busNum + "/new_device";
704 executeCmd(addDevice);
705 }
706 else
707 {
708 const string& inventoryPath =
709 singleFru["inventoryPath"]
710 .get_ref<const nlohmann::json::string_t&>();
711
712 log<level::ERR>(
713 "Wrong format of device address in Json",
714 entry("ERROR=%s",
715 ("Recollection failed for " + inventoryPath).c_str()));
716 }
717 }
718 else
719 {
720 executeCmd(createBindUnbindDriverCmnd(deviceAddress, busType,
721 driverType, "/unbind"));
722 executeCmd(createBindUnbindDriverCmnd(deviceAddress, busType,
723 driverType, "/bind"));
724 }
725}
726
Sunny Srivastava28abd6e2021-07-28 02:58:28 -0500727void Manager::deleteFRUVPD(const sdbusplus::message::object_path& path)
728{
Sunny Srivastava5ef6ccc2022-05-30 01:35:13 -0500729 std::cout << "Manager called to delete vpd for fru: " << std::string{path}
730 << std::endl;
731
Sunny Srivastava28abd6e2021-07-28 02:58:28 -0500732 using InvalidArgument =
733 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument;
734 using Argument = xyz::openbmc_project::Common::InvalidArgument;
735
Santosh Puranikbc599472022-12-19 20:17:10 +0530736 std::string objPath{path};
737
738 // Strip any inventory prefix in path
739 if (objPath.find(INVENTORY_PATH) == 0)
Sunny Srivastava28abd6e2021-07-28 02:58:28 -0500740 {
Santosh Puranikbc599472022-12-19 20:17:10 +0530741 objPath = objPath.substr(sizeof(INVENTORY_PATH) - 1);
Sunny Srivastava28abd6e2021-07-28 02:58:28 -0500742 }
743
Santosh Puranikbc599472022-12-19 20:17:10 +0530744 // if path not found in Json.
745 if (frus.find(objPath) == frus.end())
746 {
747 elog<InvalidArgument>(Argument::ARGUMENT_NAME("Object Path"),
748 Argument::ARGUMENT_VALUE(objPath.c_str()));
749 }
750
751 inventory::Path& vpdFilePath = std::get<0>(frus.find(objPath)->second);
Alpana Kumari41d498c2021-09-16 00:29:12 -0500752
753 string chipAddress =
754 jsonFile["frus"][vpdFilePath].at(0).value("pcaChipAddress", "");
755
756 // Unbind the LED driver for this FRU
757 cout << "Unbinding device- " << chipAddress << endl;
758 executeCmd(createBindUnbindDriverCmnd(chipAddress, "i2c", "leds-pca955x",
759 "/unbind"));
760
Sunny Srivastava28abd6e2021-07-28 02:58:28 -0500761 // if the FRU is not present then log error
Santosh Puranikbc599472022-12-19 20:17:10 +0530762 if (readBusProperty(objPath, "xyz.openbmc_project.Inventory.Item",
Sunny Srivastava28abd6e2021-07-28 02:58:28 -0500763 "Present") == "false")
764 {
Santosh Puranikbc599472022-12-19 20:17:10 +0530765 elog<InvalidArgument>(Argument::ARGUMENT_NAME("FRU not preset"),
766 Argument::ARGUMENT_VALUE(objPath.c_str()));
Sunny Srivastava28abd6e2021-07-28 02:58:28 -0500767 }
768 else
769 {
Santosh Puranikbc599472022-12-19 20:17:10 +0530770 // Set present property of FRU as false as it has been removed.
771 // CC data for FRU is also removed as
772 // a) FRU is not there so CC does not make sense.
773 // b) Sensors dependent on Panel uses CC data.
774 inventory::InterfaceMap interfaces{
775 {"xyz.openbmc_project.Inventory.Item", {{"Present", false}}},
776 {"com.ibm.ipzvpd.VINI", {{"CC", Binary{}}}}};
777
778 inventory::ObjectMap objectMap;
779 objectMap.emplace(objPath, move(interfaces));
Sunny Srivastava28abd6e2021-07-28 02:58:28 -0500780
781 common::utility::callPIM(move(objectMap));
782 }
783}
784
SunnySrivastava1984b59fd092020-02-03 09:58:56 -0600785} // namespace manager
786} // namespace vpd
Alpana Kumarib17dd3b2020-10-01 00:18:10 -0500787} // namespace openpower