add handler logic to handle SysEntityName
Add handler logic to handler for SysEntityName such that it splits the
true IPMI processing from the business logic.
Tested: Only ran unit-tests (added new ones).
Change-Id: I6d672a80f85843ff98c2c7e5daf4689932ff96f9
Signed-off-by: Patrick Venture <venture@google.com>
diff --git a/handler.cpp b/handler.cpp
index 8a076f2..2018ef6 100644
--- a/handler.cpp
+++ b/handler.cpp
@@ -24,11 +24,15 @@
#include <cstdio>
#include <filesystem>
#include <fstream>
+#include <map>
+#include <nlohmann/json.hpp>
+#include <phosphor-logging/elog-errors.hpp>
#include <phosphor-logging/log.hpp>
#include <sdbusplus/bus.hpp>
#include <sstream>
#include <string>
#include <tuple>
+#include <xyz/openbmc_project/Common/error.hpp>
// The phosphor-host-ipmi daemon requires a configuration that maps
// the if_name to the IPMI LAN channel. However, that doesn't strictly
@@ -51,6 +55,10 @@
namespace ipmi
{
namespace fs = std::filesystem;
+using Json = nlohmann::json;
+using namespace phosphor::logging;
+using InternalFailure =
+ sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
std::tuple<std::uint8_t, std::string> Handler::getEthDetails() const
{
@@ -190,6 +198,93 @@
}
}
+static Json config{};
+static bool parsed = false;
+static const std::map<uint8_t, std::string> entityIdToName{
+ {0x03, "cpu"},
+ {0x04, "storage_device"},
+ {0x06, "system_management_module"},
+ {0x08, "memory_module"},
+ {0x0B, "add_in_card"},
+ {0x17, "system_chassis"},
+ {0x20, "memory_device"}};
+static constexpr auto configFile =
+ "/usr/share/ipmi-entity-association/entity_association_map.json";
+
+Json parse_config()
+{
+ std::ifstream jsonFile(configFile);
+ if (!jsonFile.is_open())
+ {
+ log<level::ERR>("Entity association JSON file not found");
+ elog<InternalFailure>();
+ }
+
+ auto data = Json::parse(jsonFile, nullptr, false);
+ if (data.is_discarded())
+ {
+ log<level::ERR>("Entity association JSON parser failure");
+ elog<InternalFailure>();
+ }
+
+ return data;
+}
+
+std::string read(const std::string& type, uint8_t instance, const Json& config)
+{
+ static const std::vector<Json> empty{};
+ std::vector<Json> readings = config.value(type, empty);
+ std::string name = "";
+ for (const auto& j : readings)
+ {
+ uint8_t instanceNum = j.value("instance", 0);
+ // Not the instance we're interested in
+ if (instanceNum != instance)
+ {
+ continue;
+ }
+
+ // Found the instance we're interested in
+ name = j.value("name", "");
+
+ break;
+ }
+ return name;
+}
+
+std::string Handler::getEntityName(std::uint8_t id, std::uint8_t instance)
+{
+ // Check if we support this Entity ID.
+ auto it = entityIdToName.find(id);
+ if (it == entityIdToName.end())
+ {
+ log<level::ERR>("Unknown Entity ID", entry("ENTITY_ID=%d", id));
+ throw IpmiException(IPMI_CC_INVALID_FIELD_REQUEST);
+ }
+
+ std::string entityName;
+ try
+ {
+ // Parse the JSON config file.
+ if (!parsed)
+ {
+ config = parse_config();
+ parsed = true;
+ }
+
+ // Find the "entity id:entity instance" mapping to entity name.
+ entityName = read(it->second, instance, config);
+ if (entityName.empty())
+ throw IpmiException(IPMI_CC_INVALID_FIELD_REQUEST);
+ }
+ catch (InternalFailure& e)
+ {
+ throw IpmiException(IPMI_CC_UNSPECIFIED_ERROR);
+ }
+
+ return entityName;
+}
+
Handler handlerImpl;
} // namespace ipmi