Read channel configuration from JSON file
Read channel information from /usr/share/ipmbbridge/ipmb-channels.json
allowing platforms to override this information.
Signed-off-by: Amithash Prasad <amithash@fb.com>
Change-Id: I161cf72840ff211c270fe56a86e6d3ebd65f170c
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 107f041..80377f5 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -40,6 +40,8 @@
link_directories (${EXTERNAL_INSTALL_LOCATION}/lib)
set (SERVICE_FILES ${PROJECT_SOURCE_DIR}/ipmb.service)
+set (CONFIG_FILES ${PROJECT_SOURCE_DIR}/ipmb-channels.json)
install (TARGETS ${PROJECT_NAME} DESTINATION bin)
install (FILES ${SERVICE_FILES} DESTINATION /lib/systemd/system/)
+install (FILES ${CONFIG_FILES} DESTINATION /usr/share/ipmbbridge/)
diff --git a/ipmb-channels.json b/ipmb-channels.json
new file mode 100644
index 0000000..ee4a373
--- /dev/null
+++ b/ipmb-channels.json
@@ -0,0 +1,18 @@
+{
+ "channels": [
+ {
+ "type": "me",
+ "master-path": "/dev/i2c-5",
+ "slave-path": "/sys/bus/i2c/devices/5-1010/slave-mqueue",
+ "bmc-addr": 32,
+ "remote-addr": 44
+ },
+ {
+ "type": "ipmb",
+ "master-path": "/dev/i2c-0",
+ "slave-path": "/sys/bus/i2c/devices/0-1010/slave-mqueue",
+ "bmc-addr": 32,
+ "remote-addr": 88
+ }
+ ]
+}
diff --git a/ipmbbridged.cpp b/ipmbbridged.cpp
index 72c2e1d..b37c867 100644
--- a/ipmbbridged.cpp
+++ b/ipmbbridged.cpp
@@ -18,8 +18,11 @@
#include "ipmbdefines.hpp"
#include "ipmbutils.hpp"
+#include <fstream>
+#include <nlohmann/json.hpp>
#include <phosphor-logging/log.hpp>
#include <tuple>
+#include <unordered_map>
extern "C" {
#include <i2c/smbus.h>
@@ -37,19 +40,10 @@
boost::asio::io_service io;
auto conn = std::make_shared<sdbusplus::asio::connection>(io);
-/**
- * @brief Channel configuration table
- * TODO : move to user configuration as JSON file
- */
-static const std::vector<IpmbChannelConfig> ipmbChannelsConfig = {
- // ME channel
- {ipmbChannelType::me, "/sys/bus/i2c/devices/5-1010/slave-mqueue",
- "/dev/i2c-5", 0x20, 0x2C}, // 8 bit addresses
- // IPMB header channel
- {ipmbChannelType::ipmb, "/sys/bus/i2c/devices/0-1010/slave-mqueue",
- "/dev/i2c-0", 0x20, 0x58}}; // 8 bit addresses
-
static std::list<IpmbChannel> ipmbChannels;
+static const std::unordered_map<std::string, ipmbChannelType>
+ ipmbChannelTypeMap = {{"me", ipmbChannelType::me},
+ {"ipmb", ipmbChannelType::ipmb}};
/**
* @brief Ipmb request class methods
@@ -615,22 +609,50 @@
std::shared_ptr<IpmbCommandFilter> commandFilter =
std::make_shared<IpmbCommandFilter>();
- for (const auto &channelConfig : ipmbChannelsConfig)
+ constexpr const char *configFilePath =
+ "/usr/share/ipmbbridge/ipmb-channels.json";
+ std::ifstream configFile(configFilePath);
+ if (!configFile.is_open())
{
- auto channel = ipmbChannels.emplace(ipmbChannels.end(), io,
- channelConfig.ipmbBmcSlaveAddress,
- channelConfig.ipmbRqSlaveAddress,
- channelConfig.type, commandFilter);
-
- if (channel->ipmbChannelInit(channelConfig.ipmbI2cSlave,
- channelConfig.ipmbI2cMaster) < 0)
+ phosphor::logging::log<phosphor::logging::level::ERR>(
+ "initializeChannels: Cannot open config path");
+ return -1;
+ }
+ try
+ {
+ auto data = nlohmann::json::parse(configFile, nullptr);
+ for (const auto &channelConfig : data["channels"])
{
- phosphor::logging::log<phosphor::logging::level::ERR>(
- "initializeChannels: channel initialization failed");
- return -1;
+ const std::string &typeConfig = channelConfig["type"];
+ const std::string &masterPath = channelConfig["master-path"];
+ const std::string &slavePath = channelConfig["slave-path"];
+ uint8_t bmcAddr = channelConfig["bmc-addr"];
+ uint8_t reqAddr = channelConfig["remote-addr"];
+ ipmbChannelType type = ipmbChannelTypeMap.at(typeConfig);
+
+ auto channel = ipmbChannels.emplace(ipmbChannels.end(), io, bmcAddr,
+ reqAddr, type, commandFilter);
+ if (channel->ipmbChannelInit(slavePath.c_str(),
+ masterPath.c_str()) < 0)
+ {
+ phosphor::logging::log<phosphor::logging::level::ERR>(
+ "initializeChannels: channel initialization failed");
+ return -1;
+ }
}
}
-
+ catch (nlohmann::json::exception &e)
+ {
+ phosphor::logging::log<phosphor::logging::level::ERR>(
+ "initializeChannels: Error parsing config file");
+ return -1;
+ }
+ catch (std::out_of_range &e)
+ {
+ phosphor::logging::log<phosphor::logging::level::ERR>(
+ "initializeChannels: Error invalid type");
+ return -1;
+ }
return 0;
}
diff --git a/ipmbbridged.hpp b/ipmbbridged.hpp
index c139391..317fdab 100644
--- a/ipmbbridged.hpp
+++ b/ipmbbridged.hpp
@@ -145,18 +145,6 @@
me = 1
};
-/**
- * @brief Channel configuration structure
- */
-struct IpmbChannelConfig
-{
- ipmbChannelType type;
- const char *ipmbI2cSlave;
- const char *ipmbI2cMaster;
- uint8_t ipmbBmcSlaveAddress;
- uint8_t ipmbRqSlaveAddress;
-};
-
// TODO w/a to differentiate channel origin of incoming IPMI response:
// extracting channel number from 2 oldest bits of seq
constexpr ipmbChannelType getChannelFromSeq(const uint8_t &seq)