VPD tool : dumpInventory & dumpObject
VPD tool has four options.
a) Dump Complete Inventory - no additional arguments are needed.
b) Dump Specific Object - by providing the object name.
c) Read the keyword - by providing the object name, record name and keyword to be read.
d) Write/Update the keyword - by providing the object name, record name, keyword and the value to be updated.
{value - in ascii or hex & all the other arguments in string}
"--help" option provides details on how to use the above mentioned options.
This commit has implementation of dump inventory and dump specific object.
Output:
---------Dump Inventory---------
Not displaying the complete output.
root@rainier:/tmp# ./vpd-tool -i
[
{
"/system": {
"LocationCode": "U9105.22A.SIMP10R",
"Model": "9105-22A",
"SerialNumber": "SIMP10R",
"type": "xyz.openbmc_project.Inventory.Item.System"
},
"/system/chassis": {
"LocationCode": "U78DA.ND1.1234567",
"type": "xyz.openbmc_project.Inventory.Item.Chassis"
},
.
.
.
.
and so on..
]
---------Dump Object----------
root@rainier:/tmp# ./vpd-tool -o -O /system/chassis/motherboard/ebmc_card_bmc
[
{
"/system/chassis/motherboard/ebmc_card_bmc": {
"CC": "6B58",
"DR": "EBMC ",
"FN": "F191014",
"LocationCode": "U78DA.ND1.1234567-P0-C5",
"PN": "PN12345",
"SN": "YL6B58010000",
"type": "xyz.openbmc_project.Inventory.Item.Bmc"
}
}
]
Flag to enable VPD tool:
There is no seperate flag for VPD tool.
ibm-parser flag will generate the vpd-tool binary.
Steps to build and generate the executable using meson:
meson -Denabled=ibm-parser build
ninja -C build
Test:
Tested on simics.
Signed-off-by: PriyangaRamasamy <priyanga24@in.ibm.com>
Change-Id: I712f7ad4303eefa68f232685b6b0e53646f859f5
diff --git a/vpd_tool_impl.cpp b/vpd_tool_impl.cpp
new file mode 100644
index 0000000..ccc2765
--- /dev/null
+++ b/vpd_tool_impl.cpp
@@ -0,0 +1,234 @@
+#include "vpd_tool_impl.hpp"
+
+#include <iostream>
+#include <sdbusplus/bus.hpp>
+#include <sstream>
+#include <variant>
+#include <vector>
+
+using namespace std;
+using sdbusplus::exception::SdBusError;
+using namespace openpower::vpd;
+
+void VpdTool::debugger(json output)
+{
+ cout << output.dump(4) << '\n';
+}
+
+auto VpdTool::makeDBusCall(const string& objectName, const string& interface,
+ const string& kw)
+{
+ auto bus = sdbusplus::bus::new_default();
+ auto properties =
+ bus.new_method_call(INVENTORY_MANAGER_SERVICE, objectName.c_str(),
+ "org.freedesktop.DBus.Properties", "Get");
+ properties.append(interface);
+ properties.append(kw);
+ auto result = bus.call(properties);
+
+ if (result.is_method_error())
+ {
+ throw runtime_error("Get api failed");
+ }
+ return result;
+}
+
+void VpdTool::addFruTypeAndLocation(json exIntf, const string& object,
+ json& kwVal)
+{
+ for (const auto& intf : exIntf.items())
+ {
+ if ((intf.key().find("Item") != string::npos) &&
+ (intf.value().is_null()))
+ {
+ kwVal.emplace("type", intf.key());
+ break;
+ }
+ }
+
+ // Add location code.
+ constexpr auto LOCATION_CODE_IF = "com.ibm.ipzvpd.Location";
+ constexpr auto LOCATION_CODE_PROP = "LocationCode";
+
+ try
+ {
+ variant<string> response;
+ makeDBusCall(object, LOCATION_CODE_IF, LOCATION_CODE_PROP)
+ .read(response);
+
+ if (auto prop = get_if<string>(&response))
+ {
+ kwVal.emplace(LOCATION_CODE_PROP, *prop);
+ }
+ }
+ catch (const SdBusError& e)
+ {
+ kwVal.emplace(LOCATION_CODE_PROP, "");
+ }
+}
+
+json VpdTool::getVINIProperties(string invPath, json exIntf)
+{
+ variant<Binary> response;
+ json output = json::object({});
+ json kwVal = json::object({});
+
+ vector<string> keyword{"CC", "SN", "PN", "FN", "DR"};
+ string interface = "com.ibm.ipzvpd.VINI";
+ string objectName = INVENTORY_PATH + invPath;
+
+ for (string kw : keyword)
+ {
+ try
+ {
+ makeDBusCall(objectName, interface, kw).read(response);
+
+ if (auto vec = get_if<Binary>(&response))
+ {
+ kwVal.emplace(kw, string(vec->begin(), vec->end()));
+ }
+ }
+ catch (const SdBusError& e)
+ {
+ output.emplace(invPath, json::object({}));
+ }
+ }
+
+ addFruTypeAndLocation(exIntf, objectName, kwVal);
+ output.emplace(invPath, kwVal);
+ return output;
+}
+
+void VpdTool::getExtraInterfaceProperties(string invPath, string extraInterface,
+ json prop, json exIntf, json& output)
+{
+ variant<string> response;
+
+ string objectName = INVENTORY_PATH + invPath;
+
+ for (const auto& itProp : prop.items())
+ {
+ string kw = itProp.key();
+ try
+ {
+ makeDBusCall(objectName, extraInterface, kw).read(response);
+
+ if (auto str = get_if<string>(&response))
+ {
+ output.emplace(kw, *str);
+ }
+ }
+ catch (const SdBusError& e)
+ {
+ output.emplace(invPath, json::object({}));
+ }
+ }
+ addFruTypeAndLocation(exIntf, objectName, output);
+}
+
+json VpdTool::interfaceDecider(json& itemEEPROM)
+{
+ if (itemEEPROM.find("inventoryPath") == itemEEPROM.end())
+ {
+ throw runtime_error("Inventory Path not found");
+ }
+
+ if (itemEEPROM.find("extraInterfaces") == itemEEPROM.end())
+ {
+ throw runtime_error("Extra Interfaces not found");
+ }
+
+ bool exIntfCheck = false;
+ json output = json::object({});
+
+ if (itemEEPROM.value("inherit", true))
+ {
+ json j = getVINIProperties(itemEEPROM.at("inventoryPath"),
+ itemEEPROM["extraInterfaces"]);
+ output.insert(j.begin(), j.end());
+ }
+ else
+ {
+ json js;
+ for (const auto& ex : itemEEPROM["extraInterfaces"].items())
+ {
+ if (!(ex.value().is_null()))
+ {
+ exIntfCheck = true;
+ getExtraInterfaceProperties(itemEEPROM.at("inventoryPath"),
+ ex.key(), ex.value(),
+ itemEEPROM["extraInterfaces"], js);
+ }
+ }
+ output.emplace(itemEEPROM.at("inventoryPath"), js);
+ }
+ return output;
+}
+
+json VpdTool::parseInvJson(const json& jsObject, char flag, string fruPath)
+{
+ json output = json::object({});
+ bool validObject = false;
+
+ if (jsObject.find("frus") == jsObject.end())
+ {
+ throw runtime_error("Frus missing in Inventory json");
+ }
+ else
+ {
+ for (const auto& itemFRUS : jsObject["frus"].items())
+ {
+ for (auto itemEEPROM : itemFRUS.value())
+ {
+ try
+ {
+ if (flag == 'O')
+ {
+ if (itemEEPROM.find("inventoryPath") ==
+ itemEEPROM.end())
+ {
+ throw runtime_error("Inventory Path not found");
+ }
+
+ else if (itemEEPROM.at("inventoryPath") == fruPath)
+ {
+ validObject = true;
+ json j = interfaceDecider(itemEEPROM);
+ output.insert(j.begin(), j.end());
+ return output;
+ }
+ }
+ else
+ {
+ json j = interfaceDecider(itemEEPROM);
+ output.insert(j.begin(), j.end());
+ }
+ }
+ catch (exception& e)
+ {
+ cerr << e.what();
+ }
+ }
+ }
+ if ((flag == 'O') && (!validObject))
+ {
+ throw runtime_error(
+ "Invalid object path. Refer --dumpInventory/-i option.");
+ }
+ }
+ return output;
+}
+
+void VpdTool::dumpInventory(const nlohmann::basic_json<>& jsObject)
+{
+ char flag = 'I';
+ json output = parseInvJson(jsObject, flag, "");
+ debugger(output);
+}
+
+void VpdTool::dumpObject(const nlohmann::basic_json<>& jsObject)
+{
+ char flag = 'O';
+ json output = parseInvJson(jsObject, flag, fruPath);
+ debugger(output);
+}