vpd-tool #kw support
This commit is to enable vpd-tool read and write support for pound
keywords starting with # and for numeric keywords.
This commit enables a way to read and write keyword values using --file
option, where --file takes a file with absolute path.
when --file option used with --readKeyword flag - vpd-tool saves the
output in the given file.
and when the file option used with --writeKeyword flag - the vpd-tool
takes the value from file and performs write operation.
Test:
-----------------------------------------------
Case 1: Read from hardware and save in text file
-----------------------------------------------
vpd-tool -r -H -O /sys/bus/i2c/drivers/at24/8-0050/eeprom -R PSPD -K "#D" --file /tmp/output.txt
Value read is saved in the file /tmp/output.txt
-----------------------------------------------
Case 2: Write to hardware by taking input from a text file
-----------------------------------------------
:~# cat /tmp/write.txt
00102030405060607020304050601020304050606040302010
:~# vpd-tool -w -O /sys/bus/i2c/drivers/at24/8-0050/eeprom -R PSPD -K "#D" --file /tmp/write.txt -H
Data updated successfully
:~# vpd-tool -r -H -O /sys/bus/i2c/drivers/at24/8-0050/eeprom -R PSPD -K "#D"
{
"/sys/bus/i2c/drivers/at24/8-0050/eeprom": {
"#D": "0x0010203040506060702030405060102030405060604030201000000000 ...0000"
}
}
-----------------------------------------------
Case 3: Read from cache and pipe to text file
-----------------------------------------------
:~# vpd-tool -r -O /system/chassis/motherboard -R PSPD -K "#D" --file /tmp/read-motherboard-#D.txt
Value read is saved in the file /tmp/read-motherboard-#D.txt
-----------------------------------------------
Case 4: Write to cache by taking input from text file
-----------------------------------------------
:~# cat /tmp/write.txt
00102030405060607020304050601020304050606040302010
:~# vpd-tool -w -O /system/chassis/motherboard -R PSPD -K "#D" --file /tmp/write.txt
Data updated successfully
:~# vpd-tool -r -O /system/chassis/motherboard -R PSPD -K "#D"
{
"/system/chassis/motherboard": {
"#D": "0x0010203040506060702030405060102030405060604030201000000000000000000....."
}
}
-----------------------------------------------
Case 5: Write to cache by taking hex input from console
-----------------------------------------------
:~# vpd-tool -w -O /system/chassis/motherboard -R PSPD -K "#D" -V 0x65
Data updated successfully
:~# vpd-tool -r -O /system/chassis/motherboard -R PSPD -K "#D"
{
"/system/chassis/motherboard": {
"#D": "0x65100c0c000000000000000 ...
}
}
Case 5.1: Write to cache by providing ascii values as input from console
vpd-tool -w -O /system/chassis/motherboard -R PSPD -K "#D" -V abcd
Data updated successfully
vpd-tool -r -O /system/chassis/motherboard -R PSPD -K "#D"
{
"/system/chassis/motherboard": {
"#D": "0x6162636440506060702030405060102030405060604030201000000 .."
}
}
-----------------------------------------------
Case 6: Read from cache and display on console
-----------------------------------------------
:~# vpd-tool -r -O /system/chassis/motherboard -R PSPD -K "#D"
{
"/system/chassis/motherboard": {
"#D": "0x00100c0c00000000000000000000000000000000000000 .....
}
}
-----------------------------------------------
Case 7: Read from hardware and display on console
-----------------------------------------------
vpd-tool -r -O /sys/bus/i2c/drivers/at24/8-0050/eeprom -R PSPD -K "#D" -H
{
"/sys/bus/i2c/drivers/at24/8-0050/eeprom": {
"#D": "0x651020304050606070203040506010203040506060403020100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ......... 000000000000000000000000000000000000000"
}
}
-----------------------------------------------
Case 8: Write to hardware via console
-----------------------------------------------
vpd-tool -w -H -O /sys/bus/i2c/drivers/at24/8-0050/eeprom -R PSPD -K "#D" -V 0x00100c0c000000000000000000000000000000000000
Data updated successfully
vpd-tool -r -O /sys/bus/i2c/drivers/at24/8-0050/eeprom -R PSPD -K "#D" -H
{
"/sys/bus/i2c/drivers/at24/8-0050/eeprom": {
"#D": "0x00100c0c00000000000000000000000000000000000030201000000000000000000000000 ...
}
}
-----------------------------------------------
Case 9: Write 10240 bytes on dbus
-----------------------------------------------
time vpd-tool -w -O /system/chassis/motherboard -R PSPD -K "#D" --file /tmp/output.txt
Data updated successfully
real 0m49.564s
user 0m0.047s
sys 0m0.009s
time vpd-tool -r -O /system/chassis/motherboard -R PSPD -K "#D"
{
"/system/chassis/motherboard": {
"#D": "0x01100c0c0000.....0000123456782746002"
}
}
real 0m0.072s
user 0m0.057s
sys 0m0.001s
------------------------------------------------
Signed-off-by: Priyanga Ramasamy <priyanga24@in.ibm.com>
Change-Id: I3977a7778b28ebcada7788f619b18bbca6ed0c8c
diff --git a/vpd_tool_impl.cpp b/vpd_tool_impl.cpp
index 93c4d40..5870659 100644
--- a/vpd_tool_impl.cpp
+++ b/vpd_tool_impl.cpp
@@ -22,6 +22,71 @@
using namespace openpower::vpd::parser::factory;
using namespace openpower::vpd::parser::interface;
+bool VpdTool::fileToVector(Binary& data)
+{
+ try
+ {
+ std::ifstream file(value, std::ifstream::in);
+
+ if (file)
+ {
+ std::string line;
+ while (std::getline(file, line))
+ {
+ std::istringstream iss(line);
+ std::string byteStr;
+ while (iss >> std::setw(2) >> std::hex >> byteStr)
+ {
+ uint8_t byte = strtoul(byteStr.c_str(), nullptr, 16);
+ data.emplace(data.end(), byte);
+ }
+ }
+ return true;
+ }
+ else
+ {
+ std::cerr << "Unable to open the given file " << value << std::endl;
+ }
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << e.what();
+ }
+ return false;
+}
+
+bool VpdTool::copyStringToFile(const std::string& input)
+{
+ try
+ {
+ std::ofstream outFile(value, std::ofstream::out);
+
+ if (outFile.is_open())
+ {
+ std::string hexString = input;
+ if (input.substr(0, 2) == "0x")
+ {
+ // truncating prefix 0x
+ hexString = input.substr(2);
+ }
+ outFile.write(hexString.c_str(), hexString.length());
+ }
+ else
+ {
+ std::cerr << "Error opening output file " << value << std::endl;
+ return false;
+ }
+
+ outFile.close();
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << e.what();
+ return false;
+ }
+ return true;
+}
+
static void
getVPDInMap(const std::string& vpdPath,
std::unordered_map<std::string, DbusPropertyMap>& vpdMap,
@@ -320,8 +385,9 @@
}
catch (const sdbusplus::exception::SdBusError& e)
{
- // not required to handle the exception. Present will be set to Unknown
+ presence = "Unknown";
}
+
json js;
js.emplace("Present", presence);
return js;
@@ -408,14 +474,14 @@
void VpdTool::readKeyword()
{
+ const std::string& kw = getDbusNameForThisKw(keyword);
+
string interface = "com.ibm.ipzvpd.";
variant<Binary> response;
try
{
- json output = json::object({});
- json kwVal = json::object({});
- makeDBusCall(INVENTORY_PATH + fruPath, interface + recordName, keyword)
+ makeDBusCall(INVENTORY_PATH + fruPath, interface + recordName, kw)
.read(response);
string printableVal{};
@@ -423,6 +489,25 @@
{
printableVal = getPrintableValue(*vec);
}
+
+ if (!value.empty())
+ {
+ if (copyStringToFile(printableVal))
+ {
+ std::cout << "Value read is saved in the file " << value
+ << std::endl;
+ return;
+ }
+ else
+ {
+ std::cerr << "Error while saving the read value in file. "
+ "Displaying the read value on console"
+ << std::endl;
+ }
+ }
+
+ json output = json::object({});
+ json kwVal = json::object({});
kwVal.emplace(keyword, printableVal);
output.emplace(fruPath, kwVal);
@@ -438,7 +523,22 @@
int VpdTool::updateKeyword()
{
- Binary val = toBinary(value);
+ Binary val;
+
+ if (std::filesystem::exists(value))
+ {
+ if (!fileToVector(val))
+ {
+ std::cout << "Keyword " << keyword << " update failed."
+ << std::endl;
+ return 1;
+ }
+ }
+ else
+ {
+ val = toBinary(value);
+ }
+
auto bus = sdbusplus::bus::new_default();
auto properties =
bus.new_method_call(BUSNAME, OBJPATH, IFACE, "WriteKeyword");
@@ -446,12 +546,18 @@
properties.append(recordName);
properties.append(keyword);
properties.append(val);
- auto result = bus.call(properties);
+
+ // When there is a request to write 10K bytes, there occurs a delay in dbus
+ // call which leads to dbus timeout exception. To avoid such exceptions
+ // increase the timeout period from default 25 seconds to 60 seconds.
+ auto timeoutInMicroSeconds = 60 * 1000000L;
+ auto result = bus.call(properties, timeoutInMicroSeconds);
if (result.is_method_error())
{
throw runtime_error("Get api failed");
}
+ std::cout << "Data updated successfully " << std::endl;
return 0;
}
@@ -505,7 +611,21 @@
int VpdTool::updateHardware(const uint32_t offset)
{
int rc = 0;
- const Binary& val = static_cast<const Binary&>(toBinary(value));
+ Binary val;
+ if (std::filesystem::exists(value))
+ {
+ if (!fileToVector(val))
+ {
+ std::cout << "Keyword " << keyword << " update failed."
+ << std::endl;
+ return 1;
+ }
+ }
+ else
+ {
+ val = toBinary(value);
+ }
+
ifstream inventoryJson(INVENTORY_JSON_SYM_LINK);
try
{
@@ -518,6 +638,7 @@
{
throw(VpdJsonException("Json Parsing failed", INVENTORY_JSON_SYM_LINK));
}
+ std::cout << "Data updated successfully " << std::endl;
return rc;
}
@@ -558,23 +679,39 @@
vpdStartOffset);
std::string keywordVal = obj.readKwFromHw(recordName, keyword);
- if (!keywordVal.empty())
- {
- json output = json::object({});
- json kwVal = json::object({});
- kwVal.emplace(keyword, getPrintableValue(keywordVal));
+ keywordVal = getPrintableValue(keywordVal);
- output.emplace(fruPath, kwVal);
-
- debugger(output);
- }
- else
+ if (keywordVal.empty())
{
std::cerr << "The given keyword " << keyword << " or record "
<< recordName
<< " or both are not present in the given FRU path "
<< fruPath << std::endl;
+ return;
}
+
+ if (!value.empty())
+ {
+ if (copyStringToFile(keywordVal))
+ {
+ std::cout << "Value read is saved in the file " << value
+ << std::endl;
+ return;
+ }
+ else
+ {
+ std::cerr
+ << "Error while saving the read value in file. Displaying "
+ "the read value on console"
+ << std::endl;
+ }
+ }
+
+ json output = json::object({});
+ json kwVal = json::object({});
+ kwVal.emplace(keyword, keywordVal);
+ output.emplace(fruPath, kwVal);
+ debugger(output);
}
void VpdTool::printFixSystemVPDOption(UserOption option)
@@ -998,10 +1135,9 @@
}
}
- std::cout
- << "\n The critical keywords from system backplane VPD has been "
- "reset successfully."
- << std::endl;
+ std::cout << "\n The critical keywords from system backplane VPD has "
+ "been reset successfully."
+ << std::endl;
}
catch (const std::exception& e)
{
@@ -1010,4 +1146,4 @@
<< "\nManufacturing reset on system vpd keywords is unsuccessful";
}
return 0;
-}
+}
\ No newline at end of file