summaryrefslogtreecommitdiff
path: root/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0048-Implement-IPMI-Master-Write-Read-command.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0048-Implement-IPMI-Master-Write-Read-command.patch')
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0048-Implement-IPMI-Master-Write-Read-command.patch351
1 files changed, 0 insertions, 351 deletions
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0048-Implement-IPMI-Master-Write-Read-command.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0048-Implement-IPMI-Master-Write-Read-command.patch
deleted file mode 100644
index 542c4f667..000000000
--- a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0048-Implement-IPMI-Master-Write-Read-command.patch
+++ /dev/null
@@ -1,351 +0,0 @@
-From a8d7429b7bd9dea33d59c6e83f17372e77fe6145 Mon Sep 17 00:00:00 2001
-From: Yong Li <yong.b.li@linux.intel.com>
-Date: Fri, 21 Sep 2018 09:21:14 +0800
-Subject: [PATCH] Implement IPMI Master Write-Read command
-
-This command can be used for low-level I2C/SMBus write, read, or write-read
-accesses to the IPMB or private busses behind a management controller.
-
-The command can also be used for providing low-level access to devices
-that provide an SMBus slave interface.
-
-Signed-off-by: Yong Li <yong.b.li@linux.intel.com>
----
- apphandler.cpp | 276 +++++++++++++++++++++++++++++++++++++-
- apphandler.hpp | 1 +
- host-ipmid-whitelist.conf | 1 +
- 3 files changed, 274 insertions(+), 4 deletions(-)
-
-diff --git a/apphandler.cpp b/apphandler.cpp
-index 15965ca..d8fb23d 100644
---- a/apphandler.cpp
-+++ b/apphandler.cpp
-@@ -1,6 +1,19 @@
-+#include "apphandler.hpp"
-+
-+#include "app/watchdog.hpp"
-+#include "sys_info_param.hpp"
-+#include "transporthandler.hpp"
-+
- #include <arpa/inet.h>
-+#include <fcntl.h>
-+#include <ipmid/api.h>
- #include <limits.h>
-+#include <linux/i2c-dev.h>
-+#include <linux/i2c.h>
- #include <mapper.h>
-+#include <sys/ioctl.h>
-+#include <sys/stat.h>
-+#include <sys/types.h>
- #include <systemd/sd-bus.h>
- #include <unistd.h>
-
-@@ -41,6 +54,8 @@ constexpr auto bmc_guid_interface = "xyz.openbmc_project.Common.UUID";
- constexpr auto bmc_guid_property = "UUID";
- constexpr auto bmc_guid_len = 16;
-
-+static constexpr uint8_t maxIPMIWriteReadSize = 144;
-+
- static constexpr auto redundancyIntf =
- "xyz.openbmc_project.Software.RedundancyPriority";
- static constexpr auto versionIntf = "xyz.openbmc_project.Software.Version";
-@@ -59,6 +74,47 @@ using BMC = sdbusplus::xyz::openbmc_project::State::server::BMC;
- namespace fs = std::filesystem;
- namespace variant_ns = sdbusplus::message::variant_ns;
-
-+// Offset in get device id command.
-+typedef struct
-+{
-+ uint8_t id;
-+ uint8_t revision;
-+ uint8_t fw[2];
-+ uint8_t ipmi_ver;
-+ uint8_t addn_dev_support;
-+ uint8_t manuf_id[3];
-+ uint8_t prod_id[2];
-+ uint8_t aux[4];
-+} __attribute__((packed)) ipmi_device_id_t;
-+
-+typedef struct
-+{
-+ uint8_t busId;
-+ uint8_t slaveAddr;
-+ uint8_t readCount;
-+} __attribute__((packed)) ipmiI2cRwReq;
-+
-+typedef struct
-+{
-+ uint8_t busId;
-+ uint8_t slaveAddr;
-+ std::vector<uint8_t> data;
-+} ipmiMasterRwWhitelist;
-+
-+static std::vector<ipmiMasterRwWhitelist>& getWhiteList()
-+{
-+ static std::vector<ipmiMasterRwWhitelist> rwWhiteList;
-+ return rwWhiteList;
-+}
-+
-+static constexpr const char* whiteListFilename =
-+ "/usr/share/ipmi-providers/master_write_read_white_list.json";
-+
-+static constexpr const char* filtersStr = "filters";
-+static constexpr const char* busIdStr = "busId";
-+static constexpr const char* slaveAddrStr = "slaveAddr";
-+static constexpr const char* cmdStr = "command";
-+
- /**
- * @brief Returns the Version info from primary s/w object
- *
-@@ -1022,6 +1078,192 @@ writeResponse:
- return IPMI_CC_OK;
- }
-
-+static int loadI2CWhiteList()
-+{
-+ nlohmann::json data = nullptr;
-+ std::ifstream jsonFile(whiteListFilename);
-+
-+ if (!jsonFile.good())
-+ {
-+ log<level::WARNING>("whitelist file not found!");
-+ return -1;
-+ }
-+
-+ try
-+ {
-+ data = nlohmann::json::parse(jsonFile, nullptr, false);
-+ }
-+ catch (nlohmann::json::parse_error& e)
-+ {
-+ log<level::ERR>("Corrupted whitelist config file",
-+ entry("MSG: %s", e.what()));
-+ return -1;
-+ }
-+
-+ try
-+ {
-+ unsigned int i = 0;
-+ nlohmann::json filters = data[filtersStr].get<nlohmann::json>();
-+ getWhiteList().resize(filters.size());
-+
-+ for (const auto& it : filters.items())
-+ {
-+ nlohmann::json filter = it.value();
-+ if (filter.is_null())
-+ {
-+ log<level::ERR>("Incorrect filter");
-+ return -1;
-+ }
-+
-+ getWhiteList()[i].busId =
-+ std::stoul(filter[busIdStr].get<std::string>(), nullptr, 16);
-+
-+ getWhiteList()[i].slaveAddr = std::stoul(
-+ filter[slaveAddrStr].get<std::string>(), nullptr, 16);
-+
-+ std::string command = filter[cmdStr].get<std::string>();
-+
-+ log<level::DEBUG>("IPMI I2C whitelist ", entry("INDEX=%d", i),
-+ entry("BUS=%d", getWhiteList()[i].busId),
-+ entry("ADDR=0x%x", getWhiteList()[i].slaveAddr),
-+ entry("LEN=0x%x", command.length()),
-+ entry("COMMAND=[%s]", command.c_str()));
-+
-+ // convert data string
-+ std::istringstream iss(command);
-+ std::string token;
-+ while (std::getline(iss, token, ' '))
-+ {
-+ log<level::DEBUG>("IPMI I2C command\n",
-+ entry("TOKEN=%s", token.c_str()));
-+ getWhiteList()[i].data.emplace_back(
-+ std::stoul(token, nullptr, 16));
-+ }
-+ i++;
-+ }
-+ }
-+ catch (std::exception& e)
-+ {
-+ log<level::ERR>("unexpected exception", entry("ERROR=%s", e.what()));
-+ return -1;
-+ }
-+ return 0;
-+}
-+
-+ipmi_ret_t ipmiMasterWriteRead(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
-+ ipmi_request_t request, ipmi_response_t response,
-+ ipmi_data_len_t data_len, ipmi_context_t context)
-+{
-+ bool foundInList = false;
-+ int ret = 0;
-+ i2c_rdwr_ioctl_data msgRdwr = {0};
-+ i2c_msg i2cmsg[2] = {0};
-+ ipmiI2cRwReq* reqi2c = reinterpret_cast<ipmiI2cRwReq*>(request);
-+
-+ if (*data_len <= sizeof(ipmiI2cRwReq))
-+ {
-+ log<level::ERR>("Failed in request", entry("LEN=%d", *data_len));
-+ *data_len = 0;
-+ return IPMI_CC_REQ_DATA_LEN_INVALID;
-+ }
-+
-+ if (reqi2c->readCount > maxIPMIWriteReadSize)
-+ {
-+ log<level::ERR>("Failed in request", entry("R=%d", reqi2c->readCount));
-+ *data_len = 0;
-+ return IPMI_CC_PARM_OUT_OF_RANGE;
-+ }
-+
-+ uint8_t* resptr = reinterpret_cast<uint8_t*>(response);
-+ uint8_t busId = (reqi2c->busId & 0xFF) >> 1;
-+ // Convert the I2C address from 7-bit format
-+ uint8_t i2cAddr = reqi2c->slaveAddr >> 1;
-+ size_t writeCount = *data_len - sizeof(ipmiI2cRwReq);
-+
-+ log<level::DEBUG>(
-+ "INPUT: ", entry("LEN=%d", *data_len), entry("ID=0x%x", busId),
-+ entry("ADDR=0x%x", reqi2c->slaveAddr), entry("R=%d", reqi2c->readCount),
-+ entry("W=%d", writeCount));
-+
-+ *data_len = 0;
-+
-+ std::vector<uint8_t> inBuf(reqi2c->readCount);
-+ std::vector<uint8_t> outBuf(writeCount);
-+ uint8_t* reqptr = reinterpret_cast<uint8_t*>(request);
-+
-+ reqptr += sizeof(ipmiI2cRwReq);
-+ std::copy(reqptr, reqptr + writeCount, outBuf.begin());
-+
-+ log<level::DEBUG>("checking list ",
-+ entry("SIZE=%d", getWhiteList().size()));
-+ // command whitelist checking
-+ for (unsigned int i = 0; i < getWhiteList().size(); i++)
-+ {
-+ // TODO add wildchard/regex support
-+ if ((busId == getWhiteList()[i].busId) &&
-+ (i2cAddr == getWhiteList()[i].slaveAddr) &&
-+ (outBuf == getWhiteList()[i].data))
-+ {
-+ log<level::DEBUG>("In whitelist");
-+ foundInList = true;
-+ break;
-+ }
-+ }
-+
-+ if (!foundInList)
-+ {
-+ log<level::ERR>("Request blocked!", entry("BUS=%d", busId),
-+ entry("ADDR=0x%x", reqi2c->slaveAddr));
-+ return IPMI_CC_INVALID_FIELD_REQUEST;
-+ }
-+
-+ log<level::DEBUG>("IPMI Master WriteRead ", entry("BUS=%d", busId),
-+ entry("ADDR=0x%x", reqi2c->slaveAddr),
-+ entry("R=%d", reqi2c->readCount),
-+ entry("W=%d", writeCount));
-+
-+ std::string i2cBus = "/dev/i2c-" + std::to_string(busId);
-+
-+ int i2cDev = ::open(i2cBus.c_str(), O_RDWR | O_CLOEXEC);
-+ if (i2cDev < 0)
-+ {
-+ log<level::ERR>("Failed in opening i2c device",
-+ entry("BUS=%s", i2cBus.c_str()));
-+ return IPMI_CC_UNSPECIFIED_ERROR;
-+ }
-+
-+ // write message
-+ i2cmsg[0].addr = i2cAddr;
-+ i2cmsg[0].flags = 0x00;
-+ i2cmsg[0].len = writeCount;
-+ i2cmsg[0].buf = outBuf.data();
-+
-+ // read message
-+ i2cmsg[1].addr = i2cAddr;
-+ i2cmsg[1].flags = I2C_M_RD;
-+ i2cmsg[1].len = reqi2c->readCount;
-+ i2cmsg[1].buf = inBuf.data();
-+
-+ msgRdwr.msgs = i2cmsg;
-+ msgRdwr.nmsgs = 2;
-+
-+ ret = ::ioctl(i2cDev, I2C_RDWR, &msgRdwr);
-+ ::close(i2cDev);
-+
-+ // TODO add completion code support
-+ if (ret < 0)
-+ {
-+ log<level::ERR>("RDWR ioctl error", entry("RET=%d", ret));
-+ return IPMI_CC_UNSPECIFIED_ERROR;
-+ }
-+
-+ *data_len = msgRdwr.msgs[1].len;
-+ std::copy(msgRdwr.msgs[1].buf, msgRdwr.msgs[1].buf + msgRdwr.msgs[1].len,
-+ resptr);
-+
-+ return IPMI_CC_OK;
-+}
-+
- void register_netfn_app_functions()
- {
- // <Get Device ID>
-@@ -1063,6 +1306,31 @@ void register_netfn_app_functions()
- ipmi_register_callback(NETFUN_APP, IPMI_CMD_GET_ACPI, NULL,
- ipmi_app_get_acpi_power_state, PRIVILEGE_ADMIN);
-
-+// TODO: Below code and associated api's need to be removed later.
-+// Its commented for now to avoid merge conflicts with upstream
-+// changes and smooth upstream upgrades.
-+#if 0
-+>>>>>>> IPMI Channel commands implementation
-+ // <Get Channel Access>
-+ ipmi_register_callback(NETFUN_APP, IPMI_CMD_GET_CHANNEL_ACCESS, NULL,
-+ ipmi_get_channel_access, PRIVILEGE_USER);
-+
-+ // <Get Channel Info Command>
-+ ipmi_register_callback(NETFUN_APP, IPMI_CMD_GET_CHAN_INFO, NULL,
-+ ipmi_app_channel_info, PRIVILEGE_USER);
-+#endif
-+
-+ int ret = loadI2CWhiteList();
-+ log<level::DEBUG>("i2c white list is loaded", entry("RET=%d", ret),
-+ entry("SIZE=%d", getWhiteList().size()));
-+ if (ret == 0)
-+ {
-+ log<level::DEBUG>("Register Master RW command");
-+ // <Master Write Read Command>
-+ ipmi_register_callback(NETFUN_APP, IPMI_CMD_MASTER_WRITE_READ, NULL,
-+ ipmiMasterWriteRead, PRIVILEGE_OPERATOR);
-+ }
-+
- // <Get System GUID Command>
- ipmi_register_callback(NETFUN_APP, IPMI_CMD_GET_SYS_GUID, NULL,
- ipmi_app_get_sys_guid, PRIVILEGE_USER);
-diff --git a/apphandler.hpp b/apphandler.hpp
-index d4dd8e8..f9e5c59 100644
---- a/apphandler.hpp
-+++ b/apphandler.hpp
-@@ -19,6 +19,7 @@ enum ipmi_netfn_app_cmds
- IPMI_CMD_SET_CHAN_ACCESS = 0x40,
- IPMI_CMD_GET_CHANNEL_ACCESS = 0x41,
- IPMI_CMD_GET_CHAN_INFO = 0x42,
-+ IPMI_CMD_MASTER_WRITE_READ = 0x52,
- IPMI_CMD_GET_CHAN_CIPHER_SUITES = 0x54,
- IPMI_CMD_SET_SYSTEM_INFO = 0x58,
- IPMI_CMD_GET_SYSTEM_INFO = 0x59,
-diff --git a/host-ipmid-whitelist.conf b/host-ipmid-whitelist.conf
-index 49ff7b0..1ae79fd 100644
---- a/host-ipmid-whitelist.conf
-+++ b/host-ipmid-whitelist.conf
-@@ -27,6 +27,7 @@
- 0x06:0x37 //<App>:<Get System GUID>
- 0x06:0x42 //<App>:<Get Channel Info Command>
- 0x06:0x4E //<App>:<Get Channel Payload Support>
-+0x06:0x52 //<App>:<Master Write Read Command>
- 0x06:0x54 //<App>:<Get Channel Cipher Suites>
- 0x0A:0x10 //<Storage>:<Get FRU Inventory Area Info>
- 0x0A:0x11 //<Storage>:<Read FRU Data>
---
-2.17.1
-