194e9d1a8SQiang XU /*
294e9d1a8SQiang XU // Copyright (c) 2019 Intel Corporation
394e9d1a8SQiang XU //
494e9d1a8SQiang XU // Licensed under the Apache License, Version 2.0 (the "License");
594e9d1a8SQiang XU // you may not use this file except in compliance with the License.
694e9d1a8SQiang XU // You may obtain a copy of the License at
794e9d1a8SQiang XU //
894e9d1a8SQiang XU //      http://www.apache.org/licenses/LICENSE-2.0
994e9d1a8SQiang XU //
1094e9d1a8SQiang XU // Unless required by applicable law or agreed to in writing, software
1194e9d1a8SQiang XU // distributed under the License is distributed on an "AS IS" BASIS,
1294e9d1a8SQiang XU // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1394e9d1a8SQiang XU // See the License for the specific language governing permissions and
1494e9d1a8SQiang XU // limitations under the License.
1594e9d1a8SQiang XU */
1694e9d1a8SQiang XU 
1794e9d1a8SQiang XU #include <ipmid/api.hpp>
1894e9d1a8SQiang XU #include <ipmid/utils.hpp>
1994e9d1a8SQiang XU #include <multinodecommands.hpp>
2094e9d1a8SQiang XU #include <oemcommands.hpp>
2194e9d1a8SQiang XU #include <phosphor-logging/log.hpp>
2294e9d1a8SQiang XU #include <sdbusplus/bus.hpp>
2394e9d1a8SQiang XU #include <sdbusplus/message/types.hpp>
24fcd2d3a9SJames Feist 
2594e9d1a8SQiang XU #include <string>
2694e9d1a8SQiang XU 
2794e9d1a8SQiang XU namespace ipmi
2894e9d1a8SQiang XU {
2994e9d1a8SQiang XU void registerMultiNodeFunctions() __attribute__((constructor));
3094e9d1a8SQiang XU 
getMultiNodeInfo(std::string name)3194e9d1a8SQiang XU std::optional<uint8_t> getMultiNodeInfo(std::string name)
3294e9d1a8SQiang XU {
3394e9d1a8SQiang XU     auto pdbus = getSdBus();
3494e9d1a8SQiang XU     try
3594e9d1a8SQiang XU     {
36*b37abfb2SPatrick Williams         std::string service = getService(*pdbus, multiNodeIntf,
37*b37abfb2SPatrick Williams                                          multiNodeObjPath);
3894e9d1a8SQiang XU         Value dbusValue = getDbusProperty(*pdbus, service, multiNodeObjPath,
3994e9d1a8SQiang XU                                           multiNodeIntf, name);
4094e9d1a8SQiang XU         return std::get<uint8_t>(dbusValue);
4194e9d1a8SQiang XU     }
4294e9d1a8SQiang XU     catch (const std::exception& e)
4394e9d1a8SQiang XU     {
4494e9d1a8SQiang XU         phosphor::logging::log<phosphor::logging::level::ERR>(
4594e9d1a8SQiang XU             "getMultiNodeInfo: can't get multi node info from dbus!",
4694e9d1a8SQiang XU             phosphor::logging::entry("ERR=%s", e.what()));
4794e9d1a8SQiang XU         return std::nullopt;
4894e9d1a8SQiang XU     }
4994e9d1a8SQiang XU }
5094e9d1a8SQiang XU 
getMultiNodeRole()5194e9d1a8SQiang XU std::optional<uint8_t> getMultiNodeRole()
5294e9d1a8SQiang XU {
5394e9d1a8SQiang XU     auto pdbus = getSdBus();
5494e9d1a8SQiang XU     try
5594e9d1a8SQiang XU     {
56*b37abfb2SPatrick Williams         std::string service = getService(*pdbus, multiNodeIntf,
57*b37abfb2SPatrick Williams                                          multiNodeObjPath);
5894e9d1a8SQiang XU         Value dbusValue = getDbusProperty(*pdbus, service, multiNodeObjPath,
5994e9d1a8SQiang XU                                           multiNodeIntf, "NodeRole");
6094e9d1a8SQiang XU         std::string valueStr = std::get<std::string>(dbusValue);
6194e9d1a8SQiang XU         uint8_t value;
6294e9d1a8SQiang XU         if (valueStr == "single")
6394e9d1a8SQiang XU             value = static_cast<uint8_t>(NodeRole::single);
6494e9d1a8SQiang XU         else if (valueStr == "master")
6580d4d5f9SMatt Simmering             value = static_cast<uint8_t>(NodeRole::controller);
6694e9d1a8SQiang XU         else if (valueStr == "slave")
6780d4d5f9SMatt Simmering             value = static_cast<uint8_t>(NodeRole::target);
6894e9d1a8SQiang XU         else if (valueStr == "arbitrating")
6994e9d1a8SQiang XU             value = static_cast<uint8_t>(NodeRole::arbitrating);
7036ed8d24SP Dheeraj Srujan Kumar         else
7136ed8d24SP Dheeraj Srujan Kumar         {
7236ed8d24SP Dheeraj Srujan Kumar             phosphor::logging::log<phosphor::logging::level::ERR>(
7336ed8d24SP Dheeraj Srujan Kumar                 "getMultiNodeRole: Invalid dbus value!",
7436ed8d24SP Dheeraj Srujan Kumar                 phosphor::logging::entry("VALUE=%s", valueStr.c_str()));
7536ed8d24SP Dheeraj Srujan Kumar             return std::nullopt;
7636ed8d24SP Dheeraj Srujan Kumar         }
7794e9d1a8SQiang XU         return value;
7894e9d1a8SQiang XU     }
7994e9d1a8SQiang XU     catch (const std::exception& e)
8094e9d1a8SQiang XU     {
8194e9d1a8SQiang XU         phosphor::logging::log<phosphor::logging::level::ERR>(
8294e9d1a8SQiang XU             "getMultiNodeRole: can't get multi node role from dbus!",
8394e9d1a8SQiang XU             phosphor::logging::entry("ERR=%s", e.what()));
8494e9d1a8SQiang XU         return std::nullopt;
8594e9d1a8SQiang XU     }
8694e9d1a8SQiang XU }
8794e9d1a8SQiang XU 
ipmiGetMultiNodePresence()8894e9d1a8SQiang XU ipmi::RspType<uint8_t> ipmiGetMultiNodePresence()
8994e9d1a8SQiang XU 
9094e9d1a8SQiang XU {
9194e9d1a8SQiang XU     std::optional<uint8_t> nodeInfo = getMultiNodeInfo("NodePresence");
9294e9d1a8SQiang XU     if (!nodeInfo)
9394e9d1a8SQiang XU     {
9494e9d1a8SQiang XU         return ipmi::responseResponseError();
9594e9d1a8SQiang XU     }
9694e9d1a8SQiang XU 
9794e9d1a8SQiang XU     return ipmi::responseSuccess(*nodeInfo);
9894e9d1a8SQiang XU }
9994e9d1a8SQiang XU 
ipmiGetMultiNodeId()10094e9d1a8SQiang XU ipmi::RspType<uint8_t> ipmiGetMultiNodeId()
10194e9d1a8SQiang XU {
10294e9d1a8SQiang XU     std::optional<uint8_t> nodeInfo = getMultiNodeInfo("NodeId");
10394e9d1a8SQiang XU     if (!nodeInfo)
10494e9d1a8SQiang XU     {
10594e9d1a8SQiang XU         return ipmi::responseResponseError();
10694e9d1a8SQiang XU     }
10794e9d1a8SQiang XU 
10894e9d1a8SQiang XU     return ipmi::responseSuccess(*nodeInfo);
10994e9d1a8SQiang XU }
11094e9d1a8SQiang XU 
ipmiGetMultiNodeRole()11194e9d1a8SQiang XU ipmi::RspType<uint8_t> ipmiGetMultiNodeRole()
11294e9d1a8SQiang XU {
11394e9d1a8SQiang XU     std::optional<uint8_t> nodeInfo = getMultiNodeRole();
11494e9d1a8SQiang XU     if (!nodeInfo)
11594e9d1a8SQiang XU     {
11694e9d1a8SQiang XU         return ipmi::responseResponseError();
11794e9d1a8SQiang XU     }
11894e9d1a8SQiang XU 
11994e9d1a8SQiang XU     return ipmi::responseSuccess(*nodeInfo);
12094e9d1a8SQiang XU }
12194e9d1a8SQiang XU 
registerMultiNodeFunctions(void)12294e9d1a8SQiang XU void registerMultiNodeFunctions(void)
12394e9d1a8SQiang XU {
12494e9d1a8SQiang XU     phosphor::logging::log<phosphor::logging::level::INFO>(
12594e9d1a8SQiang XU         "Registering MultiNode commands");
12694e9d1a8SQiang XU 
12798bbf69aSVernon Mauery     ipmi::registerHandler(ipmi::prioOemBase, ipmi::intel::netFnGeneral,
12898bbf69aSVernon Mauery                           ipmi::intel::general::cmdGetMultiNodePresence,
12994e9d1a8SQiang XU                           ipmi::Privilege::User, ipmiGetMultiNodePresence);
13094e9d1a8SQiang XU 
13198bbf69aSVernon Mauery     ipmi::registerHandler(ipmi::prioOemBase, ipmi::intel::netFnGeneral,
13298bbf69aSVernon Mauery                           ipmi::intel::general::cmdGetMultiNodeId,
13394e9d1a8SQiang XU                           ipmi::Privilege::User, ipmiGetMultiNodeId);
13494e9d1a8SQiang XU 
13598bbf69aSVernon Mauery     ipmi::registerHandler(ipmi::prioOemBase, ipmi::intel::netFnGeneral,
13698bbf69aSVernon Mauery                           ipmi::intel::general::cmdGetMultiNodeRole,
13794e9d1a8SQiang XU                           ipmi::Privilege::User, ipmiGetMultiNodeRole);
13894e9d1a8SQiang XU }
13994e9d1a8SQiang XU 
14094e9d1a8SQiang XU } // namespace ipmi
141