blob: 616dc900273587bf68a301b86bf672998fe15e42 [file] [log] [blame]
Vernon Mauery9e801a22018-10-12 13:20:49 -07001#include "provider_registration.hpp"
2
3#include "command_table.hpp"
4#include "main.hpp"
5
Tom485038e2016-12-02 13:44:45 +05306#include <dirent.h>
7#include <dlfcn.h>
William A. Kennington III4f09eae2019-02-12 17:10:35 -08008#include <ipmid/api.h>
Tom485038e2016-12-02 13:44:45 +05309#include <stdlib.h>
10#include <string.h>
11
Vernon Maueryfc37e592018-12-19 14:55:15 -080012#include <phosphor-logging/log.hpp>
13
14using namespace phosphor::logging;
Tom485038e2016-12-02 13:44:45 +053015
Tom485038e2016-12-02 13:44:45 +053016namespace provider
17{
18
19int handler_select(const struct dirent* entry)
20{
21 // Check for versioned libraries .so.*
22 if (strstr(entry->d_name, PROVIDER_SONAME_EXTN))
23 {
24 return 1;
25 }
26 else
27 {
28 return 0;
29 }
30}
31
32void registerCallbackHandlers(const char* providerLibPath)
33{
34 if (providerLibPath == NULL)
35 {
Vernon Maueryfc37e592018-12-19 14:55:15 -080036 log<level::ERR>(
37 "Path not provided for registering IPMI provider libraries");
Tom485038e2016-12-02 13:44:45 +053038 return;
39 }
40
41 struct dirent** handlerList = nullptr;
42 std::string handlerPath(providerLibPath);
43
Vernon Mauery9e801a22018-10-12 13:20:49 -070044 auto numLibs =
45 scandir(providerLibPath, &handlerList, handler_select, alphasort);
Tom485038e2016-12-02 13:44:45 +053046 if (numLibs < 0)
47 {
48 return;
49 }
50
51 // dlopen each IPMI provider shared library
52 while (numLibs--)
53 {
54 handlerPath = providerLibPath;
55 handlerPath += handlerList[numLibs]->d_name;
Tom485038e2016-12-02 13:44:45 +053056
57 auto lib_handler = dlopen(handlerPath.c_str(), RTLD_NOW);
58
59 if (lib_handler == NULL)
60 {
Vernon Maueryfc37e592018-12-19 14:55:15 -080061 log<level::ERR>("Error opening provider library",
62 entry("PATH=%s", handlerPath.c_str()),
63 entry("ERROR=%s", dlerror()));
Tom485038e2016-12-02 13:44:45 +053064 }
65 free(handlerList[numLibs]);
66 }
67
68 free(handlerList);
69}
70
71} // namespace provider
72
73/*
74 * @brief Method that gets called from IPMI provider shared libraries to get
75 * the command handlers registered.
76 *
77 * When the IPMI provider shared library is loaded, the dynamic loader program
78 * looks for special section(.ctors on ELF) which contains references to the
79 * functions marked with the constructor attributes. This function is invoked
80 * in such manner.
81 *
82 * @param[in] netfn - Network Function code
83 * @param[in] cmd - Command
84 * @param[in] context - User specific data
85 * @param[in] handler - The callback routine for the command
Tom Joseph935606c2017-01-27 10:53:33 +053086 * @param[in] priv - IPMI Command Privilege
Tom485038e2016-12-02 13:44:45 +053087 */
88void ipmi_register_callback(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
Vernon Mauery9e801a22018-10-12 13:20:49 -070089 ipmi_context_t context, ipmid_callback_t handler,
90 ipmi_cmd_privilege_t priv)
Tom485038e2016-12-02 13:44:45 +053091{
92 uint16_t netFn = netfn << 10;
93
94 // The payload type of IPMI commands provided by the shared libraries
95 // is IPMI
Vernon Mauery9e801a22018-10-12 13:20:49 -070096 command::CommandID command = {
97 ((static_cast<uint32_t>(message::PayloadType::IPMI)) << 16) | netFn |
98 cmd};
Tom485038e2016-12-02 13:44:45 +053099
Vernon Mauery9e801a22018-10-12 13:20:49 -0700100 std::get<command::Table&>(singletonPool)
101 .registerCommand(command, std::make_unique<command::ProviderIpmidEntry>(
102 command, handler,
103 static_cast<session::Privilege>(priv)));
Tom485038e2016-12-02 13:44:45 +0530104}