1*94e9d1a8SQiang XU /*
2*94e9d1a8SQiang XU // Copyright (c) 2019 Intel Corporation
3*94e9d1a8SQiang XU //
4*94e9d1a8SQiang XU // Licensed under the Apache License, Version 2.0 (the "License");
5*94e9d1a8SQiang XU // you may not use this file except in compliance with the License.
6*94e9d1a8SQiang XU // You may obtain a copy of the License at
7*94e9d1a8SQiang XU //
8*94e9d1a8SQiang XU //      http://www.apache.org/licenses/LICENSE-2.0
9*94e9d1a8SQiang XU //
10*94e9d1a8SQiang XU // Unless required by applicable law or agreed to in writing, software
11*94e9d1a8SQiang XU // distributed under the License is distributed on an "AS IS" BASIS,
12*94e9d1a8SQiang XU // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*94e9d1a8SQiang XU // See the License for the specific language governing permissions and
14*94e9d1a8SQiang XU // limitations under the License.
15*94e9d1a8SQiang XU */
16*94e9d1a8SQiang XU 
17*94e9d1a8SQiang XU #include <ipmid/api.hpp>
18*94e9d1a8SQiang XU #include <ipmid/utils.hpp>
19*94e9d1a8SQiang XU #include <multinodecommands.hpp>
20*94e9d1a8SQiang XU #include <oemcommands.hpp>
21*94e9d1a8SQiang XU #include <phosphor-logging/log.hpp>
22*94e9d1a8SQiang XU #include <sdbusplus/bus.hpp>
23*94e9d1a8SQiang XU #include <sdbusplus/message/types.hpp>
24*94e9d1a8SQiang XU #include <string>
25*94e9d1a8SQiang XU 
26*94e9d1a8SQiang XU namespace ipmi
27*94e9d1a8SQiang XU {
28*94e9d1a8SQiang XU void registerMultiNodeFunctions() __attribute__((constructor));
29*94e9d1a8SQiang XU 
30*94e9d1a8SQiang XU std::optional<uint8_t> getMultiNodeInfo(std::string name)
31*94e9d1a8SQiang XU {
32*94e9d1a8SQiang XU     auto pdbus = getSdBus();
33*94e9d1a8SQiang XU     try
34*94e9d1a8SQiang XU     {
35*94e9d1a8SQiang XU         std::string service =
36*94e9d1a8SQiang XU             getService(*pdbus, multiNodeIntf, multiNodeObjPath);
37*94e9d1a8SQiang XU         Value dbusValue = getDbusProperty(*pdbus, service, multiNodeObjPath,
38*94e9d1a8SQiang XU                                           multiNodeIntf, name);
39*94e9d1a8SQiang XU         return std::get<uint8_t>(dbusValue);
40*94e9d1a8SQiang XU     }
41*94e9d1a8SQiang XU     catch (const std::exception& e)
42*94e9d1a8SQiang XU     {
43*94e9d1a8SQiang XU         phosphor::logging::log<phosphor::logging::level::ERR>(
44*94e9d1a8SQiang XU             "getMultiNodeInfo: can't get multi node info from dbus!",
45*94e9d1a8SQiang XU             phosphor::logging::entry("ERR=%s", e.what()));
46*94e9d1a8SQiang XU         return std::nullopt;
47*94e9d1a8SQiang XU     }
48*94e9d1a8SQiang XU }
49*94e9d1a8SQiang XU 
50*94e9d1a8SQiang XU std::optional<uint8_t> getMultiNodeRole()
51*94e9d1a8SQiang XU {
52*94e9d1a8SQiang XU     auto pdbus = getSdBus();
53*94e9d1a8SQiang XU     try
54*94e9d1a8SQiang XU     {
55*94e9d1a8SQiang XU         std::string service =
56*94e9d1a8SQiang XU             getService(*pdbus, multiNodeIntf, multiNodeObjPath);
57*94e9d1a8SQiang XU         Value dbusValue = getDbusProperty(*pdbus, service, multiNodeObjPath,
58*94e9d1a8SQiang XU                                           multiNodeIntf, "NodeRole");
59*94e9d1a8SQiang XU         std::string valueStr = std::get<std::string>(dbusValue);
60*94e9d1a8SQiang XU         uint8_t value;
61*94e9d1a8SQiang XU         if (valueStr == "single")
62*94e9d1a8SQiang XU             value = static_cast<uint8_t>(NodeRole::single);
63*94e9d1a8SQiang XU         else if (valueStr == "master")
64*94e9d1a8SQiang XU             value = static_cast<uint8_t>(NodeRole::master);
65*94e9d1a8SQiang XU         else if (valueStr == "slave")
66*94e9d1a8SQiang XU             value = static_cast<uint8_t>(NodeRole::slave);
67*94e9d1a8SQiang XU         else if (valueStr == "arbitrating")
68*94e9d1a8SQiang XU             value = static_cast<uint8_t>(NodeRole::arbitrating);
69*94e9d1a8SQiang XU         return value;
70*94e9d1a8SQiang XU     }
71*94e9d1a8SQiang XU     catch (const std::exception& e)
72*94e9d1a8SQiang XU     {
73*94e9d1a8SQiang XU         phosphor::logging::log<phosphor::logging::level::ERR>(
74*94e9d1a8SQiang XU             "getMultiNodeRole: can't get multi node role from dbus!",
75*94e9d1a8SQiang XU             phosphor::logging::entry("ERR=%s", e.what()));
76*94e9d1a8SQiang XU         return std::nullopt;
77*94e9d1a8SQiang XU     }
78*94e9d1a8SQiang XU }
79*94e9d1a8SQiang XU 
80*94e9d1a8SQiang XU ipmi::RspType<uint8_t> ipmiGetMultiNodePresence()
81*94e9d1a8SQiang XU 
82*94e9d1a8SQiang XU {
83*94e9d1a8SQiang XU     std::optional<uint8_t> nodeInfo = getMultiNodeInfo("NodePresence");
84*94e9d1a8SQiang XU     if (!nodeInfo)
85*94e9d1a8SQiang XU     {
86*94e9d1a8SQiang XU         return ipmi::responseResponseError();
87*94e9d1a8SQiang XU     }
88*94e9d1a8SQiang XU 
89*94e9d1a8SQiang XU     return ipmi::responseSuccess(*nodeInfo);
90*94e9d1a8SQiang XU }
91*94e9d1a8SQiang XU 
92*94e9d1a8SQiang XU ipmi::RspType<uint8_t> ipmiGetMultiNodeId()
93*94e9d1a8SQiang XU {
94*94e9d1a8SQiang XU     std::optional<uint8_t> nodeInfo = getMultiNodeInfo("NodeId");
95*94e9d1a8SQiang XU     if (!nodeInfo)
96*94e9d1a8SQiang XU     {
97*94e9d1a8SQiang XU         return ipmi::responseResponseError();
98*94e9d1a8SQiang XU     }
99*94e9d1a8SQiang XU 
100*94e9d1a8SQiang XU     return ipmi::responseSuccess(*nodeInfo);
101*94e9d1a8SQiang XU }
102*94e9d1a8SQiang XU 
103*94e9d1a8SQiang XU ipmi::RspType<uint8_t> ipmiGetMultiNodeRole()
104*94e9d1a8SQiang XU {
105*94e9d1a8SQiang XU     std::optional<uint8_t> nodeInfo = getMultiNodeRole();
106*94e9d1a8SQiang XU     if (!nodeInfo)
107*94e9d1a8SQiang XU     {
108*94e9d1a8SQiang XU         return ipmi::responseResponseError();
109*94e9d1a8SQiang XU     }
110*94e9d1a8SQiang XU 
111*94e9d1a8SQiang XU     return ipmi::responseSuccess(*nodeInfo);
112*94e9d1a8SQiang XU }
113*94e9d1a8SQiang XU 
114*94e9d1a8SQiang XU void registerMultiNodeFunctions(void)
115*94e9d1a8SQiang XU {
116*94e9d1a8SQiang XU     phosphor::logging::log<phosphor::logging::level::INFO>(
117*94e9d1a8SQiang XU         "Registering MultiNode commands");
118*94e9d1a8SQiang XU 
119*94e9d1a8SQiang XU     ipmi::registerHandler(
120*94e9d1a8SQiang XU         ipmi::prioOemBase, ipmi::netFnOemOne,
121*94e9d1a8SQiang XU         static_cast<ipmi::Cmd>(IPMINetfnMultiNodeCmd::cmdGetMultiNodePresence),
122*94e9d1a8SQiang XU         ipmi::Privilege::User, ipmiGetMultiNodePresence);
123*94e9d1a8SQiang XU 
124*94e9d1a8SQiang XU     ipmi::registerHandler(
125*94e9d1a8SQiang XU         ipmi::prioOemBase, ipmi::netFnOemOne,
126*94e9d1a8SQiang XU         static_cast<ipmi::Cmd>(IPMINetfnMultiNodeCmd::cmdGetMultiNodeId),
127*94e9d1a8SQiang XU         ipmi::Privilege::User, ipmiGetMultiNodeId);
128*94e9d1a8SQiang XU 
129*94e9d1a8SQiang XU     ipmi::registerHandler(
130*94e9d1a8SQiang XU         ipmi::prioOemBase, ipmi::netFnOemOne,
131*94e9d1a8SQiang XU         static_cast<ipmi::Cmd>(IPMINetfnMultiNodeCmd::cmdGetMultiNodeRole),
132*94e9d1a8SQiang XU         ipmi::Privilege::User, ipmiGetMultiNodeRole);
133*94e9d1a8SQiang XU }
134*94e9d1a8SQiang XU 
135*94e9d1a8SQiang XU } // namespace ipmi
136