blob: f376d44acd6e38f199ce4bcdaebb869083b69a63 [file] [log] [blame]
Patrick Venture391b8b02018-03-08 08:31:13 -08001/**
2 * Copyright 2017 Google Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Patrick Venture36ab6f62020-08-03 10:50:26 -070017#include "manualcmds.hpp"
18
William A. Kennington III331143c2019-02-07 15:52:44 -080019#include <ipmid/api.h>
Patrick Venture391b8b02018-03-08 08:31:13 -080020
William A. Kennington III331143c2019-02-07 15:52:44 -080021#include <ipmid/iana.hpp>
22#include <ipmid/oemopenbmc.hpp>
23#include <ipmid/oemrouter.hpp>
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070024#include <sdbusplus/bus.hpp>
25#include <sdbusplus/message.hpp>
Patrick Venturea83a3ec2020-08-04 09:52:05 -070026
27#include <map>
Patrick Venture391b8b02018-03-08 08:31:13 -080028#include <string>
29#include <tuple>
James Feist1f802f52019-02-08 13:51:43 -080030#include <variant>
Patrick Venture391b8b02018-03-08 08:31:13 -080031
Patrick Venture36ab6f62020-08-03 10:50:26 -070032namespace pid_control
Patrick Venture391b8b02018-03-08 08:31:13 -080033{
Patrick Venture36ab6f62020-08-03 10:50:26 -070034namespace ipmi
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070035{
Patrick Venture391b8b02018-03-08 08:31:13 -080036
37static constexpr auto objectPath = "/xyz/openbmc_project/settings/fanctrl/zone";
38static constexpr auto busName = "xyz.openbmc_project.State.FanCtrl";
Patrick Venturedc3b7902018-03-24 10:41:19 -070039static constexpr auto intf = "xyz.openbmc_project.Control.Mode";
Patrick Venture391b8b02018-03-08 08:31:13 -080040static constexpr auto manualProperty = "Manual";
41static constexpr auto failsafeProperty = "FailSafe";
42static constexpr auto propertiesintf = "org.freedesktop.DBus.Properties";
43
44using Property = std::string;
William A. Kennington III323f1d92020-06-03 11:18:24 -070045using Value = std::variant<bool>;
Patrick Venture391b8b02018-03-08 08:31:13 -080046using PropertyMap = std::map<Property, Value>;
47
48/* The following was copied directly from my manual thread handler. */
Patrick Venture7af157b2018-10-30 11:24:40 -070049static std::string getControlPath(int8_t zone)
Patrick Venture391b8b02018-03-08 08:31:13 -080050{
51 return std::string(objectPath) + std::to_string(zone);
52}
53
54/*
55 * busctl call xyz.openbmc_project.State.FanCtrl \
56 * /xyz/openbmc_project/settings/fanctrl/zone1 \
57 * org.freedesktop.DBus.Properties \
58 * GetAll \
59 * s \
Patrick Venturedc3b7902018-03-24 10:41:19 -070060 * xyz.openbmc_project.Control.Mode
Patrick Venture391b8b02018-03-08 08:31:13 -080061 * a{sv} 2 "Manual" b false "FailSafe" b false
62 */
63
Patrick Venture7af157b2018-10-30 11:24:40 -070064static ipmi_ret_t getFanCtrlProperty(uint8_t zoneId, bool* value,
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070065 const std::string& property)
Patrick Venture391b8b02018-03-08 08:31:13 -080066{
Patrick Venture7af157b2018-10-30 11:24:40 -070067 std::string path = getControlPath(zoneId);
Patrick Venture391b8b02018-03-08 08:31:13 -080068
James Feist9fa90c12019-01-11 15:35:22 -080069 auto propertyReadBus = sdbusplus::bus::new_system();
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070070 auto pimMsg = propertyReadBus.new_method_call(busName, path.c_str(),
71 propertiesintf, "GetAll");
Patrick Venture391b8b02018-03-08 08:31:13 -080072 pimMsg.append(intf);
73
Patrick Ventureacecf6b2018-09-06 17:56:41 -070074 try
75 {
Patrick Ventureacecf6b2018-09-06 17:56:41 -070076 PropertyMap propMap;
Patrick Venture8f179142018-09-10 09:24:12 -070077
78 /* a method could error but the call not error. */
79 auto valueResponseMsg = propertyReadBus.call(pimMsg);
Patrick Venture8f179142018-09-10 09:24:12 -070080
Patrick Ventureacecf6b2018-09-06 17:56:41 -070081 valueResponseMsg.read(propMap);
82
James Feist1f802f52019-02-08 13:51:43 -080083 *value = std::get<bool>(propMap[property]);
Patrick Ventureacecf6b2018-09-06 17:56:41 -070084 }
85 catch (const sdbusplus::exception::SdBusError& ex)
Patrick Venture391b8b02018-03-08 08:31:13 -080086 {
87 return IPMI_CC_INVALID;
88 }
89
Patrick Venture391b8b02018-03-08 08:31:13 -080090 return IPMI_CC_OK;
91}
92
Patrick Venture7af157b2018-10-30 11:24:40 -070093static ipmi_ret_t getFailsafeModeState(const uint8_t* reqBuf, uint8_t* replyBuf,
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070094 size_t* dataLen)
Patrick Venture391b8b02018-03-08 08:31:13 -080095{
Patrick Venture391b8b02018-03-08 08:31:13 -080096 bool current;
97
98 if (*dataLen < sizeof(struct FanCtrlRequest))
99 {
100 return IPMI_CC_INVALID;
101 }
102
103 const auto request =
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700104 reinterpret_cast<const struct FanCtrlRequest*>(&reqBuf[0]);
Patrick Venture391b8b02018-03-08 08:31:13 -0800105
Patrick Venture37b247a2020-08-03 11:15:21 -0700106 ipmi_ret_t rc =
107 getFanCtrlProperty(request->zone, &current, failsafeProperty);
Patrick Venture391b8b02018-03-08 08:31:13 -0800108 if (rc)
109 {
110 return rc;
111 }
112
113 *replyBuf = (uint8_t)current;
114 *dataLen = sizeof(uint8_t);
Patrick Venture37b247a2020-08-03 11:15:21 -0700115 return IPMI_CC_OK;
Patrick Venture391b8b02018-03-08 08:31:13 -0800116}
117
118/*
119 * <method name="GetAll">
120 * <arg name="interface" direction="in" type="s"/>
121 * <arg name="properties" direction="out" type="a{sv}"/>
122 * </method>
123 */
Patrick Venture7af157b2018-10-30 11:24:40 -0700124static ipmi_ret_t getManualModeState(const uint8_t* reqBuf, uint8_t* replyBuf,
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700125 size_t* dataLen)
Patrick Venture391b8b02018-03-08 08:31:13 -0800126{
Patrick Venture391b8b02018-03-08 08:31:13 -0800127 bool current;
128
129 if (*dataLen < sizeof(struct FanCtrlRequest))
130 {
131 return IPMI_CC_INVALID;
132 }
133
134 const auto request =
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700135 reinterpret_cast<const struct FanCtrlRequest*>(&reqBuf[0]);
Patrick Venture391b8b02018-03-08 08:31:13 -0800136
Patrick Venture37b247a2020-08-03 11:15:21 -0700137 ipmi_ret_t rc = getFanCtrlProperty(request->zone, &current, manualProperty);
Patrick Venture391b8b02018-03-08 08:31:13 -0800138 if (rc)
139 {
140 return rc;
141 }
142
143 *replyBuf = (uint8_t)current;
144 *dataLen = sizeof(uint8_t);
Patrick Venture37b247a2020-08-03 11:15:21 -0700145 return IPMI_CC_OK;
Patrick Venture391b8b02018-03-08 08:31:13 -0800146}
147
148/*
149 * <method name="Set">
150 * <arg name="interface" direction="in" type="s"/>
151 * <arg name="property" direction="in" type="s"/>
152 * <arg name="value" direction="in" type="v"/>
153 * </method>
154 */
Patrick Venture7af157b2018-10-30 11:24:40 -0700155static ipmi_ret_t setManualModeState(const uint8_t* reqBuf, uint8_t* replyBuf,
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700156 size_t* dataLen)
Patrick Venture391b8b02018-03-08 08:31:13 -0800157{
Patrick Venture391b8b02018-03-08 08:31:13 -0800158 if (*dataLen < sizeof(struct FanCtrlRequestSet))
159 {
160 return IPMI_CC_INVALID;
161 }
162
William A. Kennington III323f1d92020-06-03 11:18:24 -0700163 using Value = std::variant<bool>;
Patrick Venture391b8b02018-03-08 08:31:13 -0800164
165 const auto request =
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700166 reinterpret_cast<const struct FanCtrlRequestSet*>(&reqBuf[0]);
Patrick Venture391b8b02018-03-08 08:31:13 -0800167
168 /* 0 is false, 1 is true */
169 bool setValue = static_cast<bool>(request->value);
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700170 Value v{setValue};
Patrick Venture391b8b02018-03-08 08:31:13 -0800171
James Feist9fa90c12019-01-11 15:35:22 -0800172 auto PropertyWriteBus = sdbusplus::bus::new_system();
Patrick Venture391b8b02018-03-08 08:31:13 -0800173
Patrick Venture7af157b2018-10-30 11:24:40 -0700174 std::string path = getControlPath(request->zone);
Patrick Venture391b8b02018-03-08 08:31:13 -0800175
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700176 auto pimMsg = PropertyWriteBus.new_method_call(busName, path.c_str(),
177 propertiesintf, "Set");
Patrick Venture391b8b02018-03-08 08:31:13 -0800178 pimMsg.append(intf);
179 pimMsg.append(manualProperty);
180 pimMsg.append(v);
Patrick Ventureacecf6b2018-09-06 17:56:41 -0700181
Patrick Venture37b247a2020-08-03 11:15:21 -0700182 ipmi_ret_t rc = IPMI_CC_OK;
183
Patrick Ventureacecf6b2018-09-06 17:56:41 -0700184 try
185 {
186 PropertyWriteBus.call_noreply(pimMsg);
187 }
188 catch (const sdbusplus::exception::SdBusError& ex)
Patrick Venture391b8b02018-03-08 08:31:13 -0800189 {
190 rc = IPMI_CC_INVALID;
191 }
192 /* TODO(venture): Should sanity check the result. */
193
194 return rc;
195}
196
197/* Three command packages: get, set true, set false */
Patrick Venture7af157b2018-10-30 11:24:40 -0700198static ipmi_ret_t manualModeControl(ipmi_cmd_t cmd, const uint8_t* reqBuf,
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700199 uint8_t* replyCmdBuf, size_t* dataLen)
Patrick Venture391b8b02018-03-08 08:31:13 -0800200{
Patrick Venture391b8b02018-03-08 08:31:13 -0800201 // FanCtrlRequest is the smaller of the requests, so it's at a minimum.
202 if (*dataLen < sizeof(struct FanCtrlRequest))
203 {
204 return IPMI_CC_INVALID;
205 }
206
207 const auto request =
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700208 reinterpret_cast<const struct FanCtrlRequest*>(&reqBuf[0]);
Patrick Venture391b8b02018-03-08 08:31:13 -0800209
Patrick Venture37b247a2020-08-03 11:15:21 -0700210 ipmi_ret_t rc = IPMI_CC_OK;
211
Patrick Venture391b8b02018-03-08 08:31:13 -0800212 switch (request->command)
213 {
Patrick Venture12775432020-08-04 09:57:36 -0700214 case getControlState:
Patrick Venture7af157b2018-10-30 11:24:40 -0700215 return getManualModeState(reqBuf, replyCmdBuf, dataLen);
Patrick Venture12775432020-08-04 09:57:36 -0700216 case setControlState:
Patrick Venture7af157b2018-10-30 11:24:40 -0700217 return setManualModeState(reqBuf, replyCmdBuf, dataLen);
Patrick Venture12775432020-08-04 09:57:36 -0700218 case getFailsafeState:
Patrick Venture7af157b2018-10-30 11:24:40 -0700219 return getFailsafeModeState(reqBuf, replyCmdBuf, dataLen);
Patrick Venture391b8b02018-03-08 08:31:13 -0800220 default:
221 rc = IPMI_CC_INVALID;
222 }
223
224 return rc;
225}
226
Patrick Venture36ab6f62020-08-03 10:50:26 -0700227} // namespace ipmi
228} // namespace pid_control
229
Patrick Venture391b8b02018-03-08 08:31:13 -0800230void setupGlobalOemFanControl() __attribute__((constructor));
231
232void setupGlobalOemFanControl()
233{
Patrick Ventureba003432018-07-27 06:59:05 -0700234 oem::Router* router = oem::mutableRouter();
Patrick Venture391b8b02018-03-08 08:31:13 -0800235
236 fprintf(stderr,
237 "Registering OEM:[%#08X], Cmd:[%#04X] for Manual Zone Control\n",
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700238 oem::obmcOemNumber, oem::Cmd::fanManualCmd);
Patrick Venture391b8b02018-03-08 08:31:13 -0800239
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700240 router->registerHandler(oem::obmcOemNumber, oem::Cmd::fanManualCmd,
Patrick Venture36ab6f62020-08-03 10:50:26 -0700241 pid_control::ipmi::manualModeControl);
Patrick Venture391b8b02018-03-08 08:31:13 -0800242}