vpd-tool:Fix system VPD and its backup VPD
vpd-tool fixSystemVPD implementation to backup and restore system VPD
to and from the backup VPD if the backup VPD path is found in
vpd inventory JSON.
Test:
(Truncating the output in commit message)
===>>CASE 1: Option 6 to update new value on both backup and primary
hardware and its cache.
vpd-tool --fixSystemVPD
=============================================================
S.No Record Keyword Backup Data Primary Data Data Mismatch
1 UTIL D0 0x01 0x01 NO
============================================================
>> Enter the new value to update on both primary & backup. Value should be in ASCII or in HEX(prefixed with 0x) : 0x00
busctl get-property xyz.openbmc_project.Inventory.Manager /xyz/openbmc_project/inventory/system/chassis/motherboard/base_op_panel_blyth com.ibm.ipzvpd.VSBK D0
ay 1 0
busctl get-property xyz.openbmc_project.Inventory.Manager /xyz/openbmc_project/inventory/system/chassis/motherboard com.ibm.ipzvpd.UTIL D0
ay 1 0
===>>CASE 2: Option 4 to update primary with backup data
vpd-tool -w -O /system/chassis/motherboard -R LXR0 -K LX -V 0x333435363738
Data updated successfully
vpd-tool --fixSystemVPD
=================================================================================
S.No Record Keyword Backup Data Primary Data Data Mismatch
6 LXR0 LX 0x310004010030007b 0x333435363738007b YES
=================================================================================
Enter 4 => If you choose the data on backup as the right value : 4
busctl get-property xyz.openbmc_project.Inventory.Manager /xyz/openbmc_project/inventory/system/chassis/motherboard com.ibm.ipzvpd.LXR0 LX
ay 8 49 0 4 1 0 48 0 123
===>>CASE 3: Option 5 to update backup with primary value
vpd-tool -w -O /system/chassis/motherboard/base_op_panel_blyth -R VSBK -K FC -V "abcd"
Data updated successfully
vpd-tool --fixSystemVPD
=================================================================================
S.No Record Keyword Backup Data Primary Data Data Mismatch
7 VCEN FC 0x616263642d303031 0x324534412d303031 YES
=================================================================================
Enter 5 => If you choose the data on primary as the right value : 5
busctl get-property xyz.openbmc_project.Inventory.Manager /xyz/openbmc_project/inventory/system/chassis/motherboard/base_op_panel_blyth com.ibm.ipzvpd.VSBK FC
ay 8 50 69 52 65 45 48 48 49
===>>CASE 4: Option 2 to update all mismatching keywords with its primary data
vpd-tool -w -O /system/chassis/motherboard/base_op_panel_blyth -R VSBK -K FC -V "abcd"
Data updated successfully
vpd-tool -w -O /system/chassis/motherboard/base_op_panel_blyth -R VSBK -K D0 -V "abcd"
Data updated successfully
vpd-tool --fixSystemVPD
=================================================================================
S.No Record Keyword Backup Data Primary Data Data Mismatch
=================================================================================
1 UTIL D0 0x61 0x01 YES
-------------------------------------------------------------------------------
7 VCEN FC 0x616263642d303031 0x324534412d303031 YES
=================================================================================
Enter 2 => If you choose the data on primary for all mismatching record-keyword pairs : 2
Data updated successfully for all mismatching record-keyword pairs by choosing their corresponding data from primary VPD.
vpd-tool -r -O /system/chassis/motherboard/base_op_panel_blyth -R VSBK -K FC
{
"/system/chassis/motherboard/base_op_panel_blyth": {
"FC": "2E4A-001"
}
}
vpd-tool -r -O /system/chassis/motherboard/base_op_panel_blyth -R VSBK -K D0
{
"/system/chassis/motherboard/base_op_panel_blyth": {
"D0": "0x01"
}
}
===>>CASE 5: Option 1
vpd-tool -w -O /system/chassis/motherboard -R UTIL -K D0 -V "abcd"
Data updated successfully
vpd-tool -w -O /system/chassis/motherboard -R UTIL -K D1 -V "abcd"
Data updated successfully
vpd-tool --fixSystemVPD
=================================================================================
S.No Record Keyword Backup Data Primary Data Data Mismatch
=================================================================================
1 UTIL D0 0x01 0x61 YES
-------------------------------------------------------------------------------
2 UTIL D1 0x00 0x61 YES
=================================================================================
Enter 1 => If you choose the data on backup for all mismatching record-keyword pairs: 1
Data updated successfully for all mismatching record-keyword pairs by choosing their corresponding data from backup. Exit successfully.
vpd-tool -r -O /system/chassis/motherboard -R UTIL -K D0
{
"/system/chassis/motherboard": {
"D0": "0x01"
}
}
vpd-tool -r -O /system/chassis/motherboard -R UTIL -K D1
{
"/system/chassis/motherboard": {
"D1": "0x00"
}
}
Change-Id: I0cfa5c869d4c44d2dd74916b5284fa2ad9b4f398
Signed-off-by: Priyanga Ramasamy <priyanga24@in.ibm.com>
diff --git a/ibm_vpd_utils.cpp b/ibm_vpd_utils.cpp
index 81bd87d..29817b2 100644
--- a/ibm_vpd_utils.cpp
+++ b/ibm_vpd_utils.cpp
@@ -1180,5 +1180,46 @@
}
}
}
+
+void findBackupVPDPaths(std::string& backupEepromPath,
+ std::string& backupInvPath, const nlohmann::json& js)
+{
+ for (const auto& item : js["frus"][constants::systemVpdFilePath])
+ {
+ if (item.find("systemVpdBackupPath") != item.end())
+ {
+ backupEepromPath = item["systemVpdBackupPath"];
+ for (const auto& item : js["frus"][backupEepromPath])
+ {
+ if (item.find("inventoryPath") != item.end())
+ {
+ backupInvPath = item["inventoryPath"];
+ break;
+ }
+ }
+ break;
+ }
+ }
+}
+
+void getBackupRecordKeyword(std::string& record, std::string& keyword)
+{
+ for (const auto& recordKw : svpdKwdMap)
+ {
+ if (record == recordKw.first)
+ {
+ for (const auto& keywordInfo : recordKw.second)
+ {
+ if (keyword == get<0>(keywordInfo))
+ {
+ record = get<4>(keywordInfo);
+ keyword = get<5>(keywordInfo);
+ break;
+ }
+ }
+ break;
+ }
+ }
+}
} // namespace vpd
} // namespace openpower
diff --git a/ibm_vpd_utils.hpp b/ibm_vpd_utils.hpp
index b441b76..82a0083 100644
--- a/ibm_vpd_utils.hpp
+++ b/ibm_vpd_utils.hpp
@@ -539,5 +539,24 @@
*/
void clearVpdOnRemoval(const std::string& objPath,
inventory::InterfaceMap& interfacesPropMap);
+
+/**
+ * @brief Find backup VPD path if any for the system VPD
+ *
+ * @param[out] backupEepromPath - Backup VPD path
+ * @param[out] backupInvPath - Backup inventory path
+ * @param[in] js - Inventory JSON object
+ */
+void findBackupVPDPaths(std::string& backupEepromPath,
+ std::string& backupInvPath, const nlohmann::json& js);
+
+/**
+ * @brief Get backup VPD's record and keyword for the given system VPD keyword
+ *
+ * @param[in,out] record - Record name
+ * @param[in,out] keyword - Keyword name
+ */
+void getBackupRecordKeyword(std::string& record, std::string& keyword);
+
} // namespace vpd
} // namespace openpower
diff --git a/vpd_tool.cpp b/vpd_tool.cpp
index 9bad631..911ce7f 100644
--- a/vpd_tool.cpp
+++ b/vpd_tool.cpp
@@ -199,8 +199,20 @@
}
else if (*fixSystemVPDFlag)
{
+ std::string backupEepromPath;
+ std::string backupInvPath;
+ findBackupVPDPaths(backupEepromPath, backupInvPath, jsObject);
VpdTool vpdToolObj;
- rc = vpdToolObj.fixSystemVPD();
+
+ if (backupEepromPath.empty())
+ {
+ rc = vpdToolObj.fixSystemVPD();
+ }
+ else
+ {
+ rc = vpdToolObj.fixSystemBackupVPD(backupEepromPath,
+ backupInvPath);
+ }
}
else if (*mfgClean)
{
diff --git a/vpd_tool_impl.cpp b/vpd_tool_impl.cpp
index 8b96641..885cd5e 100644
--- a/vpd_tool_impl.cpp
+++ b/vpd_tool_impl.cpp
@@ -117,9 +117,9 @@
Binary vpdVector{};
uint32_t vpdStartOffset = 0;
- vpdVector = getVpdDataInVector(js, constants::systemVpdFilePath);
- ParserInterface* parser = ParserFactory::getParser(
- vpdVector, invPath, constants::systemVpdFilePath, vpdStartOffset);
+ vpdVector = getVpdDataInVector(js, vpdPath);
+ ParserInterface* parser = ParserFactory::getParser(vpdVector, invPath,
+ vpdPath, vpdStartOffset);
auto parseResult = parser->parse();
ParserFactory::freeParser(parser);
@@ -834,7 +834,7 @@
<< "Data Mismatch\n"
<< outline << std::endl;
- int num = 0;
+ uint8_t num = 0;
// Get system VPD data in map
unordered_map<string, DbusPropertyMap> vpdMap;
@@ -929,18 +929,19 @@
make_tuple(++num, record, keyword, busStr, hwValStr, mismatch));
std::string splitLine(191, '-');
- cout << left << setw(6) << num << left << setw(8) << record << left
- << setw(9) << keyword << left << setw(75) << setfill(' ')
- << busStr << left << setw(75) << setfill(' ') << hwValStr
- << left << setw(14) << mismatch << '\n'
+ cout << left << setw(6) << static_cast<int>(num) << left << setw(8)
+ << record << left << setw(9) << keyword << left << setw(75)
+ << setfill(' ') << busStr << left << setw(75) << setfill(' ')
+ << hwValStr << left << setw(14) << mismatch << '\n'
<< splitLine << endl;
}
}
- parseSVPDOptions(js);
+ parseSVPDOptions(js, std::string());
return 0;
}
-void VpdTool::parseSVPDOptions(const nlohmann::json& json)
+void VpdTool::parseSVPDOptions(const nlohmann::json& json,
+ const std::string& backupEEPROMPath)
{
do
{
@@ -992,12 +993,24 @@
}
else if (option == VpdTool::SYSTEM_BACKPLANE_DATA_FOR_ALL)
{
+ std::string hardwarePath = constants::systemVpdFilePath;
+ if (!backupEEPROMPath.empty())
+ {
+ hardwarePath = backupEEPROMPath;
+ }
+
for (const auto& data : recKwData)
{
if (get<5>(data) == "YES")
{
- EditorImpl edit(constants::systemVpdFilePath, json,
- get<1>(data), get<2>(data));
+ std::string record = get<1>(data), keyword = get<2>(data);
+
+ if (!backupEEPROMPath.empty())
+ {
+ getBackupRecordKeyword(record, keyword);
+ }
+
+ EditorImpl edit(hardwarePath, json, record, keyword);
edit.updateKeyword(toBinary(get<4>(data)), 0, true);
mismatchFound = true;
}
@@ -1034,11 +1047,11 @@
<< setw(75) << setfill(' ') << "Primary Data" << left
<< setw(14) << "Data Mismatch" << endl;
- cout << left << setw(6) << get<0>(data) << left << setw(8)
- << get<1>(data) << left << setw(9) << get<2>(data)
- << left << setw(75) << setfill(' ') << get<3>(data)
- << left << setw(75) << setfill(' ') << get<4>(data)
- << left << setw(14) << get<5>(data);
+ cout << left << setw(6) << static_cast<int>(get<0>(data))
+ << left << setw(8) << get<1>(data) << left << setw(9)
+ << get<2>(data) << left << setw(75) << setfill(' ')
+ << get<3>(data) << left << setw(75) << setfill(' ')
+ << get<4>(data) << left << setw(14) << get<5>(data);
cout << '\n' << outline << endl;
@@ -1063,11 +1076,10 @@
cin >> option;
cout << '\n' << outline << endl;
- EditorImpl edit(constants::systemVpdFilePath, json,
- get<1>(data), get<2>(data));
-
if (option == VpdTool::BACKUP_DATA_FOR_CURRENT)
{
+ EditorImpl edit(constants::systemVpdFilePath, json,
+ get<1>(data), get<2>(data));
edit.updateKeyword(toBinary(get<3>(data)), 0, true);
cout << "\nData updated successfully.\n";
break;
@@ -1075,6 +1087,17 @@
else if (option ==
VpdTool::SYSTEM_BACKPLANE_DATA_FOR_CURRENT)
{
+ std::string hardwarePath = constants::systemVpdFilePath;
+ std::string record = get<1>(data);
+ std::string keyword = get<2>(data);
+
+ if (!backupEEPROMPath.empty())
+ {
+ hardwarePath = backupEEPROMPath;
+ getBackupRecordKeyword(record, keyword);
+ }
+
+ EditorImpl edit(hardwarePath, json, record, keyword);
edit.updateKeyword(toBinary(get<4>(data)), 0, true);
cout << "\nData updated successfully.\n";
break;
@@ -1088,7 +1111,21 @@
cin >> value;
cout << '\n' << outline << endl;
+ EditorImpl edit(constants::systemVpdFilePath, json,
+ get<1>(data), get<2>(data));
edit.updateKeyword(toBinary(value), 0, true);
+
+ if (!backupEEPROMPath.empty())
+ {
+ std::string record = get<1>(data);
+ std::string keyword = get<2>(data);
+
+ getBackupRecordKeyword(record, keyword);
+ EditorImpl edit(backupEEPROMPath, json, record,
+ keyword);
+ edit.updateKeyword(toBinary(value), 0, true);
+ }
+
cout << "\nData updated successfully.\n";
break;
}
@@ -1190,3 +1227,125 @@
}
return 0;
}
+
+int VpdTool::fixSystemBackupVPD(const std::string& backupEepromPath,
+ const std::string& backupInvPath)
+{
+ std::string outline(191, '=');
+ cout << "\nRestorable record-keyword pairs and their data on backup & "
+ "primary.\n\n"
+ << outline << std::endl;
+
+ cout << left << setw(6) << "S.No" << left << setw(8) << "Record" << left
+ << setw(9) << "Keyword" << left << setw(75) << "Data On Backup" << left
+ << setw(75) << "Data On Primary" << left << setw(14)
+ << "Data Mismatch\n"
+ << outline << std::endl;
+
+ uint8_t num = 0;
+ // Get system VPD data in map
+ unordered_map<string, DbusPropertyMap> systemVPDMap;
+ json js;
+ getVPDInMap(constants::systemVpdFilePath, systemVPDMap, js,
+ constants::pimPath +
+ static_cast<std::string>(constants::SYSTEM_OBJECT));
+
+ // Get backup VPD data in map
+ unordered_map<string, DbusPropertyMap> backupVPDMap;
+ getVPDInMap(backupEepromPath, backupVPDMap, js,
+ constants::pimPath + backupInvPath);
+
+ for (const auto& recordKw : svpdKwdMap)
+ {
+ const std::string& primaryRecord = recordKw.first;
+
+ std::string primaryValStr{}, backupValStr{};
+
+ for (const auto& keywordInfo : recordKw.second)
+ {
+ const auto& primaryKeyword = get<0>(keywordInfo);
+ const auto& bkRecord = get<4>(keywordInfo);
+ const auto& bkKeyword = get<5>(keywordInfo);
+ string mismatch = "NO";
+ string primaryValue{};
+ string backupValue{};
+
+ // Find keyword value for system VPD (primary VPD)
+ auto primaryRecItr = systemVPDMap.find(primaryRecord);
+ if (primaryRecItr != systemVPDMap.end())
+ {
+ DbusPropertyMap& primaryKwValMap = primaryRecItr->second;
+ auto kwItr = primaryKwValMap.find(primaryKeyword);
+ if (kwItr != primaryKwValMap.end())
+ {
+ primaryValue = kwItr->second;
+ }
+ }
+
+ // Find keyword value for backup VPD
+ auto bkRecItr = backupVPDMap.find(bkRecord);
+ if (bkRecItr != backupVPDMap.end())
+ {
+ DbusPropertyMap& bkKwValMap = bkRecItr->second;
+ auto kwItr = bkKwValMap.find(bkKeyword);
+ if (kwItr != bkKwValMap.end())
+ {
+ backupValue = kwItr->second;
+ }
+ }
+
+ // SE to display in hex string only
+ if (primaryKeyword != "SE")
+ {
+ ostringstream hwValStream;
+ hwValStream << "0x";
+ primaryValStr = hwValStream.str();
+
+ for (uint16_t byte : primaryValue)
+ {
+ hwValStream << setfill('0') << setw(2) << hex << byte;
+ primaryValStr = hwValStream.str();
+ }
+
+ hwValStream.str(std::string());
+ hwValStream << "0x";
+ backupValStr = hwValStream.str();
+
+ for (uint16_t byte : backupValue)
+ {
+ hwValStream << setfill('0') << setw(2) << hex << byte;
+ backupValStr = hwValStream.str();
+ }
+ if (primaryValStr != backupValStr)
+ {
+ mismatch = "YES";
+ }
+ }
+ else
+ {
+ if (primaryValue != backupValue)
+ {
+ mismatch = "YES";
+ }
+
+ primaryValStr = primaryValue;
+ backupValStr = backupValue;
+ }
+
+ recKwData.push_back(make_tuple(++num, primaryRecord, primaryKeyword,
+ backupValStr, primaryValStr,
+ mismatch));
+
+ std::string splitLine(191, '-');
+ cout << left << setw(6) << static_cast<int>(num) << left << setw(8)
+ << primaryRecord << left << setw(9) << primaryKeyword << left
+ << setw(75) << setfill(' ') << backupValStr << left << setw(75)
+ << setfill(' ') << primaryValStr << left << setw(14)
+ << mismatch << '\n'
+ << splitLine << endl;
+ }
+ }
+
+ parseSVPDOptions(js, backupEepromPath);
+ return 0;
+}
diff --git a/vpd_tool_impl.hpp b/vpd_tool_impl.hpp
index 11e6ef8..25f07af 100644
--- a/vpd_tool_impl.hpp
+++ b/vpd_tool_impl.hpp
@@ -12,7 +12,7 @@
// <S.no, Record, Keyword, D-Bus value, HW value, Data mismatch>
using SystemCriticalData =
- std::vector<std::tuple<int, std::string, std::string, std::string,
+ std::vector<std::tuple<uint8_t, std::string, std::string, std::string,
std::string, std::string>>;
class VpdTool
@@ -141,8 +141,10 @@
* @brief Parse through the options to fix system VPD
*
* @param[in] json - Inventory JSON
+ * @param[in] backupEEPROMPath - Backup VPD path
*/
- void parseSVPDOptions(const nlohmann::json& json);
+ void parseSVPDOptions(const nlohmann::json& json,
+ const std::string& backupEEPROMPath);
/**
* @brief List of user options that can be used to fix system VPD keywords.
@@ -279,6 +281,19 @@
int cleanSystemVPD();
/**
+ * @brief Fix system VPD and its backup VPD
+ * API is triggerred if the backup of system VPD has to be taken in a
+ * hardware VPD. User can use the --fixSystemVPD option to restore the
+ * keywords in backup VPD and/or system VPD.
+ *
+ * @param[in] backupEepromPath - Backup VPD path
+ * @param[in] backupInvPath - Backup inventory path
+ * @return returncode
+ */
+ int fixSystemBackupVPD(const std::string& backupEepromPath,
+ const std::string& backupInvPath);
+
+ /**
* @brief Constructor
* Constructor is called during the
* object instantiation for dumpInventory option and