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