blob: 69fbe6e331911025dcc2c1fc83809387898faac3 [file] [log] [blame]
SunnySrivastava198443306542020-04-01 02:50:20 -05001#include "config.h"
2
Deepak Kodihalli76794492017-02-16 23:48:18 -06003#include "utils.hpp"
Patrick Venturec83c4dc2018-11-01 16:29:18 -07004
SunnySrivastava1984d076da82020-03-05 05:33:35 -06005#include "defines.hpp"
PriyangaRamasamyc0a534f2020-08-24 21:29:18 +05306#include "vpd_exceptions.hpp"
SunnySrivastava1984d076da82020-03-05 05:33:35 -06007
PriyangaRamasamyc0a534f2020-08-24 21:29:18 +05308#include <fstream>
9#include <iomanip>
SunnySrivastava19849094d4f2020-08-05 09:32:29 -050010#include <phosphor-logging/elog-errors.hpp>
Patrick Venturec83c4dc2018-11-01 16:29:18 -070011#include <phosphor-logging/log.hpp>
12#include <sdbusplus/server.hpp>
PriyangaRamasamyc0a534f2020-08-24 21:29:18 +053013#include <sstream>
14#include <vector>
SunnySrivastava19849094d4f2020-08-05 09:32:29 -050015#include <xyz/openbmc_project/Common/error.hpp>
Deepak Kodihalli76794492017-02-16 23:48:18 -060016
PriyangaRamasamyc0a534f2020-08-24 21:29:18 +053017using json = nlohmann::json;
18
Deepak Kodihalli76794492017-02-16 23:48:18 -060019namespace openpower
20{
21namespace vpd
22{
SunnySrivastava1984945a02d2020-05-06 01:55:41 -050023using namespace openpower::vpd::constants;
SunnySrivastava1984a20be8e2020-08-26 02:00:50 -050024using namespace inventory;
25using namespace phosphor::logging;
SunnySrivastava19849094d4f2020-08-05 09:32:29 -050026using namespace sdbusplus::xyz::openbmc_project::Common::Error;
PriyangaRamasamyc0a534f2020-08-24 21:29:18 +053027using namespace record;
28using namespace openpower::vpd::exceptions;
Deepak Kodihalli76794492017-02-16 23:48:18 -060029namespace inventory
30{
31
SunnySrivastava1984a20be8e2020-08-26 02:00:50 -050032std::string getService(sdbusplus::bus::bus& bus, const std::string& path,
33 const std::string& interface)
Deepak Kodihalli76794492017-02-16 23:48:18 -060034{
SunnySrivastava1984a20be8e2020-08-26 02:00:50 -050035 auto mapper = bus.new_method_call(mapperDestination, mapperObjectPath,
36 mapperInterface, "GetObject");
37 mapper.append(path, std::vector<std::string>({interface}));
Deepak Kodihalli76794492017-02-16 23:48:18 -060038
39 std::map<std::string, std::vector<std::string>> response;
SunnySrivastava1984a20be8e2020-08-26 02:00:50 -050040 try
41 {
42 auto reply = bus.call(mapper);
43 reply.read(response);
44 }
45 catch (const sdbusplus::exception::SdBusError& e)
46 {
47 log<level::ERR>("D-Bus call exception",
48 entry("OBJPATH=%s", mapperObjectPath),
49 entry("INTERFACE=%s", mapperInterface),
50 entry("EXCEPTION=%s", e.what()));
51
52 throw std::runtime_error("Service name is not found");
53 }
54
Patrick Venturec83c4dc2018-11-01 16:29:18 -070055 if (response.empty())
Deepak Kodihalli76794492017-02-16 23:48:18 -060056 {
SunnySrivastava1984a20be8e2020-08-26 02:00:50 -050057 throw std::runtime_error("Service name response is empty");
Deepak Kodihalli76794492017-02-16 23:48:18 -060058 }
59
60 return response.begin()->first;
61}
62
63void callPIM(ObjectMap&& objects)
64{
Deepak Kodihalli76794492017-02-16 23:48:18 -060065 try
66 {
Deepak Kodihalli76794492017-02-16 23:48:18 -060067 auto bus = sdbusplus::bus::new_default();
SunnySrivastava1984a20be8e2020-08-26 02:00:50 -050068 auto service = getService(bus, pimPath, pimIntf);
Patrick Venturec83c4dc2018-11-01 16:29:18 -070069 auto pimMsg =
70 bus.new_method_call(service.c_str(), pimPath, pimIntf, "Notify");
Deepak Kodihalli76794492017-02-16 23:48:18 -060071 pimMsg.append(std::move(objects));
72 auto result = bus.call(pimMsg);
Patrick Venturec83c4dc2018-11-01 16:29:18 -070073 if (result.is_method_error())
Deepak Kodihalli76794492017-02-16 23:48:18 -060074 {
75 std::cerr << "PIM Notify() failed\n";
76 }
77 }
78 catch (const std::runtime_error& e)
79 {
Deepak Kodihalli76794492017-02-16 23:48:18 -060080 log<level::ERR>(e.what());
81 }
82}
83
SunnySrivastava19849094d4f2020-08-05 09:32:29 -050084MapperResponse
85 getObjectSubtreeForInterfaces(const std::string& root, const int32_t depth,
86 const std::vector<std::string>& interfaces)
87{
88 auto bus = sdbusplus::bus::new_default();
89 auto mapperCall = bus.new_method_call(mapperDestination, mapperObjectPath,
90 mapperInterface, "GetSubTree");
91 mapperCall.append(root);
92 mapperCall.append(depth);
93 mapperCall.append(interfaces);
94
95 MapperResponse result = {};
96
97 try
98 {
99 auto response = bus.call(mapperCall);
100
101 response.read(result);
102 }
103 catch (const sdbusplus::exception::SdBusError& e)
104 {
105 log<level::ERR>("Error in mapper GetSubTree",
106 entry("ERROR=%s", e.what()));
107 }
108
109 return result;
110}
111
Deepak Kodihalli76794492017-02-16 23:48:18 -0600112} // namespace inventory
113
SunnySrivastava1984945a02d2020-05-06 01:55:41 -0500114vpdType vpdTypeCheck(const Binary& vpdVector)
115{
116 // Read first 3 Bytes to check the 11S bar code format
117 std::string is11SFormat = "";
118 for (uint8_t i = 0; i < FORMAT_11S_LEN; i++)
119 {
120 is11SFormat += vpdVector[MEMORY_VPD_DATA_START + i];
121 }
122
123 if (vpdVector[IPZ_DATA_START] == KW_VAL_PAIR_START_TAG)
124 {
125 // IPZ VPD FORMAT
126 return vpdType::IPZ_VPD;
127 }
128 else if (vpdVector[KW_VPD_DATA_START] == KW_VPD_START_TAG)
129 {
130 // KEYWORD VPD FORMAT
131 return vpdType::KEYWORD_VPD;
132 }
133 else if (is11SFormat.compare(MEMORY_VPD_START_TAG) == 0)
134 {
135 // Memory VPD format
136 return vpdType::MEMORY_VPD;
137 }
138
139 // INVALID VPD FORMAT
140 return vpdType::INVALID_VPD_FORMAT;
141}
142
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600143LE2ByteData readUInt16LE(Binary::const_iterator iterator)
144{
145 LE2ByteData lowByte = *iterator;
146 LE2ByteData highByte = *(iterator + 1);
147 lowByte |= (highByte << 8);
148 return lowByte;
149}
150
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600151/** @brief Encodes a keyword for D-Bus.
152 */
153string encodeKeyword(const string& kw, const string& encoding)
154{
155 if (encoding == "MAC")
156 {
157 string res{};
158 size_t first = kw[0];
159 res += toHex(first >> 4);
160 res += toHex(first & 0x0f);
161 for (size_t i = 1; i < kw.size(); ++i)
162 {
163 res += ":";
164 res += toHex(kw[i] >> 4);
165 res += toHex(kw[i] & 0x0f);
166 }
167 return res;
168 }
169 else if (encoding == "DATE")
170 {
171 // Date, represent as
172 // <year>-<month>-<day> <hour>:<min>
173 string res{};
174 static constexpr uint8_t skipPrefix = 3;
175
176 auto strItr = kw.begin();
177 advance(strItr, skipPrefix);
178 for_each(strItr, kw.end(), [&res](size_t c) { res += c; });
179
180 res.insert(BD_YEAR_END, 1, '-');
181 res.insert(BD_MONTH_END, 1, '-');
182 res.insert(BD_DAY_END, 1, ' ');
183 res.insert(BD_HOUR_END, 1, ':');
184
185 return res;
186 }
187 else // default to string encoding
188 {
189 return string(kw.begin(), kw.end());
190 }
191}
SunnySrivastava198443306542020-04-01 02:50:20 -0500192
193string readBusProperty(const string& obj, const string& inf, const string& prop)
194{
195 std::string propVal{};
196 std::string object = INVENTORY_PATH + obj;
197 auto bus = sdbusplus::bus::new_default();
198 auto properties = bus.new_method_call(
199 "xyz.openbmc_project.Inventory.Manager", object.c_str(),
200 "org.freedesktop.DBus.Properties", "Get");
201 properties.append(inf);
202 properties.append(prop);
203 auto result = bus.call(properties);
204 if (!result.is_method_error())
205 {
SunnySrivastava1984bca5aaa2020-04-21 05:31:04 -0500206 variant<Binary, string> val;
SunnySrivastava198443306542020-04-01 02:50:20 -0500207 result.read(val);
SunnySrivastava198443306542020-04-01 02:50:20 -0500208 if (auto pVal = get_if<Binary>(&val))
209 {
210 propVal.assign(reinterpret_cast<const char*>(pVal->data()),
211 pVal->size());
212 }
SunnySrivastava1984bca5aaa2020-04-21 05:31:04 -0500213 else if (auto pVal = get_if<string>(&val))
214 {
215 propVal.assign(pVal->data(), pVal->size());
216 }
SunnySrivastava198443306542020-04-01 02:50:20 -0500217 }
218 return propVal;
219}
SunnySrivastava1984a20be8e2020-08-26 02:00:50 -0500220
221void createPEL(const std::map<std::string, std::string>& additionalData,
222 const std::string& errIntf)
223{
224 try
225 {
226 auto bus = sdbusplus::bus::new_default();
SunnySrivastava1984a20be8e2020-08-26 02:00:50 -0500227 auto service = getService(bus, loggerObjectPath, loggerCreateInterface);
228 auto method = bus.new_method_call(service.c_str(), loggerObjectPath,
229 loggerCreateInterface, "Create");
230
231 method.append(errIntf, "xyz.openbmc_project.Logging.Entry.Level.Error",
232 additionalData);
233 auto resp = bus.call(method);
234 }
235 catch (const sdbusplus::exception::SdBusError& e)
236 {
237 throw std::runtime_error(
238 "Error in invoking D-Bus logging create interface to register PEL");
239 }
240}
PriyangaRamasamyc0a534f2020-08-24 21:29:18 +0530241
242inventory::VPDfilepath getVpdFilePath(const string& jsonFile,
243 const std::string& ObjPath)
244{
245 ifstream inventoryJson(jsonFile);
246 const auto& jsonObject = json::parse(inventoryJson);
247 inventory::VPDfilepath filePath{};
248
249 if (jsonObject.find("frus") == jsonObject.end())
250 {
251 throw(VpdJsonException(
252 "Invalid JSON structure - frus{} object not found in ", jsonFile));
253 }
254
255 const nlohmann::json& groupFRUS =
256 jsonObject["frus"].get_ref<const nlohmann::json::object_t&>();
257 for (const auto& itemFRUS : groupFRUS.items())
258 {
259 const std::vector<nlohmann::json>& groupEEPROM =
260 itemFRUS.value().get_ref<const nlohmann::json::array_t&>();
261 for (const auto& itemEEPROM : groupEEPROM)
262 {
263 if (itemEEPROM["inventoryPath"]
264 .get_ref<const nlohmann::json::string_t&>() == ObjPath)
265 {
266 filePath = itemFRUS.key();
267 return filePath;
268 }
269 }
270 }
271
272 return filePath;
273}
274
275bool isPathInJson(const std::string& eepromPath)
276{
277 bool present = false;
278 ifstream inventoryJson(INVENTORY_JSON_SYM_LINK);
279
280 try
281 {
282 auto js = json::parse(inventoryJson);
283 if (js.find("frus") == js.end())
284 {
285 throw(VpdJsonException(
286 "Invalid JSON structure - frus{} object not found in ",
287 INVENTORY_JSON_SYM_LINK));
288 }
289 json fruJson = js["frus"];
290
291 if (fruJson.find(eepromPath) != fruJson.end())
292 {
293 present = true;
294 }
295 }
296 catch (json::parse_error& ex)
297 {
298 throw(VpdJsonException("Json Parsing failed", INVENTORY_JSON_SYM_LINK));
299 }
300 return present;
301}
302
303bool isRecKwInDbusJson(const std::string& recordName,
304 const std::string& keyword)
305{
306 ifstream propertyJson(DBUS_PROP_JSON);
307 json dbusProperty;
308 bool present = false;
309
310 if (propertyJson.is_open())
311 {
312 try
313 {
314 auto dbusPropertyJson = json::parse(propertyJson);
315 if (dbusPropertyJson.find("dbusProperties") ==
316 dbusPropertyJson.end())
317 {
318 throw(VpdJsonException("dbusProperties{} object not found in "
319 "DbusProperties json : ",
320 DBUS_PROP_JSON));
321 }
322
323 dbusProperty = dbusPropertyJson["dbusProperties"];
324 if (dbusProperty.contains(recordName))
325 {
326 const vector<string>& kwdsToPublish = dbusProperty[recordName];
327 if (find(kwdsToPublish.begin(), kwdsToPublish.end(), keyword) !=
328 kwdsToPublish.end()) // present
329 {
330 present = true;
331 }
332 }
333 }
334 catch (json::parse_error& ex)
335 {
336 throw(VpdJsonException("Json Parsing failed", DBUS_PROP_JSON));
337 }
338 }
339 else
340 {
341 // If dbus properties json is not available, we assume the given
342 // record-keyword is part of dbus-properties json. So setting the bool
343 // variable to true.
344 present = true;
345 }
346 return present;
347}
348
Patrick Venturec83c4dc2018-11-01 16:29:18 -0700349} // namespace vpd
350} // namespace openpower