Correction of VPD using ECC
ECC algorithm corrects VPD data in 32:1 bit ratio in the
event of corruption.
Main Test Cases:
1) Check correction of KW in records.
2) Check correction while writing and reading VPD.
3) Check for Module VPD correction.
Signed-off-by: Giridhari Krishna <giridharikrishnan@gmail.com>
Change-Id: I48a3db18df9d3a2aecde814610ab1b357e6f310d
diff --git a/vpd-manager/editor_impl.cpp b/vpd-manager/editor_impl.cpp
index 4d81278..426dd7b 100644
--- a/vpd-manager/editor_impl.cpp
+++ b/vpd-manager/editor_impl.cpp
@@ -214,6 +214,18 @@
return lowByte;
}
+void EditorImpl::checkRecordData()
+{
+ auto itrToRecordData = vpdFile.cbegin();
+ std::advance(itrToRecordData, thisRecord.recOffset);
+
+ auto itrToRecordECC = vpdFile.cbegin();
+ std::advance(itrToRecordECC, thisRecord.recECCoffset);
+
+ checkECC(itrToRecordData, itrToRecordECC, thisRecord.recSize,
+ thisRecord.recECCLength);
+}
+
void EditorImpl::checkECC(Binary::const_iterator& itrToRecData,
Binary::const_iterator& itrToECCData,
RecordLength recLength, ECCLength eccLength)
@@ -222,9 +234,33 @@
vpdecc_check_data(const_cast<uint8_t*>(&itrToRecData[0]), recLength,
const_cast<uint8_t*>(&itrToECCData[0]), eccLength);
- if (l_status != VPD_ECC_OK)
+ if (l_status == VPD_ECC_CORRECTABLE_DATA)
{
- throw std::runtime_error("Ecc check failed for VTOC");
+ try
+ {
+ if (vpdFileStream.is_open())
+ {
+ vpdFileStream.seekp(startOffset + thisRecord.recOffset,
+ std::ios::beg);
+ auto end = itrToRecData;
+ std::advance(end, recLength);
+ std::copy(itrToRecData, end,
+ std::ostreambuf_iterator<char>(vpdFileStream));
+ }
+ else
+ {
+ throw std::runtime_error("Ecc correction failed");
+ }
+ }
+ catch (const std::fstream::failure& e)
+ {
+ std::cout << "Error while operating on file with exception";
+ throw std::runtime_error("Ecc correction failed");
+ }
+ }
+ else if (l_status != VPD_ECC_OK)
+ {
+ throw std::runtime_error("Ecc check failed");
}
}
@@ -600,8 +636,8 @@
if (vpdType == KW_VAL_PAIR_START_TAG)
{
// objPath should be empty only in case of test run.
- ParserInterface* Iparser =
- ParserFactory::getParser(completeVPDFile, objPath);
+ ParserInterface* Iparser = ParserFactory::getParser(
+ completeVPDFile, objPath, vpdFilePath, startOffset);
IpzVpdParser* ipzParser = dynamic_cast<IpzVpdParser*>(Iparser);
try
@@ -622,6 +658,9 @@
// check record for keywrod
checkRecordForKwd();
+ // Check Data before updating
+ checkRecordData();
+
// update the data to the file
updateData(kwdData);
diff --git a/vpd-manager/editor_impl.hpp b/vpd-manager/editor_impl.hpp
index d10e157..5beedba 100644
--- a/vpd-manager/editor_impl.hpp
+++ b/vpd-manager/editor_impl.hpp
@@ -171,6 +171,9 @@
void makeDbusCall(const std::string& object, const std::string& interface,
const std::string& property, const std::variant<T>& data);
+ /** @brief Method to check the record's Data using ECC */
+ void checkRecordData();
+
// path to the VPD file to edit
inventory::Path vpdFilePath;
@@ -180,6 +183,9 @@
// stream to perform operation on file
std::fstream vpdFileStream;
+ // stream to operate on VPD data
+ std::fstream vpdDataFileStream;
+
// offset to get vpd data from EEPROM
uint32_t startOffset;
diff --git a/vpd-manager/manager.cpp b/vpd-manager/manager.cpp
index 53c9ad8..5fc415e 100644
--- a/vpd-manager/manager.cpp
+++ b/vpd-manager/manager.cpp
@@ -168,11 +168,13 @@
try
{
auto vpdVector = getVpdDataInVector(jsonFile, systemVpdFilePath);
+ uint32_t vpdStartOffset = 0;
const auto& inventoryPath =
jsonFile["frus"][systemVpdFilePath][0]["inventoryPath"]
.get_ref<const nlohmann::json::string_t&>();
- parser = ParserFactory::getParser(vpdVector, (pimPath + inventoryPath));
+ parser = ParserFactory::getParser(vpdVector, (pimPath + inventoryPath),
+ systemVpdFilePath, vpdStartOffset);
auto parseResult = parser->parse();
if (auto pVal = std::get_if<Store>(&parseResult))