blob: d7c8504fea76cf52c78d0e4e7895f9a4b5bcbd87 [file] [log] [blame]
PriyangaRamasamy1f0b1e62020-02-20 20:48:25 +05301#include "vpd_tool_impl.hpp"
2
3#include <iostream>
4#include <sdbusplus/bus.hpp>
5#include <sstream>
6#include <variant>
7#include <vector>
8
9using namespace std;
10using sdbusplus::exception::SdBusError;
11using namespace openpower::vpd;
12
13void VpdTool::debugger(json output)
14{
15 cout << output.dump(4) << '\n';
16}
17
18auto VpdTool::makeDBusCall(const string& objectName, const string& interface,
19 const string& kw)
20{
21 auto bus = sdbusplus::bus::new_default();
22 auto properties =
23 bus.new_method_call(INVENTORY_MANAGER_SERVICE, objectName.c_str(),
24 "org.freedesktop.DBus.Properties", "Get");
25 properties.append(interface);
26 properties.append(kw);
27 auto result = bus.call(properties);
28
29 if (result.is_method_error())
30 {
31 throw runtime_error("Get api failed");
32 }
33 return result;
34}
35
36void VpdTool::addFruTypeAndLocation(json exIntf, const string& object,
37 json& kwVal)
38{
39 for (const auto& intf : exIntf.items())
40 {
41 if ((intf.key().find("Item") != string::npos) &&
42 (intf.value().is_null()))
43 {
44 kwVal.emplace("type", intf.key());
45 break;
46 }
47 }
48
49 // Add location code.
50 constexpr auto LOCATION_CODE_IF = "com.ibm.ipzvpd.Location";
51 constexpr auto LOCATION_CODE_PROP = "LocationCode";
52
53 try
54 {
55 variant<string> response;
56 makeDBusCall(object, LOCATION_CODE_IF, LOCATION_CODE_PROP)
57 .read(response);
58
59 if (auto prop = get_if<string>(&response))
60 {
61 kwVal.emplace(LOCATION_CODE_PROP, *prop);
62 }
63 }
64 catch (const SdBusError& e)
65 {
66 kwVal.emplace(LOCATION_CODE_PROP, "");
67 }
68}
69
70json VpdTool::getVINIProperties(string invPath, json exIntf)
71{
72 variant<Binary> response;
73 json output = json::object({});
74 json kwVal = json::object({});
75
76 vector<string> keyword{"CC", "SN", "PN", "FN", "DR"};
77 string interface = "com.ibm.ipzvpd.VINI";
78 string objectName = INVENTORY_PATH + invPath;
79
80 for (string kw : keyword)
81 {
82 try
83 {
84 makeDBusCall(objectName, interface, kw).read(response);
85
86 if (auto vec = get_if<Binary>(&response))
87 {
88 kwVal.emplace(kw, string(vec->begin(), vec->end()));
89 }
90 }
91 catch (const SdBusError& e)
92 {
93 output.emplace(invPath, json::object({}));
94 }
95 }
96
97 addFruTypeAndLocation(exIntf, objectName, kwVal);
98 output.emplace(invPath, kwVal);
99 return output;
100}
101
102void VpdTool::getExtraInterfaceProperties(string invPath, string extraInterface,
103 json prop, json exIntf, json& output)
104{
105 variant<string> response;
106
107 string objectName = INVENTORY_PATH + invPath;
108
109 for (const auto& itProp : prop.items())
110 {
111 string kw = itProp.key();
112 try
113 {
114 makeDBusCall(objectName, extraInterface, kw).read(response);
115
116 if (auto str = get_if<string>(&response))
117 {
118 output.emplace(kw, *str);
119 }
120 }
121 catch (const SdBusError& e)
122 {
123 output.emplace(invPath, json::object({}));
124 }
125 }
126 addFruTypeAndLocation(exIntf, objectName, output);
127}
128
129json VpdTool::interfaceDecider(json& itemEEPROM)
130{
131 if (itemEEPROM.find("inventoryPath") == itemEEPROM.end())
132 {
133 throw runtime_error("Inventory Path not found");
134 }
135
136 if (itemEEPROM.find("extraInterfaces") == itemEEPROM.end())
137 {
138 throw runtime_error("Extra Interfaces not found");
139 }
140
141 bool exIntfCheck = false;
142 json output = json::object({});
143
144 if (itemEEPROM.value("inherit", true))
145 {
146 json j = getVINIProperties(itemEEPROM.at("inventoryPath"),
147 itemEEPROM["extraInterfaces"]);
148 output.insert(j.begin(), j.end());
149 }
150 else
151 {
152 json js;
153 for (const auto& ex : itemEEPROM["extraInterfaces"].items())
154 {
155 if (!(ex.value().is_null()))
156 {
157 exIntfCheck = true;
158 getExtraInterfaceProperties(itemEEPROM.at("inventoryPath"),
159 ex.key(), ex.value(),
160 itemEEPROM["extraInterfaces"], js);
161 }
162 }
163 output.emplace(itemEEPROM.at("inventoryPath"), js);
164 }
165 return output;
166}
167
168json VpdTool::parseInvJson(const json& jsObject, char flag, string fruPath)
169{
170 json output = json::object({});
171 bool validObject = false;
172
173 if (jsObject.find("frus") == jsObject.end())
174 {
175 throw runtime_error("Frus missing in Inventory json");
176 }
177 else
178 {
179 for (const auto& itemFRUS : jsObject["frus"].items())
180 {
181 for (auto itemEEPROM : itemFRUS.value())
182 {
183 try
184 {
185 if (flag == 'O')
186 {
187 if (itemEEPROM.find("inventoryPath") ==
188 itemEEPROM.end())
189 {
190 throw runtime_error("Inventory Path not found");
191 }
192
193 else if (itemEEPROM.at("inventoryPath") == fruPath)
194 {
195 validObject = true;
196 json j = interfaceDecider(itemEEPROM);
197 output.insert(j.begin(), j.end());
198 return output;
199 }
200 }
201 else
202 {
203 json j = interfaceDecider(itemEEPROM);
204 output.insert(j.begin(), j.end());
205 }
206 }
207 catch (exception& e)
208 {
209 cerr << e.what();
210 }
211 }
212 }
213 if ((flag == 'O') && (!validObject))
214 {
215 throw runtime_error(
216 "Invalid object path. Refer --dumpInventory/-i option.");
217 }
218 }
219 return output;
220}
221
222void VpdTool::dumpInventory(const nlohmann::basic_json<>& jsObject)
223{
224 char flag = 'I';
225 json output = parseInvJson(jsObject, flag, "");
226 debugger(output);
227}
228
229void VpdTool::dumpObject(const nlohmann::basic_json<>& jsObject)
230{
231 char flag = 'O';
232 json output = parseInvJson(jsObject, flag, fruPath);
233 debugger(output);
234}
PriyangaRamasamy02d4d4e2020-02-24 14:54:45 +0530235
236void VpdTool::readKeyword()
237{
238 string interface = "com.ibm.ipzvpd.";
239 variant<Binary> response;
240
241 try
242 {
243 json output = json::object({});
244 json kwVal = json::object({});
245 makeDBusCall(INVENTORY_PATH + fruPath, interface + recordName, keyword)
246 .read(response);
247
248 if (auto vec = get_if<Binary>(&response))
249 {
250 kwVal.emplace(keyword, string(vec->begin(), vec->end()));
251 }
252
253 output.emplace(fruPath, kwVal);
254
255 debugger(output);
256 }
257 catch (json::exception& e)
258 {
259 json output = json::object({});
260 json kwVal = json::object({});
261
262 if (e.id == 316) // invalid UTF-8 byte exception
263 {
264 stringstream ss;
265 string hexByte;
266 string hexRep = "0x";
267 ss << hexRep;
268 hexByte = ss.str();
269
270 // convert Decimal to Hex
271 if (auto resp = get_if<Binary>(&response))
272 {
273 for (auto& vec : *resp)
274 {
275 if ((int)vec == 0)
276 {
277 ss << hex << (int)vec;
278 hexByte = ss.str();
279 }
280 ss << hex << (int)vec;
281 hexByte = ss.str();
282 }
283 }
284
285 kwVal.emplace(keyword, hexByte);
286 output.emplace(fruPath, kwVal);
287
288 debugger(output);
289 }
290 }
291}