blob: 036f843126220a9ab24131096766be3419c8340d [file] [log] [blame]
SunnySrivastava1984b59fd092020-02-03 09:58:56 -06001#include "config.h"
2
3#include "manager.hpp"
4
SunnySrivastava1984d076da82020-03-05 05:33:35 -06005#include "editor_impl.hpp"
Alpana Kumarib17dd3b2020-10-01 00:18:10 -05006#include "gpioMonitor.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"
SunnySrivastava1984bca5aaa2020-04-21 05:31:04 -05009#include "reader_impl.hpp"
SunnySrivastava19849a195542020-09-07 06:04:50 -050010#include "vpd_exceptions.hpp"
11
12#include <phosphor-logging/elog-errors.hpp>
SunnySrivastava1984b59fd092020-02-03 09:58:56 -060013
Alpana Kumarib17dd3b2020-10-01 00:18:10 -050014using namespace openpower::vpd::manager;
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -060015using namespace openpower::vpd::constants;
SunnySrivastava19841356d7e2020-04-24 04:29:35 -050016using namespace openpower::vpd::inventory;
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -060017using namespace openpower::vpd::manager::editor;
SunnySrivastava1984bca5aaa2020-04-21 05:31:04 -050018using namespace openpower::vpd::manager::reader;
SunnySrivastava19849a195542020-09-07 06:04:50 -050019using namespace std;
20using namespace openpower::vpd::parser;
21using namespace openpower::vpd::exceptions;
22using namespace phosphor::logging;
SunnySrivastava1984b59fd092020-02-03 09:58:56 -060023
24namespace openpower
25{
26namespace vpd
27{
28namespace manager
29{
30Manager::Manager(sdbusplus::bus::bus&& bus, const char* busName,
Priyanga Ramasamy9d149342020-07-16 23:41:26 +053031 const char* objPath, const char* /*iFace*/) :
SunnySrivastava1984b59fd092020-02-03 09:58:56 -060032 ServerObject<ManagerIface>(bus, objPath),
33 _bus(std::move(bus)), _manager(_bus, objPath)
34{
35 _bus.request_name(busName);
36}
37
38void Manager::run()
39{
SunnySrivastava1984de3c60d2020-02-03 10:34:33 -060040 try
41 {
42 processJSON();
Sunny Srivastavaecb5c7d2021-09-02 07:20:24 -050043 listenHostState();
Alpana Kumarib17dd3b2020-10-01 00:18:10 -050044
45 auto event = sdeventplus::Event::get_default();
46 GpioMonitor gpioMon1(jsonFile, event);
47
48 _bus.attach_event(event.get(), SD_EVENT_PRIORITY_IMPORTANT);
49 cout << "VPD manager event loop started\n";
50 event.loop();
SunnySrivastava1984de3c60d2020-02-03 10:34:33 -060051 }
52 catch (const std::exception& e)
53 {
54 std::cerr << e.what() << "\n";
55 }
SunnySrivastava1984de3c60d2020-02-03 10:34:33 -060056}
57
Sunny Srivastavaecb5c7d2021-09-02 07:20:24 -050058void Manager::listenHostState()
59{
60 static std::shared_ptr<sdbusplus::bus::match::match> hostState =
61 std::make_shared<sdbusplus::bus::match::match>(
62 _bus,
63 sdbusplus::bus::match::rules::propertiesChanged(
64 "/xyz/openbmc_project/state/host0",
65 "xyz.openbmc_project.State.Host"),
66 [this](sdbusplus::message::message& msg) {
67 hostStateCallBack(msg);
68 });
69}
70
71void Manager::hostStateCallBack(sdbusplus::message::message& msg)
72{
73 if (msg.is_method_error())
74 {
75 std::cerr << "Error in reading signal " << std::endl;
76 }
77
78 Path object;
79 PropertyMap propMap;
80 msg.read(object, propMap);
81 const auto itr = propMap.find("CurrentHostState");
82 if (itr != propMap.end())
83 {
84 if (auto hostState = std::get_if<std::string>(&(itr->second)))
85 {
86 // implies system is moving from standby to power on state
87 if (*hostState == "xyz.openbmc_project.State.Host.HostState."
88 "TransitioningToRunning")
89 {
90 // check and perfrom recollection for FRUs replaceable at
91 // standby.
92 performVPDRecollection();
93 return;
94 }
95 }
96 std::cerr << "Failed to read Host state" << std::endl;
97 }
98}
99
SunnySrivastava1984de3c60d2020-02-03 10:34:33 -0600100void Manager::processJSON()
101{
Santosh Puranik0246a4d2020-11-04 16:57:39 +0530102 std::ifstream json(INVENTORY_JSON_SYM_LINK, std::ios::binary);
SunnySrivastava1984de3c60d2020-02-03 10:34:33 -0600103
104 if (!json)
105 {
106 throw std::runtime_error("json file not found");
107 }
108
109 jsonFile = nlohmann::json::parse(json);
110 if (jsonFile.find("frus") == jsonFile.end())
111 {
112 throw std::runtime_error("frus group not found in json");
113 }
114
115 const nlohmann::json& groupFRUS =
116 jsonFile["frus"].get_ref<const nlohmann::json::object_t&>();
117 for (const auto& itemFRUS : groupFRUS.items())
118 {
119 const std::vector<nlohmann::json>& groupEEPROM =
120 itemFRUS.value().get_ref<const nlohmann::json::array_t&>();
121 for (const auto& itemEEPROM : groupEEPROM)
SunnySrivastava1984b59fd092020-02-03 09:58:56 -0600122 {
SunnySrivastava198443306542020-04-01 02:50:20 -0500123 bool isMotherboard = false;
124 if (itemEEPROM["extraInterfaces"].find(
125 "xyz.openbmc_project.Inventory.Item.Board.Motherboard") !=
126 itemEEPROM["extraInterfaces"].end())
127 {
128 isMotherboard = true;
129 }
SunnySrivastava1984de3c60d2020-02-03 10:34:33 -0600130 frus.emplace(itemEEPROM["inventoryPath"]
131 .get_ref<const nlohmann::json::string_t&>(),
SunnySrivastava198443306542020-04-01 02:50:20 -0500132 std::make_pair(itemFRUS.key(), isMotherboard));
SunnySrivastava1984bca5aaa2020-04-21 05:31:04 -0500133
Alpana Kumari414d5ae2021-03-04 21:06:35 +0000134 if (itemEEPROM["extraInterfaces"].find(IBM_LOCATION_CODE_INF) !=
Alpana Kumari920408d2020-05-14 00:07:03 -0500135 itemEEPROM["extraInterfaces"].end())
136 {
137 fruLocationCode.emplace(
Alpana Kumari414d5ae2021-03-04 21:06:35 +0000138 itemEEPROM["extraInterfaces"][IBM_LOCATION_CODE_INF]
Alpana Kumari920408d2020-05-14 00:07:03 -0500139 ["LocationCode"]
140 .get_ref<const nlohmann::json::string_t&>(),
141 itemEEPROM["inventoryPath"]
142 .get_ref<const nlohmann::json::string_t&>());
143 }
SunnySrivastava19849a195542020-09-07 06:04:50 -0500144
Sunny Srivastavaecb5c7d2021-09-02 07:20:24 -0500145 if (itemEEPROM.value("replaceableAtStandby", false))
SunnySrivastava19849a195542020-09-07 06:04:50 -0500146 {
147 replaceableFrus.emplace_back(itemFRUS.key());
148 }
SunnySrivastava1984b59fd092020-02-03 09:58:56 -0600149 }
150 }
151}
152
153void Manager::writeKeyword(const sdbusplus::message::object_path path,
154 const std::string recordName,
155 const std::string keyword, const Binary value)
156{
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600157 try
158 {
Santosh Puranik8c796812021-12-01 19:17:56 +0530159 std::string objPath{path};
160 // Strip any inventory prefix in path
161 if (objPath.find(INVENTORY_PATH) == 0)
162 {
163 objPath = objPath.substr(sizeof(INVENTORY_PATH) - 1);
164 }
165
166 if (frus.find(objPath) == frus.end())
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600167 {
168 throw std::runtime_error("Inventory path not found");
169 }
170
Santosh Puranik8c796812021-12-01 19:17:56 +0530171 inventory::Path vpdFilePath = frus.find(objPath)->second.first;
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600172
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500173 // instantiate editor class to update the data
Santosh Puranik8c796812021-12-01 19:17:56 +0530174 EditorImpl edit(vpdFilePath, jsonFile, recordName, keyword, objPath);
PriyangaRamasamyc0a534f2020-08-24 21:29:18 +0530175 edit.updateKeyword(value, true);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600176
SunnySrivastava198443306542020-04-01 02:50:20 -0500177 // if it is a motehrboard FRU need to check for location expansion
Santosh Puranik8c796812021-12-01 19:17:56 +0530178 if (frus.find(objPath)->second.second)
SunnySrivastava198443306542020-04-01 02:50:20 -0500179 {
180 if (recordName == "VCEN" && (keyword == "FC" || keyword == "SE"))
181 {
182 edit.expandLocationCode("fcs");
183 }
184 else if (recordName == "VSYS" &&
185 (keyword == "TM" || keyword == "SE"))
186 {
187 edit.expandLocationCode("mts");
188 }
189 }
190
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500191 return;
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600192 }
193 catch (const std::exception& e)
194 {
195 std::cerr << e.what() << std::endl;
196 }
SunnySrivastava1984b59fd092020-02-03 09:58:56 -0600197}
198
SunnySrivastava19841356d7e2020-04-24 04:29:35 -0500199ListOfPaths
SunnySrivastava1984fb5815a2020-04-24 08:03:52 -0500200 Manager::getFRUsByUnexpandedLocationCode(const LocationCode locationCode,
201 const NodeNumber nodeNumber)
SunnySrivastava1984b59fd092020-02-03 09:58:56 -0600202{
SunnySrivastava19841356d7e2020-04-24 04:29:35 -0500203 ReaderImpl read;
204 return read.getFrusAtLocation(locationCode, nodeNumber, fruLocationCode);
SunnySrivastava1984b59fd092020-02-03 09:58:56 -0600205}
206
SunnySrivastava19841356d7e2020-04-24 04:29:35 -0500207ListOfPaths
SunnySrivastava1984fb5815a2020-04-24 08:03:52 -0500208 Manager::getFRUsByExpandedLocationCode(const LocationCode locationCode)
SunnySrivastava1984b59fd092020-02-03 09:58:56 -0600209{
SunnySrivastava1984fb5815a2020-04-24 08:03:52 -0500210 ReaderImpl read;
211 return read.getFRUsByExpandedLocationCode(locationCode, fruLocationCode);
SunnySrivastava1984b59fd092020-02-03 09:58:56 -0600212}
213
SunnySrivastava1984fb5815a2020-04-24 08:03:52 -0500214LocationCode Manager::getExpandedLocationCode(const LocationCode locationCode,
215 const NodeNumber nodeNumber)
SunnySrivastava1984b59fd092020-02-03 09:58:56 -0600216{
SunnySrivastava1984bca5aaa2020-04-21 05:31:04 -0500217 ReaderImpl read;
218 return read.getExpandedLocationCode(locationCode, nodeNumber,
219 fruLocationCode);
SunnySrivastava1984b59fd092020-02-03 09:58:56 -0600220}
SunnySrivastava1984de3c60d2020-02-03 10:34:33 -0600221
SunnySrivastava19849a195542020-09-07 06:04:50 -0500222void Manager::performVPDRecollection()
223{
224 // get list of FRUs replaceable at standby
225 for (const auto& item : replaceableFrus)
226 {
227 const vector<nlohmann::json>& groupEEPROM = jsonFile["frus"][item];
228 const nlohmann::json& singleFru = groupEEPROM[0];
229
230 const string& inventoryPath =
231 singleFru["inventoryPath"]
232 .get_ref<const nlohmann::json::string_t&>();
233
234 if ((singleFru.find("devAddress") == singleFru.end()) ||
235 (singleFru.find("driverType") == singleFru.end()) ||
236 (singleFru.find("busType") == singleFru.end()))
237 {
238 // The FRUs is marked for replacement but missing mandatory
239 // fields for recollection. Skip to another replaceable fru.
240 log<level::ERR>(
241 "Recollection Failed as mandatory field missing in Json",
242 entry("ERROR=%s",
243 ("Recollection failed for " + inventoryPath).c_str()));
244 continue;
245 }
246
247 string str = "echo ";
248 string deviceAddress = singleFru["devAddress"];
249 const string& driverType = singleFru["driverType"];
250 const string& busType = singleFru["busType"];
251
252 // devTreeStatus flag is present in json as false to mention
253 // that the EEPROM is not mentioned in device tree. If this flag
254 // is absent consider the value to be true, i.e EEPROM is
255 // mentioned in device tree
256 if (!singleFru.value("devTreeStatus", true))
257 {
258 auto pos = deviceAddress.find('-');
259 if (pos != string::npos)
260 {
261 string busNum = deviceAddress.substr(0, pos);
262 deviceAddress =
263 "0x" + deviceAddress.substr(pos + 1, string::npos);
264
265 string deleteDevice = str + deviceAddress + " > /sys/bus/" +
266 busType + "/devices/" + busType + "-" +
267 busNum + "/delete_device";
268 executeCmd(deleteDevice);
269
270 string addDevice = str + driverType + " " + deviceAddress +
271 " > /sys/bus/" + busType + "/devices/" +
272 busType + "-" + busNum + "/new_device";
273 executeCmd(addDevice);
274 }
275 else
276 {
277 log<level::ERR>(
278 "Wrong format of device address in Json",
279 entry(
280 "ERROR=%s",
281 ("Recollection failed for " + inventoryPath).c_str()));
282 continue;
283 }
284 }
285 else
286 {
Alpana Kumarib17dd3b2020-10-01 00:18:10 -0500287 executeCmd(createBindUnbindDriverCmnd(deviceAddress, busType,
288 driverType, "/unbind"));
289 executeCmd(createBindUnbindDriverCmnd(deviceAddress, busType,
290 driverType, "/bind"));
SunnySrivastava19849a195542020-09-07 06:04:50 -0500291 }
292 }
293}
294
SunnySrivastava1984b59fd092020-02-03 09:58:56 -0600295} // namespace manager
296} // namespace vpd
Alpana Kumarib17dd3b2020-10-01 00:18:10 -0500297} // namespace openpower