Translate Udev Event path to a generic path
Given Udev event generated path is translated into sys bus path - as the json will
have the sys/bus path.
Test:
-> Translation successful for all frus including frus behind muxes.
-> If the system vpd is triggered by udev event, then the execution stops as
the system vpd will already be parsed via system-vpd.service.
Few Reasons why we translate the path to a generic path:
-> Each i2c bus is memory mapped to a certain address in ASPEED.
In future if there are any architectural changes in the kernel, we need to
make changes to the JSON accordingly.
-> Also in future if the system runs on a different ASPEED, we need to
update the JSON accordingly.
-> This generic /sys/bus path represents the system wiring and doesnot rely on
how the busses are memory mapped.
-> Also for call out based events, generic path is expected than the udev event path.
Sample Udev Event i2c path : "/sys/devices/platform/ahb/ahb:apb/ahb:apb:bus@1e78a000/1e78a480.i2c-bus/i2c-8/8-0050/8-00500/nvmem"
Which gets translated to /sys/bus/ path as : "/sys/bus/i2c/drivers/at24/8-0050/eeprom"
Sample Udev Event spi path : "/sys/devices/platform/ahb/ahb:apb/1e79b000.fsi/fsi-master/fsi0/slave@00:00/00:00:00:0a/fsi-master/fsi1/slave@03:00/01:03:00:04/spi_master/spi6/spi6.0/spi6.00/nvmem"
Which gets translated to /sys/bus/ path as : "/sys/bus/spi/drivers/at25/spi6.0/eeprom"
Sample Udev Event i2c path for frus behind mux : "/sys/devices/platform/ahb/ahb:apb/ahb:apb:bus@1e78a000/1e78a300.i2c-bus/i2c-5/i2c-24/24-0051/24-00510/nvmem"
Which gets translated to generic path as /sys/bus/i2c/drivers/at24/24-0051/eeprom
Tested on simics:
<the inventory json should have generic eeprom paths for all frus>
root@rainier:/tmp# ./ibm-read-vpd-UG -f /sys/devices/platform/ahb/ahb:apb/1e79b000.fsi/fsi-master/fsi0/slave@00:00/00:00:00:04/spi_master/spi12/spi12.0/spi12.00/nvmem
the path after translation : /sys/bus/spi/drivers/at25/spi12.0/eeprom
root@rainier:/tmp# ./ibm-read-vpd-UG -f /sys/devices/platform/ahb/ahb:apb/ahb:apb:bus@1e78a000/1e78a480.i2c-bus/i2c-8/8-0051/8-00510/nvmem
the path after translation : /sys/bus/i2c/drivers/at24/8-0051/eeprom
root@rainier:/tmp# ./ibm-read-vpd-UG -f /sys/bus/i2c/drivers/at24/8-0051/8-00510/nvmem
the path after translation : /sys/bus/i2c/drivers/at24/8-0051/eeprom
Signed-off-by: PriyangaRamasamy <priyanga24@in.ibm.com>
Change-Id: I6d5995a85ef15e63d2d0b6f054fb0bf14a2b756c
diff --git a/const.hpp b/const.hpp
index 92107fa..e173e89 100644
--- a/const.hpp
+++ b/const.hpp
@@ -90,6 +90,9 @@
constexpr auto motherBoardInterface =
"xyz.openbmc_project.Inventory.Item.Board.Motherboard";
constexpr auto systemVpdFilePath = "/sys/bus/i2c/drivers/at24/8-0050/eeprom";
+constexpr auto i2cPathPrefix = "/sys/bus/i2c/drivers/at24/";
+constexpr auto spiPathPrefix = "/sys/bus/spi/drivers/at25/";
+
namespace lengths
{
enum Lengths
diff --git a/ibm_vpd_app.cpp b/ibm_vpd_app.cpp
index 6532982..1c212f8 100644
--- a/ibm_vpd_app.cpp
+++ b/ibm_vpd_app.cpp
@@ -887,7 +887,6 @@
int main(int argc, char** argv)
{
int rc = 0;
- string file{};
json js{};
// map to hold additional data in case of logging pel
@@ -902,9 +901,9 @@
try
{
+ string file{};
App app{"ibm-read-vpd - App to read IPZ format VPD, parse it and store "
"in DBUS"};
- string file{};
app.add_option("-f, --file", file, "File containing VPD (IPZ/KEYWORD)")
->required();
@@ -942,6 +941,22 @@
throw(VpdJsonException("Json parsing failed", jsonToParse));
}
+ // Check if it's a udev path - patterned as(/ahb/ahb:apb/ahb:apb:bus@)
+ if (file.find("/ahb:apb") != string::npos)
+ {
+ // Translate udev path to a generic /sys/bus/.. file path.
+ udevToGenericPath(file);
+ if (js["frus"][file].at(0).value("isSystemVpd", false))
+ {
+ return 0;
+ }
+ }
+
+ if (file.empty())
+ {
+ cerr << "The EEPROM path <" << file << "> is not valid.";
+ return 0;
+ }
if ((js.find("frus") == js.end()) ||
(js["frus"].find(file) == js["frus"].end()))
{
@@ -970,13 +985,6 @@
try
{
- // check if vpd file is empty
- if (file.empty())
- {
- throw(VpdDataException(
- "VPD file is empty. Can't process with blank file."));
- }
-
Binary vpdVector = getVpdDataInVector(js, file);
ParserInterface* parser = ParserFactory::getParser(move(vpdVector));
diff --git a/ibm_vpd_utils.cpp b/ibm_vpd_utils.cpp
index 15e3116..3c7304f 100644
--- a/ibm_vpd_utils.cpp
+++ b/ibm_vpd_utils.cpp
@@ -11,6 +11,7 @@
#include <nlohmann/json.hpp>
#include <phosphor-logging/elog-errors.hpp>
#include <phosphor-logging/log.hpp>
+#include <regex>
#include <sdbusplus/server.hpp>
#include <sstream>
#include <vector>
@@ -420,5 +421,71 @@
return jsonPath;
}
+void udevToGenericPath(string& file)
+{
+ // Sample udevEvent i2c path :
+ // "/sys/devices/platform/ahb/ahb:apb/ahb:apb:bus@1e78a000/1e78a480.i2c-bus/i2c-8/8-0051/8-00510/nvmem"
+ // find if the path contains the word i2c in it.
+ if (file.find("i2c") != string::npos)
+ {
+ string i2cBusAddr{};
+
+ // Every udev i2c path should have the common pattern
+ // "i2c-bus_number/bus_number-vpd_address". Search for
+ // "bus_number-vpd_address".
+ regex i2cPattern("((i2c)-[0-9]+\\/)([0-9]+-[0-9]{4})");
+ smatch match;
+ if (regex_search(file, match, i2cPattern))
+ {
+ i2cBusAddr = match.str(3);
+ }
+ else
+ {
+ cerr << "The given udev path < " << file
+ << " > doesn't match the required pattern. Skipping VPD "
+ "collection."
+ << endl;
+ exit(EXIT_SUCCESS);
+ }
+ // Forming the generic file path
+ file = i2cPathPrefix + i2cBusAddr + "/eeprom";
+ }
+ // Sample udevEvent spi path :
+ // "/sys/devices/platform/ahb/ahb:apb/1e79b000.fsi/fsi-master/fsi0/slave@00:00/00:00:00:04/spi_master/spi2/spi2.0/spi2.00/nvmem"
+ // find if the path contains the word spi in it.
+ else if (file.find("spi") != string::npos)
+ {
+ // Every udev spi path will have common pattern "spi<Digit>/", which
+ // describes the spi bus number at which the fru is connected; Followed
+ // by a slash following the vpd address of the fru. Taking the above
+ // input as a common key, we try to search for the pattern "spi<Digit>/"
+ // using regular expression.
+ regex spiPattern("((spi)[0-9]+)(\\/)");
+ string spiBus{};
+ smatch match;
+ if (regex_search(file, match, spiPattern))
+ {
+ spiBus = match.str(1);
+ }
+ else
+ {
+ cerr << "The given udev path < " << file
+ << " > doesn't match the required pattern. Skipping VPD "
+ "collection."
+ << endl;
+ exit(EXIT_SUCCESS);
+ }
+ // Forming the generic path
+ file = spiPathPrefix + spiBus + ".0/eeprom";
+ }
+ else
+ {
+ cerr << "\n The given EEPROM path < " << file
+ << " > is not valid. It's neither I2C nor "
+ "SPI path. Skipping VPD collection.."
+ << endl;
+ exit(EXIT_SUCCESS);
+ }
+}
} // namespace vpd
} // namespace openpower
\ No newline at end of file
diff --git a/ibm_vpd_utils.hpp b/ibm_vpd_utils.hpp
index 29996a9..4649adc 100644
--- a/ibm_vpd_utils.hpp
+++ b/ibm_vpd_utils.hpp
@@ -182,5 +182,9 @@
*/
const string getIM(const Parsed& vpdMap);
+/** @brief Translate udev event generated path to a generic /sys/bus eeprom path
+ * @param[io] file - path generated from udev event.
+ */
+void udevToGenericPath(string& file);
} // namespace vpd
} // namespace openpower
\ No newline at end of file