blob: 829dce8808a369f7556a89e31c1a7a388f67cf46 [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"
Sunny Srivastava6c71c9d2021-04-15 04:43:54 -05006#include "ibm_vpd_utils.hpp"
SunnySrivastava1984e12b1812020-05-26 02:23:11 -05007#include "ipz_parser.hpp"
SunnySrivastava1984bca5aaa2020-04-21 05:31:04 -05008#include "reader_impl.hpp"
SunnySrivastava19849a195542020-09-07 06:04:50 -05009#include "vpd_exceptions.hpp"
10
11#include <phosphor-logging/elog-errors.hpp>
SunnySrivastava1984b59fd092020-02-03 09:58:56 -060012
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -060013using namespace openpower::vpd::constants;
SunnySrivastava19841356d7e2020-04-24 04:29:35 -050014using namespace openpower::vpd::inventory;
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -060015using namespace openpower::vpd::manager::editor;
SunnySrivastava1984bca5aaa2020-04-21 05:31:04 -050016using namespace openpower::vpd::manager::reader;
SunnySrivastava19849a195542020-09-07 06:04:50 -050017using namespace std;
18using namespace openpower::vpd::parser;
19using namespace openpower::vpd::exceptions;
20using namespace phosphor::logging;
SunnySrivastava1984b59fd092020-02-03 09:58:56 -060021
22namespace openpower
23{
24namespace vpd
25{
26namespace manager
27{
28Manager::Manager(sdbusplus::bus::bus&& bus, const char* busName,
Priyanga Ramasamy9d149342020-07-16 23:41:26 +053029 const char* objPath, const char* /*iFace*/) :
SunnySrivastava1984b59fd092020-02-03 09:58:56 -060030 ServerObject<ManagerIface>(bus, objPath),
31 _bus(std::move(bus)), _manager(_bus, objPath)
32{
33 _bus.request_name(busName);
34}
35
36void Manager::run()
37{
SunnySrivastava1984de3c60d2020-02-03 10:34:33 -060038 try
39 {
40 processJSON();
41 }
42 catch (const std::exception& e)
43 {
44 std::cerr << e.what() << "\n";
45 }
46
SunnySrivastava1984b59fd092020-02-03 09:58:56 -060047 while (true)
48 {
SunnySrivastava1984de3c60d2020-02-03 10:34:33 -060049 _bus.process_discard();
50
51 // wait for event
52 _bus.wait();
53 }
54}
55
56void Manager::processJSON()
57{
Santosh Puranik0246a4d2020-11-04 16:57:39 +053058 std::ifstream json(INVENTORY_JSON_SYM_LINK, std::ios::binary);
SunnySrivastava1984de3c60d2020-02-03 10:34:33 -060059
60 if (!json)
61 {
62 throw std::runtime_error("json file not found");
63 }
64
65 jsonFile = nlohmann::json::parse(json);
66 if (jsonFile.find("frus") == jsonFile.end())
67 {
68 throw std::runtime_error("frus group not found in json");
69 }
70
71 const nlohmann::json& groupFRUS =
72 jsonFile["frus"].get_ref<const nlohmann::json::object_t&>();
73 for (const auto& itemFRUS : groupFRUS.items())
74 {
75 const std::vector<nlohmann::json>& groupEEPROM =
76 itemFRUS.value().get_ref<const nlohmann::json::array_t&>();
77 for (const auto& itemEEPROM : groupEEPROM)
SunnySrivastava1984b59fd092020-02-03 09:58:56 -060078 {
SunnySrivastava198443306542020-04-01 02:50:20 -050079 bool isMotherboard = false;
80 if (itemEEPROM["extraInterfaces"].find(
81 "xyz.openbmc_project.Inventory.Item.Board.Motherboard") !=
82 itemEEPROM["extraInterfaces"].end())
83 {
84 isMotherboard = true;
85 }
SunnySrivastava1984de3c60d2020-02-03 10:34:33 -060086 frus.emplace(itemEEPROM["inventoryPath"]
87 .get_ref<const nlohmann::json::string_t&>(),
SunnySrivastava198443306542020-04-01 02:50:20 -050088 std::make_pair(itemFRUS.key(), isMotherboard));
SunnySrivastava1984bca5aaa2020-04-21 05:31:04 -050089
Alpana Kumari414d5ae2021-03-04 21:06:35 +000090 if (itemEEPROM["extraInterfaces"].find(IBM_LOCATION_CODE_INF) !=
Alpana Kumari920408d2020-05-14 00:07:03 -050091 itemEEPROM["extraInterfaces"].end())
92 {
93 fruLocationCode.emplace(
Alpana Kumari414d5ae2021-03-04 21:06:35 +000094 itemEEPROM["extraInterfaces"][IBM_LOCATION_CODE_INF]
Alpana Kumari920408d2020-05-14 00:07:03 -050095 ["LocationCode"]
96 .get_ref<const nlohmann::json::string_t&>(),
97 itemEEPROM["inventoryPath"]
98 .get_ref<const nlohmann::json::string_t&>());
99 }
SunnySrivastava19849a195542020-09-07 06:04:50 -0500100
101 if (itemEEPROM.value("isReplaceable", false))
102 {
103 replaceableFrus.emplace_back(itemFRUS.key());
104 }
SunnySrivastava1984b59fd092020-02-03 09:58:56 -0600105 }
106 }
107}
108
109void Manager::writeKeyword(const sdbusplus::message::object_path path,
110 const std::string recordName,
111 const std::string keyword, const Binary value)
112{
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600113 try
114 {
115 if (frus.find(path) == frus.end())
116 {
117 throw std::runtime_error("Inventory path not found");
118 }
119
SunnySrivastava198443306542020-04-01 02:50:20 -0500120 inventory::Path vpdFilePath = frus.find(path)->second.first;
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600121
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500122 // instantiate editor class to update the data
Alpana Kumari920408d2020-05-14 00:07:03 -0500123 EditorImpl edit(vpdFilePath, jsonFile, recordName, keyword, path);
PriyangaRamasamyc0a534f2020-08-24 21:29:18 +0530124 edit.updateKeyword(value, true);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600125
SunnySrivastava198443306542020-04-01 02:50:20 -0500126 // if it is a motehrboard FRU need to check for location expansion
127 if (frus.find(path)->second.second)
128 {
129 if (recordName == "VCEN" && (keyword == "FC" || keyword == "SE"))
130 {
131 edit.expandLocationCode("fcs");
132 }
133 else if (recordName == "VSYS" &&
134 (keyword == "TM" || keyword == "SE"))
135 {
136 edit.expandLocationCode("mts");
137 }
138 }
139
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500140 return;
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600141 }
142 catch (const std::exception& e)
143 {
144 std::cerr << e.what() << std::endl;
145 }
SunnySrivastava1984b59fd092020-02-03 09:58:56 -0600146}
147
SunnySrivastava19841356d7e2020-04-24 04:29:35 -0500148ListOfPaths
SunnySrivastava1984fb5815a2020-04-24 08:03:52 -0500149 Manager::getFRUsByUnexpandedLocationCode(const LocationCode locationCode,
150 const NodeNumber nodeNumber)
SunnySrivastava1984b59fd092020-02-03 09:58:56 -0600151{
SunnySrivastava19841356d7e2020-04-24 04:29:35 -0500152 ReaderImpl read;
153 return read.getFrusAtLocation(locationCode, nodeNumber, fruLocationCode);
SunnySrivastava1984b59fd092020-02-03 09:58:56 -0600154}
155
SunnySrivastava19841356d7e2020-04-24 04:29:35 -0500156ListOfPaths
SunnySrivastava1984fb5815a2020-04-24 08:03:52 -0500157 Manager::getFRUsByExpandedLocationCode(const LocationCode locationCode)
SunnySrivastava1984b59fd092020-02-03 09:58:56 -0600158{
SunnySrivastava1984fb5815a2020-04-24 08:03:52 -0500159 ReaderImpl read;
160 return read.getFRUsByExpandedLocationCode(locationCode, fruLocationCode);
SunnySrivastava1984b59fd092020-02-03 09:58:56 -0600161}
162
SunnySrivastava1984fb5815a2020-04-24 08:03:52 -0500163LocationCode Manager::getExpandedLocationCode(const LocationCode locationCode,
164 const NodeNumber nodeNumber)
SunnySrivastava1984b59fd092020-02-03 09:58:56 -0600165{
SunnySrivastava1984bca5aaa2020-04-21 05:31:04 -0500166 ReaderImpl read;
167 return read.getExpandedLocationCode(locationCode, nodeNumber,
168 fruLocationCode);
SunnySrivastava1984b59fd092020-02-03 09:58:56 -0600169}
SunnySrivastava1984de3c60d2020-02-03 10:34:33 -0600170
SunnySrivastava19849a195542020-09-07 06:04:50 -0500171void Manager::performVPDRecollection()
172{
173 // get list of FRUs replaceable at standby
174 for (const auto& item : replaceableFrus)
175 {
176 const vector<nlohmann::json>& groupEEPROM = jsonFile["frus"][item];
177 const nlohmann::json& singleFru = groupEEPROM[0];
178
179 const string& inventoryPath =
180 singleFru["inventoryPath"]
181 .get_ref<const nlohmann::json::string_t&>();
182
183 if ((singleFru.find("devAddress") == singleFru.end()) ||
184 (singleFru.find("driverType") == singleFru.end()) ||
185 (singleFru.find("busType") == singleFru.end()))
186 {
187 // The FRUs is marked for replacement but missing mandatory
188 // fields for recollection. Skip to another replaceable fru.
189 log<level::ERR>(
190 "Recollection Failed as mandatory field missing in Json",
191 entry("ERROR=%s",
192 ("Recollection failed for " + inventoryPath).c_str()));
193 continue;
194 }
195
196 string str = "echo ";
197 string deviceAddress = singleFru["devAddress"];
198 const string& driverType = singleFru["driverType"];
199 const string& busType = singleFru["busType"];
200
201 // devTreeStatus flag is present in json as false to mention
202 // that the EEPROM is not mentioned in device tree. If this flag
203 // is absent consider the value to be true, i.e EEPROM is
204 // mentioned in device tree
205 if (!singleFru.value("devTreeStatus", true))
206 {
207 auto pos = deviceAddress.find('-');
208 if (pos != string::npos)
209 {
210 string busNum = deviceAddress.substr(0, pos);
211 deviceAddress =
212 "0x" + deviceAddress.substr(pos + 1, string::npos);
213
214 string deleteDevice = str + deviceAddress + " > /sys/bus/" +
215 busType + "/devices/" + busType + "-" +
216 busNum + "/delete_device";
217 executeCmd(deleteDevice);
218
219 string addDevice = str + driverType + " " + deviceAddress +
220 " > /sys/bus/" + busType + "/devices/" +
221 busType + "-" + busNum + "/new_device";
222 executeCmd(addDevice);
223 }
224 else
225 {
226 log<level::ERR>(
227 "Wrong format of device address in Json",
228 entry(
229 "ERROR=%s",
230 ("Recollection failed for " + inventoryPath).c_str()));
231 continue;
232 }
233 }
234 else
235 {
236 string cmd = str + deviceAddress + " > /sys/bus/" + busType +
237 "/drivers/" + driverType;
238
239 executeCmd(cmd + "/unbind");
240 executeCmd(cmd + "/bind");
241 }
242 }
243}
244
SunnySrivastava1984b59fd092020-02-03 09:58:56 -0600245} // namespace manager
246} // namespace vpd
247} // namespace openpower