blob: 255e2c554679edec7abdc7d58b1402b390e6d95e [file] [log] [blame]
/**
* Copyright © 2024 IBM 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 "pmbus.hpp"
#include "xyz/openbmc_project/Logging/Entry/server.hpp"
#include <phosphor-logging/lg2.hpp>
#include <sdbusplus/bus.hpp>
#include <sdbusplus/exception.hpp>
#include <cstdint>
#include <format>
#include <map>
#include <memory>
#include <string>
#include <vector>
namespace phosphor::power::sequencer
{
using namespace sdbusplus::xyz::openbmc_project::Logging::server;
using PMBusBase = phosphor::pmbus::PMBusBase;
using PMBus = phosphor::pmbus::PMBus;
/**
* @class Services
*
* Abstract base class that provides an interface to system services like error
* logging and the journal.
*/
class Services
{
public:
// Specify which compiler-generated methods we want
Services() = default;
Services(const Services&) = delete;
Services(Services&&) = delete;
Services& operator=(const Services&) = delete;
Services& operator=(Services&&) = delete;
virtual ~Services() = default;
/**
* Returns the D-Bus bus object.
*
* @return D-Bus bus
*/
virtual sdbusplus::bus_t& getBus() = 0;
/**
* Logs an error message in the system journal.
*
* @param message message to log
*/
virtual void logErrorMsg(const std::string& message) = 0;
/**
* Logs an informational message in the system journal.
*
* @param message message to log
*/
virtual void logInfoMsg(const std::string& message) = 0;
/**
* Logs an error.
*
* If logging fails, a message is written to the system journal but an
* exception is not thrown.
*
* @param message Message property of the error log entry
* @param severity Severity property of the error log entry
* @param additionalData AdditionalData property of the error log entry
*/
virtual void
logError(const std::string& message, Entry::Level severity,
std::map<std::string, std::string>& additionalData) = 0;
/**
* Returns whether the hardware with the specified inventory path is
* present.
*
* Throws an exception if an error occurs while obtaining the presence
* value.
*
* @param inventoryPath D-Bus inventory path of the hardware
* @return true if hardware is present, false otherwise
*/
virtual bool isPresent(const std::string& inventoryPath) = 0;
/**
* Reads all the GPIO values on the chip with the specified label.
*
* Throws an exception if an error occurs while obtaining the values.
*
* @param chipLabel label identifying the chip with the GPIOs
* @return GPIO values
*/
virtual std::vector<int> getGPIOValues(const std::string& chipLabel) = 0;
/**
* Creates object for communicating with a PMBus device by reading and
* writing sysfs files.
*
* Throws an exception if an error occurs.
*
* @param bus I2C bus
* @param address I2C address
* @param driverName Device driver name
* @param instance Chip instance number
* @return object for communicating with PMBus device
*/
virtual std::unique_ptr<PMBusBase>
createPMBus(uint8_t bus, uint16_t address,
const std::string& driverName = "",
size_t instance = 0) = 0;
/**
* Clear any cached data.
*
* Some data may be cached for performance reasons, such as hardware
* presence. Clearing the cache results in the latest data being obtained
* by a subsequent method calls.
*/
virtual void clearCache() = 0;
};
/**
* @class BMCServices
*
* Implementation of the Services interface using standard BMC system services.
*/
class BMCServices : public Services
{
public:
// Specify which compiler-generated methods we want
BMCServices() = delete;
BMCServices(const BMCServices&) = delete;
BMCServices(BMCServices&&) = delete;
BMCServices& operator=(const BMCServices&) = delete;
BMCServices& operator=(BMCServices&&) = delete;
virtual ~BMCServices() = default;
/**
* Constructor.
*
* @param bus D-Bus bus object
*/
explicit BMCServices(sdbusplus::bus_t& bus) : bus{bus} {}
/** @copydoc Services::getBus() */
virtual sdbusplus::bus_t& getBus() override
{
return bus;
}
/** @copydoc Services::logErrorMsg() */
virtual void logErrorMsg(const std::string& message) override
{
lg2::error(message.c_str());
}
/** @copydoc Services::logInfoMsg() */
virtual void logInfoMsg(const std::string& message) override
{
lg2::info(message.c_str());
}
/** @copydoc Services::logError() */
virtual void
logError(const std::string& message, Entry::Level severity,
std::map<std::string, std::string>& additionalData) override;
/** @copydoc Services::isPresent() */
virtual bool isPresent(const std::string& inventoryPath) override;
/** @copydoc Services::getGPIOValues() */
virtual std::vector<int>
getGPIOValues(const std::string& chipLabel) override;
/** @copydoc Services::createPMBus() */
virtual std::unique_ptr<PMBusBase>
createPMBus(uint8_t bus, uint16_t address,
const std::string& driverName = "",
size_t instance = 0) override
{
std::string path = std::format("/sys/bus/i2c/devices/{}-{:04x}", bus,
address);
return std::make_unique<PMBus>(path, driverName, instance);
}
/** @copydoc Services::clearCache() */
virtual void clearCache() override
{
presenceCache.clear();
}
private:
/**
* Returns whether the specified D-Bus exception is one of the expected
* types that can be thrown if hardware is not present.
*
* @return true if exception type is expected, false otherwise
*/
bool isExpectedException(const sdbusplus::exception_t& e);
/**
* D-Bus bus object.
*/
sdbusplus::bus_t& bus;
/**
* Cached presence data.
*
* Map from inventory paths to presence values.
*/
std::map<std::string, bool> presenceCache{};
};
} // namespace phosphor::power::sequencer