Initial commit

This commit is contained in:
Your Name
2026-04-23 17:07:55 +08:00
commit b7e39e063b
16725 changed files with 1625565 additions and 0 deletions
+41
View File
@@ -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"
+21
View File
@@ -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