blob: 616dc900273587bf68a301b86bf672998fe15e42 [file] [log] [blame]
#include "provider_registration.hpp"
#include "command_table.hpp"
#include "main.hpp"
#include <dirent.h>
#include <dlfcn.h>
#include <ipmid/api.h>
#include <stdlib.h>
#include <string.h>
#include <phosphor-logging/log.hpp>
using namespace phosphor::logging;
namespace provider
{
int handler_select(const struct dirent* entry)
{
// Check for versioned libraries .so.*
if (strstr(entry->d_name, PROVIDER_SONAME_EXTN))
{
return 1;
}
else
{
return 0;
}
}
void registerCallbackHandlers(const char* providerLibPath)
{
if (providerLibPath == NULL)
{
log<level::ERR>(
"Path not provided for registering IPMI provider libraries");
return;
}
struct dirent** handlerList = nullptr;
std::string handlerPath(providerLibPath);
auto numLibs =
scandir(providerLibPath, &handlerList, handler_select, alphasort);
if (numLibs < 0)
{
return;
}
// dlopen each IPMI provider shared library
while (numLibs--)
{
handlerPath = providerLibPath;
handlerPath += handlerList[numLibs]->d_name;
auto lib_handler = dlopen(handlerPath.c_str(), RTLD_NOW);
if (lib_handler == NULL)
{
log<level::ERR>("Error opening provider library",
entry("PATH=%s", handlerPath.c_str()),
entry("ERROR=%s", dlerror()));
}
free(handlerList[numLibs]);
}
free(handlerList);
}
} // namespace provider
/*
* @brief Method that gets called from IPMI provider shared libraries to get
* the command handlers registered.
*
* When the IPMI provider shared library is loaded, the dynamic loader program
* looks for special section(.ctors on ELF) which contains references to the
* functions marked with the constructor attributes. This function is invoked
* in such manner.
*
* @param[in] netfn - Network Function code
* @param[in] cmd - Command
* @param[in] context - User specific data
* @param[in] handler - The callback routine for the command
* @param[in] priv - IPMI Command Privilege
*/
void ipmi_register_callback(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
ipmi_context_t context, ipmid_callback_t handler,
ipmi_cmd_privilege_t priv)
{
uint16_t netFn = netfn << 10;
// The payload type of IPMI commands provided by the shared libraries
// is IPMI
command::CommandID command = {
((static_cast<uint32_t>(message::PayloadType::IPMI)) << 16) | netFn |
cmd};
std::get<command::Table&>(singletonPool)
.registerCommand(command, std::make_unique<command::ProviderIpmidEntry>(
command, handler,
static_cast<session::Privilege>(priv)));
}