Collect Bad/Broken VPDs in BMC
When there is a vpd failure case due to the
corruption in vpd data, this commit collects the bad vpd
into BMC tmp/bad-vpd directory, so that this bad-vpd directory
gets into BMC Dump collection.
Tested on simics.
1.Corrupted the data of a vpd file.
dd if=/dev/zero of=/sys/devices/platform/ahb/ahb:apb/ahb:apb:bus@1e78a000/1e78a500.i2c-bus/i2c-9/9-0050/9-00500/nvmem bs=1 seek=170 count=3
2.No bad-vpd directory before executing the commit changes.
root@rainier:/tmp# ls
dbus_properties.json systemd-private-9dfe8fba43254dfc8b7be9e4278a3ced-systemd-resolved.service-8pLWbo
ibm-read-vpd systemd-private-9dfe8fba43254dfc8b7be9e4278a3ced-systemd-timesyncd.service-7yowK9
images vpd-manager
overlays vpd-tool
systemd-private-9dfe8fba43254dfc8b7be9e4278a3ced-dbus-broker.service-hb47BQ
root@rainier:/tmp#
3. Due to the data corruption, ibm-read-vpd throws exception
root@rainier:/tmp# ./ibm-read-vpd --file /sys/devices/platform/ahb/ahb:apb/ahb:apb:bus@1e78a000/1e78a500.i2c-bus/i2c-9/9-0050/9-00500/nvmem
std::exception
root@rainier:/tmp#
4. And collects the broken vpd into bad-vpd directory in /tmp
root@rainier:/tmp# ls
bad-vpd systemd-private-9dfe8fba43254dfc8b7be9e4278a3ced-dbus-broker.service-hb47BQ
dbus_properties.json systemd-private-9dfe8fba43254dfc8b7be9e4278a3ced-systemd-resolved.service-8pLWbo
ibm-read-vpd systemd-private-9dfe8fba43254dfc8b7be9e4278a3ced-systemd-timesyncd.service-7yowK9
images vpd-manager
overlays vpd-tool
root@rainier:/tmp#
5. The bad vpd file is stored in /tmp/bad-vpd directory.
root@rainier:/tmp/bad-vpd# ls -l
-rw-r--r-- 1 root root 16384 Mar 28 19:54 i2c-9-0050
-rw-r--r-- 1 root root 65504 Mar 28 20:01 spi22
(vpd-names of i2c eeproms will be in the pattern "i2c-busNumber-eepromAddress";
for spi eeproms - "spiBusNumber")
Signed-off-by: PriyangaRamasamy <priyanga24@in.ibm.com>
Change-Id: I34fb8c61c79e02ca72d7e99413baebf7e5cb3d53
diff --git a/ibm_vpd_utils.cpp b/ibm_vpd_utils.cpp
index 3c7304f..2413a3d 100644
--- a/ibm_vpd_utils.cpp
+++ b/ibm_vpd_utils.cpp
@@ -6,6 +6,7 @@
#include "defines.hpp"
#include "vpd_exceptions.hpp"
+#include <filesystem>
#include <fstream>
#include <iomanip>
#include <nlohmann/json.hpp>
@@ -31,6 +32,7 @@
using namespace openpower::vpd::exceptions;
using namespace common::utility;
using Severity = openpower::vpd::constants::PelSeverity;
+namespace fs = std::filesystem;
// mapping of severity enum to severity interface
static std::unordered_map<Severity, std::string> sevMap = {
@@ -487,5 +489,59 @@
exit(EXIT_SUCCESS);
}
}
+string getBadVpdName(const string& file)
+{
+ string badVpd = BAD_VPD_DIR;
+ if (file.find("i2c") != string::npos)
+ {
+ badVpd += "i2c-";
+ regex i2cPattern("(at24/)([0-9]+-[0-9]+)\\/");
+ smatch match;
+ if (regex_search(file, match, i2cPattern))
+ {
+ badVpd += match.str(2);
+ }
+ }
+ else if (file.find("spi") != string::npos)
+ {
+ regex spiPattern("((spi)[0-9]+)(.0)");
+ smatch match;
+ if (regex_search(file, match, spiPattern))
+ {
+ badVpd += match.str(1);
+ }
+ }
+ return badVpd;
+}
+
+void dumpBadVpd(const string& file, const Binary& vpdVector)
+{
+ fs::path badVpdDir = BAD_VPD_DIR;
+ fs::create_directory(badVpdDir);
+ string badVpdPath = getBadVpdName(file);
+ if (fs::exists(badVpdPath))
+ {
+ std::error_code ec;
+ fs::remove(badVpdPath, ec);
+ if (ec) // error code
+ {
+ string error = "Error removing the existing broken vpd in ";
+ error += badVpdPath;
+ error += ". Error code : ";
+ error += ec.value();
+ error += ". Error message : ";
+ error += ec.message();
+ throw runtime_error(error);
+ }
+ }
+ ofstream badVpdFileStream(badVpdPath, ofstream::binary);
+ if (!badVpdFileStream)
+ {
+ throw runtime_error("Failed to open bad vpd file path in /tmp/bad-vpd. "
+ "Unable to dump the broken/bad vpd file.");
+ }
+ badVpdFileStream.write(reinterpret_cast<const char*>(vpdVector.data()),
+ vpdVector.size());
+}
} // namespace vpd
} // namespace openpower
\ No newline at end of file