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 #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/Pwm_";
47 static constexpr const char* fanTachPathPrefix =
48     "/xyz/openbmc_project/sensors/fan_tach/Fan_";
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* busPropertyIntf =
55     "org.freedesktop.DBus.Properties";
56 static constexpr const char* ledStateStr =
57     "xyz.openbmc_project.Led.Physical.Action."; // Comes with postfix Off/On
58 
59 static constexpr const char* specialModeService =
60     "xyz.openbmc_project.SpecialMode";
61 static constexpr const char* specialModeObjPath =
62     "/xyz/openbmc_project/security/special_mode";
63 static constexpr const char* specialModeIntf =
64     "xyz.openbmc_project.Security.SpecialMode";
65 
66 /** @enum MtmLvl
67 .*
68  *  Manufacturing command access levels
69  */
70 enum class MtmLvl
71 {
72     mtmNotRunning = 0x00,
73     mtmExpired = 0x01,
74     mtmAvailable = 0x02,
75 };
76 
77 enum class SmActionGet : uint8_t
78 {
79     sample = 0,
80     ignore = 1,
81     revert = 2
82 };
83 
84 enum class SmActionSet : uint8_t
85 {
86     forceDeasserted = 0,
87     forceAsserted = 1,
88     revert = 2
89 };
90 
91 enum class SmSignalGet : uint8_t
92 {
93     smPowerButton = 0,
94     smResetButton = 1,
95     smSleepButton,
96     smNMIButton = 3,
97     smChassisIntrusion = 4,
98     smPowerGood,
99     smPowerRequestGet,
100     smSleepRequestGet,
101     smFrbTimerHaltGet,
102     smForceUpdate,
103     smRingIndication,
104     smCarrierDetect,
105     smIdentifyButton = 0xc,
106     smFanPwmGet = 0xd,
107     smSignalReserved,
108     smFanTachometerGet = 0xf,
109     smNcsiDiag = 0x10,
110     smGetSignalMax
111 };
112 
113 enum class SmSignalSet : uint8_t
114 {
115     smPowerLed = 0,
116     smPowerFaultLed,
117     smClusterLed,
118     smDiskFaultLed,
119     smCoolingFaultLed,
120     smFanPowerSpeed = 5,
121     smPowerRequestSet,
122     smSleepRequestSet,
123     smAcpiSci,
124     smSpeaker,
125     smFanPackFaultLed,
126     smCpuFailLed,
127     smDimmFailLed,
128     smIdentifyLed,
129     smHddLed,
130     smSystemReadyLed,
131     smLcdBacklight = 0x10,
132     smSetSignalMax
133 };
134 
135 struct SetSmSignalReq
136 {
137     SmSignalSet Signal;
138     uint8_t Instance;
139     SmActionSet Action;
140     uint8_t Value;
141 };
142 
143 class LedProperty
144 {
145     SmSignalSet signal;
146     std::string name;
147     std::string prevState;
148     std::string currentState;
149     bool isLocked;
150 
151   public:
152     LedProperty(SmSignalSet signal_, std::string name_) :
153         signal(signal_), name(name_), prevState(""), isLocked(false)
154     {
155     }
156 
157     LedProperty() = delete;
158 
159     SmSignalSet getSignal() const
160     {
161         return signal;
162     }
163 
164     void setLock(const bool& lock)
165     {
166         isLocked = lock;
167     }
168     void setPrevState(const std::string& state)
169     {
170         prevState = state;
171     }
172     void setCurrState(const std::string& state)
173     {
174         currentState = state;
175     }
176     std::string getCurrState() const
177     {
178         return currentState;
179     }
180     bool getLock() const
181     {
182         return isLocked;
183     }
184     std::string getPrevState() const
185     {
186         return prevState;
187     }
188     std::string getName() const
189     {
190         return name;
191     }
192 };
193 
194 /** @class Manufacturing
195  *
196  *  @brief Implemet commands to support Manufacturing Test Mode.
197  */
198 class Manufacturing
199 {
200     std::string path;
201     std::string gpioPaths[(uint8_t)SmSignalGet::smGetSignalMax];
202     std::vector<LedProperty> ledPropertyList;
203     void initData();
204 
205   public:
206     Manufacturing();
207 
208     ipmi_return_codes detectAccessLvl(ipmi_request_t request,
209                                       ipmi_data_len_t req_len);
210 
211     LedProperty* findLedProperty(const SmSignalSet& signal)
212     {
213         auto it = std::find_if(ledPropertyList.begin(), ledPropertyList.end(),
214                                [&signal](const LedProperty& led) {
215                                    return led.getSignal() == signal;
216                                });
217         if (it != ledPropertyList.end())
218         {
219             return &(*it);
220         }
221         return nullptr;
222     }
223 
224     std::string getLedPropertyName(const SmSignalSet signal)
225     {
226         LedProperty* led = findLedProperty(signal);
227         if (led != nullptr)
228         {
229             return led->getName();
230         }
231         else
232         {
233             return "";
234         }
235     }
236 
237     int8_t getProperty(const std::string& service, const std::string& path,
238                        const std::string& interface,
239                        const std::string& propertyName, ipmi::Value* value);
240     int8_t setProperty(const std::string& service, const std::string& path,
241                        const std::string& interface,
242                        const std::string& propertyName, ipmi::Value value);
243     int8_t disablePidControlService(const bool disable);
244 
245     void revertTimerHandler();
246 
247     MtmLvl getAccessLvl(void)
248     {
249         static MtmLvl mtmMode = MtmLvl::mtmNotRunning;
250         if (mtmMode != MtmLvl::mtmExpired)
251         {
252             ipmi::Value mode;
253             if (getProperty(specialModeService, specialModeObjPath,
254                             specialModeIntf, "SpecialMode", &mode) != 0)
255             {
256                 mtmMode = MtmLvl::mtmExpired;
257                 return mtmMode;
258             }
259             mtmMode = static_cast<MtmLvl>(std::get<std::uint8_t>(mode));
260         }
261         return mtmMode;
262     }
263 
264     bool revertFanPWM = false;
265     bool revertLedCallback = false;
266     phosphor::Timer revertTimer;
267 };
268 
269 } // namespace ipmi
270