1a3702c1fSVernon Mauery /*
2a3702c1fSVernon Mauery // Copyright (c) 2018 Intel Corporation
3a3702c1fSVernon Mauery //
4a3702c1fSVernon Mauery // Licensed under the Apache License, Version 2.0 (the "License");
5a3702c1fSVernon Mauery // you may not use this file except in compliance with the License.
6a3702c1fSVernon Mauery // You may obtain a copy of the License at
7a3702c1fSVernon Mauery //
8a3702c1fSVernon Mauery // http://www.apache.org/licenses/LICENSE-2.0
9a3702c1fSVernon Mauery //
10a3702c1fSVernon Mauery // Unless required by applicable law or agreed to in writing, software
11a3702c1fSVernon Mauery // distributed under the License is distributed on an "AS IS" BASIS,
12a3702c1fSVernon Mauery // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a3702c1fSVernon Mauery // See the License for the specific language governing permissions and
14a3702c1fSVernon Mauery // limitations under the License.
15a3702c1fSVernon Mauery */
16a3702c1fSVernon Mauery
17a3702c1fSVernon Mauery #include "oemcommands.hpp"
18a3702c1fSVernon Mauery
19edf25e61SRichard Marian Thomaiyar #include <boost/algorithm/string.hpp>
20a3702c1fSVernon Mauery #include <ipmid/api.hpp>
21a3702c1fSVernon Mauery #include <ipmid/utils.hpp>
22a3702c1fSVernon Mauery #include <phosphor-logging/log.hpp>
230748c69dSJason M. Bills #include <types.hpp>
24fcd2d3a9SJames Feist
25edf25e61SRichard Marian Thomaiyar #include <variant>
26a3702c1fSVernon Mauery
27edf25e61SRichard Marian Thomaiyar namespace ipmi
28edf25e61SRichard Marian Thomaiyar {
29a3702c1fSVernon Mauery void register_netfn_bmc_control_functions() __attribute__((constructor));
30a3702c1fSVernon Mauery
31edf25e61SRichard Marian Thomaiyar static constexpr uint8_t rmcpServiceBitPos = 3;
32edf25e61SRichard Marian Thomaiyar static constexpr uint8_t webServiceBitPos = 5;
33edf25e61SRichard Marian Thomaiyar static constexpr uint8_t solServiceBitPos = 6;
34edf25e61SRichard Marian Thomaiyar static constexpr uint8_t kvmServiceBitPos = 15;
35edf25e61SRichard Marian Thomaiyar
3695f69336SJiaqing Zhao static constexpr std::array<std::pair<uint8_t, const char*>, 4> bmcServices = {{
3795f69336SJiaqing Zhao // {bit position for service, service name}
3895f69336SJiaqing Zhao {rmcpServiceBitPos, "phosphor-ipmi-net"},
3995f69336SJiaqing Zhao {webServiceBitPos, "bmcweb"},
4095f69336SJiaqing Zhao {solServiceBitPos, "obmc-console-ssh"},
41*9890d29dSMohammed Javith Akthar M {kvmServiceBitPos, "obmc-ikvm"},
4295f69336SJiaqing Zhao }};
43a3702c1fSVernon Mauery
4498cb6186SArun P. Mohanan static constexpr uint16_t maskBit15 = 0x8000;
45a3702c1fSVernon Mauery
46a3702c1fSVernon Mauery static constexpr const char* objectManagerIntf =
47a3702c1fSVernon Mauery "org.freedesktop.DBus.ObjectManager";
48edf25e61SRichard Marian Thomaiyar static constexpr const char* dBusPropIntf = "org.freedesktop.DBus.Properties";
49a3702c1fSVernon Mauery static constexpr const char* serviceConfigBasePath =
50a3702c1fSVernon Mauery "/xyz/openbmc_project/control/service";
51a3702c1fSVernon Mauery static constexpr const char* serviceConfigAttrIntf =
52a3702c1fSVernon Mauery "xyz.openbmc_project.Control.Service.Attributes";
53edf25e61SRichard Marian Thomaiyar static constexpr const char* getMgdObjMethod = "GetManagedObjects";
54edf25e61SRichard Marian Thomaiyar static constexpr const char* propMasked = "Masked";
55a3702c1fSVernon Mauery
getServiceConfigMgrName()56edf25e61SRichard Marian Thomaiyar std::string getServiceConfigMgrName()
57a3702c1fSVernon Mauery {
58a3702c1fSVernon Mauery static std::string serviceCfgMgr{};
59a3702c1fSVernon Mauery if (serviceCfgMgr.empty())
60a3702c1fSVernon Mauery {
61a3702c1fSVernon Mauery try
62a3702c1fSVernon Mauery {
63edf25e61SRichard Marian Thomaiyar auto sdbusp = getSdBus();
64edf25e61SRichard Marian Thomaiyar serviceCfgMgr = ipmi::getService(*sdbusp, objectManagerIntf,
65a3702c1fSVernon Mauery serviceConfigBasePath);
66a3702c1fSVernon Mauery }
67f944d2e5SPatrick Williams catch (const sdbusplus::exception_t& e)
68a3702c1fSVernon Mauery {
69a3702c1fSVernon Mauery serviceCfgMgr.clear();
70a3702c1fSVernon Mauery phosphor::logging::log<phosphor::logging::level::ERR>(
71a3702c1fSVernon Mauery "Error: In fetching disabling service manager name");
72edf25e61SRichard Marian Thomaiyar return serviceCfgMgr;
73a3702c1fSVernon Mauery }
74a3702c1fSVernon Mauery }
75edf25e61SRichard Marian Thomaiyar return serviceCfgMgr;
76edf25e61SRichard Marian Thomaiyar }
77edf25e61SRichard Marian Thomaiyar
checkAndThrowError(boost::system::error_code & ec,const std::string & msg)78edf25e61SRichard Marian Thomaiyar static inline void checkAndThrowError(boost::system::error_code& ec,
79edf25e61SRichard Marian Thomaiyar const std::string& msg)
80a3702c1fSVernon Mauery {
81edf25e61SRichard Marian Thomaiyar if (ec)
82edf25e61SRichard Marian Thomaiyar {
83edf25e61SRichard Marian Thomaiyar std::string msgToLog = ec.message() + (msg.empty() ? "" : " - " + msg);
84edf25e61SRichard Marian Thomaiyar phosphor::logging::log<phosphor::logging::level::ERR>(msgToLog.c_str());
85edf25e61SRichard Marian Thomaiyar throw sdbusplus::exception::SdBusError(-EIO, msgToLog.c_str());
86a3702c1fSVernon Mauery }
87edf25e61SRichard Marian Thomaiyar return;
88edf25e61SRichard Marian Thomaiyar }
89edf25e61SRichard Marian Thomaiyar
getEnabledValue(const DbusInterfaceMap & intfMap)90edf25e61SRichard Marian Thomaiyar static inline bool getEnabledValue(const DbusInterfaceMap& intfMap)
91edf25e61SRichard Marian Thomaiyar {
92edf25e61SRichard Marian Thomaiyar for (const auto& intf : intfMap)
93edf25e61SRichard Marian Thomaiyar {
94edf25e61SRichard Marian Thomaiyar if (intf.first == serviceConfigAttrIntf)
95edf25e61SRichard Marian Thomaiyar {
96edf25e61SRichard Marian Thomaiyar auto it = intf.second.find(propMasked);
97edf25e61SRichard Marian Thomaiyar if (it == intf.second.end())
98a3702c1fSVernon Mauery {
99a3702c1fSVernon Mauery phosphor::logging::log<phosphor::logging::level::ERR>(
100edf25e61SRichard Marian Thomaiyar "Error: in getting Masked property value");
101edf25e61SRichard Marian Thomaiyar throw sdbusplus::exception::SdBusError(
102edf25e61SRichard Marian Thomaiyar -EIO, "ERROR in reading Masked property value");
103edf25e61SRichard Marian Thomaiyar }
104edf25e61SRichard Marian Thomaiyar // return !Masked value
105edf25e61SRichard Marian Thomaiyar return !std::get<bool>(it->second);
106edf25e61SRichard Marian Thomaiyar }
107a3702c1fSVernon Mauery }
10813b0039dSJames Feist return false;
109a3702c1fSVernon Mauery }
110a3702c1fSVernon Mauery
setBmcControlServices(boost::asio::yield_context yield,uint8_t state,uint16_t serviceValue)111edf25e61SRichard Marian Thomaiyar ipmi::RspType<> setBmcControlServices(boost::asio::yield_context yield,
112edf25e61SRichard Marian Thomaiyar uint8_t state, uint16_t serviceValue)
113edf25e61SRichard Marian Thomaiyar {
114edf25e61SRichard Marian Thomaiyar constexpr uint16_t servicesRsvdMask = 0x3F97;
115edf25e61SRichard Marian Thomaiyar constexpr uint8_t enableService = 0x1;
116a3702c1fSVernon Mauery
117edf25e61SRichard Marian Thomaiyar if ((state > enableService) || (serviceValue & servicesRsvdMask) ||
118edf25e61SRichard Marian Thomaiyar !serviceValue)
119a3702c1fSVernon Mauery {
120edf25e61SRichard Marian Thomaiyar return ipmi::responseInvalidFieldRequest();
121a3702c1fSVernon Mauery }
122edf25e61SRichard Marian Thomaiyar try
123edf25e61SRichard Marian Thomaiyar {
124edf25e61SRichard Marian Thomaiyar auto sdbusp = getSdBus();
125edf25e61SRichard Marian Thomaiyar boost::system::error_code ec;
126edf25e61SRichard Marian Thomaiyar auto objectMap = sdbusp->yield_method_call<ObjectValueTree>(
127edf25e61SRichard Marian Thomaiyar yield, ec, getServiceConfigMgrName().c_str(), serviceConfigBasePath,
128edf25e61SRichard Marian Thomaiyar objectManagerIntf, getMgdObjMethod);
129edf25e61SRichard Marian Thomaiyar checkAndThrowError(ec, "GetMangagedObjects for service cfg failed");
130a3702c1fSVernon Mauery
131edf25e61SRichard Marian Thomaiyar for (const auto& services : bmcServices)
132a3702c1fSVernon Mauery {
133edf25e61SRichard Marian Thomaiyar // services.first holds the bit position of the service, check
134edf25e61SRichard Marian Thomaiyar // whether it has to be updated.
135edf25e61SRichard Marian Thomaiyar const uint16_t serviceMask = 1 << services.first;
136edf25e61SRichard Marian Thomaiyar if (!(serviceValue & serviceMask))
137edf25e61SRichard Marian Thomaiyar {
138edf25e61SRichard Marian Thomaiyar continue;
139a3702c1fSVernon Mauery }
140edf25e61SRichard Marian Thomaiyar for (const auto& obj : objectMap)
141a3702c1fSVernon Mauery {
14295f69336SJiaqing Zhao if (boost::algorithm::starts_with(obj.first.filename(),
143edf25e61SRichard Marian Thomaiyar services.second))
144a3702c1fSVernon Mauery {
145edf25e61SRichard Marian Thomaiyar if (state != getEnabledValue(obj.second))
146a3702c1fSVernon Mauery {
147edf25e61SRichard Marian Thomaiyar ec.clear();
148edf25e61SRichard Marian Thomaiyar sdbusp->yield_method_call<>(
149edf25e61SRichard Marian Thomaiyar yield, ec, getServiceConfigMgrName().c_str(),
150edf25e61SRichard Marian Thomaiyar obj.first.str, dBusPropIntf, "Set",
151edf25e61SRichard Marian Thomaiyar serviceConfigAttrIntf, propMasked,
1520748c69dSJason M. Bills ipmi::DbusVariant(!state));
153edf25e61SRichard Marian Thomaiyar checkAndThrowError(ec, "Set Masked property failed");
154edf25e61SRichard Marian Thomaiyar // Multiple instances may be present, so continue
155a3702c1fSVernon Mauery }
156a3702c1fSVernon Mauery }
157a3702c1fSVernon Mauery }
158edf25e61SRichard Marian Thomaiyar }
159edf25e61SRichard Marian Thomaiyar }
160f944d2e5SPatrick Williams catch (const sdbusplus::exception_t& e)
161edf25e61SRichard Marian Thomaiyar {
162edf25e61SRichard Marian Thomaiyar return ipmi::responseUnspecifiedError();
163edf25e61SRichard Marian Thomaiyar }
164a3702c1fSVernon Mauery return ipmi::responseSuccess();
165a3702c1fSVernon Mauery }
166a3702c1fSVernon Mauery
getBmcControlServices(boost::asio::yield_context yield)167edf25e61SRichard Marian Thomaiyar ipmi::RspType<uint16_t> getBmcControlServices(boost::asio::yield_context yield)
168edf25e61SRichard Marian Thomaiyar {
169edf25e61SRichard Marian Thomaiyar uint16_t serviceValue = 0;
170edf25e61SRichard Marian Thomaiyar try
171edf25e61SRichard Marian Thomaiyar {
172edf25e61SRichard Marian Thomaiyar auto sdbusp = getSdBus();
173edf25e61SRichard Marian Thomaiyar boost::system::error_code ec;
174edf25e61SRichard Marian Thomaiyar auto objectMap = sdbusp->yield_method_call<ObjectValueTree>(
175edf25e61SRichard Marian Thomaiyar yield, ec, getServiceConfigMgrName().c_str(), serviceConfigBasePath,
176edf25e61SRichard Marian Thomaiyar objectManagerIntf, getMgdObjMethod);
177edf25e61SRichard Marian Thomaiyar checkAndThrowError(ec, "GetMangagedObjects for service cfg failed");
178edf25e61SRichard Marian Thomaiyar
179edf25e61SRichard Marian Thomaiyar for (const auto& services : bmcServices)
180edf25e61SRichard Marian Thomaiyar {
181edf25e61SRichard Marian Thomaiyar for (const auto& obj : objectMap)
182edf25e61SRichard Marian Thomaiyar {
18395f69336SJiaqing Zhao if (boost::algorithm::starts_with(obj.first.filename(),
184edf25e61SRichard Marian Thomaiyar services.second))
185edf25e61SRichard Marian Thomaiyar {
186edf25e61SRichard Marian Thomaiyar serviceValue |= getEnabledValue(obj.second)
187edf25e61SRichard Marian Thomaiyar << services.first;
188edf25e61SRichard Marian Thomaiyar break;
189edf25e61SRichard Marian Thomaiyar }
190edf25e61SRichard Marian Thomaiyar }
191edf25e61SRichard Marian Thomaiyar }
192edf25e61SRichard Marian Thomaiyar }
193f944d2e5SPatrick Williams catch (const sdbusplus::exception_t& e)
194edf25e61SRichard Marian Thomaiyar {
195edf25e61SRichard Marian Thomaiyar return ipmi::responseUnspecifiedError();
196edf25e61SRichard Marian Thomaiyar }
197edf25e61SRichard Marian Thomaiyar // Bit 14 should match bit 15 as single service maintains Video & USB
198edf25e61SRichard Marian Thomaiyar // redirection
199edf25e61SRichard Marian Thomaiyar serviceValue |= (serviceValue & maskBit15) >> 1;
200edf25e61SRichard Marian Thomaiyar return ipmi::responseSuccess(serviceValue);
201edf25e61SRichard Marian Thomaiyar }
202edf25e61SRichard Marian Thomaiyar
register_netfn_bmc_control_functions()203a3702c1fSVernon Mauery void register_netfn_bmc_control_functions()
204a3702c1fSVernon Mauery {
20598bbf69aSVernon Mauery registerHandler(prioOpenBmcBase, intel::netFnGeneral,
20698bbf69aSVernon Mauery intel::general::cmdControlBmcServices, Privilege::Admin,
20798bbf69aSVernon Mauery setBmcControlServices);
208edf25e61SRichard Marian Thomaiyar
20998bbf69aSVernon Mauery registerHandler(prioOpenBmcBase, intel::netFnGeneral,
21098bbf69aSVernon Mauery intel::general::cmdGetBmcServiceStatus, Privilege::User,
21198bbf69aSVernon Mauery getBmcControlServices);
212a3702c1fSVernon Mauery }
213edf25e61SRichard Marian Thomaiyar } // namespace ipmi
214