1 /*
2 // Copyright (c) 2018 Intel Corporation
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 
17 #pragma once
18 
19 #include <ipmid/api-types.hpp>
20 #include <ipmid/utils.hpp>
21 #include <phosphor-logging/log.hpp>
22 #include <sdbusplus/bus.hpp>
23 #include <sdbusplus/message.hpp>
24 #include <sdbusplus/timer.hpp>
25 #include <variantvisitors.hpp>
26 
27 #include <vector>
28 
29 #define FAN_SENSOR_NOT_PRESENT (0 << 0)
30 #define FAN_SENSOR_PRESENT (1 << 0)
31 #define FAN_NOT_PRESENT (0 << 1)
32 #define FAN_PRESENT (1 << 1)
33 
34 namespace ipmi
35 {
36 
37 // TODO: Service names may change. Worth to consider dynamic detection.
38 static constexpr const char* fanService = "xyz.openbmc_project.FanSensor";
39 static constexpr const char* buttonService =
40     "xyz.openbmc_project.Chassis.Buttons";
41 static constexpr const char* ledServicePrefix =
42     "xyz.openbmc_project.LED.Controller.";
43 
44 static constexpr const char* ledPathPrefix =
45     "/xyz/openbmc_project/led/physical/";
46 static constexpr const char* fanPwmPath =
47     "/xyz/openbmc_project/sensors/fan_pwm/Pwm_";
48 static constexpr const char* fanTachBasePath =
49     "/xyz/openbmc_project/sensors/fan_tach/";
50 
51 static constexpr const char* fanIntf = "xyz.openbmc_project.Sensor.Value";
52 static constexpr const char* buttonIntf = "xyz.openbmc_project.Chassis.Buttons";
53 static constexpr const char* ledIntf = "xyz.openbmc_project.Led.Physical";
54 
55 static constexpr const char* intrusionService =
56     "xyz.openbmc_project.IntrusionSensor";
57 static constexpr const char* intrusionPath =
58     "/xyz/openbmc_project/Intrusion/Chassis_Intrusion";
59 static constexpr const char* intrusionIntf =
60     "xyz.openbmc_project.Chassis.Intrusion";
61 
62 static constexpr const char* busPropertyIntf =
63     "org.freedesktop.DBus.Properties";
64 static constexpr const char* ledStateStr =
65     "xyz.openbmc_project.Led.Physical.Action."; // Comes with postfix Off/On
66 
67 static constexpr const char* specialModeService =
68     "xyz.openbmc_project.SpecialMode";
69 static constexpr const char* specialModeObjPath =
70     "/xyz/openbmc_project/security/special_mode";
71 static constexpr const char* specialModeIntf =
72     "xyz.openbmc_project.Security.SpecialMode";
73 
74 enum class SpecialMode : uint8_t
75 {
76     none = 0,
77     mfg = 1,
78 #ifdef BMC_VALIDATION_UNSECURE_FEATURE
79     valUnsecure = 2
80 #endif
81 };
82 
83 enum class SmActionGet : uint8_t
84 {
85     sample = 0,
86     ignore = 1,
87     revert = 2
88 };
89 
90 enum class SmActionSet : uint8_t
91 {
92     forceDeasserted = 0,
93     forceAsserted = 1,
94     revert = 2
95 };
96 
97 enum class SmSignalGet : uint8_t
98 {
99     smPowerButton = 0,
100     smResetButton = 1,
101     smSleepButton,
102     smNMIButton = 3,
103     smChassisIntrusion = 4,
104     smPowerGood,
105     smPowerRequestGet,
106     smSleepRequestGet,
107     smFrbTimerHaltGet,
108     smForceUpdate,
109     smRingIndication,
110     smCarrierDetect,
111     smIdentifyButton = 0xc,
112     smFanPwmGet = 0xd,
113     smSignalReserved,
114     smFanTachometerGet = 0xf,
115     smNcsiDiag = 0x10,
116     smGetSignalMax
117 };
118 
119 enum class SmSignalSet : uint8_t
120 {
121     smPowerLed = 0,
122     smPowerFaultLed,
123     smClusterLed,
124     smDiskFaultLed,
125     smCoolingFaultLed,
126     smFanPowerSpeed = 5,
127     smPowerRequestSet,
128     smSleepRequestSet,
129     smAcpiSci,
130     smSpeaker,
131     smFanPackFaultLed,
132     smCpuFailLed,
133     smDimmFailLed,
134     smIdentifyLed,
135     smHddLed,
136     smSystemReadyLed,
137     smLcdBacklight = 0x10,
138     smSetSignalMax
139 };
140 
141 /** @enum IntrusionStatus
142 .*
143  *  Intrusion Status
144  */
145 enum class IntrusionStatus : uint8_t
146 {
147     normal = 0,
148     hardwareIntrusion,
149     tamperingDetected
150 };
151 
152 struct SetSmSignalReq
153 {
154     SmSignalSet Signal;
155     uint8_t Instance;
156     SmActionSet Action;
157     uint8_t Value;
158 };
159 
160 class LedProperty
161 {
162     SmSignalSet signal;
163     std::string name;
164     std::string prevState;
165     std::string currentState;
166     bool isLocked;
167 
168   public:
169     LedProperty(SmSignalSet signal_, std::string name_) :
170         signal(signal_), name(name_), prevState(""), isLocked(false)
171     {}
172 
173     LedProperty() = delete;
174 
175     SmSignalSet getSignal() const
176     {
177         return signal;
178     }
179 
180     void setLock(const bool& lock)
181     {
182         isLocked = lock;
183     }
184     void setPrevState(const std::string& state)
185     {
186         prevState = state;
187     }
188     void setCurrState(const std::string& state)
189     {
190         currentState = state;
191     }
192     std::string getCurrState() const
193     {
194         return currentState;
195     }
196     bool getLock() const
197     {
198         return isLocked;
199     }
200     std::string getPrevState() const
201     {
202         return prevState;
203     }
204     std::string getName() const
205     {
206         return name;
207     }
208 };
209 
210 /** @class Manufacturing
211  *
212  *  @brief Implemet commands to support Manufacturing Test Mode.
213  */
214 class Manufacturing
215 {
216     std::string path;
217     std::string gpioPaths[(uint8_t)SmSignalGet::smGetSignalMax];
218     std::vector<LedProperty> ledPropertyList;
219     void initData();
220 
221   public:
222     Manufacturing();
223 
224     ipmi_return_codes detectAccessLvl(ipmi_request_t request,
225                                       ipmi_data_len_t req_len);
226 
227     LedProperty* findLedProperty(const SmSignalSet& signal)
228     {
229         auto it = std::find_if(ledPropertyList.begin(), ledPropertyList.end(),
230                                [&signal](const LedProperty& led) {
231                                    return led.getSignal() == signal;
232                                });
233         if (it != ledPropertyList.end())
234         {
235             return &(*it);
236         }
237         return nullptr;
238     }
239 
240     std::string getLedPropertyName(const SmSignalSet signal)
241     {
242         LedProperty* led = findLedProperty(signal);
243         if (led != nullptr)
244         {
245             return led->getName();
246         }
247         else
248         {
249             return "";
250         }
251     }
252 
253     int8_t getProperty(const std::string& service, const std::string& path,
254                        const std::string& interface,
255                        const std::string& propertyName, ipmi::Value* value);
256     int8_t setProperty(const std::string& service, const std::string& path,
257                        const std::string& interface,
258                        const std::string& propertyName, ipmi::Value value);
259     int8_t disablePidControlService(const bool disable);
260 
261     void revertTimerHandler();
262 
263     SpecialMode getMfgMode(void)
264     {
265         ipmi::Value mode;
266         if (getProperty(specialModeService, specialModeObjPath, specialModeIntf,
267                         "SpecialMode", &mode) != 0)
268         {
269             return SpecialMode::none;
270         }
271         if (std::get<std::string>(mode) ==
272             "xyz.openbmc_project.Control.Security.SpecialMode.Modes."
273             "Manufacturing")
274         {
275             return SpecialMode::mfg;
276         }
277 #ifdef BMC_VALIDATION_UNSECURE_FEATURE
278         if (std::get<std::string>(mode) ==
279             "xyz.openbmc_project.Control.Security.SpecialMode.Modes."
280             "ValidationUnsecure")
281         {
282             return SpecialMode::valUnsecure;
283         }
284 #endif
285         return SpecialMode::none;
286     }
287 
288     bool revertFanPWM = false;
289     bool revertLedCallback = false;
290     phosphor::Timer revertTimer;
291     int mtmTestBeepFd = -1;
292 };
293 
294 } // namespace ipmi
295