Initial commit
This commit is contained in:
+41
@@ -0,0 +1,41 @@
|
||||
FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"
|
||||
LICENSE = "CLOSED"
|
||||
SUMMARY = "FRU Write IPMI Command"
|
||||
|
||||
TARGET_CC_ARCH += "${LDFLAGS}"
|
||||
|
||||
SRC_URI += " \
|
||||
file://ipmi-fru.cpp \
|
||||
file://Makefile \
|
||||
"
|
||||
SRCREV = "${AUTOREV}"
|
||||
|
||||
PR = "r1"
|
||||
SO_VERSION = "1"
|
||||
S = "${WORKDIR}"
|
||||
|
||||
DEPENDS = " \
|
||||
boost \
|
||||
sdbusplus \
|
||||
phosphor-ipmi-host \
|
||||
phosphor-logging \
|
||||
"
|
||||
|
||||
inherit pkgconfig
|
||||
inherit obmc-phosphor-ipmiprovider-symlink
|
||||
|
||||
do_compile () {
|
||||
oe_runmake
|
||||
}
|
||||
|
||||
do_install() {
|
||||
install -d ${D}${libdir}/ipmid-providers
|
||||
install -m 0755 ${S}/libipmi-fru.so.${SO_VERSION} ${D}/${libdir}/ipmid-providers/
|
||||
}
|
||||
|
||||
|
||||
HOSTIPMI_PROVIDER_LIBRARY += "libipmi-fru.so"
|
||||
FILES:${PN}:append = " ${libdir}/ipmid-providers/lib*${SOLIBS}"
|
||||
FILES:${PN}:append = " ${libdir}/host-ipmid/lib*${SOLIBS}"
|
||||
|
||||
RDEPENDS_${PN} += " phosphor-ipmi-host"
|
||||
@@ -0,0 +1,21 @@
|
||||
SRC = ipmi-fru.cpp
|
||||
SO_VERSION = 1
|
||||
OUTPUT = libipmi-fru.so.$(SO_VERSION)
|
||||
CFLAGS += -O3 -Wno-unused-result -std=c++20
|
||||
|
||||
BUILD_LIB = -shared -fPIC
|
||||
|
||||
BOOST_CXX_FLAG += -DBOOST_ERROR_CODE_HEADER_ONLY
|
||||
BOOST_CXX_FLAG += -DBOOST_SYSTEM_NO_DEPRECATED
|
||||
BOOST_CXX_FLAG += -DBOOST_ALL_NO_LIB
|
||||
BOOST_CXX_FLAG += -DBOOST_NO_RTTI
|
||||
BOOST_CXX_FLAG += -DBOOST_NO_TYPEID
|
||||
BOOST_CXX_FLAG += -DBOOST_ASIO_DISABLE_THREADS
|
||||
BOOST_CXX_FLAG += -DBOOST_COROUTINES_NO_DEPRECATION_WARNING
|
||||
|
||||
LIBS += -lsdbusplus -lsystemd -lipmid
|
||||
|
||||
all: $(SRC)
|
||||
$(CXX) $(BUILD_LIB) $(SRC) -o $(OUTPUT) $(CFLAGS) $(LIBS) $(BOOST_CXX_FLAG)
|
||||
clean:
|
||||
-rm -rf $(OUTPUT)
|
||||
@@ -0,0 +1,180 @@
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/container/flat_map.hpp>
|
||||
#include <boost/process.hpp>
|
||||
#include <filesystem>
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <ipmid/api.hpp>
|
||||
#include <ipmid/message.hpp>
|
||||
#include <ipmid/types.hpp>
|
||||
#include <phosphor-logging/log.hpp>
|
||||
#include <sdbusplus/message/types.hpp>
|
||||
#include <sdbusplus/timer.hpp>
|
||||
#include <stdexcept>
|
||||
#include <string_view>
|
||||
|
||||
namespace ipmi {
|
||||
|
||||
namespace storage {
|
||||
std::map<uint8_t, std::string> __attribute__((init_priority(101)))
|
||||
fruIDMap = {{0, "/sys/bus/i2c/devices/i2c-14/14-0053/eeprom"}};
|
||||
|
||||
std::map<uint8_t, std::vector<uint8_t>> fruCache
|
||||
__attribute__((init_priority(101)));
|
||||
|
||||
constexpr uint16_t FRUMAXSIZE = 0x8000;
|
||||
|
||||
void register_netfn_storage_functions() __attribute__((constructor));
|
||||
|
||||
void cacheFruData() {
|
||||
for (auto fruInfo : fruIDMap) {
|
||||
std::ifstream fruFile(fruInfo.second, std::ios::binary);
|
||||
if (!fruFile) {
|
||||
continue;
|
||||
}
|
||||
fruFile.seekg(0, std::ios::end);
|
||||
std::streampos fileSize = fruFile.tellg();
|
||||
fruFile.seekg(0, std::ios::beg);
|
||||
|
||||
fruCache[fruInfo.first].resize(fileSize);
|
||||
fruFile.read(reinterpret_cast<char *>(fruCache[fruInfo.first].data()),
|
||||
fileSize);
|
||||
fruCache[fruInfo.first].resize(FRUMAXSIZE);
|
||||
}
|
||||
}
|
||||
|
||||
/** @brief implements the write FRU data command
|
||||
* @param fruDeviceId - FRU Device ID
|
||||
* @param fruInventoryOffset - FRU Inventory Offset to write
|
||||
* @param dataToWrite - Data to write
|
||||
*
|
||||
* @returns ipmi completion code plus response data
|
||||
* - countWritten - Count written
|
||||
*/
|
||||
ipmi::RspType<uint8_t>
|
||||
ipmiStorageWriteFruData(ipmi::Context::ptr ctx, uint8_t fruDeviceId,
|
||||
uint16_t fruInventoryOffset,
|
||||
std::vector<uint8_t> &dataToWrite) {
|
||||
constexpr uint8_t fruHeaderMutiRecOffset = 5;
|
||||
constexpr uint8_t fruHeaderCheckSumOffset = 7;
|
||||
uint8_t countWritten = 0;
|
||||
|
||||
if (fruIDMap.find(fruDeviceId) == fruIDMap.end() || fruDeviceId == 0xFF ||
|
||||
fruCache.find(fruDeviceId) == fruCache.end()) {
|
||||
return ipmi::responseInvalidFieldRequest();
|
||||
}
|
||||
|
||||
// Not Support MutiRecord, set to disabled
|
||||
if (fruInventoryOffset == 0) {
|
||||
|
||||
dataToWrite[fruHeaderMutiRecOffset] = 0;
|
||||
int zsum = 0;
|
||||
for (uint8_t index = 0; index < 5; index++)
|
||||
zsum += dataToWrite[index];
|
||||
dataToWrite[fruHeaderCheckSumOffset] = -(zsum % 256);
|
||||
}
|
||||
|
||||
if ((fruInventoryOffset + dataToWrite.size()) > FRUMAXSIZE) {
|
||||
return ipmi::responseParmOutOfRange();
|
||||
}
|
||||
|
||||
std::copy(dataToWrite.begin(), dataToWrite.end(),
|
||||
fruCache[fruDeviceId].begin() + fruInventoryOffset);
|
||||
|
||||
std::ofstream fruFile(fruIDMap[fruDeviceId],
|
||||
std::ios::binary | std::ios::out);
|
||||
if (!fruFile) {
|
||||
return ipmi::responseUnspecifiedError();
|
||||
}
|
||||
|
||||
fruFile.seekp(fruInventoryOffset);
|
||||
|
||||
std::copy(dataToWrite.begin(), dataToWrite.end(),
|
||||
std::ostreambuf_iterator<char>(fruFile));
|
||||
|
||||
countWritten = std::min(dataToWrite.size(), static_cast<size_t>(0xFF));
|
||||
|
||||
return ipmi::responseSuccess(countWritten);
|
||||
}
|
||||
|
||||
/**@brief implements the Read FRU Data command
|
||||
* @param fruDeviceId - FRU device ID. FFh = reserved
|
||||
* @param offset - FRU inventory offset to read
|
||||
* @param readCount - count to read
|
||||
*
|
||||
* @return IPMI completion code plus response data
|
||||
* - returnCount - response data count.
|
||||
* - data - response data
|
||||
*/
|
||||
ipmi::RspType<uint8_t, // count returned
|
||||
std::vector<uint8_t>> // FRU data
|
||||
ipmiStorageReadFruData(uint8_t fruDeviceId, uint16_t offset,
|
||||
uint8_t readCount) {
|
||||
if (fruDeviceId == 0xFF) {
|
||||
return ipmi::responseInvalidFieldRequest();
|
||||
}
|
||||
|
||||
auto iter = fruIDMap.find(fruDeviceId);
|
||||
if (iter == fruIDMap.end()) {
|
||||
return ipmi::responseSensorInvalid();
|
||||
}
|
||||
|
||||
if (fruCache.find(fruDeviceId) == fruCache.end()) {
|
||||
return ipmi::responseSensorInvalid();
|
||||
}
|
||||
|
||||
uint8_t returnCount;
|
||||
if ((offset + readCount) <= FRUMAXSIZE) {
|
||||
returnCount = readCount;
|
||||
} else {
|
||||
returnCount = FRUMAXSIZE - offset;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> fruData(
|
||||
(fruCache[fruDeviceId].begin() + offset),
|
||||
(fruCache[fruDeviceId].begin() + offset + returnCount));
|
||||
return ipmi::responseSuccess(returnCount, fruData);
|
||||
}
|
||||
|
||||
/** @brief implements the get FRU Inventory Area Info command
|
||||
*
|
||||
* @returns IPMI completion code plus response data
|
||||
* - FRU Inventory area size in bytes,
|
||||
* - access bit
|
||||
**/
|
||||
ipmi::RspType<uint16_t, // FRU Inventory area size in bytes,
|
||||
uint8_t // access size (bytes / words)
|
||||
>
|
||||
ipmiStorageGetFruInvAreaInfo(uint8_t fruID) {
|
||||
|
||||
auto iter = fruIDMap.find(fruID);
|
||||
if (iter == fruIDMap.end()) {
|
||||
return ipmi::responseSensorInvalid();
|
||||
}
|
||||
|
||||
if (!std::filesystem::exists(iter->second)) {
|
||||
return ipmi::responseSensorInvalid();
|
||||
}
|
||||
|
||||
return ipmi::responseSuccess(static_cast<uint16_t>(FRUMAXSIZE),
|
||||
static_cast<uint8_t>(0));
|
||||
}
|
||||
|
||||
void register_netfn_storage_functions() {
|
||||
cacheFruData();
|
||||
// <WRITE FRU Data>
|
||||
ipmi::registerHandler(ipmi::prioMax, ipmi::netFnStorage,
|
||||
ipmi::storage::cmdWriteFruData,
|
||||
ipmi::Privilege::Operator, ipmiStorageWriteFruData);
|
||||
// <READ FRU Data>
|
||||
ipmi::registerHandler(ipmi::prioMax, ipmi::netFnStorage,
|
||||
ipmi::storage::cmdReadFruData,
|
||||
ipmi::Privilege::Operator, ipmiStorageReadFruData);
|
||||
// <Get FRU Inventory Area Info>
|
||||
ipmi::registerHandler(ipmi::prioMax, ipmi::netFnStorage,
|
||||
ipmi::storage::cmdGetFruInventoryAreaInfo,
|
||||
ipmi::Privilege::User, ipmiStorageGetFruInvAreaInfo);
|
||||
}
|
||||
} // namespace storage
|
||||
} // namespace ipmi
|
||||
Reference in New Issue
Block a user