blob: a6ac45f9b854abab18ce37d923e6b1266d405e7f [file] [log] [blame]
/*
// Copyright (c) 2018 Intel Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
*/
#pragma once
#include <ipmid/api-types.hpp>
#include <ipmid/utils.hpp>
#include <phosphor-logging/log.hpp>
#include <sdbusplus/bus.hpp>
#include <sdbusplus/message.hpp>
#include <sdbusplus/timer.hpp>
#include <variantvisitors.hpp>
#include <vector>
#define FAN_SENSOR_NOT_PRESENT (0 << 0)
#define FAN_SENSOR_PRESENT (1 << 0)
#define FAN_NOT_PRESENT (0 << 1)
#define FAN_PRESENT (1 << 1)
namespace ipmi
{
// TODO: Service names may change. Worth to consider dynamic detection.
static constexpr const char* fanService = "xyz.openbmc_project.FanSensor";
static constexpr const char* buttonService =
"xyz.openbmc_project.Chassis.Buttons";
static constexpr const char* ledServicePrefix =
"xyz.openbmc_project.LED.Controller.";
static constexpr const char* ledPathPrefix =
"/xyz/openbmc_project/led/physical/";
static constexpr const char* fanPwmPath =
"/xyz/openbmc_project/sensors/fan_pwm/Pwm_";
static constexpr const char* fanTachPathPrefix =
"/xyz/openbmc_project/sensors/fan_tach/Fan_";
static constexpr const char* fanIntf = "xyz.openbmc_project.Sensor.Value";
static constexpr const char* buttonIntf = "xyz.openbmc_project.Chassis.Buttons";
static constexpr const char* ledIntf = "xyz.openbmc_project.Led.Physical";
static constexpr const char* busPropertyIntf =
"org.freedesktop.DBus.Properties";
static constexpr const char* ledStateStr =
"xyz.openbmc_project.Led.Physical.Action."; // Comes with postfix Off/On
/** @enum MtmLvl
.*
* Manufacturing command access levels
*/
enum class MtmLvl
{
mtmNotRunning = 0x00,
mtmExpired = 0x01,
mtmAvailable = 0x02,
};
enum class SmActionGet : uint8_t
{
sample = 0,
ignore = 1,
revert = 2
};
enum class SmActionSet : uint8_t
{
forceDeasserted = 0,
forceAsserted = 1,
revert = 2
};
enum class SmSignalGet : uint8_t
{
smPowerButton = 0,
smResetButton = 1,
smSleepButton,
smNMIButton = 3,
smChassisIntrusion = 4,
smPowerGood,
smPowerRequestGet,
smSleepRequestGet,
smFrbTimerHaltGet,
smForceUpdate,
smRingIndication,
smCarrierDetect,
smIdentifyButton = 0xc,
smFanPwmGet = 0xd,
smSignalReserved,
smFanTachometerGet = 0xf,
smNcsiDiag = 0x10,
smGetSignalMax
};
enum class SmSignalSet : uint8_t
{
smPowerLed = 0,
smPowerFaultLed,
smClusterLed,
smDiskFaultLed,
smCoolingFaultLed,
smFanPowerSpeed = 5,
smPowerRequestSet,
smSleepRequestSet,
smAcpiSci,
smSpeaker,
smFanPackFaultLed,
smCpuFailLed,
smDimmFailLed,
smIdentifyLed,
smHddLed,
smSystemReadyLed,
smLcdBacklight = 0x10,
smSetSignalMax
};
struct SetSmSignalReq
{
SmSignalSet Signal;
uint8_t Instance;
SmActionSet Action;
uint8_t Value;
};
class LedProperty
{
SmSignalSet signal;
std::string name;
std::string prevState;
std::string currentState;
bool isLocked;
public:
LedProperty(SmSignalSet signal_, std::string name_) :
signal(signal_), name(name_), prevState(""), isLocked(false)
{
}
LedProperty() = delete;
SmSignalSet getSignal() const
{
return signal;
}
void setLock(const bool& lock)
{
isLocked = lock;
}
void setPrevState(const std::string& state)
{
prevState = state;
}
void setCurrState(const std::string& state)
{
currentState = state;
}
std::string getCurrState() const
{
return currentState;
}
bool getLock() const
{
return isLocked;
}
std::string getPrevState() const
{
return prevState;
}
std::string getName() const
{
return name;
}
};
/** @class Manufacturing
*
* @brief Implemet commands to support Manufacturing Test Mode.
*/
class Manufacturing
{
std::string path;
std::string gpioPaths[(uint8_t)SmSignalGet::smGetSignalMax];
std::vector<LedProperty> ledPropertyList;
void initData();
public:
Manufacturing();
ipmi_return_codes detectAccessLvl(ipmi_request_t request,
ipmi_data_len_t req_len);
LedProperty* findLedProperty(const SmSignalSet& signal)
{
auto it = std::find_if(ledPropertyList.begin(), ledPropertyList.end(),
[&signal](const LedProperty& led) {
return led.getSignal() == signal;
});
if (it != ledPropertyList.end())
{
return &(*it);
}
return nullptr;
}
std::string getLedPropertyName(const SmSignalSet signal)
{
LedProperty* led = findLedProperty(signal);
if (led != nullptr)
{
return led->getName();
}
else
{
return "";
}
}
int8_t getProperty(const std::string& service, const std::string& path,
const std::string& interface,
const std::string& propertyName, ipmi::Value* value);
int8_t setProperty(const std::string& service, const std::string& path,
const std::string& interface,
const std::string& propertyName, ipmi::Value value);
int8_t disablePidControlService(const bool disable);
void revertTimerHandler();
MtmLvl getAccessLvl(void)
{
static MtmLvl mtmMode = MtmLvl::mtmNotRunning;
if (mtmMode != MtmLvl::mtmExpired)
{
ipmi::Value mode;
if (getProperty("xyz.openbmc_project.SpecialMode",
"/xyz/openbmc_project/security/specialMode",
"xyz.openbmc_project.Security.SpecialMode",
"SpecialMode", &mode) != 0)
{
mtmMode = MtmLvl::mtmExpired;
return mtmMode;
}
mtmMode = static_cast<MtmLvl>(std::get<std::uint8_t>(mode));
}
return mtmMode;
}
bool revertFanPWM = false;
bool revertLedCallback = false;
phosphor::Timer revertTimer;
};
} // namespace ipmi