blob: d691c84d0172078fe9b824e668cb095d4f8c6cda [file] [log] [blame]
SunnySrivastava198443306542020-04-01 02:50:20 -05001#include "config.h"
2
Sunny Srivastava6c71c9d2021-04-15 04:43:54 -05003#include "ibm_vpd_utils.hpp"
Patrick Venturec83c4dc2018-11-01 16:29:18 -07004
Sunny Srivastava6c71c9d2021-04-15 04:43:54 -05005#include "common_utility.hpp"
SunnySrivastava1984d076da82020-03-05 05:33:35 -06006#include "defines.hpp"
PriyangaRamasamyc0a534f2020-08-24 21:29:18 +05307#include "vpd_exceptions.hpp"
SunnySrivastava1984d076da82020-03-05 05:33:35 -06008
PriyangaRamasamyc0a534f2020-08-24 21:29:18 +05309#include <fstream>
10#include <iomanip>
Sunny Srivastava6c71c9d2021-04-15 04:43:54 -050011#include <nlohmann/json.hpp>
SunnySrivastava19849094d4f2020-08-05 09:32:29 -050012#include <phosphor-logging/elog-errors.hpp>
Patrick Venturec83c4dc2018-11-01 16:29:18 -070013#include <phosphor-logging/log.hpp>
14#include <sdbusplus/server.hpp>
PriyangaRamasamyc0a534f2020-08-24 21:29:18 +053015#include <sstream>
16#include <vector>
SunnySrivastava19849094d4f2020-08-05 09:32:29 -050017#include <xyz/openbmc_project/Common/error.hpp>
Deepak Kodihalli76794492017-02-16 23:48:18 -060018
PriyangaRamasamyc0a534f2020-08-24 21:29:18 +053019using json = nlohmann::json;
20
Deepak Kodihalli76794492017-02-16 23:48:18 -060021namespace openpower
22{
23namespace vpd
24{
SunnySrivastava1984945a02d2020-05-06 01:55:41 -050025using namespace openpower::vpd::constants;
SunnySrivastava1984a20be8e2020-08-26 02:00:50 -050026using namespace inventory;
27using namespace phosphor::logging;
SunnySrivastava19849094d4f2020-08-05 09:32:29 -050028using namespace sdbusplus::xyz::openbmc_project::Common::Error;
PriyangaRamasamyc0a534f2020-08-24 21:29:18 +053029using namespace record;
30using namespace openpower::vpd::exceptions;
Sunny Srivastava6c71c9d2021-04-15 04:43:54 -050031using namespace common::utility;
Deepak Kodihalli76794492017-02-16 23:48:18 -060032namespace inventory
33{
34
SunnySrivastava19849094d4f2020-08-05 09:32:29 -050035MapperResponse
36 getObjectSubtreeForInterfaces(const std::string& root, const int32_t depth,
37 const std::vector<std::string>& interfaces)
38{
39 auto bus = sdbusplus::bus::new_default();
40 auto mapperCall = bus.new_method_call(mapperDestination, mapperObjectPath,
41 mapperInterface, "GetSubTree");
42 mapperCall.append(root);
43 mapperCall.append(depth);
44 mapperCall.append(interfaces);
45
46 MapperResponse result = {};
47
48 try
49 {
50 auto response = bus.call(mapperCall);
51
52 response.read(result);
53 }
54 catch (const sdbusplus::exception::SdBusError& e)
55 {
56 log<level::ERR>("Error in mapper GetSubTree",
57 entry("ERROR=%s", e.what()));
58 }
59
60 return result;
61}
62
Deepak Kodihalli76794492017-02-16 23:48:18 -060063} // namespace inventory
64
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -060065LE2ByteData readUInt16LE(Binary::const_iterator iterator)
66{
67 LE2ByteData lowByte = *iterator;
68 LE2ByteData highByte = *(iterator + 1);
69 lowByte |= (highByte << 8);
70 return lowByte;
71}
72
SunnySrivastava1984d076da82020-03-05 05:33:35 -060073/** @brief Encodes a keyword for D-Bus.
74 */
75string encodeKeyword(const string& kw, const string& encoding)
76{
77 if (encoding == "MAC")
78 {
79 string res{};
80 size_t first = kw[0];
81 res += toHex(first >> 4);
82 res += toHex(first & 0x0f);
83 for (size_t i = 1; i < kw.size(); ++i)
84 {
85 res += ":";
86 res += toHex(kw[i] >> 4);
87 res += toHex(kw[i] & 0x0f);
88 }
89 return res;
90 }
91 else if (encoding == "DATE")
92 {
93 // Date, represent as
94 // <year>-<month>-<day> <hour>:<min>
95 string res{};
96 static constexpr uint8_t skipPrefix = 3;
97
98 auto strItr = kw.begin();
99 advance(strItr, skipPrefix);
100 for_each(strItr, kw.end(), [&res](size_t c) { res += c; });
101
102 res.insert(BD_YEAR_END, 1, '-');
103 res.insert(BD_MONTH_END, 1, '-');
104 res.insert(BD_DAY_END, 1, ' ');
105 res.insert(BD_HOUR_END, 1, ':');
106
107 return res;
108 }
109 else // default to string encoding
110 {
111 return string(kw.begin(), kw.end());
112 }
113}
SunnySrivastava198443306542020-04-01 02:50:20 -0500114
115string readBusProperty(const string& obj, const string& inf, const string& prop)
116{
117 std::string propVal{};
118 std::string object = INVENTORY_PATH + obj;
119 auto bus = sdbusplus::bus::new_default();
120 auto properties = bus.new_method_call(
121 "xyz.openbmc_project.Inventory.Manager", object.c_str(),
122 "org.freedesktop.DBus.Properties", "Get");
123 properties.append(inf);
124 properties.append(prop);
125 auto result = bus.call(properties);
126 if (!result.is_method_error())
127 {
SunnySrivastava1984bca5aaa2020-04-21 05:31:04 -0500128 variant<Binary, string> val;
SunnySrivastava198443306542020-04-01 02:50:20 -0500129 result.read(val);
SunnySrivastava198443306542020-04-01 02:50:20 -0500130 if (auto pVal = get_if<Binary>(&val))
131 {
132 propVal.assign(reinterpret_cast<const char*>(pVal->data()),
133 pVal->size());
134 }
SunnySrivastava1984bca5aaa2020-04-21 05:31:04 -0500135 else if (auto pVal = get_if<string>(&val))
136 {
137 propVal.assign(pVal->data(), pVal->size());
138 }
SunnySrivastava198443306542020-04-01 02:50:20 -0500139 }
140 return propVal;
141}
SunnySrivastava1984a20be8e2020-08-26 02:00:50 -0500142
143void createPEL(const std::map<std::string, std::string>& additionalData,
144 const std::string& errIntf)
145{
146 try
147 {
148 auto bus = sdbusplus::bus::new_default();
SunnySrivastava1984a20be8e2020-08-26 02:00:50 -0500149 auto service = getService(bus, loggerObjectPath, loggerCreateInterface);
150 auto method = bus.new_method_call(service.c_str(), loggerObjectPath,
151 loggerCreateInterface, "Create");
152
153 method.append(errIntf, "xyz.openbmc_project.Logging.Entry.Level.Error",
154 additionalData);
155 auto resp = bus.call(method);
156 }
157 catch (const sdbusplus::exception::SdBusError& e)
158 {
159 throw std::runtime_error(
160 "Error in invoking D-Bus logging create interface to register PEL");
161 }
162}
PriyangaRamasamyc0a534f2020-08-24 21:29:18 +0530163
164inventory::VPDfilepath getVpdFilePath(const string& jsonFile,
165 const std::string& ObjPath)
166{
167 ifstream inventoryJson(jsonFile);
168 const auto& jsonObject = json::parse(inventoryJson);
169 inventory::VPDfilepath filePath{};
170
171 if (jsonObject.find("frus") == jsonObject.end())
172 {
173 throw(VpdJsonException(
174 "Invalid JSON structure - frus{} object not found in ", jsonFile));
175 }
176
177 const nlohmann::json& groupFRUS =
178 jsonObject["frus"].get_ref<const nlohmann::json::object_t&>();
179 for (const auto& itemFRUS : groupFRUS.items())
180 {
181 const std::vector<nlohmann::json>& groupEEPROM =
182 itemFRUS.value().get_ref<const nlohmann::json::array_t&>();
183 for (const auto& itemEEPROM : groupEEPROM)
184 {
185 if (itemEEPROM["inventoryPath"]
186 .get_ref<const nlohmann::json::string_t&>() == ObjPath)
187 {
188 filePath = itemFRUS.key();
189 return filePath;
190 }
191 }
192 }
193
194 return filePath;
195}
196
197bool isPathInJson(const std::string& eepromPath)
198{
199 bool present = false;
200 ifstream inventoryJson(INVENTORY_JSON_SYM_LINK);
201
202 try
203 {
204 auto js = json::parse(inventoryJson);
205 if (js.find("frus") == js.end())
206 {
207 throw(VpdJsonException(
208 "Invalid JSON structure - frus{} object not found in ",
209 INVENTORY_JSON_SYM_LINK));
210 }
211 json fruJson = js["frus"];
212
213 if (fruJson.find(eepromPath) != fruJson.end())
214 {
215 present = true;
216 }
217 }
218 catch (json::parse_error& ex)
219 {
220 throw(VpdJsonException("Json Parsing failed", INVENTORY_JSON_SYM_LINK));
221 }
222 return present;
223}
224
225bool isRecKwInDbusJson(const std::string& recordName,
226 const std::string& keyword)
227{
228 ifstream propertyJson(DBUS_PROP_JSON);
229 json dbusProperty;
230 bool present = false;
231
232 if (propertyJson.is_open())
233 {
234 try
235 {
236 auto dbusPropertyJson = json::parse(propertyJson);
237 if (dbusPropertyJson.find("dbusProperties") ==
238 dbusPropertyJson.end())
239 {
240 throw(VpdJsonException("dbusProperties{} object not found in "
241 "DbusProperties json : ",
242 DBUS_PROP_JSON));
243 }
244
245 dbusProperty = dbusPropertyJson["dbusProperties"];
246 if (dbusProperty.contains(recordName))
247 {
248 const vector<string>& kwdsToPublish = dbusProperty[recordName];
249 if (find(kwdsToPublish.begin(), kwdsToPublish.end(), keyword) !=
250 kwdsToPublish.end()) // present
251 {
252 present = true;
253 }
254 }
255 }
256 catch (json::parse_error& ex)
257 {
258 throw(VpdJsonException("Json Parsing failed", DBUS_PROP_JSON));
259 }
260 }
261 else
262 {
263 // If dbus properties json is not available, we assume the given
264 // record-keyword is part of dbus-properties json. So setting the bool
265 // variable to true.
266 present = true;
267 }
268 return present;
269}
270
Sunny Srivastava6c71c9d2021-04-15 04:43:54 -0500271vpdType vpdTypeCheck(const Binary& vpdVector)
272{
273 // Read first 3 Bytes to check the 11S bar code format
274 std::string is11SFormat = "";
275 for (uint8_t i = 0; i < FORMAT_11S_LEN; i++)
276 {
277 is11SFormat += vpdVector[MEMORY_VPD_DATA_START + i];
278 }
279
280 if (vpdVector[IPZ_DATA_START] == KW_VAL_PAIR_START_TAG)
281 {
282 // IPZ VPD FORMAT
283 return vpdType::IPZ_VPD;
284 }
285 else if (vpdVector[KW_VPD_DATA_START] == KW_VPD_START_TAG)
286 {
287 // KEYWORD VPD FORMAT
288 return vpdType::KEYWORD_VPD;
289 }
290 else if (is11SFormat.compare(MEMORY_VPD_START_TAG) == 0)
291 {
292 // Memory VPD format
293 return vpdType::MEMORY_VPD;
294 }
295
296 // INVALID VPD FORMAT
297 return vpdType::INVALID_VPD_FORMAT;
298}
299
Patrick Venturec83c4dc2018-11-01 16:29:18 -0700300} // namespace vpd
301} // namespace openpower