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